Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
9a78c10b
Commit
9a78c10b
authored
Aug 05, 2011
by
Matthias Braun
Browse files
factor out code for address of register param taken
So sparc can handle this case now.
parent
9446bb8b
Changes
5
Hide whitespace changes
Inline
Side-by-side
ir/be/beabi.c
View file @
9a78c10b
...
...
@@ -1353,7 +1353,6 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl,
}
typedef
struct
lower_frame_sels_env_t
{
ir_entity
**
value_param_list
;
/**< the list of all value param entities */
ir_node
*
frame
;
/**< the current frame */
const
arch_register_class_t
*
sp_class
;
/**< register class of the stack pointer */
const
arch_register_class_t
*
link_class
;
/**< register class of the link pointer */
...
...
@@ -1378,111 +1377,12 @@ static void lower_frame_sels_walker(ir_node *irn, void *data)
ir_node
*
bl
=
get_nodes_block
(
irn
);
ir_node
*
nw
;
if
(
is_parameter_entity
(
ent
)
&&
get_entity_link
(
ent
)
==
NULL
)
{
/* replace by its copy from the argument type */
ARR_APP1
(
ir_entity
*
,
ctx
->
value_param_list
,
ent
);
/* just a mark */
set_entity_link
(
ent
,
ctx
->
value_param_list
);
}
nw
=
be_new_FrameAddr
(
ctx
->
sp_class
,
bl
,
ctx
->
frame
,
ent
);
exchange
(
irn
,
nw
);
}
}
}
/**
* Check if a value parameter is transmitted as a register.
* This might happen if the address of an parameter is taken which is
* transmitted in registers.
*
* Note that on some architectures this case must be handled specially
* because the place of the backing store is determined by their ABI.
*
* In the default case we move the entity to the frame type and create
* a backing store into the first block.
*/
static
void
fix_address_of_parameter_access
(
be_abi_irg_t
*
env
,
ir_graph
*
irg
,
ir_entity
**
value_param_list
)
{
be_abi_call_t
*
call
=
env
->
call
;
const
arch_env_t
*
arch_env
=
be_get_irg_arch_env
(
irg
);
size_t
n
=
ARR_LEN
(
value_param_list
);
size_t
i
;
bool
need_fixes
=
false
;
ir_node
*
first_store
=
NULL
;
ir_node
*
start_bl
;
ir_node
*
frame
;
ir_node
*
imem
;
ir_node
*
mem
;
ir_node
*
args
;
for
(
i
=
0
;
i
<
n
;
++
i
)
{
ir_entity
*
entity
=
value_param_list
[
i
];
size_t
pos
=
get_entity_parameter_number
(
entity
);
be_abi_call_arg_t
*
arg
=
get_call_arg
(
call
,
0
,
pos
,
1
);
if
(
arg
->
in_reg
)
{
need_fixes
=
true
;
DBG
((
dbg
,
LEVEL_2
,
"
\t
arg #%d need backing store
\n
"
,
pos
));
}
}
if
(
!
need_fixes
)
return
;
/* ok, change the graph */
start_bl
=
get_irg_start_block
(
irg
);
/* now create backing stores */
frame
=
get_irg_frame
(
irg
);
imem
=
get_irg_initial_mem
(
irg
);
mem
=
imem
;
args
=
get_irg_args
(
irg
);
for
(
i
=
0
;
i
<
n
;
++
i
)
{
ir_entity
*
entity
=
value_param_list
[
i
];
size_t
pos
=
get_entity_parameter_number
(
entity
);
be_abi_call_arg_t
*
arg
=
get_call_arg
(
call
,
0
,
pos
,
1
);
ir_node
*
addr
;
if
(
!
arg
->
in_reg
)
continue
;
/* address for the backing store */
addr
=
be_new_FrameAddr
(
arch_env
->
sp
->
reg_class
,
start_bl
,
frame
,
entity
);
if
(
entity
->
attr
.
parameter
.
doubleword_low_mode
!=
NULL
)
{
ir_mode
*
mode
=
entity
->
attr
.
parameter
.
doubleword_low_mode
;
ir_node
*
val0
=
new_r_Proj
(
args
,
mode
,
pos
);
ir_node
*
val1
=
new_r_Proj
(
args
,
mode
,
pos
+
1
);
ir_node
*
store0
=
new_r_Store
(
start_bl
,
mem
,
addr
,
val0
,
cons_none
);
ir_node
*
mem0
=
new_r_Proj
(
store0
,
mode_M
,
pn_Store_M
);
size_t
offset
=
get_mode_size_bits
(
mode
)
/
8
;
ir_mode
*
addr_mode
=
get_irn_mode
(
addr
);
ir_node
*
cnst
=
new_r_Const_long
(
irg
,
addr_mode
,
offset
);
ir_node
*
next_addr
=
new_r_Add
(
start_bl
,
addr
,
cnst
,
addr_mode
);
ir_node
*
store1
=
new_r_Store
(
start_bl
,
mem0
,
next_addr
,
val1
,
cons_none
);
mem
=
new_r_Proj
(
store1
,
mode_M
,
pn_Store_M
);
if
(
first_store
==
NULL
)
first_store
=
store0
;
}
else
{
ir_type
*
tp
=
get_entity_type
(
entity
);
ir_mode
*
mode
=
get_type_mode
(
tp
);
/* the backing store itself */
ir_node
*
val
=
new_r_Proj
(
args
,
mode
,
pos
);
ir_node
*
store
=
new_r_Store
(
start_bl
,
mem
,
addr
,
val
,
cons_none
);
mem
=
new_r_Proj
(
store
,
mode_M
,
pn_Store_M
);
if
(
first_store
==
NULL
)
first_store
=
store
;
}
}
assert
(
mem
!=
imem
);
edges_reroute
(
imem
,
mem
);
set_Store_mem
(
first_store
,
imem
);
}
/**
* The start block has no jump, instead it has an initial exec Proj.
* The backend wants to handle all blocks the same way, so we replace
...
...
@@ -1514,64 +1414,6 @@ static void fix_start_block(ir_graph *irg)
}
}
/**
* Update the entity of Sels to the outer value parameters.
*/
static
void
update_outer_frame_sels
(
ir_node
*
irn
,
void
*
env
)
{
lower_frame_sels_env_t
*
ctx
=
(
lower_frame_sels_env_t
*
)
env
;
ir_node
*
ptr
;
ir_entity
*
ent
;
if
(
!
is_Sel
(
irn
))
return
;
ptr
=
get_Sel_ptr
(
irn
);
if
(
!
is_arg_Proj
(
ptr
))
return
;
if
(
get_Proj_proj
(
ptr
)
!=
ctx
->
static_link_pos
)
return
;
ent
=
get_Sel_entity
(
irn
);
if
(
is_parameter_entity
(
ent
))
{
/* check, if we have not seen this entity before */
if
(
get_entity_link
(
ent
)
==
NULL
)
{
ARR_APP1
(
ir_entity
*
,
ctx
->
value_param_list
,
ent
);
/* just a mark */
set_entity_link
(
ent
,
ctx
->
value_param_list
);
}
}
}
/**
* Fix access to outer local variables.
*/
static
void
fix_outer_variable_access
(
be_abi_irg_t
*
env
,
lower_frame_sels_env_t
*
ctx
)
{
int
i
;
ir_graph
*
irg
;
(
void
)
env
;
for
(
i
=
get_class_n_members
(
ctx
->
frame_tp
)
-
1
;
i
>=
0
;
--
i
)
{
ir_entity
*
ent
=
get_class_member
(
ctx
->
frame_tp
,
i
);
if
(
!
is_method_entity
(
ent
))
continue
;
irg
=
get_entity_irg
(
ent
);
if
(
irg
==
NULL
)
continue
;
/*
* FIXME: find the number of the static link parameter
* for now we assume 0 here
*/
ctx
->
static_link_pos
=
0
;
irg_walk_graph
(
irg
,
NULL
,
update_outer_frame_sels
,
ctx
);
}
}
/**
* Modify the irg itself and the frame type.
*/
...
...
@@ -1615,7 +1457,6 @@ static void modify_irg(ir_graph *irg)
arg_type
=
compute_arg_type
(
irg
,
call
,
method_type
,
&
param_map
);
/* Convert the Sel nodes in the irg to frame addr nodes: */
ctx
.
value_param_list
=
NEW_ARR_F
(
ir_entity
*
,
0
);
ctx
.
frame
=
get_irg_frame
(
irg
);
ctx
.
sp_class
=
arch_env
->
sp
->
reg_class
;
ctx
.
link_class
=
arch_env
->
link_class
;
...
...
@@ -1626,8 +1467,6 @@ static void modify_irg(ir_graph *irg)
default_layout_compound_type
(
ctx
.
frame_tp
);
}
irg_walk_graph
(
irg
,
lower_frame_sels_walker
,
NULL
,
&
ctx
);
/* align stackframe to 4 byte */
frame_size
=
get_type_size_bytes
(
ctx
.
frame_tp
);
if
(
frame_size
%
4
!=
0
)
{
...
...
@@ -1639,24 +1478,10 @@ static void modify_irg(ir_graph *irg)
n_params
=
get_method_n_params
(
method_type
);
args
=
OALLOCNZ
(
obst
,
ir_node
*
,
n_params
);
/*
* for inner function we must now fix access to outer frame entities.
*/
fix_outer_variable_access
(
env
,
&
ctx
);
be_add_parameter_entity_stores
(
irg
);
/* Check if a value parameter is transmitted as a register.
* This might happen if the address of an parameter is taken which is
* transmitted in registers.
*
* Note that on some architectures this case must be handled specially
* because the place of the backing store is determined by their ABI.
*
* In the default case we move the entity to the frame type and create
* a backing store into the first block.
*/
fix_address_of_parameter_access
(
env
,
irg
,
ctx
.
value_param_list
);
irg_walk_graph
(
irg
,
lower_frame_sels_walker
,
NULL
,
&
ctx
);
DEL_ARR_F
(
ctx
.
value_param_list
);
irp_free_resources
(
irp
,
IRP_RESOURCE_ENTITY_LINK
);
/* Fill the argument vector */
...
...
ir/be/beabi.h
View file @
9a78c10b
...
...
@@ -36,6 +36,7 @@
#include "beirg.h"
#include "bearch.h"
#include "beabi.h"
#include "beabihelper.h"
struct
be_abi_call_flags_bits_t
{
unsigned
store_args_sequential
:
1
;
/**< Use sequential stores for arguments. */
...
...
ir/be/beabihelper.c
View file @
9a78c10b
...
...
@@ -641,3 +641,59 @@ ir_node *be_get_stack_pred(const beabi_helper_env_t *env, const ir_node *node)
{
return
(
ir_node
*
)
phase_get_irn_data
(
env
->
stack_order
,
node
);
}
void
be_add_parameter_entity_stores
(
ir_graph
*
irg
)
{
ir_type
*
frame_type
=
get_irg_frame_type
(
irg
);
size_t
n
=
get_compound_n_members
(
frame_type
);
ir_node
*
frame
=
get_irg_frame
(
irg
);
ir_node
*
initial_mem
=
get_irg_initial_mem
(
irg
);
ir_node
*
mem
=
initial_mem
;
ir_node
*
first_store
=
NULL
;
ir_node
*
start_block
=
get_irg_start_block
(
irg
);
ir_node
*
args
=
get_irg_args
(
irg
);
size_t
i
;
/* all parameter entities left in the frame type require stores.
* (The ones passed on the stack have been moved to the arg type) */
for
(
i
=
0
;
i
<
n
;
++
i
)
{
ir_entity
*
entity
=
get_compound_member
(
frame_type
,
i
);
ir_node
*
addr
;
size_t
arg
;
if
(
!
is_parameter_entity
(
entity
))
continue
;
arg
=
get_entity_parameter_number
(
entity
);
addr
=
new_r_Sel
(
start_block
,
mem
,
frame
,
0
,
NULL
,
entity
);
if
(
entity
->
attr
.
parameter
.
doubleword_low_mode
!=
NULL
)
{
ir_mode
*
mode
=
entity
->
attr
.
parameter
.
doubleword_low_mode
;
ir_node
*
val0
=
new_r_Proj
(
args
,
mode
,
arg
);
ir_node
*
val1
=
new_r_Proj
(
args
,
mode
,
arg
+
1
);
ir_node
*
store0
=
new_r_Store
(
start_block
,
mem
,
addr
,
val0
,
cons_none
);
ir_node
*
mem0
=
new_r_Proj
(
store0
,
mode_M
,
pn_Store_M
);
size_t
offset
=
get_mode_size_bits
(
mode
)
/
8
;
ir_mode
*
addr_mode
=
get_irn_mode
(
addr
);
ir_node
*
cnst
=
new_r_Const_long
(
irg
,
addr_mode
,
offset
);
ir_node
*
next_addr
=
new_r_Add
(
start_block
,
addr
,
cnst
,
addr_mode
);
ir_node
*
store1
=
new_r_Store
(
start_block
,
mem0
,
next_addr
,
val1
,
cons_none
);
mem
=
new_r_Proj
(
store1
,
mode_M
,
pn_Store_M
);
if
(
first_store
==
NULL
)
first_store
=
store0
;
}
else
{
ir_type
*
tp
=
get_entity_type
(
entity
);
ir_mode
*
mode
=
get_type_mode
(
tp
);
ir_node
*
val
=
new_r_Proj
(
args
,
mode
,
arg
);
ir_node
*
store
=
new_r_Store
(
start_block
,
mem
,
addr
,
val
,
cons_none
);
mem
=
new_r_Proj
(
store
,
mode_M
,
pn_Store_M
);
if
(
first_store
==
NULL
)
first_store
=
store
;
}
}
if
(
mem
!=
initial_mem
)
{
edges_reroute
(
initial_mem
,
mem
);
set_Store_mem
(
first_store
,
initial_mem
);
}
}
ir/be/beabihelper.h
View file @
9a78c10b
...
...
@@ -124,4 +124,14 @@ void be_collect_stacknodes(beabi_helper_env_t *env);
*/
ir_node
*
be_get_stack_pred
(
const
beabi_helper_env_t
*
env
,
const
ir_node
*
node
);
/**
* In case where a parameter is transmitted via register but someone takes its
* address a store to the frame which can be references is necessary.
* This function can be used as a preprocessing phase before transformation to
* do this. The assumption is that all parameter_entities which are passed
* through the stack are already moved to the arg_type and all remaining
* parameter_entities on the frame type need stores.
*/
void
be_add_parameter_entity_stores
(
ir_graph
*
irg
);
#endif
ir/be/sparc/sparc_transform.c
View file @
9a78c10b
...
...
@@ -1380,40 +1380,70 @@ static ir_type *sparc_get_between_type(void)
return
between_type
;
}
static
void
create_stacklayout
(
ir_graph
*
irg
)
static
ir_type
*
compute_arg_type
(
ir_graph
*
irg
)
{
ir_entity
*
entity
=
get_irg_entity
(
irg
);
ir_type
*
function_type
=
get_entity_type
(
entity
);
be_stack_layout_t
*
layout
=
be_get_irg_stack_layout
(
irg
);
ir_type
*
arg_type
;
int
p
;
int
n_params
;
ir_entity
*
entity
=
get_irg_entity
(
irg
);
ir_type
*
mtp
=
get_entity_type
(
entity
);
size_t
n_params
=
get_method_n_params
(
mtp
);
ir_entity
**
param_map
=
ALLOCANZ
(
ir_entity
*
,
n_params
);
/* calling conventions must be decided by now */
assert
(
current_cconv
!=
NULL
);
ir_type
*
frame_type
=
get_irg_frame_type
(
irg
);
size_t
n_frame_members
=
get_compound_n_members
(
frame_type
);
size_t
f
;
size_t
i
;
/* construct argument type */
arg_type
=
new_type_struct
(
id_mangle_u
(
get_entity_ident
(
entity
),
new_id_from_chars
(
"arg_type"
,
8
)));
n_params
=
get_method_n_params
(
function_type
);
for
(
p
=
0
;
p
<
n_params
;
++
p
)
{
reg_or_stackslot_t
*
param
=
&
current_cconv
->
parameters
[
p
]
;
char
buf
[
128
]
;
ident
*
id
;
ir_type
*
res
=
new_type_struct
(
id_mangle_u
(
get_entity_ident
(
entity
),
new_id_from_chars
(
"arg_type"
,
8
)));
/* search for existing value_param entities */
for
(
f
=
n_frame_members
;
f
>
0
;
)
{
ir_entity
*
member
=
get_compound_member
(
frame_type
,
--
f
)
;
size_t
num
;
const
reg_or_stackslot_t
*
param
;
if
(
param
->
type
==
NULL
)
if
(
!
is_
param
eter_entity
(
member
)
)
continue
;
num
=
get_entity_parameter_number
(
member
);
assert
(
num
<
n_params
);
if
(
param_map
[
num
]
!=
NULL
)
panic
(
"multiple entities for parameter %u in %+F found"
,
f
,
irg
);
param
=
&
current_cconv
->
parameters
[
num
];
if
(
param
->
reg0
!=
NULL
)
continue
;
param_map
[
num
]
=
member
;
/* move to new arg_type */
set_entity_owner
(
member
,
res
);
}
for
(
i
=
0
;
i
<
n_params
;
++
i
)
{
reg_or_stackslot_t
*
param
=
&
current_cconv
->
parameters
[
i
];
ir_entity
*
entity
;
snprintf
(
buf
,
sizeof
(
buf
),
"param_%d"
,
p
);
id
=
new_id_from_str
(
buf
);
param
->
entity
=
new_entity
(
arg_type
,
id
,
param
->
type
);
set_entity_offset
(
param
->
entity
,
param
->
offset
);
if
(
param
->
reg0
!=
NULL
)
continue
;
entity
=
param_map
[
i
];
if
(
entity
==
NULL
)
entity
=
new_parameter_entity
(
res
,
i
,
param
->
type
);
param
->
entity
=
entity
;
set_entity_offset
(
entity
,
param
->
offset
);
}
return
res
;
}
static
void
create_stacklayout
(
ir_graph
*
irg
)
{
be_stack_layout_t
*
layout
=
be_get_irg_stack_layout
(
irg
);
/* calling conventions must be decided by now */
assert
(
current_cconv
!=
NULL
);
memset
(
layout
,
0
,
sizeof
(
*
layout
));
layout
->
frame_type
=
get_irg_frame_type
(
irg
);
layout
->
between_type
=
sparc_get_between_type
();
layout
->
arg_type
=
arg_type
;
layout
->
arg_type
=
compute_
arg_type
(
irg
)
;
layout
->
initial_offset
=
0
;
layout
->
initial_bias
=
0
;
layout
->
sp_relative
=
current_cconv
->
omit_fp
;
...
...
@@ -2224,6 +2254,7 @@ void sparc_transform_graph(ir_graph *irg)
current_cconv
=
sparc_decide_calling_convention
(
get_entity_type
(
entity
),
irg
);
create_stacklayout
(
irg
);
be_add_parameter_entity_stores
(
irg
);
be_transform_graph
(
irg
,
NULL
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a 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