Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
c563dd65
Commit
c563dd65
authored
Jul 22, 2010
by
Matthias Braun
Browse files
fix sparc stack offset, stack must be 8byte aligned on calls
[r27784]
parent
94786154
Changes
3
Hide whitespace changes
Inline
Side-by-side
ir/be/sparc/bearch_sparc.c
View file @
c563dd65
...
...
@@ -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
);
...
...
ir/be/sparc/bearch_sparc_t.h
View file @
c563dd65
...
...
@@ -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
ir/be/sparc/sparc_emitter.c
View file @
c563dd65
...
...
@@ -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
(
"
\t
save "
);
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
(
"
\t
add "
);
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
(
"
\t
sub "
);
sparc_emit_source_register
(
irn
,
0
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment