assign esp to special stack node (frame_base Proj)
authorChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Fri, 20 Jan 2006 17:55:44 +0000 (17:55 +0000)
committerChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Fri, 20 Jan 2006 17:55:44 +0000 (17:55 +0000)
check for alloca and use ebp as stack register if found

ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_map_regs.c
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c

index 5be53ce..a3af2ef 100644 (file)
@@ -58,6 +58,17 @@ static int is_Call_Proj(const ir_node *n) {
        return 0;
 }
 
+static int is_P_frame_base_Proj(const ir_node *n) {
+       if (is_Proj(n)                                    &&
+               get_irn_opcode(get_Proj_pred(n)) == iro_Start &&
+               get_Proj_proj(n) == pn_Start_P_frame_base)
+       {
+               return 1;
+       }
+
+       return 0;
+}
+
 static int is_used_by_Keep(const ir_node *n) {
        return be_is_Keep(get_edge_src_irn(get_irn_out_edge_first(n)));
 }
@@ -138,8 +149,6 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const arch_irn_ops_t *sel
                                case pn_Start_X_initial_exec:
                                case pn_Start_P_value_arg_base:
                                case pn_Start_P_globals:
-                                       memcpy(req, &(ia32_default_req_none.req), sizeof(*req));
-                                       break;
                                case pn_Start_P_frame_base:
                                        memcpy(req, &(ia32_default_req_none.req), sizeof(*req));
                                        break;
