Chapter 3. Storage Mapping

Storage mapping of Pascal arrays, records, and variant records is described in the first part of this chapter. Ranges are discussed in the second part. Alignment, size and value ranges for the various data types are described in the third part. The last section discusses rules for set sizing.

Arrays, Records, and Variant Records

Pascal maps arrays and records into storage like C maps arrays and structures.

Arrays

An array has the same boundary requirements as the data type specified for the array. The size of an array is the size of the data type, multiplied by the number of elements.

For example, for the following declaration,

x : array [1..2, 1..3] of double;

the size of the resulting array is 48 bytes (2*3*8, where 8 is the size of the double-floating point type in bytes).

Records

Each member of a record begins at an offset from the record base. The offset corresponds to the order in which a member is declared; the first member is at offset 0.

The size of a record in the object file is the size of its combined members plus padding added, where necessary, by the compiler.

The following rules apply to records:

  • Records must align on the same boundary as that required by the member with the most restrictive boundary requirement. These are the boundary requirements, listed by increasing degree of restrictiveness:

    • byte

    • halfword

    • doubleword

  • The compiler terminates the record on the same alignment boundary on which it begins. For example, if a record begins on an even-byte boundary, it also ends on an even-byte boundary.

Example: Record

This example shows a record in code:

type S = record
     v : integer;
     n : array [1..10] of char;
end;

Figure 3-1 shows how it is mapped in storage.

Figure 3-1. Record in Storage, End Padded


Note that the length of the record is 16 bytes, even though the byte count as defined by the v:integer and the n:array[1..10] of char components is only 14. Because integer has a stricter boundary requirement (word boundary) than char (byte boundary), the record must end on a word boundary (a byte offset divisible by four). The compiler therefore adds two bytes of padding to meet this requirement.

An array of data records illustrates the reason for this requirement. For example, if the above record were the element-type of an array, some of the v:integer components would not be aligned properly without the two-byte pad.

Example: Record with Different Alignment

This example shows a record with different alignment in code:

type S = record
     n : packed array [1..10] of char;
     v : integer;
end;

Figure 3-2 shows how it is mapped in storage.

Figure 3-2. Record in Storage, Middle Padding


In the example, the alignment requirements cause padding to appear in the middle of the record. Note that the size of the record remains 16 bytes, but two bytes of padding follow the n component to align v on a word boundary.

Variant Records

A variant record must align on the same boundary as the member with the most restrictive boundary requirement.

These are the boundary requirements, listed by increasing degree of restrictiveness:

  • byte

  • halfword

  • word

  • doubleword

For example, a variant record containing integer, char, and double data types must align on a doubleword boundary, as required by the double data type.

Ranges

Ranges in a packed record are packed from the most-significant bit to the least-significant bit in a word.

Ranges in a Packed Record

This example shows a packed record in code:

type virtual_address = packed record
    offset : 0..4095;               (* 12 bits *)
    page : 0..1023;                 (* 10 bits *)
    segment : 0..511;               (* 9 bits *)
    supervisor : 0..1;              (* 1 bit *)
end;

Figure 3-3 shows how it is mapped in storage.

Figure 3-3. Ranges in a Packed Record


Ranges in an Unpacked Record

Ranges in an unpacked record are packed from the most-significant bit to the least-significant bit, but each range is aligned to the appropriate boundary. This example shows an unpacked record in code:

type virtual_address = record
    offset : 0..4095;        (* 12 bits *)
    page : 0..1023;          (* 10 bits *)
    segment : 0..511;        (* 9 bits *)
    supervisor : 0..1;       (* 1 bit *)
end;

Figure 3-4 shows how it is mapped in storage.

Figure 3-4. Ranges in an Unpacked Record


Non-Ranges Following Ranges in Unpacked Records

For unpacked records, the compiler aligns a non-range element that follows a range declaration to the next boundary appropriate for its type.

This example shows another unpacked record in code:

var x : record
    a : 0..7;                 (* 3 bits packed *)
    b : char;                 (* 8 bits *)
    c : -32768..32767;        (* 16 bits *)
end;

Figure 3-5 shows how it is mapped in storage.

Figure 3-5. Non-Range Elements in an Unpacked Record


Non-Range Elements in a Packed Record

For a packed record, the computer bit-aligns booleans, chars, and ranges. All other types are word or double-word aligned as appropriate for the type. This example shows the same code as above in a packed record and its mapping in storage:

var x : packed record
    a : 0..7;             (* 3 bits *)
    b : char;             (* 8 bits *)
    c : -32768..32767     (* 16 bits *)
end;

Figure 3-6 shows how it is mapped in storage.

Figure 3-6. Non-Range Elements in a Packed Record


Alignment, Size, and Value by Data Type

This section describes how the Pascal compiler implements size, alignment, and value ranges for the various data types.

Table 3-1 shows the value ranges for the Pascal scalar types.

Table 3-1. Value Ranges by Data Type

Scalar Type

Value Ranges

boolean

0 or 1

char

0..127

integer

-231..231-1

cardinal

0..232-1

real

See Note

double

See Note



Note: See Table 3-2 and Table 3-3 for more data.

