.ALIGN

Align the data location counter to a boundary

WTSupported in traditional Synergy on Windows
WNSupported in Synergy .NET on Windows
USupported on UNIX
VSupported on OpenVMS
.ALIGN[  boundary]

Arguments

boundary

(optional) One of the following keywords or an expression that specifies the alignment boundary (traditional Synergy only):

BYTE = 1 byte

WORD = 2 bytes

LONG = 4 bytes

QUAD = 8 bytes

PAGE = 512 bytes on Windows and UNIX, 4096 bytes on OpenVMS I64, or 8192 bytes on OpenVMS Alpha

expression = An expression in the range 0 through 9 (n)

Discussion

In Synergy .NET, data is automatically aligned on a native boundary for .NET Framework CLR requirements, which causes an automatic align warning to notify of the implicit alignment of objects. The .ALIGN directive suppresses this warning.

In traditional Synergy, the .ALIGN compiler directive aligns the data location counter to a specified boundary for the next data element to be processed. It can help increase an application’s speed by properly aligning integer variables. You can specify .ALIGN before a record or single variable.

Tip

We recommend compiling with the -qalign option in traditional Synergy, so you don’t have to use .ALIGN before records. (The -qalign option is always on in Synergy .NET.)

.ALIGN looks at the address of the next memory location and adds as many filler bytes as necessary to cause the next memory location to fall on the desired boundary. If you specify the BYTE, WORD, LONG, QUAD, or PAGE keyword, the data location counter is aligned to an address that is the next multiple of the number of bytes for that keyword. For example, if the next memory location is 21 and longword alignment is desired, three bytes are added to update the next memory location to 24 (the next higher number that is evenly divisible by 4), thus placing the next variable on a longword-aligned memory boundary.

The default is to align to the natural “int” size on your machine. This is usually longword alignment (4-byte boundaries), except on 64-bit machines, where it is quadword alignment (8-byte boundaries).

If you specify expression, the data location counter is aligned to an address that is the value of 2 raised to the power of expression.

Note

If .ALIGN boundary is used on any system, the alignment is only guaranteed up to the natural register size of that machine. If boundary is larger and memory alignment cannot be guaranteed, a warning (NOTALIGNED) is issued.

General rules of thumb are as follows:

If you specify .ALIGN before a declaration that doesn’t define data (such as an overlaid data declaration statement, an EXTERNAL COMMON statement, an EXTERNAL LITERAL statement, or any field in an EXTERNAL COMMON declaration), the compiler generates an “Alignment not performed” warning (NOALIGN).

Important

The .ALIGN directive can cause empty bytes to be allocated between successive data fields. Be careful when redefining the record that contains the .ALIGN directive or when subscripting across an .ALIGN directive, because the empty bytes can be accessed!

Examples

In the following example, data2 is longword-aligned.

record
    data1               ,d3
.align LONG
    data2               ,d8

In the next example, data5 is aligned to a page boundary and data6 through data8 are aligned at the 128-byte boundary with room for future growth.

.align PAGE
record
    data5               ,a90
.align 7
    data6               ,a90
.align 7
    data7               ,a90
.align 7
    data8               ,a90

It’s important to understand the difference between the placement of the .ALIGN statement in these two examples:

record alpha                     record alpha
    fld1        ,a1                    fld1        ,a1
record beta                      .align long
.align long                      record beta   
    fld2        ,i4                   fld2        ,i4
record gamma, X                  record gamma, X
    fld3        ,i4                   fld3        ,i4

The example on the left causes fld2 to be aligned on a longword boundary and allows fld2 to be accessed as efficiently as possible. The problem with this approach is not always apparent. The .ALIGN LONG has increased the size of record beta, and fld3 no longer overlays fld2 properly. You would see this easily if ^SIZE(beta) were displayed. In this case, the size of record beta is 7, and only the fourth byte of fld3 coincides with fld2, which is not the desired effect.

When the .ALIGN LONG is moved before the record, as in the example on the right, the size of record beta is 4 as desired. But what about the size of record alpha? In the left example, the size of record alpha is quite obviously 1. If we displayed ^SIZE(alpha) in this example, we’d see it’s still 1. So now we wonder, is fld2 really aligned as desired, and where are the 3 bytes needed for alignment? The answer is that fld2 is aligned, and the extra 3 bytes have been added to the data division between the two records and not as part of either record. ^SIZE(alpha) is 1, ^SIZE(beta) is 4, ^SIZE(gamma) is 4, and fld3 and fld2 coincide as desired.