X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2FTEMPLATE%2FTEMPLATE_emitter.c;h=db1fb0ca3569a412297312924b6f2cfe3c3c8c5d;hb=b59e22a229aa1227ef992c184c79fdafe34908cf;hp=195e80af88ac75719d2af32c1e4fe185deb02f92;hpb=ea6ab29016f445f24e6ced97375d16be87513daa;p=libfirm diff --git a/ir/be/TEMPLATE/TEMPLATE_emitter.c b/ir/be/TEMPLATE/TEMPLATE_emitter.c index 195e80af8..db1fb0ca3 100644 --- a/ir/be/TEMPLATE/TEMPLATE_emitter.c +++ b/ir/be/TEMPLATE/TEMPLATE_emitter.c @@ -25,6 +25,7 @@ #include +#include "error.h" #include "xmalloc.h" #include "tv.h" #include "iredges.h" @@ -46,24 +47,24 @@ #include "TEMPLATE_nodes_attr.h" #include "TEMPLATE_new_nodes.h" -void TEMPLATE_emit_immediate(const ir_node *node) +static void TEMPLATE_emit_immediate(const ir_node *node) { const TEMPLATE_attr_t *attr = get_TEMPLATE_attr_const(node); - be_emit_tarval(attr->value); + be_emit_irprintf("%T", attr->value); } static void emit_register(const arch_register_t *reg) { - be_emit_string(arch_register_get_name(reg)); + be_emit_string(reg->name); } -void TEMPLATE_emit_source_register(const ir_node *node, int pos) +static void TEMPLATE_emit_source_register(const ir_node *node, int pos) { const arch_register_t *reg = arch_get_irn_register_in(node, pos); emit_register(reg); } -void TEMPLATE_emit_dest_register(const ir_node *node, int pos) +static void TEMPLATE_emit_dest_register(const ir_node *node, int pos) { const arch_register_t *reg = arch_get_irn_register_out(node, pos); emit_register(reg); @@ -78,16 +79,96 @@ static void TEMPLATE_emit_cfop_target(const ir_node *node) be_gas_emit_block_name(block); } +void TEMPLATE_emitf(const ir_node *node, const char *format, ...) +{ + va_list ap; + va_start(ap, format); + be_emit_char('\t'); + for (;;) { + const char *start = format; + while (*format != '%' && *format != '\0') + ++format; + be_emit_string_len(start, format-start); + if (*format == '\0') + break; + ++format; + + switch (*format++) { + case '%': + be_emit_char('%'); + break; + + case 'S': { + if (*format < '0' || '9' <= *format) + goto unknown; + unsigned const pos = *format++ - '0'; + TEMPLATE_emit_source_register(node, pos); + break; + } + + case 'D': { + if (*format < '0' || '9' <= *format) + goto unknown; + unsigned const pos = *format++ - '0'; + TEMPLATE_emit_dest_register(node, pos); + break; + } + + case 'I': + TEMPLATE_emit_immediate(node); + break; + + case 'X': { + int num = va_arg(ap, int); + be_emit_irprintf("%X", num); + break; + } + + case 'u': { + unsigned num = va_arg(ap, unsigned); + be_emit_irprintf("%u", num); + break; + } + + case 'd': { + int num = va_arg(ap, int); + be_emit_irprintf("%d", num); + break; + } + + case 's': { + const char *string = va_arg(ap, const char *); + be_emit_string(string); + break; + } + + case 'L': { + TEMPLATE_emit_cfop_target(node); + break; + } + + case '\n': + be_emit_char('\n'); + be_emit_write_line(); + be_emit_char('\t'); + break; + + default: +unknown: + panic("unknown format conversion"); + } + } + va_end(ap); + be_emit_finish_line_gas(node); +} /** * Emits code for a unconditional jump. */ static void emit_TEMPLATE_Jmp(const ir_node *node) { - be_emit_cstring("\tjmp "); - TEMPLATE_emit_cfop_target(node); - be_emit_finish_line_gas(node); + TEMPLATE_emitf(node, "jmp %L"); } static void emit_be_IncSP(const ir_node *node) @@ -98,17 +179,13 @@ static void emit_be_IncSP(const ir_node *node) return; /* downwards growing stack */ - if (offset > 0) { - be_emit_cstring("\tsub "); - } else { - be_emit_cstring("\tadd "); + const char *op = "add"; + if (offset < 0) { + op = "sub"; 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); + TEMPLATE_emitf(node, "%s %S0, %d, %D0", op, offset); } static void emit_be_Start(const ir_node *node) @@ -121,11 +198,7 @@ static void emit_be_Start(const ir_node *node) /* allocate stackframe */ if (size > 0) { - be_emit_cstring("\tsub "); - emit_register(&TEMPLATE_registers[REG_SP]); - be_emit_irprintf(", %u, ", size); - emit_register(&TEMPLATE_registers[REG_SP]); - be_emit_finish_line_gas(node); + TEMPLATE_emitf(node, "sub %%sp, %u, %%sp", size); } } @@ -139,31 +212,11 @@ static void emit_be_Return(const ir_node *node) /* deallocate stackframe */ if (size > 0) { - be_emit_cstring("\tadd "); - emit_register(&TEMPLATE_registers[REG_SP]); - be_emit_irprintf(", %u, ", size); - emit_register(&TEMPLATE_registers[REG_SP]); - be_emit_finish_line_gas(node); + TEMPLATE_emitf(node, "add %%sp, %u, %%sp", size); } /* return */ - 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; + TEMPLATE_emitf(node, "ret"); } /** @@ -179,31 +232,14 @@ static void TEMPLATE_register_emitters(void) TEMPLATE_register_spec_emitters(); /* custom emitters not provided by the spec */ - set_emitter(op_TEMPLATE_Jmp, emit_TEMPLATE_Jmp); - set_emitter(op_be_IncSP, emit_be_IncSP); - set_emitter(op_be_Return, emit_be_Return); - set_emitter(op_be_Start, emit_be_Start); + be_set_emitter(op_TEMPLATE_Jmp, emit_TEMPLATE_Jmp); + be_set_emitter(op_be_IncSP, emit_be_IncSP); + be_set_emitter(op_be_Return, emit_be_Return); + be_set_emitter(op_be_Start, emit_be_Start); /* no need to emit anything for the following nodes */ - set_emitter(op_Phi, emit_nothing); - set_emitter(op_be_Keep, emit_nothing); -} - -typedef void (*emit_func_ptr) (const ir_node *); - -/** - * Emits code for a node. - */ -static void TEMPLATE_emit_node(const ir_node *node) -{ - ir_op *op = get_irn_op(node); - - if (op->ops.generic) { - emit_func_ptr func = (emit_func_ptr) op->ops.generic; - (*func) (node); - } else { - ir_fprintf(stderr, "No emitter for node %+F\n", node); - } + be_set_emitter(op_Phi, be_emit_nothing); + be_set_emitter(op_be_Keep, be_emit_nothing); } /** @@ -212,14 +248,10 @@ static void TEMPLATE_emit_node(const ir_node *node) */ static void TEMPLATE_emit_block(ir_node *block) { - ir_node *node; - - be_gas_emit_block_name(block); - be_emit_cstring(":\n"); - be_emit_write_line(); + be_gas_begin_block(block, true); sched_foreach(block, node) { - TEMPLATE_emit_node(node); + be_emit_node(node); } }