decl.c (gnat_to_gnu_entity): Add support for scalar types with small alignment.
authorEric Botcazou <ebotcazou@adacore.com>
Sat, 8 Mar 2008 11:10:18 +0000 (11:10 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Sat, 8 Mar 2008 11:10:18 +0000 (11:10 +0000)
* decl.c (gnat_to_gnu_entity) <E_Signed_Integer_Subtype>: Add support
for scalar types with small alignment.

From-SVN: r133027

gcc/ada/ChangeLog
gcc/ada/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/small_alignment.adb [new file with mode: 0644]

index 4d6f170f31735fe031e9cdc53a6f602934e47889..2a10f10f1b68e648880a0de873aefd81e14143b3 100644 (file)
@@ -1,3 +1,8 @@
+2008-03-08  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * decl.c (gnat_to_gnu_entity) <E_Signed_Integer_Subtype>: Add support
+       for scalar types with small alignment.
+
 2008-03-08  Eric Botcazou  <ebotcazou@adacore.com>
 
        * trans.c (Loop_Statement_to_gnu): Set the SLOC of the loop label
index c1d02ec5d5eea23f56ffceb5eb7a6ed6198439d8..62783202f01fc125800194d57ff3c9fd1ec7ec13 100644 (file)
@@ -1520,6 +1520,45 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
          copy_alias_set (gnu_type, gnu_field_type);
        }
 
+      /* If the type we are dealing with has got a smaller alignment than the
+        natural one, we need to wrap it up in a record type and under-align
+        the latter.  We reuse the padding machinery for this purpose.  */
+      else if (Known_Alignment (gnat_entity)
+              && UI_Is_In_Int_Range (Alignment (gnat_entity))
+              && (align = UI_To_Int (Alignment (gnat_entity)) * BITS_PER_UNIT)
+              && align < TYPE_ALIGN (gnu_type))
+       {
+         tree gnu_field_type = gnu_type;
+         tree gnu_field;
+
+         gnu_type = make_node (RECORD_TYPE);
+         TYPE_NAME (gnu_type) = create_concat_name (gnat_entity, "PAD");
+
+         TYPE_ALIGN (gnu_type) = align;
+         TYPE_PACKED (gnu_type) = 1;
+
+         /* Create a stripped-down declaration of the original type, mainly
+            for debugging.  */
+         create_type_decl (get_entity_name (gnat_entity), gnu_field_type,
+                           NULL, true, debug_info_p, gnat_entity);
+
+         /* Don't notify the field as "addressable", since we won't be taking
+            it's address and it would prevent create_field_decl from making a
+            bitfield.  */
+         gnu_field = create_field_decl (get_identifier ("OBJECT"),
+                                        gnu_field_type, gnu_type, 1, 0, 0, 0);
+
+         finish_record_type (gnu_type, gnu_field, 0, false);
+         TYPE_IS_PADDING_P (gnu_type) = 1;
+         SET_TYPE_ADA_SIZE (gnu_type, bitsize_int (esize));
+
+         copy_alias_set (gnu_type, gnu_field_type);
+       }
+
+      /* Otherwise reset the alignment lest we computed it above.  */
+      else
+       align = 0;
+
       break;
 
     case E_Floating_Point_Type:
index 5a6735d7df436f0ff2fd14448a5917a3c00800e1..64896b804ef5298b5147cf4877d139c07af829cc 100644 (file)
@@ -1,3 +1,7 @@
+2008-03-08  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/small_alignment.adb: New test.
+
 2008-03-07  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/specs/alignment2.ads: New test.
diff --git a/gcc/testsuite/gnat.dg/small_alignment.adb b/gcc/testsuite/gnat.dg/small_alignment.adb
new file mode 100644 (file)
index 0000000..fbe1c21
--- /dev/null
@@ -0,0 +1,28 @@
+-- { dg-do run }
+-- { dg-options "-gnatws" }
+
+procedure Small_Alignment is
+
+  type My_Integer is new Integer;
+  for My_Integer'Alignment use 1;
+
+  function Set_A return My_Integer is
+  begin
+    return 12;
+  end;
+
+  function Set_B return My_Integer is
+  begin
+    return 6;
+  end;
+
+  C : Character;
+  A : My_Integer := Set_A;
+  B : My_Integer := Set_B;
+
+begin
+  A := A * B / 2;
+  if A /= 36 then
+    raise Program_Error;
+  end if;
+end;