#include "../besched.h"
#include "../begnuas.h"
+#include "../beblocksched.h"
+#include "../benode.h"
#include "TEMPLATE_emitter.h"
#include "gen_TEMPLATE_emitter.h"
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)
/**
* 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 *);
* 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");
}
}
-
-/**
- * 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)
*/
/**
* 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);
}
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
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);
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 */
};
$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:
#
{ 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 },
{ name => "f13", type => 1 },
{ name => "f14", type => 1 },
{ name => "f15", type => 1 },
- { mode => "mode_D" }
+ { mode => $mode_fp }
]
);
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
irn_flags => "R",
state => "exc_pinned",
reg_req => { in => [ "gp", "none" ], out => [ "gp" ] },
- emit => '. mov (%S1), %D1'
+ emit => '. mov (%S1), %D1',
},
Store => {
irn_flags => "R",
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ] },
- emit => '. movl %S2, (%S1)'
+ emit => '. movl %S2, (%S1)',
},
# Floating Point operations
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 => {
'
/* TODO: compare fConst attributes */
return 1;
-'
+',
+ mode => $mode_fp,
},
# Load / Store
irn_flags => "R",
state => "exc_pinned",
reg_req => { in => [ "gp", "none" ], out => [ "fp" ] },
- emit => '. fmov (%S1), %D1'
+ emit => '. fmov (%S1), %D1',
},
fStore => {
irn_flags => "R",
state => "exc_pinned",
reg_req => { in => [ "gp", "fp", "none" ] },
- emit => '. fmov %S2, (%S1)'
+ emit => '. fmov %S2, (%S1)',
},
);
#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"
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)
void TEMPLATE_init_transform(void);
-void TEMPLATE_transform_node(ir_node *node, void *env);
+void TEMPLATE_transform_graph(TEMPLATE_code_gen_t *cg);
#endif
{
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);
}
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);
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;
}
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 {
/* 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);
{
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)
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);
*/
static ir_node *bad_transform(ir_node *irn)
{
- panic("ARM backend: Not implemented: %+F", irn);
+ panic("ARM backend: unexpected node %+F", irn);
}
/**
set_transformer(op_Tuple, bad_transform);
}
-/**
- * Pre-transform all unknown nodes.
- */
-static void arm_pretransform_node(void)
-{
-}
-
/**
* Initialize fpa Immediate support.
*/
}
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)
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:
#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
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;
/**
* 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
/* 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);
}
/**
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();
/* 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");
}
void mips_transform_graph(mips_code_gen_t *cg)
{
register_transformers();
- be_transform_graph(cg->birg, NULL);
+ be_transform_graph(cg->irg, NULL);
}
/**
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)
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);
{
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)