start register allocator again, fix typo
[libfirm] / ir / be / TEMPLATE / TEMPLATE_emitter.c
index 4a38e5f..3fe41fa 100644 (file)
@@ -15,6 +15,7 @@
 #include "irprintf.h"
 #include "irop_t.h"
 #include "irargs_t.h"
+#include "irprog.h"
 
 #include "../besched.h"
 
@@ -86,8 +87,6 @@ static const arch_register_t *get_out_reg(ir_node *irn, int pos) {
        ir_node                *proj;
        const arch_register_t  *reg = NULL;
 
-       assert(get_irn_n_edges(irn) > pos && "Invalid OUT position");
-
        /* 1st case: irn is not of mode_T, so it has only                 */
        /*           one OUT register -> good                             */
        /* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
@@ -168,8 +167,7 @@ static int TEMPLATE_get_reg_name(lc_appendable_t *app,
                buf = get_TEMPLATE_reg_name(X, nr, 0);
        }
 
-       lc_appendable_chadd(app, '%');
-       return lc_arg_append(app, occ, buf, strlen(buf));
+       return buf ? lc_arg_append(app, occ, buf, strlen(buf)) : 0;
 }
 
 /**
@@ -270,66 +268,49 @@ static char *get_cfop_target(const ir_node *irn, char *buf) {
  ***********************************************************************************/
 
 /**
- * Emits code for a node.
+ * Enters the emitter functions for handled nodes into the generic
+ * pointer of an opcode.
  */
-void TEMPLATE_emit_node(ir_node *irn, void *env) {
-       emit_env_t *emit_env   = env;
-       firm_dbg_module_t *mod = emit_env->mod;
-       FILE              *F   = emit_env->out;
-
-       DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
-
-#define BE_EMIT(a) if (is_TEMPLATE_##a(irn)) { emit_TEMPLATE_##a(irn, emit_env); return; }
-
-       BE_EMIT(Const);
-
-       BE_EMIT(Add);
-       BE_EMIT(Add_i);
-       BE_EMIT(Sub);
-       BE_EMIT(Sub_i);
-       BE_EMIT(Minus);
-       BE_EMIT(Inc);
-       BE_EMIT(Dec);
-
-       BE_EMIT(And);
-       BE_EMIT(And_i);
-       BE_EMIT(Or);
-       BE_EMIT(Or_i);
-       BE_EMIT(Eor);
-       BE_EMIT(Eor_i);
-       BE_EMIT(Not);
+static void TEMPLATE_register_emitters(void) {
 
-       BE_EMIT(Shl);
-       BE_EMIT(Shl_i);
-       BE_EMIT(Shr);
-       BE_EMIT(Shr_i);
-       BE_EMIT(RotL);
-       BE_EMIT(RotL_i);
-       BE_EMIT(RotR);
+/* 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
 
-       BE_EMIT(Mul);
-       BE_EMIT(Mul_i);
+       /* first clear the generic function pointer for all ops */
+       clear_irp_opcodes_generic_func();
 
-       BE_EMIT(Store);
-       BE_EMIT(Load);
+       /* register all emitter functions defined in spec */
+       TEMPLATE_register_spec_emitters();
 
-       /* generated floating point emitter */
-       BE_EMIT(fConst);
+       /* register addtional emitter functions if needed */
 
-       BE_EMIT(fAdd);
-       BE_EMIT(fSub);
-       BE_EMIT(fMinus);
+#undef TEMPLATE_EMIT
+#undef BE_EMIT
+#undef EMIT
+}
 
-       BE_EMIT(fMul);
-       BE_EMIT(fDiv);
 
-       BE_EMIT(fMin);
-       BE_EMIT(fMax);
+/**
+ * Emits code for a node.
+ */
+void TEMPLATE_emit_node(ir_node *irn, void *env) {
+       TEMPLATE_emit_env_t *emit_env = env;
+       FILE                *F        = emit_env->out;
+       ir_op               *op       = get_irn_op(irn);
+       DEBUG_ONLY(firm_dbg_module_t *mod = emit_env->mod;)
 
-       BE_EMIT(fLoad);
-       BE_EMIT(fStore);
+       DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
 
-       ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn);
+       if (op->ops.generic) {
+               void (*emit)(const ir_node *, void *) = (void (*)(const ir_node *, void *))op->ops.generic;
+               (*emit)(irn, env);
+       }
+       else {
+               ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn);
+       }
 }
 
 /**
@@ -337,12 +318,13 @@ void TEMPLATE_emit_node(ir_node *irn, void *env) {
  * and emits code for each node.
  */
 void TEMPLATE_gen_block(ir_node *block, void *env) {
+       TEMPLATE_emit_env_t *emit_env = env;
        ir_node *irn;
 
        if (! is_Block(block))
                return;
 
-       fprintf(((emit_env_t *)env)->out, "BLOCK_%ld:\n", get_irn_node_nr(block));
+       fprintf(emit_env->out, "BLOCK_%ld:\n", get_irn_node_nr(block));
        sched_foreach(block, irn) {
                TEMPLATE_emit_node(irn, env);
        }
@@ -352,7 +334,7 @@ void TEMPLATE_gen_block(ir_node *block, void *env) {
 /**
  * Emits code for function start.
  */
-void TEMPLATE_emit_start(FILE *F, ir_graph *irg) {
+void TEMPLATE_emit_func_prolog(FILE *F, ir_graph *irg) {
        const char *irg_name = get_entity_name(get_irg_entity(irg));
 
        /* TODO: emit function header */
@@ -361,7 +343,7 @@ void TEMPLATE_emit_start(FILE *F, ir_graph *irg) {
 /**
  * Emits code for function end
  */
-void TEMPLATE_emit_end(FILE *F, ir_graph *irg) {
+void TEMPLATE_emit_func_epilog(FILE *F, ir_graph *irg) {
        const char *irg_name = get_entity_name(get_irg_entity(irg));
 
        /* TODO: emit function end */
@@ -385,18 +367,21 @@ void TEMPLATE_gen_labels(ir_node *block, void *env) {
  * Main driver
  */
 void TEMPLATE_gen_routine(FILE *F, ir_graph *irg, const TEMPLATE_code_gen_t *cg) {
-       emit_env_t emit_env;
+       TEMPLATE_emit_env_t emit_env;
 
-       emit_env.mod      = firm_dbg_register("firm.be.TEMPLATE.emit");
        emit_env.out      = F;
        emit_env.arch_env = cg->arch_env;
        emit_env.cg       = cg;
+       FIRM_DBG_REGISTER(emit_env.mod, "firm.be.TEMPLATE.emit");
 
        /* set the global arch_env (needed by print hooks) */
        arch_env = cg->arch_env;
 
-       TEMPLATE_emit_start(F, irg);
+       /* register all emitter functions */
+       TEMPLATE_register_emitters();
+
+       TEMPLATE_emit_func_prolog(F, irg);
        irg_block_walk_graph(irg, TEMPLATE_gen_labels, NULL, &emit_env);
        irg_walk_blkwise_graph(irg, NULL, TEMPLATE_gen_block, &emit_env);
-       TEMPLATE_emit_end(F, irg);
+       TEMPLATE_emit_func_epilog(F, irg);
 }