summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog27
-rw-r--r--gcc/ada/ChangeLog7
-rw-r--r--gcc/ada/gcc-interface/utils2.c23
-rw-r--r--gcc/output.h5
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gnat.dg/oconst1.adb18
-rw-r--r--gcc/testsuite/gnat.dg/oconst1.ads25
-rw-r--r--gcc/testsuite/gnat.dg/oconst2.adb15
-rw-r--r--gcc/testsuite/gnat.dg/oconst2.ads23
-rw-r--r--gcc/testsuite/gnat.dg/oconst3.adb16
-rw-r--r--gcc/testsuite/gnat.dg/oconst3.ads26
-rw-r--r--gcc/testsuite/gnat.dg/oconst4.adb24
-rw-r--r--gcc/testsuite/gnat.dg/oconst4.ads66
-rw-r--r--gcc/testsuite/gnat.dg/oconst5.adb15
-rw-r--r--gcc/testsuite/gnat.dg/oconst5.ads27
-rw-r--r--gcc/testsuite/gnat.dg/oconst6.ads18
-rw-r--r--gcc/testsuite/gnat.dg/test_oconst.adb13
-rw-r--r--gcc/tree.h5
-rw-r--r--gcc/varasm.c742
19 files changed, 815 insertions, 285 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f589b8a8c25..eee6e8447fd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,30 @@
+2009-06-01 Olivier Hainque <hainque@adacore.com>
+ Eric Botcazou <botcazou@adacore.com>
+
+ * tree.h (CONSTRUCTOR_BITFIELD_P): True if NODE, a FIELD_DECL, is
+ to be processed as a bitfield for constructor output purposes.
+ * output.h (initializer_constant_valid_for_bitfield_p): Declare
+ new function.
+ * varasm.c (oc_local_state): New type, output_constructor
+ local state to support communication with helpers.
+ (oc_outer_state): New type, output_constructor outer state of
+ relevance in recursive calls.
+ (output_constructor_array_range): New output_constructor helper,
+ extracted code for an array range element.
+ (output_constructor_regular_field): New output_constructor helper,
+ extracted code for an element that is not a bitfield.
+ (output_constructor_bitfield): New output_constructor helper,
+ extracted code for a bitfield element. Accept an OUTER state
+ argument for recursive processing. Recurse on record or array
+ CONSTRUCTOR values, possibly past noop conversions.
+ (initializer_constant_valid_for_bitfield_p): New predicate. Whether
+ VALUE is a valid constant-valued expression for use in a static
+ bit-field initializer.
+ (output_constructor): Rework to use helpers. Accept and honor an
+ OUTER state argument for recursive calls. Return total size. Be
+ prepared for nested constructors initializing bitfields.
+ (output_constant): Feed OUTER in calls to output_constructor.
+
2009-06-01 Maxim Kuvyrkov <maxim@codesourcery.com>
* calls.c (emit_library_call_value_1): Don't force_operand for move
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 69aa6229e25..51be8bf3a22 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,10 @@
+2009-06-01 Olivier Hainque <hainque@adacore.com>
+ Eric Botcazou <botcazou@adacore.com>
+
+ * gcc-interface/utils2.c (gnat_build_constructor): Factor
+ out code. Use initializer_constant_valid_for_bitfield_p and
+ CONSTRUCTOR_BITFIELD_P for bit-fields.
+
2009-05-26 Ian Lance Taylor <iant@google.com>
* gcc-interface/Makefile.in (COMPILER): Define.
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index 3fe85853879..ec72a27ebbc 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -1623,34 +1623,35 @@ compare_elmt_bitpos (const PTR rt1, const PTR rt2)
tree
gnat_build_constructor (tree type, tree list)
{
- tree elmt;
- int n_elmts;
bool allconstant = (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST);
bool side_effects = false;
- tree result;
+ tree elmt, result;
+ int n_elmts;
/* Scan the elements to see if they are all constant or if any has side
effects, to let us set global flags on the resulting constructor. Count
the elements along the way for possible sorting purposes below. */
for (n_elmts = 0, elmt = list; elmt; elmt = TREE_CHAIN (elmt), n_elmts ++)
{
- if (!TREE_CONSTANT (TREE_VALUE (elmt))
+ tree obj = TREE_PURPOSE (elmt);
+ tree val = TREE_VALUE (elmt);
+
+ /* The predicate must be in keeping with output_constructor. */
+ if (!TREE_CONSTANT (val)
|| (TREE_CODE (type) == RECORD_TYPE
- && DECL_BIT_FIELD (TREE_PURPOSE (elmt))
- && TREE_CODE (TREE_VALUE (elmt)) != INTEGER_CST)
- || !initializer_constant_valid_p (TREE_VALUE (elmt),
- TREE_TYPE (TREE_VALUE (elmt))))
+ && CONSTRUCTOR_BITFIELD_P (obj)
+ && !initializer_constant_valid_for_bitfield_p (val))
+ || !initializer_constant_valid_p (val, TREE_TYPE (val)))
allconstant = false;
- if (TREE_SIDE_EFFECTS (TREE_VALUE (elmt)))
+ if (TREE_SIDE_EFFECTS (val))
side_effects = true;
/* Propagate an NULL_EXPR from the size of the type. We won't ever
be executing the code we generate here in that case, but handle it
specially to avoid the compiler blowing up. */
if (TREE_CODE (type) == RECORD_TYPE
- && (0 != (result
- = contains_null_expr (DECL_SIZE (TREE_PURPOSE (elmt))))))
+ && (result = contains_null_expr (DECL_SIZE (obj))) != NULL_TREE)
return build1 (NULL_EXPR, type, TREE_OPERAND (result, 0));
}
diff --git a/gcc/output.h b/gcc/output.h
index 543164a4c69..9e2b704920a 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -303,6 +303,11 @@ extern bool constructor_static_from_elts_p (const_tree);
arithmetic-combinations of integers. */
extern tree initializer_constant_valid_p (tree, tree);
+/* Return true if VALUE is a valid constant-valued expression
+ for use in initializing a static bit-field; one that can be
+ an element of a "constant" initializer. */
+extern bool initializer_constant_valid_for_bitfield_p (tree);
+
/* Output assembler code for constant EXP to FILE, with no label.
This includes the pseudo-op such as ".int" or ".byte", and a newline.
Assumes output_addressed_constants has been done on EXP already.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 10af18ea0da..f82565b5b37 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-06-01 Olivier Hainque <hainque@adacore.com>
+ Eric Botcazou <botcazou@adacore.com>
+
+ * gnat.dg/oconst[1-6].ad[bs]: New tests. Also support for ...
+ * gnat.dg/test_oconst.adb: New test.
2009-05-31 Basile Starynkevitch <basile@starynkevitch.net>
diff --git a/gcc/testsuite/gnat.dg/oconst1.adb b/gcc/testsuite/gnat.dg/oconst1.adb
new file mode 100644
index 00000000000..1e97ad8f2eb
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst1.adb
@@ -0,0 +1,18 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package body OCONST1 is
+
+ procedure check (arg : R) is
+ begin
+ if arg.u /= 1
+ or else arg.b.i1 /= 2
+ or else arg.b.i2 /= 3
+ or else arg.b.i3 /= 4
+ then
+ raise Program_Error;
+ end if;
+ end;
+
+end;
+
diff --git a/gcc/testsuite/gnat.dg/oconst1.ads b/gcc/testsuite/gnat.dg/oconst1.ads
new file mode 100644
index 00000000000..93b35f79bae
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst1.ads
@@ -0,0 +1,25 @@
+package OCONST1 is
+
+ type u8 is mod 2**8;
+
+ type Base is record
+ i1 : Integer;
+ i2 : Integer;
+ i3 : Integer;
+ end Record;
+
+ type R is record
+ u : u8;
+ b : Base;
+ end record;
+
+ for R use record
+ u at 0 range 0 .. 7;
+ b at 1 range 0 .. 95; -- BLKmode bitfield
+ end record;
+
+ My_R : constant R := (u=>1, b=>(2, 3, 4));
+
+ procedure check (arg : R);
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst2.adb b/gcc/testsuite/gnat.dg/oconst2.adb
new file mode 100644
index 00000000000..d4f45ad5d04
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst2.adb
@@ -0,0 +1,15 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package body OCONST2 is
+
+ procedure check (arg : R) is
+ begin
+ if arg.u /= 1
+ or else arg.b.i1 /= 2
+ then
+ raise Program_Error;
+ end if;
+ end;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst2.ads b/gcc/testsuite/gnat.dg/oconst2.ads
new file mode 100644
index 00000000000..23e57a74cc2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst2.ads
@@ -0,0 +1,23 @@
+package OCONST2 is
+
+ type u8 is mod 2**8;
+
+ type Base is record
+ i1 : Integer;
+ end Record;
+
+ type R is record
+ u : u8;
+ b : Base;
+ end record;
+
+ for R use record
+ u at 0 range 0 .. 7;
+ b at 1 range 0 .. 31; -- aligned SImode bitfield
+ end record;
+
+ My_R : constant R := (u=>1, b=>(i1=>2));
+
+ procedure check (arg : R);
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst3.adb b/gcc/testsuite/gnat.dg/oconst3.adb
new file mode 100644
index 00000000000..c9a94d4f491
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst3.adb
@@ -0,0 +1,16 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package body OCONST3 is
+
+ procedure check (arg : R) is
+ begin
+ if arg.u /= 1
+ or else arg.f /= one
+ or else arg.b.i1 /= 3
+ then
+ raise Program_Error;
+ end if;
+ end;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst3.ads b/gcc/testsuite/gnat.dg/oconst3.ads
new file mode 100644
index 00000000000..6a0094b57e9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst3.ads
@@ -0,0 +1,26 @@
+package OCONST3 is
+
+ type bit is (zero, one);
+ type u8 is mod 2**8;
+
+ type Base is record
+ i1 : Integer;
+ end Record;
+
+ type R is record
+ u : u8;
+ f : bit;
+ b : Base;
+ end record;
+
+ for R use record
+ u at 0 range 0 .. 7;
+ f at 1 range 0 .. 0;
+ b at 1 range 1 .. 32; -- unaligned SImode bitfield
+ end record;
+
+ My_R : constant R := (u=>1, f=>one, b=>(i1=>3));
+
+ procedure check (arg : R);
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst4.adb b/gcc/testsuite/gnat.dg/oconst4.adb
new file mode 100644
index 00000000000..f97f217b3da
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst4.adb
@@ -0,0 +1,24 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package body OCONST4 is
+
+ procedure check (arg : R) is
+ begin
+ if arg.u /= 1
+ or else arg.d.f1 /= 17
+ or else arg.d.b.f1 /= one
+ or else arg.d.b.f2 /= 2
+ or else arg.d.b.f3 /= 17
+ or else arg.d.b.f4 /= 42
+ or else arg.d.f2 /= one
+ or else arg.d.f3 /= 1
+ or else arg.d.f4 /= 111
+ or else arg.d.i1 /= 2
+ or else arg.d.i2 /= 3
+ then
+ raise Program_Error;
+ end if;
+ end;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst4.ads b/gcc/testsuite/gnat.dg/oconst4.ads
new file mode 100644
index 00000000000..cde0935fe8d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst4.ads
@@ -0,0 +1,66 @@
+package OCONST4 is
+
+ type bit is (zero, one);
+ type u2 is mod 2**2;
+ type u5 is mod 2**5;
+ type u8 is mod 2**8;
+
+ type Base is record
+ f1 : bit;
+ f2 : u2;
+ f3 : u5;
+ f4 : u8;
+ end record;
+
+ for Base use record
+ f1 at 0 range 0 .. 0;
+ f2 at 0 range 1 .. 2;
+ f3 at 0 range 3 .. 7;
+ f4 at 1 range 0 .. 7;
+ end record;
+
+ type Derived is record
+ f1 : u5;
+ b : Base;
+ f2 : bit;
+ f3 : u2;
+ f4 : u8;
+ i1 : Integer;
+ i2 : Integer;
+ end record;
+
+ for Derived use record
+ f1 at 0 range 0 .. 4;
+ b at 0 range 5 .. 20; -- unaligned HImode bitfield
+ f2 at 0 range 21 .. 21;
+ f3 at 0 range 22 .. 23;
+ f4 at 0 range 24 .. 31;
+ i1 at 4 range 0 .. 31;
+ i2 at 8 range 0 .. 31;
+ end record;
+
+ type R is record
+ u : u8;
+ d : Derived;
+ end record;
+
+ for R use record
+ u at 0 range 0 .. 7;
+ d at 1 range 0 .. 95; -- BLKmode bitfield
+ end record;
+
+ My_R : constant R := (u=>1,
+ d=>(f1=>17,
+ b=>(f1=>one,
+ f2=>2,
+ f3=>17,
+ f4=>42),
+ f2=>one,
+ f3=>1,
+ f4=>111,
+ i1=>2,
+ i2=>3));
+
+ procedure check (arg : R);
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst5.adb b/gcc/testsuite/gnat.dg/oconst5.adb
new file mode 100644
index 00000000000..4d4896aea58
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst5.adb
@@ -0,0 +1,15 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package body OCONST5 is
+
+ procedure Check (Arg : R; Bit : U1) is
+ begin
+ if Arg.Bit /= Bit
+ or else Arg.Agg.A /= 3
+ or else Arg.Agg.B /= 7
+ then
+ raise Program_Error;
+ end if;
+ end;
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst5.ads b/gcc/testsuite/gnat.dg/oconst5.ads
new file mode 100644
index 00000000000..f12a265d0d3
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst5.ads
@@ -0,0 +1,27 @@
+package OCONST5 is
+
+ type u1 is mod 2**1;
+ type u8 is mod 2**8;
+
+ type HI_Record is record
+ A, B : U8;
+ end record;
+ pragma Suppress_Initialization (HI_Record);
+
+ type R is record
+ Bit : U1;
+ Agg : HI_Record;
+ end record;
+ pragma Suppress_Initialization (R);
+
+ for R use record
+ Bit at 0 range 0 .. 0;
+ Agg at 0 range 1 .. 16;
+ end record;
+
+ My_R0 : R := (Bit => 0, Agg => (A => 3, B => 7));
+ My_R1 : R := (Bit => 1, Agg => (A => 3, B => 7));
+
+ procedure Check (Arg : R; Bit : U1);
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst6.ads b/gcc/testsuite/gnat.dg/oconst6.ads
new file mode 100644
index 00000000000..e4c3c50eb0d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst6.ads
@@ -0,0 +1,18 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package OCONST6 is
+
+ type Sequence is array (1 .. 1) of Natural;
+
+ type Message is record
+ Data : Sequence;
+ end record;
+
+ for Message'Alignment use 1;
+ pragma PACK (Message);
+
+ ACK : Message := (Data => (others => 1));
+
+end;
+
diff --git a/gcc/testsuite/gnat.dg/test_oconst.adb b/gcc/testsuite/gnat.dg/test_oconst.adb
new file mode 100644
index 00000000000..23e5a97d537
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/test_oconst.adb
@@ -0,0 +1,13 @@
+-- { dg-do run }
+
+with OCONST1, OCONST2, OCONST3, OCONST4, OCONST5;
+
+procedure Test_Oconst is
+begin
+ OCONST1.check (OCONST1.My_R);
+ OCONST2.check (OCONST2.My_R);
+ OCONST3.check (OCONST3.My_R);
+ OCONST4.check (OCONST4.My_R);
+ OCONST5.check (OCONST5.My_R0, 0);
+ OCONST5.check (OCONST5.My_R1, 1);
+end;
diff --git a/gcc/tree.h b/gcc/tree.h
index 0adf75d9530..5853d762afd 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1502,6 +1502,11 @@ struct GTY(()) tree_vec {
_ce___->value = VALUE; \
} while (0)
+/* True if NODE, a FIELD_DECL, is to be processed as a bitfield for
+ constructor output purposes. */
+#define CONSTRUCTOR_BITFIELD_P(NODE) \
+ (DECL_BIT_FIELD (FIELD_DECL_CHECK (NODE)) && DECL_MODE (NODE) != BLKmode)
+
/* A single element of a CONSTRUCTOR. VALUE holds the actual value of the
element. INDEX can optionally design the position of VALUE: in arrays,
it is the index where VALUE has to be placed; in structures, it is the
diff --git a/gcc/varasm.c b/gcc/varasm.c
index c85cf9ddf27..c5de9ae7a73 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -114,7 +114,6 @@ static void output_constant_def_contents (rtx);
static void output_addressed_constants (tree);
static unsigned HOST_WIDE_INT array_size_for_constructor (tree);
static unsigned min_align (unsigned, unsigned);
-static void output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int);
static void globalize_decl (tree);
#ifdef BSS_SECTION_ASM_OP
#ifdef ASM_OUTPUT_BSS
@@ -4366,6 +4365,55 @@ initializer_constant_valid_p (tree value, tree endtype)
return 0;
}
+/* Return true if VALUE is a valid constant-valued expression
+ for use in initializing a static bit-field; one that can be
+ an element of a "constant" initializer. */
+
+bool
+initializer_constant_valid_for_bitfield_p (tree value)
+{
+ /* For bitfields we support integer constants or possibly nested aggregates
+ of such. */
+ switch (TREE_CODE (value))
+ {
+ case CONSTRUCTOR:
+ {
+ unsigned HOST_WIDE_INT idx;
+ tree elt;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
+ if (!initializer_constant_valid_for_bitfield_p (elt))
+ return false;
+ return true;
+ }
+
+ case INTEGER_CST:
+ return true;
+
+ case VIEW_CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
+ return
+ initializer_constant_valid_for_bitfield_p (TREE_OPERAND (value, 0));
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/* output_constructor outer state of relevance in recursive calls, typically
+ for nested aggregate bitfields. */
+
+typedef struct {
+ unsigned int bit_offset; /* current position in ... */
+ int byte; /* ... the outer byte buffer. */
+} oc_outer_state;
+
+static unsigned HOST_WIDE_INT
+ output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int,
+ oc_outer_state *);
+
/* Output assembler code for constant EXP to FILE, with no label.
This includes the pseudo-op such as ".int" or ".byte", and a newline.
Assumes output_addressed_constants has been done on EXP already.
@@ -4504,7 +4552,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
switch (TREE_CODE (exp))
{
case CONSTRUCTOR:
- output_constructor (exp, size, align);
+ output_constructor (exp, size, align, NULL);
return;
case STRING_CST:
thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),
@@ -4542,7 +4590,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
case RECORD_TYPE:
case UNION_TYPE:
gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
- output_constructor (exp, size, align);
+ output_constructor (exp, size, align, NULL);
return;
case ERROR_MARK:
@@ -4598,316 +4646,462 @@ array_size_for_constructor (tree val)
return tree_low_cst (i, 1);
}
-/* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
- Generate at least SIZE bytes, padding if necessary. */
+/* Other datastructures + helpers for output_constructor. */
-static void
-output_constructor (tree exp, unsigned HOST_WIDE_INT size,
- unsigned int align)
-{
- tree type = TREE_TYPE (exp);
- tree field = 0;
- tree min_index = 0;
- /* Number of bytes output or skipped so far.
- In other words, current position within the constructor. */
- HOST_WIDE_INT total_bytes = 0;
- /* Nonzero means BYTE contains part of a byte, to be output. */
- int byte_buffer_in_use = 0;
- int byte = 0;
- unsigned HOST_WIDE_INT cnt;
- constructor_elt *ce;
+/* output_constructor local state to support interaction with helpers. */
- gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
+typedef struct {
- if (TREE_CODE (type) == RECORD_TYPE)
- field = TYPE_FIELDS (type);
+ /* Received arguments. */
+ tree exp; /* Constructor expression. */
+ unsigned HOST_WIDE_INT size; /* # bytes to output - pad if necessary. */
+ unsigned int align; /* Known initial alignment. */
- if (TREE_CODE (type) == ARRAY_TYPE
- && TYPE_DOMAIN (type) != 0)
- min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
+ /* Constructor expression data. */
+ tree type; /* Expression type. */
+ tree field; /* Current field decl in a record. */
+ tree min_index; /* Lower bound if specified for an array. */
- /* As LINK goes through the elements of the constant,
- FIELD goes through the structure fields, if the constant is a structure.
- if the constant is a union, then we override this,
- by getting the field from the TREE_LIST element.
- But the constant could also be an array. Then FIELD is zero.
+ /* Output processing state. */
+ HOST_WIDE_INT total_bytes; /* # bytes output so far / current position. */
+ bool byte_buffer_in_use; /* Whether byte ... */
+ int byte; /* ... contains part of a bitfield byte yet to
+ be output. */
- There is always a maximum of one element in the chain LINK for unions
- (even if the initializer in a source program incorrectly contains
- more one). */
- for (cnt = 0;
- VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), cnt, ce);
- cnt++, field = field ? TREE_CHAIN (field) : 0)
+ int last_relative_index; /* Implicit or explicit index of the last
+ array element output within a bitfield. */
+ /* Current element. */
+ tree val; /* Current element value. */
+ tree index; /* Current element index. */
+
+} oc_local_state;
+
+/* Helper for output_constructor. From the current LOCAL state, output a
+ RANGE_EXPR element. */
+
+static void
+output_constructor_array_range (oc_local_state *local)
+{
+ unsigned HOST_WIDE_INT fieldsize
+ = int_size_in_bytes (TREE_TYPE (local->type));
+
+ HOST_WIDE_INT lo_index
+ = tree_low_cst (TREE_OPERAND (local->index, 0), 0);
+ HOST_WIDE_INT hi_index
+ = tree_low_cst (TREE_OPERAND (local->index, 1), 0);
+ HOST_WIDE_INT index;
+
+ unsigned int align2
+ = min_align (local->align, fieldsize * BITS_PER_UNIT);
+
+ for (index = lo_index; index <= hi_index; index++)
{
- tree val = ce->value;
- tree index = 0;
+ /* Output the element's initial value. */
+ if (local->val == NULL_TREE)
+ assemble_zeros (fieldsize);
+ else
+ output_constant (local->val, fieldsize, align2);
+
+ /* Count its size. */
+ local->total_bytes += fieldsize;
+ }
+}
- /* The element in a union constructor specifies the proper field
- or index. */
- if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
- || TREE_CODE (type) == QUAL_UNION_TYPE)
- && ce->index != 0)
- field = ce->index;
+/* Helper for output_constructor. From the current LOCAL state, output a
+ field element that is not true bitfield or part of an outer one. */
- else if (TREE_CODE (type) == ARRAY_TYPE)
- index = ce->index;
+static void
+output_constructor_regular_field (oc_local_state *local)
+{
+ /* Field size and position. Since this structure is static, we know the
+ positions are constant. */
+ unsigned HOST_WIDE_INT fieldsize;
+ HOST_WIDE_INT fieldpos;
-#ifdef ASM_COMMENT_START
- if (field && flag_verbose_asm)
- fprintf (asm_out_file, "%s %s:\n",
- ASM_COMMENT_START,
- DECL_NAME (field)
- ? IDENTIFIER_POINTER (DECL_NAME (field))
- : "<anonymous>");
-#endif
+ unsigned int align2;
- /* Eliminate the marker that makes a cast not be an lvalue. */
- if (val != 0)
- STRIP_NOPS (val);
+ if (local->index != NULL_TREE)
+ fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
+ * ((tree_low_cst (local->index, 0)
+ - tree_low_cst (local->min_index, 0))));
+ else if (local->field != NULL_TREE)
+ fieldpos = int_byte_position (local->field);
+ else
+ fieldpos = 0;
+
+ /* Output any buffered-up bit-fields preceding this element. */
+ if (local->byte_buffer_in_use)
+ {
+ assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
+ local->total_bytes++;
+ local->byte_buffer_in_use = false;
+ }
+
+ /* Advance to offset of this element.
+ Note no alignment needed in an array, since that is guaranteed
+ if each element has the proper size. */
+ if ((local->field != NULL_TREE || local->index != NULL_TREE)
+ && fieldpos != local->total_bytes)
+ {
+ gcc_assert (fieldpos >= local->total_bytes);
+ assemble_zeros (fieldpos - local->total_bytes);
+ local->total_bytes = fieldpos;
+ }
+
+ /* Find the alignment of this element. */
+ align2 = min_align (local->align, BITS_PER_UNIT * fieldpos);
- if (index && TREE_CODE (index) == RANGE_EXPR)
+ /* Determine size this element should occupy. */
+ if (local->field)
+ {
+ fieldsize = 0;
+
+ /* If this is an array with an unspecified upper bound,
+ the initializer determines the size. */
+ /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,
+ but we cannot do this until the deprecated support for
+ initializing zero-length array members is removed. */
+ if (TREE_CODE (TREE_TYPE (local->field)) == ARRAY_TYPE
+ && TYPE_DOMAIN (TREE_TYPE (local->field))
+ && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (local->field))))
{
- unsigned HOST_WIDE_INT fieldsize
- = int_size_in_bytes (TREE_TYPE (type));
- HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0);
- HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0);
- HOST_WIDE_INT index;
- unsigned int align2 = min_align (align, fieldsize * BITS_PER_UNIT);
-
- for (index = lo_index; index <= hi_index; index++)
- {
- /* Output the element's initial value. */
- if (val == 0)
- assemble_zeros (fieldsize);
- else
- output_constant (val, fieldsize, align2);
-
- /* Count its size. */
- total_bytes += fieldsize;
- }
+ fieldsize = array_size_for_constructor (local->val);
+ /* Given a non-empty initialization, this field had
+ better be last. */
+ gcc_assert (!fieldsize || !TREE_CHAIN (local->field));
}
- else if (field == 0 || !DECL_BIT_FIELD (field))
+ else if (DECL_SIZE_UNIT (local->field))
{
- /* An element that is not a bit-field. */
+ /* ??? This can't be right. If the decl size overflows
+ a host integer we will silently emit no data. */
+ if (host_integerp (DECL_SIZE_UNIT (local->field), 1))
+ fieldsize = tree_low_cst (DECL_SIZE_UNIT (local->field), 1);
+ }
+ }
+ else
+ fieldsize = int_size_in_bytes (TREE_TYPE (local->type));
+
+ /* Output the element's initial value. */
+ if (local->val == NULL_TREE)
+ assemble_zeros (fieldsize);
+ else
+ output_constant (local->val, fieldsize, align2);
- unsigned HOST_WIDE_INT fieldsize;
- /* Since this structure is static,
- we know the positions are constant. */
- HOST_WIDE_INT pos = field ? int_byte_position (field) : 0;
- unsigned int align2;
+ /* Count its size. */
+ local->total_bytes += fieldsize;
+}
- if (index != 0)
- pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
- * (tree_low_cst (index, 0) - tree_low_cst (min_index, 0)));
+/* Helper for output_constructor. From the current LOCAL and OUTER states,
+ output an element that is a true bitfield or part of an outer one. */
- /* Output any buffered-up bit-fields preceding this element. */
- if (byte_buffer_in_use)
- {
- assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
- total_bytes++;
- byte_buffer_in_use = 0;
- }
-
- /* Advance to offset of this element.
- Note no alignment needed in an array, since that is guaranteed
- if each element has the proper size. */
- if ((field != 0 || index != 0) && pos != total_bytes)
- {
- gcc_assert (pos >= total_bytes);
- assemble_zeros (pos - total_bytes);
- total_bytes = pos;
- }
+static void
+output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
+{
+ /* Bit size of this element. */
+ HOST_WIDE_INT ebitsize
+ = (local->field
+ ? tree_low_cst (DECL_SIZE (local->field), 1)
+ : tree_low_cst (TYPE_SIZE (TREE_TYPE (local->type)), 1));
+
+ /* Relative index of this element if this is an array component. */
+ HOST_WIDE_INT relative_index
+ = (!local->field
+ ? (local->index
+ ? (tree_low_cst (local->index, 0)
+ - tree_low_cst (local->min_index, 0))
+ : local->last_relative_index + 1)
+ : 0);
+
+ /* Bit position of this element from the start of the containing
+ constructor. */
+ HOST_WIDE_INT constructor_relative_ebitpos
+ = (local->field
+ ? int_bit_position (local->field)
+ : ebitsize * relative_index);
+
+ /* Bit position of this element from the start of a possibly ongoing
+ outer byte buffer. */
+ HOST_WIDE_INT byte_relative_ebitpos
+ = ((outer ? outer->bit_offset : 0) + constructor_relative_ebitpos);
+
+ /* From the start of a possibly ongoing outer byte buffer, offsets to
+ the first bit of this element and to the first bit past the end of
+ this element. */
+ HOST_WIDE_INT next_offset = byte_relative_ebitpos;
+ HOST_WIDE_INT end_offset = byte_relative_ebitpos + ebitsize;
+
+ local->last_relative_index = relative_index;
+
+ if (local->val == NULL_TREE)
+ local->val = integer_zero_node;
+
+ while (TREE_CODE (local->val) == VIEW_CONVERT_EXPR
+ || TREE_CODE (local->val) == NON_LVALUE_EXPR)
+ local->val = TREE_OPERAND (local->val, 0);
+
+ if (TREE_CODE (local->val) != INTEGER_CST
+ && TREE_CODE (local->val) != CONSTRUCTOR)
+ {
+ error ("invalid initial value for member %qE", DECL_NAME (local->field));
+ return;
+ }
- /* Find the alignment of this element. */
- align2 = min_align (align, BITS_PER_UNIT * pos);
+ /* If this field does not start in this (or, next) byte,
+ skip some bytes. */
+ if (next_offset / BITS_PER_UNIT != local->total_bytes)
+ {
+ /* Output remnant of any bit field in previous bytes. */
+ if (local->byte_buffer_in_use)
+ {
+ assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
+ local->total_bytes++;
+ local->byte_buffer_in_use = false;
+ }
+
+ /* If still not at proper byte, advance to there. */
+ if (next_offset / BITS_PER_UNIT != local->total_bytes)
+ {
+ gcc_assert (next_offset / BITS_PER_UNIT >= local->total_bytes);
+ assemble_zeros (next_offset / BITS_PER_UNIT - local->total_bytes);
+ local->total_bytes = next_offset / BITS_PER_UNIT;
+ }
+ }
+
+ /* Set up the buffer if necessary. */
+ if (!local->byte_buffer_in_use)
+ {
+ local->byte = 0;
+ if (ebitsize > 0)
+ local->byte_buffer_in_use = true;
+ }
+
+ /* If this is nested constructor, recurse passing the bit offset and the
+ pending data, then retrieve the new pending data afterwards. */
+ if (TREE_CODE (local->val) == CONSTRUCTOR)
+ {
+ oc_outer_state output_state;
- /* Determine size this element should occupy. */
- if (field)
+ output_state.bit_offset = next_offset % BITS_PER_UNIT;
+ output_state.byte = local->byte;
+ local->total_bytes
+ += output_constructor (local->val, 0, 0, &output_state);
+ local->byte = output_state.byte;
+ return;
+ }
+
+ /* Otherwise, we must split the element into pieces that fall within
+ separate bytes, and combine each byte with previous or following
+ bit-fields. */
+ while (next_offset < end_offset)
+ {
+ int this_time;
+ int shift;
+ HOST_WIDE_INT value;
+ HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
+ HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
+
+ /* Advance from byte to byte
+ within this element when necessary. */
+ while (next_byte != local->total_bytes)
+ {
+ assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
+ local->total_bytes++;
+ local->byte = 0;
+ }
+
+ /* Number of bits we can process at once
+ (all part of the same byte). */
+ this_time = MIN (end_offset - next_offset,
+ BITS_PER_UNIT - next_bit);
+ if (BYTES_BIG_ENDIAN)
+ {
+ /* On big-endian machine, take the most significant bits
+ first (of the bits that are significant)
+ and put them into bytes from the most significant end. */
+ shift = end_offset - next_offset - this_time;
+
+ /* Don't try to take a bunch of bits that cross
+ the word boundary in the INTEGER_CST. We can
+ only select bits from the LOW or HIGH part
+ not from both. */
+ if (shift < HOST_BITS_PER_WIDE_INT
+ && shift + this_time > HOST_BITS_PER_WIDE_INT)
{
- fieldsize = 0;
-
- /* If this is an array with an unspecified upper bound,
- the initializer determines the size. */
- /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,
- but we cannot do this until the deprecated support for
- initializing zero-length array members is removed. */
- if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
- && TYPE_DOMAIN (TREE_TYPE (field))
- && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
- {
- fieldsize = array_size_for_constructor (val);
- /* Given a non-empty initialization, this field had
- better be last. */
- gcc_assert (!fieldsize || !TREE_CHAIN (field));
- }
- else if (DECL_SIZE_UNIT (field))
- {
- /* ??? This can't be right. If the decl size overflows
- a host integer we will silently emit no data. */
- if (host_integerp (DECL_SIZE_UNIT (field), 1))
- fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
- }
+ this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
+ shift = HOST_BITS_PER_WIDE_INT;
}
+
+ /* Now get the bits from the appropriate constant word. */
+ if (shift < HOST_BITS_PER_WIDE_INT)
+ value = TREE_INT_CST_LOW (local->val);
else
- fieldsize = int_size_in_bytes (TREE_TYPE (type));
-
- /* Output the element's initial value. */
- if (val == 0)
- assemble_zeros (fieldsize);
- else
- output_constant (val, fieldsize, align2);
-
- /* Count its size. */
- total_bytes += fieldsize;
+ {
+ gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
+ value = TREE_INT_CST_HIGH (local->val);
+ shift -= HOST_BITS_PER_WIDE_INT;
+ }
+
+ /* Get the result. This works only when:
+ 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
+ local->byte |= (((value >> shift)
+ & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
+ << (BITS_PER_UNIT - this_time - next_bit));
}
- else if (val != 0 && TREE_CODE (val) != INTEGER_CST)
- error ("invalid initial value for member %qE",
- DECL_NAME (field));
else
{
- /* Element that is a bit-field. */
+ /* On little-endian machines,
+ take first the least significant bits of the value
+ and pack them starting at the least significant
+ bits of the bytes. */
+ shift = next_offset - byte_relative_ebitpos;
+
+ /* Don't try to take a bunch of bits that cross
+ the word boundary in the INTEGER_CST. We can
+ only select bits from the LOW or HIGH part
+ not from both. */
+ if (shift < HOST_BITS_PER_WIDE_INT
+ && shift + this_time > HOST_BITS_PER_WIDE_INT)
+ this_time = (HOST_BITS_PER_WIDE_INT - shift);
+
+ /* Now get the bits from the appropriate constant word. */
+ if (shift < HOST_BITS_PER_WIDE_INT)
+ value = TREE_INT_CST_LOW (local->val);
+ else
+ {
+ gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
+ value = TREE_INT_CST_HIGH (local->val);
+ shift -= HOST_BITS_PER_WIDE_INT;
+ }
+
+ /* Get the result. This works only when:
+ 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
+ local->byte |= (((value >> shift)
+ & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
+ << next_bit);
+ }
+
+ next_offset += this_time;
+ local->byte_buffer_in_use = true;
+ }
+}
- HOST_WIDE_INT next_offset = int_bit_position (field);
- HOST_WIDE_INT end_offset
- = (next_offset + tree_low_cst (DECL_SIZE (field), 1));
+/* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
+ Generate at least SIZE bytes, padding if necessary. OUTER designates the
+ caller output state of relevance in recursive invocations. */
- if (val == 0)
- val = integer_zero_node;
+static unsigned HOST_WIDE_INT
+output_constructor (tree exp, unsigned HOST_WIDE_INT size,
+ unsigned int align, oc_outer_state * outer)
+{
+ unsigned HOST_WIDE_INT cnt;
+ constructor_elt *ce;
- /* If this field does not start in this (or, next) byte,
- skip some bytes. */
- if (next_offset / BITS_PER_UNIT != total_bytes)
- {
- /* Output remnant of any bit field in previous bytes. */
- if (byte_buffer_in_use)
- {
- assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
- total_bytes++;
- byte_buffer_in_use = 0;
- }
+ oc_local_state local;
- /* If still not at proper byte, advance to there. */
- if (next_offset / BITS_PER_UNIT != total_bytes)
- {
- gcc_assert (next_offset / BITS_PER_UNIT >= total_bytes);
- assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes);
- total_bytes = next_offset / BITS_PER_UNIT;
- }
- }
+ /* Setup our local state to communicate with helpers. */
+ local.exp = exp;
+ local.size = size;
+ local.align = align;
- if (! byte_buffer_in_use)
- byte = 0;
+ local.total_bytes = 0;
+ local.byte_buffer_in_use = outer != NULL;
+ local.byte = outer ? outer->byte : 0;
- /* We must split the element into pieces that fall within
- separate bytes, and combine each byte with previous or
- following bit-fields. */
+ local.type = TREE_TYPE (exp);
- /* next_offset is the offset n fbits from the beginning of
- the structure to the next bit of this element to be processed.
- end_offset is the offset of the first bit past the end of
- this element. */
- while (next_offset < end_offset)
- {
- int this_time;
- int shift;
- HOST_WIDE_INT value;
- HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
- HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
-
- /* Advance from byte to byte
- within this element when necessary. */
- while (next_byte != total_bytes)
- {
- assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
- total_bytes++;
- byte = 0;
- }
+ local.last_relative_index = -1;
- /* Number of bits we can process at once
- (all part of the same byte). */
- this_time = MIN (end_offset - next_offset,
- BITS_PER_UNIT - next_bit);
- if (BYTES_BIG_ENDIAN)
- {
- /* On big-endian machine, take the most significant bits
- first (of the bits that are significant)
- and put them into bytes from the most significant end. */
- shift = end_offset - next_offset - this_time;
-
- /* Don't try to take a bunch of bits that cross
- the word boundary in the INTEGER_CST. We can
- only select bits from the LOW or HIGH part
- not from both. */
- if (shift < HOST_BITS_PER_WIDE_INT
- && shift + this_time > HOST_BITS_PER_WIDE_INT)
- {
- this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
- shift = HOST_BITS_PER_WIDE_INT;
- }
-
- /* Now get the bits from the appropriate constant word. */
- if (shift < HOST_BITS_PER_WIDE_INT)
- value = TREE_INT_CST_LOW (val);
- else
- {
- gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
- value = TREE_INT_CST_HIGH (val);
- shift -= HOST_BITS_PER_WIDE_INT;
- }
-
- /* Get the result. This works only when:
- 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
- byte |= (((value >> shift)
- & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
- << (BITS_PER_UNIT - this_time - next_bit));
- }
- else
- {
- /* On little-endian machines,
- take first the least significant bits of the value
- and pack them starting at the least significant
- bits of the bytes. */
- shift = next_offset - int_bit_position (field);
-
- /* Don't try to take a bunch of bits that cross
- the word boundary in the INTEGER_CST. We can
- only select bits from the LOW or HIGH part
- not from both. */
- if (shift < HOST_BITS_PER_WIDE_INT
- && shift + this_time > HOST_BITS_PER_WIDE_INT)
- this_time = (HOST_BITS_PER_WIDE_INT - shift);
-
- /* Now get the bits from the appropriate constant word. */
- if (shift < HOST_BITS_PER_WIDE_INT)
- value = TREE_INT_CST_LOW (val);
- else
- {
- gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
- value = TREE_INT_CST_HIGH (val);
- shift -= HOST_BITS_PER_WIDE_INT;
- }
-
- /* Get the result. This works only when:
- 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
- byte |= (((value >> shift)
- & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
- << next_bit);
- }
+ local.min_index = NULL_TREE;
+ if (TREE_CODE (local.type) == ARRAY_TYPE
+ && TYPE_DOMAIN (local.type) != NULL_TREE)
+ local.min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (local.type));
+
+ gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
- next_offset += this_time;
- byte_buffer_in_use = 1;
- }
- }
- }
+ /* As CE goes through the elements of the constant, FIELD goes through the
+ structure fields if the constant is a structure. If the constant is a
+ union, we override this by getting the field from the TREE_LIST element.
+ But the constant could also be an array. Then FIELD is zero.
- if (byte_buffer_in_use)
+ There is always a maximum of one element in the chain LINK for unions
+ (even if the initializer in a source program incorrectly contains
+ more one). */
+
+ local.field = NULL_TREE;
+ if (TREE_CODE (local.type) == RECORD_TYPE)
+ local.field = TYPE_FIELDS (local.type);
+
+ for (cnt = 0;
+ VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), cnt, ce);
+ cnt++, local.field = local.field ? TREE_CHAIN (local.field) : 0)
{
- assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
- total_bytes++;
+ local.val = ce->value;
+ local.index = NULL_TREE;
+
+ /* The element in a union constructor specifies the proper field
+ or index. */
+ if ((TREE_CODE (local.type) == RECORD_TYPE
+ || TREE_CODE (local.type) == UNION_TYPE
+ || TREE_CODE (local.type) == QUAL_UNION_TYPE)
+ && ce->index != NULL_TREE)
+ local.field = ce->index;
+
+ else if (TREE_CODE (local.type) == ARRAY_TYPE)
+ local.index = ce->index;
+
+#ifdef ASM_COMMENT_START
+ if (local.field && flag_verbose_asm)
+ fprintf (asm_out_file, "%s %s:\n",
+ ASM_COMMENT_START,
+ DECL_NAME (local.field)
+ ? IDENTIFIER_POINTER (DECL_NAME (local.field))
+ : "<anonymous>");
+#endif
+
+ /* Eliminate the marker that makes a cast not be an lvalue. */
+ if (local.val != NULL_TREE)
+ STRIP_NOPS (local.val);
+
+ /* Output the current element, using the appropriate helper ... */
+
+ /* For an array slice not part of an outer bitfield. */
+ if (!outer
+ && local.index != NULL_TREE
+ && TREE_CODE (local.index) == RANGE_EXPR)
+ output_constructor_array_range (&local);
+
+ /* For a field that is neither a true bitfield nor part of an outer one,
+ known to be at least byte aligned and multiple-of-bytes long. */
+ else if (!outer
+ && (local.field == NULL_TREE
+ || !CONSTRUCTOR_BITFIELD_P (local.field)))
+ output_constructor_regular_field (&local);
+
+ /* For a true bitfield or part of an outer one. */
+ else
+ output_constructor_bitfield (&local, outer);
}
- if ((unsigned HOST_WIDE_INT)total_bytes < size)
- assemble_zeros (size - total_bytes);
+ /* If we are not at toplevel, save the pending data for our caller.
+ Otherwise output the pending data and padding zeros as needed. */
+ if (outer)
+ outer->byte = local.byte;
+ else
+ {
+ if (local.byte_buffer_in_use)
+ {
+ assemble_integer (GEN_INT (local.byte), 1, BITS_PER_UNIT, 1);
+ local.total_bytes++;
+ }
+
+ if ((unsigned HOST_WIDE_INT)local.total_bytes < local.size)
+ {
+ assemble_zeros (local.size - local.total_bytes);
+ local.total_bytes = local.size;
+ }
+ }
+
+ return local.total_bytes;
}
/* Mark DECL as weak. */