Table 3-2 and Table 3-3 show the approximate valid ranges for real and double. Enumerated types with n elements are treated in the same manner as the integer subrange 0..n-1.

Table 3-2. Real and Double Maximum Values

Type

Maximum Value

real

3.40282356*1038

double

1.7976931348623158*10308


Table 3-3. Real and Double Minimum Values

 

Minimum Value

 

Type

Denormalized

Normalized

real

1.40129846 * 10-46

1.17 549429 * 10-38

double

4.9406564584124654*10-324

2.2250738585072012*10-308


Set Sizing for Unpacked Records

Table 3-4, following, lists size and alignment parameters for unpacked records. See Section 3.4, “Rules for Set Sizes,” for rules about specifying the upper and lower bounds of s

Table 3-4. Size and Alignment of Data Types in Unpacked Records or Arrays

 

Unpacked Records or Arrays (variables or fields)

 

Type

Size

Alignment

boolean

8

byte

char

8

byte

integer

32

word

cardinal

32

word

pointer

32

word

file

32

word

real

32

word

double

64

doubleword

subrange of:

 

 

0..255 or -128..127

8

byte

0..65535 or -32768..32767

16

halfword

0..232 - 1

 

 

-231..-231 - 1

32

word

set of char

128

word

set of a..b

See note

word



Note: For unpacked records, the compiler uses the following formula for determining the size of the set of a..b:


       size=[b2⌋ - ⌊a/32⌋ + 1 words

The notation [ x ] indicates the floor of x, which is the largest

integer not greater than x.

Set Sizing for Packed Arrays by Type

The compiler uses the rules shown in Table 3-5 for aligning packed arrays.

Table 3-5. Size and Alignment of Pascal Packed Arrays

 

Packed Arrays

 

Scalar Type

Size

Alignment

boolean

8

byte

char

8

byte

integer

32

word

cardinal

32

word

pointer

32

word

file

32

word

real

32

word

double

64

doubleword

subrange of:

 

 

0..1 or -1..0

1

bit

0..3 or -2..1

2

2-bit

0..15 or -8..7

4

4-bit

0..255 or -128..127

8

byte

0..65535 or -32768..32767

16

halfword

0..232 - 1

 

 

-231..-231 - 1

32

word

set of char

128

word

set of a..b

See note

 



Note: For packed arrays, the compiler uses the minimum number of bits possible in creating the set of a..b.

The following formula is used:

If
   (b - 32 ⌊a/32⌋ + 1 ) ≤ 32
then
   size = b - 32 \ξεβ a/32⌋ + 1 bits
else
   size = ⌊b/32⌋ - \ξεβ a/32⌋ + 1 words

Note that the set of a..b is aligned on an n-bit boundary where n is a power of 2. The value of n is computed as follows:

n = 2log2(size)

For example, the set of 0..2 has a size of 3 bits as computed above and will align on a 4-bit boundary.

See Section 3.4 at the end of this chapter for rules about specifying the upper and lower bounds of sets.

Packed Record Alignment

The compiler uses the rules shown in Table 3-6 for aligning packed records.

Table 3-6. Size and Alignment of Pascal Packed Records

Packed Arrays

 

Scalar Type

Size

Alignment

boolean

8

byte

char

8

byte

integer

32

word

cardinal

32

word

pointer

32

word

file

32

word

real

32

word

double

64

doubleword

subrange of a..b

See note

bit/word



Note: For packed records, the compiler uses the minimum number of bits possible in creating a subrange field.

For the subrange a..b, this formula is used:

If  a >= 0  then  size = ⌈log2(b + 1) ⌉ bits

If a > 0    then  size = max(⌈log2(b + 1)⌉,⌈log2(-a ) ⌉)+1  bits 

The notation ⌈ x ⌉ indicates the ceiling of x, which is the smallest integer not less than x.

To avoid crossing a word boundary, the compiler moves data types aligned to bit boundaries in a packed record to the next word.

Rules for Set Sizes

The maximum number of elements permitted in a set ranges between 481 and 512. This variance is due to the way Pascal implements sets. For efficient accessing of set elements, Pascal expects the lower-bound of a set to be a multiple of 32. If for the set specified:

set of a..b

a is not a multiple of 32, Pascal adds elements to the set from a down to the next multiple of 32 less than a.

For example, the set:

set of 5..31

would have internal padding elements 0..4 added. These padding elements are inaccessible to the program. This implementation sacrifices some space for a fast, consistent method of accessing set elements.

The padding required to pad the lower bound down to a multiple of 32 varies between 0 and 31 elements.

For the set of a..b to be a valid set in Pascal, the following conditions must be met:

size = ( b - 32 ⌊a / 32⌋+ 1 ) < 512

Table 3-7 shows some example sets and whether each set is valid by the above equation.

Table 3-7. Set Specifications

Specification

Lower

Upper

Set Size

Valid Size

set of 1..511

0 (padded down to value by Pascal)

511

512

Yes

set of 0..511

0

511

512

Yes

set of 1..512

0*

512

513

No

set of 31..512

0*

512

513

No

set of 32..512

32

512

481

Yes

set of 32..543

32

543

512

Yes