aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ada/ChangeLog5
-rw-r--r--gcc/ada/decl.c39
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gnat.dg/small_alignment.adb28
4 files changed, 76 insertions, 0 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 4d6f170..2a10f10 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,5 +1,10 @@
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
from that of the front-end's end label.
(gnat_gimplify_stmt) <LOOP_STMT>: Set the SLOC of the backward goto
diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c
index c1d02ec..6278320 100644
--- a/gcc/ada/decl.c
+++ b/gcc/ada/decl.c
@@ -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:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5a6735d..64896b8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..fbe1c21
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/small_alignment.adb
@@ -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;