remove the deprecated and unused construct of a value_res_base entities in method...
[libfirm] / ir / be / sparc / sparc_cconv.c
index 4f83049..7e7af83 100644 (file)
 
 #include "sparc_cconv.h"
 #include "irmode.h"
+#include "irgwalk.h"
 #include "typerep.h"
 #include "xmalloc.h"
+#include "util.h"
 #include "error.h"
+#include "gen_sparc_regalloc_if.h"
+
+static const unsigned ignore_regs[] = {
+       REG_G0,
+       /* reserved for sparc ABI: */
+       REG_G5,
+       REG_G6,
+       REG_G7,
+
+       REG_SP,
+       REG_O7,
+       REG_FRAME_POINTER,
+       REG_I7,
+
+       REG_FPFLAGS,
+       REG_FLAGS,
+       REG_Y,
+};
 
 /**
  * Maps an input register representing the i'th register input
  */
 static const arch_register_t *map_i_to_o_reg(const arch_register_t *reg)
 {
-       unsigned idx = arch_register_get_index(reg);
+       unsigned idx = reg->global_index;
        assert(REG_I0 <= idx && idx <= REG_I7);
        idx += REG_O0 - REG_I0;
        assert(REG_O0 <= idx && idx <= REG_O7);
-       return &sparc_gp_regs[idx];
+       return &sparc_registers[idx];
+}
+
+static void check_omit_fp(ir_node *node, void *env)
+{
+       bool *can_omit_fp = (bool*) env;
+
+       /* omit-fp is not possible if:
+        *  - we have allocations on the stack
+        *  - we have calls (with the exception of tail-calls once we support them)
+        */
+       if ((is_Alloc(node) && get_Alloc_where(node) == stack_alloc)
+                       || (is_Free(node) && get_Free_where(node) == stack_alloc)
+                       || is_Call(node)) {
+               *can_omit_fp = false;
+       }
 }
 
 calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
-                                                      bool caller)
+                                                      ir_graph *irg)
 {
-       int                   stack_offset = 0;
+       int                   stack_offset        = 0;
+       int                   n_param_regs        = ARRAY_SIZE(param_regs);
+       int                   n_float_result_regs = ARRAY_SIZE(float_result_regs);
+       bool                  omit_fp             = false;
        reg_or_stackslot_t   *params;
        reg_or_stackslot_t   *results;
-       int                   n_param_regs
-               = sizeof(param_regs)/sizeof(param_regs[0]);
-       int                   n_float_result_regs
-               = sizeof(float_result_regs)/sizeof(float_result_regs[0]);
        int                   n_params;
        int                   n_results;
        int                   i;
@@ -61,6 +95,12 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
        int                   float_regnum;
        calling_convention_t *cconv;
 
+       if (irg != NULL) {
+               const be_options_t *options = be_get_irg_options(irg);
+               omit_fp = options->omit_fp;
+               irg_walk_graph(irg, check_omit_fp, NULL, &omit_fp);
+       }
+
        /* determine how parameters are passed */
        n_params = get_method_n_params(function_type);
        regnum   = 0;
@@ -71,14 +111,14 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
                ir_mode            *mode       = get_type_mode(param_type);
                int                 bits       = get_mode_size_bits(mode);
                reg_or_stackslot_t *param      = &params[i];
-               param->type = param_type;
 
                if (regnum < n_param_regs) {
                        const arch_register_t *reg = param_regs[regnum++];
-                       if (caller)
+                       if (irg == NULL || omit_fp)
                                reg = map_i_to_o_reg(reg);
                        param->reg0 = reg;
                } else {
+                       param->type   = param_type;
                        param->offset = stack_offset;
                        /* increase offset 4 bytes so everything is aligned */
                        stack_offset += bits > 32 ? bits/8 : 4;
@@ -92,7 +132,7 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
 
                        if (regnum < n_param_regs) {
                                const arch_register_t *reg = param_regs[regnum++];
-                               if (caller)
+                               if (irg == NULL || omit_fp)
                                        reg = map_i_to_o_reg(reg);
                                param->reg1 = reg;
                        } else {
@@ -132,7 +172,7 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
                                panic("Too many results for sparc backend");
                        } else {
                                const arch_register_t *reg = param_regs[regnum++];
-                               if (caller)
+                               if (irg == NULL || omit_fp)
                                        reg = map_i_to_o_reg(reg);
                                result->reg0 = reg;
                        }
@@ -143,6 +183,22 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
        cconv->parameters       = params;
        cconv->param_stack_size = stack_offset;
        cconv->results          = results;
+       cconv->omit_fp          = omit_fp;
+
+       /* setup ignore register array */
+       if (irg != NULL) {
+               be_irg_t       *birg      = be_birg_from_irg(irg);
+               size_t          n_ignores = ARRAY_SIZE(ignore_regs);
+               struct obstack *obst      = &birg->obst;
+               size_t          r;
+
+               assert(birg->allocatable_regs == NULL);
+               birg->allocatable_regs = rbitset_obstack_alloc(obst, N_SPARC_REGISTERS);
+               rbitset_set_all(birg->allocatable_regs, N_SPARC_REGISTERS);
+               for (r = 0; r < n_ignores; ++r) {
+                       rbitset_clear(birg->allocatable_regs, ignore_regs[r]);
+               }
+       }
 
        return cconv;
 }