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
e086f5c2
Commit
e086f5c2
authored
Jul 09, 2010
by
Matthias Braun
Browse files
handle arm ABI in arm transform phase
[r27726]
parent
b4bdc4fe
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
ir/be/arm/arm_cconv.c
0 → 100644
View file @
e086f5c2
/*
* 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 "arm_cconv.h"
#include "irmode.h"
#include "typerep.h"
#include "xmalloc.h"
#include "error.h"
calling_convention_t
*
decide_calling_convention
(
ir_type
*
function_type
)
{
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_result_regs
=
sizeof
(
result_regs
)
/
sizeof
(
result_regs
[
0
]);
int
n_params
;
int
n_results
;
int
i
;
int
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
];
if
(
regnum
<
n_param_regs
)
{
const
arch_register_t
*
reg
=
param_regs
[
regnum
++
];
param
->
reg0
=
reg
;
}
else
{
param
->
type
=
param_type
;
param
->
offset
=
stack_offset
;
/* increase offset 4 bytes so everything is aligned */
stack_offset
+=
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 arm backend"
);
if
(
regnum
<
n_param_regs
)
{
const
arch_register_t
*
reg
=
param_regs
[
regnum
++
];
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
;
stack_offset
+=
4
;
}
}
}
n_results
=
get_method_n_ress
(
function_type
);
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
(
get_mode_size_bits
(
result_mode
)
>
32
)
{
panic
(
"Results with more than 32bits not supported by arm backend yet"
);
}
if
(
regnum
>=
n_result_regs
)
{
panic
(
"Too many results for arm backend"
);
}
else
{
const
arch_register_t
*
reg
=
result_regs
[
regnum
++
];
result
->
reg0
=
reg
;
}
}
cconv
=
XMALLOCZ
(
calling_convention_t
);
cconv
->
parameters
=
params
;
cconv
->
param_stack_size
=
stack_offset
;
cconv
->
results
=
results
;
return
cconv
;
}
void
free_calling_convention
(
calling_convention_t
*
cconv
)
{
free
(
cconv
->
parameters
);
free
(
cconv
->
results
);
free
(
cconv
);
}
ir/be/arm/arm_cconv.h
0 → 100644
View file @
e086f5c2
/*
* 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 support functions for calling conventions
* @author Matthias Braun
* @version $Id$
*/
#ifndef FIRM_BE_ARM_ARM_CCONV_H
#define FIRM_BE_ARM_ARM_CCONV_H
#include "firm_types.h"
#include "../be_types.h"
#include "gen_arm_regalloc_if.h"
static
const
arch_register_t
*
const
callee_saves
[]
=
{
&
arm_gp_regs
[
REG_R4
],
&
arm_gp_regs
[
REG_R5
],
&
arm_gp_regs
[
REG_R6
],
&
arm_gp_regs
[
REG_R7
],
&
arm_gp_regs
[
REG_R8
],
&
arm_gp_regs
[
REG_R9
],
&
arm_gp_regs
[
REG_R10
],
&
arm_gp_regs
[
REG_R11
],
&
arm_gp_regs
[
REG_LR
],
};
static
const
arch_register_t
*
const
caller_saves
[]
=
{
&
arm_gp_regs
[
REG_R0
],
&
arm_gp_regs
[
REG_R1
],
&
arm_gp_regs
[
REG_R2
],
&
arm_gp_regs
[
REG_R3
],
&
arm_gp_regs
[
REG_LR
]
};
static
const
arch_register_t
*
const
param_regs
[]
=
{
&
arm_gp_regs
[
REG_R0
],
&
arm_gp_regs
[
REG_R1
],
&
arm_gp_regs
[
REG_R2
],
&
arm_gp_regs
[
REG_R3
]
};
static
const
arch_register_t
*
const
result_regs
[]
=
{
&
arm_gp_regs
[
REG_R0
],
&
arm_gp_regs
[
REG_R1
],
&
arm_gp_regs
[
REG_R2
],
&
arm_gp_regs
[
REG_R3
]
};
/** information about a single parameter or result */
typedef
struct
reg_or_stackslot_t
{
const
arch_register_t
*
reg0
;
const
arch_register_t
*
reg1
;
ir_type
*
type
;
/**< indicates that an entity of the specific
type is needed */
int
offset
;
ir_entity
*
entity
;
/**< entity in frame type */
}
reg_or_stackslot_t
;
typedef
struct
calling_convention_t
{
reg_or_stackslot_t
*
parameters
;
int
param_stack_size
;
reg_or_stackslot_t
*
results
;
}
calling_convention_t
;
/**
* determine how function parameters and return values are passed.
* 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
);
/**
* free memory used by a calling_convention_t
*/
void
free_calling_convention
(
calling_convention_t
*
cconv
);
#endif
ir/be/arm/arm_new_nodes.c
View file @
e086f5c2
...
...
@@ -67,12 +67,12 @@ const char *arm_get_fpa_imm_name(long imm_value)
static
bool
arm_has_symconst_attr
(
const
ir_node
*
node
)
{
return
is_arm_SymConst
(
node
)
||
is_arm_FrameAddr
(
node
);
return
is_arm_SymConst
(
node
)
||
is_arm_FrameAddr
(
node
)
||
is_arm_Bl
(
node
)
;
}
static
bool
has_load_store_attr
(
const
ir_node
*
node
)
{
return
is_arm_Ldr
(
node
)
||
is_arm_Str
(
node
);
return
is_arm_Ldr
(
node
)
||
is_arm_Str
(
node
)
||
is_arm_LinkLdrPC
(
node
)
;
}
static
bool
has_shifter_operand
(
const
ir_node
*
node
)
...
...
@@ -80,7 +80,7 @@ static bool has_shifter_operand(const ir_node *node)
return
is_arm_Add
(
node
)
||
is_arm_And
(
node
)
||
is_arm_Or
(
node
)
||
is_arm_Eor
(
node
)
||
is_arm_Bic
(
node
)
||
is_arm_Sub
(
node
)
||
is_arm_Rsb
(
node
)
||
is_arm_Mov
(
node
)
||
is_arm_Mvn
(
node
)
||
is_arm_Cmp
(
node
)
||
is_arm_Tst
(
node
);
||
is_arm_Cmp
(
node
)
||
is_arm_Tst
(
node
)
||
is_arm_LinkMovPC
(
node
)
;
}
static
bool
has_cmp_attr
(
const
ir_node
*
node
)
...
...
@@ -215,7 +215,7 @@ const arm_attr_t *get_arm_attr_const(const ir_node *node)
static
bool
has_symconst_attr
(
const
ir_node
*
node
)
{
return
is_arm_SymConst
(
node
)
||
is_arm_FrameAddr
(
node
);
return
is_arm_SymConst
(
node
)
||
is_arm_FrameAddr
(
node
)
||
is_arm_Bl
(
node
)
;
}
arm_SymConst_attr_t
*
get_arm_SymConst_attr
(
ir_node
*
node
)
...
...
ir/be/arm/arm_spec.pl
View file @
e086f5c2
...
...
@@ -309,6 +309,46 @@ Abs => {
mode
=>
$mode_gp
,
},
# mov lr, pc\n mov pc, XXX -- This combination is used for calls to function
# pointers
LinkMovPC
=>
{
state
=>
"
exc_pinned
",
arity
=>
"
variable
",
out_arity
=>
"
variable
",
attr_type
=>
"
arm_shifter_operand_t
",
attr
=>
"
arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot
",
custominit
=>
"
init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);
\n
"
.
"
\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
# pointers
LinkLdrPC
=>
{
state
=>
"
exc_pinned
",
arity
=>
"
variable
",
out_arity
=>
"
variable
",
attr_type
=>
"
arm_load_store_attr_t
",
attr
=>
"
ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity
",
custominit
=>
"
arch_irn_add_flags(res, arch_irn_flags_modify_flags);
",
emit
=>
"
. mov lr, pc
\n
"
.
"
. ldr pc, %SO
",
mode
=>
"
mode_T
",
},
Bl
=>
{
state
=>
"
exc_pinned
",
arity
=>
"
variable
",
out_arity
=>
"
variable
",
attr_type
=>
"
arm_SymConst_attr_t
",
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
EmptyReg
=>
{
op_flags
=>
"
c
",
...
...
@@ -539,44 +579,24 @@ fpaFix => {
emit
=>
'
. fix %D0, %S0
',
},
fpaCmfBra
=>
{
op_flags
=>
"
L|X|Y
",
state
=>
"
pinned
",
mode
=>
"
mode_T
",
attr
=>
"
pn_Cmp pnc
",
init_attr
=>
"
\t
set_arm_CondJmp_pnc(res, pnc);
",
reg_req
=>
{
in
=>
[
"
fpa
",
"
fpa
"
],
out
=>
[
"
none
",
"
none
"]
},
attr_type
=>
"
arm_CondJmp_attr_t
",
},
fpaCnfBra
=>
{
op_flags
=>
"
L|X|Y
",
state
=>
"
pinned
",
mode
=>
"
mode_T
",
attr
=>
"
int pnc
",
init_attr
=>
"
\t
set_arm_CondJmp_pnc(res, pnc);
",
reg_req
=>
{
in
=>
[
"
fpa
",
"
fpa
"
],
out
=>
[
"
none
",
"
none
"]
},
attr_type
=>
"
arm_CondJmp_attr_t
",
},
fpaCmfeBra
=>
{
op_flags
=>
"
L|X|Y
",
state
=>
"
pinned
",
mode
=>
"
mode_T
",
attr
=>
"
int pnc
",
init_attr
=>
"
\t
set_arm_CondJmp_pnc(res, pnc);
",
reg_req
=>
{
in
=>
[
"
fpa
",
"
fpa
"
],
out
=>
[
"
none
",
"
none
"]
},
attr_type
=>
"
arm_CondJmp_attr_t
",
},
fpaCnfeBra
=>
{
op_flags
=>
"
L|X|Y
",
state
=>
"
pinned
",
mode
=>
"
mode_T
",
attr
=>
"
int pnc
",
init_attr
=>
"
\t
set_arm_CondJmp_pnc(res, pnc);
",
reg_req
=>
{
in
=>
[
"
fpa
",
"
fpa
"
],
out
=>
[
"
none
",
"
none
"]
},
attr_type
=>
"
arm_CondJmp_attr_t
",
Cmf
=>
{
irn_flags
=>
"
R|F
",
mode
=>
$mode_flags
,
attr_type
=>
"
arm_cmp_attr_t
",
attr
=>
"
bool ins_permuted
",
init_attr
=>
"
init_arm_cmp_attr(res, ins_permuted, false);
",
reg_req
=>
{
in
=>
[
"
fpa
",
"
fpa
"
],
out
=>
[
"
flags
"
]
},
emit
=>
'
. cmf %S0, %S1
',
},
Cmfe
=>
{
irn_flags
=>
"
R|F
",
mode
=>
$mode_flags
,
attr_type
=>
"
arm_cmp_attr_t
",
attr
=>
"
bool ins_permuted
",
init_attr
=>
"
init_arm_cmp_attr(res, ins_permuted, false);
",
reg_req
=>
{
in
=>
[
"
fpa
",
"
fpa
"
],
out
=>
[
"
flags
"
]
},
emit
=>
'
. cmfe %S0, %S1
',
},
fpaLdf
=>
{
...
...
ir/be/arm/arm_transform.c
View file @
e086f5c2
This diff is collapsed.
Click to expand it.
ir/be/arm/bearch_arm.c
View file @
e086f5c2
...
...
@@ -72,6 +72,7 @@
static
arch_irn_class_t
arm_classify
(
const
ir_node
*
irn
)
{
(
void
)
irn
;
/* TODO: we should mark reload/spill instructions and classify them here */
return
0
;
}
...
...
@@ -119,7 +120,7 @@ static void arm_set_stack_bias(ir_node *irn, int bias)
static
int
arm_get_sp_bias
(
const
ir_node
*
irn
)
{
/* We don't have any nodes changing the stack pointer.
TODO: w
e probably want to support post-/pre increment/decrement later */
W
e probably want to support post-/pre increment/decrement later */
(
void
)
irn
;
return
0
;
}
...
...
@@ -200,10 +201,9 @@ static void arm_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_Reload
_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
);
...
...
@@ -227,10 +227,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
);
...
...
@@ -288,205 +287,13 @@ static void arm_emit_and_done(void *self)
free
(
self
);
}
/**
* Move a double floating point value into an integer register.
* Place the move operation into block bl.
*
* Handle some special cases here:
* 1.) A constant: simply split into two
* 2.) A load: simply split into two
*/
static
ir_node
*
convert_dbl_to_int
(
ir_node
*
bl
,
ir_node
*
arg
,
ir_node
*
mem
,
ir_node
**
resH
,
ir_node
**
resL
)
{
if
(
is_Const
(
arg
))
{
tarval
*
tv
=
get_Const_tarval
(
arg
);
unsigned
v
;
/* get the upper 32 bits */
v
=
get_tarval_sub_bits
(
tv
,
7
);
v
=
(
v
<<
8
)
|
get_tarval_sub_bits
(
tv
,
6
);
v
=
(
v
<<
8
)
|
get_tarval_sub_bits
(
tv
,
5
);
v
=
(
v
<<
8
)
|
get_tarval_sub_bits
(
tv
,
4
);
*
resH
=
new_Const_long
(
mode_Is
,
v
);
/* get the lower 32 bits */
v
=
get_tarval_sub_bits
(
tv
,
3
);
v
=
(
v
<<
8
)
|
get_tarval_sub_bits
(
tv
,
2
);
v
=
(
v
<<
8
)
|
get_tarval_sub_bits
(
tv
,
1
);
v
=
(
v
<<
8
)
|
get_tarval_sub_bits
(
tv
,
0
);
*
resL
=
new_Const_long
(
mode_Is
,
v
);
}
else
if
(
is_Load
(
skip_Proj
(
arg
)))
{
/* FIXME: handling of low/high depends on LE/BE here */
panic
(
"Unimplemented convert_dbl_to_int() case"
);
}
else
{
ir_node
*
conv
;
conv
=
new_bd_arm_fpaDbl2GP
(
NULL
,
bl
,
arg
,
mem
);
/* move high/low */
*
resL
=
new_r_Proj
(
conv
,
mode_Is
,
pn_arm_fpaDbl2GP_low
);
*
resH
=
new_r_Proj
(
conv
,
mode_Is
,
pn_arm_fpaDbl2GP_high
);
mem
=
new_r_Proj
(
conv
,
mode_M
,
pn_arm_fpaDbl2GP_M
);
}
return
mem
;
}
/**
* Move a single floating point value into an integer register.
* Place the move operation into block bl.
*
* Handle some special cases here:
* 1.) A constant: simply move
* 2.) A load: simply load
*/
static
ir_node
*
convert_sng_to_int
(
ir_node
*
bl
,
ir_node
*
arg
)
{
(
void
)
bl
;
if
(
is_Const
(
arg
))
{
tarval
*
tv
=
get_Const_tarval
(
arg
);
unsigned
v
;
/* get the lower 32 bits */
v
=
get_tarval_sub_bits
(
tv
,
3
);
v
=
(
v
<<
8
)
|
get_tarval_sub_bits
(
tv
,
2
);
v
=
(
v
<<
8
)
|
get_tarval_sub_bits
(
tv
,
1
);
v
=
(
v
<<
8
)
|
get_tarval_sub_bits
(
tv
,
0
);
return
new_Const_long
(
mode_Is
,
v
);
}
panic
(
"Unimplemented convert_sng_to_int() case"
);
}
/**
* Convert the arguments of a call to support the
* ARM calling convention of general purpose AND floating
* point arguments.
*/
static
void
handle_calls
(
ir_node
*
call
,
void
*
env
)
{
arm_code_gen_t
*
cg
=
env
;
int
i
,
j
,
n
,
size
,
idx
,
flag
,
n_param
,
n_res
,
first_variadic
;
ir_type
*
mtp
,
*
new_mtd
,
*
new_tp
[
5
];
ir_node
*
new_in
[
5
],
**
in
;
ir_node
*
bl
;
if
(
!
is_Call
(
call
))
return
;
/* check, if we need conversions */
n
=
get_Call_n_params
(
call
);
mtp
=
get_Call_type
(
call
);
assert
(
get_method_n_params
(
mtp
)
==
n
);
/* it's always enough to handle the first 4 parameters */
if
(
n
>
4
)
n
=
4
;
flag
=
size
=
idx
=
0
;
bl
=
get_nodes_block
(
call
);
for
(
i
=
0
;
i
<
n
;
++
i
)
{
ir_type
*
param_tp
=
get_method_param_type
(
mtp
,
i
);
if
(
is_compound_type
(
param_tp
))
{
/* an aggregate parameter: bad case */
assert
(
0
);
}
else
{
/* a primitive parameter */
ir_mode
*
mode
=
get_type_mode
(
param_tp
);
if
(
mode_is_float
(
mode
))
{
if
(
get_mode_size_bits
(
mode
)
>
32
)
{
ir_node
*
mem
=
get_Call_mem
(
call
);
/* Beware: ARM wants the high part first */
size
+=
2
*
4
;
new_tp
[
idx
]
=
cg
->
int_tp
;
new_tp
[
idx
+
1
]
=
cg
->
int_tp
;
mem
=
convert_dbl_to_int
(
bl
,
get_Call_param
(
call
,
i
),
mem
,
&
new_in
[
idx
],
&
new_in
[
idx
+
1
]);
idx
+=
2
;
set_Call_mem
(
call
,
mem
);
}
else
{
size
+=
4
;
new_tp
[
idx
]
=
cg
->
int_tp
;
new_in
[
idx
]
=
convert_sng_to_int
(
bl
,
get_Call_param
(
call
,
i
));
++
idx
;
}
flag
=
1
;
}
else
{
size
+=
4
;
new_tp
[
idx
]
=
param_tp
;
new_in
[
idx
]
=
get_Call_param
(
call
,
i
);
++
idx
;
}
}
if
(
size
>=
16
)
break
;
}
/* if flag is NOT set, no need to translate the method type */
if
(
!
flag
)
return
;
/* construct a new method type */
n
=
i
;
n_param
=
get_method_n_params
(
mtp
)
-
n
+
idx
;
n_res
=
get_method_n_ress
(
mtp
);
new_mtd
=
new_d_type_method
(
n_param
,
n_res
,
get_type_dbg_info
(
mtp
));
for
(
i
=
0
;
i
<
idx
;
++
i
)
set_method_param_type
(
new_mtd
,
i
,
new_tp
[
i
]);
for
(
i
=
n
,
j
=
idx
;
i
<
get_method_n_params
(
mtp
);
++
i
)
set_method_param_type
(
new_mtd
,
j
++
,
get_method_param_type
(
mtp
,
i
));
for
(
i
=
0
;
i
<
n_res
;
++
i
)
set_method_res_type
(
new_mtd
,
i
,
get_method_res_type
(
mtp
,
i
));
set_method_calling_convention
(
new_mtd
,
get_method_calling_convention
(
mtp
));
first_variadic
=
get_method_first_variadic_param_index
(
mtp
);
if
(
first_variadic
>=
0
)
set_method_first_variadic_param_index
(
new_mtd
,
first_variadic
);
if
(
is_lowered_type
(
mtp
))
{
mtp
=
get_associated_type
(
mtp
);
}
set_lowered_type
(
mtp
,
new_mtd
);
set_Call_type
(
call
,
new_mtd
);
/* calculate new in array of the Call */
NEW_ARR_A
(
ir_node
*
,
in
,
n_param
+
2
);
for
(
i
=
0
;
i
<
idx
;
++
i
)
in
[
2
+
i
]
=
new_in
[
i
];
for
(
i
=
n
,
j
=
idx
;
i
<
get_method_n_params
(
mtp
);
++
i
)
in
[
2
+
j
++
]
=
get_Call_param
(
call
,
i
);
in
[
0
]
=
get_Call_mem
(
call
);
in
[
1
]
=
get_Call_ptr
(
call
);
/* finally, change the call inputs */
set_irn_in
(
call
,
n_param
+
2
,
in
);
}
/**
* Handle graph transformations before the abi converter does its work.
*/
static
void
arm_before_abi
(
void
*
self
)
{
arm_code_gen_t
*
cg
=
self
;
irg_walk_graph
(
cg
->
irg
,
NULL
,
handle_calls
,
cg
);
}
/* forward */
static
void
*
arm_cg_init
(
ir_graph
*
irg
);
static
const
arch_code_generator_if_t
arm_code_gen_if
=
{
arm_cg_init
,
NULL
,
/* get_pic_base */
arm_before_abi
,
/* before abi introduce */
NULL
,
/* before abi introduce */
arm_prepare_graph
,
NULL
,
/* spill */
arm_before_ra
,
/* before register allocation hook */
...
...
@@ -667,7 +474,7 @@ static arm_isa_t arm_isa_template = {
NULL
,
/* main environment */
7
,
/* spill costs */
5
,
/* reload costs */
fals
e
,
/*
no
custom abi handling */
tru
e
,
/*
we do have
custo