Commit 59738a68 authored by Manuel Mohr's avatar Manuel Mohr
Browse files

sparc: Fix Alloc nodes.

parent 8597cc9f
......@@ -478,7 +478,9 @@ static void sparc_lower_for_target(void)
ir_graph *irg = get_irp_irg(i);
ir_lower_mode_b(irg, mode_Iu);
lower_switch(irg, 4, 256, false);
lower_alloc(irg, SPARC_STACK_ALIGNMENT, false, SPARC_MIN_STACKSIZE);
/* TODO: Pass SPARC_MIN_STACKSIZE as addr_delta as soon as
* Alloc nodes are implemented more efficiently. */
lower_alloc(irg, SPARC_STACK_ALIGNMENT, true, 0);
}
}
......
......@@ -370,7 +370,8 @@ static bool emits_multiple_instructions(const ir_node *node)
return is_sparc_SMulh(node) || is_sparc_UMulh(node)
|| is_sparc_SDiv(node) || is_sparc_UDiv(node)
|| be_is_MemPerm(node) || be_is_Perm(node);
|| be_is_MemPerm(node) || be_is_Perm(node)
|| is_sparc_SubSP(node);
}
static bool uses_reg(const ir_node *node, const arch_register_t *reg)
......@@ -503,6 +504,28 @@ static void emit_be_IncSP(const ir_node *irn)
be_emit_finish_line_gas(irn);
}
/**
* Emits code for stack space management.
*/
static void emit_sparc_SubSP(const ir_node *irn)
{
sparc_emit_indent();
be_emit_cstring("sub ");
sparc_emit_source_register(irn, 0);
be_emit_cstring(", ");
sparc_emit_reg_or_imm(irn, 1);
be_emit_cstring(", ");
sparc_emit_dest_register(irn, 0);
be_emit_finish_line_gas(irn);
sparc_emit_indent();
be_emit_cstring("add ");
sparc_emit_source_register(irn, 0);
be_emit_irprintf(", %u, ", SPARC_MIN_STACKSIZE);
sparc_emit_dest_register(irn, 1);
be_emit_finish_line_gas(irn);
}
/**
* emits code for mulh
*/
......@@ -1230,6 +1253,7 @@ static void sparc_register_emitters(void)
set_emitter(op_sparc_fbfcc, emit_sparc_fbfcc);
set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr);
set_emitter(op_sparc_SMulh, emit_sparc_Mulh);
set_emitter(op_sparc_SubSP, emit_sparc_SubSP);
set_emitter(op_sparc_UMulh, emit_sparc_Mulh);
set_emitter(op_sparc_Restore, emit_sparc_Restore);
set_emitter(op_sparc_Return, emit_sparc_Return);
......
......@@ -447,11 +447,19 @@ RestoreZero => {
},
SubSP => {
reg_req => { in => [ "sp", "gp" ], out => [ "sp:I|S" ] },
ins => [ "stack", "size" ],
outs => [ "stack" ],
emit => ". sub %S0, %S1, %D0\n",
mode => $mode_gp,
constructors => {
imm => {
attr => "ir_entity *immediate_entity, int32_t immediate_value",
custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
reg_req => { in => [ "sp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
ins => [ "stack", "mem" ],
},
reg => {
reg_req => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
ins => [ "stack", "size", "mem" ],
}
},
outs => [ "stack", "addr", "M" ],
},
AddSP => {
......
......@@ -65,6 +65,14 @@ static void process_bias(ir_node *block, bool sp_relative, int bias,
arch_set_frame_offset(irn, offset);
}
/* The additional alignment bytes cannot be used
* anymore after alloca. */
if (is_sparc_SubSP(irn)) {
free_bytes = 0;
} else if (is_sparc_AddSP(irn)) {
assert(free_bytes == 0);
}
irn_bias = arch_get_sp_bias(irn);
if (irn_bias == 0) {
/* do nothing */
......
......@@ -2022,7 +2022,10 @@ static ir_node *gen_Alloc(ir_node *node)
ir_type *type = get_Alloc_type(node);
ir_node *size = get_Alloc_count(node);
ir_node *stack_pred = get_stack_pointer_for(node);
ir_node *mem = get_Alloc_mem(node);
ir_node *new_mem = be_transform_node(mem);
ir_node *subsp;
if (get_Alloc_where(node) != stack_alloc)
panic("only stack-alloc supported in sparc backend (at %+F)", node);
/* lowerer should have transformed all allocas to byte size */
......@@ -2032,37 +2035,38 @@ static ir_node *gen_Alloc(ir_node *node)
if (is_Const(size)) {
ir_tarval *tv = get_Const_tarval(size);
long sizel = get_tarval_long(tv);
subsp = be_new_IncSP(sp_reg, new_block, stack_pred, sizel, 0);
set_irn_dbg_info(subsp, dbgi);
assert((sizel & (SPARC_STACK_ALIGNMENT - 1)) == 0 && "Found Alloc with misaligned constant");
subsp = new_bd_sparc_SubSP_imm(dbgi, new_block, stack_pred, new_mem, NULL, sizel);
} else {
ir_node *new_size = be_transform_node(size);
subsp = new_bd_sparc_SubSP(dbgi, new_block, stack_pred, new_size);
arch_set_irn_register(subsp, sp_reg);
subsp = new_bd_sparc_SubSP_reg(dbgi, new_block, stack_pred, new_size, new_mem);
}
/* if we are the last IncSP producer in a block then we have to keep
* the stack value.
* Note: This here keeps all producers which is more than necessary */
keep_alive(subsp);
ir_node *stack_proj = new_r_Proj(subsp, mode_gp, pn_sparc_SubSP_stack);
arch_set_irn_register(stack_proj, sp_reg);
/* If we are the last stack producer in a block, we have to keep the
* stack value. This keeps all producers, which is more than necessary. */
keep_alive(stack_proj);
pmap_insert(node_to_stack, node, subsp);
/* the "result" is the unmodified sp value */
return stack_pred;
pmap_insert(node_to_stack, node, stack_proj);
return subsp;
}
static ir_node *gen_Proj_Alloc(ir_node *node)
{
ir_node *alloc = get_Proj_pred(node);
long pn = get_Proj_proj(node);
ir_node *alloc = get_Proj_pred(node);
ir_node *new_alloc = be_transform_node(alloc);
long pn = get_Proj_proj(node);
switch ((pn_Alloc)pn) {
case pn_Alloc_M: {
ir_node *alloc_mem = get_Alloc_mem(alloc);
return be_transform_node(alloc_mem);
}
case pn_Alloc_M:
return new_r_Proj(new_alloc, mode_M, pn_sparc_SubSP_M);
case pn_Alloc_res: {
ir_node *new_alloc = be_transform_node(alloc);
return new_alloc;
ir_node *addr_proj = new_r_Proj(new_alloc, mode_gp, pn_sparc_SubSP_addr);
arch_set_irn_register(addr_proj, arch_get_irn_register(node));
return addr_proj;
}
case pn_Alloc_X_regular:
case pn_Alloc_X_except:
......
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