• Aucun résultat trouvé

Alignment-Extension

Dans le document Domain Pascal Language Reference (Page 117-131)

QUAD WORD ALIGNMENT

3.15 Attributes for Variables and Types-Extension

3.15.6 Alignment-Extension

Domain Pascal supports two alignment attributes: aligned and natural. In the following sections we tell you:

• The format for the aligned and natural attributes.

• How to use natural and aligned to align objects on natural boundaries.

• How to use aligned to prevent padding by default.

3-62 Data Types

• How to use aligned to ensure the same record layout in all alignment environ-ments.

• How to suppress informational messages about alignment by using the alignment attributes.

• How and why to use alignment attributes to inform the compiler that an object is not naturally aligned. This is especially important in connection with dereferenc-ing pointers and passdereferenc-ing arguments by reference.

3.15.6.1 Format for the aligned and natural Attributes The format for the aligned attribute is:

[aligned [ (n) ]] typename;

where n is the number of low order zeros in the address (in binary representation). If you omit a value for n, then the compiler will default to a value of 0 (byte aligned). Note that:

aligned specifies byte alignment aligned (I) specifies word alignment aligned (2) specifies longword alignment aligned (3) specifies quadword alignment aligned (4) specifies octaword alignment

Thus, aligned(n) implies 2**n-byte alignment. For example, the declaration

TYPE

word_aligned_integer32

=

[ALIGNED(l)] integer32;

tells the compiler that all objects of type word_aligned_integer32 are at least word aligned.

The format for the natural attribute is as follows:

[natural] typename;

For example, the declaration

TYPE

natural_integer32 = [NATURAL] integer32;

tells the compiler that all objects of type natural_integer32 are at least longword aligned.

Data Types 3-63

The natural attribute has one main use;

• Overriding the· default alignment rules to ensure that objects are stored on natural boundaries.

Similarly, you can use the aligned attribute to ensure natural alignment by specifying the correct value for n. In addition, the aligned attribute has these uses:

• Preventing the compiler from inserting padding in records.

• Ensuring the same layout in all alignment environments.

• Suppressing informational messages.

• Dereferencing pointers to unaligned objects.

• Passing arguments by reference.

Each of these uses is described in the following sections.

3.1S. 6. 2 Aligning Objects on Natural Boundaries

In general, natural alignment produces faster executable code, although the efficiency sav-ings vary a great deal from one processor to another. (See Section 3.10.5 for a descrip-tion of natural alignment.) Code for the 68000 family of processors runs slightly faster if objects are naturally aligned. Code for the Series 10000 workstations runs significantly faster if objects are naturally aligned. Moreover, on the Series 10000, if the compiler as-sumes that an object is naturally aligned when it is not, then the loss of efficiency is se-vere.

Although natural alignment often results in faster code, it can also produce holes in struc-tures such as arrays and records, which can have an impact on memory efficiency. Before naturally aligning record fields, you need to weigh these two efficiency concerns.

The aligned and natural attributes override the default alignment rules (described in the

"Internal Representation of Unpacked Records" section of this chapter) as well as the alignment rules specified by any compiler alignment directive that is currently in effect.

(See Chapter 4 for more information about specifying alignment rules with compiler direc-tives.)

Note that if all of the record fields are scalar, it is always possible to guarantee natural alignment of the entire record by arranging the fields in decreasing order of size. This method is preferable to using the aligned and natural attributes because it is portable.

(See the "Internal Representation of Unpacked Records" section of this chapter for an example of using this rule.)

3-64 Data Types

Although it is usually possible to align record fields naturally by arranging them in descend-ing order of size, the arrangement of fields does not guarantee that a record will remain aligned if it is used within another aggregate (that is, in an array or record). Consider the following example:

TYPE

S record

end;

a: integer32;

b: integer16

The layout is shown in Figure 3-19. Note that both a and b are naturally aligned, and that the entire record is aligned on a longword boundary .

...

1 word

0 - - - -...

2 a

4

Figure 3-19. Naturally Aligned Record S

Note what happens, however, if we declare an array of three S records:

VAR

bunch_of_records: ARRAY [1 .. 3] OF S;

The memory layout for this array is shown in Figure 3-20.

Data Types 3-65

4 1 word

..

0

2 a

4 6

8 a

10 12

14 a

16

Figure 3-20. Array of S Records

Note that the second element of the array, which starts at address 6, is not naturally aligned. This alignment results from the fact that each element is six bytes long and array elements must be laid out contiguously in memory. There are several solutions to this problem. They are as follows:

• Explicitly enter a word of padding in the record so that the total size of the re-cord is divisible by four. Specifically, change the declaration of S-type rere-cords to:

TYPE

S record

end;

a: integer32;

b: integer16;

padding: integer16

• Use the natural attribute for the record. Specifically, change the declaration to:

TYPE

3-66 Data Types

S [NATURAL] record a: integer32;

b: integer16 end;

