From: Robin Redeker Date: Mon, 28 Jun 2010 10:41:54 +0000 (+0000) Subject: amd64: Added Load and FrameAddr transformation. And fixed some corruption bugs w... X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=ca8f759819873b6990bd2017bdcf96bf2b02f4d0;p=libfirm amd64: Added Load and FrameAddr transformation. And fixed some corruption bugs w.r.t. node attribute handling. [r27666] --- diff --git a/ir/be/amd64/amd64_emitter.c b/ir/be/amd64/amd64_emitter.c index 7db04904e..edc933309 100644 --- a/ir/be/amd64/amd64_emitter.c +++ b/ir/be/amd64/amd64_emitter.c @@ -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); diff --git a/ir/be/amd64/amd64_new_nodes.c b/ir/be/amd64/amd64_new_nodes.c index a75bd3602..6be6cdf8e 100644 --- a/ir/be/amd64/amd64_new_nodes.c +++ b/ir/be/amd64/amd64_new_nodes.c @@ -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; diff --git a/ir/be/amd64/amd64_nodes_attr.h b/ir/be/amd64/amd64_nodes_attr.h index 1e3668e4c..cd58f0b4c 100644 --- a/ir/be/amd64/amd64_nodes_attr.h +++ b/ir/be/amd64/amd64_nodes_attr.h @@ -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)) diff --git a/ir/be/amd64/amd64_spec.pl b/ir/be/amd64/amd64_spec.pl index d184a76be..147dab059 100644 --- a/ir/be/amd64/amd64_spec.pl +++ b/ir/be/amd64/amd64_spec.pl @@ -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", diff --git a/ir/be/amd64/amd64_transform.c b/ir/be/amd64/amd64_transform.c index 4907ee050..1c6e588ba 100644 --- a/ir/be/amd64/amd64_transform.c +++ b/ir/be/amd64/amd64_transform.c @@ -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); } diff --git a/ir/be/amd64/bearch_amd64.c b/ir/be/amd64/bearch_amd64.c index f0923d00e..63e4b5df9 100644 --- a/ir/be/amd64/bearch_amd64.c +++ b/ir/be/amd64/bearch_amd64.c @@ -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)