From: Matthias Braun Date: Fri, 30 Apr 2010 13:10:23 +0000 (+0000) Subject: modernize TEMPLATE backend and simplify some backend APIs X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=72fca46dfebc45e1c8466d0b7035a68b9d1495fe;p=libfirm modernize TEMPLATE backend and simplify some backend APIs [r27460] --- diff --git a/ir/be/TEMPLATE/TEMPLATE_emitter.c b/ir/be/TEMPLATE/TEMPLATE_emitter.c index 9caf817d8..151463675 100644 --- a/ir/be/TEMPLATE/TEMPLATE_emitter.c +++ b/ir/be/TEMPLATE/TEMPLATE_emitter.c @@ -38,6 +38,8 @@ #include "../besched.h" #include "../begnuas.h" +#include "../beblocksched.h" +#include "../benode.h" #include "TEMPLATE_emitter.h" #include "gen_TEMPLATE_emitter.h" @@ -113,8 +115,8 @@ static const arch_register_t *get_out_reg(const ir_node *node, int pos) void TEMPLATE_emit_immediate(const ir_node *node) { - (void) node; - /* TODO */ + const TEMPLATE_attr_t *attr = get_irn_generic_attr_const(node); + be_emit_tarval(attr->value); } void TEMPLATE_emit_source_register(const ir_node *node, int pos) @@ -151,38 +153,77 @@ static void TEMPLATE_emit_cfop_target(const ir_node *node) /** * Emits code for a unconditional jump. */ -static void emit_Jmp(const ir_node *node) +static void emit_TEMPLATE_Jmp(const ir_node *node) { be_emit_cstring("\tjmp "); TEMPLATE_emit_cfop_target(node); be_emit_finish_line_gas(node); } +static void emit_be_IncSP(const ir_node *node) +{ + int offset = be_get_IncSP_offset(node); + + if (offset == 0) + return; + + /* downwards growing stack */ + if (offset > 0) { + be_emit_cstring("\tsub "); + } else { + be_emit_cstring("\tadd "); + offset = -offset; + } + + TEMPLATE_emit_source_register(node, 0); + be_emit_irprintf(", %d, ", offset); + TEMPLATE_emit_dest_register(node, 0); + be_emit_finish_line_gas(node); +} + +static void emit_be_Return(const ir_node *node) +{ + be_emit_cstring("\tret"); + be_emit_finish_line_gas(node); +} + +static void emit_nothing(const ir_node *node) +{ + (void) node; +} + +/** + * The type of a emitter function. + */ +typedef void (emit_func)(const ir_node *node); + +static inline void set_emitter(ir_op *op, emit_func func) +{ + op->ops.generic = (op_func)func; +} + /** * Enters the emitter functions for handled nodes into the generic * pointer of an opcode. */ static void TEMPLATE_register_emitters(void) { - -/* some convienience macros to register additional emitter functions - (other than the generated ones) */ -#define TEMPLATE_EMIT(a) op_TEMPLATE_##a->ops.generic = (op_func)emit_TEMPLATE_##a -#define EMIT(a) op_##a->ops.generic = (op_func)emit_##a -#define BE_EMIT(a) op_be_##a->ops.generic = (op_func)emit_be_##a - /* first clear the generic function pointer for all ops */ clear_irp_opcodes_generic_func(); /* register all emitter functions defined in spec */ TEMPLATE_register_spec_emitters(); - /* register addtional emitter functions if needed */ - EMIT(Jmp); + /* custom emitters not provided by the spec */ + set_emitter(op_TEMPLATE_Jmp, emit_TEMPLATE_Jmp); + set_emitter(op_be_Return, emit_be_Return); + set_emitter(op_be_IncSP, emit_be_IncSP); -#undef TEMPLATE_EMIT -#undef BE_EMIT -#undef EMIT + /* no need to emit anything for the following nodes */ + set_emitter(op_Phi, emit_nothing); + set_emitter(op_be_Keep, emit_nothing); + set_emitter(op_be_Start, emit_nothing); + set_emitter(op_be_Barrier, emit_nothing); } typedef void (*emit_func_ptr) (const ir_node *); @@ -206,13 +247,9 @@ static void TEMPLATE_emit_node(const ir_node *node) * Walks over the nodes in a block connected by scheduling edges * and emits code for each node. */ -static void TEMPLATE_gen_block(ir_node *block, void *data) +static void TEMPLATE_emit_block(ir_node *block) { ir_node *node; - (void) data; - - if (! is_Block(block)) - return; be_gas_emit_block_name(block); be_emit_cstring(":\n"); @@ -223,35 +260,6 @@ static void TEMPLATE_gen_block(ir_node *block, void *data) } } - -/** - * Emits code for function start. - */ -static void TEMPLATE_emit_func_prolog(ir_graph *irg) -{ - const char *irg_name = get_entity_name(get_irg_entity(irg)); - - /* TODO: emit function header */ - be_emit_cstring("/* start of "); - be_emit_string(irg_name); - be_emit_cstring(" */\n"); - be_emit_write_line(); -} - -/** - * Emits code for function end - */ -static void TEMPLATE_emit_func_epilog(ir_graph *irg) -{ - const char *irg_name = get_entity_name(get_irg_entity(irg)); - - /* TODO: emit function end */ - be_emit_cstring("/* end of "); - be_emit_string(irg_name); - be_emit_cstring(" */\n"); - be_emit_write_line(); -} - /** * Sets labels for control flow nodes (jump target) */ @@ -270,15 +278,29 @@ static void TEMPLATE_gen_labels(ir_node *block, void *env) /** * Main driver */ -void TEMPLATE_gen_routine(const TEMPLATE_code_gen_t *cg, ir_graph *irg) +void TEMPLATE_emit_routine(ir_graph *irg) { - (void)cg; + ir_node **block_schedule; + ir_entity *entity = get_irg_entity(irg); + int i; + int n; /* register all emitter functions */ TEMPLATE_register_emitters(); - TEMPLATE_emit_func_prolog(irg); + /* create the block schedule */ + block_schedule = be_create_block_schedule(irg); + + /* emit assembler prolog */ + be_gas_emit_function_prolog(entity, 4); + + /* populate jump link fields with their destinations */ irg_block_walk_graph(irg, TEMPLATE_gen_labels, NULL, NULL); - irg_walk_blkwise_graph(irg, NULL, TEMPLATE_gen_block, NULL); - TEMPLATE_emit_func_epilog(irg); + + n = ARR_LEN(block_schedule); + for (i = 0; i < n; ++i) { + ir_node *block = block_schedule[i]; + TEMPLATE_emit_block(block); + } + be_gas_emit_function_epilog(entity); } diff --git a/ir/be/TEMPLATE/TEMPLATE_emitter.h b/ir/be/TEMPLATE/TEMPLATE_emitter.h index 5e5715c12..31eae4d83 100644 --- a/ir/be/TEMPLATE/TEMPLATE_emitter.h +++ b/ir/be/TEMPLATE/TEMPLATE_emitter.h @@ -38,10 +38,6 @@ void TEMPLATE_emit_source_register(const ir_node *node, int pos); void TEMPLATE_emit_dest_register(const ir_node *node, int pos); void TEMPLATE_emit_immediate(const ir_node *node); -int get_TEMPLATE_reg_nr(ir_node *irn, int posi, int in_out); -const char *get_TEMPLATE_in_reg_name(ir_node *irn, int pos); - - -void TEMPLATE_gen_routine(const TEMPLATE_code_gen_t *cg, ir_graph *irg); +void TEMPLATE_emit_routine(ir_graph *irg); #endif diff --git a/ir/be/TEMPLATE/TEMPLATE_new_nodes.c b/ir/be/TEMPLATE/TEMPLATE_new_nodes.c index b1fc94667..1302ced37 100644 --- a/ir/be/TEMPLATE/TEMPLATE_new_nodes.c +++ b/ir/be/TEMPLATE/TEMPLATE_new_nodes.c @@ -147,6 +147,12 @@ static void init_TEMPLATE_attributes(ir_node *node, arch_irn_flags_t flags, memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0])); } +static void set_TEMPLATE_value(ir_node *node, tarval *value) +{ + TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node); + attr->value = value; +} + static int TEMPLATE_compare_attr(ir_node *a, ir_node *b) { const TEMPLATE_attr_t *attr_a = get_TEMPLATE_attr_const(a); diff --git a/ir/be/TEMPLATE/TEMPLATE_nodes_attr.h b/ir/be/TEMPLATE/TEMPLATE_nodes_attr.h index fece34739..6c667c901 100644 --- a/ir/be/TEMPLATE/TEMPLATE_nodes_attr.h +++ b/ir/be/TEMPLATE/TEMPLATE_nodes_attr.h @@ -31,6 +31,8 @@ typedef struct TEMPLATE_attr_t TEMPLATE_attr_t; struct TEMPLATE_attr_t { + tarval *value; + const arch_register_req_t **in_req; /**< register requirements for arguments */ const arch_register_req_t **out_req; /**< register requirements for results */ }; diff --git a/ir/be/TEMPLATE/TEMPLATE_spec.pl b/ir/be/TEMPLATE/TEMPLATE_spec.pl index f24a58dec..db9aa4d63 100644 --- a/ir/be/TEMPLATE/TEMPLATE_spec.pl +++ b/ir/be/TEMPLATE/TEMPLATE_spec.pl @@ -5,6 +5,12 @@ $arch = "TEMPLATE"; +# +# Modes +# +$mode_gp = "mode_Iu"; # mode used by general purpose registers +$mode_fp = "mode_E"; # mode used by floatingpoint registers + # The node description is done as a perl hash initializer with the # following structure: # @@ -114,7 +120,7 @@ $arch = "TEMPLATE"; { name => "r13", type => 2 }, { name => "sp", realname => "r14", type => 4 }, # stackpointer { name => "bp", realname => "r15", type => 4 }, # basepointer - { mode => "mode_Iu" } + { mode => $mode_gp } ], fp => [ { name => "f0", type => 1 }, @@ -133,7 +139,7 @@ $arch = "TEMPLATE"; { name => "f13", type => 1 }, { name => "f14", type => 1 }, { name => "f15", type => 1 }, - { mode => "mode_D" } + { mode => $mode_fp } ] ); @@ -161,157 +167,91 @@ Add => { op_flags => "C", irn_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. add %S1, %S2, %D1' -}, - -Add_i => { - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. add %S1, %C, %D1' + emit => '. add %S1, %S2, %D1', + mode => $mode_gp, }, Mul => { op_flags => "C", irn_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit =>'. mul %S1, %S2, %D1' -}, - -Mul_i => { - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. mul %S1, %C, %D1' + emit =>'. mul %S1, %S2, %D1', + mode => $mode_gp, }, And => { op_flags => "C", irn_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. and %S1, %S2, %D1' -}, - -And_i => { - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. and %S1, %C, %D1' + emit => '. and %S1, %S2, %D1', + mode => $mode_gp, }, Or => { op_flags => "C", irn_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. or %S1, %S2, %D1' -}, - -Or_i => { - op_flags => "C", - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. or %S1, %C, %D1' + emit => '. or %S1, %S2, %D1', + mode => $mode_gp, }, -Eor => { +Xor => { op_flags => "C", irn_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. xor %S1, %S2, %D1' -}, - -Eor_i => { - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. xor %S1, %C, %D1' + emit => '. xor %S1, %S2, %D1', + mode => $mode_gp, }, Sub => { irn_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. sub %S1, %S2, %D1' -}, - -Sub_i => { - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. subl %S1, %C, %D1' + emit => '. sub %S1, %S2, %D1', + mode => $mode_gp, }, Shl => { irn_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. shl %S1, %S2, %D1' -}, - -Shl_i => { - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. shl %S1, %C, %D1' + emit => '. shl %S1, %S2, %D1', + mode => $mode_gp, }, Shr => { irn_flags => "R", reg_req => { in => [ "gp", "gp" ], out => [ "in_r1" ] }, - emit => '. shr %S2, %D1' -}, - -Shr_i => { - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. shr %S1, %C, %D1' -}, - -RotR => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. ror %S1, %S2, %D1' -}, - -RotL => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, - emit => '. rol %S1, %S2, %D1' -}, - -RotL_i => { - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. rol %S1, %C, %D1' + emit => '. shr %S2, %D1', + mode => $mode_gp, }, Minus => { irn_flags => "R", reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. neg %S1, %D1' -}, - -Inc => { - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. inc %S1, %D1' -}, - -Dec => { - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. dec %S1, %D1' + emit => '. neg %S1, %D1', + mode => $mode_gp, }, Not => { - arity => 1, - remat => 1, - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - emit => '. not %S1, %D1' + arity => 1, + remat => 1, + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + emit => '. not %S1, %D1', + mode => $mode_gp, }, Const => { - op_flags => "c", - irn_flags => "R", - reg_req => { out => [ "gp" ] }, - emit => '. mov %C, %D1', - cmp_attr => + op_flags => "c", + irn_flags => "R", + attr => "tarval *value", + custominit => "set_TEMPLATE_value(res, value);", + reg_req => { out => [ "gp" ] }, + emit => '. mov %C, %D1', + cmp_attr => ' /* TODO: compare Const attributes */ return 1; -' +', + mode => $mode_gp, }, # Control Flow @@ -331,7 +271,7 @@ Load => { irn_flags => "R", state => "exc_pinned", reg_req => { in => [ "gp", "none" ], out => [ "gp" ] }, - emit => '. mov (%S1), %D1' + emit => '. mov (%S1), %D1', }, Store => { @@ -339,7 +279,7 @@ Store => { irn_flags => "R", state => "exc_pinned", reg_req => { in => [ "gp", "gp", "none" ] }, - emit => '. movl %S2, (%S1)' + emit => '. movl %S2, (%S1)', }, # Floating Point operations @@ -348,44 +288,35 @@ fAdd => { op_flags => "C", irn_flags => "R", reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, - emit => '. fadd %S1, %S2, %D1' + emit => '. fadd %S1, %S2, %D1', + mode => $mode_fp, }, fMul => { op_flags => "C", reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, - emit =>'. fmul %S1, %S2, %D1' -}, - -fMax => { - op_flags => "C", - irn_flags => "R", - reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, - emit =>'. fmax %S1, %S2, %D1' -}, - -fMin => { - op_flags => "C", - irn_flags => "R", - reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, - emit =>'. fmin %S1, %S2, %D1' + emit =>'. fmul %S1, %S2, %D1', + mode => $mode_fp, }, fSub => { irn_flags => "R", reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, - emit => '. fsub %S1, %S2, %D1' + emit => '. fsub %S1, %S2, %D1', + mode => $mode_fp, }, fDiv => { reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, - emit => '. fdiv %S1, %S2, %D1' + emit => '. fdiv %S1, %S2, %D1', + mode => $mode_fp, }, fMinus => { irn_flags => "R", reg_req => { in => [ "fp" ], out => [ "fp" ] }, - emit => '. fneg %S1, %D1' + emit => '. fneg %S1, %D1', + mode => $mode_fp, }, fConst => { @@ -397,7 +328,8 @@ fConst => { ' /* TODO: compare fConst attributes */ return 1; -' +', + mode => $mode_fp, }, # Load / Store @@ -407,7 +339,7 @@ fLoad => { irn_flags => "R", state => "exc_pinned", reg_req => { in => [ "gp", "none" ], out => [ "fp" ] }, - emit => '. fmov (%S1), %D1' + emit => '. fmov (%S1), %D1', }, fStore => { @@ -415,7 +347,7 @@ fStore => { irn_flags => "R", state => "exc_pinned", reg_req => { in => [ "gp", "fp", "none" ] }, - emit => '. fmov %S2, (%S1)' + emit => '. fmov %S2, (%S1)', }, ); diff --git a/ir/be/TEMPLATE/TEMPLATE_transform.c b/ir/be/TEMPLATE/TEMPLATE_transform.c index 289cf7869..72996fae2 100644 --- a/ir/be/TEMPLATE/TEMPLATE_transform.c +++ b/ir/be/TEMPLATE/TEMPLATE_transform.c @@ -33,8 +33,10 @@ #include "ircons.h" #include "iropt_t.h" #include "debug.h" +#include "error.h" #include "../benode.h" +#include "../betranshlp.h" #include "bearch_TEMPLATE_t.h" #include "TEMPLATE_nodes_attr.h" @@ -45,359 +47,271 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) -/** - * Creates an TEMPLATE Add. - * - * @param env The transformation environment - * @param op1 first operator - * @param op2 second operator - * @return the created TEMPLATE Add node - */ -static ir_node *gen_Add(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) +typedef ir_node* (*new_binop_func)(dbg_info *dbgi, ir_node *block, + ir_node *left, ir_node *right); + +static ir_node *transform_binop(ir_node *node, new_binop_func new_func) { - return new_bd_TEMPLATE_Add(env->dbg, env->block, op1, op2, env->mode); + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *left = get_binop_left(node); + ir_node *new_left = be_transform_node(left); + ir_node *right = get_binop_right(node); + ir_node *new_right = be_transform_node(right); + + return new_func(dbgi, new_block, new_left, new_right); } - - -/** - * Creates an TEMPLATE Mul. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Mul node - */ -static ir_node *gen_Mul(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) +static ir_node *gen_And(ir_node *node) { - if (mode_is_float(env->mode)) { - return new_bd_TEMPLATE_fMul(env->dbg, env->block, op1, op2, env->mode); - } else { - return new_bd_TEMPLATE_Mul(env->dbg, env->block, op1, op2, env->mode); - } + return transform_binop(node, new_bd_TEMPLATE_And); } - - -/** - * Creates an TEMPLATE And. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE And node - */ -static ir_node *gen_And(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) +static ir_node *gen_Or(ir_node *node) { - return new_bd_TEMPLATE_And(env->dbg, env->block, op1, op2, env->mode); + return transform_binop(node, new_bd_TEMPLATE_Or); } +static ir_node *gen_Eor(ir_node *node) +{ + return transform_binop(node, new_bd_TEMPLATE_Xor); +} - -/** - * Creates an TEMPLATE Or. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Or node - */ -static ir_node *gen_Or(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) +static ir_node *gen_Quot(ir_node *node) { - return new_bd_TEMPLATE_Or(env->dbg, env->block, op1, op2, env->mode); + return transform_binop(node, new_bd_TEMPLATE_fDiv); } +static ir_node *gen_Shl(ir_node *node) +{ + return transform_binop(node, new_bd_TEMPLATE_Shl); +} +static ir_node *gen_Shr(ir_node *node) +{ + return transform_binop(node, new_bd_TEMPLATE_Shr); +} -/** - * Creates an TEMPLATE Eor. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Eor node - */ -static ir_node *gen_Eor(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) +static ir_node *gen_Add(ir_node *node) { - return new_bd_TEMPLATE_Eor(env->dbg, env->block, op1, op2, env->mode); + ir_mode *mode = get_irn_mode(node); + + if (mode_is_float(mode)) { + return transform_binop(node, new_bd_TEMPLATE_fAdd); + } + return transform_binop(node, new_bd_TEMPLATE_Add); } +static ir_node *gen_Sub(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); + if (mode_is_float(mode)) { + return transform_binop(node, new_bd_TEMPLATE_fSub); + } + return transform_binop(node, new_bd_TEMPLATE_Sub); +} -/** - * Creates an TEMPLATE Sub. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Sub node - */ -static ir_node *gen_Sub(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) +static ir_node *gen_Mul(ir_node *node) { - if (mode_is_float(env->mode)) { - return new_bd_TEMPLATE_fSub(env->dbg, env->block, op1, op2, env->mode); - } else { - return new_bd_TEMPLATE_Sub(env->dbg, env->block, op1, op2, env->mode); + ir_mode *mode = get_irn_mode(node); + + if (mode_is_float(mode)) { + return transform_binop(node, new_bd_TEMPLATE_fMul); } + return transform_binop(node, new_bd_TEMPLATE_Mul); } +typedef ir_node* (*new_unop_func)(dbg_info *dbgi, ir_node *block, ir_node *op); -/** - * Creates an TEMPLATE floating Div. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE fDiv node - */ -static ir_node *gen_Quot(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) +static ir_node *transform_unop(ir_node *node, new_unop_func new_func) { - return new_bd_TEMPLATE_fDiv(env->dbg, env->block, op1, op2, env->mode); + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *op = get_unop_op(node); + ir_node *new_op = be_transform_node(op); + + return new_func(dbgi, new_block, new_op); } +static ir_node *gen_Minus(ir_node *node) +{ + ir_mode *mode = get_irn_mode(node); + if (mode_is_float(mode)) { + return transform_unop(node, new_bd_TEMPLATE_fMinus); + } + return transform_unop(node, new_bd_TEMPLATE_Minus); +} -/** - * Creates an TEMPLATE Shl. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Shl node - */ -static ir_node *gen_Shl(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) +static ir_node *gen_Not(ir_node *node) { - return new_bd_TEMPLATE_Shl(env->dbg, env->block, op1, op2, env->mode); + return transform_unop(node, new_bd_TEMPLATE_Not); } +static ir_node *gen_Const(ir_node *node) +{ + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + tarval *value = get_Const_tarval(node); + ir_node *result; + result = new_bd_TEMPLATE_Const(dbgi, new_block, value); -/** - * Creates an TEMPLATE Shr. - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created TEMPLATE Shr node - */ -static ir_node *gen_Shr(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) -{ - return new_bd_TEMPLATE_Shr(env->dbg, env->block, op1, op2, env->mode); -} + /* make sure the node does not float above the barrier into the prologue */ + be_dep_on_frame(result); + return result; +} +static ir_node *gen_Load(ir_node *node) +{ + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(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_irn_mode(node); + + if (mode_is_float(mode)) { + return new_bd_TEMPLATE_fLoad(dbgi, new_block, new_ptr, new_mem, mode); + } + return new_bd_TEMPLATE_Load(dbgi, new_block, new_ptr, new_mem, mode); +} -/** - * Transforms a Minus node. - * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Minus node - * @param op operator - * @param mode node mode - * @return the created TEMPLATE Minus node - */ -static ir_node *gen_Minus(TEMPLATE_transform_env_t *env, ir_node *op) +static ir_node *gen_Store(ir_node *node) { - if (mode_is_float(env->mode)) { - return new_bd_TEMPLATE_fMinus(env->dbg, env->block, op, env->mode); + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *ptr = get_Store_ptr(node); + ir_node *new_ptr = be_transform_node(ptr); + ir_node *val = get_Store_value(node); + ir_node *new_val = be_transform_node(val); + ir_node *mem = get_Store_mem(node); + ir_node *new_mem = be_transform_node(mem); + ir_mode *mode = get_irn_mode(node); + + if (mode_is_float(mode)) { + return new_bd_TEMPLATE_fStore(dbgi, new_block, new_ptr, new_val, new_mem, mode); } - return new_bd_TEMPLATE_Minus(env->dbg, env->block, op, env->mode); + return new_bd_TEMPLATE_Store(dbgi, new_block, new_ptr, new_mem, new_val, mode); } +static ir_node *gen_Jmp(ir_node *node) +{ + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + return new_bd_TEMPLATE_Jmp(dbgi, new_block); +} /** - * Transforms a Not node. - * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Not node - * @param op operator - * @param mode node mode - * @return the created TEMPLATE Not node + * returns true if mode should be stored in a general purpose register */ -static ir_node *gen_Not(TEMPLATE_transform_env_t *env, ir_node *op) +static inline bool mode_needs_gp_reg(ir_mode *mode) { - return new_bd_TEMPLATE_Not(env->dbg, env->block, op, env->mode); + return mode_is_int(mode) || mode_is_reference(mode); } +static ir_node *gen_Phi(ir_node *node) +{ + const arch_register_req_t *req; + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_mode *mode = get_irn_mode(node); + ir_graph *irg = get_irn_irg(node); + ir_node *phi; + + if (mode_needs_gp_reg(mode)) { + mode = mode_Iu; + req = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].class_req; + } else { + req = arch_no_register_req; + } + + phi = new_ir_node(dbgi, irg, new_block, op_Phi, mode, get_irn_arity(node), + get_irn_in(node)+1); + copy_node_attr(irg, node, phi); + be_duplicate_deps(node, phi); + arch_set_out_register_req(phi, 0, req); + be_enqueue_preds(node); + return phi; +} -/** - * Transforms a Load. - * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Load node - * @param mode node mode - * @return the created TEMPLATE Load node - */ -static ir_node *gen_Load(TEMPLATE_transform_env_t *env) +static ir_node *bad_transform(ir_node *node) { - ir_node *node = env->irn; - - if (mode_is_float(env->mode)) { - return new_bd_TEMPLATE_fLoad(env->dbg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode); - } - return new_bd_TEMPLATE_Load(env->dbg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode); + panic("TEMPLATE backend: unexpected node %+F", node); } -/** - * Transforms a Store. - * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Store node - * @param mode node mode - * @return the created TEMPLATE Store node - */ -static ir_node *gen_Store(TEMPLATE_transform_env_t *env) +static void set_transformer(ir_op *op, be_transform_func transform_func) { - ir_node *node = env->irn; - - if (mode_is_float(env->mode)) { - return new_bd_TEMPLATE_fStore(env->dbg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode); - } - return new_bd_TEMPLATE_Store(env->dbg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode); + op->ops.generic = (op_func)transform_func; } -static ir_node *gen_Jmp(TEMPLATE_transform_env_t *env) +static void TEMPLATE_register_transformers(void) { - return new_bd_TEMPLATE_Jmp(env->dbg, env->block); + /* first clear the generic function pointer for all ops */ + clear_irp_opcodes_generic_func(); + + set_transformer(op_Add, gen_Add); + set_transformer(op_And, gen_And); + set_transformer(op_Const, gen_Const); + set_transformer(op_Eor, gen_Eor); + set_transformer(op_Jmp, gen_Jmp); + set_transformer(op_Load, gen_Load); + set_transformer(op_Minus, gen_Minus); + set_transformer(op_Mul, gen_Mul); + set_transformer(op_Not, gen_Not); + set_transformer(op_Or, gen_Or); + set_transformer(op_Phi, gen_Phi); + set_transformer(op_Quot, gen_Quot); + set_transformer(op_Shl, gen_Shl); + set_transformer(op_Shr, gen_Shr); + set_transformer(op_Store, gen_Store); + set_transformer(op_Sub, gen_Sub); + + /* TODO: implement missing nodes */ + + + /* you should not see the following nodes */ + set_transformer(op_ASM, bad_transform); + set_transformer(op_Builtin, bad_transform); + set_transformer(op_CallBegin, bad_transform); + set_transformer(op_Cast, bad_transform); + set_transformer(op_Confirm, bad_transform); + set_transformer(op_DivMod, bad_transform); + set_transformer(op_EndExcept, bad_transform); + set_transformer(op_EndReg, bad_transform); + set_transformer(op_Filter, bad_transform); + set_transformer(op_Free, bad_transform); + set_transformer(op_Id, bad_transform); + set_transformer(op_InstOf, bad_transform); + set_transformer(op_Mulh, bad_transform); + set_transformer(op_Mux, bad_transform); + set_transformer(op_Raise, bad_transform); + set_transformer(op_Sel, bad_transform); + set_transformer(op_Tuple, bad_transform); } - - - /** - * Transforms the given firm node (and maybe some other related nodes) - * into one or more assembler nodes. - * - * @param node the firm node - * @param env the debug module + * Transform generic IR-nodes into TEMPLATE machine instructions */ -void TEMPLATE_transform_node(ir_node *node, void *env) +void TEMPLATE_transform_graph(TEMPLATE_code_gen_t *cg) { - ir_opcode code = get_irn_opcode(node); - ir_node *asm_node = NULL; - TEMPLATE_transform_env_t tenv; - (void) env; - - if (is_Block(node)) - return; - - tenv.block = get_nodes_block(node); - tenv.dbg = get_irn_dbg_info(node); - tenv.irg = current_ir_graph; - tenv.irn = node; - tenv.mode = get_irn_mode(node); - -#define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break -#define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break -#define GEN(a) case iro_##a: asm_node = gen_##a(&tenv); break -#define IGN(a) case iro_##a: break -#define BAD(a) case iro_##a: goto bad - - DBG((dbg, LEVEL_1, "check %+F ... ", node)); - - switch (code) { - BINOP(Add); - BINOP(Mul); - BINOP(And); - BINOP(Or); - BINOP(Eor); - - BINOP(Sub); - BINOP(Shl); - BINOP(Shr); - BINOP(Quot); - - - UNOP(Minus); - UNOP(Not); - - GEN(Load); - GEN(Store); - GEN(Jmp); - - /* TODO: implement these nodes */ - IGN(Shrs); - IGN(Div); - IGN(Mod); - IGN(DivMod); - IGN(Const); - IGN(SymConst); - IGN(Conv); - IGN(Abs); - IGN(Cond); - IGN(Mux); - IGN(Mulh); - IGN(CopyB); - IGN(Unknown); - IGN(Cmp); - - /* You probably don't need to handle the following nodes */ - - IGN(Call); - IGN(Proj); - IGN(Alloc); - - IGN(Block); - IGN(Start); - IGN(End); - IGN(NoMem); - IGN(Phi); - IGN(IJmp); - IGN(Break); - IGN(Sync); - - BAD(Raise); - BAD(Sel); - BAD(InstOf); - BAD(Cast); - BAD(Free); - BAD(Tuple); - BAD(Id); - BAD(Bad); - BAD(Confirm); - BAD(Filter); - BAD(CallBegin); - BAD(EndReg); - BAD(EndExcept); - - default: - break; -bad: - fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node)); - assert(0); - } - - if (asm_node) { - exchange(node, asm_node); - DB((dbg, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node)); - } else { - DB((dbg, LEVEL_1, "ignored\n")); - } + TEMPLATE_register_transformers(); + be_transform_graph(cg->irg, NULL); } void TEMPLATE_init_transform(void) diff --git a/ir/be/TEMPLATE/TEMPLATE_transform.h b/ir/be/TEMPLATE/TEMPLATE_transform.h index 8afd51a2f..e72b03035 100644 --- a/ir/be/TEMPLATE/TEMPLATE_transform.h +++ b/ir/be/TEMPLATE/TEMPLATE_transform.h @@ -27,6 +27,6 @@ void TEMPLATE_init_transform(void); -void TEMPLATE_transform_node(ir_node *node, void *env); +void TEMPLATE_transform_graph(TEMPLATE_code_gen_t *cg); #endif diff --git a/ir/be/TEMPLATE/bearch_TEMPLATE.c b/ir/be/TEMPLATE/bearch_TEMPLATE.c index 81b249acc..f0fa0f748 100644 --- a/ir/be/TEMPLATE/bearch_TEMPLATE.c +++ b/ir/be/TEMPLATE/bearch_TEMPLATE.c @@ -115,7 +115,8 @@ static void TEMPLATE_prepare_graph(void *self) { TEMPLATE_code_gen_t *cg = self; - irg_walk_blkwise_graph(cg->irg, NULL, TEMPLATE_transform_node, cg); + /* transform nodes into assembler instructions */ + TEMPLATE_transform_graph(cg); } @@ -155,7 +156,7 @@ static void TEMPLATE_emit_and_done(void *self) TEMPLATE_code_gen_t *cg = self; ir_graph *irg = cg->irg; - TEMPLATE_gen_routine(cg, irg); + TEMPLATE_emit_routine(irg); /* de-allocate code generator */ free(cg); @@ -187,7 +188,6 @@ static void *TEMPLATE_cg_init(be_irg_t *birg) cg->impl = &TEMPLATE_code_gen_if; cg->irg = be_get_birg_irg(birg); cg->isa = isa; - cg->birg = birg; return (arch_code_generator_t *)cg; } diff --git a/ir/be/TEMPLATE/bearch_TEMPLATE_t.h b/ir/be/TEMPLATE/bearch_TEMPLATE_t.h index 8ae81ecd8..59d842820 100644 --- a/ir/be/TEMPLATE/bearch_TEMPLATE_t.h +++ b/ir/be/TEMPLATE/bearch_TEMPLATE_t.h @@ -39,7 +39,6 @@ struct TEMPLATE_code_gen_t { const arch_code_generator_if_t *impl; /**< implementation */ ir_graph *irg; /**< current irg */ TEMPLATE_isa_t *isa; /**< the isa instance */ - const be_irg_t *birg; /**< The be-irg (contains additional information about the irg) */ }; struct TEMPLATE_isa_t { diff --git a/ir/be/amd64/amd64_emitter.c b/ir/be/amd64/amd64_emitter.c index dc50f1cbe..9a9c36b18 100644 --- a/ir/be/amd64/amd64_emitter.c +++ b/ir/be/amd64/amd64_emitter.c @@ -272,7 +272,7 @@ void amd64_gen_routine(const amd64_code_gen_t *cg, ir_graph *irg) /* register all emitter functions */ amd64_register_emitters(); - blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq); + blk_sched = be_create_block_schedule(irg); be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi)); be_gas_emit_function_prolog(entity, 4); diff --git a/ir/be/amd64/amd64_transform.c b/ir/be/amd64/amd64_transform.c index 2dea3ccb3..577f6b740 100644 --- a/ir/be/amd64/amd64_transform.c +++ b/ir/be/amd64/amd64_transform.c @@ -137,7 +137,7 @@ void amd64_transform_graph(amd64_code_gen_t *cg) { amd64_register_transformers(); env_cg = cg; - be_transform_graph(cg->birg, amd64_pretransform_node); + be_transform_graph(cg->irg, amd64_pretransform_node); } void amd64_init_transform(void) diff --git a/ir/be/arm/arm_emitter.c b/ir/be/arm/arm_emitter.c index 5f26f3f96..11fe8a3bf 100644 --- a/ir/be/arm/arm_emitter.c +++ b/ir/be/arm/arm_emitter.c @@ -1116,8 +1116,8 @@ void arm_gen_routine(const arm_code_gen_t *arm_cg, ir_graph *irg) be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi)); - /* create the block schedule. For now, we don't need it earlier. */ - blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq); + /* create the block schedule */ + blk_sched = be_create_block_schedule(irg); be_gas_emit_function_prolog(entity, 4); diff --git a/ir/be/arm/arm_transform.c b/ir/be/arm/arm_transform.c index 0829ed8a2..96353fb2c 100644 --- a/ir/be/arm/arm_transform.c +++ b/ir/be/arm/arm_transform.c @@ -1507,7 +1507,7 @@ static ir_node *gen_Phi(ir_node *node) */ static ir_node *bad_transform(ir_node *irn) { - panic("ARM backend: Not implemented: %+F", irn); + panic("ARM backend: unexpected node %+F", irn); } /** @@ -1577,13 +1577,6 @@ static void arm_register_transformers(void) set_transformer(op_Tuple, bad_transform); } -/** - * Pre-transform all unknown nodes. - */ -static void arm_pretransform_node(void) -{ -} - /** * Initialize fpa Immediate support. */ @@ -1631,7 +1624,7 @@ void arm_transform_graph(arm_code_gen_t *cg) } arm_register_transformers(); env_cg = cg; - be_transform_graph(cg->birg, arm_pretransform_node); + be_transform_graph(cg->irg, NULL); } void arm_init_transform(void) diff --git a/ir/be/beblocksched.c b/ir/be/beblocksched.c index ecf3884e5..f8c19c1e3 100644 --- a/ir/be/beblocksched.c +++ b/ir/be/beblocksched.c @@ -745,8 +745,11 @@ void be_init_blocksched(void) FIRM_DBG_REGISTER(dbg, "firm.be.blocksched"); } -ir_node **be_create_block_schedule(ir_graph *irg, ir_exec_freq *execfreqs) +ir_node **be_create_block_schedule(ir_graph *irg) { + const be_irg_t *birg = be_birg_from_irg(irg); + ir_exec_freq *execfreqs = be_get_birg_exec_freq(birg); + switch (algo) { case BLOCKSCHED_GREEDY: case BLOCKSCHED_NAIV: diff --git a/ir/be/beblocksched.h b/ir/be/beblocksched.h index 13b84576c..460a0a860 100644 --- a/ir/be/beblocksched.h +++ b/ir/be/beblocksched.h @@ -29,6 +29,6 @@ #include "firm_types.h" -ir_node **be_create_block_schedule(ir_graph *irg, ir_exec_freq *execfreqs); +ir_node **be_create_block_schedule(ir_graph *irg); -#endif /* FIRM_BE_BEBLOCKSCHED_H */ +#endif diff --git a/ir/be/betranshlp.c b/ir/be/betranshlp.c index f5a6d65ee..b79d3fa1f 100644 --- a/ir/be/betranshlp.c +++ b/ir/be/betranshlp.c @@ -396,12 +396,12 @@ static ir_node *gen_End(ir_node *node) return new_end; } -void be_transform_graph(be_irg_t *birg, arch_pretrans_nodes *func) +void be_transform_graph(ir_graph *irg, arch_pretrans_nodes *func) { - ir_graph *irg = birg->irg; ir_graph *old_current_ir_graph = current_ir_graph; struct obstack *old_obst = NULL; struct obstack *new_obst = NULL; + be_irg_t *birg = be_birg_from_irg(irg); current_ir_graph = irg; diff --git a/ir/be/betranshlp.h b/ir/be/betranshlp.h index e0be48a95..2c269efc9 100644 --- a/ir/be/betranshlp.h +++ b/ir/be/betranshlp.h @@ -82,6 +82,6 @@ void be_enqueue_preds(ir_node *node); /** * Transform a graph. Transformers must be registered first. */ -void be_transform_graph(be_irg_t *birg, arch_pretrans_nodes *func); +void be_transform_graph(ir_graph *irg, arch_pretrans_nodes *func); -#endif /* FIRM_BE_BETRANSHLP_H */ +#endif diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index ba40feef0..1228eac7b 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -1420,7 +1420,7 @@ static void ia32_finish(void *self) /* create block schedule, this also removes empty blocks which might * produce critical edges */ - cg->blk_sched = be_create_block_schedule(irg, cg->birg->exec_freq); + cg->blk_sched = be_create_block_schedule(irg); } /** diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 2b31c4fff..dc011d044 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -5979,7 +5979,7 @@ void ia32_transform_graph(ia32_code_gen_t *cg) call_list = NEW_ARR_F(ir_node *, 0); call_types = NEW_ARR_F(ir_type *, 0); - be_transform_graph(cg->birg, ia32_pretransform_node); + be_transform_graph(cg->irg, ia32_pretransform_node); if (ia32_cg_config.use_sse2) postprocess_fp_call_results(); diff --git a/ir/be/mips/bearch_mips.c b/ir/be/mips/bearch_mips.c index df2a16f54..47ffc82b8 100644 --- a/ir/be/mips/bearch_mips.c +++ b/ir/be/mips/bearch_mips.c @@ -221,7 +221,7 @@ static void mips_finish_irg(void *self) /* create block schedule, this also removes empty blocks which might * produce critical edges */ - cg->block_schedule = be_create_block_schedule(irg, cg->birg->exec_freq); + cg->block_schedule = be_create_block_schedule(irg); dump_ir_block_graph_sched(irg, "-mips-finished"); } diff --git a/ir/be/mips/mips_transform.c b/ir/be/mips/mips_transform.c index d1ba5a55f..5af7c24f8 100644 --- a/ir/be/mips/mips_transform.c +++ b/ir/be/mips/mips_transform.c @@ -1138,7 +1138,7 @@ static void register_transformers(void) void mips_transform_graph(mips_code_gen_t *cg) { register_transformers(); - be_transform_graph(cg->birg, NULL); + be_transform_graph(cg->irg, NULL); } /** diff --git a/ir/be/ppc32/bearch_ppc32.c b/ir/be/ppc32/bearch_ppc32.c index adb00bdcc..19f0a6e3c 100644 --- a/ir/be/ppc32/bearch_ppc32.c +++ b/ir/be/ppc32/bearch_ppc32.c @@ -322,7 +322,7 @@ static void ppc32_finish_irg(void *self) static void ppc32_before_ra(void *self) { ppc32_code_gen_t *cg = self; - cg->blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq); + cg->blk_sched = be_create_block_schedule(cg->irg); } static void ppc32_transform_spill(ir_node *node, void *env) diff --git a/ir/be/sparc/sparc_emitter.c b/ir/be/sparc/sparc_emitter.c index dbf2c0608..3951c21b9 100644 --- a/ir/be/sparc/sparc_emitter.c +++ b/ir/be/sparc/sparc_emitter.c @@ -738,7 +738,7 @@ void sparc_gen_routine(const sparc_code_gen_t *cg, ir_graph *irg) be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi)); /* create the block schedule. For now, we don't need it earlier. */ - blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq); + blk_sched = be_create_block_schedule(irg); // emit function prolog sparc_emit_func_prolog(irg); diff --git a/ir/be/sparc/sparc_transform.c b/ir/be/sparc/sparc_transform.c index 066c9a615..6c2832e6c 100644 --- a/ir/be/sparc/sparc_transform.c +++ b/ir/be/sparc/sparc_transform.c @@ -1052,7 +1052,7 @@ void sparc_transform_graph(sparc_code_gen_t *cg) { sparc_register_transformers(); env_cg = cg; - be_transform_graph(cg->birg, sparc_pretransform_node); + be_transform_graph(cg->irg, sparc_pretransform_node); } void sparc_init_transform(void)