X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbegnuas.c;h=c2b87bf197f4f531369b888790d00f2ac95be19a;hb=bd31a5350ce9e110c058b4ad2223d460c9eb5c4e;hp=501499b832d9bfa9d0509f7002ff736da0ffd4f5;hpb=06746a3efddc51571046cafdff94392f5fa98ed2;p=libfirm diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c index 501499b83..c2b87bf19 100644 --- a/ir/be/begnuas.c +++ b/ir/be/begnuas.c @@ -38,7 +38,6 @@ #include "obst.h" #include "tv.h" #include "irnode.h" -#include "entity.h" #include "irprog.h" #include "pdeq.h" #include "error.h" @@ -80,8 +79,8 @@ static const char *get_section_name(be_gas_section_t section) { } }; - assert(be_gas_flavour >= 0 && be_gas_flavour < GAS_FLAVOUR_MAX); - assert(section >= 0 && section < GAS_SECTION_MAX); + assert((int) be_gas_flavour >= 0 && be_gas_flavour < GAS_FLAVOUR_MAX); + assert((int) section >= 0 && section < GAS_SECTION_MAX); return text[be_gas_flavour][section]; } @@ -91,11 +90,11 @@ static const char *get_section_name(be_gas_section_t section) { * @param env the emitter environment * @param section the section to switch to */ -void be_gas_emit_switch_section(be_emit_env_t *env, be_gas_section_t section) { - be_emit_char(env, '\t'); - be_emit_string(env, get_section_name(section)); - be_emit_char(env, '\n'); - be_emit_write_line(env); +void be_gas_emit_switch_section(be_gas_section_t section) { + be_emit_char('\t'); + be_emit_string(get_section_name(section)); + be_emit_char('\n'); + be_emit_write_line(); } /** @@ -169,10 +168,24 @@ static void dump_arith_tarval(obstack_t *obst, tarval *tv, int bytes) } } +/** + * Return the label prefix for labeled blocks. + */ +const char *be_gas_label_prefix(void) { + return ".LG"; +} + +/** + * Dump a label. + */ +static void dump_label(obstack_t *obst, ir_label_t label) { + obstack_printf(obst, "%s%ld", be_gas_label_prefix(), label); +} + /** * Return the tarval of an atomic initializer. * - * @param init a node representing the initializer (on teh const code irg) + * @param init a node representing the initializer (on the const code irg) * * @return the tarval */ @@ -208,6 +221,9 @@ static tarval *get_atomic_init_tv(ir_node *init) case symconst_enum_const: return get_enumeration_value(get_SymConst_enum(init)); + case symconst_label: + return NULL; + default: return NULL; } @@ -231,6 +247,7 @@ static void do_dump_atomic_init(be_gas_decl_env_t *env, obstack_t *obst, ir_mode *mode = get_irn_mode(init); int bytes = get_mode_size_bytes(mode); tarval *tv; + ir_label_t label; ir_entity *ent; switch (get_irn_opcode(init)) { @@ -258,9 +275,9 @@ static void do_dump_atomic_init(be_gas_decl_env_t *env, obstack_t *obst, case symconst_addr_ent: ent = get_SymConst_entity(init); - if(!entity_visited(ent)) { + if(!is_entity_backend_marked(ent)) { waitq_put(env->worklist, ent); - mark_entity_visited(ent); + set_entity_backend_marked(ent, 1); } obstack_printf(obst, "%s", get_entity_ld_name(ent)); break; @@ -268,9 +285,9 @@ static void do_dump_atomic_init(be_gas_decl_env_t *env, obstack_t *obst, case symconst_ofs_ent: ent = get_SymConst_entity(init); #if 0 /* not needed, is it? */ - if(!entity_visited(ent)) { + if(!is_entity_backend_marked(ent)) { waitq_put(env->worklist, ent); - mark_entity_visited(ent); + set_entity_backend_marked(ent, 1); } #endif obstack_printf(obst, "%d", get_entity_offset(ent)); @@ -289,6 +306,11 @@ static void do_dump_atomic_init(be_gas_decl_env_t *env, obstack_t *obst, dump_arith_tarval(obst, tv, bytes); break; + case symconst_label: + label = get_SymConst_label(init); + dump_label(obst, label); + break; + default: assert(!"dump_atomic_init(): don't know how to init from this SymConst"); } @@ -476,37 +498,6 @@ static void dump_string_cst(obstack_t *obst, ir_entity *ent) } } -static void dump_array_init(be_gas_decl_env_t *env, obstack_t *obst, - ir_entity *ent) -{ - const ir_type *ty = get_entity_type(ent); - int i; - int filler; - int size = 0; - - /* potential spare values should be already included! */ - for (i = 0; i < get_compound_ent_n_values(ent); ++i) { - ir_entity *step = get_compound_ent_value_member(ent, i); - ir_type *stype = get_entity_type(step); - - if (get_type_mode(stype)) { - int align = (get_type_alignment_bits(stype) + 7) >> 3; - int n = size % align; - - if (n > 0) { - obstack_printf(obst, "\t.zero\t%d\n", align - n); - size += align - n; - } - } - dump_atomic_init(env, obst, get_compound_ent_value(ent, i)); - size += get_type_size_bytes(stype); - } - filler = get_type_size_bytes(ty) - size; - - if (filler > 0) - obstack_printf(obst, "\t.skip\t%d\n", filler); -} - enum normal_or_bitfield_kind { NORMAL = 0, BITFIELD @@ -569,32 +560,33 @@ static void dump_compound_init(be_gas_decl_env_t *env, obstack_t *obst, 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); + unsigned char curr_bits, last_bits = 0; 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) { - panic("Couldn't shift numeric value for bitfield initializer '%s'\n", - get_entity_ld_name(ent)); - } + /* normalize offset */ + offset += offset_bits >> 3; + offset_bits &= 7; - for (j = 0; value_len > 0; ++j) { + 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; - vals[offset + j].v.bf_val |= get_tarval_sub_bits(shifted, j); - value_len -= 8 - offset_bits; - offset_bits = 0; + 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); - assert(vals[offset].v.value == NULL); + for (i = 1; i < value_len / 8; ++i) { + assert(vals[offset + i].v.value == NULL); + } vals[offset].v.value = value; } } @@ -615,7 +607,6 @@ static void dump_compound_init(be_gas_decl_env_t *env, obstack_t *obst, } ++i; - space = 0; while (i < last_ofs && vals[i].kind == NORMAL && vals[i].v.value == NULL) { ++space; ++i; @@ -642,10 +633,10 @@ static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons obstack_t *obst; ir_type *type = get_entity_type(ent); const char *ld_name = get_entity_ld_name(ent); - ir_variability variability = get_entity_variability(ent); - ir_visibility visibility = get_entity_visibility(ent); int align = get_type_alignment_bytes(type); int emit_as_common = 0; + ir_variability variability; + ir_visibility visibility; obst = env->data_obst; if (is_Method_type(type)) { @@ -656,13 +647,17 @@ static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons obstack_printf(obst, "%s\n", ld_name); } return; - } else if (variability == variability_constant) { + } + + variability = get_entity_variability(ent); + visibility = get_entity_visibility(ent); + if (variability == variability_constant) { /* a constant entity, put it on the rdata */ obst = env->rodata_obst; } else if (variability == variability_uninitialized) { /* uninitialized entity put it in bss segment */ obst = env->bss_obst; - if(emit_commons && visibility != visibility_local) + if (emit_commons && visibility != visibility_local) emit_as_common = 1; } @@ -696,16 +691,28 @@ static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons } else { obstack_printf(obst, "\t.zero %d\n", get_type_size_bytes(type)); } - } else if (is_atomic_type(type)) { - dump_atomic_init(env, obst, get_atomic_ent_value(ent)); - } else if (ent_is_string_const(ent)) { - dump_string_cst(obst, ent); - } else if (is_Array_type(type)) { - dump_array_init(env, obst, ent); - } else if (is_compound_type(type)) { - dump_compound_init(env, obst, ent); } else { - assert(0 && "unsupported type"); + if (is_atomic_entity(ent)) { + dump_atomic_init(env, obst, get_atomic_ent_value(ent)); + } else { + /* sort_compound_ent_values(ent); */ + + switch (get_type_tpop_code(get_entity_type(ent))) { + case tpo_array: + if (ent_is_string_const(ent)) + dump_string_cst(obst, ent); + else + dump_compound_init(env, obst, ent); + break; + case tpo_struct: + case tpo_class: + case tpo_union: + dump_compound_init(env, obst, ent); + break; + default: + assert(0); + } + } } } @@ -724,27 +731,26 @@ static void be_gas_dump_globals(ir_type *gt, be_gas_decl_env_t *env, int i, n = get_compound_n_members(gt); waitq *worklist = new_waitq(); - if(only_emit_marked) { + if (only_emit_marked) { for (i = 0; i < n; i++) { ir_entity *ent = get_compound_member(gt, i); - if(entity_visited(ent) || - get_entity_visibility(ent) != visibility_external_allocated) { + if (is_entity_backend_marked(ent) || + get_entity_visibility(ent) != visibility_external_allocated) { waitq_put(worklist, ent); - mark_entity_visited(ent); + set_entity_backend_marked(ent, 1); } } } else { - inc_master_type_visited(); for (i = 0; i < n; i++) { ir_entity *ent = get_compound_member(gt, i); - mark_entity_visited(ent); + set_entity_backend_marked(ent, 1); waitq_put(worklist, ent); } } env->worklist = worklist; - while(!waitq_empty(worklist)) { + while (!waitq_empty(worklist)) { ir_entity *ent = waitq_get(worklist); dump_global(env, ent, emit_commons); @@ -757,13 +763,16 @@ static void be_gas_dump_globals(ir_type *gt, be_gas_decl_env_t *env, /************************************************************************/ /* Generate all entities. */ -void be_gas_emit_decls(be_emit_env_t *emit, const be_main_env_t *main_env, +void be_gas_emit_decls(const be_main_env_t *main_env, int only_emit_marked_entities) { be_gas_decl_env_t env; - obstack_t rodata, data, bss, ctor; - int size; - char *cp; + obstack_t rodata; + obstack_t data; + obstack_t bss; + obstack_t ctor; + int size; + char *cp; /* dump the global type */ obstack_init(&rodata); @@ -782,33 +791,33 @@ void be_gas_emit_decls(be_emit_env_t *emit, const be_main_env_t *main_env, size = obstack_object_size(&data); cp = obstack_finish(&data); if (size > 0) { - be_gas_emit_switch_section(emit, GAS_SECTION_DATA); - be_emit_string_len(emit, cp, size); - be_emit_write_line(emit); + be_gas_emit_switch_section(GAS_SECTION_DATA); + be_emit_string_len(cp, size); + be_emit_write_line(); } size = obstack_object_size(&rodata); cp = obstack_finish(&rodata); if (size > 0) { - be_gas_emit_switch_section(emit, GAS_SECTION_RODATA); - be_emit_string_len(emit, cp, size); - be_emit_write_line(emit); + be_gas_emit_switch_section(GAS_SECTION_RODATA); + be_emit_string_len(cp, size); + be_emit_write_line(); } size = obstack_object_size(&bss); cp = obstack_finish(&bss); if (size > 0) { - be_gas_emit_switch_section(emit, GAS_SECTION_COMMON); - be_emit_string_len(emit, cp, size); - be_emit_write_line(emit); + be_gas_emit_switch_section(GAS_SECTION_COMMON); + be_emit_string_len(cp, size); + be_emit_write_line(); } size = obstack_object_size(&ctor); cp = obstack_finish(&ctor); if (size > 0) { - be_gas_emit_switch_section(emit, GAS_SECTION_CTOR); - be_emit_string_len(emit, cp, size); - be_emit_write_line(emit); + be_gas_emit_switch_section(GAS_SECTION_CTOR); + be_emit_string_len(cp, size); + be_emit_write_line(); } obstack_free(&rodata, NULL); @@ -829,11 +838,11 @@ void be_gas_emit_decls(be_emit_env_t *emit, const be_main_env_t *main_env, size = obstack_object_size(&data); cp = obstack_finish(&data); if (size > 0) { - be_gas_emit_switch_section(emit, GAS_SECTION_TLS); - be_emit_cstring(emit, ".balign\t32\n"); - be_emit_write_line(emit); - be_emit_string_len(emit, cp, size); - be_emit_write_line(emit); + be_gas_emit_switch_section(GAS_SECTION_TLS); + be_emit_cstring(".balign\t32\n"); + be_emit_write_line(); + be_emit_string_len(cp, size); + be_emit_write_line(); } obstack_free(&data, NULL);