Implement semi-binary emitter for SwitchJmp.
[libfirm] / ir / be / ia32 / bearch_ia32.c
index 14f542d..5076630 100644 (file)
@@ -53,7 +53,7 @@
 
 #include "../beabi.h"
 #include "../beirg.h"
-#include "../benode_t.h"
+#include "../benode.h"
 #include "../belower.h"
 #include "../besched.h"
 #include "be.h"
@@ -96,9 +96,6 @@ transformer_t be_transformer = TRANSFORMER_DEFAULT;
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
-/* TODO: ugly */
-static set *cur_reg_set = NULL;
-
 ir_mode         *mode_fpcw       = NULL;
 ia32_code_gen_t *ia32_current_cg = NULL;
 
@@ -808,7 +805,6 @@ static const be_abi_callbacks_t ia32_abi_callbacks = {
 /* register allocator interface */
 static const arch_irn_ops_t ia32_irn_ops = {
        get_ia32_in_req,
-       get_ia32_out_req,
        ia32_classify,
        ia32_get_frame_entity,
        ia32_set_frame_entity,
@@ -830,7 +826,6 @@ static const arch_irn_ops_t ia32_SwitchJmp_irn_ops = {
           Querying for negative proj numbers which can happen for switchs
           isn't possible and will result in inputs getting queried */
        get_ia32_SwitchJmp_out_req,
-       get_ia32_SwitchJmp_out_req,
        ia32_classify,
        ia32_get_frame_entity,
        ia32_set_frame_entity,
@@ -887,27 +882,7 @@ static void ia32_before_abi(void *self)
  */
 static void ia32_prepare_graph(void *self)
 {
-       ia32_code_gen_t *cg  = self;
-       ir_graph        *irg = cg->irg;
-
-       /* do local optimizations */
-       optimize_graph_df(irg);
-
-       /* we have to do cfopt+remove_critical_edges as we can't have Bad-blocks
-        * or critical edges in the backend */
-       optimize_cf(irg);
-       remove_critical_cf_edges(irg);
-
-       /* TODO: we often have dead code reachable through out-edges here. So for
-        * now we rebuild edges (as we need correct user count for code selection)
-        */
-#if 1
-       edges_deactivate(cg->irg);
-       edges_activate(cg->irg);
-#endif
-
-       if (cg->dump)
-               be_dump(cg->irg, "-pre_transform", dump_ir_block_graph_sched);
+       ia32_code_gen_t *cg = self;
 
        switch (be_transformer) {
        case TRANSFORMER_DEFAULT:
@@ -1306,7 +1281,7 @@ static void transform_MemPerm(ia32_code_gen_t *cg, ir_node *node)
        }
 
        in[0] = sp;
-       keep  = be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], block, 1, in);
+       keep  = be_new_Keep(block, 1, in);
        sched_add_before(node, keep);
 
        /* exchange memprojs */
@@ -1476,9 +1451,11 @@ static void ia32_codegen(void *self)
        ia32_code_gen_t *cg = self;
        ir_graph        *irg = cg->irg;
 
-       ia32_gen_routine(cg, irg);
-
-       cur_reg_set = NULL;
+       if (ia32_cg_config.emit_machcode) {
+               ia32_gen_binary_routine(cg, irg);
+       } else {
+               ia32_gen_routine(cg, irg);
+       }
 
        /* remove it from the isa */
        cg->isa->cg = NULL;
@@ -1487,7 +1464,6 @@ static void ia32_codegen(void *self)
        ia32_current_cg = NULL;
 
        /* de-allocate code generator */
-       del_set(cg->reg_set);
        free(cg);
 }
 
@@ -1534,7 +1510,6 @@ static void *ia32_cg_init(be_irg_t *birg)
 
        cg->impl      = &ia32_code_gen_if;
        cg->irg       = birg->irg;
-       cg->reg_set   = new_set(ia32_cmp_irn_reg_assoc, 1024);
        cg->isa       = isa;
        cg->birg      = birg;
        cg->blk_sched = NULL;
@@ -1556,8 +1531,6 @@ static void *ia32_cg_init(be_irg_t *birg)
        }
 #endif /* NDEBUG */
 
