Commit 4161365d authored by Andreas Fried's avatar Andreas Fried Committed by Christoph Mallon
Browse files

Implement variadic functions in the SPARC backend.

parent f833aa25
......@@ -17,6 +17,7 @@
#include "bera.h"
#include "besched.h"
#include "betranshlp.h"
#include "bevarargs.h"
#include "debug.h"
#include "gen_sparc_regalloc_if.h"
#include "irarch_t.h"
......@@ -480,6 +481,7 @@ static void sparc_lower_for_target(void)
supported[s++] = ir_bk_saturating_increment;
if (sparc_cg_config.use_cas)
supported[s++] = ir_bk_compare_swap;
supported[s++] = ir_bk_va_start;
assert(s < ARRAY_SIZE(supported));
lower_builtins(s, supported);
be_after_irp_transform("lower-builtins");
......@@ -536,8 +538,8 @@ static const backend_params *sparc_get_backend_params(void)
.stack_param_align = 4,
.float_int_overflow = ir_overflow_min_max,
.vararg = {
.va_list_type = NULL,
.lower_va_arg = NULL,
.va_list_type = NULL, /* will be set later */
.lower_va_arg = be_default_lower_va_arg,
},
};
......@@ -548,9 +550,12 @@ static const backend_params *sparc_get_backend_params(void)
= new_int_mode("unsigned long long", irma_twos_complement, 64, 0, 64);
ir_type *type_unsigned_long_long
= new_type_primitive(mode_unsigned_long_long);
ir_type *type_va_list
= new_type_pointer(new_type_primitive(mode_ANY));
p.type_long_long = type_long_long;
p.type_unsigned_long_long = type_unsigned_long_long;
p.vararg.va_list_type = type_va_list;
sparc_mode_Q
= new_float_mode("Q", irma_ieee754, 15, 112, ir_overflow_min_max);
......
......@@ -66,6 +66,7 @@ bool sparc_variadic_fixups(ir_graph *irg, calling_convention_t *cconv);
void sparc_create_stacklayout(ir_graph *irg, calling_convention_t *cconv);
void sparc_adjust_stack_entity_offsets(ir_graph *irg);
void sparc_fix_stack_bias(ir_graph *irg);
ir_entity *sparc_get_va_start_entity(void);
ir_entity *sparc_get_frame_entity(const ir_node *node);
......
......@@ -20,6 +20,8 @@
#include "besched.h"
#include "bestack.h"
static ir_entity *va_start_entity;
static void sparc_set_frame_offset(ir_node *node, int offset)
{
if (be_is_MemPerm(node)) {
......@@ -206,7 +208,6 @@ bool sparc_variadic_fixups(ir_graph *irg, calling_convention_t *cconv)
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);
size_t n_params = cconv->n_parameters;
ir_entity **param_map = ALLOCANZ(ir_entity*, n_params);
......@@ -223,13 +224,6 @@ static ir_type *compute_arg_type(ir_graph *irg, calling_convention_t *cconv,
continue;
size_t 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);
......@@ -261,10 +255,13 @@ static ir_type *compute_arg_type(ir_graph *irg, calling_convention_t *cconv,
set_entity_offset(entity, param->offset);
}
if (va_start_entity != NULL) {
ir_type *const mtp = get_entity_type(entity);
if (is_method_variadic(mtp)) {
ir_type *unknown = get_unknown_type();
va_start_entity = new_parameter_entity(res, IR_VA_START_PARAMETER_NUMBER, unknown);
/* sparc_variadic_fixups() fiddled with our type, find out the
* original number of parameters */
ir_type const *const mtp = get_entity_type(entity);
ir_type *const non_lowered = get_higher_type(mtp);
size_t const orig_n_params = get_method_n_params(non_lowered);
assert(is_method_variadic(mtp));
......@@ -278,12 +275,20 @@ static ir_type *compute_arg_type(ir_graph *irg, calling_convention_t *cconv,
set_entity_owner(va_start_entity, res);
set_entity_offset(va_start_entity, cconv->param_stack_size);
}
} else {
va_start_entity = NULL;
}
set_type_size_bytes(res, cconv->param_stack_size);
return res;
}
ir_entity *sparc_get_va_start_entity(void)
{
return va_start_entity;
}
void sparc_create_stacklayout(ir_graph *irg, calling_convention_t *cconv)
{
be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
......
......@@ -50,6 +50,7 @@ static ir_mode *mode_fp2;
//static ir_mode *mode_fp4;
static pmap *node_to_stack;
static ir_node *frame_base;
static ir_node *initial_va_list;
static const arch_register_t *const omit_fp_callee_saves[] = {
&sparc_registers[REG_L0],
......@@ -2069,6 +2070,34 @@ static ir_node *gen_compare_swap(ir_node *node)
return cas;
}
static ir_node *get_frame_base(ir_graph *irg)
{
if (frame_base == NULL) {
if (current_cconv->omit_fp) {
frame_base = get_initial_sp(irg);
} else {
frame_base = get_initial_fp(irg);
}
}
return frame_base;
}
static ir_node *gen_va_start(ir_node *node)
{
if (initial_va_list == NULL) {
dbg_info *dbgi = get_irn_dbg_info(node);
ir_graph *irg = get_irn_irg(node);
ir_node *block = get_irg_start_block(irg);
ir_entity *entity = sparc_get_va_start_entity();
ir_node *frame = get_frame_base(irg);
ir_node *ap = new_bd_sparc_FrameAddr(dbgi, block, frame, entity, 0);
initial_va_list = ap;
}
return initial_va_list;
}
/**
* Transform Builtin node.
*/
......@@ -2098,8 +2127,9 @@ static ir_node *gen_Builtin(ir_node *node)
return gen_compare_swap(node);
case ir_bk_saturating_increment:
return gen_saturating_increment(node);
case ir_bk_may_alias:
case ir_bk_va_start:
return gen_va_start(node);
case ir_bk_may_alias:
case ir_bk_va_arg:
break;
}
......@@ -2142,8 +2172,14 @@ static ir_node *gen_Proj_Builtin(ir_node *proj)
assert(pn == pn_Builtin_max+1);
return be_new_Proj(new_pred, pn_sparc_Cas_res);
}
case ir_bk_may_alias:
case ir_bk_va_start:
if (pn == pn_Builtin_M) {
return be_transform_node(get_Builtin_mem(pred));
} else {
assert(pn == pn_Builtin_max+1);
return new_pred;
}
case ir_bk_may_alias:
case ir_bk_va_arg:
break;
}
......@@ -2275,18 +2311,6 @@ static ir_node *gen_Proj_Div(ir_node *node)
panic("unsupported Proj from Div");
}
static ir_node *get_frame_base(ir_graph *irg)
{
if (frame_base == NULL) {
if (current_cconv->omit_fp) {
frame_base = get_initial_sp(irg);
} else {
frame_base = get_initial_fp(irg);
}
}
return frame_base;
}
static ir_node *gen_Proj_Start(ir_node *node)
{
unsigned pn = get_Proj_num(node);
......@@ -2525,6 +2549,7 @@ void sparc_transform_graph(ir_graph *irg)
pmap_destroy(node_to_stack);
node_to_stack = NULL;
initial_va_list = NULL;
/* do code placement, to optimize the position of constants */
place_code(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