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 */
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;
}
/**
***********************************************************************************/
/**
- * 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) {
+ 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);
+ }
}
/**
/**
* 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 */
/**
* 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 */
void TEMPLATE_gen_routine(FILE *F, ir_graph *irg, const TEMPLATE_code_gen_t *cg) {
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);
}