new bitfield struct layout code for big-endian (=sparc) machines
authorMatthias Braun <matze@braunis.de>
Mon, 6 Sep 2010 13:06:09 +0000 (13:06 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 6 Sep 2010 13:06:09 +0000 (13:06 +0000)
[r27975]

lang_features.h
main.c
type.c

index b51b8cb..2d967f8 100644 (file)
@@ -34,19 +34,22 @@ typedef enum lang_features_t {
        _ALL  = 0xFF
 } lang_features_t;
 
-/* the current C mode/dialect */
+/** the current C mode/dialect */
 extern unsigned int c_mode;
 
-/* the 'machine size', 16, 32 or 64 bit */
+/** the 'machine size', 16, 32 or 64 bit */
 extern unsigned int machine_size;
 
-/* true if the char type is signed */
+/** byte-order: true = big-endian, false = little-endian */
+extern bool byte_order_big_endian;
+
+/** true if the char type is signed */
 extern bool char_is_signed;
 
-/* true for strict language checking. */
+/** true for strict language checking. */
 extern bool strict_mode;
 
-/* atomic type of wchar_t */
+/** atomic type of wchar_t */
 extern atomic_type_kind_t wchar_atomic_kind;
 
 #endif
diff --git a/main.c b/main.c
index 568063e..5e3e769 100644 (file)
--- a/main.c
+++ b/main.c
 #endif
 #endif
 
-/** The current c mode/dialect. */
-unsigned int c_mode = _C89 | _ANSI | _C99 | _GNUC;
-
-/** The 'machine size', 16, 32 or 64 bit, 32bit is the default. */
-unsigned int machine_size = 32;
-
-/** true if the char type is signed. */
-bool char_is_signed = true;
-
-/** true for strict language checking. */
-bool strict_mode = false;
-
-/** use builtins for some libc functions */
-bool use_builtins = false;
-
-/** we have extern function with const attribute. */
-bool have_const_functions = false;
-
-atomic_type_kind_t wchar_atomic_kind = ATOMIC_TYPE_INT;
+unsigned int       c_mode                = _C89 | _ANSI | _C99 | _GNUC;
+unsigned int       machine_size          = 32;
+bool               byte_order_big_endian = false;
+bool               char_is_signed        = true;
+bool               strict_mode           = false;
+bool               use_builtins          = false;
+bool               have_const_functions  = false;
+atomic_type_kind_t wchar_atomic_kind     = ATOMIC_TYPE_INT;
 
 /* to switch on printing of implicit casts */
 extern bool print_implicit_casts;
@@ -1182,6 +1171,7 @@ int main(int argc, char **argv)
        c_mode &= ~features_off;
 
        gen_firm_init();
+       byte_order_big_endian = be_get_backend_param()->byte_order_big_endian;
        init_symbol_table();
        init_types();
        init_typehash();
diff --git a/type.c b/type.c
index f36d446..2f7ff1b 100644 (file)
--- a/type.c
+++ b/type.c
@@ -1682,6 +1682,57 @@ type_t *make_array_type(type_t *element_type, size_t size,
        return identify_new_type(type);
 }
 
+static entity_t *pack_bitfield_members_big_endian(il_size_t *struct_offset,
+               il_alignment_t *struct_alignment, bool packed, entity_t *first)
+{
+       type_t        *current_base_type = NULL;
+       il_size_t      offset            = *struct_offset;
+       il_alignment_t alignment         = *struct_alignment;
+       size_t         bit_offset        = 0;
+
+       if (packed)
+               panic("packed bitfields on big-endian arch not supported yet");
+
+       entity_t *member;
+       for (member = first; member != NULL; member = member->base.next) {
+               if (member->kind != ENTITY_COMPOUND_MEMBER)
+                       continue;
+
+               type_t *type = member->declaration.type;
+               if (type->kind != TYPE_BITFIELD)
+                       break;
+
+               size_t  bit_size  = type->bitfield.bit_size;
+               type_t *base_type = skip_typeref(type->bitfield.base_type);
+
+               /* see if we need to start a new "bucket" */
+               if (base_type != current_base_type || bit_size > bit_offset) {
+                       if (current_base_type != NULL)
+                               offset += get_type_size(current_base_type);
+
+                       current_base_type = base_type;
+                       il_alignment_t base_alignment = get_type_alignment(base_type);
+                       il_alignment_t alignment_mask = base_alignment-1;
+                       if (base_alignment > alignment)
+                               alignment = base_alignment;
+                       offset     = (offset + base_alignment-1) & ~alignment_mask;
+                       bit_offset = get_type_size(base_type) * BITS_PER_BYTE;
+                       assert(bit_offset >= bit_size);
+               }
+
+               bit_offset -= bit_size;
+               member->compound_member.offset     = offset;
+               member->compound_member.bit_offset = bit_offset;
+       }
+
+       if (current_base_type != NULL)
+               offset += get_type_size(current_base_type);
+
+       *struct_offset    = offset;
+       *struct_alignment = alignment;
+       return member;
+}
+
 static entity_t *pack_bitfield_members(il_size_t *struct_offset,
                                        il_alignment_t *struct_alignment,
                                                                           bool packed, entity_t *first)
@@ -1693,7 +1744,7 @@ static entity_t *pack_bitfield_members(il_size_t *struct_offset,
        entity_t *member;
        for (member = first; member != NULL; member = member->base.next) {
                if (member->kind != ENTITY_COMPOUND_MEMBER)
-                       break;
+                       continue;
 
                type_t *type = member->declaration.type;
                if (type->kind != TYPE_BITFIELD)
@@ -1731,7 +1782,6 @@ static entity_t *pack_bitfield_members(il_size_t *struct_offset,
 
        *struct_offset    = offset;
        *struct_alignment = alignment;
-
        return member;
 }
 
@@ -1764,8 +1814,14 @@ void layout_struct_type(compound_type_t *type)
                }
 
                if (skipped->kind == TYPE_BITFIELD) {
-                       entry = pack_bitfield_members(&offset, &alignment,
-                                                     compound->packed, entry);
+                       if (byte_order_big_endian) {
+                               entry = pack_bitfield_members_big_endian(&offset, &alignment,
+                                                                        compound->packed,
+                                                                        entry);
+                       } else {
+                               entry = pack_bitfield_members(&offset, &alignment,
+                                                             compound->packed, entry);
+                       }
                        continue;
                }