X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbegnuas.c;h=63a34b0faaa962cf04056c99f0f8fc8c883c0033;hb=5474a1c188c9d59eea2c915515980cd9cbab58d8;hp=c51f6d4dc474a84f0abec2b1e4a65193fb87ee16;hpb=fc1f5076debb6225fa652f6c28758350a7b5449d;p=libfirm diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c index c51f6d4dc..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" @@ -529,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 @@ -597,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(); } /** @@ -1539,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; @@ -1553,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 { @@ -1577,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 @@ -1711,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)