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
1cf8643e
Commit
1cf8643e
authored
Mar 09, 2006
by
Christian Würdig
Browse files
added after_ra hook
lower some benodes emit some other benodes implemented frame entity functions
parent
df1fb856
Changes
4
Hide whitespace changes
Inline
Side-by-side
ir/be/ia32/bearch_ia32.c
View file @
1cf8643e
...
...
@@ -205,15 +205,22 @@ static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
}
}
static
entity
*
ia32_get_frame_entity
(
const
void
*
self
,
const
ir_node
*
irn
)
{
/* TODO: Implement */
return
NULL
;
static
entity
*
ia32_get_frame_entity
(
const
void
*
self
,
const
ir_node
*
irn
)
{
return
is_ia32_irn
(
irn
)
?
get_ia32_frame_ent
(
irn
)
:
NULL
;
}
static
void
ia32_set_stack_bias
(
const
void
*
self
,
ir_node
*
irn
,
int
bias
)
{
char
buf
[
64
];
const
ia32_irn_ops_t
*
ops
=
self
;
if
(
is_ia32_use_frame
(
irn
))
{
/* TODO: correct offset */
ia32_am_flavour_t
am_flav
=
get_ia32_am_flavour
(
irn
);
DBG
((
ops
->
cg
->
mod
,
LEVEL_1
,
"stack biased %+F with %d
\n
"
,
irn
,
bias
));
snprintf
(
buf
,
sizeof
(
buf
),
"%d"
,
bias
);
add_ia32_am_offs
(
irn
,
buf
);
am_flav
|=
ia32_O
;
set_ia32_am_flavour
(
irn
,
am_flav
);
}
}
...
...
@@ -263,12 +270,54 @@ static void ia32_prepare_graph(void *self) {
}
/**
* Insert copies for all ia32 nodes where the should_be_same requirement
* is not fulfilled.
*/
static
void
ia32_finish_irg_walker
(
ir_node
*
irn
,
void
*
env
)
{
ia32_code_gen_t
*
cg
=
env
;
const
ia32_register_req_t
**
reqs
;
const
arch_register_t
*
out_reg
,
*
in_reg
;
int
n_res
,
i
;
ir_node
*
copy
,
*
in_node
,
*
block
;
if
(
!
is_ia32_irn
(
irn
))
return
;
reqs
=
get_ia32_out_req_all
(
irn
);
n_res
=
get_ia32_n_res
(
irn
);
block
=
get_nodes_block
(
irn
);
/* check all OUT requirements, if there is a should_be_same */
for
(
i
=
0
;
i
<
n_res
;
i
++
)
{
if
(
arch_register_req_is
(
&
(
reqs
[
i
]
->
req
),
should_be_same
))
{
/* get in and out register */
out_reg
=
get_ia32_out_reg
(
irn
,
i
);
in_node
=
get_irn_n
(
irn
,
reqs
[
i
]
->
same_pos
);
in_reg
=
arch_get_irn_register
(
cg
->
arch_env
,
in_node
);
/* check if in and out register are equal */
if
(
arch_register_get_index
(
out_reg
)
!=
arch_register_get_index
(
in_reg
))
{
DBG
((
cg
->
mod
,
LEVEL_1
,
"inserting copy for %+F in_pos %d
\n
"
,
irn
,
reqs
[
i
]
->
same_pos
));
/* create copy from in register */
copy
=
be_new_Copy
(
arch_register_get_class
(
in_reg
),
cg
->
irg
,
block
,
in_node
);
/* destination is the out register */
arch_set_irn_register
(
cg
->
arch_env
,
copy
,
out_reg
);
/* insert copy before the node into the schedule */
sched_add_before
(
irn
,
copy
);
}
}
}
}
/**
*
Stack reservation and StackParam lowering.
*
Add Copy nodes for not fulfilled should_be_equal constraints
*/
static
void
ia32_finish_irg
(
ir_graph
*
irg
,
ia32_code_gen_t
*
cg
)
{
irg_walk_blkwise_graph
(
irg
,
NULL
,
ia32_finish_irg_walker
,
cg
);
}
...
...
@@ -284,6 +333,131 @@ static void ia32_before_ra(void *self) {
/**
* Transforms a be node into a Load.
*/
static
void
transform_to_Load
(
ia32_transform_env_t
*
env
)
{
ir_node
*
irn
=
env
->
irn
;
entity
*
ent
=
be_get_frame_entity
(
irn
);
ir_mode
*
mode
=
env
->
mode
;
ir_node
*
noreg
=
ia32_new_NoReg_gp
(
env
->
cg
);
ir_node
*
nomem
=
new_rd_NoMem
(
env
->
irg
);
ir_node
*
new_op
,
*
proj
;
ir_node
*
sched_point
=
NULL
;
if
(
sched_is_scheduled
(
irn
))
{
sched_point
=
sched_prev
(
irn
);
}
if
(
mode_is_float
(
mode
))
{
new_op
=
new_rd_ia32_fLoad
(
env
->
dbg
,
env
->
irg
,
env
->
block
,
get_irn_n
(
irn
,
0
),
noreg
,
nomem
,
mode_T
);
}
else
{
new_op
=
new_rd_ia32_Load
(
env
->
dbg
,
env
->
irg
,
env
->
block
,
get_irn_n
(
irn
,
0
),
noreg
,
nomem
,
mode_T
);
}
set_ia32_am_support
(
new_op
,
ia32_am_Source
);
set_ia32_op_type
(
new_op
,
ia32_AddrModeS
);
set_ia32_am_flavour
(
new_op
,
ia32_B
);
set_ia32_ls_mode
(
new_op
,
mode
);
set_ia32_frame_ent
(
new_op
,
ent
);
set_ia32_use_frame
(
new_op
);
proj
=
new_rd_Proj
(
env
->
dbg
,
env
->
irg
,
env
->
block
,
new_op
,
mode
,
pn_Load_res
);
if
(
sched_point
)
{
sched_add_after
(
sched_point
,
new_op
);
sched_add_after
(
new_op
,
proj
);
sched_remove
(
irn
);
}
exchange
(
irn
,
proj
);
}
/**
* Transforms a be node into a Store.
*/
static
void
transform_to_Store
(
ia32_transform_env_t
*
env
)
{
ir_node
*
irn
=
env
->
irn
;
entity
*
ent
=
be_get_frame_entity
(
irn
);
ir_mode
*
mode
=
env
->
mode
;
ir_node
*
noreg
=
ia32_new_NoReg_gp
(
env
->
cg
);
ir_node
*
nomem
=
new_rd_NoMem
(
env
->
irg
);
ir_node
*
ptr
=
get_irn_n
(
irn
,
0
);
ir_node
*
val
=
get_irn_n
(
irn
,
1
);
ir_node
*
new_op
,
*
proj
;
ir_node
*
sched_point
=
NULL
;
if
(
sched_is_scheduled
(
irn
))
{
sched_point
=
sched_prev
(
irn
);
}
if
(
mode_is_float
(
mode
))
{
new_op
=
new_rd_ia32_fStore
(
env
->
dbg
,
env
->
irg
,
env
->
block
,
ptr
,
noreg
,
val
,
nomem
,
mode_T
);
}
else
{
new_op
=
new_rd_ia32_Store
(
env
->
dbg
,
env
->
irg
,
env
->
block
,
ptr
,
noreg
,
val
,
nomem
,
mode_T
);
}
set_ia32_am_support
(
new_op
,
ia32_am_Dest
);
set_ia32_op_type
(
new_op
,
ia32_AddrModeD
);
set_ia32_am_flavour
(
new_op
,
ia32_B
);
set_ia32_ls_mode
(
new_op
,
get_irn_mode
(
val
));
set_ia32_frame_ent
(
new_op
,
ent
);
set_ia32_use_frame
(
new_op
);
proj
=
new_rd_Proj
(
env
->
dbg
,
env
->
irg
,
env
->
block
,
new_op
,
mode
,
0
);
if
(
sched_point
)
{
sched_add_after
(
sched_point
,
new_op
);
sched_add_after
(
new_op
,
proj
);
sched_remove
(
irn
);
}
exchange
(
irn
,
proj
);
}
/**
* Calls the transform functions for StackParam, Spill and Reload.
*/
static
void
ia32_after_ra_walker
(
ir_node
*
node
,
void
*
env
)
{
ia32_code_gen_t
*
cg
=
env
;
ir_node
*
new_node
=
NULL
;
ia32_transform_env_t
tenv
;
if
(
is_Block
(
node
))
return
;
tenv
.
block
=
get_nodes_block
(
node
);
tenv
.
dbg
=
get_irn_dbg_info
(
node
);
tenv
.
irg
=
current_ir_graph
;
tenv
.
irn
=
node
;
tenv
.
mod
=
cg
->
mod
;
tenv
.
mode
=
get_irn_mode
(
node
);
tenv
.
cg
=
cg
;
if
(
be_is_StackParam
(
node
)
||
be_is_Reload
(
node
))
{
transform_to_Load
(
&
tenv
);
}
else
if
(
be_is_Spill
(
node
))
{
transform_to_Store
(
&
tenv
);
}
}
/**
* We transform StackParam, Spill and Reload here. This needs to be done before
* stack biasing otherwise we would miss the corrected offset for these nodes.
*/
static
void
ia32_after_ra
(
void
*
self
)
{
ia32_code_gen_t
*
cg
=
self
;
irg_walk_blkwise_graph
(
cg
->
irg
,
NULL
,
ia32_after_ra_walker
,
self
);
}
/**
* Emits the code, closes the output file and frees
* the code generator interface.
...
...
@@ -293,15 +467,13 @@ static void ia32_codegen(void *self) {
ir_graph
*
irg
=
cg
->
irg
;
FILE
*
out
=
cg
->
out
;
ia32_register_emitters
();
if
(
cg
->
emit_decls
)
{
ia32_gen_decls
(
cg
->
out
);
cg
->
emit_decls
=
0
;
}
ia32_finish_irg
(
irg
,
cg
);
//
dump_ir_block_graph_sched(irg, "-finished");
dump_ir_block_graph_sched
(
irg
,
"-finished"
);
ia32_gen_routine
(
out
,
irg
,
cg
);
cur_reg_set
=
NULL
;
...
...
@@ -321,6 +493,7 @@ static const arch_code_generator_if_t ia32_code_gen_if = {
ia32_prepare_graph
,
ia32_before_sched
,
/* before scheduling hook */
ia32_before_ra
,
/* before register allocation hook */
ia32_after_ra
,
/* after register allocation hook */
ia32_codegen
/* emit && done */
};
...
...
ir/be/ia32/ia32_emitter.c
View file @
1cf8643e
...
...
@@ -803,7 +803,7 @@ void emit_be_AddSP(const ir_node *irn, emit_env_t *emit_env) {
* Enters the emitter functions for handled nodes into the generic
* pointer of an opcode.
*/
void
ia32_register_emitters
(
void
)
{
static
void
ia32_register_emitters
(
void
)
{
#define IA32_EMIT(a) op_ia32_##a->ops.generic = (op_func)emit_ia32_##a
#define EMIT(a) op_##a->ops.generic = (op_func)emit_##a
...
...
@@ -815,7 +815,7 @@ void ia32_register_emitters(void) {
/* register all emitter functions defined in spec */
ia32_register_spec_emitters
();
/* other emitter functions */
/* other
ia32
emitter functions */
IA32_EMIT
(
CondJmp
);
IA32_EMIT
(
SwitchJmp
);
IA32_EMIT
(
CopyB
);
...
...
@@ -922,6 +922,8 @@ void ia32_gen_routine(FILE *F, ir_graph *irg, const ia32_code_gen_t *cg) {
/* set the global arch_env (needed by print hooks) */
arch_env
=
cg
->
arch_env
;
ia32_register_emitters
();
ia32_emit_func_prolog
(
F
,
irg
);
irg_block_walk_graph
(
irg
,
ia32_gen_labels
,
NULL
,
&
emit_env
);
irg_walk_blkwise_graph
(
irg
,
NULL
,
ia32_gen_block
,
&
emit_env
);
...
...
ir/be/ia32/ia32_emitter.h
View file @
1cf8643e
...
...
@@ -25,7 +25,6 @@ char *ia32_emit_am(const ir_node *irn);
int
get_ia32_reg_nr
(
ir_node
*
irn
,
int
posi
,
int
in_out
);
const
char
*
get_ia32_in_reg_name
(
ir_node
*
irn
,
int
pos
);
void
ia32_register_emitters
(
void
);
void
ia32_gen_routine
(
FILE
*
F
,
ir_graph
*
irg
,
const
ia32_code_gen_t
*
cg
);
#endif
/* _IA32_EMITTER_H_ */
ir/be/ia32/ia32_transform.c
View file @
1cf8643e
...
...
@@ -5,12 +5,14 @@
#include
"irnode_t.h"
#include
"irgraph_t.h"
#include
"irmode_t.h"
#include
"iropt_t.h"
#include
"irop_t.h"
#include
"irprog_t.h"
#include
"irgmod.h"
#include
"iredges.h"
#include
"irvrfy.h"
#include
"ircons.h"
#include
"dbginfo.h"
#include
"iropt_t.h"
#include
"debug.h"
#include
"../benode_t.h"
...
...
@@ -1280,6 +1282,17 @@ static ir_node *gen_Mux(ia32_transform_env_t *env) {
/********************************************
* _ _
* | | | |
* | |__ ___ _ __ ___ __| | ___ ___
* | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
* | |_) | __/ | | | (_) | (_| | __/\__ \
* |_.__/ \___|_| |_|\___/ \__,_|\___||___/
*
********************************************/
/*********************************************************
* _ _ _
* (_) | | (_)
...
...
@@ -1290,8 +1303,6 @@ static ir_node *gen_Mux(ia32_transform_env_t *env) {
*
*********************************************************/
/**
* Transforms the given firm node (and maybe some other related nodes)
* into one or more assembler nodes.
...
...
@@ -1321,6 +1332,16 @@ void ia32_transform_node(ir_node *node, void *env) {
#define GEN(a) case iro_##a: asm_node = gen_##a(&tenv); break
#define IGN(a) case iro_##a: break
#define BAD(a) case iro_##a: goto bad
#define OTHER_BIN(a) \
if (get_irn_op(node) == get_op_##a()) { \
asm_node = gen_##a(&tenv, get_irn_n(node, 0), get_irn_n(node, 1)); \
break; \
}
#define BE_GEN(a) \
if (be_is_##a(node)) { \
asm_node = gen_##a(&tenv); \
break; \
}
DBG
((
tenv
.
mod
,
LEVEL_1
,
"check %+F ... "
,
node
));
...
...
@@ -1367,6 +1388,7 @@ void ia32_transform_node(ir_node *node, void *env) {
IGN
(
Break
);
IGN
(
Cmp
);
IGN
(
Unknown
);
/* constant transformation happens earlier */
IGN
(
Const
);
IGN
(
SymConst
);
...
...
@@ -1387,21 +1409,16 @@ void ia32_transform_node(ir_node *node, void *env) {
BAD
(
EndExcept
);
default:
if
(
get_irn_op
(
node
)
==
get_op_Max
())
{
asm_node
=
gen_Max
(
&
tenv
,
get_irn_n
(
node
,
0
),
get_irn_n
(
node
,
1
));
}
else
if
(
get_irn_op
(
node
)
==
get_op_Min
())
{
asm_node
=
gen_Min
(
&
tenv
,
get_irn_n
(
node
,
0
),
get_irn_n
(
node
,
1
));
}
else
if
(
get_irn_op
(
node
)
==
get_op_Mulh
())
{
asm_node
=
gen_Mulh
(
&
tenv
,
get_irn_n
(
node
,
0
),
get_irn_n
(
node
,
1
));
}
OTHER_BIN
(
Max
);
OTHER_BIN
(
Min
);
OTHER_BIN
(
Mulh
);
break
;
bad:
fprintf
(
stderr
,
"Not implemented: %s
\n
"
,
get_irn_opname
(
node
));
assert
(
0
);
}
/* exchange nodes if a new one was generated */
if
(
asm_node
)
{
exchange
(
node
,
asm_node
);
DB
((
tenv
.
mod
,
LEVEL_1
,
"created node %+F[%p]
\n
"
,
asm_node
,
asm_node
));
...
...
@@ -1409,4 +1426,12 @@ bad:
else
{
DB
((
tenv
.
mod
,
LEVEL_1
,
"ignored
\n
"
));
}
#undef UNOP
#undef BINOP
#undef GEN
#undef IGN
#undef BAD
#undef OTHER_BIN
#undef BE_GEN
}
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