amd64: Added Load and FrameAddr transformation. And fixed some corruption bugs w...
authorRobin Redeker <rredeker@ipd.info.uni-karlsruhe.de>
Mon, 28 Jun 2010 10:41:54 +0000 (10:41 +0000)
committerRobin Redeker <rredeker@ipd.info.uni-karlsruhe.de>
Mon, 28 Jun 2010 10:41:54 +0000 (10:41 +0000)
[r27666]

ir/be/amd64/amd64_emitter.c
ir/be/amd64/amd64_new_nodes.c
ir/be/amd64/amd64_nodes_attr.h
ir/be/amd64/amd64_spec.pl
ir/be/amd64/amd64_transform.c
ir/be/amd64/bearch_amd64.c

index 7db0490..edc9333 100644 (file)
@@ -353,15 +353,32 @@ static void emit_be_Copy(const ir_node *irn)
                panic("emit_be_Copy: move not supported for FP");
        } else if (mode_is_data(mode)) {
                be_emit_cstring("\tmov ");
-               amd64_emit_source_register(irn, 0);
-               be_emit_cstring(", ");
                amd64_emit_dest_register(irn, 0);
+               be_emit_cstring(", ");
+               amd64_emit_source_register(irn, 0);
                be_emit_finish_line_gas(irn);
        } else {
                panic("emit_be_Copy: move not supported for this mode");
        }
 }
 
+static void emit_amd64_FrameAddr(const ir_node *irn)
+{
+       const amd64_SymConst_attr_t *attr = get_irn_generic_attr_const(irn);
+
+       be_emit_cstring("\tmov ");
+       amd64_emit_dest_register(irn, 0);
+       be_emit_cstring(", ");
+       amd64_emit_source_register(irn, 0);
+       be_emit_finish_line_gas(irn);
+
+       be_emit_cstring("\tadd ");
+       amd64_emit_dest_register(irn, 0);
+       be_emit_cstring(", ");
+       be_emit_irprintf("$0x%X", attr->fp_offset);
+       be_emit_finish_line_gas(irn);
+}
+
 /**
  * Emits code for a return.
  */
@@ -399,6 +416,7 @@ static void amd64_register_emitters(void)
        set_emitter(op_amd64_SymConst,   emit_amd64_SymConst);
        set_emitter(op_amd64_Jmp,        emit_amd64_Jmp);
        set_emitter(op_amd64_Jcc,        emit_amd64_Jcc);
+       set_emitter(op_amd64_FrameAddr,  emit_amd64_FrameAddr);
        set_emitter(op_be_Return,        emit_be_Return);
        set_emitter(op_be_Call,          emit_be_Call);
        set_emitter(op_be_Copy,          emit_be_Copy);
index a75bd36..6be6cdf 100644 (file)
@@ -170,7 +170,8 @@ static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags,
 static void init_amd64_SymConst_attributes(ir_node *node, ir_entity *entity)
 {
        amd64_SymConst_attr_t *attr = get_irn_generic_attr (node);
-       attr->entity = entity;
+       attr->entity    = entity;
+       attr->fp_offset = 0;
 }
 
 /** Compare node attributes for SymConst. */
@@ -179,7 +180,8 @@ static int cmp_amd64_attr_SymConst(ir_node *a, ir_node *b)
        const amd64_SymConst_attr_t *attr_a = get_amd64_SymConst_attr_const(a);
        const amd64_SymConst_attr_t *attr_b = get_amd64_SymConst_attr_const(b);
 
-       if (attr_a->entity != attr_b->entity)
+       if (attr_a->entity != attr_b->entity
+           || attr_a->fp_offset != attr_b->fp_offset)
                return 1;
 
        return 0;
index 1e3668e..cd58f0b 100644 (file)
@@ -32,6 +32,7 @@ typedef struct amd64_SymConst_attr_t   amd64_SymConst_attr_t;
 
 struct amd64_attr_t
 {
+       except_attr                 exc;     /**< the exception attribute. MUST be the first one. */
        const arch_register_req_t **in_req;  /**< register requirements for arguments */
        const arch_register_req_t **out_req; /**< register requirements for results */
        ir_mode                    *ls_mode; /**< Stores the "input" mode */
@@ -48,7 +49,9 @@ struct amd64_attr_t
 
 struct amd64_SymConst_attr_t
 {
-       ir_entity *entity;
+       amd64_attr_t  base;
+       ir_entity    *entity;
+       unsigned      fp_offset;
 };
 
 #define CAST_AMD64_ATTR(type,ptr)        ((type *)(ptr))
index d184a76..147dab0 100644 (file)
@@ -208,8 +208,8 @@ Add => {
        reg_req    => { in => [ "gp", "gp" ],
                        out => [ "gp" ] },
        in         => [ "left", "right" ],
-       emit       => ". mov %S2, %D1\n"
-                     . ". add %S1, %D1\n",
+       emit       => ". mov %D1, %S2\n"
+                     . ". add %D1, %S1\n",
        outs       => [ "res" ],
        mode       => $mode_gp,
 },
@@ -218,7 +218,7 @@ Immediate => {
        attr      => "unsigned imm_value",
        init_attr => "attr->ext.imm_value = imm_value;",
        reg_req   => { out => [ "gp" ] },
-       emit      => '. movq %C, %D1',
+       emit      => '. movq %D1, %C',
        mode      => $mode_gp,
 },
 SymConst => {
@@ -268,6 +268,33 @@ Jcc => {
        init_attr => "attr->ext.pnc = pnc;",
        mode      => "mode_T",
 },
+Load => {
+       op_flags  => "L|F",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "none" ],
+                      out => [ "gp", "none" ] },
+       ins       => [ "ptr", "mem" ],
+       outs      => [ "res",  "M" ],
+       emit      => ". lea %D1, [%S1]"
+},
+FrameAddr => {
+       op_flags  => "c",
+       irn_flags => "R",
+       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+       ins       => [ "base" ],
+       attr      => "ir_entity *entity",
+       attr_type => "amd64_SymConst_attr_t",
+       mode      => $mode_gp,
+},
+#Store => {
+#      op_flags  => "L|F",
+#      state     => "exc_pinned",
+#      reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none", "none" ] },
+#      ins       => [ "base", "index", "mem", "val" ],
+#      outs      => [ "M", "X_exc" ],
+#      mode      => "mode_M",
+#},
+
 
 #NoReg_GP => {
 #      state     => "pinned",
index 4907ee0..1c6e588 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "../benode.h"
 #include "../betranshlp.h"
+#include "../beutil.h"
 #include "bearch_amd64_t.h"
 
 #include "amd64_nodes_attr.h"
@@ -357,6 +358,149 @@ static ir_node *gen_Conv(ir_node *node)
        }
 }
 