• Use the aligned attribute for the record. Specifically, change the declaration to:

TYPE

S [ALIGNED(2)] record a: integer32;

b: integer16 end;

• Use the natural attribute for field a. This works because a record inherits the largest alignment specification of its fields. Since a is declared to be aligned on a longword boundary, the entire record will be also be longword aligned. Specifi-cally, change the declaration to:

TYPE

S record

end;

a: [NATURAL] integer32;

b: integer16

• Use the aligned attribute for field a. This method also works because of the rule that a record inherits the largest alignment specification of its fields. Specifically, change the declaration to:

TYPE

S record

end;

a: [ALIGNED(2)] integer32;

b: integer16

Figure 3-21 shows the memory allocation for S records resulting from all of the above methods of declaring S.

1 word _ _ _ - - I . . . .

o~---2 a

4~---~

b 6

Figure 3-21. Naturally Aligned Record S

The principal difference between declaring a padding field and using an alignment attribute is that the padding word is accessible if you explicitly declare it. It is inaccessible if the compiler includes it to satisfy an alignment attribute. Furthermore, if you use padding in-stead of the attribute, your record declaration is portable.

Data Types 3-67

NOTE: Assigning attribute specifications to a record or field can have unexpected repercussions. Consider the following declarations:

3-68 Data Types

TYPE

S record

a: [NATURAL] integer32;

b: integer16 end;

Sl record

x: integer16;

y: S;

z: integer16 end;

The layout for record S is shown in Figure 3-21 and the layout for SI is shown in Figure 3-22. Note that record S inherits the alignment of field a (longword alignment) and that this alignment requirement causes an additional word of padding to be inserted between x and y. In addition, record S 1 inherits longword align-ment from record S, causing a word of padding to be added at the end of S1.

...

word ~

0

x 2

4

6 S.a

8

S.b 10

12 14 16

Figure 3-22. Naturally Aligned Record Sl

3.1S.6.3 Using the aligned Attribute to Prevent Padding

In the previous example, we used the aligned attribute to insert padding in a record so that the size of the record would be evenly divisible by the size of its largest field (four bytes). You can also use the aligned attribute to prevent the compiler from inserting pad-ding. This is particularly useful. if you need to declare a record that maps onto an existing layout (for example, a shared memory area).

Suppose, for example, that you want to declare a record that consists of a char followed by two integers:

TYPE

52 record

a: char;

b, c: integer16 end;

By default, the compiler produces the layout shown in Figure 3-23.

...

1 word---I~~

Figure 3-23. Default Layout for Sl

The compiler inserts a byte of padding after a to ensure that b starts on a word boundary.

If you want to create a record without padding at this position, you need to use the aligned specifier as shown in the following declaration:

TYPE

82 record

a: char;

b, c: [ALIGNED(O)] integer16 end;

The aligned(O) attribute tells the compiler that these fields may be aligned on byte boundaries. This declaration results in the layout shown in Figure 3-24.

Data Types 3-69

1 word

...

0---2 4

6

Figure 3-24. Layout for Sl with Byte Alignment Specified

Note that the compiler still inserts a byte of padding so that the size of the record is evenly divisible by two. There is no way to suppress this trailing byte. Records created by Do-main Pascal are always 2-byte multiples.

