X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbegnuas.c;h=63a34b0faaa962cf04056c99f0f8fc8c883c0033;hb=5474a1c188c9d59eea2c915515980cd9cbab58d8;hp=03d3c91faab3dccde84caff6d6513b951b7fd8d9;hpb=f19e702def23bd76d2e770f0f981f876864bb69b;p=libfirm diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c index 03d3c91fa..63a34b0fa 100644 --- a/ir/be/begnuas.c +++ b/ir/be/begnuas.c @@ -22,7 +22,6 @@ * @brief Dumps global variables and constants as gas assembler. * @author Christian Wuerdig, Matthias Braun * @date 04.11.2005 - * @version $Id$ */ #include "config.h" @@ -86,6 +85,10 @@ static void emit_section_macho(be_gas_section_t section) case GAS_SECTION_PIC_TRAMPOLINES: name = "section\t__IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5"; break; case GAS_SECTION_PIC_SYMBOLS: name = "section\t__IMPORT,__pointers,non_lazy_symbol_pointers"; break; case GAS_SECTION_CSTRING: name = "cstring"; break; + case GAS_SECTION_DEBUG_INFO: name = "section __DWARF,__debug_info,regular,debug"; break; + case GAS_SECTION_DEBUG_ABBREV: name = "section __DWARF,__debug_abbrev,regular,debug"; break; + case GAS_SECTION_DEBUG_LINE: name = "section __DWARF,__debug_line,regular,debug"; break; + case GAS_SECTION_DEBUG_PUBNAMES: name = "section __DWARF,__debug_pubnames,regular,debug"; break; default: panic("unsupported scetion type 0x%X", section); } be_emit_irprintf("\t.%s\n", name); @@ -108,8 +111,20 @@ static void emit_section_sparc(be_gas_section_t section, const ir_entity *entity { be_gas_section_t base = section & GAS_SECTION_TYPE_MASK; be_gas_section_t flags = section & ~GAS_SECTION_TYPE_MASK; - static const char *const basename[] = { - "text", "data", "rodata", "bss", "ctors", "dtors" + static const char *const basename[GAS_SECTION_LAST+1] = { + "text", + "data", + "rodata", + "bss", + "ctors", + "dtors", + NULL, /* cstring */ + NULL, /* pic trampolines */ + NULL, /* pic symbols */ + "debug_info", + "debug_abbrev", + "debug_line", + "debug_pubnames" }; if (current_section == section && !(section & GAS_SECTION_FLAG_COMDAT)) @@ -162,19 +177,20 @@ static void emit_section(be_gas_section_t section, const ir_entity *entity) const char *name; const char *type; const char *flags; - } sectioninfos[] = { - { "text", "progbits", "ax" }, - { "data", "progbits", "aw" }, - { "rodata", "progbits", "a" }, - { "bss", "nobits", "aw" }, - { "ctors", "progbits", "aw" }, - { "dtors", "progbits", "aw" }, - { NULL, NULL, NULL }, /* cstring */ - { NULL, NULL, NULL }, /* pic trampolines */ - { NULL, NULL, NULL }, /* pic symbols */ - { "debug_info", "progbits", "" }, - { "debug_abbrev", "progbits", "" }, - { "debug_line", "progbits", "" }, + } sectioninfos[GAS_SECTION_LAST+1] = { + { "text", "progbits", "ax" }, + { "data", "progbits", "aw" }, + { "rodata", "progbits", "a" }, + { "bss", "nobits", "aw" }, + { "ctors", "progbits", "aw" }, + { "dtors", "progbits", "aw" }, + { NULL, NULL, NULL }, /* cstring */ + { NULL, NULL, NULL }, /* pic trampolines */ + { NULL, NULL, NULL }, /* pic symbols */ + { "debug_info", "progbits", "" }, + { "debug_abbrev", "progbits", "" }, + { "debug_line", "progbits", "" }, + { "debug_pubnames", "progbits", "" }, }; if (be_gas_object_file_format == OBJECT_FILE_FORMAT_MACH_O) { @@ -512,7 +528,11 @@ static void emit_visibility(const ir_entity *entity) void be_gas_emit_function_prolog(const ir_entity *entity, unsigned po2alignment) { - be_gas_section_t section = determine_section(NULL, entity); + be_gas_section_t section; + + be_dbg_method_begin(entity); + + section = determine_section(NULL, entity); emit_section(section, entity); /* write the begin line (makes the life easier for scripts parsing the @@ -580,6 +600,11 @@ void be_gas_emit_function_epilog(const ir_entity *entity) be_gas_emit_entity(entity); be_emit_char('\n'); be_emit_write_line(); + + be_dbg_method_end(); + + be_emit_char('\n'); + be_emit_write_line(); } /** @@ -1522,7 +1547,7 @@ char const *be_gas_get_private_prefix(void) void be_gas_emit_entity(const ir_entity *entity) { - if (entity->type == firm_code_type) { + if (entity->type == get_code_type()) { ir_label_t label = get_entity_label(entity); be_emit_irprintf("%s_%lu", be_gas_get_private_prefix(), label); return; @@ -1536,7 +1561,7 @@ void be_gas_emit_entity(const ir_entity *entity) void be_gas_emit_block_name(const ir_node *block) { - if (has_Block_entity(block)) { + if (get_Block_entity(block) != NULL) { ir_entity *entity = get_Block_entity(block); be_gas_emit_entity(entity); } else { @@ -1560,7 +1585,7 @@ static void emit_global(be_gas_decl_env_t *env, const ir_entity *entity) ir_linkage linkage = get_entity_linkage(entity); /* block labels are already emittet in the code */ - if (type == firm_code_type) + if (type == get_code_type()) return; /* we already emitted all methods. Except for the trampolines which @@ -1694,66 +1719,101 @@ static void emit_global_decls(const be_main_env_t *main_env) } } -void emit_jump_table(const ir_node *node, long default_pn, ir_entity *entity, - get_cfop_target_func get_cfop_target) +void be_emit_jump_table(const ir_node *node, const ir_switch_table *table, + ir_entity *entity, get_cfop_target_func get_cfop_target) { - long switch_max = LONG_MIN; - ir_node *default_block = NULL; - unsigned long length; - const ir_edge_t *edge; - unsigned i; - ir_node **table; - - /* go over all proj's and collect them */ + unsigned n_outs = arch_get_irn_n_outs(node); + const ir_node **targets = XMALLOCNZ(const ir_node*, n_outs); + size_t n_entries = ir_switch_table_get_n_entries(table); + unsigned long length = 0; + size_t e; + const ir_edge_t *edge; + unsigned i; + const ir_node **labels; + + /* go over all proj's and collect their jump targets */ foreach_out_edge(node, edge) { - ir_node *proj = get_edge_src_irn(edge); - long pn = get_Proj_proj(proj); - - /* check for default proj */ - if (pn == default_pn) { - assert(default_block == NULL); /* more than 1 default_pn? */ - default_block = get_cfop_target(proj); - } else { - switch_max = pn > switch_max ? pn : switch_max; + ir_node *proj = get_edge_src_irn(edge); + long pn = get_Proj_proj(proj); + ir_node *target = get_cfop_target(proj); + assert(targets[pn] == NULL); + targets[pn] = target; + } + + /* go over table to determine max value (note that we normalized the + * ranges so that the minimum is 0) */ + for (e = 0; e < n_entries; ++e) { + const ir_switch_table_entry *entry + = ir_switch_table_get_entry_const(table, e); + ir_tarval *max = entry->max; + unsigned long val; + if (entry->pn == 0) + continue; + if (!tarval_is_long(max)) + panic("switch case overflow (%+F)", node); + val = (unsigned long) get_tarval_long(max); + if (val > length) { + length = val; } } - assert(switch_max > LONG_MIN); - length = (unsigned long) switch_max + 1; /* the 16000 isn't a real limit of the architecture. But should protect us * from seamingly endless compiler runs */ if (length > 16000) { /* switch lowerer should have broken this monster to pieces... */ - panic("too large switch encountered"); + panic("too large switch encountered (%+F)", node); + } + ++length; + + labels = XMALLOCNZ(const ir_node*, length); + for (e = 0; e < n_entries; ++e) { + const ir_switch_table_entry *entry + = ir_switch_table_get_entry_const(table, e); + ir_tarval *min = entry->min; + ir_tarval *max = entry->max; + const ir_node *target = targets[entry->pn]; + assert(entry->pn < (long)n_outs); + if (min == max) { + unsigned long val = (unsigned long)get_tarval_long(max); + labels[val] = target; + } else { + unsigned long min_val; + unsigned long max_val; + unsigned long i; + if (!tarval_is_long(min)) + panic("switch case overflow (%+F)", node); + min_val = (unsigned long)get_tarval_long(min); + max_val = (unsigned long)get_tarval_long(max); + assert(min_val <= max_val); + for (i = min_val; i <= max_val; ++i) { + labels[i] = target; + } + } } - table = XMALLOCNZ(ir_node*, length); - foreach_out_edge(node, edge) { - ir_node *proj = get_edge_src_irn(edge); - long pn = get_Proj_proj(proj); - if (pn == default_pn) - continue; - - table[pn] = get_cfop_target(proj); + /* emit table */ + if (entity != NULL) { + be_gas_emit_switch_section(GAS_SECTION_RODATA); + be_emit_cstring("\t.align 4\n"); + be_gas_emit_entity(entity); + be_emit_cstring(":\n"); } - /* emit table */ - be_gas_emit_switch_section(GAS_SECTION_RODATA); - be_emit_cstring("\t.align 4\n"); - be_gas_emit_entity(entity); - be_emit_cstring(":\n"); for (i = 0; i < length; ++i) { - ir_node *block = table[i]; + const ir_node *block = labels[i]; if (block == NULL) - block = default_block; + block = targets[0]; be_emit_cstring("\t.long "); be_gas_emit_block_name(block); be_emit_char('\n'); be_emit_write_line(); } - be_gas_emit_switch_section(GAS_SECTION_TEXT); - xfree(table); + if (entity != NULL) + be_gas_emit_switch_section(GAS_SECTION_TEXT); + + xfree(labels); + xfree(targets); } static void emit_global_asms(void)