+/**
+ * Transforms a Load.
+ *
+ * @return the created AMD64 Load node
+ */
+static ir_node *gen_Load(ir_node *node)
+{
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *ptr      = get_Load_ptr(node);
+       ir_node  *new_ptr  = be_transform_node(ptr);
+       ir_node  *mem      = get_Load_mem(node);
+       ir_node  *new_mem  = be_transform_node(mem);
+       ir_mode  *mode     = get_Load_mode(node);
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       ir_node  *new_load = NULL;
+
+       if (mode_is_float(mode)) {
+               panic("Float not supported yet");
+       } else {
+               assert(mode_is_data(mode) && "unsupported mode for Load");
+               new_load = new_bd_amd64_Load(dbgi, block, new_ptr, new_mem);
+       }
+       set_irn_pinned(new_load, get_irn_pinned(node));
+
+       /* check for special case: the loaded value might not be used */
+//     if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) {
+//             /* add a result proj and a Keep to produce a pseudo use */
+//             ir_node *proj = new_r_Proj(new_load, mode_Iu, pn_amd64_Load_res);
+//             be_new_Keep(block, 1, &proj);
+//     }
+
+       return new_load;
+}
+
+/**
+ * Transform a Proj from a Load.
+ */
+static ir_node *gen_Proj_Load(ir_node *node)
+{
+       ir_node  *load     = get_Proj_pred(node);
+       ir_node  *new_load = be_transform_node(load);
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       long     proj      = get_Proj_proj(node);
+
+       /* renumber the proj */
+       switch (get_amd64_irn_opcode(new_load)) {
+               case iro_amd64_Load:
+                       /* handle all gp loads equal: they have the same proj numbers. */
+                       if (proj == pn_Load_res) {
+                               return new_rd_Proj(dbgi, new_load, mode_Iu, pn_amd64_Load_res);
+                       } else if (proj == pn_Load_M) {
+                               return new_rd_Proj(dbgi, new_load, mode_M, pn_amd64_Load_M);
+                       }
+               break;
+       /*
+               case iro_sparc_fpaLoad:
+                       panic("FP not implemented yet");
+               break;
+       */
+               default:
+                       panic("Unsupported Proj from Load");
+       }
+
+    return be_duplicate_node(node);
+}
+
+/**
+ * Transform a Proj node.
+ */
+static ir_node *gen_Proj(ir_node *node)
+{
+       ir_graph *irg  = current_ir_graph;
+       dbg_info *dbgi = get_irn_dbg_info(node);
+       ir_node  *pred = get_Proj_pred(node);
+       long     proj  = get_Proj_proj(node);
+
+       (void) irg;
+    (void) dbgi;
+
+       if (is_Store(pred)) {
+               if (proj == pn_Store_M) {
+                       return be_transform_node(pred);
+               } else {
+                       panic("Unsupported Proj from Store");
+               }
+       } else if (is_Load(pred)) {
+               return gen_Proj_Load(node);
+//     } else if (be_is_SubSP(pred)) {
+//             //panic("gen_Proj not implemented for SubSP");
+//             return gen_Proj_be_SubSP(node);
+//     } else if (be_is_AddSP(pred)) {
+//             //panic("gen_Proj not implemented for AddSP");
+//             return gen_Proj_be_AddSP(node);
+//     } else if (is_Cmp(pred)) {
+//             //panic("gen_Proj not implemented for Cmp");
+//             return gen_Proj_Cmp(node);
+//     } else if (is_Div(pred)) {
+//             return gen_Proj_Div(node);
+       } else if (is_Start(pred)) {
+//     /*
+//             if (proj == pn_Start_X_initial_exec) {
+//                     ir_node *block = get_nodes_block(pred);
+//                     ir_node *jump;
+//
+//                     // we exchange the ProjX with a jump
+//                     block = be_transform_node(block);
+//                     jump  = new_rd_Jmp(dbgi, block);
+//                     return jump;
+//             }
+//
+//             if (node == get_irg_anchor(irg, anchor_tls)) {
+//                     return gen_Proj_tls(node);
+//             }
+//     */
+//     } else {
+//             ir_node *new_pred = be_transform_node(pred);
+//             ir_mode *mode     = get_irn_mode(node);
+//             if (mode_needs_gp_reg(mode)) {
+//                     ir_node *new_proj = new_r_Proj(new_pred, mode_Iu, get_Proj_proj(node));
+//                     new_proj->node_nr = node->node_nr;
+//                     return new_proj;
+//             }
+       }
+
+    return be_duplicate_node(node);
+}
+
+/**
+ * Transforms a FrameAddr into an AMD64 Add.
+ */
+static ir_node *gen_be_FrameAddr(ir_node *node)
+{
+       ir_node   *block  = be_transform_node(get_nodes_block(node));
+       ir_entity *ent    = be_get_frame_entity(node);
+       ir_node   *fp     = be_get_FrameAddr_frame(node);
+       ir_node   *new_fp = be_transform_node(fp);
+       dbg_info  *dbgi   = get_irn_dbg_info(node);
+       ir_node   *new_node;
+
+       new_node = new_bd_amd64_FrameAddr(dbgi, block, new_fp, ent);
+       return new_node;
+}
+
 /* Boilerplate code for transformation: */
 
 static void amd64_pretransform_node(void)
@@ -380,11 +524,14 @@ static void amd64_register_transformers(void)
        set_transformer(op_SymConst,     gen_SymConst);
        set_transformer(op_Add,          gen_Add);
        set_transformer(op_be_Call,      gen_be_Call);
+       set_transformer(op_be_FrameAddr, gen_be_FrameAddr);
        set_transformer(op_Conv,         gen_Conv);
        set_transformer(op_Jmp,          gen_Jmp);
        set_transformer(op_Cmp,          gen_Cmp);
        set_transformer(op_Cond,         gen_Cond);
        set_transformer(op_Phi,          gen_Phi);
+       set_transformer(op_Load,         gen_Load);
+       set_transformer(op_Proj,         gen_Proj);
 }
 
 
index f0923d0..63e4b5d 100644 (file)
@@ -63,6 +63,11 @@ static arch_irn_class_t amd64_classify(const ir_node *irn)
 
 static ir_entity *amd64_get_frame_entity(const ir_node *node)
 {
+       if (is_amd64_FrameAddr(node)) {
+               const amd64_SymConst_attr_t *attr = get_irn_generic_attr_const(node);
+               return attr->entity;
+       }
+
        (void) node;
        /* TODO: return the ir_entity assigned to the frame */
        return NULL;
@@ -81,9 +86,10 @@ static void amd64_set_frame_entity(ir_node *node, ir_entity *ent)
  */
 static void amd64_set_frame_offset(ir_node *irn, int offset)
 {
-       (void) irn;
-       (void) offset;
-       /* TODO: correct offset if irn accesses the stack */
+       if (is_amd64_FrameAddr(irn)) {
+               amd64_SymConst_attr_t *attr = get_irn_generic_attr(irn);
+               attr->fp_offset += offset;
+       }
 }
 
 static int amd64_get_sp_bias(const ir_node *irn)