Commit a18ed4e9 authored by Tobias Rapp's avatar Tobias Rapp
Browse files

amd64: Added no-omit frame pointer mode

parent 5a011af7
...@@ -93,6 +93,16 @@ PushAM => { ...@@ -93,6 +93,16 @@ PushAM => {
emit => "push%M %A", emit => "push%M %A",
}, },
PushRbp => {
op_flags => [ "uses_memory" ],
state => "exc_pinned",
reg_req => { in => [ "rsp" ], out => [ "rsp:I|S" ] },
ins => [ "stack" ],
outs => [ "stack" ],
fixed => "amd64_op_mode_t op_mode = AMD64_OP_NONE;\n",
emit => "pushq %%rbp",
},
PopAM => { PopAM => {
op_flags => [ "uses_memory" ], op_flags => [ "uses_memory" ],
state => "exc_pinned", state => "exc_pinned",
...@@ -105,6 +115,15 @@ PopAM => { ...@@ -105,6 +115,15 @@ PopAM => {
emit => "pop%M %A", emit => "pop%M %A",
}, },
Leave => {
op_flags => [ "uses_memory" ],
state => "exc_pinned",
reg_req => { in => [ "rbp" ], out => [ "rbp:I", "rbp:I|S" ] },
outs => [ "frame", "stack" ],
fixed => "amd64_op_mode_t op_mode = AMD64_OP_NONE;\n",
emit => "leave",
},
Add => { Add => {
irn_flags => [ "rematerializable" ], irn_flags => [ "rematerializable" ],
state => "exc_pinned", state => "exc_pinned",
......
...@@ -2057,17 +2057,23 @@ static void amd64_register_transformers(void) ...@@ -2057,17 +2057,23 @@ static void amd64_register_transformers(void)
be_set_upper_bits_clean_function(op_Shrs, NULL); be_set_upper_bits_clean_function(op_Shrs, NULL);
} }
static ir_type *amd64_get_between_type(void) static ir_type *amd64_get_between_type(bool omit_fp)
{ {
static ir_type *between_type = NULL; static ir_type *between_type = NULL;
static ir_type *omit_fp_between_type = NULL;
assert(current_cconv->omit_fp);
if (between_type == NULL) { if (between_type == NULL) {
between_type = new_type_class(new_id_from_str("amd64_between_type")); between_type = new_type_class(new_id_from_str("amd64_between_type"));
set_type_size_bytes(between_type, get_mode_size_bytes(mode_gp)); /* between type contains return address + saved base pointer */
set_type_size_bytes(between_type, 2*get_mode_size_bytes(mode_gp));
omit_fp_between_type
= new_type_class(new_id_from_str("amd64_between_type"));
/* between type contains return address */
set_type_size_bytes(omit_fp_between_type, get_mode_size_bytes(mode_gp));
} }
return between_type; return omit_fp ? omit_fp_between_type : between_type;
} }
static void amd64_create_stacklayout(ir_graph *irg, amd64_cconv_t *cconv) static void amd64_create_stacklayout(ir_graph *irg, amd64_cconv_t *cconv)
...@@ -2096,7 +2102,7 @@ static void amd64_create_stacklayout(ir_graph *irg, amd64_cconv_t *cconv) ...@@ -2096,7 +2102,7 @@ static void amd64_create_stacklayout(ir_graph *irg, amd64_cconv_t *cconv)
memset(layout, 0, sizeof(*layout)); memset(layout, 0, sizeof(*layout));
layout->frame_type = get_irg_frame_type(irg); layout->frame_type = get_irg_frame_type(irg);
layout->between_type = amd64_get_between_type(); layout->between_type = amd64_get_between_type(cconv->omit_fp);
layout->arg_type = arg_type; layout->arg_type = arg_type;
layout->initial_offset = 0; layout->initial_offset = 0;
layout->initial_bias = 0; layout->initial_bias = 0;
......
...@@ -96,21 +96,19 @@ static void amd64_set_frame_offset(ir_node *node, int offset) ...@@ -96,21 +96,19 @@ static void amd64_set_frame_offset(ir_node *node, int offset)
static int amd64_get_sp_bias(const ir_node *node) static int amd64_get_sp_bias(const ir_node *node)
{ {
if (is_amd64_Start(node)) { if (is_amd64_PushAM(node)) {
ir_graph *irg = get_irn_irg(node);
ir_type *frame_type = get_irg_frame_type(irg);
return get_type_size_bytes(frame_type);
} else if (is_amd64_Return(node)) {
ir_graph *irg = get_irn_irg(node);
ir_type *frame_type = get_irg_frame_type(irg);
return -(int)get_type_size_bytes(frame_type);
} else if (is_amd64_PushAM(node)) {
const amd64_addr_attr_t *attr = get_amd64_addr_attr_const(node); const amd64_addr_attr_t *attr = get_amd64_addr_attr_const(node);
return get_insn_mode_bytes(attr->insn_mode); return get_insn_mode_bytes(attr->insn_mode);
} else if (is_amd64_PushRbp(node)) {
/* 64-bit register size */
return 8;
} else if (is_amd64_PopAM(node)) { } else if (is_amd64_PopAM(node)) {
const amd64_addr_attr_t *attr = get_amd64_addr_attr_const(node); const amd64_addr_attr_t *attr = get_amd64_addr_attr_const(node);
return -get_insn_mode_bytes(attr->insn_mode); return -get_insn_mode_bytes(attr->insn_mode);
} else if (is_amd64_Leave(node)) {
return SP_BIAS_RESET;
} }
return 0; return 0;
} }
...@@ -167,7 +165,7 @@ static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp, ...@@ -167,7 +165,7 @@ static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp,
amd64_addr_t addr; amd64_addr_t addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.base_input = 0; addr.base_input = 1;
addr.index_input = NO_INPUT; addr.index_input = NO_INPUT;
addr.immediate.entity = ent; addr.immediate.entity = ent;
ir_node *in[] = { sp, frame, mem }; ir_node *in[] = { sp, frame, mem };
...@@ -187,7 +185,7 @@ static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_e ...@@ -187,7 +185,7 @@ static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_e
amd64_addr_t addr; amd64_addr_t addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.base_input = 0; addr.base_input = 1;
addr.index_input = NO_INPUT; addr.index_input = NO_INPUT;
addr.immediate.entity = ent; addr.immediate.entity = ent;
ir_node *in[] = { sp, frame, get_irg_no_mem(irg) }; ir_node *in[] = { sp, frame, get_irg_no_mem(irg) };
...@@ -327,9 +325,20 @@ static void amd64_collect_frame_entity_nodes(ir_node *node, void *data) ...@@ -327,9 +325,20 @@ static void amd64_collect_frame_entity_nodes(ir_node *node, void *data)
} }
} }
static int determine_rbp_input(ir_node *ret)
{
const arch_register_t *bp = &amd64_registers[REG_RSP];
foreach_irn_in(ret, i, input) {
if (arch_get_irn_register(input) == bp)
return i;
}
panic("no rbp input found at %+F", ret);
}
static void introduce_epilogue(ir_node *ret) static void introduce_epilogue(ir_node *ret)
{ {
const arch_register_t *sp = &amd64_registers[REG_RSP]; const arch_register_t *sp = &amd64_registers[REG_RSP];
const arch_register_t *bp = &amd64_registers[REG_RBP];
ir_graph *irg = get_irn_irg(ret); ir_graph *irg = get_irn_irg(ret);
ir_node *start = get_irg_start(irg); ir_node *start = get_irg_start(irg);
ir_node *block = get_nodes_block(start); ir_node *block = get_nodes_block(start);
...@@ -338,9 +347,20 @@ static void introduce_epilogue(ir_node *ret) ...@@ -338,9 +347,20 @@ static void introduce_epilogue(ir_node *ret)
be_stack_layout_t *layout = be_get_irg_stack_layout(irg); be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
ir_node *first_sp = get_irn_n(ret, n_be_Return_sp); ir_node *first_sp = get_irn_n(ret, n_be_Return_sp);
ir_node *curr_sp = first_sp; ir_node *curr_sp = first_sp;
ir_mode *mode_gp = mode_Lu;
if(!layout->sp_relative) { if(!layout->sp_relative) {
assert(false); int n_rbp = determine_rbp_input(ret);
ir_node *curr_bp = get_irn_n(ret, n_rbp);
ir_node *leave = new_bd_amd64_Leave(NULL, block, curr_bp);
curr_bp = new_r_Proj(leave, mode_gp, pn_amd64_Leave_frame);
curr_sp = new_r_Proj(leave, mode_gp, pn_amd64_Leave_stack);
arch_set_irn_register(curr_bp, bp);
arch_set_irn_register(curr_sp, sp);
sched_add_before(ret, leave);
set_irn_n(ret, n_rbp, curr_bp);
} else { } else {
if (frame_size > 0) { if (frame_size > 0) {
ir_node *incsp = be_new_IncSP(sp, block, curr_sp, ir_node *incsp = be_new_IncSP(sp, block, curr_sp,
...@@ -350,20 +370,57 @@ static void introduce_epilogue(ir_node *ret) ...@@ -350,20 +370,57 @@ static void introduce_epilogue(ir_node *ret)
} }
} }
set_irn_n(ret, n_be_Return_sp, curr_sp); set_irn_n(ret, n_be_Return_sp, curr_sp);
/* keep verifier happy... */
if (get_irn_n_edges(first_sp) == 0 && is_Proj(first_sp)) {
kill_node(first_sp);
}
} }
static void introduce_prologue_epilogue(ir_graph *irg) static void introduce_prologue_epilogue(ir_graph *irg)
{ {
const arch_register_t *sp = &amd64_registers[REG_RSP]; const arch_register_t *sp = &amd64_registers[REG_RSP];
const arch_register_t *bp = &amd64_registers[REG_RBP];
ir_node *start = get_irg_start(irg); ir_node *start = get_irg_start(irg);
ir_node *block = get_nodes_block(start); ir_node *block = get_nodes_block(start);
ir_type *frame_type = get_irg_frame_type(irg); ir_type *frame_type = get_irg_frame_type(irg);
unsigned frame_size = get_type_size_bytes(frame_type); unsigned frame_size = get_type_size_bytes(frame_type);
be_stack_layout_t *layout = be_get_irg_stack_layout(irg); be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
ir_node *initial_sp = be_get_initial_reg_value(irg, sp); ir_node *initial_sp = be_get_initial_reg_value(irg, sp);
ir_mode *mode_gp = mode_Lu;
if (is_Deleted(start))
return;
if (!layout->sp_relative) { if (!layout->sp_relative) {
assert(false); /* push rbp */
ir_node *push = new_bd_amd64_PushRbp(NULL, block, initial_sp);
ir_node *curr_sp = new_r_Proj(push, mode_gp, pn_amd64_PushRbp_stack);
arch_set_irn_register(curr_sp, sp);
sched_add_after(start, push);
/* move rsp to rbp */
ir_node *const curr_bp = be_new_Copy(block, curr_sp);
sched_add_after(push, curr_bp);
be_set_constr_single_reg_out(curr_bp, 0,
bp, arch_register_req_type_ignore);
curr_sp = be_new_CopyKeep_single(block, curr_sp, curr_bp);
sched_add_after(curr_bp, curr_sp);
be_set_constr_single_reg_out(curr_sp, 0,
sp, arch_register_req_type_produces_sp);
ir_node *incsp = be_new_IncSP(sp, block, curr_sp, frame_size, 0);
sched_add_after(curr_sp, incsp);
/* make sure the initial IncSP is really used by someone */
if (get_irn_n_edges(incsp) <= 1) {
ir_node *in[] = { incsp };
ir_node *keep = be_new_Keep(block, 1, in);
sched_add_after(incsp, keep);
}
layout->initial_bias = -8;
} else { } else {
if (frame_size > 0) { if (frame_size > 0) {
ir_node *const incsp = be_new_IncSP(sp, block, initial_sp, ir_node *const incsp = be_new_IncSP(sp, block, initial_sp,
...@@ -395,12 +452,12 @@ static void amd64_finish_graph(ir_graph *irg) ...@@ -395,12 +452,12 @@ static void amd64_finish_graph(ir_graph *irg)
irg_block_walk_graph(irg, NULL, amd64_after_ra_walker, NULL); irg_block_walk_graph(irg, NULL, amd64_after_ra_walker, NULL);
introduce_prologue_epilogue(irg);
/* fix stack entity offsets */ /* fix stack entity offsets */
be_abi_fix_stack_nodes(irg); be_abi_fix_stack_nodes(irg);
be_abi_fix_stack_bias(irg); be_abi_fix_stack_bias(irg);
introduce_prologue_epilogue(irg);
/* Fix 2-address code constraints. */ /* Fix 2-address code constraints. */
amd64_finish_irg(irg); amd64_finish_irg(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