Set svn:keywords property.
[libfirm] / ir / be / sparc / bearch_sparc.c
index 212b59a..6ab6ada 100644 (file)
@@ -20,7 +20,7 @@
 /**
  * @file
  * @brief    The main sparc backend driver file.
- * @version  $Id: bearch_TEMPLATE.c 26673 2009-10-01 16:43:13Z matze $
+ * @version  $Id$
  */
 
 #include "config.h"
@@ -65,6 +65,7 @@
 #include "gen_sparc_regalloc_if.h"
 #include "sparc_transform.h"
 #include "sparc_emitter.h"
+#include "sparc_map_regs.h"
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
@@ -74,10 +75,22 @@ static arch_irn_class_t sparc_classify(const ir_node *irn)
        return 0;
 }
 
-static ir_entity *sparc_get_frame_entity(const ir_node *node)
+static ir_entity *sparc_get_frame_entity(const ir_node *irn)
 {
-       (void) node;
-       /* TODO: return the ir_entity assigned to the frame */
+       const sparc_attr_t *attr = get_sparc_attr_const(irn);
+
+       if (is_sparc_FrameAddr(irn)) {
+               const sparc_symconst_attr_t *attr = get_irn_generic_attr_const(irn);
+               return attr->entity;
+       }
+
+       if (attr->is_load_store) {
+               const sparc_load_store_attr_t *load_store_attr = get_sparc_load_store_attr_const(irn);
+               if (load_store_attr->is_frame_entity) {
+                       return load_store_attr->entity;
+               }
+       }
+
        return NULL;
 }
 
@@ -85,6 +98,7 @@ static void sparc_set_frame_entity(ir_node *node, ir_entity *ent)
 {
        (void) node;
        (void) ent;
+       panic("sparc_set_frame_entity() called. This should not happen.");
        /* TODO: set the ir_entity assigned to the frame */
 }
 
@@ -94,9 +108,14 @@ static void sparc_set_frame_entity(ir_node *node, ir_entity *ent)
  */
 static void sparc_set_frame_offset(ir_node *irn, int offset)
 {
-       (void) irn;
-       (void) offset;
-       /* TODO: correct offset if irn accesses the stack */
+       if (is_sparc_FrameAddr(irn)) {
+               sparc_symconst_attr_t *attr = get_irn_generic_attr(irn);
+               attr->fp_offset += offset;
+       } else {
+               sparc_load_store_attr_t *attr = get_sparc_load_store_attr(irn);
+               assert(attr->base.is_load_store);
+               attr->offset += offset;
+       }
 }
 
 static int sparc_get_sp_bias(const ir_node *irn)
@@ -174,10 +193,86 @@ static void sparc_before_ra(void *self)
        be_sched_fix_flags(cg->birg, &sparc_reg_classes[CLASS_sparc_flags], &sparc_flags_remat);
 }
 
+/**
+ * transform reload node => load
+ */
+static void transform_Reload(ir_node *node)
+{
+       ir_graph  *irg    = get_irn_irg(node);
+       ir_node   *block  = get_nodes_block(node);
+       dbg_info  *dbgi   = get_irn_dbg_info(node);
+       ir_node   *ptr    = get_irg_frame(irg);
+       ir_node   *mem    = get_irn_n(node, be_pos_Reload_mem);
+       ir_mode   *mode   = get_irn_mode(node);
+       ir_entity *entity = be_get_frame_entity(node);
+       const arch_register_t *reg;
+       ir_node   *proj;
+       ir_node   *load;
+
+       ir_node  *sched_point = sched_prev(node);
+
+       load = new_bd_sparc_Load(dbgi, block, ptr, mem, mode, entity, false, 0, true);
+       sched_add_after(sched_point, load);
+       sched_remove(node);
+
+       proj = new_rd_Proj(dbgi, load, mode, pn_sparc_Load_res);
+
+       reg = arch_get_irn_register(node);
+       arch_set_irn_register(proj, reg);
+
+       exchange(node, proj);
+}
+
+/**
+ * transform spill node => store
+ */
+static void transform_Spill(ir_node *node)
+{
+       ir_graph  *irg    = get_irn_irg(node);
+       ir_node   *block  = get_nodes_block(node);
+       dbg_info  *dbgi   = get_irn_dbg_info(node);
+       ir_node   *ptr    = get_irg_frame(irg);
+       ir_node   *mem    = new_NoMem();
+       ir_node   *val    = get_irn_n(node, be_pos_Spill_val);
+       ir_mode   *mode   = get_irn_mode(val);
+       ir_entity *entity = be_get_frame_entity(node);
+       ir_node   *sched_point;
+       ir_node   *store;
+
+       sched_point = sched_prev(node);
+       store = new_bd_sparc_Store(dbgi, block, ptr, val, mem, mode, entity, false, 0, true);
+       sched_remove(node);
+       sched_add_after(sched_point, store);
+
+       exchange(node, store);
+}
+
+/**
+ * walker to transform be_Spill and be_Reload nodes
+ */
+static void sparc_after_ra_walker(ir_node *block, void *data)
+{
+       ir_node *node, *prev;
+       (void) data;
+
+       for (node = sched_last(block); !sched_is_begin(node); node = prev) {
+               prev = sched_prev(node);
+
+               if (be_is_Reload(node)) {
+                       transform_Reload(node);
+               } else if (be_is_Spill(node)) {
+                       transform_Spill(node);
+               }
+       }
+}
+
+
 static void sparc_after_ra(void *self)
 {
-       (void) self;
-       /* Some stuff you need to do immediatly after register allocation */
+       sparc_code_gen_t *cg = self;
+       be_coalesce_spillslots(cg->birg);
+
+       irg_block_walk_graph(cg->irg, NULL, sparc_after_ra_walker, NULL);
 }
 
 