Suppressing padding sometimes becomes more important if a "natural_alignment directive is in effect. The "natural_alignment directive tells the compiler to use natural alignment for any data that does not have an alignment attribute in its declaration. (See the "Com-piler Directives" section of Chapter 4 for more details about the "natural_alignment directive). Consider the following declaration:

81

=

record

end;

a: char;

b: integer32;

c: char

The "natural_alignment directive applies not only to each field, but also to the entire record. A record is considered to be naturally aligned if it starts on a boundary that en-sures natural alignment for its largest field (and every other field). The layout for SI is shown in Figure 3-25.

3-70 Data Types

..

1 word ~

0 2 4 6 8 10

Figure 3-25. Layout for Sl with Natural Alignment Specified

By specifying word alignment for the record, we can remove the final word of padding, as shown in Figure 3-26.

TYPE

51 = [ALIGNED(1)] record a: chari endi

b: integer32i c: char

1 word ----.~.

Figure 3-26. Layout for Sl with Word Alignment Specified

Data Types 3-71

To remove at least some of the padding between a and b, we need to specify word align-ment for b. Figure 3-27 shows the layout if we specify word alignment for b as well as for the whole record.

TYPE

81

=

[ALIGNED(1)] record a: char;

end;

b: [ALIGNED(1)] integer32;

c: char

...

1 word,..---I~~

o---~--~----~--~

a

4

c

Figure 3-27. Layout for Sl with Word Alignment for B Specified Note that specifying byte alignment for b produces the same layout as specifying word alignment for b-namely, the layout in Figure 3-27. The results are the same because of the rule that a byte aligned object may not cross two word boundaries. (See the "Internal Representation of Unpacked Records" section of this chapter for more details about the rules for record layout.)

3.15.6.4 Ensuring the Same Layout in All Alignment Environments

Alignment attributes can be particularly useful for ensuring that a record receives the same layout regardless of what alignment environment is in effect due to a compiler directive or a compiler option.

Suppose, for example, that you want to declare a record that consists of an integer16 fol-lowed by an integer32, and you want to guarantee that there is no padding in the structure regardless of the alignment environment. Consider the following declaration:

82

=

record end;

3-72 Data Types

a: integer16;

b: integer32

If the alignment environment is natural alignment, then the layout of 82 type records will be the layout shown in Figure 3-28. If the alignment environment is word alignment, then the layout will be that shown in Figure 3-29.

o

1 word'---~·

2 a

4

6 b

Figure 3-28. Naturally Aligned Structure S2

word ---....

o

a 2

4 b

Figure 3-29. Word Aligned Structure S2

You can use the aligned attribute to ensure that 82 never receives padding between a and b:

82

=

record

a: integer16;

b: [ALIGNED(l)] integer32 end;

NOTE: You can also use the aligned record data type or the unaligned record data type to ensure that your records have the same layout in all alignment environments.

Data Types 3-73

3.1S.6.S Suppressing Informational Messages about Alignment

In general, the compiler assumes that all objects are naturally aligned. If the compiler en-counters an object that it knows is not naturally aligned, it issues an informational message.

This happens, for example, when the compiler is forced to use word alignment rules for a record field that is larger than a word, or when a record cannot be aligned because it is embedded in another aggregate object. The following declarations, for example, will pro-duce two informational messages:

TYPE

53 record

end;

a: integer16;

b: integer32;

c: double

The messages inform you that band c are not naturally aligned. If you attempt to declare an array of S3 records, you will receive another informational message telling you that the array elements are not naturally aligned.

The best way to suppress these messages is to rearrange the record so all the fields are naturally aligned. If rearrangement is impossible, however, you can suppress these mes-sages by specifying the alignment and telling the compiler that the objects are not naturally aligned:

TYPE

53 record

end;

a: integer16;

b: [ALIGNED(l)] integer32;

c: [ALIGNED(l)] double

Note that these alignment specifications do not affect the record's layout-they merely reaf-firm that the compiler should use word alignment rules rather than natural alignment rules.

NOTE: If you compile with -info 4, you will receive informational mes-sages even if you specify alignment. See Chapter 6 for more in-formation about the -info option.

3.1S.6.6 Informing the Compiler that an Object Is Not Naturally Aligned (Series 10000 Only)

In many instances, the compiler can determine whether an object is naturally aligned.

When the compiler knows that an object is not naturally aligned, it produces code that ac-cesses the object as if it consisted of separate parts, where each part is naturally aligned.

For example, suppose a program accesses a 4-byte integer that starts on a 2-byte bound-ary. Because the computer can't access the entire integer at once, the compiler treats the 4-byte integer as if it ~ere composed of two contiguous 2-byte integers, each of which is

3-74 Data Types

naturally aligned. The compiler produces code that accesses each half of the 4-byte object and then recombines the two halves to obtain the 4-byte integer value.

Obviously, this decomposition and recomposition of objects is less efficient than accessing the object in a single instruction. Still, it is considerably better than taking a hardware function). This causes the compiler to use the decomposition/recomposition technique instead of suffering a hardware fault at run time.

NOTE: If you run your Domain Pascal program on a Series 10000 work-station, you should make sure that the compiler is informed about any objects that are not naturally aligned. If the compiler as-sumes that an object is naturally aligned when, in fact, the object is not naturally aligned, your program will suffer a severe loss of efficiency when you run it on Series 10000 workstations.

3.1S.6.7 Dereferencing Pointers

When you declare a pointer to an object, the compiler assumes that the object pointed to is naturally aligned unless you tell it otherwise. Consider the following declarations:

TYPE

You can correct this problem by declaring iptr as pointing to a word aligned integer32 type variable, as follows:

VAR

word_int32 : [ALIGNED (1)] integer32;

iptr : Aword int32

- {iptr is a longword aligned pointer; it points to a word aligned 4-byte integer}

Note that the above declaration tells the compiler that iptr points to a word aligned integer32-type variable. It is different from the following declaration, which tells the com-piler that iptr is a word aligned pointer variable and also that what it points to is a word aligned integer32-type variable:

VAR

word_int32 : [ALIGNED (1)] integer32;

int_ptr: Aword_int32;

iptr : [ALIGNED(l)] int_ptr;

{iptr is a word aligned pointer variable;

it points to a word aligned 4-byte integer}

3.1S.6.8 Passing Arguments by Reference

The compiler is unable to, determine the alignment of objects passed by reference as argu-ments to routines. By default, the compiler assumes that such objects are naturally aligned. Therefore, if you know that an argument passed by reference is not naturally aligned, you should specify its alignment.

Dans le document Domain Pascal Language Reference (Page 117-131)