changed function signature to stop gcc from moaning
[libfirm] / ir / be / ia32 / ia32_emitter.c
index c51cb32..999317a 100644 (file)
@@ -1,5 +1,10 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <limits.h>
 
+#include "xmalloc.h"
 #include "tv.h"
 #include "iredges.h"
 #include "debug.h"
@@ -40,7 +45,7 @@ const char *node_const_to_str(ir_node *n) {
        tarval *tv = get_ia32_Immop_tarval(n);
 
        if (tv) {
-               buf = malloc(SNPRINTF_BUF_LEN);
+               buf = xmalloc(SNPRINTF_BUF_LEN);
                tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
                return buf;
        }
@@ -56,10 +61,10 @@ const char *node_const_to_str(ir_node *n) {
  */
 char *node_offset_to_str(ir_node *n) {
        char   *buf;
-       tarval *tv = get_ia32_offs(n);
+       tarval *tv = get_ia32_am_offs(n);
 
        if (tv) {
-               buf = malloc(SNPRINTF_BUF_LEN);
+               buf = xmalloc(SNPRINTF_BUF_LEN);
                tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
                return buf;
        }
@@ -134,15 +139,8 @@ static const arch_register_t *get_out_reg(ir_node *irn, int pos) {
  */
 int get_ia32_reg_nr(ir_node *irn, int pos, int in_out) {
        const arch_register_t *reg;
-       ir_node               *op;
 
        if (in_out == 1) {
-               /* special case Proj P_fame_base */
-               op = get_irn_n(irn, pos);
-               if (is_Proj(op) && get_Proj_proj(op) == pn_Start_P_frame_base) {
-                       return 10;
-               }
-
                reg = get_in_reg(irn, pos);
        }
        else {
@@ -157,14 +155,8 @@ int get_ia32_reg_nr(ir_node *irn, int pos, int in_out) {
  */
 const char *get_ia32_reg_name(ir_node *irn, int pos, int in_out) {
        const arch_register_t *reg;
-       ir_node               *op;
 
        if (in_out == 1) {
-               /* special case Proj P_fame_base */
-               op = get_irn_n(irn, pos);
-               if (is_Proj(op) && get_Proj_proj(op) == pn_Start_P_frame_base) {
-                       return "x(esp)";
-               }
                reg = get_in_reg(irn, pos);
        }
        else {
@@ -187,10 +179,10 @@ static int ia32_get_reg_name(lc_appendable_t *app,
        if (!X)
                return lc_arg_append(app, occ, "(null)", 6);
 
-       if (occ->conversion == 's') {
+       if (occ->conversion == 'S') {
                buf = get_ia32_reg_name(X, nr, 1);
        }
-       else { /* 'd' */
+       else { /* 'D' */
                buf = get_ia32_reg_name(X, nr, 0);
        }
 
@@ -210,10 +202,10 @@ static int ia32_const_to_str(lc_appendable_t *app,
        if (!X)
                return lc_arg_append(app, occ, "(null)", 6);
 
-       if (occ->conversion == 'c') {
+       if (occ->conversion == 'C') {
                buf = node_const_to_str(X);
        }
-       else { /* 'o' */
+       else { /* 'O' */
                buf = node_offset_to_str(X);
        }
 
@@ -251,12 +243,13 @@ const lc_arg_env_t *ia32_get_arg_env(void) {
        if(env == NULL) {
                /* extend the firm printer */
                env = firm_get_arg_env();
+                       //lc_arg_new_env();
 
-               lc_arg_register(env, "ia32:sreg", 's', &ia32_reg_handler);
-               lc_arg_register(env, "ia32:dreg", 'd', &ia32_reg_handler);
-               lc_arg_register(env, "ia32:cnst", 'c', &ia32_const_handler);
-               lc_arg_register(env, "ia32:offs", 'o', &ia32_const_handler);
-               lc_arg_register(env, "ia32:mode", 'm', &ia32_mode_handler);
+               lc_arg_register(env, "ia32:sreg", 'S', &ia32_reg_handler);
+               lc_arg_register(env, "ia32:dreg", 'D', &ia32_reg_handler);
+               lc_arg_register(env, "ia32:cnst", 'C', &ia32_const_handler);
+               lc_arg_register(env, "ia32:offs", 'O', &ia32_const_handler);
+               lc_arg_register(env, "ia32:mode", 'M', &ia32_mode_handler);
        }
 
        return env;
@@ -270,11 +263,11 @@ void equalize_dest_src(FILE *F, ir_node *n) {
                if (get_irn_arity(n) > 1 && get_ia32_reg_nr(n, 1, 1) == get_ia32_reg_nr(n, 0, 0)) {
                        if (! is_op_commutative(get_irn_op(n))) {
                                /* we only need to exchange for non-commutative ops */
-                               lc_efprintf(ia32_get_arg_env(), F, "\txchg %1s, %2s\t\t\t/* xchg src1 <-> src2 for 2 address code */\n", n, n);
+                               lc_efprintf(ia32_get_arg_env(), F, "\txchg %1S, %2S\t\t\t/* xchg src1 <-> src2 for 2 address code */\n", n, n);
                        }
                }
                else {
-                       lc_efprintf(ia32_get_arg_env(), F, "\tmovl %1s, %1d\t\t\t/* src -> dest for 2 address code */\n", n, n);
+                       lc_efprintf(ia32_get_arg_env(), F, "\tmovl %1S, %1D\t\t\t/* src -> dest for 2 address code */\n", n, n);
                }
        }
 }
@@ -409,7 +402,7 @@ static void finish_CondJmp(FILE *F, ir_node *irn) {
 static void emit_ia32_CondJmp(ir_node *irn, emit_env_t *env) {
        FILE *F = env->out;
 
-       lc_efprintf(ia32_get_arg_env(), F, "\tcmp %2s, %1s\t\t\t/* CondJmp(%+F, %+F) */\n", irn, irn,
+       lc_efprintf(ia32_get_arg_env(), F, "\tcmp %2S, %1S\t\t\t/* CondJmp(%+F, %+F) */\n", irn, irn,
                                                                                                                                        get_irn_n(irn, 0), get_irn_n(irn, 1));
        finish_CondJmp(F, irn);
 }
@@ -420,7 +413,7 @@ static void emit_ia32_CondJmp(ir_node *irn, emit_env_t *env) {
 void emit_ia32_CondJmp_i(ir_node *irn, emit_env_t *env) {
        FILE *F = env->out;
 
-       lc_efprintf(ia32_get_arg_env(), F, "\tcmp %c, %1s\t\t\t/* CondJmp_i(%+F) */\n", irn, irn, get_irn_n(irn, 0));
+       lc_efprintf(ia32_get_arg_env(), F, "\tcmp %C, %1S\t\t\t/* CondJmp_i(%+F) */\n", irn, irn, get_irn_n(irn, 0));
        finish_CondJmp(F, irn);
 }
 
@@ -482,11 +475,11 @@ void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) {
        FILE               *F   = emit_env->out;
 
        /* fill the table structure */
-       tbl.label        = malloc(SNPRINTF_BUF_LEN);
+       tbl.label        = xmalloc(SNPRINTF_BUF_LEN);
        tbl.label        = get_unique_label(tbl.label, SNPRINTF_BUF_LEN, "JMPTBL_");
        tbl.defProj      = NULL;
        tbl.num_branches = get_irn_n_edges(irn);
-       tbl.branches     = calloc(tbl.num_branches, sizeof(tbl.branches[0]));
+       tbl.branches     = xcalloc(tbl.num_branches, sizeof(tbl.branches[0]));
        tbl.min_value    = INT_MAX;
        tbl.max_value    = INT_MIN;
 
@@ -534,11 +527,11 @@ void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) {
                /* emit the table */
                if (tbl.min_value != 0) {
                        fprintf(F, "\tcmpl %lu, -%d", interval, tbl.min_value);
-                       lc_efprintf(env, F, "(%1s)\t\t/* first switch value is not 0 */\n", irn);
+                       lc_efprintf(env, F, "(%1S)\t\t/* first switch value is not 0 */\n", irn);
                }
                else {
                        fprintf(F, "\tcmpl %lu, ", interval);
-                       lc_efprintf(env, F, "%1s\t\t\t/* compare for switch */\n", irn);
+                       lc_efprintf(env, F, "%1S\t\t\t/* compare for switch */\n", irn);
                }
 
                fprintf(F, "\tja %s\t\t\t/* default jump if out of range  */\n", get_cfop_target(tbl.defProj, buf));
@@ -546,8 +539,8 @@ void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) {
                if (tbl.num_branches > 1) {
                        /* create table */
 
-                       fprintf(F, "\tjmp *%s", tbl.label);
-                       lc_efprintf(env, F, "(,%1s,4)\t\t/* get jump table entry as target */\n", irn);
+                       //fprintf(F, "\tjmp *%s", tbl.label);
+                       lc_efprintf(env, F, "\tjmp *%s(,%1S,4)\t\t/* get jump table entry as target */\n", tbl.label, irn);
 
                        fprintf(F, "\t.section\t.rodata\t\t/* start jump table */\n");
                        fprintf(F, "\t.align 4\n");
@@ -573,7 +566,7 @@ void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) {
        else { // no jump table
                for (i = 0; i < tbl.num_branches; ++i) {
                        fprintf(F, "\tcmpl %d, ", tbl.branches[i].value);
-                       lc_efprintf(env, F, "%1s", irn);
+                       lc_efprintf(env, F, "%1S", irn);
                        fprintf(F, "\t\t\t/* case %d */\n", tbl.branches[i].value);
                        fprintf(F, "\tje %s\n", get_cfop_target(tbl.branches[i].target, buf));
                }
@@ -616,7 +609,7 @@ void emit_Jmp(ir_node *irn, emit_env_t *env) {
 void emit_Proj(ir_node *irn, emit_env_t *env) {
        ir_node *pred = get_Proj_pred(irn);
 
-       if (get_irn_opcode(pred) == iro_Start) {
+       if (get_irn_op(pred) == op_Start) {
                switch(get_Proj_proj(irn)) {
                        case pn_Start_X_initial_exec:
                                emit_Jmp(irn, env);
@@ -627,6 +620,95 @@ void emit_Proj(ir_node *irn, emit_env_t *env) {
        }
 }
 
+/********************
+ *   _____      _ _
+ *  / ____|    | | |
+ * | |     __ _| | |
+ * | |    / _` | | |
+ * | |___| (_| | | |
+ *  \_____\__,_|_|_|
+ *
+ ********************/
+
+void emit_ia32_Call(ir_node *irn, emit_env_t *emit_env) {
+       int                 i, n      = get_irn_arity(irn);
+       int                 args_size = 0;
+       ir_node            *sync      = get_irn_n(irn, n - 1);
+       FILE               *F         = emit_env->out;
+       const lc_arg_env_t *env       = ia32_get_arg_env();
+
+       if (get_irn_op(sync) == op_Sync) {
+               /* We have stack arguments */
+               ir_node **args = get_Sync_preds_arr(sync);
+
+               for (i = 0; i < get_Sync_n_preds(sync); i++) {
+                       lc_efprintf(env, F, "\tpush %1D\t\t\t\t/* push %+F on stack */\n", args[i], args[i]);
+
+                       if (mode_is_int(get_irn_mode(args[i]))) {
+                               args_size += 4;
+                       }
+                       else {
+                               args_size += 16;
+                       }
+               }
+       }
+
+       lc_efprintf(env, F, "\tcall %C\t\t\t/* %+F */\n", irn, irn);
+
+       if (get_irn_op(sync) == op_Sync) {
+               /* We had stack arguments: clear the stack */
+               fprintf(F, "\tadd %d, ", args_size);
+               if (emit_env->cg->has_alloca) {
+                       fprintf(F, "%ebp");
+               }
+               else {
+                       fprintf(F, "%esp");
+               }
+               fprintf(F, "\t\t\t\t/* clear stack after call */\n");
+       }
+}
+
+
+
+/**
+ * Emits code for Alloca (increase stack pointer, cpoy to destination)
+ */
+void emit_Alloca(ir_node *irn, emit_env_t *emit_env, int is_imm) {
+       const lc_arg_env_t *env = ia32_get_arg_env();
+       FILE               *F   = emit_env->out;
+       char               *sp;
+
+       if (emit_env->cg->has_alloca) {
+               sp = "%ebp";
+       }
+       else {
+               sp = "%esp";
+       }
+
+
+       /* allocate the memory */
+       fprintf(F, "\tsub %s", sp);
+
+       if (is_imm) {
+               lc_efprintf(env, F, "%C", irn);
+       }
+       else {
+               lc_efprintf(env, F, "%1S", irn);
+       }
+
+       fprintf(F, "\t\t\t\t/* reserve memory on stack */\n");
+
+       /* copy the new stack pointer to destination register */
+       lc_efprintf(env, F, "\tmov %s, %1D\t\t\t/* copy stack pointer to destination */\n", sp, irn);
+}
+
+void emit_ia32_Alloca(ir_node *irn, emit_env_t *emit_env) {
+       emit_Alloca(irn, emit_env, 0);
+}
+
+void emit_ia32_Alloca_i(ir_node *irn, emit_env_t *emit_env) {
+       emit_Alloca(irn, emit_env, 1);
+}
 
 
 /***********************************************************************************
@@ -692,8 +774,6 @@ void ia32_emit_node(ir_node *irn, void *env) {
 
        IA32_EMIT(Mul);
        IA32_EMIT(Mul_i);
-       IA32_EMIT(Mulh);
-       IA32_EMIT(Mulh_i);
 
        IA32_EMIT(Cltd);
        IA32_EMIT(DivMod);
@@ -721,6 +801,9 @@ void ia32_emit_node(ir_node *irn, void *env) {
        IA32_EMIT(CondJmp);
        IA32_EMIT(CondJmp_i);
        IA32_EMIT(SwitchJmp);
+       IA32_EMIT(Call);
+       IA32_EMIT(Alloca);
+       IA32_EMIT(Alloca_i);
 
        EMIT(Jmp);
        EMIT(Proj);
@@ -784,14 +867,13 @@ void ia32_gen_labels(ir_node *block, void *env) {
 /**
  * Main driver
  */
-void ia32_gen_routine(FILE *F, ir_graph *irg, const arch_env_t *env) {
+void ia32_gen_routine(FILE *F, ir_graph *irg, const ia32_code_gen_t *cg) {
        emit_env_t emit_env;
 
        emit_env.mod      = firm_dbg_register("ir.be.codegen.ia32");
        emit_env.out      = F;
-       emit_env.arch_env = env;
-
-       arch_env = env;
+       emit_env.arch_env = cg->arch_env;
+       emit_env.cg       = cg;
 
        ia32_emit_start(F, irg);
        irg_block_walk_graph(irg, ia32_gen_labels, NULL, &emit_env);