@@ -222,7 +317,7 @@ static void *sparc_cg_init(be_irg_t *birg)
 
        if (! int_tp) {
                /* create an integer type with machine size */
-               int_tp = new_type_primitive(new_id_from_chars("int", 3), mode_Is);
+               int_tp = new_type_primitive(mode_Is);
        }
 
        cg                               = XMALLOC(sparc_code_gen_t);
@@ -237,8 +332,6 @@ static void *sparc_cg_init(be_irg_t *birg)
        //cg->unknown_fpa               = NULL;
        cg->dump                                = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0;
 
-       FIRM_DBG_REGISTER(cg->mod, "firm.be.sparc.cg");
-
        /* enter the current code generator */
        isa->cg = cg;
 
@@ -271,7 +364,7 @@ static arch_env_t *sparc_init(FILE *outfile)
        static int run_once = 0;
        sparc_isa_t *isa;
 
-       if(run_once)
+       if (run_once)
                return NULL;
        run_once = 1;
 
@@ -296,7 +389,7 @@ static void sparc_done(void *self)
        sparc_isa_t *isa = self;
 
        /* emit now all global declarations */
-       be_gas_emit_decls(isa->arch_env.main_env, 0);
+       be_gas_emit_decls(isa->arch_env.main_env);
 
        be_emit_exit();
        free(self);
@@ -322,7 +415,7 @@ static const arch_register_class_t *sparc_get_reg_class(unsigned i)
  * @param mode The mode in question.
  * @return A register class which can hold values of the given mode.
  */
-const arch_register_class_t *sparc_get_reg_class_for_mode(const ir_mode *mode)
+static const arch_register_class_t *sparc_get_reg_class_for_mode(const ir_mode *mode)
 {
        if (mode_is_float(mode))
                return &sparc_reg_classes[CLASS_sparc_fp];
@@ -377,7 +470,7 @@ static const arch_register_t *sparc_abi_prologue(void *self, ir_node **mem,
        (void) mem;
        (void) stack_bias;
 
-       if(env->flags.try_omit_fp)
+       if (env->flags.try_omit_fp)
                return env->arch_env->sp;
 
        //panic("framepointer not implemented yet");
@@ -408,8 +501,8 @@ static const be_abi_callbacks_t sparc_abi_callbacks = {
  * @param method_type The type of the method (procedure) in question.
  * @param abi         The abi object to be modified
  */
-void sparc_get_call_abi(const void *self, ir_type *method_type,
-                           be_abi_call_t *abi)
+static void sparc_get_call_abi(const void *self, ir_type *method_type,
+                               be_abi_call_t *abi)
 {
        ir_type  *tp;
        ir_mode  *mode;
@@ -428,13 +521,17 @@ void sparc_get_call_abi(const void *self, ir_type *method_type,
        be_abi_call_set_flags(abi, call_flags, &sparc_abi_callbacks);
 
        for (i = 0; i < n; i++) {
-               /* TODO: implement register parameter: */
                /* reg = get reg for param i;          */
                /* be_abi_call_param_reg(abi, i, reg); */
-               /* default: all parameters on stack */
-               tp   = get_method_param_type(method_type, i);
-               mode = get_type_mode(tp);
-               be_abi_call_param_stack(abi, i, mode, 4, 0, 0);
+
+               /* pass args 0-5 via registers, remaining via stack */
+               if (i < 6) {
+                       be_abi_call_param_reg(abi, i, sparc_get_RegParam_reg(i));
+               } else {
+                       tp   = get_method_param_type(method_type, i);
+                       mode = get_type_mode(tp);
+                       be_abi_call_param_stack(abi, i, mode, 4, 0, 0);
+               }
        }
 
        /* TODO: set correct return register */
@@ -448,11 +545,11 @@ void sparc_get_call_abi(const void *self, ir_type *method_type,
        }
 }
 
-int sparc_to_appear_in_schedule(void *block_env, const ir_node *irn)
+static int sparc_to_appear_in_schedule(void *block_env, const ir_node *irn)
 {
        (void) block_env;
 
-       if(!is_sparc_irn(irn))
+       if (!is_sparc_irn(irn))
                return -1;
 
        return 1;
@@ -503,7 +600,8 @@ static int sparc_get_reg_class_alignment(const arch_register_class_t *cls)
 /**
  * Returns the libFirm configuration parameter for this backend.
  */
-static const backend_params *sparc_get_backend_params(void) {
+static const backend_params *sparc_get_backend_params(void)
+{
        static backend_params p = {
                0,     /* no dword lowering */
                0,     /* no inline assembly */
@@ -525,16 +623,14 @@ static const be_execution_unit_t ***sparc_get_allowed_execution_units(
 {
        (void) irn;
        /* TODO */
-       assert(0);
-       return NULL;
+       panic("sparc_get_allowed_execution_units not implemented yet");
 }
 
 static const be_machine_t *sparc_get_machine(const void *self)
 {
        (void) self;
        /* TODO */
-       assert(0);
-       return NULL;
+       panic("sparc_get_machine not implemented yet");
 }
 
 static ir_graph **sparc_get_backend_irg_list(const void *self,
@@ -578,6 +674,7 @@ const arch_isa_if_t sparc_isa_if = {
        sparc_is_valid_clobber
 };
 
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc);
 void be_init_arch_sparc(void)
 {
        be_register_isa_if("sparc", &sparc_isa_if);
@@ -585,4 +682,3 @@ void be_init_arch_sparc(void)
        sparc_init_transform();
        sparc_init_emitter();
 }
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc);