Commit c563dd65 authored by Matthias Braun's avatar Matthias Braun
Browse files

fix sparc stack offset, stack must be 8byte aligned on calls

[r27784]
parent 94786154
......@@ -65,11 +65,6 @@
#include "sparc_transform.h"
#include "sparc_emitter.h"
// sparc ABI requires a min stacksize to
// save registers in case of a trap etc.
// by now we assume only non-leaf procedures: 92 + 4 (padding)
#define SPARC_MIN_STACKSIZE 112
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
static arch_irn_class_t sparc_classify(const ir_node *irn)
......@@ -113,10 +108,17 @@ static void sparc_set_frame_offset(ir_node *irn, int offset)
}
}
static int sparc_get_sp_bias(const ir_node *irn)
static int sparc_get_sp_bias(const ir_node *node)
{
(void) irn;
return SPARC_MIN_STACKSIZE;
if (is_sparc_Save(node)) {
const sparc_save_attr_t *attr = get_sparc_save_attr_const(node);
/* Note we do not retport the change of the SPARC_MIN_STACKSIZE
* size, since we have additional magic in the emitter which
* calculates that! */
assert(attr->initial_stacksize >= SPARC_MIN_STACKSIZE);
return attr->initial_stacksize - SPARC_MIN_STACKSIZE;
}
return 0;
}
/* fill register allocator interface */
......@@ -315,7 +317,7 @@ static sparc_isa_t sparc_isa_template = {
&sparc_gp_regs[REG_FP], /* base pointer register */
&sparc_reg_classes[CLASS_sparc_gp], /* link pointer register class */
-1, /* stack direction */
1, /* power of two stack alignment for calls, 2^2 == 4 */
3, /* power of two stack alignment for calls, 2^2 == 4 */
NULL, /* main environment */
7, /* costs for a spill instruction */
5, /* costs for a reload instruction */
......@@ -493,7 +495,7 @@ static ir_type *sparc_get_between_type(void *self)
if (between_type == NULL) {
between_type = new_type_class(new_id_from_str("sparc_between_type"));
set_type_size_bytes(between_type, 0);
set_type_size_bytes(between_type, SPARC_MIN_STACKSIZE);
}
return between_type;
......@@ -526,7 +528,6 @@ static const arch_register_t *sparc_abi_prologue(void *self, ir_node **mem,
(void) mem;
(void) stack_bias;
*stack_bias -= SPARC_MIN_STACKSIZE;
sp_proj = new_r_Proj(save, sp->reg_class->mode, pn_sparc_Save_stack);
*mem = new_r_Proj(save, mode_M, pn_sparc_Save_mem);
......
......@@ -59,4 +59,19 @@ struct sparc_transform_env_t {
void sparc_finish_irg(sparc_code_gen_t *cg);
/**
* Sparc ABI requires some space which is always available at the top of
* the stack. It contains:
* 16*4 bytes space for spilling the register window
* 1*4 byte holding a pointer to space for agregate returns (the space is
* always reserved, regardless wether we have an agregate return
* or not)
* 6*4 bytes Space for spilling parameters 0-5. For the cases when someone
* takes the adress of a parameter. I guess this is also there so
* the implementation of va_args gets easier -> We can simply store
* param 0-5 in this spaces and then handle va_next by simply
* incrementing the stack pointer
*/
#define SPARC_MIN_STACKSIZE 92
#endif
......@@ -57,13 +57,6 @@
#define SNPRINTF_BUF_LEN 128
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
/**
* attribute of SAVE node which follows immediatelly after the START node
* we need this to correct all offsets since SPARC expects
* some reserved stack space after the stackpointer
*/
const sparc_save_attr_t *save_attr;
/**
* Returns the register at in position pos.
*/
......@@ -155,16 +148,27 @@ void sparc_emit_reg_or_imm(const ir_node *node, int pos)
}
}
static bool is_stack_pointer_relative(const ir_node *node)
{
const arch_register_t *sp = &sparc_gp_regs[REG_SP];
return (is_sparc_St(node) && get_in_reg(node, n_sparc_St_ptr) == sp)
|| (is_sparc_Ld(node) && get_in_reg(node, n_sparc_Ld_ptr) == sp);
}
/**
* emit SP offset
*/
void sparc_emit_offset(const ir_node *node)
{
const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
assert(attr->base.is_load_store);
if (attr->offset != 0) {
be_emit_irprintf("%+ld", attr->offset);
long offset = attr->offset;
/* bad hack: the real stack stuff is behind the always-there spill
* space for the register window and stack */
if (is_stack_pointer_relative(node))
offset += SPARC_MIN_STACKSIZE;
if (offset != 0) {
be_emit_irprintf("%+ld", offset);
}
}
......@@ -326,7 +330,7 @@ static void emit_be_IncSP(const ir_node *irn)
*/
static void emit_sparc_Save(const ir_node *irn)
{
save_attr = get_sparc_save_attr_const(irn);
const sparc_save_attr_t *save_attr = get_sparc_save_attr_const(irn);
be_emit_cstring("\tsave ");
sparc_emit_source_register(irn, 0);
be_emit_irprintf(", %d, ", -save_attr->initial_stacksize);
......@@ -570,7 +574,7 @@ static void emit_sparc_FrameAddr(const ir_node *irn)
be_emit_cstring("\tadd ");
sparc_emit_source_register(irn, 0);
be_emit_cstring(", ");
be_emit_irprintf("%ld", attr->fp_offset + save_attr->initial_stacksize);
be_emit_irprintf("%ld", attr->fp_offset);
} else {
be_emit_cstring("\tsub ");
sparc_emit_source_register(irn, 0);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment