X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Fbe%2FTEMPLATE%2FTEMPLATE_emitter.c;h=cd9a013a525e99e43a29c75e43cc01fcca12c677;hb=0ac0b440ce2d239c5e7e7db56b8273559d9a7741;hp=61c19f358e7ed7851beed848388c93227a34f770;hpb=f8cc15664f571aa7ef89d6f6bc8d5bd2b8ca7d53;p=libfirm diff --git a/ir/be/TEMPLATE/TEMPLATE_emitter.c b/ir/be/TEMPLATE/TEMPLATE_emitter.c index 61c19f358..cd9a013a5 100644 --- a/ir/be/TEMPLATE/TEMPLATE_emitter.c +++ b/ir/be/TEMPLATE/TEMPLATE_emitter.c @@ -1,20 +1,6 @@ /* - * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. - * * This file is part of libFirm. - * - * This file may be distributed and/or modified under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation and appearing in the file LICENSE.GPL included in the - * packaging of this file. - * - * Licensees holding valid libFirm Professional Edition licenses may use - * this file in accordance with the libFirm Commercial License. - * Agreement provided with the Software. - * - * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE. + * Copyright (C) 2012 University of Karlsruhe. */ /** @@ -25,6 +11,7 @@ #include +#include "error.h" #include "xmalloc.h" #include "tv.h" #include "iredges.h" @@ -46,26 +33,24 @@ #include "TEMPLATE_nodes_attr.h" #include "TEMPLATE_new_nodes.h" -#define SNPRINTF_BUF_LEN 128 - -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); @@ -80,16 +65,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) @@ -100,17 +165,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) @@ -123,11 +184,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); } } @@ -141,31 +198,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"); } /** @@ -175,37 +212,20 @@ static inline void set_emitter(ir_op *op, emit_func func) static void TEMPLATE_register_emitters(void) { /* first clear the generic function pointer for all ops */ - clear_irp_opcodes_generic_func(); + ir_clear_opcodes_generic_func(); /* register all emitter functions defined in spec */ 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); } /** @@ -214,14 +234,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); } } @@ -257,7 +273,7 @@ void TEMPLATE_emit_routine(ir_graph *irg) block_schedule = be_create_block_schedule(irg); /* emit assembler prolog */ - be_gas_emit_function_prolog(entity, 4); + be_gas_emit_function_prolog(entity, 4, NULL); /* populate jump link fields with their destinations */ irg_block_walk_graph(irg, TEMPLATE_gen_labels, NULL, NULL);