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
637450ac
Commit
637450ac
authored
Jul 22, 2010
by
Matthias Braun
Browse files
perform custom abi construction in sparc as well to handle floatingpoint
[r27788]
parent
4ec0521f
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
ir/be/arm/arm_cconv.c
View file @
637450ac
...
...
@@ -31,7 +31,7 @@
#include
"xmalloc.h"
#include
"error.h"
calling_convention_t
*
decide_calling_convention
(
ir_type
*
function_type
)
calling_convention_t
*
arm_
decide_calling_convention
(
ir_type
*
function_type
)
{
int
stack_offset
=
0
;
reg_or_stackslot_t
*
params
;
...
...
@@ -128,7 +128,7 @@ calling_convention_t *decide_calling_convention(ir_type *function_type)
return
cconv
;
}
void
free_calling_convention
(
calling_convention_t
*
cconv
)
void
arm_
free_calling_convention
(
calling_convention_t
*
cconv
)
{
free
(
cconv
->
parameters
);
free
(
cconv
->
results
);
...
...
ir/be/arm/arm_cconv.h
View file @
637450ac
...
...
@@ -102,11 +102,11 @@ typedef struct calling_convention_t
* Decides what goes to register or to stack and what stack offsets/
* datatypes are used.
*/
calling_convention_t
*
decide_calling_convention
(
ir_type
*
function_type
);
calling_convention_t
*
arm_
decide_calling_convention
(
ir_type
*
function_type
);
/**
* free memory used by a calling_convention_t
*/
void
free_calling_convention
(
calling_convention_t
*
cconv
);
void
arm_
free_calling_convention
(
calling_convention_t
*
cconv
);
#endif
ir/be/arm/arm_spec.pl
View file @
637450ac
...
...
@@ -316,7 +316,6 @@ LinkMovPC => {
"
\t
arch_irn_add_flags(res, arch_irn_flags_modify_flags);
",
emit
=>
"
. mov lr, pc
\n
"
.
"
. mov pc, %SO
",
mode
=>
"
mode_T
",
},
# mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
...
...
@@ -330,7 +329,6 @@ LinkLdrPC => {
custominit
=>
"
arch_irn_add_flags(res, arch_irn_flags_modify_flags);
",
emit
=>
"
. mov lr, pc
\n
"
.
"
. ldr pc, %SO
",
mode
=>
"
mode_T
",
},
Bl
=>
{
...
...
@@ -341,7 +339,6 @@ Bl => {
attr
=>
"
ir_entity *entity, int symconst_offset
",
custominit
=>
"
arch_irn_add_flags(res, arch_irn_flags_modify_flags);
",
emit
=>
'
. bl %SC
',
mode
=>
"
mode_T
",
},
# this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
...
...
@@ -442,7 +439,7 @@ Str => {
op_flags
=>
[
"
labeled
",
"
fragile
"
],
state
=>
"
exc_pinned
",
ins
=>
[
"
ptr
",
"
val
",
"
mem
"
],
outs
=>
[
"
mem
"
],
outs
=>
[
"
M
"
],
reg_req
=>
{
in
=>
[
"
gp
",
"
gp
",
"
none
"
],
out
=>
[
"
none
"
]
},
emit
=>
'
. str%SM %S1, [%S0, #%O]
',
mode
=>
"
mode_M
",
...
...
ir/be/arm/arm_transform.c
View file @
637450ac
...
...
@@ -1299,7 +1299,7 @@ static ir_node *gen_Proj_Proj_Call(ir_node *node)
ir_node
*
call
=
get_Proj_pred
(
get_Proj_pred
(
node
));
ir_node
*
new_call
=
be_transform_node
(
call
);
ir_type
*
function_type
=
get_Call_type
(
call
);
calling_convention_t
*
cconv
=
decide_calling_convention
(
function_type
);
calling_convention_t
*
cconv
=
arm_
decide_calling_convention
(
function_type
);
const
reg_or_stackslot_t
*
res
=
&
cconv
->
results
[
pn
];
ir_mode
*
mode
;
int
regn
;
...
...
@@ -1312,7 +1312,7 @@ static ir_node *gen_Proj_Proj_Call(ir_node *node)
}
mode
=
res
->
reg0
->
reg_class
->
mode
;
free_calling_convention
(
cconv
);
arm_
free_calling_convention
(
cconv
);
return
new_r_Proj
(
new_call
,
mode
,
regn
);
}
...
...
@@ -1616,7 +1616,7 @@ static ir_node *gen_Call(ir_node *node)
ir_node
*
new_mem
=
be_transform_node
(
mem
);
dbg_info
*
dbgi
=
get_irn_dbg_info
(
node
);
ir_type
*
type
=
get_Call_type
(
node
);
calling_convention_t
*
cconv
=
decide_calling_convention
(
type
);
calling_convention_t
*
cconv
=
arm_
decide_calling_convention
(
type
);
int
n_params
=
get_Call_n_params
(
node
);
int
n_param_regs
=
sizeof
(
param_regs
)
/
sizeof
(
param_regs
[
0
]);
/* max inputs: memory, callee, register arguments */
...
...
@@ -1782,7 +1782,7 @@ static ir_node *gen_Call(ir_node *node)
/* copy pinned attribute */
set_irn_pinned
(
res
,
get_irn_pinned
(
node
));
free_calling_convention
(
cconv
);
arm_
free_calling_convention
(
cconv
);
return
res
;
}
...
...
@@ -1941,7 +1941,7 @@ void arm_transform_graph(arm_code_gen_t *cg)
abihelper
=
be_abihelper_prepare
(
irg
);
be_collect_stacknodes
(
abihelper
);
assert
(
cconv
==
NULL
);
cconv
=
decide_calling_convention
(
get_entity_type
(
entity
));
cconv
=
arm_
decide_calling_convention
(
get_entity_type
(
entity
));
create_stacklayout
(
irg
);
be_transform_graph
(
cg
->
irg
,
NULL
);
...
...
@@ -1949,7 +1949,7 @@ void arm_transform_graph(arm_code_gen_t *cg)
be_abihelper_finish
(
abihelper
);
abihelper
=
NULL
;
free_calling_convention
(
cconv
);
arm_
free_calling_convention
(
cconv
);
cconv
=
NULL
;
frame_type
=
get_irg_frame_type
(
irg
);
...
...
ir/be/beabihelper.c
View file @
637450ac
...
...
@@ -132,8 +132,8 @@ static void rsm_clear_regs(register_state_mapping_t *rsm,
}
}
static
void
rsm_add_reg
(
register_state_mapping_t
*
rsm
,
const
arch_register_t
*
reg
,
arch_irn_flags_t
flags
)
static
int
rsm_add_reg
(
register_state_mapping_t
*
rsm
,
const
arch_register_t
*
reg
,
arch_irn_flags_t
flags
)
{
int
input_idx
=
ARR_LEN
(
rsm
->
regs
);
int
cls_idx
=
reg
->
reg_class
->
index
;
...
...
@@ -144,6 +144,12 @@ static void rsm_add_reg(register_state_mapping_t *rsm,
assert
(
rsm
->
reg_index_map
[
cls_idx
][
reg_idx
]
==
-
1
);
rsm
->
reg_index_map
[
cls_idx
][
reg_idx
]
=
input_idx
;
ARR_APP1
(
reg_flag_t
,
rsm
->
regs
,
regflag
);
if
(
rsm
->
value_map
!=
NULL
)
{
ARR_APP1
(
ir_node
*
,
rsm
->
value_map
,
NULL
);
assert
(
ARR_LEN
(
rsm
->
value_map
)
==
ARR_LEN
(
rsm
->
regs
));
}
return
input_idx
;
}
...
...
@@ -317,8 +323,8 @@ void be_epilog_begin(beabi_helper_env_t *env)
void
be_epilog_add_reg
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
,
arch_irn_flags_t
flags
,
ir_node
*
value
)
{
rsm_add_reg
(
&
env
->
epilog
,
reg
,
flags
);
ARR_APP1
(
ir_node
*
,
env
->
epilog
.
value_map
,
value
);
int
index
=
rsm_add_reg
(
&
env
->
epilog
,
reg
,
flags
);
rsm_set_value
(
&
env
->
epilog
,
index
,
value
);
}
void
be_epilog_set_reg_value
(
beabi_helper_env_t
*
env
,
...
...
@@ -379,7 +385,7 @@ ir_node *be_epilog_create_return(beabi_helper_env_t *env, dbg_info *dbgi,
static
void
add_missing_keep_walker
(
ir_node
*
node
,
void
*
data
)
{
int
n_outs
,
i
;
unsigned
found_projs
=
0
;
unsigned
*
found_projs
;
const
ir_edge_t
*
edge
;
ir_mode
*
mode
=
get_irn_mode
(
node
);
ir_node
*
last_keep
;
...
...
@@ -391,7 +397,7 @@ static void add_missing_keep_walker(ir_node *node, void *data)
if
(
n_outs
<=
0
)
return
;
assert
(
n_outs
<
(
int
)
sizeof
(
unsigned
)
*
8
);
rbitset_alloca
(
found_projs
,
n_outs
);
foreach_out_edge
(
node
,
edge
)
{
ir_node
*
succ
=
get_edge_src_irn
(
edge
);
int
pn
;
...
...
@@ -405,7 +411,7 @@ static void add_missing_keep_walker(ir_node *node, void *data)
pn
=
get_Proj_proj
(
succ
);
assert
(
pn
<
n_outs
);
found_projs
|=
1
<<
pn
;
rbitset_set
(
found_projs
,
pn
)
;
}
...
...
@@ -417,7 +423,7 @@ static void add_missing_keep_walker(ir_node *node, void *data)
const
arch_register_req_t
*
req
;
const
arch_register_class_t
*
cls
;
if
(
found_projs
&
(
1
<<
i
))
{
if
(
rbitset_is_set
(
found_projs
,
i
))
{
continue
;
}
...
...
ir/be/scripts/generate_new_opcodes.pl
View file @
637450ac
...
...
@@ -206,7 +206,9 @@ sub create_constructor {
}
elsif
(
$out_arity
eq
"
dynamic
")
{
$out_arity
=
$ARITY_DYNAMIC
;
}
if
(
$out_arity
!=
0
&&
$out_arity
!=
1
&&
!
defined
(
$known_mode
))
{
$known_mode
=
"
mode_T
";
}
my
$comment
=
$n
->
{"
comment
"};
if
(
!
exists
(
$n
->
{"
comment
"}))
{
...
...
ir/be/sparc/bearch_sparc.c
View file @
637450ac
...
...
@@ -48,7 +48,6 @@
#include
"../belower.h"
#include
"../besched.h"
#include
"be.h"
#include
"../beabi.h"
#include
"../bemachine.h"
#include
"../beilpsched.h"
#include
"../bemodule.h"
...
...
@@ -182,10 +181,9 @@ static void sparc_before_ra(void *self)
*/
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_ir
g
_frame
(
irg
);
ir_node
*
ptr
=
get_ir
n_n
(
node
,
be_pos_Spill
_frame
);
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
);
...
...
@@ -212,10 +210,9 @@ static void transform_Reload(ir_node *node)
*/
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_ir
g
_frame
(
irg
);
ir_node
*
ptr
=
get_ir
n_n
(
node
,
be_pos_Spill
_frame
);
ir_node
*
mem
=
new_NoMem
();
ir_node
*
val
=
get_irn_n
(
node
,
be_pos_Spill_val
);
ir_mode
*
mode
=
get_irn_mode
(
val
);
...
...
@@ -313,16 +310,17 @@ static void *sparc_cg_init(ir_graph *irg)
const
arch_isa_if_t
sparc_isa_if
;
static
sparc_isa_t
sparc_isa_template
=
{
{
&
sparc_isa_if
,
/* isa interface implementation */
&
sparc_gp_regs
[
REG_SP
],
/* stack pointer register */
&
sparc_gp_regs
[
REG_FP
],
/* base pointer register */
&
sparc_reg_classes
[
CLASS_sparc_gp
],
/* link pointer register class */
-
1
,
/* stack direction */
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 */
false
,
/* no custom abi handling */
&
sparc_isa_if
,
/* isa interface implementation */
&
sparc_gp_regs
[
REG_SP
],
/* stack pointer register */
&
sparc_gp_regs
[
REG_FRAME_POINTER
],
/* base pointer register */
&
sparc_reg_classes
[
CLASS_sparc_gp
],
/* link pointer register class */
-
1
,
/* stack direction */
3
,
/* power of two stack alignment
for calls */
NULL
,
/* main environment */
7
,
/* costs for a spill instruction */
5
,
/* costs for a reload instruction */
true
,
/* custom abi handling */
},
NULL
/* current code generator */
};
...
...
@@ -468,196 +466,6 @@ static const arch_register_class_t *sparc_get_reg_class_for_mode(const ir_mode *
return
&
sparc_reg_classes
[
CLASS_sparc_gp
];
}
typedef
struct
{
be_abi_call_flags_bits_t
flags
;
ir_graph
*
irg
;
}
sparc_abi_env_t
;
static
void
*
sparc_abi_init
(
const
be_abi_call_t
*
call
,
ir_graph
*
irg
)
{
sparc_abi_env_t
*
env
=
XMALLOC
(
sparc_abi_env_t
);
be_abi_call_flags_t
fl
=
be_abi_call_get_flags
(
call
);
env
->
flags
=
fl
.
bits
;
env
->
irg
=
irg
;
return
env
;
}
/**
* Get the between type for that call.
* @param self The callback object.
* @return The between type of for that call.
*/
static
ir_type
*
sparc_get_between_type
(
void
*
self
)
{
static
ir_type
*
between_type
=
NULL
;
(
void
)
self
;
if
(
between_type
==
NULL
)
{
between_type
=
new_type_class
(
new_id_from_str
(
"sparc_between_type"
));
set_type_size_bytes
(
between_type
,
SPARC_MIN_STACKSIZE
);
}
return
between_type
;
}
/**
* Build the prolog, return the BASE POINTER register
*/
static
const
arch_register_t
*
sparc_abi_prologue
(
void
*
self
,
ir_node
**
mem
,
pmap
*
reg_map
,
int
*
stack_bias
)
{
sparc_abi_env_t
*
env
=
self
;
ir_node
*
block
=
get_irg_start_block
(
env
->
irg
);
const
arch_register_t
*
fp
=
&
sparc_gp_regs
[
REG_FP
];
const
arch_register_t
*
sp
=
&
sparc_gp_regs
[
REG_SP
];
// sp
ir_node
*
sp_proj
=
be_abi_reg_map_get
(
reg_map
,
sp
);
//ir_type *frame_type = get_irg_frame_type(env->irg);
//frame_alloc_area(frame_type, reserved_stack_size, 1, 1);
// alloc min required stack space
// TODO: the min stacksize depends on wether this is a leaf procedure or not
ir_node
*
save
=
new_bd_sparc_Save
(
NULL
,
block
,
sp_proj
,
*
mem
,
SPARC_MIN_STACKSIZE
);
(
void
)
reg_map
;
(
void
)
mem
;
(
void
)
stack_bias
;
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
);
arch_set_irn_register
(
sp_proj
,
sp
);
be_abi_reg_map_set
(
reg_map
,
sp
,
sp_proj
);
// we always have a framepointer
return
fp
;
}
/* Build the epilog */
static
void
sparc_abi_epilogue
(
void
*
self
,
ir_node
*
bl
,
ir_node
**
mem
,
pmap
*
reg_map
)
{
(
void
)
self
;
(
void
)
bl
;
(
void
)
mem
;
(
void
)
reg_map
;
}
static
const
be_abi_callbacks_t
sparc_abi_callbacks
=
{
sparc_abi_init
,
free
,
sparc_get_between_type
,
sparc_abi_prologue
,
sparc_abi_epilogue
,
};
static
const
arch_register_t
*
gp_param_out_regs
[]
=
{
&
sparc_gp_regs
[
REG_O0
],
&
sparc_gp_regs
[
REG_O1
],
&
sparc_gp_regs
[
REG_O2
],
&
sparc_gp_regs
[
REG_O3
],
&
sparc_gp_regs
[
REG_O4
],
&
sparc_gp_regs
[
REG_O5
],
};
static
const
arch_register_t
*
gp_param_in_regs
[]
=
{
&
sparc_gp_regs
[
REG_I0
],
&
sparc_gp_regs
[
REG_I1
],
&
sparc_gp_regs
[
REG_I2
],
&
sparc_gp_regs
[
REG_I3
],
&
sparc_gp_regs
[
REG_I4
],
&
sparc_gp_regs
[
REG_I5
],
};
/**
* get register for outgoing parameters 1-6
*/
static
const
arch_register_t
*
sparc_get_RegParamOut_reg
(
int
n
)
{
assert
(
n
<
6
&&
n
>=
0
&&
"trying to get (out) register for param >= 6"
);
return
gp_param_out_regs
[
n
];
}
/**
* get register for incoming parameters 1-6
*/
static
const
arch_register_t
*
sparc_get_RegParamIn_reg
(
int
n
)
{
assert
(
n
<
6
&&
n
>=
0
&&
"trying to get (in) register for param >= 6"
);
return
gp_param_in_regs
[
n
];
}
/**
* Get the ABI restrictions for procedure calls.
* @param self The this pointer.
* @param method_type The type of the method (procedure) in question.
* @param abi The abi object to be modified
*/
static
void
sparc_get_call_abi
(
const
void
*
self
,
ir_type
*
method_type
,
be_abi_call_t
*
abi
)
{
ir_type
*
tp
;
ir_mode
*
mode
;
int
i
,
n
=
get_method_n_params
(
method_type
);
be_abi_call_flags_t
call_flags
;
(
void
)
self
;
/* set abi flags for calls */
call_flags
.
bits
.
left_to_right
=
0
;
call_flags
.
bits
.
store_args_sequential
=
1
;
call_flags
.
bits
.
try_omit_fp
=
0
;
call_flags
.
bits
.
fp_free
=
0
;
call_flags
.
bits
.
call_has_imm
=
1
;
/* set stack parameter passing style */
be_abi_call_set_flags
(
abi
,
call_flags
,
&
sparc_abi_callbacks
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
ir_type
*
type
=
get_method_param_type
(
method_type
,
i
);
ir_mode
*
mode
=
get_type_mode
(
type
);
if
(
mode_is_float
(
mode
)
||
i
>=
6
)
{
unsigned
align
=
get_type_size_bytes
(
type
);
be_abi_call_param_stack
(
abi
,
i
,
mode
,
align
,
0
,
0
,
ABI_CONTEXT_BOTH
);
continue
;
}
/* pass integer params 0-5 via registers.
* On sparc we need to set the ABI context since register names of
* parameters change to i0-i5 if we are the callee */
be_abi_call_param_reg
(
abi
,
i
,
sparc_get_RegParamOut_reg
(
i
),
ABI_CONTEXT_CALLER
);
be_abi_call_param_reg
(
abi
,
i
,
sparc_get_RegParamIn_reg
(
i
),
ABI_CONTEXT_CALLEE
);
}
n
=
get_method_n_ress
(
method_type
);
/* more than 1 result not supported */
assert
(
n
<=
1
);
for
(
i
=
0
;
i
<
n
;
++
i
)
{
tp
=
get_method_res_type
(
method_type
,
i
);
mode
=
get_type_mode
(
tp
);
/* set return value register: return value is in i0 resp. f0 */
if
(
mode_is_float
(
mode
))
{
be_abi_call_res_reg
(
abi
,
i
,
&
sparc_fp_regs
[
REG_F0
],
ABI_CONTEXT_BOTH
);
}
else
{
be_abi_call_res_reg
(
abi
,
i
,
&
sparc_gp_regs
[
REG_I0
],
ABI_CONTEXT_CALLEE
);
be_abi_call_res_reg
(
abi
,
i
,
&
sparc_gp_regs
[
REG_O0
],
ABI_CONTEXT_CALLER
);
}
}
}
static
int
sparc_to_appear_in_schedule
(
void
*
block_env
,
const
ir_node
*
irn
)
{
(
void
)
block_env
;
...
...
@@ -773,7 +581,7 @@ const arch_isa_if_t sparc_isa_if = {
sparc_get_n_reg_class
,
sparc_get_reg_class
,
sparc_get_reg_class_for_mode
,
sparc_get_call_abi
,
NULL
,
sparc_get_code_generator_if
,
sparc_get_list_sched_selector
,
sparc_get_ilp_sched_selector
,
...
...
ir/be/sparc/sparc_cconv.c
0 → 100644
View file @
637450ac
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief calling convention helpers
* @author Matthias Braun
* @version $Id$
*/
#include
"config.h"
#include
"sparc_cconv.h"
#include
"irmode.h"
#include
"typerep.h"
#include
"xmalloc.h"
#include
"error.h"
static
const
arch_register_t
*
map_i_to_o_reg
(
const
arch_register_t
*
reg
)
{
unsigned
idx
=
arch_register_get_index
(
reg
);
assert
(
REG_I0
<=
idx
&&
idx
<=
REG_I7
);
idx
+=
REG_O0
-
REG_I0
;
assert
(
REG_O0
<=
idx
&&
idx
<=
REG_O7
);
return
&
sparc_gp_regs
[
idx
];
}
calling_convention_t
*
sparc_decide_calling_convention
(
ir_type
*
function_type
,
bool
caller
)
{
int
stack_offset
=
0
;
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
;
int
regnum
;
int
float_regnum
;
calling_convention_t
*
cconv
;
/* determine how parameters are passed */
n_params
=
get_method_n_params
(
function_type
);
regnum
=
0
;
params
=
XMALLOCNZ
(
reg_or_stackslot_t
,
n_params
);
for
(
i
=
0
;
i
<
n_params
;
++
i
)
{
ir_type
*
param_type
=
get_method_param_type
(
function_type
,
i
);
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
)
reg
=
map_i_to_o_reg
(
reg
);
param
->
reg0
=
reg
;
}
else
{
param
->
offset
=
stack_offset
;
/* increase offset 4 bytes so everything is aligned */
stack_offset
+=
bits
>
32
?
bits
/
8
:
4
;
continue
;
}
/* we might need a 2nd 32bit component (for 64bit or double values) */
if
(
bits
>
32
)
{
if
(
bits
>
64
)
panic
(
"only 32 and 64bit modes supported in sparc backend"
);
if
(
regnum
<
n_param_regs
)
{
const
arch_register_t
*
reg
=
param_regs
[
regnum
++
];
if
(
caller
)
reg
=
map_i_to_o_reg
(
reg
);
param
->
reg1
=
reg
;
}
else
{
ir_mode
*
mode
=
param_regs
[
0
]
->
reg_class
->
mode
;
ir_type
*
type
=
get_type_for_mode
(
mode
);
param
->
type
=
type
;
param
->
offset
=
stack_offset
;
assert
(
get_mode_size_bits
(
mode
)
==
32
);
stack_offset
+=
4
;
}
}
}
/* determine how results are passed */
n_results
=
get_method_n_ress
(
function_type
);
regnum
=
0
;
float_regnum
=
0
;
results
=
XMALLOCNZ
(
reg_or_stackslot_t
,
n_results
);
for
(
i
=
0
;
i
<
n_results
;
++
i
)
{
ir_type
*
result_type
=
get_method_res_type
(
function_type
,
i
);
ir_mode
*
result_mode
=
get_type_mode
(
result_type
);
reg_or_stackslot_t
*
result
=
&
results
[
i
];
if
(
mode_is_float
(
result_mode
))
{
if
(
float_regnum
>=
n_float_result_regs
)
{
panic
(
"Too many float results for sparc backend"
);
}
else
{
const
arch_register_t
*
reg
=
float_result_regs
[
float_regnum
++
];
result
->
reg0
=
reg
;
}
}
else
{
if
(
get_mode_size_bits
(
result_mode
)
>
32
)
{
panic
(
"Results with more than 32bits not supported by sparc backend yet"
);
}
if
(
regnum
>=
n_param_regs
)
{
panic
(
"Too many results for sparc backend"
);
}
else
{
const
arch_register_t
*
reg
=
param_regs
[
regnum
++
];
if
(
caller
)
reg
=
map_i_to_o_reg
(
reg
);
result
->
reg0
=
reg
;
}
}
}
cconv
=
XMALLOCZ
(
calling_convention_t
);
cconv
->
parameters
=
params
;
cconv
->
param_stack_size
=
stack_offset
;
cconv
->
results
=
results
;
return
cconv
;
}
void
sparc_free_calling_convention
(
calling_convention_t
*
cconv
)
{
free
(
cconv
->
parameters
);
free
(
cconv
->
results
);
free
(
cconv
);
}
ir/be/sparc/sparc_cconv.h
0 → 100644
View file @
637450ac
/*