X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbegnuas.c;h=63a34b0faaa962cf04056c99f0f8fc8c883c0033;hb=5474a1c188c9d59eea2c915515980cd9cbab58d8;hp=0946e506f3ed62edd67caa4fabda2ac8a2161acf;hpb=e3b765fcef0e337f4fe2e17d57d2fbaf1912ec79;p=libfirm diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c index 0946e506f..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)) @@ -157,11 +172,25 @@ static void emit_section(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 type[] = { - "progbits", "progbits", "progbits", "nobits", "progbits", "progbits" + const char *f; + static const struct { + const char *name; + const char *type; + const char *flags; + } 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) { @@ -200,12 +229,12 @@ static void emit_section(be_gas_section_t section, const ir_entity *entity) } } - assert(base < (be_gas_section_t) ARRAY_SIZE(basename)); + assert(base < (be_gas_section_t) ARRAY_SIZE(sectioninfos)); be_emit_cstring("\t.section\t."); /* section name */ if (flags & GAS_SECTION_FLAG_TLS) be_emit_char('t'); - be_emit_string(basename[base]); + be_emit_string(sectioninfos[base].name); if (flags & GAS_SECTION_FLAG_COMDAT) { be_emit_char('.'); be_gas_emit_entity(entity); @@ -213,21 +242,19 @@ static void emit_section(be_gas_section_t section, const ir_entity *entity) /* section flags */ be_emit_cstring(",\""); - if (be_gas_object_file_format != OBJECT_FILE_FORMAT_COFF) - be_emit_char('a'); - if (base == GAS_SECTION_TEXT) - be_emit_char('x'); - if (base != GAS_SECTION_RODATA && base != GAS_SECTION_TEXT) - be_emit_char('w'); + for (f = sectioninfos[base].flags; *f != '\0'; ++f) { + be_emit_char(*f); + } if (flags & GAS_SECTION_FLAG_TLS) be_emit_char('T'); if (flags & GAS_SECTION_FLAG_COMDAT) be_emit_char('G'); + /* section type */ if (be_gas_object_file_format != OBJECT_FILE_FORMAT_COFF) { be_emit_cstring("\","); be_emit_char(be_gas_elf_type_char); - be_emit_string(type[base]); + be_emit_string(sectioninfos[base].type); } if (flags & GAS_SECTION_FLAG_COMDAT) { @@ -501,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 @@ -569,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(); } /** @@ -1511,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; @@ -1525,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 { @@ -1549,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 @@ -1654,7 +1690,7 @@ static void be_gas_emit_globals(ir_type *gt, be_gas_decl_env_t *env) } /* Generate all entities. */ -void be_gas_emit_decls(const be_main_env_t *main_env) +static void emit_global_decls(const be_main_env_t *main_env) { be_gas_decl_env_t env; memset(&env, 0, sizeof(env)); @@ -1683,64 +1719,135 @@ void be_gas_emit_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(); } + + if (entity != NULL) + be_gas_emit_switch_section(GAS_SECTION_TEXT); + + xfree(labels); + xfree(targets); +} + +static void emit_global_asms(void) +{ + size_t n = get_irp_n_asms(); + size_t i; + be_gas_emit_switch_section(GAS_SECTION_TEXT); + for (i = 0; i < n; ++i) { + ident *asmtext = get_irp_asm(i); + + be_emit_cstring("#APP\n"); + be_emit_write_line(); + be_emit_ident(asmtext); + be_emit_char('\n'); + be_emit_write_line(); + be_emit_cstring("#NO_APP\n"); + be_emit_write_line(); + } +} + +void be_gas_begin_compilation_unit(const be_main_env_t *env) +{ + be_dbg_open(); + be_dbg_unit_begin(env->cup_name); + be_dbg_types(); + + emit_global_asms(); +} + +void be_gas_end_compilation_unit(const be_main_env_t *env) +{ + emit_global_decls(env); - xfree(table); + be_dbg_unit_end(); + be_dbg_close(); }