sparc: attempt to fix stack alignment/address for omit-fp again
[libfirm] / ir / be / sparc / sparc_stackframe.c
index 5407e19..36370d5 100644 (file)
@@ -31,9 +31,9 @@
 #include "sparc_new_nodes.h"
 #include "sparc_cconv.h"
 #include "bitfiddle.h"
-#include "../bearch.h"
-#include "../benode.h"
-#include "../besched.h"
+#include "bearch.h"
+#include "benode.h"
+#include "besched.h"
 
 static void set_irn_sp_bias(ir_node *node, int new_bias)
 {
@@ -65,7 +65,7 @@ static void process_bias(ir_node *block, bool sp_relative, int bias,
                if (entity != NULL) {
                        int offset = get_entity_offset(entity);
                        if (sp_relative)
-                               offset -= bias;
+                               offset += bias + SPARC_MIN_STACKSIZE;
                        arch_set_frame_offset(irn, offset);
                }
 
@@ -116,6 +116,13 @@ static void adjust_entity_offsets(ir_type *type, long offset)
        }
 }
 
+/**
+ * Perform some fixups for variadic functions.
+ * To make the rest of the frontend code easier to understand we add
+ * "dummy" parameters until the number of parameters transmitted in registers.
+ * (because otherwise the backend wouldn't store the value of the register
+ *  parameters into memory for the VLA magic)
+ */
 bool sparc_variadic_fixups(ir_graph *irg, calling_convention_t *cconv)
 {
        ir_entity *entity = get_irg_entity(irg);
@@ -154,7 +161,7 @@ bool sparc_variadic_fixups(ir_graph *irg, calling_convention_t *cconv)
        set_method_variadicity(new_mtp, get_method_variadicity(mtp));
        set_method_calling_convention(new_mtp, get_method_calling_convention(mtp));
        set_method_additional_properties(new_mtp, get_method_additional_properties(mtp));
-       set_lowered_type(mtp, new_mtp);
+       set_higher_type(new_mtp, mtp);
 
        set_entity_type(entity, new_mtp);
        }
@@ -209,7 +216,7 @@ static ir_type *compute_arg_type(ir_graph *irg, calling_convention_t *cconv,
                if (param->reg0 != NULL) {
                        /* use reserved spill space on between type */
                        if (entity != NULL) {
-                               long offset = SPARC_PARAMS_SPILL_OFFSET + i*4;
+                               long offset = SPARC_PARAMS_SPILL_OFFSET + i * SPARC_REGISTER_SIZE;
                                assert(i < SPARC_N_PARAM_REGS);
                                set_entity_owner(entity, between_type);
                                set_entity_offset(entity, offset);
@@ -226,7 +233,7 @@ static ir_type *compute_arg_type(ir_graph *irg, calling_convention_t *cconv,
        if (va_start_entity != NULL) {
                /* sparc_variadic_fixups() fiddled with our type, find out the
                 * original number of parameters */
-               ir_type *non_lowered   = get_associated_type(mtp);
+               ir_type *non_lowered   = get_higher_type(mtp);
                size_t   orig_n_params = get_method_n_params(non_lowered);
                long     offset;
                assert(get_method_variadicity(mtp) == variadicity_variadic);
@@ -252,7 +259,11 @@ void sparc_create_stacklayout(ir_graph *irg, calling_convention_t *cconv)
        memset(layout, 0, sizeof(*layout));
 
        between_type = new_type_class(new_id_from_str("sparc_between_type"));
-       set_type_size_bytes(between_type, SPARC_MIN_STACKSIZE);
+       if (cconv->omit_fp) {
+               set_type_size_bytes(between_type, 0);
+       } else {
+               set_type_size_bytes(between_type, SPARC_MIN_STACKSIZE);
+       }
 
        layout->frame_type     = get_irg_frame_type(irg);
        layout->between_type   = between_type;
@@ -306,12 +317,14 @@ static void process_frame_types(ir_graph *irg)
 
 void sparc_fix_stack_bias(ir_graph *irg)
 {
+       bool sp_relative = be_get_irg_stack_layout(irg)->sp_relative;
+
        ir_node *start_block = get_irg_start_block(irg);
 
        process_frame_types(irg);
 
        ir_reserve_resources(irg, IR_RESOURCE_BLOCK_VISITED);
        inc_irg_block_visited(irg);
-       process_bias(start_block, be_get_irg_stack_layout(irg)->sp_relative, 0, 0);
+       process_bias(start_block, sp_relative, 0, 0);
        ir_free_resources(irg, IR_RESOURCE_BLOCK_VISITED);
 }