make code a bit more readble
[libfirm] / ir / be / ia32 / ia32_gen_decls.c
index c051db4..0fa4320 100644 (file)
@@ -74,48 +74,52 @@ static void dump_arith_tarval(obstack_t *obst, tarval *tv, int bytes)
        }
 }
 
+/**
+ * Return the tarval of an atomic initializer.
+ */
 static tarval *get_atomic_init_tv(ir_node *init)
 {
-       ir_mode *mode = get_irn_mode(init);
+       for (;;) {
+               ir_mode *mode = get_irn_mode(init);
 
-       switch (get_irn_opcode(init)) {
+               switch (get_irn_opcode(init)) {
 
-       case iro_Cast:
-               return get_atomic_init_tv(get_Cast_op(init));
+               case iro_Cast:
+                       init = get_Cast_op(init);
+                       continue;
 
-       case iro_Conv:
-               return get_atomic_init_tv(get_Conv_op(init));
+               case iro_Conv:
+                       init = get_Conv_op(init);
+                       continue;
 
-       case iro_Const:
-               return get_Const_tarval(init);
+               case iro_Const:
+                       return get_Const_tarval(init);
 
-       case iro_SymConst:
-               switch (get_SymConst_kind(init)) {
-               case symconst_ofs_ent:
-                       return new_tarval_from_long(get_entity_offset(get_SymConst_entity(init)), mode);
-                       break;
+               case iro_SymConst:
+                       switch (get_SymConst_kind(init)) {
+                       case symconst_ofs_ent:
+                               return new_tarval_from_long(get_entity_offset(get_SymConst_entity(init)), mode);
 
-               case symconst_type_size:
-                       return new_tarval_from_long(get_type_size_bytes(get_SymConst_type(init)), mode);
+                       case symconst_type_size:
+                               return new_tarval_from_long(get_type_size_bytes(get_SymConst_type(init)), mode);
 
-               case symconst_type_align:
-                       return new_tarval_from_long(get_type_alignment_bytes(get_SymConst_type(init)), mode);
+                       case symconst_type_align:
+                               return new_tarval_from_long(get_type_alignment_bytes(get_SymConst_type(init)), mode);
 
-               case symconst_enum_const:
-                       return get_enumeration_value(get_SymConst_enum(init));
+                       case symconst_enum_const:
+                               return get_enumeration_value(get_SymConst_enum(init));
 
-               default:
-                       return NULL;
-               }
+                       default:
+                               return NULL;
+                       }
 
                default:
                        return NULL;
+               }
        }
-
-       return NULL;
 }
 
-/*
+/**
  * dump an atomic value
  */
 static void do_dump_atomic_init(obstack_t *obst, ir_node *init)
@@ -199,7 +203,7 @@ static void do_dump_atomic_init(obstack_t *obst, ir_node *init)
        }
 }
 
-/*
+/**
  * dumps the type for given size (.byte, .long, ...)
  */
 static void dump_size_type(obstack_t *obst, int size) {
@@ -232,8 +236,8 @@ static void dump_size_type(obstack_t *obst, int size) {
        }
 }
 
-/*
- * dump an atomic value
+/**
+ * dump an atomic value to an obstack
  */
 static void dump_atomic_init(obstack_t *obst, ir_node *init)
 {
@@ -254,7 +258,7 @@ static void dump_atomic_init(obstack_t *obst, ir_node *init)
  * @param ent The entity
  * @return 1 if it is a string constant, 0 otherwise
  */
-static int ent_is_string_const(entity *ent)
+static int ent_is_string_const(ir_entity *ent)
 {
        int res = 0;
        ir_type *ty;
@@ -270,9 +274,9 @@ static int ent_is_string_const(entity *ent)
                        ir_mode *mode = get_type_mode(elm_ty);
 
                        /*
-                       * and the mode of the element type is an int of
-                       * the same size as the byte mode
-                       */
+                        * and the mode of the element type is an int of
+                        * the same size as the byte mode
+                        */
                        if (mode_is_int(mode)
                                && get_mode_size_bits(mode) == get_mode_size_bits(mode_Bs))
                        {
@@ -300,12 +304,12 @@ static int ent_is_string_const(entity *ent)
 }
 
 /**
- * Dump a atring constant.
+ * Dump a string constant.
  * No checks are made!!
  * @param obst The obst to dump on.
  * @param ent The entity to dump.
  */
-static void dump_string_cst(obstack_t *obst, entity *ent)
+static void dump_string_cst(obstack_t *obst, ir_entity *ent)
 {
        int i, n;
 
@@ -329,14 +333,14 @@ static void dump_string_cst(obstack_t *obst, entity *ent)
                        if (isprint(c))
                                obstack_printf(obst, "%c", c);
                        else
-                               obstack_printf(obst, "%O", c);
+                               obstack_printf(obst, "\\%o", c);
                        break;
                }
        }
        obstack_printf(obst, "\"\n");
 }
 
