case 12:
break;
+ case 16:
+ obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%02x%02x%02x%02x%02x%02x%02x%02x",
+ get_tarval_sub_bits(tv, 15), get_tarval_sub_bits(tv, 16),
+ get_tarval_sub_bits(tv, 13), get_tarval_sub_bits(tv, 12),
+ get_tarval_sub_bits(tv, 11), get_tarval_sub_bits(tv, 10),
+ get_tarval_sub_bits(tv, 9), get_tarval_sub_bits(tv, 8),
+ get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6),
+ get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
+ get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2),
+ get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
+ break;
+
+
default:
fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
assert(0);
}
}
+/**
+ * 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)
case iro_Const:
tv = get_Const_tarval(init);
- /* beware of old stuff */
- //assert(! mode_is_reference(mode));
-
/* it's a arithmetic value */
dump_arith_tarval(obst, tv, bytes);
return;
}
}
-/*
+/**
* dumps the type for given size (.byte, .long, ...)
*/
static void dump_size_type(obstack_t *obst, int size) {
/* handled in arith */
break;
+ case 16:
+ obstack_printf(obst, "\t.octa\t");
+ break;
+
default:
fprintf(stderr, "Try to dump a type with %d bytes\n", size);
assert(0);
}
}
-/*
- * dump an atomic value
+/**
+ * dump an atomic value to an obstack
*/
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;
+ ir_type *type, *element_type;
+ ir_mode *mode;
+ int i, c, n;
- ty = get_entity_type(ent);
+ type = get_entity_type(ent);
/* if it's an array */
- if (is_Array_type(ty)) {
- ir_type *elm_ty = get_array_element_type(ty);
-
- /* and the array's element type is primitive */
- if (is_Primitive_type(elm_ty)) {
- 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
- */
- if (mode_is_int(mode)
- && get_mode_size_bits(mode) == get_mode_size_bits(mode_Bs))
- {
- int i, c, n;
-
- n = get_compound_ent_n_values(ent);
- for (i = 0; i < n; ++i) {
- ir_node *irn = get_compound_ent_value(ent, i);
- if(get_irn_opcode(irn) != iro_Const)
- return 0;
-
- c = (int) get_tarval_long(get_Const_tarval(irn));
-
- if((i < n - 1 && !(isgraph(c) || isspace(c)))
- || (i == n - 1 && c != '\0'))
- return 0;
- }
-
- res = 1;
- }
- }
+ if (!is_Array_type(type))
+ return 0;
+
+ element_type = get_array_element_type(type);
+
+ /* and the array's element type is primitive */
+ if (!is_Primitive_type(element_type))
+ return 0;
+
+ /* and the mode of the element type is an int of
+ * the same size as the byte mode */
+ mode = get_type_mode(element_type);
+ if (!mode_is_int(mode)
+ || get_mode_size_bits(mode) != get_mode_size_bits(mode_Bs))
+ return 0;
+
+ /* if it contains only printable chars and a 0 at the end */
+ n = get_compound_ent_n_values(ent);
+ for (i = 0; i < n; ++i) {
+ ir_node *irn = get_compound_ent_value(ent, i);
+ if(get_irn_opcode(irn) != iro_Const)
+ return 0;
+
+ c = (int) get_tarval_long(get_Const_tarval(irn));
+
+ if((i < n - 1 && !(isgraph(c) || isspace(c)))
+ || (i == n - 1 && c != '\0'))
+ return 0;
}
- return res;
+ /* then we can emit it as a string constant */
+ return 1;
}
/**
- * 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;
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;
/* 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)) {
} 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 field 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));
- res = compute_compound_ent_array_indices(ent);
- if(!res) {
- panic("Couldn't emit initializer for entity '%s'\n", get_entity_ld_name(ent));
+ offset += (value_len + bits_remainder + 7) >> 3;
+
+ 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 && value_len != 16 && value_len != 32 && value_len != 64)) {
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));
}
+ tv = tarval_convert_to(tv, mode_Lu);
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; 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);
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;
}
/* 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) {
- dump_atomic_init(obst, vals[i].v.value);
- skip = get_mode_size_bytes(get_irn_mode(vals[i].v.value)) - 1;
- } else {
- space = 1;
- }
+ if(vals[i].v.value != NULL) {
+ dump_atomic_init(obst, vals[i].v.value);
+ skip = get_mode_size_bytes(get_irn_mode(vals[i].v.value)) - 1;
+ } else {
+ space = 1;
+ }
} else {
+ assert(vals[i].kind == BITFIELD);
obstack_printf(obst, "\t.byte\t%d\n", vals[i].v.bf_val);
}
++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;
}
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);
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;
}
be_dbg_variable(env->main_env->db_handle, obst, ent);
/* global or not global */
- if(visibility == visibility_external_visible) {
+ if(visibility == visibility_external_visible
+ && variability != variability_uninitialized) {
obstack_printf(obst, ".global\t%s\n", ld_name);
} else if(visibility == visibility_external_allocated) {
obstack_printf(obst, ".global\t%s\n", ld_name);
return;
}
/* alignment */
- if(align > 1) {
+ if(align > 1 && variability != variability_uninitialized) {
obstack_printf(obst, ".balign\t%d\n", align);
}
- obstack_printf(obst, "%s:\n", ld_name);
-
- if(variability == variability_uninitialized) {
- obstack_printf(obst, "\t.zero %d\n", get_type_size_bytes(type));
- return;
+ if(variability != variability_uninitialized) {
+ obstack_printf(obst, "%s:\n", ld_name);
}
- if (is_atomic_type(type)) {
+ if (variability == variability_uninitialized) {
+ obstack_printf(obst, "\t.comm %s,%d,%d\n",
+ ld_name, get_type_size_bytes(type), align);
+ } 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");
}
/**
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);
}
}