#define OUT_POS(x) (-((x) + 1))
-/* Sometimes we want to put const nodes into get_irn_generic_attr ... */
-#define get_irn_attr(irn) get_irn_generic_attr((ir_node *) (irn))
+#define get_irn_attr(irn) get_irn_generic_attr(irn)
+#define get_irn_attr_const(irn) get_irn_generic_attr_const(irn)
static unsigned be_node_tag = FOURCC('B', 'E', 'N', 'O');
typedef struct {
be_node_attr_t node_attr;
int num_ret_vals; /**< number of return values */
+ unsigned pop; /**< number of bytes that should be popped */
} be_return_attr_t;
/** The be_Stack attribute type. */
typedef struct {
be_node_attr_t node_attr;
ir_entity *ent; /**< The called entity if this is a static call. */
+ unsigned pop;
ir_type *call_tp; /**< The call type, copied from the original Call node. */
} be_call_attr_t;
ir_op *op_be_IncSP;
ir_op *op_be_AddSP;
ir_op *op_be_SubSP;
-ir_op *op_be_SetSP;
ir_op *op_be_RegParams;
-ir_op *op_be_StackParam;
ir_op *op_be_FrameAddr;
-ir_op *op_be_FrameLoad;
-ir_op *op_be_FrameStore;
ir_op *op_be_Barrier;
static int beo_base = -1;
if (a_attr->num_ret_vals != b_attr->num_ret_vals)
return 1;
+ if (a_attr->pop != b_attr->pop)
+ return 1;
return _node_cmp_attr((be_node_attr_t*) a_attr, (be_node_attr_t*) b_attr);
}
static INLINE be_req_t *get_be_req(const ir_node *node, int pos)
{
int idx;
- be_node_attr_t *attr;
+ const be_node_attr_t *attr;
be_reg_data_t *rd;
assert(is_be_node(node));
- attr = get_irn_attr(node);
+ attr = get_irn_attr_const(node);
if(pos < 0) {
idx = -(pos + 1);
op_be_AddSP = new_ir_op(beo_base + beo_AddSP, "be_AddSP", op_pin_state_pinned, N, oparity_unary, 0, sizeof(be_node_attr_t), &be_node_op_ops);
op_be_SubSP = new_ir_op(beo_base + beo_SubSP, "be_SubSP", op_pin_state_pinned, N, oparity_unary, 0, sizeof(be_node_attr_t), &be_node_op_ops);
op_be_IncSP = new_ir_op(beo_base + beo_IncSP, "be_IncSP", op_pin_state_pinned, N, oparity_unary, 0, sizeof(be_stack_attr_t), &be_node_op_ops);
- op_be_SetSP = new_ir_op(beo_base + beo_SetSP, "be_SetSP", op_pin_state_pinned, N, oparity_binary, 0, sizeof(be_stack_attr_t), &be_node_op_ops);
op_be_RegParams = new_ir_op(beo_base + beo_RegParams, "be_RegParams", op_pin_state_pinned, N, oparity_zero, 0, sizeof(be_node_attr_t), &be_node_op_ops);
- op_be_StackParam = new_ir_op(beo_base + beo_StackParam, "be_StackParam", op_pin_state_floats, N, oparity_unary, 0, sizeof(be_frame_attr_t), &be_node_op_ops);
- op_be_FrameLoad = new_ir_op(beo_base + beo_FrameLoad, "be_FrameLoad", op_pin_state_floats, N, oparity_any, 0, sizeof(be_frame_attr_t), &be_node_op_ops);
- op_be_FrameStore = new_ir_op(beo_base + beo_FrameStore, "be_FrameStore", op_pin_state_floats, N, oparity_any, 0, sizeof(be_frame_attr_t), &be_node_op_ops);
op_be_FrameAddr = new_ir_op(beo_base + beo_FrameAddr, "be_FrameAddr", op_pin_state_floats, N, oparity_unary, 0, sizeof(be_frame_attr_t), &be_node_op_ops);
op_be_Barrier = new_ir_op(beo_base + beo_Barrier, "be_Barrier", op_pin_state_pinned, N, oparity_dynamic, 0, sizeof(be_node_attr_t), &be_node_op_ops);
op_be_AddSP->ops.node_cmp_attr = node_cmp_attr;
set_op_tag(op_be_SubSP, &be_node_tag);
op_be_SubSP->ops.node_cmp_attr = node_cmp_attr;
- set_op_tag(op_be_SetSP, &be_node_tag);
- op_be_SetSP->ops.node_cmp_attr = Stack_cmp_attr;
set_op_tag(op_be_IncSP, &be_node_tag);
op_be_IncSP->ops.node_cmp_attr = Stack_cmp_attr;
set_op_tag(op_be_RegParams, &be_node_tag);
op_be_RegParams->ops.node_cmp_attr = node_cmp_attr;
- set_op_tag(op_be_StackParam, &be_node_tag);
- op_be_StackParam->ops.node_cmp_attr = FrameAddr_cmp_attr;
- set_op_tag(op_be_FrameLoad, &be_node_tag);
- op_be_FrameLoad->ops.node_cmp_attr = FrameAddr_cmp_attr;
- set_op_tag(op_be_FrameStore, &be_node_tag);
- op_be_FrameStore->ops.node_cmp_attr = FrameAddr_cmp_attr;
set_op_tag(op_be_FrameAddr, &be_node_tag);
op_be_FrameAddr->ops.node_cmp_attr = FrameAddr_cmp_attr;
set_op_tag(op_be_Barrier, &be_node_tag);
static be_reg_data_t *retrieve_reg_data(const ir_node *node)
{
- be_node_attr_t *attr;
+ const be_node_attr_t *attr;
int pos = 0;
if(is_Proj(node)) {
}
assert(is_be_node(node));
- attr = get_irn_attr(node);
+ attr = get_irn_attr_const(node);
assert(pos >= 0 && pos < ARR_LEN(attr->reg_data) && "illegal proj number");
return &attr->reg_data[pos];
void be_Perm_reduce(ir_node *perm, int new_size, int *map)
{
ir_graph *irg = get_irn_irg(perm);
- int n = get_irn_arity(perm);
- be_reg_data_t *old_data = xmalloc(n * sizeof(old_data[0]));
+ int arity = get_irn_arity(perm);
+ be_reg_data_t *old_data = alloca(arity * sizeof(old_data[0]));
be_node_attr_t *attr = get_irn_attr(perm);
- ir_node **new_in = NEW_ARR_D(ir_node *, irg->obst, new_size + 1);
+ ir_node **new_in = NEW_ARR_D(ir_node *, irg->obst, new_size);
int i;
assert(be_is_Perm(perm));
- assert(new_size <= n);
+ assert(new_size <= arity);
/* save the old register data */
- memcpy(old_data, attr->reg_data, n * sizeof(old_data[0]));
+ memcpy(old_data, attr->reg_data, arity * sizeof(old_data[0]));
/* compose the new in array and set the new register data directly in place */
- for (i = 0; i < n; ++i) {
+ for (i = 0; i < new_size; ++i) {
int idx = map[i];
- if (idx >= 0) {
- new_in[idx] = get_irn_n(perm, i);
- attr->reg_data[idx] = old_data[i];
- }
+ new_in[i] = get_irn_n(perm, idx);
+ attr->reg_data[i] = old_data[idx];
}
- free(old_data);
set_irn_in(perm, new_size, new_in);
}
req = get_req(res, OUT_POS(0));
req->cls = cls;
req->type = arch_register_req_type_should_be_same;
- req->other_same = 0;
+ req->other_same = 1U << 0;
return res;
}
a = init_node_attr(irn, (n_outs > real_n ? n_outs : real_n));
a->ent = NULL;
a->call_tp = call_tp;
+ a->pop = 0;
return irn;
}
/* Gets the call entity or NULL if this is no static call. */
ir_entity *be_Call_get_entity(const ir_node *call) {
- be_call_attr_t *a = get_irn_attr(call);
+ const be_call_attr_t *a = get_irn_attr_const(call);
assert(be_is_Call(call));
return a->ent;
}
/* Gets the call type. */
ir_type *be_Call_get_type(ir_node *call) {
- be_call_attr_t *a = get_irn_attr(call);
+ const be_call_attr_t *a = get_irn_attr_const(call);
assert(be_is_Call(call));
return a->call_tp;
}
a->call_tp = call_tp;
}
+void be_Call_set_pop(ir_node *call, unsigned pop) {
+ be_call_attr_t *a = get_irn_attr(call);
+ a->pop = pop;
+}
+
+unsigned be_Call_get_pop(const ir_node *call) {
+ const be_call_attr_t *a = get_irn_attr_const(call);
+ return a->pop;
+}
+
/* Construct a new be_Return. */
ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *block, int n_res,
- int n, ir_node *in[])
+ unsigned pop, int n, ir_node *in[])
{
be_return_attr_t *a;
ir_node *res;
a = get_irn_attr(res);
a->num_ret_vals = n_res;
+ a->pop = pop;
return res;
}
/* Returns the number of real returns values */
-int be_Return_get_n_rets(ir_node *ret)
+int be_Return_get_n_rets(const ir_node *ret)
{
- be_return_attr_t *a = get_irn_attr(ret);
+ const be_return_attr_t *a = get_irn_generic_attr_const(ret);
return a->num_ret_vals;
}
+unsigned be_Return_get_pop(const ir_node *ret)
+{
+ const be_return_attr_t *a = get_irn_generic_attr_const(ret);
+ return a->pop;
+}
+
int be_Return_append_node(ir_node *ret, ir_node *node)
{
int pos;
return irn;
}
-ir_node *be_new_SetSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl,
- ir_node *old_sp, ir_node *op, ir_node *mem)
-{
- be_node_attr_t *a;
- ir_node *irn;
- ir_node *in[3];
-
- in[0] = mem;
- in[1] = old_sp;
- in[2] = op;
- irn = new_ir_node(NULL, irg, bl, op_be_SetSP, get_irn_mode(old_sp), 3, in);
- a = init_node_attr(irn, 3);
-
- be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore | arch_irn_flags_modify_sp);
-
- /* Set output constraint to stack register. */
- be_set_constr_single_reg(irn, OUT_POS(0), sp);
- be_node_set_reg_class(irn, be_pos_AddSP_size, sp->reg_class);
- be_node_set_reg_class(irn, be_pos_AddSP_old_sp, sp->reg_class);
-
- return irn;
-}
-
-ir_node *be_new_StackParam(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_mode *mode, ir_node *frame_pointer, ir_entity *ent)
-{
- be_frame_attr_t *a;
- ir_node *irn;
- ir_node *in[1];
-
- in[0] = frame_pointer;
- irn = new_ir_node(NULL, irg, bl, op_be_StackParam, mode, 1, in);
- a = init_node_attr(irn, 1);
- a->ent = ent;
-
- be_node_set_reg_class(irn, 0, cls_frame);
- be_node_set_reg_class(irn, OUT_POS(0), cls);
- be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_rematerializable);
-
- return irn;
-}
-
ir_node *be_new_RegParams(ir_graph *irg, ir_node *bl, int n_outs)
{
ir_node *res;
return proj;
}
-ir_node *be_new_FrameLoad(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
- ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, ir_entity *ent)
-{
- be_frame_attr_t *a;
- ir_node *irn;
- ir_node *in[2];
-
- in[0] = mem;
- in[1] = frame;
- irn = new_ir_node(NULL, irg, bl, op_be_FrameLoad, mode_T, 2, in);
- a = init_node_attr(irn, 3);
- a->ent = ent;
- a->offset = 0;
- be_node_set_reg_class(irn, 1, cls_frame);
- be_node_set_reg_class(irn, OUT_POS(pn_Load_res), cls_data);
- return irn;
-}
-
-ir_node *be_new_FrameStore(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
- ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, ir_node *data, ir_entity *ent)
-{
- be_frame_attr_t *a;
- ir_node *irn;
- ir_node *in[3];
-
- in[0] = mem;
- in[1] = frame;
- in[2] = data;
- irn = new_ir_node(NULL, irg, bl, op_be_FrameStore, mode_T, 3, in);
- a = init_node_attr(irn, 3);
- a->ent = ent;
- a->offset = 0;
- be_node_set_reg_class(irn, 1, cls_frame);
- be_node_set_reg_class(irn, 2, cls_data);
- return irn;
-}
-
ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, ir_entity *ent)
{
be_frame_attr_t *a;
return optimize_node(irn);
}
-ir_node *be_get_FrameAddr_frame(ir_node *node) {
+ir_node *be_get_FrameAddr_frame(const ir_node *node) {
assert(be_is_FrameAddr(node));
return get_irn_n(node, be_pos_FrameAddr_ptr);
}
+ir_entity *be_get_FrameAddr_entity(const ir_node *node)
+{
+ const be_frame_attr_t *attr = get_irn_generic_attr_const(node);
+ return attr->ent;
+}
+
ir_node *be_new_CopyKeep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, int n, ir_node *in_keep[], ir_mode *mode)
{
ir_node *irn;
int be_is_Call (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Call ; }
int be_is_Return (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Return ; }
int be_is_IncSP (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_IncSP ; }
-int be_is_SetSP (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_SetSP ; }
int be_is_AddSP (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_AddSP ; }
int be_is_SubSP (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_SubSP ; }
int be_is_RegParams (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_RegParams ; }
-int be_is_StackParam (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_StackParam ; }
int be_is_FrameAddr (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameAddr ; }
-int be_is_FrameLoad (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameLoad ; }
-int be_is_FrameStore (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameStore ; }
int be_is_Barrier (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Barrier ; }
int be_has_frame_entity(const ir_node *irn)
{
switch(be_get_irn_opcode(irn)) {
- case beo_StackParam:
case beo_Spill:
case beo_Reload:
- case beo_FrameStore:
- case beo_FrameLoad:
case beo_FrameAddr:
return 1;
default:
ir_entity *be_get_frame_entity(const ir_node *irn)
{
if (be_has_frame_entity(irn)) {
- be_frame_attr_t *a = get_irn_attr(irn);
+ const be_frame_attr_t *a = get_irn_attr_const(irn);
return a->ent;
}
return NULL;
{
assert(is_be_node(irn));
if (be_has_frame_entity(irn)) {
- be_frame_attr_t *a = get_irn_attr(irn);
+ const be_frame_attr_t *a = get_irn_attr_const(irn);
return a->offset;
}
return 0;
void be_set_MemPerm_in_entity(const ir_node *irn, int n, ir_entity *ent)
{
- be_memperm_attr_t *attr = get_irn_attr(irn);
+ const be_memperm_attr_t *attr = get_irn_attr_const(irn);
assert(be_is_MemPerm(irn));
assert(n < be_get_MemPerm_entity_arity(irn));
ir_entity* be_get_MemPerm_in_entity(const ir_node* irn, int n)
{
- be_memperm_attr_t *attr = get_irn_attr(irn);
+ const be_memperm_attr_t *attr = get_irn_attr_const(irn);
assert(be_is_MemPerm(irn));
assert(n < be_get_MemPerm_entity_arity(irn));
void be_set_MemPerm_out_entity(const ir_node *irn, int n, ir_entity *ent)
{
- be_memperm_attr_t *attr = get_irn_attr(irn);
+ const be_memperm_attr_t *attr = get_irn_attr_const(irn);
assert(be_is_MemPerm(irn));
assert(n < be_get_MemPerm_entity_arity(irn));
ir_entity* be_get_MemPerm_out_entity(const ir_node* irn, int n)
{
- be_memperm_attr_t *attr = get_irn_attr(irn);
+ const be_memperm_attr_t *attr = get_irn_attr_const(irn);
assert(be_is_MemPerm(irn));
assert(n < be_get_MemPerm_entity_arity(irn));
bereq->flags = flags;
}
+void be_node_add_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
+{
+ be_req_t *bereq = get_be_req(irn, pos);
+ bereq->flags |= flags;
+}
+
void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls)
{
arch_register_req_t *req = get_req(irn, pos);
set_irn_n(incsp, 0, pred);
}
-ir_node *be_get_IncSP_mem(ir_node *irn) {
- assert(be_is_IncSP(irn));
- return get_irn_n(irn, 1);
-}
-
void be_set_IncSP_offset(ir_node *irn, int offset)
{
be_stack_attr_t *a = get_irn_attr(irn);
int be_get_IncSP_offset(const ir_node *irn)
{
- be_stack_attr_t *a = get_irn_attr(irn);
+ const be_stack_attr_t *a = get_irn_attr_const(irn);
assert(be_is_IncSP(irn));
return a->offset;
}
-ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn)
+ir_node *be_spill(const arch_env_t *arch_env, ir_node *block, ir_node *irn)
{
- ir_node *bl = get_nodes_block(irn);
- ir_graph *irg = get_irn_irg(bl);
+ ir_graph *irg = get_irn_irg(block);
ir_node *frame = get_irg_frame(irg);
const arch_register_class_t *cls = arch_get_irn_reg_class(arch_env, irn, -1);
const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
ir_node *spill;
- spill = be_new_Spill(cls, cls_frame, irg, bl, frame, irn);
+ spill = be_new_Spill(cls, cls_frame, irg, block, frame, irn);
return spill;
}
static const
arch_register_req_t *get_out_reg_req(const ir_node *irn, int out_pos)
{
- const be_node_attr_t *a = get_irn_attr(irn);
+ const be_node_attr_t *a = get_irn_attr_const(irn);
if(out_pos >= ARR_LEN(a->reg_data)) {
return arch_no_register_req;
static const
arch_register_req_t *get_in_reg_req(const ir_node *irn, int pos)
{
- const be_node_attr_t *a = get_irn_attr(irn);
+ const be_node_attr_t *a = get_irn_attr_const(irn);
if(pos >= get_irn_arity(irn) || pos >= ARR_LEN(a->reg_data))
return arch_no_register_req;
XXX(Perm, perm);
XXX(Copy, copy);
XXX(Return, branch);
- XXX(StackParam, stackparam);
#undef XXX
default:
return arch_irn_class_normal;
static int be_node_get_sp_bias(const void *self, const ir_node *irn)
{
(void) self;
- return be_is_IncSP(irn) ? be_get_IncSP_offset(irn) : 0;
+ if(be_is_IncSP(irn))
+ return be_get_IncSP_offset(irn);
+ if(be_is_Call(irn))
+ return -(int)be_Call_get_pop(irn);
+
+ return 0;
}
/*
fprintf(f, get_op_name(get_irn_op(irn)));
break;
case dump_node_mode_txt:
- fprintf(f, get_mode_name(get_irn_mode(irn)));
+ if(be_is_Perm(irn) || be_is_Copy(irn) || be_is_CopyKeep(irn)) {
+ fprintf(f, " %s", get_mode_name(get_irn_mode(irn)));
+ }
break;
case dump_node_nodeattr_txt:
if(be_is_Call(irn)) {
if (a->ent)
fprintf(f, " [%s] ", get_entity_name(a->ent));
}
+ if(be_is_IncSP(irn)) {
+ const be_stack_attr_t *attr = get_irn_generic_attr_const(irn);
+ if(attr->offset == BE_STACK_FRAME_SIZE_EXPAND) {
+ fprintf(f, " [Setup Stackframe] ");
+ } else if(attr->offset == BE_STACK_FRAME_SIZE_SHRINK) {
+ fprintf(f, " [Destroy Stackframe] ");
+ } else {
+ fprintf(f, " [%d] ", attr->offset);
+ }
+ }
break;
case dump_node_info_txt:
dump_node_reqs(f, irn);
*/
static void copy_attr(const ir_node *old_node, ir_node *new_node)
{
- be_node_attr_t *old_attr = get_irn_attr(old_node);
+ const be_node_attr_t *old_attr = get_irn_attr_const(old_node);
be_node_attr_t *new_attr = get_irn_attr(new_node);
struct obstack *obst = get_irg_obstack(get_irn_irg(new_node));
unsigned i, len;