-       cur_reg_set = cg->reg_set;
-
        assert(ia32_current_cg == NULL);
        ia32_current_cg = cg;
 
@@ -1783,19 +1756,16 @@ static void ia32_done(void *self)
  *  - the virtual floating point registers
  *  - the SSE vector register set
  */
-static unsigned ia32_get_n_reg_class(const void *self)
+static unsigned ia32_get_n_reg_class(void)
 {
-       (void) self;
        return N_CLASSES;
 }
 
 /**
  * Return the register class for index i.
  */
-static const arch_register_class_t *ia32_get_reg_class(const void *self,
-                                                       unsigned i)
+static const arch_register_class_t *ia32_get_reg_class(unsigned i)
 {
-       (void) self;
        assert(i < N_CLASSES);
        return &ia32_reg_classes[i];
 }
@@ -1806,11 +1776,8 @@ static const arch_register_class_t *ia32_get_reg_class(const void *self,
  * @param mode The mode in question.
  * @return A register class which can hold values of the given mode.
  */
-const arch_register_class_t *ia32_get_reg_class_for_mode(const void *self,
-               const ir_mode *mode)
+const arch_register_class_t *ia32_get_reg_class_for_mode(const ir_mode *mode)
 {
-       (void) self;
-
        if (mode_is_float(mode)) {
                return ia32_cg_config.use_sse2 ? &ia32_reg_classes[CLASS_ia32_xmm] : &ia32_reg_classes[CLASS_ia32_vfp];
        }
@@ -1818,6 +1785,88 @@ const arch_register_class_t *ia32_get_reg_class_for_mode(const void *self,
                return &ia32_reg_classes[CLASS_ia32_gp];
 }
 
+/**
+ * Returns the register for parameter nr.
+ */
+static const arch_register_t *ia32_get_RegParam_reg(unsigned cc, unsigned nr,
+                                                    const ir_mode *mode)
+{
+       static const arch_register_t *gpreg_param_reg_fastcall[] = {
+               &ia32_gp_regs[REG_ECX],
+               &ia32_gp_regs[REG_EDX],
+               NULL
+       };
+       static const unsigned MAXNUM_GPREG_ARGS = 3;
+
+       static const arch_register_t *gpreg_param_reg_regparam[] = {
+               &ia32_gp_regs[REG_EAX],
+               &ia32_gp_regs[REG_EDX],
+               &ia32_gp_regs[REG_ECX]
+       };
+
+       static const arch_register_t *gpreg_param_reg_this[] = {
+               &ia32_gp_regs[REG_ECX],
+               NULL,
+               NULL
+       };
+
+       static const arch_register_t *fpreg_sse_param_reg_std[] = {
+               &ia32_xmm_regs[REG_XMM0],
+               &ia32_xmm_regs[REG_XMM1],
+               &ia32_xmm_regs[REG_XMM2],
+               &ia32_xmm_regs[REG_XMM3],
+               &ia32_xmm_regs[REG_XMM4],
+               &ia32_xmm_regs[REG_XMM5],
+               &ia32_xmm_regs[REG_XMM6],
+               &ia32_xmm_regs[REG_XMM7]
+       };
+
+       static const arch_register_t *fpreg_sse_param_reg_this[] = {
+               NULL,  /* in case of a "this" pointer, the first parameter must not be a float */
+       };
+       static const unsigned MAXNUM_SSE_ARGS = 8;
+
+       if ((cc & cc_this_call) && nr == 0)
+               return gpreg_param_reg_this[0];
+
+       if (! (cc & cc_reg_param))
+               return NULL;
+
+       if (mode_is_float(mode)) {
+               if (!ia32_cg_config.use_sse2 || (cc & cc_fpreg_param) == 0)
+                       return NULL;
+               if (nr >= MAXNUM_SSE_ARGS)
+                       return NULL;
+
+               if (cc & cc_this_call) {
+                       return fpreg_sse_param_reg_this[nr];
+               }
+               return fpreg_sse_param_reg_std[nr];
+       } else if (mode_is_int(mode) || mode_is_reference(mode)) {
+               unsigned num_regparam;
+
+               if (get_mode_size_bits(mode) > 32)
+                       return NULL;
+
+               if (nr >= MAXNUM_GPREG_ARGS)
+                       return NULL;
+
+               if (cc & cc_this_call) {
+                       return gpreg_param_reg_this[nr];
+               }
+               num_regparam = cc & ~cc_bits;
+               if (num_regparam == 0) {
+                       /* default fastcall */
+                       return gpreg_param_reg_fastcall[nr];
+               }
+               if (nr < num_regparam)
+                       return gpreg_param_reg_regparam[nr];
+               return NULL;
+       }
+
+       panic("unknown argument mode");
+}
+
 /**
  * Get the ABI restrictions for procedure calls.
  * @param self        The this pointer.
@@ -1990,12 +2039,10 @@ static const ilp_sched_selector_t *ia32_get_ilp_sched_selector(const void *self)
 /**
  * Returns the necessary byte alignment for storing a register of given class.
  */
-static int ia32_get_reg_class_alignment(const void *self,
-                                        const arch_register_class_t *cls)
+static int ia32_get_reg_class_alignment(const arch_register_class_t *cls)
 {
        ir_mode *mode = arch_register_class_mode(cls);
        int bytes     = get_mode_size_bytes(mode);
-       (void) self;
 
        if (mode_is_float(mode) && bytes > 8)
                return 16;
@@ -2003,7 +2050,7 @@ static int ia32_get_reg_class_alignment(const void *self,
 }
 
 static const be_execution_unit_t ***ia32_get_allowed_execution_units(
-               const void *self, const ir_node *irn)
+               const ir_node *irn)
 {
        static const be_execution_unit_t *_allowed_units_BRANCH[] = {
                &ia32_execution_units_BRANCH[IA32_EXECUNIT_TP_BRANCH_BRANCH1],
@@ -2037,7 +2084,6 @@ static const be_execution_unit_t ***ia32_get_allowed_execution_units(
                NULL
        };
        const be_execution_unit_t ***ret;
-       (void) self;
 
        if (is_ia32_irn(irn)) {
                ret = get_ia32_exec_units(irn);
@@ -2076,9 +2122,8 @@ static ir_graph **ia32_get_irg_list(const void *self, ir_graph ***irg_list)
        return NULL;
 }
 
-static void ia32_mark_remat(const void *self, ir_node *node)
+static void ia32_mark_remat(ir_node *node)
 {
-       (void) self;
        if (is_ia32_irn(node)) {
                set_ia32_is_remat(node);
        }
@@ -2345,9 +2390,8 @@ static int ia32_is_mux_allowed(ir_node *sel, ir_node *phi_list, int i, int j)
        return 0;
 }
 
-static asm_constraint_flags_t ia32_parse_asm_constraint(const void *self, const char **c)
+static asm_constraint_flags_t ia32_parse_asm_constraint(const char **c)
 {
-       (void) self;
        (void) c;
 
        /* we already added all our simple flags to the flags modifier list in
@@ -2355,10 +2399,8 @@ static asm_constraint_flags_t ia32_parse_asm_constraint(const void *self, const
        return ASM_CONSTRAINT_FLAG_INVALID;
 }
 
-static int ia32_is_valid_clobber(const void *self, const char *clobber)
+static int ia32_is_valid_clobber(const char *clobber)
 {
-       (void) self;
-
        return ia32_get_clobber_register(clobber) != NULL;
 }