@@ -163,10 +172,10 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const arch_irn_ops_t *sel
 static void ia32_set_irn_reg(const arch_irn_ops_t *self, ir_node *irn, const arch_register_t *reg) {
        int pos = 0;
 
-       if (is_Call_Proj(irn) && is_used_by_Keep(irn)) {
+       if ((is_Call_Proj(irn) && is_used_by_Keep(irn)) || is_P_frame_base_Proj(irn)) {
                /* don't skip the proj, we want to take the else below */
        }
-       if (is_Proj(irn)) {
+       else if (is_Proj(irn)) {
                pos = ia32_translate_proj_pos(irn);
                irn = my_skip_proj(irn);
        }
@@ -186,7 +195,7 @@ static const arch_register_t *ia32_get_irn_reg(const arch_irn_ops_t *self, const
        int pos = 0;
        const arch_register_t *reg = NULL;
 
-       if (is_Call_Proj(irn) && is_used_by_Keep(irn)) {
+       if ((is_Call_Proj(irn) && is_used_by_Keep(irn)) || is_P_frame_base_Proj(irn)) {
                /* don't skip the proj, we want to take the else below */
        }
        else if (is_Proj(irn)) {
@@ -251,25 +260,72 @@ static const arch_irn_ops_t ia32_irn_ops = {
  *                       |___/
  **************************************************/
 
+static void check_for_alloca(ir_node *irn, void *env) {
+       int *has_alloca = env;
+
+       if (get_irn_opcode(irn) == iro_Alloc) {
+               if (get_Alloc_where(irn) == stack_alloc) {
+                       *has_alloca = 1;
+               }
+       }
+}
+
 /**
  * Transforms the standard firm graph into
  * an ia32 firm graph
  */
 static void ia32_prepare_graph(void *self) {
-       ia32_code_gen_t *cg  = self;
+       ia32_code_gen_t *cg         = self;
+       int              has_alloca = 0;
+
+       if (! is_pseudo_ir_graph(cg->irg)) {
+               /* If there is a alloca in the irg, we use %ebp for stack addressing */
+               /* instead of %esp, as alloca destroys %esp.                         */
+
+               /* check for alloca node */
+               irg_walk_blkwise_graph(cg->irg, check_for_alloca, NULL, &has_alloca);
+
+               if (has_alloca) {
+                       ia32_general_purpose_regs[REG_EBP].type = arch_register_type_ignore;
+               }
 
-       if (! is_pseudo_ir_graph(cg->irg))
                irg_walk_blkwise_graph(cg->irg, NULL, ia32_transform_node, cg);
+       }
 }
 
 
 
 /**
- * Dummy functions for hooks we don't need but which must be filled.
+ * Set the register for P_frame_base Proj to %esp.
  */
-static void ia32_before_sched(void *self) {
+static void ia32_set_P_frame_base_Proj_reg(ir_node *irn, void *env) {
+       ia32_code_gen_t *cg = env;
+
+       if (is_P_frame_base_Proj(irn)) {
+               arch_set_irn_register(cg->arch_env, irn, &ia32_general_purpose_regs[REG_ESP]);
+       }
 }
 
+/**
+ * This function is the hook before_sched but more important: it is
+ * called after the dead node elimination. The dead node elimination changes
+ * the memory location of the nodes, which will change the hash key of
+ * the Proj_P_frame_base(Start) and this will fuck up the firm_node -> register
+ * hash map. So we need to insert the register for this node after the dead node
+ * elimination.
+ */
+static void ia32_some_stuff_need_to_be_done_after_deadnode_elimination(void *self) {
+       ia32_code_gen_t *cg  = self;
+
+       if (! is_pseudo_ir_graph(cg->irg))
+               irg_walk_blkwise_graph(cg->irg, NULL, ia32_set_P_frame_base_Proj_reg, cg);
+}
+
+
+
+/**
+ * Dummy functions for hooks we don't need but which must be filled.
+ */
 static void ia32_before_ra(void *self) {
 }
 
@@ -304,7 +360,7 @@ static void *ia32_cg_init(FILE *F, ir_graph *irg, const arch_env_t *arch_env);
 static const arch_code_generator_if_t ia32_code_gen_if = {
        ia32_cg_init,
        ia32_prepare_graph,
-       ia32_before_sched,   /* before scheduling hook */
+       ia32_some_stuff_need_to_be_done_after_deadnode_elimination,   /* before scheduling hook */
        ia32_before_ra,      /* before register allocation hook */
        ia32_codegen         /* emit && done */
 };
index 7a009d1..3816942 100644 (file)
@@ -141,12 +141,6 @@ int get_ia32_reg_nr(ir_node *irn, int pos, int in_out) {
        ir_node               *op;
 
        if (in_out == 1) {
-               /* special case Proj P_fame_base */
-               op = get_irn_n(irn, pos);
-               if (is_Proj(op) && get_Proj_proj(op) == pn_Start_P_frame_base) {
-                       return 10;
-               }
-
                reg = get_in_reg(irn, pos);
        }
        else {
@@ -164,11 +158,6 @@ const char *get_ia32_reg_name(ir_node *irn, int pos, int in_out) {
        ir_node               *op;
 
        if (in_out == 1) {
-               /* special case Proj P_fame_base */
-               op = get_irn_n(irn, pos);
-               if (is_Proj(op) && get_Proj_proj(op) == pn_Start_P_frame_base) {
-                       return "x(esp)";
-               }
                reg = get_in_reg(irn, pos);
        }
        else {
index e8acbc0..c804755 100644 (file)
@@ -23,7 +23,7 @@ int ia32_cmp_irn_reg_assoc(const void *a, const void *b, size_t len) {
        const struct ia32_irn_reg_assoc *x = a;
        const struct ia32_irn_reg_assoc *y = b;
 
-       return !(x->irn == y->irn);
+       return x->irn != y->irn;
 }
 
 static struct ia32_irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, set *reg_set) {
index 6701cd4..2c2f967 100644 (file)
@@ -76,17 +76,19 @@ $arch = "ia32";
 #   2 - caller save (register must be saved by the caller of a function)
 #   3 - callee save (register must be saved by the called function)
 #   4 - ignore (do not assign this register)
-# NOTE: Make sure to list the registers returning the call-result at first and
-#       in the correct order, otherwise it will break the magic!
+# NOTE: Make sure to list the registers returning the call-result before all other
+#       caller save registers and in the correct order, otherwise it will break
+#       the magic!
 %reg_classes = (
   "general_purpose" => [
                          { "name" => "eax", "type" => 2 },
                          { "name" => "edx", "type" => 2 },
                          { "name" => "ebx", "type" => 3 },
                          { "name" => "ecx", "type" => 2 },
-                         { "name" => "edi", "type" => 2 },
                          { "name" => "esi", "type" => 3 },
-                         { "name" => "ebp", "type" => 3 }
+                         { "name" => "edi", "type" => 3 },
+                         { "name" => "ebp", "type" => 3 },
+                         { "name" => "esp", "type" => 4 }  # we don't want esp to be assigned
                        ],
   "floating_point"  => [
                          { "name" => "xmm0", "type" => 2 },
index 74f4313..005ee48 100644 (file)
@@ -1480,9 +1480,9 @@ static ir_node *gen_Proj_Start(transform_env_t *env, ir_node *proj, ir_node *sta
                        free(projargs);
 
                        break;
+               case pn_Start_P_frame_base:
                case pn_Start_X_initial_exec:
                case pn_Start_M:
-               case pn_Start_P_frame_base:
                case pn_Start_P_globals:
                case pn_Start_P_value_arg_base:
                        break;
@@ -1604,11 +1604,11 @@ void ia32_transform_node(ir_node *node, void *env) {
                IGN(Break);
                IGN(Cmp);
 
+               BAD(Alloc);
                BAD(Raise);
                BAD(Sel);
                BAD(InstOf);
                BAD(Cast);
-               BAD(Alloc);
                BAD(Free);
                BAD(Sync);
                BAD(Tuple);