X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2FTEMPLATE%2FTEMPLATE_emitter.c;h=151463675c85d1efe4ca7f8ef7782fb825f17654;hb=6f5e548d48567ee01f0d0cc33d5bd0addda48ca1;hp=334b7bb96a2c03cc865d43787030ffc92ffa3008;hpb=194f0e40a79d0fc034f3f9cbd571e05f789c1614;p=libfirm diff --git a/ir/be/TEMPLATE/TEMPLATE_emitter.c b/ir/be/TEMPLATE/TEMPLATE_emitter.c index 334b7bb96..151463675 100644 --- a/ir/be/TEMPLATE/TEMPLATE_emitter.c +++ b/ir/be/TEMPLATE/TEMPLATE_emitter.c @@ -37,6 +37,9 @@ #include "irprog.h" #include "../besched.h" +#include "../begnuas.h" +#include "../beblocksched.h" +#include "../benode.h" #include "TEMPLATE_emitter.h" #include "gen_TEMPLATE_emitter.h" @@ -112,8 +115,8 @@ static const arch_register_t *get_out_reg(const ir_node *node, int pos) 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) @@ -150,43 +153,77 @@ static void TEMPLATE_emit_cfop_target(const ir_node *node) /** * Emits code for a unconditional jump. */ -static void emit_Jmp(const ir_node *node) +static void emit_TEMPLATE_Jmp(const ir_node *node) { - ir_node *block; - - /* for now, the code works for scheduled and non-schedules blocks */ - block = get_nodes_block(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 *); @@ -194,7 +231,7 @@ typedef void (*emit_func_ptr) (const ir_node *); /** * Emits code for a node. */ -void TEMPLATE_emit_node(const ir_node *node) +static void TEMPLATE_emit_node(const ir_node *node) { ir_op *op = get_irn_op(node); @@ -210,13 +247,9 @@ void TEMPLATE_emit_node(const ir_node *node) * Walks over the nodes in a block connected by scheduling edges * and emits code for each node. */ -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"); @@ -227,40 +260,10 @@ void TEMPLATE_gen_block(ir_node *block, void *data) } } - -/** - * Emits code for function start. - */ -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 - */ -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) - * TODO: Jump optimization */ -void TEMPLATE_gen_labels(ir_node *block, void *env) +static void TEMPLATE_gen_labels(ir_node *block, void *env) { ir_node *pred; int n = get_Block_n_cfgpreds(block); @@ -275,15 +278,29 @@ void TEMPLATE_gen_labels(ir_node *block, void *env) /** * 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); }