typedef struct {
const arch_register_t *reg;
- be_req_t req;
- be_req_t in_req;
+ be_req_t req;
+ be_req_t in_req;
} be_reg_data_t;
/** The generic be nodes attribute type. */
be_node_attr_t node_attr; /**< base attributes of every be node. */
int num_ret_vals; /**< number of return values */
unsigned pop; /**< number of bytes that should be popped */
+ int emit_pop; /**< if set, emit pop bytes, even if pop = 0 */
} be_return_attr_t;
/** The be_IncSP attribute type. */
typedef struct {
be_node_attr_t node_attr; /**< base attributes of every be node. */
- int offset; /**< The offset by which the stack shall be expanded/shrinked. */
+ int offset; /**< The offset by which the stack shall be expanded/shrinked. */
+ int align; /**< whether stack should be aligned after the
+ IncSP */
} be_incsp_attr_t;
/** The be_Frame attribute type. */
typedef struct {
- be_node_attr_t node_attr; /**< base attributes of every be node. */
- ir_entity *ent;
- int offset;
+ be_node_attr_t node_attr; /**< base attributes of every be node. */
+ ir_entity *ent;
+ int offset;
} be_frame_attr_t;
/** The be_Call attribute type. */
typedef struct {
- be_node_attr_t node_attr; /**< base attributes of every be node. */
- 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_node_attr_t node_attr; /**< base attributes of every be node. */
+ 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;
typedef struct {
- be_node_attr_t node_attr; /**< base attributes of every be node. */
- ir_entity **in_entities;
- ir_entity **out_entities;
+ be_node_attr_t node_attr; /**< base attributes of every be node. */
+ ir_entity **in_entities;
+ ir_entity **out_entities;
} be_memperm_attr_t;
ir_op *op_be_Spill;
#define K irop_flag_keep
#define M irop_flag_uses_memory
+static int be_reqs_equal(const be_req_t *req1, const be_req_t *req2)
+{
+ if(!reg_reqs_equal(&req1->req, &req2->req))
+ return 0;
+ if(req1->flags != req2->flags)
+ return 0;
+
+ return 1;
+}
/**
* Compare two be node attributes.
len = ARR_LEN(a->reg_data);
for (i = 0; i < len; ++i) {
if (a->reg_data[i].reg != b->reg_data[i].reg ||
- memcmp(&a->reg_data[i].in_req, &b->reg_data[i].in_req, sizeof(b->reg_data[i].in_req)) ||
- memcmp(&a->reg_data[i].req, &b->reg_data[i].req, sizeof(a->reg_data[i].req)))
+ !be_reqs_equal(&a->reg_data[i].in_req, &b->reg_data[i].in_req) ||
+ !be_reqs_equal(&a->reg_data[i].req, &b->reg_data[i].req))
return 1;
}
*
* @return zero if both nodes have identically attributes
*/
-static int node_cmp_attr(const ir_node *a, const ir_node *b) {
+static int node_cmp_attr(ir_node *a, ir_node *b) {
const be_node_attr_t *a_attr = get_irn_attr_const(a);
const be_node_attr_t *b_attr = get_irn_attr_const(b);
*
* @return zero if both nodes have identically attributes
*/
-static int FrameAddr_cmp_attr(const ir_node *a, const ir_node *b) {
+static int FrameAddr_cmp_attr(ir_node *a, ir_node *b) {
const be_frame_attr_t *a_attr = get_irn_attr_const(a);
const be_frame_attr_t *b_attr = get_irn_attr_const(b);
*
* @return zero if both nodes have identically attributes
*/
-static int Return_cmp_attr(const ir_node *a, const ir_node *b) {
+static int Return_cmp_attr(ir_node *a, ir_node *b) {
const be_return_attr_t *a_attr = get_irn_attr_const(a);
const be_return_attr_t *b_attr = get_irn_attr_const(b);
return 1;
if (a_attr->pop != b_attr->pop)
return 1;
+ if (a_attr->emit_pop != b_attr->emit_pop)
+ return 1;
return _node_cmp_attr(&a_attr->node_attr, &b_attr->node_attr);
}
*
* @return zero if both nodes have identically attributes
*/
-static int IncSP_cmp_attr(const ir_node *a, const ir_node *b) {
+static int IncSP_cmp_attr(ir_node *a, ir_node *b) {
const be_incsp_attr_t *a_attr = get_irn_attr_const(a);
const be_incsp_attr_t *b_attr = get_irn_attr_const(b);
*
* @return zero if both nodes have identically attributes
*/
-static int Call_cmp_attr(const ir_node *a, const ir_node *b) {
+static int Call_cmp_attr(ir_node *a, ir_node *b) {
const be_call_attr_t *a_attr = get_irn_attr_const(a);
const be_call_attr_t *b_attr = get_irn_attr_const(b);
a = get_irn_attr(res);
a->num_ret_vals = n_res;
a->pop = pop;
+ a->emit_pop = 0;
return res;
}
/* Returns the number of real returns values */
-int be_Return_get_n_rets(const ir_node *ret)
-{
+int be_Return_get_n_rets(const ir_node *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)
-{
+/* return the number of bytes that should be popped from stack when executing the Return. */
+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)
-{
+/* return non-zero, if number of popped bytes must be always emitted */
+int be_Return_get_emit_pop(const ir_node *ret) {
+ const be_return_attr_t *a = get_irn_generic_attr_const(ret);
+ return a->emit_pop;
+}
+
+/* return non-zero, if number of popped bytes must be always emitted */
+void be_Return_set_emit_pop(ir_node *ret, int emit_pop) {
+ be_return_attr_t *a = get_irn_generic_attr(ret);
+ a->emit_pop = emit_pop;
+}
+
+int be_Return_append_node(ir_node *ret, ir_node *node) {
int pos;
pos = add_irn_n(ret, node);
return pos;
}
-ir_node *be_new_IncSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, int offset)
+ir_node *be_new_IncSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl,
+ ir_node *old_sp, int offset, int align)
{
be_incsp_attr_t *a;
ir_node *irn;
ir_node *in[1];
in[0] = old_sp;
- irn = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode, sizeof(in) / sizeof(in[0]), in);
+ irn = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode,
+ sizeof(in) / sizeof(in[0]), in);
a = init_node_attr(irn, 1);
a->offset = offset;
+ a->align = align;
be_node_set_flags(irn, -1, arch_irn_flags_ignore | arch_irn_flags_modify_sp);
return a->offset;
}
+int be_get_IncSP_align(const ir_node *irn)
+{
+ const be_incsp_attr_t *a = get_irn_attr_const(irn);
+ assert(be_is_IncSP(irn));
+ return a->align;
+}
+
ir_node *be_spill(const arch_env_t *arch_env, ir_node *block, ir_node *irn)
{
ir_graph *irg = get_irn_irg(block);