-static void emit_compound_graph_init(be_gas_decl_env_t *env,
- const ir_entity *ent)
-{
- normal_or_bitfield *vals;
- int i, j, n;
- unsigned k, last_ofs;
-
- if (entity_is_string_const(ent)) {
- emit_string_cst(ent);
- return;
- }
-
- n = get_compound_ent_n_values(ent);
-
- /* 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 = get_type_size_bytes(get_entity_type(ent));
- for (i = 0; i < n; ++i) {
- unsigned offset = get_compound_ent_value_offset_bytes(ent, i);
- unsigned bits_remainder = get_compound_ent_value_offset_bit_remainder(ent, i);
- ir_node *value = get_compound_ent_value(ent, i);
- unsigned value_len = get_mode_size_bits(get_irn_mode(value));
-
- offset += (value_len + bits_remainder + 7) >> 3;
-
- if (offset > last_ofs) {
- last_ofs = offset;
- }
- }
-
- /*
- * In the worst case, every initializer allocates one byte.
- * Moreover, initializer might be big, do not allocate on stack.
- */
- vals = XMALLOCNZ(normal_or_bitfield, last_ofs);
-
- /* collect the values and store them at the offsets */
- for (i = 0; i < n; ++i) {
- unsigned 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);
- int value_len = get_mode_size_bits(get_irn_mode(value));
-
- assert(offset_bits >= 0);
-
- if (offset_bits != 0 ||
- (value_len != 8 && value_len != 16 && value_len != 32 && value_len != 64)) {
- ir_tarval *tv = get_atomic_init_tv(value);
- unsigned char curr_bits, last_bits = 0;
- if (tv == NULL) {
- panic("Couldn't get numeric value for bitfield initializer '%s'",
- get_entity_ld_name(ent));
- }
- /* normalize offset */
- offset += offset_bits >> 3;
- offset_bits &= 7;
-
- for (j = 0; value_len + offset_bits > 0; ++j) {
- assert(offset + j < last_ofs);
- assert(vals[offset + j].kind == BITFIELD || vals[offset + j].v.value == NULL);
- vals[offset + j].kind = BITFIELD;
- curr_bits = get_tarval_sub_bits(tv, j);
- vals[offset + j].v.bf_val |= (last_bits >> (8 - offset_bits)) | (curr_bits << offset_bits);
- value_len -= 8;
- last_bits = curr_bits;
- }
- } else {
- int i;
-
- assert(offset < last_ofs);
- assert(vals[offset].kind == NORMAL);
- for (i = 1; i < value_len / 8; ++i) {
- assert(vals[offset + i].v.value == NULL);
- }
- vals[offset].v.value = value;
- }
- }
-
- /* now write them sorted */
- for (k = 0; k < last_ofs; ) {
- int space = 0, skip = 0;
- if (vals[k].kind == NORMAL) {
- if (vals[k].v.value != NULL) {
- emit_node_data(env, vals[k].v.value, vals[k].type);
- skip = get_mode_size_bytes(get_irn_mode(vals[k].v.value)) - 1;
- } else {
- space = 1;
- }
- } else {
- assert(vals[k].kind == BITFIELD);
- be_emit_irprintf("\t.byte\t%d\n", vals[k].v.bf_val);
- }
-
- ++k;
- while (k < last_ofs && vals[k].kind == NORMAL && vals[k].v.value == NULL) {
- ++space;
- ++k;
- }
- space -= skip;
- assert(space >= 0);
-
- /* a gap */
- if (space > 0) {
- be_emit_irprintf("\t.space\t%d, 0\n", space);
- be_emit_write_line();
- }
- }
- xfree(vals);
-}
-