-static void dump_array_init(obstack_t *obst, entity *ent)
+static void dump_array_init(obstack_t *obst, ir_entity *ent)
 {
        const ir_type *ty = get_entity_type(ent);
        int i;
@@ -345,7 +349,7 @@ static void dump_array_init(obstack_t *obst, entity *ent)
 
        /* potential spare values should be already included! */
        for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
-               entity *step = get_compound_ent_value_member(ent, i);
+               ir_entity *step = get_compound_ent_value_member(ent, i);
                ir_type *stype = get_entity_type(step);
 
                if (get_type_mode(stype)) {
@@ -379,60 +383,76 @@ typedef struct {
        } v;
 } normal_or_bitfield;
 
-static void dump_compound_init(obstack_t *obst, entity *ent)
+/**
+ * Dump an initializer for a compound entity.
+ */
+static void dump_compound_init(obstack_t *obst, ir_entity *ent)
 {
-       ir_type *ty = get_entity_type(ent);
        normal_or_bitfield *vals;
-       int type_size;
-       int i, j;
-       int res;
+       int i, j, n = get_compound_ent_n_values(ent);
+       int last_ofs;
+
+       /* Find the initializer size. Sorrily gcc support a nasty feature:
+          The last filed of a compound may be a flexible array. This allows
+          initializers bigger than the type size. */
+       last_ofs = 0;
+       for (i = 0; i < n; ++i) {
+               int offset = get_compound_ent_value_offset_bytes(ent, i);
+               int bits_remainder = get_compound_ent_value_offset_bit_remainder(ent, i);
+               const compound_graph_path *path = get_compound_ent_value_path(ent, i);
+               int path_len = get_compound_graph_path_length(path);
+               ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
+               int value_len = get_type_size_bits(get_entity_type(last_ent));
+
+               offset += (value_len + bits_remainder + 7) >> 3;
 
-       res = compute_compound_ent_array_indices(ent);
-       if(!res) {
-               panic("Couldn't emit initializer for entity '%s'\n", get_entity_ld_name(ent));
+               if (offset > last_ofs) {
+                       last_ofs = offset;
+               }
        }
 
        /*
-        * in the worst case, every entity allocates one byte, so the type
-        * size should be equal or bigger the number of fields
+        * In the worst case, every initializer allocates one byte.
+        * Moreover, initializer might be big, do not allocate an stack.
         */
-       type_size = get_type_size_bytes(ty);
-       vals = alloca(type_size * sizeof(vals[0]));
-       memset(vals, 0, type_size * sizeof(vals[0]));
+       vals = xcalloc(last_ofs, sizeof(vals[0]));
 
        /* collect the values and store them at the offsets */
-       for(i = 0; i < get_compound_ent_n_values(ent); ++i) {
+       for (i = 0; i < n; ++i) {
                const compound_graph_path *path = get_compound_ent_value_path(ent, i);
                int path_len = get_compound_graph_path_length(path);
                int offset = get_compound_ent_value_offset_bytes(ent, i);
                int offset_bits = get_compound_ent_value_offset_bit_remainder(ent, i);
                ir_node *value = get_compound_ent_value(ent, i);
-               entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
+               ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
                int value_len = get_type_size_bits(get_entity_type(last_ent));
+               assert(offset >= 0);
+               assert(offset_bits >= 0);
 
-               if(offset_bits != 0 || value_len % 8 != 0) {
+               if (offset_bits != 0 || value_len % 8 != 0) {
                        tarval *shift, *shifted;
                        tarval *tv = get_atomic_init_tv(value);
-                       if(tv == NULL) {
+                       if (tv == NULL) {
                                panic("Couldn't get numeric value for bitfield initializer '%s'\n",
                                      get_entity_ld_name(ent));
                        }
                        shift = new_tarval_from_long(offset_bits, mode_Is);
                        shifted = tarval_shl(tv, shift);
-                       if(shifted == tarval_bad || shifted == tarval_undefined) {
+                       if (shifted == tarval_bad || shifted == tarval_undefined) {
                                panic("Couldn't shift numeric value for bitfield initializer '%s'\n",
                                      get_entity_ld_name(ent));
                        }
 
-                       for(j = 0; j < 4 && value_len > 0; ++j) {
-                               assert(offset + j < type_size);
+                       for (j = 0; j < 4 && value_len > 0; ++j) {
+                               assert(offset + j < last_ofs);
                                assert(vals[offset + j].kind == BITFIELD || vals[offset + j].v.value == NULL);
                                vals[offset + j].kind = BITFIELD;
                                vals[offset + j].v.bf_val |= get_tarval_sub_bits(shifted, j);
-                               value_len -= 8;
+                               value_len -= 8 - offset_bits;
+                               offset_bits = 0;
                        }
                } else {
-                       assert(offset < type_size);
+                       assert(offset < last_ofs);
                        assert(vals[offset].kind == NORMAL);
                        assert(vals[offset].v.value == NULL);
                        vals[offset].v.value = value;
@@ -440,7 +460,7 @@ static void dump_compound_init(obstack_t *obst, entity *ent)
        }
 
        /* now write them sorted */
-       for(i = 0; i < type_size; ) {
+       for (i = 0; i < last_ofs; ) {
                int space = 0, skip = 0;
                if (vals[i].kind == NORMAL) {
                   if(vals[i].v.value != NULL) {
@@ -455,7 +475,7 @@ static void dump_compound_init(obstack_t *obst, entity *ent)
 
                ++i;
                space = 0;
-               while(i < type_size && vals[i].kind == NORMAL && vals[i].v.value == NULL) {
+               while (i < last_ofs && vals[i].kind == NORMAL && vals[i].v.value == NULL) {
                        ++space;
                        ++i;
                }
@@ -463,12 +483,16 @@ static void dump_compound_init(obstack_t *obst, entity *ent)
                assert(space >= 0);
 
                /* a gap */
-               if(space > 0)
+               if (space > 0)
                        obstack_printf(obst, "\t.skip\t%d\n", space);
        }
+       xfree(vals);
 }
 
-static void dump_global(ia32_decl_env_t *env, entity *ent)
+/**
+ * Dump a global entity.
+ */
+static void dump_global(ia32_decl_env_t *env, ir_entity *ent)
 {
        obstack_t *obst;
        ir_type *type = get_entity_type(ent);
@@ -478,18 +502,18 @@ static void dump_global(ia32_decl_env_t *env, entity *ent)
        int align = get_type_alignment_bytes(type);
 
        obst = env->data_obst;
-       if(is_Method_type(type)) {
-               if(get_method_img_section(ent) == section_constructors) {
+       if (is_Method_type(type)) {
+               if (get_method_img_section(ent) == section_constructors) {
                        obst = env->ctor_obst;
                        obstack_printf(obst, ".balign\t%d\n", align);
                        dump_size_type(obst, align);
                        obstack_printf(obst, "%s\n", ld_name);
                }
                return;
-       } else if(variability == variability_constant) {
+       } else if (variability == variability_constant) {
                /* a constant entity, put it on the rdata */
                obst = env->rodata_obst;
-       } else if(variability == variability_uninitialized) {
+       } else if (variability == variability_uninitialized) {
                /* uninitialized entity put it in bss segment */
                obst = env->bss_obst;
        }
@@ -511,32 +535,18 @@ static void dump_global(ia32_decl_env_t *env, entity *ent)
 
        obstack_printf(obst, "%s:\n", ld_name);
 
-       if(variability == variability_uninitialized) {
+       if (variability == variability_uninitialized) {
                obstack_printf(obst, "\t.zero %d\n", get_type_size_bytes(type));
-               return;
-       }
-
-       if (is_atomic_type(type)) {
+       } else if (is_atomic_type(type)) {
                dump_atomic_init(obst, get_atomic_ent_value(ent));
-               return;
-       }
-
-       if (ent_is_string_const(ent)) {
+       } else if (ent_is_string_const(ent)) {
                dump_string_cst(obst, ent);
-               return;
-       }
-
-       if (is_Array_type(type)) {
+       } else if (is_Array_type(type)) {
                dump_array_init(obst, ent);
-               return;
-       }
-
-       if (is_compound_type(type)) {
+       } else if (is_compound_type(type)) {
                dump_compound_init(obst, ent);
-               return;
-       }
-
-       assert(0 && "unsupported type");
+       } else
+               assert(0 && "unsupported type");
 }
 
 /**
@@ -547,7 +557,7 @@ static void ia32_dump_globals(ir_type *gt, ia32_decl_env_t *env)
        int i, n = get_compound_n_members(gt);
 
        for (i = 0; i < n; i++) {
-               entity *ent = get_compound_member(gt, i);
+               ir_entity *ent = get_compound_member(gt, i);
                dump_global(env, ent);
        }
 }