Commit 4ddbdba7 authored by Andreas Fried's avatar Andreas Fried
Browse files

amd64: Add support for returns_twice calls.

parent 0bfdbf76
......@@ -85,12 +85,8 @@ x86_cconv_t *amd64_decide_calling_convention(ir_type *function_type,
irg_walk_graph(irg, check_omit_fp, NULL, &omit_fp);
}
mtp_additional_properties mtp
= get_method_additional_properties(function_type);
unsigned *caller_saves = rbitset_malloc(N_AMD64_REGISTERS);
unsigned *callee_saves = rbitset_malloc(N_AMD64_REGISTERS);
if (mtp & mtp_property_returns_twice)
panic("amd64: returns_twice calling convention NIY");
rbitset_copy(caller_saves, default_caller_saves, N_AMD64_REGISTERS);
rbitset_copy(callee_saves, default_callee_saves, N_AMD64_REGISTERS);
......
......@@ -239,5 +239,15 @@ static int amd64_switch_jmp_attrs_equal(const ir_node *const a,
return amd64_attrs_equal(a, b) && attr_a->table == attr_b->table;
}
static int amd64_call_addr_attrs_equal(const ir_node *const a,
const ir_node *const b)
{
const amd64_call_addr_attr_t *const attr_a
= get_amd64_call_addr_attr_const(a);
const amd64_call_addr_attr_t *const attr_b
= get_amd64_call_addr_attr_const(b);
return amd64_addr_attrs_equal(a, b) && attr_a->call_tp == attr_b->call_tp;
}
/* Include the generated constructor functions */
#include "gen_amd64_new_nodes.c.inl"
......@@ -129,6 +129,19 @@ static inline amd64_movimm_attr_t *get_amd64_movimm_attr(ir_node *node)
return (amd64_movimm_attr_t*)get_irn_generic_attr(node);
}
static inline const amd64_call_addr_attr_t *get_amd64_call_addr_attr_const(
const ir_node *node)
{
assert(is_amd64_call(node));
return (const amd64_call_addr_attr_t*)get_irn_generic_attr_const(node);
}
static inline amd64_call_addr_attr_t *get_amd64_call_addr_attr (ir_node *node)
{
assert(is_amd64_call(node));
return (amd64_call_addr_attr_t*)get_irn_generic_attr(node);
}
/* Include the generated headers */
#include "gen_amd64_new_nodes.h"
......
......@@ -118,4 +118,9 @@ typedef struct {
ir_entity *table_entity;
} amd64_switch_jmp_attr_t;
typedef struct {
amd64_addr_attr_t base;
ir_type *call_tp;
} amd64_call_addr_attr_t;
#endif
......@@ -75,6 +75,9 @@ $mode_xmm = "amd64_mode_xmm";
amd64_shift_attr_t =>
"be_info_init_irn(res, irn_flags, in_reqs, n_res);\n"
."\t*attr = *attr_init;\n",
amd64_call_addr_attr_t =>
"be_info_init_irn(res, irn_flags, in_reqs, n_res);\n"
."\t*attr = *attr_init;",
);
my $binop = {
......@@ -444,9 +447,8 @@ call => {
in_reqs => "...",
out_reqs => "...",
outs => [ "M", "stack", "flags", "first_result" ],
attr_type => "amd64_addr_attr_t",
attr => "amd64_op_mode_t op_mode, amd64_addr_t addr",
fixed => "amd64_insn_mode_t insn_mode = INSN_MODE_64;\n",
attr_type => "amd64_call_addr_attr_t",
attr => "const amd64_call_addr_attr_t *attr_init",
emit => "call %*AM",
},
......
......@@ -1690,9 +1690,22 @@ static ir_node *gen_Call(ir_node *node)
unsigned const n_caller_saves = rbitset_popcount(cconv->caller_saves, N_AMD64_REGISTERS);
unsigned const out_arity = o + cconv->n_reg_results + n_caller_saves;
/* create call attributes */
amd64_call_addr_attr_t call_attr = {
.base = {
.base = {
.op_mode = op_mode,
},
.needs_frame_ent = false,
.insn_mode = INSN_MODE_64,
.addr = addr,
},
.call_tp = type,
};
/* create call node */
ir_node *call = new_bd_amd64_call(dbgi, new_block, in_arity, in, out_arity,
op_mode, addr);
&call_attr);
arch_set_irn_register_reqs_in(call, in_req);
fix_node_mem_proj(call, mem_proj);
......
......@@ -463,13 +463,26 @@ static bool is_frame_load(const ir_node *node)
*/
static void amd64_collect_frame_entity_nodes(ir_node *node, void *data)
{
be_fec_env_t *env = (be_fec_env_t*)data;
/* Disable coalescing for "returns twice" calls: In case of setjmp/longjmp
* our control flow graph isn't completely correct: There are no backedges
* from longjmp to the setjmp => coalescing would produce wrong results. */
if (is_amd64_call(node)) {
const amd64_call_addr_attr_t *attrs = get_amd64_call_addr_attr_const(node);
const ir_type *type = attrs->call_tp;
const mtp_additional_properties mtp
= get_method_additional_properties(type);
if (mtp & mtp_property_returns_twice)
be_forbid_coalescing(env);
}
/* we are only interested to report Load nodes */
if (!is_frame_load(node))
return;
const amd64_addr_attr_t *attr = get_amd64_addr_attr_const(node);
if (attr->needs_frame_ent) {
be_fec_env_t *env = (be_fec_env_t*)data;
/* TODO: improve this */
const ir_mode *mode = is_amd64_movdqu(node) ? amd64_mode_xmm
: mode_Lu;
......
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