Commit 23b80d8b authored by Matthias Braun's avatar Matthias Braun
Browse files

abihelper: remove now unused prolog/epilog helpers

parent f074195d
......@@ -23,345 +23,6 @@
#include "irtools.h"
#include "heights.h"
/**
* An entry in the register state map.
*/
typedef struct reg_flag_t {
const arch_register_t *reg; /**< register at an input position.
may be NULL in case of memory input */
arch_register_req_type_t flags; /**< requirement flags for this register. */
} reg_flag_t;
/**
* A register state mapping keeps track of the symbol values (=firm nodes)
* to registers. This is useful when constructing straight line code
* like the function prolog or epilog in some architectures.
*/
typedef struct register_state_mapping_t {
ir_node **value_map; /**< mapping of state indices to values */
size_t **reg_index_map; /**< mapping of regclass,regnum to an index
into the value_map */
reg_flag_t *regs; /**< registers (and memory values) that form a
state */
} register_state_mapping_t;
/**
* The environment for all helper functions.
*/
struct beabi_helper_env_t {
ir_graph *irg; /**< the graph we operate on */
register_state_mapping_t prolog; /**< the register state map for the prolog */
register_state_mapping_t epilog; /**< the register state map for the epilog */
};
/**
* Create a new empty register state map for the given
* architecture.
*
* @param rsm the register state map to be initialized
* @param arch_env the architecture environment
*
* After this call, the register map is initialized to empty.
*/
static void prepare_rsm(register_state_mapping_t *rsm,
const arch_env_t *arch_env)
{
unsigned n_reg_classes = arch_env->n_register_classes;
unsigned c;
reg_flag_t memory = { NULL, arch_register_req_type_none };
rsm->regs = NEW_ARR_F(reg_flag_t, 0);
/* memory input at 0 */
ARR_APP1(reg_flag_t, rsm->regs, memory);
rsm->value_map = NULL;
rsm->reg_index_map = XMALLOCN(size_t*, n_reg_classes);
for (c = 0; c < n_reg_classes; ++c) {
const arch_register_class_t *cls = &arch_env->register_classes[c];
unsigned n_regs = arch_register_class_n_regs(cls);
unsigned r;
rsm->reg_index_map[c] = XMALLOCN(size_t, n_regs);
for (r = 0; r < n_regs; ++r) {
rsm->reg_index_map[c][r] = (size_t)-1;
}
}
}
/**
* Destroy a register state map for the given
* architecture.
*
* @param rsm the register state map to be destroyed
* @param arch_env the architecture environment
*
* After this call, the register map is initialized to empty.
*/
static void free_rsm(register_state_mapping_t *rsm, const arch_env_t *arch_env)
{
unsigned n_reg_classes = arch_env->n_register_classes;
unsigned c;
for (c = 0; c < n_reg_classes; ++c) {
free(rsm->reg_index_map[c]);
}
free(rsm->reg_index_map);
if (rsm->value_map != NULL)
DEL_ARR_F(rsm->value_map);
DEL_ARR_F(rsm->regs);
rsm->regs = NULL;
rsm->reg_index_map = NULL;
rsm->value_map = NULL;
}
/**
* Remove all registers from a register state map.
*
* @param rsm the register state map to be destroyed
* @param arch_env the architecture environment
*/
static void rsm_clear_regs(register_state_mapping_t *rsm,
const arch_env_t *arch_env)
{
unsigned n_reg_classes = arch_env->n_register_classes;
unsigned c;
reg_flag_t memory = { NULL, arch_register_req_type_none };
for (c = 0; c < n_reg_classes; ++c) {
const arch_register_class_t *cls = &arch_env->register_classes[c];
unsigned n_regs = arch_register_class_n_regs(cls);
unsigned r;
for (r = 0; r < n_regs; ++r) {
rsm->reg_index_map[c][r] = (size_t)-1;
}
}
ARR_RESIZE(reg_flag_t, rsm->regs, 0);
ARR_APP1(reg_flag_t, rsm->regs, memory);
if (rsm->value_map != NULL) {
DEL_ARR_F(rsm->value_map);
rsm->value_map = NULL;
}
}
/**
* Add a register and its constraint flags to a register state map
* and return its index inside the map.
*/
static size_t rsm_add_reg(register_state_mapping_t *rsm,
const arch_register_t *reg,
arch_register_req_type_t flags)
{
size_t input_idx = ARR_LEN(rsm->regs);
int cls_idx = reg->reg_class->index;
int reg_idx = reg->index;
reg_flag_t regflag = { reg, flags };
/* we must not have used get_value yet */
assert(rsm->reg_index_map[cls_idx][reg_idx] == (size_t)-1);
rsm->reg_index_map[cls_idx][reg_idx] = input_idx;
ARR_APP1(reg_flag_t, rsm->regs, regflag);
if (rsm->value_map != NULL) {
ARR_APP1(ir_node*, rsm->value_map, NULL);
assert(ARR_LEN(rsm->value_map) == ARR_LEN(rsm->regs));
}
return input_idx;
}
/**
* Retrieve the ir_node stored at the given index in the register state map.
*/
static ir_node *rsm_get_value(register_state_mapping_t *rsm, size_t index)
{
assert(index < ARR_LEN(rsm->value_map));
return rsm->value_map[index];
}
/**
* Retrieve the ir_node occupying the given register in the register state map.
*/
static ir_node *rsm_get_reg_value(register_state_mapping_t *rsm,
const arch_register_t *reg)
{
int cls_idx = reg->reg_class->index;
int reg_idx = reg->index;
size_t input_idx = rsm->reg_index_map[cls_idx][reg_idx];
return rsm_get_value(rsm, input_idx);
}
/**
* Enter a ir_node at the given index in the register state map.
*/
static void rsm_set_value(register_state_mapping_t *rsm, size_t index,
ir_node *value)
{
assert(index < ARR_LEN(rsm->value_map));
rsm->value_map[index] = value;
}
/**
* Enter a ir_node at the given register in the register state map.
*/
static void rsm_set_reg_value(register_state_mapping_t *rsm,
const arch_register_t *reg, ir_node *value)
{
int cls_idx = reg->reg_class->index;
int reg_idx = reg->index;
size_t input_idx = rsm->reg_index_map[cls_idx][reg_idx];
rsm_set_value(rsm, input_idx, value);
}
beabi_helper_env_t *be_abihelper_prepare(ir_graph *irg)
{
const arch_env_t *arch_env = be_get_irg_arch_env(irg);
beabi_helper_env_t *env = XMALLOCZ(beabi_helper_env_t);
env->irg = irg;
prepare_rsm(&env->prolog, arch_env);
prepare_rsm(&env->epilog, arch_env);
return env;
}
void be_abihelper_finish(beabi_helper_env_t *env)
{
const arch_env_t *arch_env = be_get_irg_arch_env(env->irg);
free_rsm(&env->prolog, arch_env);
if (env->epilog.reg_index_map != NULL) {
free_rsm(&env->epilog, arch_env);
}
free(env);
}
void be_prolog_add_reg(beabi_helper_env_t *env, const arch_register_t *reg,
arch_register_req_type_t flags)
{
rsm_add_reg(&env->prolog, reg, flags);
}
ir_node *be_prolog_create_start(beabi_helper_env_t *env, dbg_info *dbgi,
ir_node *block)
{
int n_start_outs = ARR_LEN(env->prolog.regs);
ir_node *start = be_new_Start(dbgi, block, n_start_outs);
int o;
assert(env->prolog.value_map == NULL);
env->prolog.value_map = NEW_ARR_F(ir_node*, n_start_outs);
for (o = 0; o < n_start_outs; ++o) {
const reg_flag_t *regflag = &env->prolog.regs[o];
const arch_register_t *reg = regflag->reg;
ir_node *proj;
if (reg == NULL) {
arch_set_irn_register_req_out(start, o, arch_no_register_req);
proj = new_r_Proj(start, mode_M, o);
} else {
be_set_constr_single_reg_out(start, o, regflag->reg,
regflag->flags);
arch_set_irn_register_out(start, o, regflag->reg);
proj = new_r_Proj(start, reg->reg_class->mode, o);
}
env->prolog.value_map[o] = proj;
}
return start;
}
ir_node *be_prolog_get_reg_value(beabi_helper_env_t *env,
const arch_register_t *reg)
{
return rsm_get_reg_value(&env->prolog, reg);
}
ir_node *be_prolog_get_memory(beabi_helper_env_t *env)
{
return rsm_get_value(&env->prolog, 0);
}
void be_prolog_set_reg_value(beabi_helper_env_t *env,
const arch_register_t *reg, ir_node *value)
{
rsm_set_reg_value(&env->prolog, reg, value);
}
void be_prolog_set_memory(beabi_helper_env_t *env, ir_node *value)
{
rsm_set_value(&env->prolog, 0, value);
}
void be_epilog_begin(beabi_helper_env_t *env)
{
const arch_env_t *arch_env = be_get_irg_arch_env(env->irg);
rsm_clear_regs(&env->epilog, arch_env);
env->epilog.value_map = NEW_ARR_F(ir_node*, 1);
env->epilog.value_map[0] = NULL;
}
void be_epilog_add_reg(beabi_helper_env_t *env, const arch_register_t *reg,
arch_register_req_type_t flags, ir_node *value)
{
size_t index = rsm_add_reg(&env->epilog, reg, flags);
rsm_set_value(&env->epilog, index, value);
}
void be_epilog_set_reg_value(beabi_helper_env_t *env,
const arch_register_t *reg, ir_node *value)
{
rsm_set_reg_value(&env->epilog, reg, value);
}
void be_epilog_set_memory(beabi_helper_env_t *env, ir_node *value)
{
rsm_set_value(&env->epilog, 0, value);
}
ir_node *be_epilog_get_reg_value(beabi_helper_env_t *env,
const arch_register_t *reg)
{
return rsm_get_reg_value(&env->epilog, reg);
}
ir_node *be_epilog_get_memory(beabi_helper_env_t *env)
{
return rsm_get_value(&env->epilog, 0);
}
ir_node *be_epilog_create_return(beabi_helper_env_t *env, dbg_info *dbgi,
ir_node *block)
{
size_t n_return_in = ARR_LEN(env->epilog.regs);
ir_node **in = env->epilog.value_map;
int n_res = 1; /* TODO */
unsigned pop = 0; /* TODO */
size_t i;
assert(ARR_LEN(env->epilog.value_map) == n_return_in);
ir_node *const ret = be_new_Return(dbgi, block, n_res, pop, n_return_in, in);
for (i = 0; i < n_return_in; ++i) {
const reg_flag_t *regflag = &env->epilog.regs[i];
const arch_register_t *reg = regflag->reg;
if (reg != NULL) {
be_set_constr_single_reg_in(ret, i, reg,
arch_register_req_type_none);
}
}
rsm_clear_regs(&env->epilog, be_get_irg_arch_env(env->irg));
return ret;
}
/**
* Tests whether a node has a real user and is not just kept by the End or
* Anchor node
......
......@@ -16,83 +16,8 @@
#include "be_types.h"
#include "bearch.h"
typedef struct beabi_helper_env_t beabi_helper_env_t;
typedef struct be_stackorder_t be_stackorder_t;
/**
* Creates a helper object for the ABI constraint handling.
*/
beabi_helper_env_t *be_abihelper_prepare(ir_graph *irg);
/**
* Terminates a helper object for the ABI constraint handling.
*/
void be_abihelper_finish(beabi_helper_env_t *env);
/**
* Mark a registers value at the beginning of the function as significant.
* This is necessary for things like:
* - Callee-Save registers (we need to restore that value at the end)
* - Parameters passed in registers
* - stack pointer, base pointer, ...
* It is possible to specify additional irn flags (useful to mark a value
* as ignore or produces_sp).
*/
void be_prolog_add_reg(beabi_helper_env_t *env, const arch_register_t *reg,
arch_register_req_type_t flags);
/**
* Creates a start node.
* Must be called after all prolog_add_reg calls
*/
ir_node *be_prolog_create_start(beabi_helper_env_t *env, dbg_info *dbgi,
ir_node *block);
/**
* Get "value" of a register.
* This usually creates a Proj node for the start-node.
* Or returns the value set by a abi_helper_set_reg_value call
*/
ir_node *be_prolog_get_reg_value(beabi_helper_env_t *env,
const arch_register_t *reg);
ir_node *be_prolog_get_memory(beabi_helper_env_t *env);
/**
* Set current register value.
*/
void be_prolog_set_reg_value(beabi_helper_env_t *env,
const arch_register_t *reg, ir_node *value);
void be_prolog_set_memory(beabi_helper_env_t *env, ir_node *value);
/**
* Set value of register at the end of the function. Necessary for:
* - Callee-save registers
* - Return values in registers
* - stack pointer, base pointer
*/
void be_epilog_add_reg(beabi_helper_env_t *env, const arch_register_t *reg,
arch_register_req_type_t flags, ir_node *value);
void be_epilog_set_reg_value(beabi_helper_env_t *env,
const arch_register_t *reg, ir_node *value);
ir_node *be_epilog_get_reg_value(beabi_helper_env_t *env,
const arch_register_t *reg);
void be_epilog_set_memory(beabi_helper_env_t *env, ir_node *value);
ir_node *be_epilog_get_memory(beabi_helper_env_t *env);
void be_epilog_begin(beabi_helper_env_t *env);
/**
* Create return node and finishes epilog handling
*/
ir_node *be_epilog_create_return(beabi_helper_env_t *env, dbg_info *dbgi,
ir_node *block);
/**
* Adds a X->Proj->Keep for each output value of X which has no Proj yet
*/
......
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