Commit 1cf8643e authored by Christian Würdig's avatar Christian Würdig
Browse files

added after_ra hook

lower some benodes
emit some other benodes
implemented frame entity functions
parent df1fb856
......@@ -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 */
};
......
......@@ -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);
......
......@@ -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_ */
......@@ -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
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment