* @brief code selection (transform FIRM into TEMPLATE FIRM)
* @version $Id$
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
#include "irnode_t.h"
#include "irgraph_t.h"
#include "ircons.h"
#include "iropt_t.h"
#include "debug.h"
+#include "error.h"
-#include "../benode_t.h"
+#include "../benode.h"
+#include "../betranshlp.h"
#include "bearch_TEMPLATE_t.h"
#include "TEMPLATE_nodes_attr.h"
-#include "archop.h"
#include "TEMPLATE_transform.h"
#include "TEMPLATE_new_nodes.h"
-#include "TEMPLATE_map_regs.h"
#include "gen_TEMPLATE_regalloc_if.h"
-extern ir_op *get_op_Mulh(void);
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
+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)
+{
+ 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);
-/****************************************************************************************************
- * _ _ __ _ _
- * | | | | / _| | | (_)
- * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
- * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
- * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
- * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
- *
- ****************************************************************************************************/
-
-/**
- * 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) {
- return new_rd_TEMPLATE_Add(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ 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) {
- if (mode_is_float(env->mode)) {
- return new_rd_TEMPLATE_fMul(env->dbg, env->irg, env->block, op1, op2, env->mode);
- }
- else {
- return new_rd_TEMPLATE_Mul(env->dbg, env->irg, env->block, op1, op2, env->mode);
- }
+static ir_node *gen_And(ir_node *node)
+{
+ 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) {
- return new_rd_TEMPLATE_And(env->dbg, env->irg, env->block, op1, op2, env->mode);
+static ir_node *gen_Or(ir_node *node)
+{
+ return transform_binop(node, new_bd_TEMPLATE_Or);
}
-
-
-/**
- * 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) {
- return new_rd_TEMPLATE_Or(env->dbg, env->irg, env->block, op1, op2, env->mode);
+static ir_node *gen_Eor(ir_node *node)
+{
+ return transform_binop(node, new_bd_TEMPLATE_Xor);
}
+static ir_node *gen_Quot(ir_node *node)
+{
+ return transform_binop(node, new_bd_TEMPLATE_fDiv);
+}
-
-/**
- * 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) {
- return new_rd_TEMPLATE_Eor(env->dbg, env->irg, env->block, op1, op2, env->mode);
+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);
+}
+static ir_node *gen_Add(ir_node *node)
+{
+ ir_mode *mode = get_irn_mode(node);
-/**
- * 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) {
- if (mode_is_float(env->mode)) {
- return new_rd_TEMPLATE_fSub(env->dbg, env->irg, env->block, op1, op2, env->mode);
- }
- else {
- return new_rd_TEMPLATE_Sub(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ 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);
-
-/**
- * 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) {
- return new_rd_TEMPLATE_fDiv(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ if (mode_is_float(mode)) {
+ return transform_binop(node, new_bd_TEMPLATE_fSub);
+ }
+ return transform_binop(node, new_bd_TEMPLATE_Sub);
}
+static ir_node *gen_Mul(ir_node *node)
+{
+ ir_mode *mode = get_irn_mode(node);
-
-/**
- * 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) {
- return new_rd_TEMPLATE_Shl(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ 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 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_rd_TEMPLATE_Shr(env->dbg, env->irg, env->block, op1, op2, env->mode);
-}
+static ir_node *transform_unop(ir_node *node, new_unop_func new_func)
+{
+ 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);
-/**
- * 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) {
- if (mode_is_float(env->mode)) {
- return new_rd_TEMPLATE_fMinus(env->dbg, env->irg, env->block, op, env->mode);
+ if (mode_is_float(mode)) {
+ return transform_unop(node, new_bd_TEMPLATE_fMinus);
}
- return new_rd_TEMPLATE_Minus(env->dbg, env->irg, env->block, op, env->mode);
+ return transform_unop(node, new_bd_TEMPLATE_Minus);
}
+static ir_node *gen_Not(ir_node *node)
+{
+ 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;
-/**
- * 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
- */
-static ir_node *gen_Not(TEMPLATE_transform_env_t *env, ir_node *op) {
- return new_rd_TEMPLATE_Not(env->dbg, env->irg, env->block, op, env->mode);
-}
+ result = new_bd_TEMPLATE_Const(dbgi, new_block, value);
+ /* make sure the node does not float above the barrier into the prologue */
+ be_dep_on_frame(result);
+ return result;
+}
-/**
- * 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) {
- ir_node *node = env->irn;
+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);
+}
- if (mode_is_float(env->mode)) {
- return new_rd_TEMPLATE_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
+static ir_node *gen_Store(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_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_rd_TEMPLATE_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), 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 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
+ * returns true if mode should be stored in a general purpose register
*/
-static ir_node *gen_Store(TEMPLATE_transform_env_t *env) {
- ir_node *node = env->irn;
-
- if (mode_is_float(env->mode)) {
- return new_rd_TEMPLATE_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
- }
- return new_rd_TEMPLATE_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
+static inline bool mode_needs_gp_reg(ir_mode *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);
-/*********************************************************
- * _ _ _
- * (_) | | (_)
- * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
- * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
- * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
- * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
- *
- *********************************************************/
-
+ arch_set_out_register_req(phi, 0, req);
+ be_enqueue_preds(node);
+ return phi;
+}
+static void TEMPLATE_register_transformers(void)
+{
+ be_start_transform_setup();
+
+ be_set_transform_function(op_Add, gen_Add);
+ be_set_transform_function(op_And, gen_And);
+ be_set_transform_function(op_Const, gen_Const);
+ be_set_transform_function(op_Eor, gen_Eor);
+ be_set_transform_function(op_Jmp, gen_Jmp);
+ be_set_transform_function(op_Load, gen_Load);
+ be_set_transform_function(op_Minus, gen_Minus);
+ be_set_transform_function(op_Mul, gen_Mul);
+ be_set_transform_function(op_Not, gen_Not);
+ be_set_transform_function(op_Or, gen_Or);
+ be_set_transform_function(op_Phi, gen_Phi);
+ be_set_transform_function(op_Quot, gen_Quot);
+ be_set_transform_function(op_Shl, gen_Shl);
+ be_set_transform_function(op_Shr, gen_Shr);
+ be_set_transform_function(op_Store, gen_Store);
+ be_set_transform_function(op_Sub, gen_Sub);
+}
/**
- * 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) {
-#ifdef DEBUG_libfirm
- TEMPLATE_code_gen_t *cgenv = (TEMPLATE_code_gen_t *)env;
-#endif
- 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;
-#ifdef DEBUG_libfirm
- tenv.mod = cgenv->mod;
-#endif
- 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((tenv.mod, 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);
-
- /* 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(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(Jmp);
- 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:
- if (get_irn_op(node) == get_op_Max() ||
- get_irn_op(node) == get_op_Min() ||
- is_Mulh(node))
- {
- /* TODO: implement */
- /* ignore for now */
- }
- break;
-bad:
- fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
- assert(0);
- }
+void TEMPLATE_transform_graph(TEMPLATE_code_gen_t *cg)
+{
+ TEMPLATE_register_transformers();
+ be_transform_graph(cg->irg, NULL);
+}
- if (asm_node) {
- exchange(node, asm_node);
- DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
- }
- else {
- DB((tenv.mod, LEVEL_1, "ignored\n"));
- }
+void TEMPLATE_init_transform(void)
+{
+ FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.transform");
}