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
fd07b149
Commit
fd07b149
authored
Oct 08, 2008
by
Christoph Mallon
Browse files
Introduce ia32_Call, which can handle address mode.
[r22609]
parent
a0ea0fb4
Changes
8
Hide whitespace changes
Inline
Side-by-side
ir/be/ia32/bearch_ia32.c
View file @
fd07b149
...
...
@@ -392,6 +392,9 @@ static void ia32_set_frame_offset(ir_node *irn, int bias)
static
int
ia32_get_sp_bias
(
const
ir_node
*
node
)
{
if
(
is_ia32_Call
(
node
))
return
-
(
int
)
get_ia32_call_attr_const
(
node
)
->
pop
;
if
(
is_ia32_Push
(
node
))
return
4
;
...
...
@@ -1889,7 +1892,7 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
call_flags
.
bits
.
store_args_sequential
=
0
;
/* call_flags.bits.try_omit_fp not changed: can handle both settings */
call_flags
.
bits
.
fp_free
=
0
;
/* the frame pointer is fixed in IA32 */
call_flags
.
bits
.
call_has_imm
=
1
;
/* No call immediates, we handle this by ourselves */
call_flags
.
bits
.
call_has_imm
=
0
;
/* No call immediates, we handle this by ourselves */
/* set parameter passing style */
be_abi_call_set_flags
(
abi
,
call_flags
,
&
ia32_abi_callbacks
);
...
...
@@ -2088,16 +2091,13 @@ static const be_execution_unit_t ***ia32_get_allowed_execution_units(
if
(
is_ia32_irn
(
irn
))
{
ret
=
get_ia32_exec_units
(
irn
);
}
else
if
(
is_be_node
(
irn
))
{
if
(
be_is_Call
(
irn
)
||
be_is_Return
(
irn
))
{
}
else
if
(
is_be_node
(
irn
))
{
if
(
be_is_Return
(
irn
))
{
ret
=
_units_callret
;
}
else
if
(
be_is_Barrier
(
irn
))
{
}
else
if
(
be_is_Barrier
(
irn
))
{
ret
=
_units_dummy
;
}
else
{
ret
=
_units_other
;
}
else
{
ret
=
_units_other
;
}
}
else
{
...
...
ir/be/ia32/ia32_emitter.c
View file @
fd07b149
...
...
@@ -255,7 +255,52 @@ void ia32_emit_source_register(const ir_node *node, int pos)
emit_register
(
reg
,
NULL
);
}
static
void
emit_ia32_Immediate
(
const
ir_node
*
node
);
static
void
ia32_emit_entity
(
ir_entity
*
entity
,
int
no_pic_adjust
)
{
ident
*
id
;
set_entity_backend_marked
(
entity
,
1
);
id
=
get_entity_ld_ident
(
entity
);
be_emit_ident
(
id
);
if
(
get_entity_owner
(
entity
)
==
get_tls_type
())
{
if
(
get_entity_visibility
(
entity
)
==
visibility_external_allocated
)
{
be_emit_cstring
(
"@INDNTPOFF"
);
}
else
{
be_emit_cstring
(
"@NTPOFF"
);
}
}
if
(
!
no_pic_adjust
&&
do_pic
)
{
/* TODO: only do this when necessary */
be_emit_char
(
'-'
);
be_emit_string
(
pic_base_label
);
}
}
static
void
emit_ia32_Immediate_no_prefix
(
const
ir_node
*
node
)
{
const
ia32_immediate_attr_t
*
attr
=
get_ia32_immediate_attr_const
(
node
);
if
(
attr
->
symconst
!=
NULL
)
{
if
(
attr
->
sc_sign
)
be_emit_char
(
'-'
);
ia32_emit_entity
(
attr
->
symconst
,
0
);
}
if
(
attr
->
symconst
==
NULL
||
attr
->
offset
!=
0
)
{
if
(
attr
->
symconst
!=
NULL
)
{
be_emit_irprintf
(
"%+d"
,
attr
->
offset
);
}
else
{
be_emit_irprintf
(
"0x%X"
,
attr
->
offset
);
}
}
}
static
void
emit_ia32_Immediate
(
const
ir_node
*
node
)
{
be_emit_char
(
'$'
);
emit_ia32_Immediate_no_prefix
(
node
);
}
void
ia32_emit_8bit_source_register_or_immediate
(
const
ir_node
*
node
,
int
pos
)
{
...
...
@@ -476,6 +521,11 @@ static void ia32_emit_cmp_suffix(int pnc)
be_emit_string
(
str
);
}
typedef
enum
ia32_emit_mod_t
{
EMIT_RESPECT_LS
=
1U
<<
0
,
EMIT_ALTERNATE_AM
=
1U
<<
1
}
ia32_emit_mod_t
;
/**
* fmt parameter output
* ---- ---------------------- ---------------------------------------------
...
...
@@ -495,6 +545,7 @@ static void ia32_emit_cmp_suffix(int pnc)
*
* x starts at 0
* # modifier for %ASx, %D and %S uses ls mode of node to alter register width
* * modifier does not prefix immediates with $, but AM with *
*/
static
void
ia32_emitf
(
const
ir_node
*
node
,
const
char
*
fmt
,
...)
{
...
...
@@ -502,8 +553,8 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
va_start
(
ap
,
fmt
);
for
(;;)
{
const
char
*
start
=
fmt
;
const
ir_mode
*
mod
e
=
NULL
;
const
char
*
start
=
fmt
;
ia32_emit_mod_t
mod
=
0
;
while
(
*
fmt
!=
'%'
&&
*
fmt
!=
'\n'
&&
*
fmt
!=
'\0'
)
++
fmt
;
...
...
@@ -523,8 +574,13 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
break
;
++
fmt
;
if
(
*
fmt
==
'*'
)
{
mod
|=
EMIT_ALTERNATE_AM
;
++
fmt
;
}
if
(
*
fmt
==
'#'
)
{
mod
e
=
get_ia32_ls_mode
(
node
)
;
mod
|=
EMIT_RESPECT_LS
;
++
fmt
;
}
...
...
@@ -536,12 +592,16 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
case
'A'
:
{
switch
(
*
fmt
++
)
{
case
'M'
:
if
(
mod
&
EMIT_ALTERNATE_AM
)
be_emit_char
(
'*'
);
ia32_emit_am
(
node
);
break
;
case
'R'
:
{
const
arch_register_t
*
reg
=
va_arg
(
ap
,
const
arch_register_t
*
);
if
(
get_ia32_op_type
(
node
)
==
ia32_AddrModeS
)
{
if
(
mod
&
EMIT_ALTERNATE_AM
)
be_emit_char
(
'*'
);
ia32_emit_am
(
node
);
}
else
{
emit_register
(
reg
,
NULL
);
...
...
@@ -551,6 +611,8 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
case
'S'
:
if
(
get_ia32_op_type
(
node
)
==
ia32_AddrModeS
)
{
if
(
mod
&
EMIT_ALTERNATE_AM
)
be_emit_char
(
'*'
);
ia32_emit_am
(
node
);
++
fmt
;
}
else
{
...
...
@@ -573,12 +635,14 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
pos
=
*
fmt
++
-
'0'
;
reg
=
get_out_reg
(
node
,
pos
);
emit_register
(
reg
,
mod
e
);
emit_register
(
reg
,
mod
&
EMIT_RESPECT_LS
?
get_ia32_ls_mode
(
node
)
:
NULL
);
break
;
}
case
'I'
:
emit_ia32_Immediate
(
node
);
if
(
!
(
mod
&
EMIT_ALTERNATE_AM
))
be_emit_char
(
'$'
);
emit_ia32_Immediate_no_prefix
(
node
);
break
;
case
'L'
:
...
...
@@ -613,10 +677,12 @@ emit_S:
pos
=
*
fmt
++
-
'0'
;
in
=
get_irn_n
(
node
,
pos
);
if
(
is_ia32_Immediate
(
in
))
{
emit_ia32_Immediate
(
in
);
if
(
!
(
mod
&
EMIT_ALTERNATE_AM
))
be_emit_char
(
'$'
);
emit_ia32_Immediate_no_prefix
(
in
);
}
else
{
const
arch_register_t
*
reg
=
get_in_reg
(
node
,
pos
);
emit_register
(
reg
,
mod
e
);
emit_register
(
reg
,
mod
&
EMIT_RESPECT_LS
?
get_ia32_ls_mode
(
node
)
:
NULL
);
}
break
;
}
...
...
@@ -698,29 +764,6 @@ void ia32_emit_unop(const ir_node *node, int pos)
ia32_emitf
(
node
,
fmt
);
}
static
void
ia32_emit_entity
(
ir_entity
*
entity
,
int
no_pic_adjust
)
{
ident
*
id
;
set_entity_backend_marked
(
entity
,
1
);
id
=
get_entity_ld_ident
(
entity
);
be_emit_ident
(
id
);
if
(
get_entity_owner
(
entity
)
==
get_tls_type
())
{
if
(
get_entity_visibility
(
entity
)
==
visibility_external_allocated
)
{
be_emit_cstring
(
"@INDNTPOFF"
);
}
else
{
be_emit_cstring
(
"@NTPOFF"
);
}
}
if
(
!
no_pic_adjust
&&
do_pic
)
{
/* TODO: only do this when necessary */
be_emit_char
(
'-'
);
be_emit_string
(
pic_base_label
);
}
}
/**
* Emits address mode.
*/
...
...
@@ -1215,25 +1258,6 @@ static void emit_Jmp(const ir_node *node)
}
}
static
void
emit_ia32_Immediate
(
const
ir_node
*
node
)
{
const
ia32_immediate_attr_t
*
attr
=
get_ia32_immediate_attr_const
(
node
);
be_emit_char
(
'$'
);
if
(
attr
->
symconst
!=
NULL
)
{
if
(
attr
->
sc_sign
)
be_emit_char
(
'-'
);
ia32_emit_entity
(
attr
->
symconst
,
0
);
}
if
(
attr
->
symconst
==
NULL
||
attr
->
offset
!=
0
)
{
if
(
attr
->
symconst
!=
NULL
)
{
be_emit_irprintf
(
"%+d"
,
attr
->
offset
);
}
else
{
be_emit_irprintf
(
"0x%X"
,
attr
->
offset
);
}
}
}
/**
* Emit an inline assembler operand.
*
...
...
@@ -1521,6 +1545,16 @@ static void emit_ia32_Conv_I2I(const ir_node *node)
}
}
/**
* Emits a call
*/
static
void
emit_ia32_Call
(
const
ir_node
*
node
)
{
/* Special case: Call must not have its immediates prefixed by $, instead
* address mode is prefixed by *. */
ia32_emitf
(
node
,
"
\t
call %*AS3
\n
"
);
}
/*******************************************
* _ _
...
...
@@ -1532,24 +1566,6 @@ static void emit_ia32_Conv_I2I(const ir_node *node)
*
*******************************************/
/**
* Emits a backend call
*/
static
void
emit_be_Call
(
const
ir_node
*
node
)
{
ir_entity
*
ent
=
be_Call_get_entity
(
node
);
be_emit_cstring
(
"
\t
call "
);
if
(
ent
)
{
ia32_emit_entity
(
ent
,
1
);
}
else
{
const
arch_register_t
*
reg
=
get_in_reg
(
node
,
be_pos_Call_ptr
);
be_emit_char
(
'*'
);
emit_register
(
reg
,
NULL
);
}
be_emit_finish_line_gas
(
node
);
}
/**
* Emits code to increase stack pointer.
*/
...
...
@@ -1795,6 +1811,7 @@ static void ia32_register_emitters(void)
IA32_EMIT2
(
Conv_I2I8Bit
,
Conv_I2I
);
IA32_EMIT
(
Asm
);
IA32_EMIT
(
CMov
);
IA32_EMIT
(
Call
);
IA32_EMIT
(
Const
);
IA32_EMIT
(
Conv_FP2FP
);
IA32_EMIT
(
Conv_FP2I
);
...
...
@@ -1810,7 +1827,6 @@ static void ia32_register_emitters(void)
IA32_EMIT
(
SwitchJmp
);
/* benode emitter */
BE_EMIT
(
Call
);
BE_EMIT
(
Copy
);
BE_EMIT
(
CopyKeep
);
BE_EMIT
(
IncSP
);
...
...
ir/be/ia32/ia32_new_nodes.c
View file @
fd07b149
...
...
@@ -438,6 +438,22 @@ const ia32_condcode_attr_t *get_ia32_condcode_attr_const(const ir_node *node) {
return
cc_attr
;
}
ia32_call_attr_t
*
get_ia32_call_attr
(
ir_node
*
node
)
{
ia32_attr_t
*
attr
=
get_ia32_attr
(
node
);
ia32_call_attr_t
*
call_attr
=
CAST_IA32_ATTR
(
ia32_call_attr_t
,
attr
);
return
call_attr
;
}
const
ia32_call_attr_t
*
get_ia32_call_attr_const
(
const
ir_node
*
node
)
{
const
ia32_attr_t
*
attr
=
get_ia32_attr_const
(
node
);
const
ia32_call_attr_t
*
call_attr
=
CONST_CAST_IA32_ATTR
(
ia32_call_attr_t
,
attr
);
return
call_attr
;
}
ia32_copyb_attr_t
*
get_ia32_copyb_attr
(
ir_node
*
node
)
{
ia32_attr_t
*
attr
=
get_ia32_attr
(
node
);
ia32_copyb_attr_t
*
copyb_attr
=
CAST_IA32_ATTR
(
ia32_copyb_attr_t
,
attr
);
...
...
@@ -1095,6 +1111,17 @@ init_ia32_immediate_attributes(ir_node *res, ir_entity *symconst,
attr
->
offset
=
offset
;
}
void
init_ia32_call_attributes
(
ir_node
*
const
res
,
unsigned
const
pop
,
ir_type
*
const
call_tp
)
{
ia32_call_attr_t
*
attr
=
get_irn_generic_attr
(
res
);
#ifndef NDEBUG
attr
->
attr
.
attr_type
|=
IA32_ATTR_ia32_call_attr_t
;
#endif
attr
->
pop
=
pop
;
attr
->
call_tp
=
call_tp
;
}
void
init_ia32_copyb_attributes
(
ir_node
*
res
,
unsigned
size
)
{
ia32_copyb_attr_t
*
attr
=
get_irn_generic_attr
(
res
);
...
...
@@ -1203,6 +1230,26 @@ int ia32_compare_condcode_attr(ir_node *a, ir_node *b)
return
0
;
}
static
int
ia32_compare_call_attr
(
ir_node
*
a
,
ir_node
*
b
)
{
const
ia32_call_attr_t
*
attr_a
;
const
ia32_call_attr_t
*
attr_b
;
if
(
ia32_compare_nodes_attr
(
a
,
b
))
return
1
;
attr_a
=
get_ia32_call_attr_const
(
a
);
attr_b
=
get_ia32_call_attr_const
(
b
);
if
(
attr_a
->
pop
!=
attr_b
->
pop
)
return
1
;
if
(
attr_a
->
call_tp
!=
attr_b
->
call_tp
)
return
1
;
return
0
;
}
/** Compare node attributes for CopyB nodes. */
static
int
ia32_compare_copyb_attr
(
ir_node
*
a
,
ir_node
*
b
)
...
...
ir/be/ia32/ia32_new_nodes.h
View file @
fd07b149
...
...
@@ -86,6 +86,12 @@ const ia32_immediate_attr_t *get_ia32_immediate_attr_const(const ir_node *node);
ia32_condcode_attr_t
*
get_ia32_condcode_attr
(
ir_node
*
node
);
const
ia32_condcode_attr_t
*
get_ia32_condcode_attr_const
(
const
ir_node
*
node
);
/**
* Gets the Call node attributes.
*/
ia32_call_attr_t
*
get_ia32_call_attr
(
ir_node
*
node
);
const
ia32_call_attr_t
*
get_ia32_call_attr_const
(
const
ir_node
*
node
);
/**
* Gets the CopyB node attributes.
*/
...
...
@@ -454,6 +460,7 @@ void init_ia32_x87_attributes(ir_node *node);
void
init_ia32_asm_attributes
(
ir_node
*
node
);
void
init_ia32_immediate_attributes
(
ir_node
*
node
,
ir_entity
*
symconst
,
int
symconst_sign
,
long
offset
);
void
init_ia32_call_attributes
(
ir_node
*
res
,
unsigned
pop
,
ir_type
*
call_tp
);
void
init_ia32_copyb_attributes
(
ir_node
*
res
,
unsigned
size
);
void
init_ia32_condcode_attributes
(
ir_node
*
res
,
long
pnc
);
...
...
ir/be/ia32/ia32_nodes_attr.h
View file @
fd07b149
...
...
@@ -82,7 +82,8 @@ typedef enum {
IA32_ATTR_ia32_asm_attr_t
=
1
<<
2
,
IA32_ATTR_ia32_immediate_attr_t
=
1
<<
3
,
IA32_ATTR_ia32_condcode_attr_t
=
1
<<
4
,
IA32_ATTR_ia32_copyb_attr_t
=
1
<<
5
IA32_ATTR_ia32_copyb_attr_t
=
1
<<
5
,
IA32_ATTR_ia32_call_attr_t
=
1
<<
6
}
ia32_attr_type_t
;
#endif
...
...
@@ -141,6 +142,16 @@ struct ia32_attr_t {
};
COMPILETIME_ASSERT
(
sizeof
(
struct
ia32_attr_data_bitfield
)
<=
4
,
attr_bitfield
);
/**
* The attributes for a Call node.
*/
typedef
struct
ia32_call_attr_t
ia32_call_attr_t
;
struct
ia32_call_attr_t
{
ia32_attr_t
attr
;
/**< generic attribute */
unsigned
pop
;
/**< number of bytes that get popped by the callee */
ir_type
*
call_tp
;
/**< The call type, copied from the original Call node. */
};
/**
* The attributes for nodes with condition code.
*/
...
...
@@ -204,6 +215,7 @@ struct ia32_asm_attr_t {
* the structs (we use them to simulate OO-inheritance) */
union
allow_casts_attr_t_
{
ia32_attr_t
attr
;
ia32_call_attr_t
call_attr
;
ia32_condcode_attr_t
cc_attr
;
ia32_copyb_attr_t
cpy_attr
;
ia32_x87_attr_t
x87_attr
;
...
...
ir/be/ia32/ia32_spec.pl
View file @
fd07b149
...
...
@@ -279,6 +279,9 @@ $custom_init_attr_func = \&ia32_custom_init_attr;
"
\t
init_ia32_asm_attributes(res);
",
ia32_attr_t
=>
"
\t
init_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);
",
ia32_call_attr_t
=>
"
\t
init_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);
\n
"
.
"
\t
init_ia32_call_attributes(res, pop, call_tp);
",
ia32_condcode_attr_t
=>
"
\t
init_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);
\n
"
.
"
\t
init_ia32_condcode_attributes(res, pnc);
",
...
...
@@ -296,6 +299,7 @@ $custom_init_attr_func = \&ia32_custom_init_attr;
%compare_attr
=
(
ia32_asm_attr_t
=>
"
ia32_compare_asm_attr
",
ia32_attr_t
=>
"
ia32_compare_nodes_attr
",
ia32_call_attr_t
=>
"
ia32_compare_call_attr
",
ia32_condcode_attr_t
=>
"
ia32_compare_condcode_attr
",
ia32_copyb_attr_t
=>
"
ia32_compare_copyb_attr
",
ia32_immediate_attr_t
=>
"
ia32_compare_immediate_attr
",
...
...
@@ -1460,6 +1464,21 @@ Bt => {
modified_flags
=>
$status_flags
# only CF is set, but the other flags are undefined
},
Call
=>
{
state
=>
"
exc_pinned
",
reg_req
=>
{
in
=>
[
"
gp
",
"
gp
",
"
none
",
"
gp
",
"
esp
",
"
fpcw
",
"
eax
",
"
ecx
",
"
edx
"
],
out
=>
[
"
esp
",
"
fpcw
",
"
none
",
"
eax
",
"
ecx
",
"
edx
",
"
vf0
",
"
vf1
",
"
vf2
",
"
vf3
",
"
vf4
",
"
vf5
",
"
vf6
",
"
vf7
",
"
xmm0
",
"
xmm1
",
"
xmm2
",
"
xmm3
",
"
xmm4
",
"
xmm5
",
"
xmm6
",
"
xmm7
"
]
},
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
addr
",
"
stack
",
"
fpcw
",
"
eax
",
"
ecx
",
"
edx
"
],
outs
=>
[
"
stack:I|S
",
"
fpcw:I
",
"
M
",
"
eax
",
"
ecx
",
"
edx
",
"
vf0
",
"
vf1
",
"
vf2
",
"
vf3
",
"
vf4
",
"
vf5
",
"
vf6
",
"
vf7
",
"
xmm0
",
"
xmm1
",
"
xmm2
",
"
xmm3
",
"
xmm4
",
"
xmm5
",
"
xmm6
",
"
xmm7
"
],
attr_type
=>
"
ia32_call_attr_t
",
attr
=>
"
unsigned pop, ir_type *call_tp
",
am
=>
"
source,unary
",
units
=>
[
"
BRANCH
"
],
latency
=>
4
,
# random number
},
#-----------------------------------------------------------------------------#
# _____ _____ ______ __ _ _ _ #
# / ____/ ____| ____| / _| | | | | | #
...
...
ir/be/ia32/ia32_transform.c
View file @
fd07b149
...
...
@@ -4210,14 +4210,30 @@ static ir_node *gen_Proj_Quot(ir_node *node) {
panic
(
"No idea how to transform proj->Quot"
);
}
static
ir_node
*
gen_be_Call
(
ir_node
*
node
)
{
ir_node
*
res
=
be_duplicate_node
(
node
);
ir_type
*
call_tp
;
be_node_add_flags
(
res
,
-
1
,
arch_irn_flags_modify_flags
);
static
ir_node
*
gen_be_Call
(
ir_node
*
node
)
{
dbg_info
*
const
dbgi
=
get_irn_dbg_info
(
node
);
ir_graph
*
const
irg
=
current_ir_graph
;
ir_node
*
const
src_block
=
get_nodes_block
(
node
);
ir_node
*
const
block
=
be_transform_node
(
src_block
);
ir_node
*
const
src_mem
=
get_irn_n
(
node
,
be_pos_Call_mem
);
ir_node
*
const
src_sp
=
get_irn_n
(
node
,
be_pos_Call_sp
);
ir_node
*
const
sp
=
be_transform_node
(
src_sp
);
ir_node
*
const
src_ptr
=
get_irn_n
(
node
,
be_pos_Call_ptr
);
ir_node
*
const
noreg
=
ia32_new_NoReg_gp
(
env_cg
);
ia32_address_mode_t
am
;
ia32_address_t
*
const
addr
=
&
am
.
addr
;
ir_node
*
mem
;
ir_node
*
call
;
int
i
;
ir_node
*
fpcw
;
ir_node
*
eax
=
noreg
;
ir_node
*
ecx
=
noreg
;
ir_node
*
edx
=
noreg
;
unsigned
const
pop
=
be_Call_get_pop
(
node
);
ir_type
*
const
call_tp
=
be_Call_get_type
(
node
);
/* Run the x87 simulator if the call returns a float value */
call_tp
=
be_Call_get_type
(
node
);
if
(
get_method_n_ress
(
call_tp
)
>
0
)
{
ir_type
*
const
res_type
=
get_method_res_type
(
call_tp
,
0
);
ir_mode
*
const
res_mode
=
get_type_mode
(
res_type
);
...
...
@@ -4227,7 +4243,41 @@ static ir_node *gen_be_Call(ir_node *node) {
}
}
return
res
;
/* We do not want be_Call direct calls */
assert
(
be_Call_get_entity
(
node
)
==
NULL
);
match_arguments
(
&
am
,
src_block
,
NULL
,
src_ptr
,
src_mem
,
match_am
|
match_immediate
);
i
=
get_irn_arity
(
node
)
-
1
;
fpcw
=
be_transform_node
(
get_irn_n
(
node
,
i
--
));
for
(;
i
>=
be_pos_Call_first_arg
;
--
i
)
{
arch_register_req_t
const
*
const
req
=
arch_get_register_req
(
env_cg
->
arch_env
,
node
,
i
);
ir_node
*
const
reg_parm
=
be_transform_node
(
get_irn_n
(
node
,
i
));
assert
(
req
->
type
==
arch_register_req_type_limited
);
assert
(
req
->
cls
==
&
ia32_reg_classes
[
CLASS_ia32_gp
]);
switch
(
*
req
->
limited
)
{
case
1
<<
REG_EAX
:
assert
(
eax
==
noreg
);
eax
=
reg_parm
;
break
;
case
1
<<
REG_ECX
:
assert
(
ecx
==
noreg
);
ecx
=
reg_parm
;
break
;
case
1
<<
REG_EDX
:
assert
(
edx
==
noreg
);
edx
=
reg_parm
;
break
;
default:
panic
(
"Invalid GP register for register parameter"
);
}
}
mem
=
transform_AM_mem
(
irg
,
block
,
src_ptr
,
src_mem
,
addr
->
mem
);
call
=
new_rd_ia32_Call
(
dbgi
,
irg
,
block
,
addr
->
base
,
addr
->
index
,
mem
,
am
.
new_op2
,
sp
,
fpcw
,
eax
,
ecx
,
edx
,
pop
,
call_tp
);
set_am_attributes
(
call
,
&
am
);
call
=
fix_mem_proj
(
call
,
&
am
);
if
(
get_irn_pinned
(
node
)
==
op_pin_state_pinned
)
set_irn_pinned
(
call
,
op_pin_state_pinned
);
SET_IA32_ORIG_NODE
(
call
,
ia32_get_old_node_name
(
env_cg
,
node
));
return
call
;
}
static
ir_node
*
gen_be_IncSP
(
ir_node
*
node
)
{
...
...
@@ -4240,7 +4290,8 @@ static ir_node *gen_be_IncSP(ir_node *node) {
/**
* Transform the Projs from a be_Call.
*/
static
ir_node
*
gen_Proj_be_Call
(
ir_node
*
node
)
{
static
ir_node
*
gen_Proj_be_Call
(
ir_node
*
node
)
{
ir_node
*
block
=
be_transform_node
(
get_nodes_block
(
node
));
ir_node
*
call
=
get_Proj_pred
(
node
);
ir_node
*
new_call
=
be_transform_node
(
call
);
...
...
@@ -4252,6 +4303,7 @@ static ir_node *gen_Proj_be_Call(ir_node *node) {
ir_mode
*
mode
=
get_irn_mode
(
node
);
ir_node
*
sse_load
;
const
arch_register_class_t
*
cls
;
ir_node
*
res
;
/* The following is kinda tricky: If we're using SSE, then we have to
* move the result value of the call in floating point registers to an
...
...
@@ -4270,9 +4322,9 @@ static ir_node *gen_Proj_be_Call(ir_node *node) {
call_res_pred
=
get_Proj_pred
(
call_res_new
);
}
if
(
call_res_pred
==
NULL
||
be_is
_Call
(
call_res_pred
))
{
if
(
call_res_pred
==
NULL
||
is_ia32
_Call
(
call_res_pred
))
{
return
new_rd_Proj
(
dbgi
,
irg
,
block
,
new_call
,
mode_M
,
p
n_
be
_Call_
M_regular
);
n_
ia32
_Call_
mem
);
}
else
{
assert
(
is_ia32_xLoad
(
call_res_pred
));
return
new_rd_Proj
(
dbgi
,
irg
,
block
,
call_res_pred
,
mode_M
,
...
...
@@ -4319,7 +4371,47 @@ static ir_node *gen_Proj_be_Call(ir_node *node) {
mode
=
cls
->
mode
;
}
return
new_rd_Proj
(
dbgi
,
irg
,
block
,
new_call
,
mode
,
proj
);
/* Map from be_Call to ia32_Call proj number */
if
(
proj
==
pn_be_Call_sp
)
{
proj
=
pn_ia32_Call_stack
;
}
else
if
(
proj
==
pn_be_Call_M_regular
)
{
proj
=
pn_ia32_Call_M
;
}
else
{
arch_register_req_t
const
*
const
req
=
arch_get_register_req
(
env_cg
->
arch_env
,
node
,
BE_OUT_POS
(
proj
));
int
const
n_outs
=
get_ia32_n_res
(
new_call
);
int
i
;
assert
(
proj
>=
pn_be_Call_first_res
);
assert
(
req
->
type
==
arch_register_req_type_limited
);
for
(
i
=
0
;
i
<
n_outs
;
++
i
)
{
arch_register_req_t
const
*
const
new_req
=
get_ia32_out_req
(
new_call
,
i
);
if
(
new_req
->
type
!=
arch_register_req_type_limited
||
new_req
->
cls
!=
req
->
cls
||
*
new_req
->
limited
!=
*
req
->
limited
)
continue
;
proj
=
i
;
break
;
}
assert
(
i
<
n_outs
);
}
res
=
new_rd_Proj
(
dbgi
,
irg
,
block
,
new_call
,
mode
,
proj
);
/* TODO arch_set_irn_register() only operates on Projs, need variant with index */
switch
(
proj
)
{
case
pn_ia32_Call_stack
:
arch_set_irn_register
(
env_cg
->
arch_env
,
res
,
&
ia32_gp_regs
[
REG_ESP
]);
break