Commit 5c34afb8 authored by Matthias Braun's avatar Matthias Braun
Browse files

sparc: support va_start

parent 38929082
......@@ -669,10 +669,9 @@ void be_free_stackorder(be_stackorder_t *env)
free(env);
}
void be_add_parameter_entity_stores(ir_graph *irg)
static void create_stores_for_type(ir_graph *irg, ir_type *type)
{
ir_type *frame_type = get_irg_frame_type(irg);
size_t n = get_compound_n_members(frame_type);
size_t n = get_compound_n_members(type);
ir_node *frame = get_irg_frame(irg);
ir_node *initial_mem = get_irg_initial_mem(irg);
ir_node *mem = initial_mem;
......@@ -684,7 +683,7 @@ void be_add_parameter_entity_stores(ir_graph *irg)
/* all parameter entities left in the frame type require stores.
* (The ones passed on the stack have been moved to the arg type) */
for (i = 0; i < n; ++i) {
ir_entity *entity = get_compound_member(frame_type, i);
ir_entity *entity = get_compound_member(type, i);
ir_node *addr;
size_t arg;
if (!is_parameter_entity(entity))
......@@ -727,3 +726,15 @@ void be_add_parameter_entity_stores(ir_graph *irg)
set_Store_mem(first_store, initial_mem);
}
}
void be_add_parameter_entity_stores(ir_graph *irg)
{
ir_type *frame_type = get_irg_frame_type(irg);
be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
ir_type *between_type = layout->between_type;
create_stores_for_type(irg, frame_type);
if (between_type != NULL) {
create_stores_for_type(irg, between_type);
}
}
......@@ -78,6 +78,8 @@ extern const arch_irn_ops_t sparc_irn_ops;
#define SPARC_IMMEDIATE_MAX 4095
#define SPARC_MIN_STACKSIZE 92
#define SPARC_AGGREGATE_RETURN_OFFSET 64
#define SPARC_PARAMS_SPILL_OFFSET 68
#define SPARC_N_PARAM_REGS 6
static inline bool sparc_is_value_imm_encodeable(int32_t value)
{
......@@ -90,6 +92,7 @@ void sparc_introduce_prolog_epilog(ir_graph *irg);
void sparc_lower_64bit(void);
bool sparc_variadic_fixups(ir_graph *irg, calling_convention_t *cconv);
void sparc_create_stacklayout(ir_graph *irg, calling_convention_t *cconv);
void sparc_fix_stack_bias(ir_graph *irg);
......
......@@ -60,6 +60,7 @@ static const arch_register_t* const param_regs[] = {
&sparc_registers[REG_I4],
&sparc_registers[REG_I5],
};
COMPILETIME_ASSERT(ARRAY_SIZE(param_regs) == SPARC_N_PARAM_REGS, sparcparamregs)
static const arch_register_t* const float_result_regs[] = {
&sparc_registers[REG_F0],
......@@ -323,7 +324,6 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
struct obstack *obst = &birg->obst;
size_t r;
assert(birg->allocatable_regs == NULL);
birg->allocatable_regs = rbitset_obstack_alloc(obst, N_SPARC_REGISTERS);
rbitset_set_all(birg->allocatable_regs, N_SPARC_REGISTERS);
for (r = 0; r < n_ignores; ++r) {
......
......@@ -48,7 +48,8 @@ static void set_irn_sp_bias(ir_node *node, int new_bias)
}
}
static void process_bias(ir_node *block, bool sp_relative, int bias, int free_bytes)
static void process_bias(ir_node *block, bool sp_relative, int bias,
int free_bytes)
{
const ir_edge_t *edge;
ir_node *irn;
......@@ -114,12 +115,59 @@ static void adjust_entity_offsets(ir_type *type, long offset)
}
}
static ir_type *compute_arg_type(ir_graph *irg, calling_convention_t *cconv)
bool sparc_variadic_fixups(ir_graph *irg, calling_convention_t *cconv)
{
ir_entity *entity = get_irg_entity(irg);
ir_type *mtp = get_entity_type(entity);
size_t n_params = get_method_n_params(mtp);
ir_entity **param_map = ALLOCANZ(ir_entity*, n_params);
ir_entity *entity = get_irg_entity(irg);
ir_type *mtp = get_entity_type(entity);
if (get_method_variadicity(mtp) != variadicity_variadic)
return false;
if (cconv->n_param_regs >= SPARC_N_PARAM_REGS)
return false;
{
size_t n_params = get_method_n_params(mtp);
type_dbg_info *dbgi = get_type_dbg_info(mtp);
size_t n_ress = get_method_n_ress(mtp);
size_t new_n_params
= n_params + (SPARC_N_PARAM_REGS - cconv->n_param_regs);
ir_type *new_mtp = new_d_type_method(new_n_params, n_ress, dbgi);
ir_mode *gp_reg_mode = sparc_reg_classes[CLASS_sparc_gp].mode;
ir_type *gp_reg_type = get_type_for_mode(gp_reg_mode);
ir_type *frame_type = get_irg_frame_type(irg);
size_t i;
for (i = 0; i < n_ress; ++i) {
ir_type *type = get_method_res_type(mtp, i);
set_method_res_type(new_mtp, i, type);
}
for (i = 0; i < n_params; ++i) {
ir_type *type = get_method_param_type(mtp, i);
set_method_param_type(new_mtp, i, type);
}
for ( ; i < new_n_params; ++i) {
set_method_param_type(new_mtp, i, gp_reg_type);
new_parameter_entity(frame_type, i, gp_reg_type);
}
set_method_variadicity(new_mtp, get_method_variadicity(mtp));
set_method_calling_convention(new_mtp, get_method_calling_convention(mtp));
set_method_additional_properties(new_mtp, get_method_additional_properties(mtp));
set_lowered_type(mtp, new_mtp);
set_entity_type(entity, new_mtp);
}
return true;
}
static ir_type *compute_arg_type(ir_graph *irg, calling_convention_t *cconv,
ir_type *between_type)
{
ir_entity *va_start_entity = NULL;
const ir_entity *entity = get_irg_entity(irg);
const ir_type *mtp = get_entity_type(entity);
size_t n_params = get_method_n_params(mtp);
ir_entity **param_map = ALLOCANZ(ir_entity*, n_params);
ir_type *frame_type = get_irg_frame_type(irg);
size_t n_frame_members = get_compound_n_members(frame_type);
......@@ -132,36 +180,65 @@ static ir_type *compute_arg_type(ir_graph *irg, calling_convention_t *cconv)
for (f = n_frame_members; f > 0; ) {
ir_entity *member = get_compound_member(frame_type, --f);
size_t num;
const reg_or_stackslot_t *param;
if (!is_parameter_entity(member))
continue;
num = get_entity_parameter_number(member);
if (num == IR_VA_START_PARAMETER_NUMBER) {
if (va_start_entity != NULL)
panic("multiple va_start entities found (%+F,%+F)",
va_start_entity, member);
va_start_entity = member;
continue;
}
assert(num < n_params);
if (param_map[num] != NULL)
panic("multiple entities for parameter %u in %+F found", f, irg);
param = &cconv->parameters[num];
if (param->reg0 != NULL)
continue;
param_map[num] = member;
/* move to new arg_type */
set_entity_owner(member, res);
}
/* calculate offsets/create missing entities */
for (i = 0; i < n_params; ++i) {
reg_or_stackslot_t *param = &cconv->parameters[i];
ir_entity *entity;
if (param->reg0 != NULL)
reg_or_stackslot_t *param = &cconv->parameters[i];
ir_entity *entity = param_map[i];
if (param->reg0 != NULL) {
/* use reserved spill space on between type */
if (entity != NULL) {
long offset = SPARC_PARAMS_SPILL_OFFSET + i*4;
assert(i < SPARC_N_PARAM_REGS);
set_entity_owner(entity, between_type);
set_entity_offset(entity, offset);
}
continue;
entity = param_map[i];
}
if (entity == NULL)
entity = new_parameter_entity(res, i, param->type);
param->entity = entity;
set_entity_offset(entity, param->offset);
}
if (va_start_entity != NULL) {
/* sparc_variadic_fixups() fiddled with our type, find out the
* original number of parameters */
ir_type *non_lowered = get_associated_type(mtp);
size_t orig_n_params = get_method_n_params(non_lowered);
long offset;
assert(get_method_variadicity(mtp) == variadicity_variadic);
if (orig_n_params < n_params) {
assert(param_map[orig_n_params] != NULL);
offset = get_entity_offset(param_map[orig_n_params]);
set_entity_owner(va_start_entity, between_type);
set_entity_offset(va_start_entity, offset);
} else {
set_entity_owner(va_start_entity, res);
set_entity_offset(va_start_entity, cconv->param_stack_size);
}
}
set_type_size_bytes(res, cconv->param_stack_size);
return res;
......@@ -178,7 +255,7 @@ void sparc_create_stacklayout(ir_graph *irg, calling_convention_t *cconv)
layout->frame_type = get_irg_frame_type(irg);
layout->between_type = between_type;
layout->arg_type = compute_arg_type(irg, cconv);
layout->arg_type = compute_arg_type(irg, cconv, between_type);
layout->initial_offset = 0;
layout->initial_bias = 0;
layout->sp_relative = cconv->omit_fp;
......@@ -228,7 +305,7 @@ static void process_frame_types(ir_graph *irg)
void sparc_fix_stack_bias(ir_graph *irg)
{
ir_node *start_block = get_irg_start_block(irg);
ir_node *start_block = get_irg_start_block(irg);
process_frame_types(irg);
......
......@@ -2061,16 +2061,13 @@ static ir_node *gen_Proj_Start(ir_node *node)
static ir_node *gen_Proj_Proj_Start(ir_node *node)
{
long pn = get_Proj_proj(node);
ir_node *block = get_nodes_block(node);
ir_graph *irg = get_irn_irg(node);
ir_node *new_block = be_transform_node(block);
ir_entity *entity = get_irg_entity(irg);
ir_type *method_type = get_entity_type(entity);
ir_type *param_type = get_method_param_type(method_type, pn);
ir_node *args = get_Proj_pred(node);
ir_node *start = get_Proj_pred(args);
ir_node *new_start = be_transform_node(start);
long pn = get_Proj_proj(node);
ir_node *block = get_nodes_block(node);
ir_graph *irg = get_irn_irg(node);
ir_node *new_block = be_transform_node(block);
ir_node *args = get_Proj_pred(node);
ir_node *start = get_Proj_pred(args);
ir_node *new_start = be_transform_node(start);
const reg_or_stackslot_t *param;
/* Proj->Proj->Start must be a method argument */
......@@ -2080,22 +2077,32 @@ static ir_node *gen_Proj_Proj_Start(ir_node *node)
if (param->reg0 != NULL) {
/* argument transmitted in register */
ir_mode *mode = get_type_mode(param_type);
const arch_register_t *reg = param->reg0;
ir_mode *reg_mode = reg->reg_class->mode;
long pn = param->reg_offset + start_params_offset;
ir_node *value = new_r_Proj(new_start, reg_mode, pn);
long new_pn = param->reg_offset + start_params_offset;
ir_node *value = new_r_Proj(new_start, reg_mode, new_pn);
bool is_float = false;
{
ir_entity *entity = get_irg_entity(irg);
ir_type *method_type = get_entity_type(entity);
if (pn < (long)get_method_n_params(method_type)) {
ir_type *param_type = get_method_param_type(method_type, pn);
ir_mode *mode = get_type_mode(param_type);
is_float = mode_is_float(mode);
}
}
if (mode_is_float(mode)) {
if (is_float) {
const arch_register_t *reg1 = param->reg1;
ir_node *value1 = NULL;
if (reg1 != NULL) {
ir_mode *reg1_mode = reg1->reg_class->mode;
value1 = new_r_Proj(new_start, reg1_mode, pn+1);
value1 = new_r_Proj(new_start, reg1_mode, new_pn+1);
} else if (param->entity != NULL) {
ir_node *fp = get_initial_fp(irg);
ir_node *mem = get_initial_mem(irg);
ir_node *fp = get_initial_fp(irg);
ir_node *mem = get_initial_mem(irg);
ir_node *ld = new_bd_sparc_Ld_imm(NULL, new_block, fp, mem,
mode_gp, param->entity,
0, true);
......@@ -2108,11 +2115,11 @@ static ir_node *gen_Proj_Proj_Start(ir_node *node)
return value;
} else {
/* argument transmitted on stack */
ir_node *mem = get_initial_mem(irg);
ir_mode *mode = get_type_mode(param->type);
ir_node *base = get_frame_base(irg);
ir_node *load;
ir_node *value;
ir_node *mem = get_initial_mem(irg);
ir_mode *mode = get_type_mode(param->type);
ir_node *base = get_frame_base(irg);
ir_node *load;
ir_node *value;
if (mode_is_float(mode)) {
load = create_ldf(NULL, new_block, base, mem, mode,
......@@ -2290,6 +2297,11 @@ void sparc_transform_graph(ir_graph *irg)
stackorder = be_collect_stacknodes(irg);
current_cconv
= sparc_decide_calling_convention(get_entity_type(entity), irg);
if (sparc_variadic_fixups(irg, current_cconv)) {
sparc_free_calling_convention(current_cconv);
current_cconv
= sparc_decide_calling_convention(get_entity_type(entity), irg);
}
sparc_create_stacklayout(irg, current_cconv);
be_add_parameter_entity_stores(irg);
......
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