Brandon S
Brandon S

Reputation: 11

What does the Alignment clause in Ada do?

I'm not clear what the Alignment clause in Ada does. See an example below. I have a 40 bit sized record, and I'm not sure what happens when I use the clause.

    type Knots_Status_Record is
      record
        Value  : Knots;
        Status : Statuses;
      end record;

    for Knots_Status_Record use
      record
        Value  at 0 range  0 .. 31; -- 32
        Status at 0 range 32 .. 39; -- 8
      end record;

    for Knots_Status_Record'Alignment use 1;

Upvotes: 1

Views: 3543

Answers (1)

Jossi
Jossi

Reputation: 1080

Attribute Alignment

Alignment of x ensure the address is divisible by x

Data'Aligment = x <=> Data'Address mod x = 0

Implication

  • Some processors requires data address to be aligned to a specific alignment.
  • Some processors accesses data faster if the data address is aligned to a specific alignment.

Example address behavior

with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Text_IO; use Ada.Text_IO;
with System.Storage_Elements; use System.Storage_Elements;
with Ada.Assertions; use Ada.Assertions;
with Ada.Command_Line; use Ada.Command_Line;

procedure Main is

   function Get_Argument_1 return Natural is
   begin
      return Natural'Value (Argument (1));
   exception
      when others => raise Program_Error with "Missing natural argument(1)";
   end;

   -- Change this size to see what happens for every address aligment under 64.
   Float_Array_Size : Natural := Get_Argument_1;
   type Float_Array is array (Integer range 1 .. Float_Array_Size) of Float;

   F4 : Float_Array;
   for F4'Alignment use 4;
   F8 : Float_Array;
   for F8'Alignment use 8;
   F16 : Float_Array;
   for F16'Alignment use 16;
   F32 : Float_Array;
   for F32'Alignment use 32;
   F64 : Float_Array;
   for F64'Alignment use 64;

begin

   -- Check if a 4 aligned address could be a 64 aligned.
   Put (Integer(To_Integer(F4'Address) mod 64));
   -- Sometimes it is, sometimes not, depends partly of Float_Array_Size.
   New_Line;
   Put (Integer(To_Integer(F8'Address) mod 64));
   New_Line;
   Put (Integer(To_Integer(F16'Address) mod 64));
   New_Line;
   Put (Integer(To_Integer(F32'Address) mod 64));
   New_Line;
   Put (Integer(To_Integer(F64'Address) mod 64));

   -- Lets see if the address is aligned to 64 storage units.
   Assert (Integer(To_Integer(F64'Address) mod 64) = 0);

end;

External resources

http://www.adaic.org/resources/add_content/standards/05rm/html/RM-13-3.html http://www.adaic.org/resources/add_content/standards/05rm/html/RM-K.html

The value of this attribute is of type universal_integer, and nonnegative; zero means that the object is not necessarily aligned on a storage element boundary. If X'Alignment is not zero, then X is aligned on a storage unit boundary and X'Address is an integral multiple of X'Alignment (that is, the Address modulo the Alignment is zero).

https://docs.adacore.com/gnat_rm-docs/html/gnat_rm/gnat_rm/representation_clauses_and_pragmas.html https://gcc.gnu.org/onlinedocs/gnat_rm/Alignment-Clauses.html

GNAT requires that all alignment clauses specify a power of 2, and all default alignments are always a power of 2. The default alignment values are as follows:

https://en.wikibooks.org/wiki/Ada_Programming/Attributes/'Alignment

X'Alignment is an Ada attribute where X is any memory-allocated object or type. This attribute controls the address values used for objects. The alignment must be non-negative. A value of zero means that the object need not be allocated at the boundary of a storage units. Otherwise the address is a multiple of X's alignment. The alignment of an object may be set.

Upvotes: 4

Related Questions