X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fmips%2Fmips_emitter.c;h=6a1ea258907955131b89b961bda5fe168ebf64d7;hb=9e56dbf066d3698df877e2a9f78caeca29ea5a03;hp=a46d66ccca5f41a604a87ec1c9e05de1b0fb6073;hpb=116626f38b827a9bd32d74764acd1fd016392a00;p=libfirm diff --git a/ir/be/mips/mips_emitter.c b/ir/be/mips/mips_emitter.c index a46d66ccc..6a1ea2589 100644 --- a/ir/be/mips/mips_emitter.c +++ b/ir/be/mips/mips_emitter.c @@ -62,19 +62,19 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) static const arch_register_t *get_in_reg(const arch_env_t *arch_env, const ir_node *node, int pos) { - ir_node *op; - const arch_register_t *reg = NULL; + ir_node *op; + const arch_register_t *reg = NULL; - assert(get_irn_arity(node) > pos && "Invalid IN position"); + assert(get_irn_arity(node) > pos && "Invalid IN position"); - /* The out register of the operator at position pos is the - in register we need. */ - op = get_irn_n(node, pos); + /* The out register of the operator at position pos is the + in register we need. */ + op = get_irn_n(node, pos); - reg = arch_get_irn_register(arch_env, op); + reg = arch_get_irn_register(arch_env, op); - assert(reg && "no in register found"); - return reg; + assert(reg && "no in register found"); + return reg; } /** @@ -83,33 +83,33 @@ static const arch_register_t *get_in_reg(const arch_env_t *arch_env, static const arch_register_t *get_out_reg(const arch_env_t *arch_env, const ir_node *node, int pos) { - ir_node *proj; - const arch_register_t *reg = NULL; + ir_node *proj; + const arch_register_t *reg = NULL; - /* 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 */ - /* Proj with the corresponding projnum for the register */ + /* 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 */ + /* Proj with the corresponding projnum for the register */ - if (get_irn_mode(node) != mode_T) { - reg = arch_get_irn_register(arch_env, node); - } else if (is_mips_irn(node)) { - reg = get_mips_out_reg(node, pos); - } else { - const ir_edge_t *edge; - - foreach_out_edge(node, edge) { - proj = get_edge_src_irn(edge); - assert(is_Proj(proj) && "non-Proj from mode_T node"); - if (get_Proj_proj(proj) == pos) { - reg = arch_get_irn_register(arch_env, proj); - break; - } - } - } + if (get_irn_mode(node) != mode_T) { + reg = arch_get_irn_register(arch_env, node); + } else if (is_mips_irn(node)) { + reg = get_mips_out_reg(node, pos); + } else { + const ir_edge_t *edge; + + foreach_out_edge(node, edge) { + proj = get_edge_src_irn(edge); + assert(is_Proj(proj) && "non-Proj from mode_T node"); + if (get_Proj_proj(proj) == pos) { + reg = arch_get_irn_register(arch_env, proj); + break; + } + } + } - assert(reg && "no out register found"); - return reg; + assert(reg && "no out register found"); + return reg; } /************************************************************* @@ -123,17 +123,25 @@ static const arch_register_t *get_out_reg(const arch_env_t *arch_env, * |_| |_| *************************************************************/ +/** + * Emit the name of the source register at given input position. + */ void mips_emit_source_register(mips_emit_env_t *env, const ir_node *node, int pos) { const arch_register_t *reg = get_in_reg(env->arch_env, node, pos); + be_emit_char(env->emit, '$'); be_emit_string(env->emit, arch_register_get_name(reg)); } +/** + * Emit the name of the destination register at given output position. + */ void mips_emit_dest_register(mips_emit_env_t *env, const ir_node *node, int pos) { const arch_register_t *reg = get_out_reg(env->arch_env, node, pos); + be_emit_char(env->emit, '$'); be_emit_string(env->emit, arch_register_get_name(reg)); } @@ -223,11 +231,13 @@ static const char *node_const_to_str(ir_node *n) void mips_emit_immediate(mips_emit_env_t *env, const ir_node *node) { - const mips_attr_t *attr; + const mips_attr_t *attr = get_mips_attr_const(node); - be_emit_char(env->emit, '$'); - attr = get_mips_attr(node); - be_emit_tarval(env->emit, attr->tv); + if(attr->tv != NULL) { + be_emit_tarval(env->emit, attr->tv); + } else { + be_emit_cstring(env->emit, "/* TODO */ 0"); + } } /* @@ -294,7 +304,7 @@ void mips_emit_nops(mips_emit_env_t *env, int n) } } -static void mips_emit_Perm(const ir_node *node, mips_emit_env_t *env) +static void mips_emit_Perm(mips_emit_env_t *env, const ir_node *node) { assert(get_irn_arity(node) == 2); @@ -329,29 +339,6 @@ static void mips_emit_Perm(const ir_node *node, mips_emit_env_t *env) /* mips_emit_nops(env, 3); */ } - -static void mips_emit_Spill(mips_emit_env_t *env, const ir_node *node) -{ -#if 0 - FILE *F = env->out; - ir_entity *ent = be_get_frame_entity(node); - - lc_efprintf(mips_get_arg_env(), F, "\tsw %1S, %d($fp)\n", node, get_entity_offset(ent)); -#endif - /* TODO lower spills and don't emit them... */ -} - -static void mips_emit_Reload(mips_emit_env_t *env, const ir_node *node) -{ -#if 0 - FILE *F = env->out; - ir_entity *ent = be_get_frame_entity(node); - - lc_efprintf(mips_get_arg_env(), F, "\tlw %1D, %d($fp)\n", node, get_entity_offset(ent)); -#endif - /* TODO lower reloads instead of emitting them... */ -} - /************************************************************************/ /* Calls */ /************************************************************************/ @@ -365,7 +352,7 @@ static void mips_emit_Call(mips_emit_env_t *env, const ir_node *node) /* call of immediate value (label) */ callee = be_Call_get_entity(node); if(callee != NULL) { - be_emit_ident(env->emit, get_entity_ident(callee)); + be_emit_ident(env->emit, get_entity_ld_ident(callee)); } else { mips_emit_source_register(env, node, be_pos_Call_ptr); } @@ -389,10 +376,13 @@ const char* mips_get_block_label(const ir_node* block) return buf; } +/** + * Emits a block label from the given block. + */ static void mips_emit_block_label(mips_emit_env_t *env, const ir_node *block) { - be_emit_irprintf(env->emit, "BLOCK_%ld", get_irn_node_nr(block)); + be_emit_irprintf(env->emit, "BLOCK_%d", get_irn_node_nr(block)); } static void mips_emit_Jump(mips_emit_env_t *env, const ir_node *node) @@ -405,7 +395,7 @@ static void mips_emit_Jump(mips_emit_env_t *env, const ir_node *node) be_emit_finish_line_gas(env->emit, node); } -ir_node *mips_get_jump_block(const ir_node* node, int projn) +ir_node *mips_get_jump_block(const ir_node* node, long projn) { const ir_edge_t *oute; for(oute = get_irn_out_edge_first(node); oute != NULL; @@ -422,7 +412,8 @@ ir_node *mips_get_jump_block(const ir_node* node, int projn) return NULL; } -void mips_emit_jump_target_proj(mips_emit_env_t *env, const ir_node *node, int projn) +void mips_emit_jump_target_proj(mips_emit_env_t *env, const ir_node *node, + long projn) { ir_node *jumpblock = mips_get_jump_block(node, projn); assert(jumpblock != NULL); @@ -438,13 +429,24 @@ void mips_emit_jump_target(mips_emit_env_t *env, const ir_node *node) mips_emit_block_label(env, jumpblock); } +void mips_emit_jump_or_fallthrough(mips_emit_env_t *env, const ir_node *node, + long pn) +{ + ir_node *jumpblock = mips_get_jump_block(node, pn); + assert(jumpblock != NULL); + + /* TODO: use fallthrough when possible */ + be_emit_cstring(env->emit, "b "); + mips_emit_block_label(env, jumpblock); +} + /************************************************************************ - * ____ _ _ _ _ * - * / ___|_ _(_) |_ ___| |__ | |_ _ _ __ ___ _ __ * - * \___ \ \ /\ / / | __/ __| '_ \ _ | | | | | '_ ` _ \| '_ \ * - * ___) \ V V /| | || (__| | | | |_| | |_| | | | | | | |_) | * - * |____/ \_/\_/ |_|\__\___|_| |_|\___/ \__,_|_| |_| |_| .__/ * - * |_| * + * ____ _ _ _ _ * + * / ___|_ _(_) |_ ___| |__ | |_ _ _ __ ___ _ __ * + * \___ \ \ /\ / / | __/ __| '_ \ _ | | | | | '_ ` _ \| '_ \ * + * ___) \ V V /| | || (__| | | | |_| | |_| | | | | | | |_) | * + * |____/ \_/\_/ |_|\__\___|_| |_|\___/ \__,_|_| |_| |_| .__/ * + * |_| * * * ************************************************************************/ @@ -490,11 +492,11 @@ const char* mips_get_jumptbl_label(const ir_node* switchjmp) * possible otherwise a cmp-jmp cascade). Stolen from ia32 */ void emit_mips_jump_table(mips_emit_env_t *env, const ir_node *irn) { - int lastval, i, i2, pn; - jmp_tbl_t tbl; - ir_node *proj; - const ir_edge_t *edge; - mips_attr_t *attr = get_mips_attr(irn); + int lastval, i, i2, pn; + jmp_tbl_t tbl; + ir_node *proj; + const ir_edge_t *edge; + const mips_attr_t *attr = get_mips_attr_const(irn); /* fill the table structure */ tbl.label = xmalloc(SNPRINTF_BUF_LEN); @@ -536,7 +538,7 @@ void emit_mips_jump_table(mips_emit_env_t *env, const ir_node *irn) { for(i2 = lastval + 1; i2 < value; ++i2) { be_emit_cstring(env->emit, "\t.word "); - be_emit_ident(env->emit, attr->symconst_id); + be_emit_ident(env->emit, get_entity_ld_ident(attr->symconst)); be_emit_char(env->emit, '\n'); be_emit_write_line(env->emit); } @@ -582,20 +584,34 @@ void dump_jump_tables(ir_node* node, void *data) * ***********************************************************************************/ -static void mips_emit_nothing(ir_mode *mode, mips_emit_env_t *env) +static void mips_emit_nothing(mips_emit_env_t *env, const ir_node *node) { + (void) env; + (void) node; } -static void mips_emit_this_shouldnt_happen(ir_mode *mode, mips_emit_env_t *env) +static void mips_emit_this_shouldnt_happen(mips_emit_env_t *env, const ir_node *node) { - assert(0); + (void) env; + panic("Found non-lowered node %+F while emitting", node); +} + +/** + * The type of a emitter function. + */ +typedef void (*emit_func) (mips_emit_env_t *, const ir_node *); + +/** + * Set a node emitter. Make it a bit more type safe. + */ +static void register_emitter(ir_op *op, emit_func func) { + op->ops.generic = (op_func) func; } /** * Register emitter functions for mips backend */ -void mips_register_emitters(void) -{ +void mips_register_emitters(void) { /* first clear the generic function pointer for all ops */ clear_irp_opcodes_generic_func(); @@ -603,28 +619,29 @@ void mips_register_emitters(void) mips_register_spec_emitters(); /* benode emitter */ - op_be_IncSP->ops.generic = (op_func) mips_emit_IncSP; - op_be_SetSP->ops.generic = (op_func) mips_emit_this_shouldnt_happen; - op_be_AddSP->ops.generic = (op_func) mips_emit_this_shouldnt_happen; - op_be_Call->ops.generic = (op_func) mips_emit_Call; - op_be_Keep->ops.generic = (op_func) mips_emit_nothing; - op_be_Copy->ops.generic = (op_func) mips_emit_Copy; - op_be_Return->ops.generic = (op_func) mips_emit_Return; - op_be_RegParams->ops.generic = (op_func) mips_emit_nothing; - op_be_Spill->ops.generic = (op_func) mips_emit_Spill; - op_be_Reload->ops.generic = (op_func) mips_emit_Reload; - op_be_Perm->ops.generic = (op_func) mips_emit_Perm; - - op_Start->ops.generic = (op_func) mips_emit_nothing; - op_Proj->ops.generic = (op_func) mips_emit_nothing; - op_SymConst->ops.generic = (op_func) mips_emit_nothing; - op_Jmp->ops.generic = (op_func) mips_emit_Jump; - op_Cmp->ops.generic = (op_func) mips_emit_this_shouldnt_happen; - op_Cond->ops.generic = (op_func) mips_emit_this_shouldnt_happen; + register_emitter(op_be_IncSP, mips_emit_IncSP); + register_emitter(op_be_SetSP, mips_emit_this_shouldnt_happen); + register_emitter(op_be_AddSP, mips_emit_this_shouldnt_happen); + register_emitter(op_be_Call, mips_emit_Call); + register_emitter(op_be_Copy, mips_emit_Copy); + register_emitter(op_be_Keep, mips_emit_nothing); + register_emitter(op_be_Barrier, mips_emit_nothing); + register_emitter(op_be_Return, mips_emit_Return); + register_emitter(op_be_RegParams, mips_emit_nothing); + register_emitter(op_be_Spill, mips_emit_this_shouldnt_happen); + register_emitter(op_be_Reload, mips_emit_this_shouldnt_happen); + register_emitter(op_be_Perm, mips_emit_Perm); + + register_emitter(op_Start, mips_emit_nothing); + register_emitter(op_Proj, mips_emit_nothing); + register_emitter(op_SymConst, mips_emit_this_shouldnt_happen); + register_emitter(op_Const, mips_emit_this_shouldnt_happen); + register_emitter(op_Jmp, mips_emit_Jump); + register_emitter(op_Cmp, mips_emit_this_shouldnt_happen); + register_emitter(op_Cond, mips_emit_this_shouldnt_happen); + register_emitter(op_Phi, mips_emit_nothing); } -typedef void (*emit_func) (mips_emit_env_t *, const ir_node *); - /** * Emits assembly for a single node */ @@ -636,8 +653,7 @@ static void mips_emit_node(mips_emit_env_t *env, const ir_node *node) emit_func emit = (emit_func) op->ops.generic; (*emit) (env, node); } else { - be_emit_cstring(env->emit, "\t/* TODO */"); - be_emit_finish_line_gas(env->emit, node); + panic("No emitter defined for node %+F", node); } } @@ -669,7 +685,7 @@ void mips_gen_block(mips_emit_env_t *env, ir_node *block) */ void mips_emit_func_prolog(mips_emit_env_t *env, ir_graph *irg) { - ident *irg_ident = get_entity_ident(get_irg_entity(irg)); + ident *irg_ident = get_entity_ld_ident(get_irg_entity(irg)); be_emit_env_t *eenv = env->emit; // dump jump tables @@ -680,7 +696,7 @@ void mips_emit_func_prolog(mips_emit_env_t *env, ir_graph *irg) be_emit_cstring(eenv, "\t.balign\t4\n"); - be_emit_cstring(eenv, "\t.global\t") + be_emit_cstring(eenv, "\t.global\t"); be_emit_ident(eenv, irg_ident); be_emit_char(eenv, '\n'); @@ -720,6 +736,7 @@ void mips_gen_labels(ir_node *block, void *env) { ir_node *pred; int n = get_Block_n_cfgpreds(block); + (void) env; for (n--; n >= 0; n--) { pred = get_Block_cfgpred(block, n);