From: Michael Beck Date: Thu, 12 Jun 2008 01:38:48 +0000 (+0000) Subject: - unfinished work to support exception label lookup X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=605afb45243e9d7c246760d4f1452dfb575b87d6;p=libfirm - unfinished work to support exception label lookup [r20072] --- diff --git a/ir/be/arm/arm_emitter.c b/ir/be/arm/arm_emitter.c index 14b3fd528..d9eec02da 100644 --- a/ir/be/arm/arm_emitter.c +++ b/ir/be/arm/arm_emitter.c @@ -338,7 +338,7 @@ static ir_node *get_cfop_target_block(const ir_node *irn) { */ static void arm_emit_block_name(const ir_node *block) { if (has_Block_label(block)) { - be_emit_string(be_gas_label_prefix()); + be_emit_string(be_gas_block_label_prefix()); be_emit_irprintf("%lu", get_Block_label(block)); } else { be_emit_cstring(BLOCK_PREFIX); diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c index fc8dc4a54..3d9ff9977 100644 --- a/ir/be/begnuas.c +++ b/ir/be/begnuas.c @@ -271,15 +271,22 @@ static void dump_arith_tarval(tarval *tv, int bytes) /** * Return the label prefix for labeled blocks. */ -const char *be_gas_label_prefix(void) { +const char *be_gas_block_label_prefix(void) { return ".LG"; } +/** + * Return the label prefix for labeled instructions. + */ +const char *be_gas_insn_label_prefix(void) { + return ".LE"; +} + /** * Dump a label. */ static void dump_label(ir_label_t label) { - be_emit_irprintf("%s%ld", be_gas_label_prefix(), label); + be_emit_irprintf("%s%u", be_gas_block_label_prefix(), label); } /** diff --git a/ir/be/begnuas.h b/ir/be/begnuas.h index 15b461f2f..7ca65e6e7 100644 --- a/ir/be/begnuas.h +++ b/ir/be/begnuas.h @@ -87,6 +87,11 @@ void be_gas_emit_function_epilog(ir_entity *entity); /** * Return the label prefix for labeled blocks. */ -const char *be_gas_label_prefix(void); +const char *be_gas_block_label_prefix(void); + +/** + * Return the label prefix for labeled instructions. + */ +const char *be_gas_insn_label_prefix(void); #endif diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 87cc8d975..ff1052c6e 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -73,6 +73,7 @@ static const ia32_isa_t *isa; static ia32_code_gen_t *cg; static int do_pic; static char pic_base_label[128]; +static ir_label_t exc_label_id; /** * Returns the register at in position pos. @@ -734,14 +735,23 @@ static ir_node *get_cfop_target_block(const ir_node *irn) { static void ia32_emit_block_name(const ir_node *block) { if (has_Block_label(block)) { - be_emit_string(be_gas_label_prefix()); - be_emit_irprintf("%u", (unsigned)get_Block_label(block)); + be_emit_string(be_gas_block_label_prefix()); + be_emit_irprintf("%u", get_Block_label(block)); } else { be_emit_cstring(BLOCK_PREFIX); be_emit_irprintf("%d", get_irn_node_nr(block)); } } +/** + * Emits an exception label for a given node. + */ +static void ia32_emit_exc_label(const ir_node *node) +{ + be_emit_string(be_gas_insn_label_prefix()); + be_emit_irprintf("%u", get_ia32_exc_label_id(node)); +} + /** * Emits the target label for a control flow node. */ @@ -1899,6 +1909,10 @@ static void ia32_emit_node(const ir_node *node) DBG((dbg, LEVEL_1, "emitting code for %+F\n", node)); + if (is_ia32_irn(node) && get_ia32_exc_label(node)) { + /* emit the exception label of this instruction */ + ia32_assign_exc_label(node); + } if (op->ops.generic) { emit_func_ptr func = (emit_func_ptr) op->ops.generic; @@ -2091,33 +2105,69 @@ static void ia32_gen_block(ir_node *block, ir_node *last_block) } } +typedef struct exc_entry { + ir_node *exc_instr; /** The instruction that can issue an exception. */ + ir_node *block; /** The block to call then. */ +} exc_entry; + /** * Block-walker: - * Sets labels for control flow nodes (jump target) + * Sets labels for control flow nodes (jump target). + * Links control predecessors to there destination blocks. */ static void ia32_gen_labels(ir_node *block, void *data) { + exc_entry **exc_list = data; ir_node *pred; - int n = get_Block_n_cfgpreds(block); - (void) data; + int n; - for (n--; n >= 0; n--) { + for (n = get_Block_n_cfgpreds(block) - 1; n >= 0; --n) { pred = get_Block_cfgpred(block, n); set_irn_link(pred, block); + + pred = skip_Proj(pred); + if (is_ia32_irn(pred) && get_ia32_exc_label(pred)) { + exc_entry e; + + e.exc_instr = pred; + e.block = block; + ARR_APP1(exc_entry, *exc_list, e); + set_irn_link(pred, block); + } } } /** * Emit an exception label if the current instruction can fail. */ -void ia32_emit_exc_label(const ir_node *node) +void ia32_assign_exc_label(const ir_node *node) { if (get_ia32_exc_label(node)) { - be_emit_irprintf(".EXL%u\n", 0); + /* assign a new ID to the instruction */ + set_ia32_exc_label_id(node, ++exc_label_id); + /* print it */ + ia32_emit_exc_label(node); + be_emit_char(':'); + be_emit_pad_comment(); + be_emit_cstring("/* exception to Block "); + ia32_emit_cfop_target(node); + be_emit_cstring(" */\n"); be_emit_write_line(); } } +/** + * Compare two exception_entries. + */ +static int cmp_exc_entry(const void *a, const void *b) { + const exc_entry *ea = a; + const exc_entry *eb = b; + + if (get_ia32_exc_label_id(ea->exc_instr) < get_ia32_exc_label_id(eb->exc_instr)) + return -1; + return +1; +} + /** * Main driver. Emits the code for one routine. */ @@ -2126,6 +2176,7 @@ void ia32_gen_routine(ia32_code_gen_t *ia32_cg, ir_graph *irg) ir_node *block; ir_node *last_block = NULL; ir_entity *entity = get_irg_entity(irg); + exc_entry *exc_list = NEW_ARR_F(exc_entry, 0); int i, n; cg = ia32_cg; @@ -2140,7 +2191,9 @@ void ia32_gen_routine(ia32_code_gen_t *ia32_cg, ir_graph *irg) be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi)); be_gas_emit_function_prolog(entity, ia32_cg_config.function_alignment); - irg_block_walk_graph(irg, ia32_gen_labels, NULL, NULL); + /* we use links to point to target blocks */ + set_using_irn_link(irg); + irg_block_walk_graph(irg, ia32_gen_labels, NULL, &exc_list); n = ARR_LEN(cg->blk_sched); for (i = 0; i < n;) { @@ -2160,6 +2213,25 @@ void ia32_gen_routine(ia32_code_gen_t *ia32_cg, ir_graph *irg) be_dbg_method_end(); be_emit_char('\n'); be_emit_write_line(); + + clear_using_irn_link(irg); + + /* Sort the exception table using the exception label id's. + Those are ascending with ascending addresses. */ + qsort(exc_list, ARR_LEN(exc_list), sizeof(exc_list[0]), cmp_exc_entry); + { + int i; + + for (i = 0; i < ARR_LEN(exc_list); ++i) { + be_emit_cstring("\t.long "); + ia32_emit_exc_label(exc_list[i].exc_instr); + be_emit_char('\n'); + be_emit_cstring("\t.long "); + ia32_emit_block_name(exc_list[i].block); + be_emit_char('\n'); + } + } + DEL_ARR_F(exc_list); } void ia32_init_emitter(void) diff --git a/ir/be/ia32/ia32_emitter.h b/ir/be/ia32/ia32_emitter.h index ac4b18f7e..c764c1d15 100644 --- a/ir/be/ia32/ia32_emitter.h +++ b/ir/be/ia32/ia32_emitter.h @@ -50,6 +50,6 @@ void ia32_emit_am(const ir_node *node); void ia32_emit_x87_binop(const ir_node *node); void ia32_gen_routine(ia32_code_gen_t *cg, ir_graph *irg); -void ia32_emit_exc_label(const ir_node *node); +void ia32_assign_exc_label(const ir_node *node); #endif diff --git a/ir/be/ia32/ia32_new_nodes.c b/ir/be/ia32/ia32_new_nodes.c index 1d98893f3..d741aef3f 100644 --- a/ir/be/ia32/ia32_new_nodes.c +++ b/ir/be/ia32/ia32_new_nodes.c @@ -864,7 +864,7 @@ const be_execution_unit_t ***get_ia32_exec_units(const ir_node *node) { */ unsigned get_ia32_exc_label(const ir_node *node) { const ia32_attr_t *attr = get_ia32_attr_const(node); - return attr->data.except_label; + return attr->data.has_except_label; } /** @@ -872,7 +872,27 @@ unsigned get_ia32_exc_label(const ir_node *node) { */ void set_ia32_exc_label(ir_node *node, unsigned flag) { ia32_attr_t *attr = get_ia32_attr(node); - attr->data.except_label = flag; + attr->data.has_except_label = flag; +} + +/** + * Return the exception label id. + */ +ir_label_t get_ia32_exc_label_id(const ir_node *node) { + const ia32_attr_t *attr = get_ia32_attr_const(node); + + assert(attr->data.has_except_label); + return attr->exc_label; +} + +/** + * Assign the exception label id. + */ +void set_ia32_exc_label_id(ir_node *node, ir_label_t id) { + ia32_attr_t *attr = get_ia32_attr(node); + + assert(attr->data.has_except_label); + attr->exc_label = id; } #ifndef NDEBUG @@ -1130,7 +1150,7 @@ int ia32_compare_attr(const ia32_attr_t *a, const ia32_attr_t *b) { if (a->data.tp != b->data.tp) return 1; - if (a->data.except_label != b->data.except_label) + if (a->data.has_except_label != b->data.has_except_label) return 1; if (a->data.ins_permuted != b->data.ins_permuted diff --git a/ir/be/ia32/ia32_new_nodes.h b/ir/be/ia32/ia32_new_nodes.h index f3335f8a0..44758a2c4 100644 --- a/ir/be/ia32/ia32_new_nodes.h +++ b/ir/be/ia32/ia32_new_nodes.h @@ -355,6 +355,16 @@ unsigned get_ia32_exc_label(const ir_node *node); */ void set_ia32_exc_label(ir_node *node, unsigned flag); +/** + * Return the exception label id. + */ +ir_label_t get_ia32_exc_label_id(const ir_node *node); + +/** + * Assign the exception label id. + */ +void set_ia32_exc_label_id(ir_node *node, ir_label_t id); + #ifndef NDEBUG /** diff --git a/ir/be/ia32/ia32_nodes_attr.h b/ir/be/ia32/ia32_nodes_attr.h index 6b854f15e..199af9a8c 100644 --- a/ir/be/ia32/ia32_nodes_attr.h +++ b/ir/be/ia32/ia32_nodes_attr.h @@ -107,7 +107,7 @@ struct ia32_attr_t { unsigned am_sc_sign:1; /**< The sign bit of the address mode symconst. */ unsigned use_frame:1; /**< Indicates whether the operation uses the frame pointer or not. */ - unsigned except_label:1; /**< Set if this node needs a label because of possible exception. */ + unsigned has_except_label:1; /**< Set if this node needs a label because of possible exception. */ unsigned is_commutative:1; /**< Indicates whether op is commutative or not. */ @@ -136,6 +136,8 @@ struct ia32_attr_t { const arch_register_t **slots; /**< register slots for assigned registers */ + ir_label_t exc_label; /**< the exception label iff this instruction can throw an exception */ + #ifndef NDEBUG const char *orig_node; /**< holds the name of the original ir node */ unsigned attr_type; /**< bitfield indicating the attribute type */ diff --git a/ir/be/mips/mips_emitter.c b/ir/be/mips/mips_emitter.c index fe355adb0..bcd4f4d23 100644 --- a/ir/be/mips/mips_emitter.c +++ b/ir/be/mips/mips_emitter.c @@ -432,7 +432,7 @@ const char* mips_get_block_label(const ir_node* block) static void mips_emit_block_label(const ir_node *block) { if (has_Block_label(block)) { - be_emit_string(be_gas_label_prefix()); + be_emit_string(be_gas_block_label_prefix()); be_emit_irprintf("%lu", get_Block_label(block)); } else { be_emit_cstring(BLOCK_PREFIX);