- unfinished work to support exception label lookup
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 12 Jun 2008 01:38:48 +0000 (01:38 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 12 Jun 2008 01:38:48 +0000 (01:38 +0000)
[r20072]

ir/be/arm/arm_emitter.c
ir/be/begnuas.c
ir/be/begnuas.h
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_emitter.h
ir/be/ia32/ia32_new_nodes.c
ir/be/ia32/ia32_new_nodes.h
ir/be/ia32/ia32_nodes_attr.h
ir/be/mips/mips_emitter.c

index 14b3fd5..d9eec02 100644 (file)
@@ -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);
index fc8dc4a..3d9ff99 100644 (file)
@@ -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);
 }
 
 /**
index 15b461f..7ca65e6 100644 (file)
@@ -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
index 87cc8d9..ff1052c 100644 (file)
@@ -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)
index ac4b18f..c764c1d 100644 (file)
@@ -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
index 1d98893..d741aef 100644 (file)
@@ -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
index f3335f8..44758a2 100644 (file)
@@ -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
 
 /**
index 6b854f1..199af9a 100644 (file)
@@ -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 */
index fe355ad..bcd4f4d 100644 (file)
@@ -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);