summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJonas Haag <jonas@lophus.org>2016-03-02 11:36:13 +0100
committerPhilipp Serrer <philipp@serrer.de>2018-01-18 18:35:27 +0100
commit724a470def0621a29acda0895affad1fcd610674 (patch)
treed7860c697200cc6481fdfe461ed08bf5da6d62e3
parentb54b70b9602f8fbc7c18987d528064c78775e911 (diff)
Introduce new "needs_reloaded_callee_saves" attr
-rw-r--r--include/libfirm/irnode.h9
-rw-r--r--ir/be/amd64/amd64_transform.c42
-rw-r--r--ir/be/benode.c4
-rw-r--r--ir/be/betranshlp.c6
-rw-r--r--ir/ir/irnode.c15
-rw-r--r--ir/ir/irnode_t.h2
6 files changed, 61 insertions, 17 deletions
diff --git a/include/libfirm/irnode.h b/include/libfirm/irnode.h
index 615df9c..e42ad41 100644
--- a/include/libfirm/irnode.h
+++ b/include/libfirm/irnode.h
@@ -299,6 +299,15 @@ FIRM_API void ir_set_throws_exception(ir_node *node, int throws_exception);
/** Returns throws_exception attribute of a fragile node */
FIRM_API int ir_throws_exception(const ir_node *node);
+/**
+ * Sets needs reloaded callee saves attribute of a fragile node
+ * @p throws_exception must be 0 or 1
+ */
+FIRM_API void ir_set_needs_reloaded_callee_saves(ir_node *node, int needs_reloaded_callee_saves);
+
+/** Returns throws_exception attribute of a fragile node */
+FIRM_API int ir_needs_reloaded_callee_saves(const ir_node *node);
+
/** Returns the name of an ir_relation */
FIRM_API const char *get_relation_string(ir_relation relation);
diff --git a/ir/be/amd64/amd64_transform.c b/ir/be/amd64/amd64_transform.c
index a0b65e5..56c5d40 100644
--- a/ir/be/amd64/amd64_transform.c
+++ b/ir/be/amd64/amd64_transform.c
@@ -1684,6 +1684,23 @@ static ir_node *gen_Proj_Start(ir_node *const node)
panic("unexpected Start Proj: %u", pn);
}
+static void add_callee_saves(ir_graph *const irg, x86_cconv_t const *cconv,
+ ir_node **in, arch_register_req_t const **in_reqs)
+{
+ size_t pos = 0;
+ for (size_t i = 0; i < N_AMD64_REGISTERS; ++i) {
+ if (!rbitset_is_set(cconv->callee_saves, i))
+ continue;
+ arch_register_t const *const reg = &amd64_registers[i];
+ in[pos] = be_get_Start_proj(irg, reg);
+ in_reqs[pos] = reg->single_req;
+ ++pos;
+ }
+
+ size_t const n_callee_saves = rbitset_popcount(cconv->callee_saves, N_AMD64_REGISTERS);
+ assert(pos == n_callee_saves);
+}
+
static ir_node *gen_Return(ir_node *const node)
{
ir_graph *const irg = get_irn_irg(node);
@@ -1717,16 +1734,9 @@ static ir_node *gen_Return(ir_node *const node)
reqs[p] = slot->reg->single_req;
++p;
}
- /* callee saves */
- for (size_t i = 0; i < N_AMD64_REGISTERS; ++i) {
- if (!rbitset_is_set(cconv->callee_saves, i))
- continue;
- arch_register_t const *const reg = &amd64_registers[i];
- in[p] = be_get_Start_proj(irg, reg);
- reqs[p] = reg->single_req;
- ++p;
- }
- assert(p == n_ins);
+ assert(p == n_ins - n_callee_saves);
+
+ add_callee_saves(irg, cconv, &in[p], &reqs[p]);
ir_node *const ret = new_bd_amd64_ret(dbgi, new_block, n_ins, in, reqs);
be_stack_record_chain(&stack_env, ret, n_amd64_ret_stack, NULL);
@@ -1798,9 +1808,10 @@ static ir_node *gen_Call(ir_node *const node)
ir_graph *const irg = get_irn_irg(node);
x86_cconv_t *const cconv
= amd64_decide_calling_convention(type, NULL);
- size_t const n_param_regs = cconv->n_param_regs;
+ size_t const n_callee_saves = rbitset_popcount(cconv->callee_saves, N_AMD64_REGISTERS);
+ size_t const n_param_regs = cconv->n_param_regs;
/* param-regs + mem + stackpointer + callee(2) + n_sse_regs */
- unsigned const max_inputs = 5 + n_param_regs;
+ unsigned const max_inputs = 5 + n_param_regs + n_callee_saves;
assert(n_params == cconv->n_parameters);
@@ -1961,6 +1972,12 @@ no_call_mem:;
/* construct memory input */
in[n_amd64_call_mem] = be_make_Sync(new_block, sync_arity, sync_ins);
+ if (ir_needs_reloaded_callee_saves(node)) {
+ /* add callee saves */
+ add_callee_saves(irg, cconv, &in[in_arity], &in_req[in_arity]);
+ in_arity += n_callee_saves;
+ }
+
assert(in_arity <= (int)max_inputs);
/* count outputs */
@@ -1983,6 +2000,7 @@ no_call_mem:;
/* create call node */
ir_node *const call = new_bd_amd64_call(dbgi, new_block, in_arity, in, in_req, out_arity, &call_attr);
ir_set_throws_exception(call, ir_throws_exception(node));
+ ir_set_needs_reloaded_callee_saves(call, ir_needs_reloaded_callee_saves(node));
fix_node_mem_proj(call, mem_proj);
/* create output register reqs */
diff --git a/ir/be/benode.c b/ir/be/benode.c
index 5daeae2..009624c 100644
--- a/ir/be/benode.c
+++ b/ir/be/benode.c
@@ -101,7 +101,7 @@ static int be_relocation_attrs_equal(ir_node const *a, ir_node const *b)
return attr_a->entity == attr_b->entity && attr_a->kind == attr_b->kind;
}
-arch_register_req_t const **be_allocate_in_reqs(ir_graph *const irg, unsigned const n)
+arch_register_req_t const **be_allocate_in_reqs(ir_graph *irg, unsigned const n)
{
struct obstack *const obst = be_get_be_obst(irg);
return OALLOCN(obst, arch_register_req_t const*, n);
@@ -511,7 +511,7 @@ ir_node *be_get_Start_mem(ir_graph *const irg)
return be_get_or_make_Proj_for_pn(start, 0);
}
-ir_node *be_get_Start_proj(ir_graph *const irg, arch_register_t const *const reg)
+ir_node *be_get_Start_proj(ir_graph *irg, arch_register_t const *const reg)
{
ir_node *const start = get_irg_start(irg);
/* do a naive linear search... */
diff --git a/ir/be/betranshlp.c b/ir/be/betranshlp.c
index d970eec..c07441e 100644
--- a/ir/be/betranshlp.c
+++ b/ir/be/betranshlp.c
@@ -576,8 +576,8 @@ void be_map_exc_node_to_runtime_call(ir_node *node, ir_mode *res_mode,
ir_node *mem = get_memop_mem(node);
ir_node *call = new_rd_Call(dbgi, block, mem, addr, n_in, in, mtp);
set_irn_pinned(call, get_irn_pinned(node));
- int throws_exception = ir_throws_exception(node);
- ir_set_throws_exception(call, throws_exception);
+ ir_set_throws_exception(call, ir_throws_exception(node));
+ ir_set_needs_reloaded_callee_saves(call, ir_needs_reloaded_callee_saves(node));
assert(pn_M < 2 && pn_res < 2 && pn_X_regular < 4 && pn_X_except < 4);
int const n_proj = 4;
@@ -586,7 +586,7 @@ void be_map_exc_node_to_runtime_call(ir_node *node, ir_mode *res_mode,
tuple_in[pn_M] = new_r_Proj(call, mode_M, pn_Call_M);
ir_node *ress = new_r_Proj(call, mode_T, pn_Call_T_result);
tuple_in[pn_res] = new_r_Proj(ress, res_mode, 0);
- if (throws_exception) {
+ if (ir_throws_exception(call)) {
tuple_in[pn_X_regular] = new_r_Proj(call, mode_X, pn_Call_X_regular);
tuple_in[pn_X_except] = new_r_Proj(call, mode_X, pn_Call_X_except);
n_operands += 2;
diff --git a/ir/ir/irnode.c b/ir/ir/irnode.c
index ad12bdc..d4e21d1 100644
--- a/ir/ir/irnode.c
+++ b/ir/ir/irnode.c
@@ -678,6 +678,21 @@ int ir_throws_exception(const ir_node *node)
return attr->throws_exception;
}
+void ir_set_needs_reloaded_callee_saves(ir_node *node, int needs_reloaded_callee_saves)
+{
+ assert(is_fragile_op(node));
+ except_attr *attr = &node->attr.except;
+ attr->needs_reloaded_callee_saves = needs_reloaded_callee_saves;
+}
+
+int ir_needs_reloaded_callee_saves(const ir_node *node)
+{
+ if (!is_fragile_op(node))
+ return false;
+ const except_attr *attr = &node->attr.except;
+ return attr->needs_reloaded_callee_saves;
+}
+
size_t get_ASM_n_output_constraints(const ir_node *node)
{
assert(is_ASM(node));
diff --git a/ir/ir/irnode_t.h b/ir/ir/irnode_t.h
index 7336655..8193526 100644
--- a/ir/ir/irnode_t.h
+++ b/ir/ir/irnode_t.h
@@ -137,6 +137,8 @@ typedef struct except_attr {
bool throws_exception : 1;
/**< Whether this node needs a label because of possible exception. */
bool needs_except_label : 1;
+ /**< Whether this node requires all callee-saves to be reloaded. */
+ bool needs_reloaded_callee_saves : 1;
} except_attr;
/** Attributes for Call nodes. */