return res;
}
+static ir_node *
+new_bd_Bound (dbg_info *db, ir_node *block,
+ ir_node *store, ir_node *idx, ir_node *lower, ir_node *upper)
+{
+ ir_node *in[4];
+ ir_node *res;
+ ir_graph *irg = current_ir_graph;
+
+ in[0] = store;
+ in[1] = idx;
+ in[2] = lower;
+ in[3] = upper;
+
+ res = new_ir_node(db, irg, block, op_Bound, mode_T, 4, in);
+
+ res->attr.copyb.exc.pin_state = op_pin_state_pinned;
+ res = optimize_node(res);
+ IRN_VRFY_IRG(res, irg);
+ return res;
+}
+
/* --------------------------------------------- */
/* private interfaces, for professional use only */
/* --------------------------------------------- */
return res;
}
+ir_node *new_rd_Bound(dbg_info *db, ir_graph *irg, ir_node *block,
+ ir_node *store, ir_node *idx, ir_node *lower, ir_node *upper)
+{
+ ir_node *res;
+ ir_graph *rem = current_ir_graph;
+
+ current_ir_graph = irg;
+ res = new_bd_Bound(db, block, store, idx, lower, upper);
+ current_ir_graph = rem;
+
+ return res;
+}
+
ir_node *new_r_Block (ir_graph *irg, int arity, ir_node **in) {
return new_rd_Block(NULL, irg, arity, in);
}
ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode) {
return new_rd_Mux(NULL, irg, block, sel, ir_false, ir_true, mode);
}
-
ir_node *new_r_CopyB(ir_graph *irg, ir_node *block,
ir_node *store, ir_node *dst, ir_node *src, type *data_type) {
return new_rd_CopyB(NULL, irg, block, store, dst, src, data_type);
}
+ir_node *new_r_Bound(ir_graph *irg, ir_node *block,
+ ir_node *store, ir_node *idx, ir_node *lower, ir_node *upper) {
+ return new_rd_Bound(NULL, irg, block, store, idx, lower, upper);
+}
/** ********************/
/** public interfaces */
}
return res;
}
-#endif
+#endif /* PRECISE_EXC_CONTEXT */
/**
computes the predecessors for the real phi node, and then
return res;
}
+ir_node *new_d_Bound(dbg_info *db,ir_node *store,
+ ir_node *idx, ir_node *lower, ir_node *upper) {
+ ir_node *res;
+ res = new_bd_Bound(db, current_ir_graph->current_block,
+ store, idx, lower, upper);
+#if PRECISE_EXC_CONTEXT
+ allocate_frag_arr(res, op_Bound, &res->attr.bound.exc.frag_arr);
+#endif
+ return res;
+}
+
/* ********************************************************************* */
/* Comfortable interface with automatic Phi node construction. */
/* (Uses also constructors of ?? interface, except new_Block. */
ir_node *new_CopyB(ir_node *store, ir_node *dst, ir_node *src, type *data_type) {
return new_d_CopyB(NULL, store, dst, src, data_type);
}
+ir_node *new_Bound(ir_node *store, ir_node *idx, ir_node *lower, ir_node *upper) {
+ return new_d_Bound(NULL, store, idx, lower, upper);
+}
* ir_node *new_NoMem (void);
* ir_node *new_Mux (ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode);
* ir_node *new_CopyB (ir_node *store, ir_node *dst, ir_node *src, type *data_type);
+ * ir_node *new_Bound (ir_node *store, ir_node *idx, ir_node *lower, ir_node *upper);
*
* void add_immBlock_pred (ir_node *block, ir_node *jmp);
* void mature_immBlock (ir_node *block);
* Describes a high level block copy of a compound type form address src to
* address dst. Must be lowered to a Call to a runtime memory copy function.
*
+ * ir_node *new_Bound (ir_node *store, ir_node *idx, ir_node *lower, ir_node *upper);
+ * -----------------------------------------------------------------------------------
+ *
+ * Describes a high level bounds check. Must be lowered to a Call to a runtime check
+ * function.
+ *
* ir_node *new_Proj (ir_node *arg, ir_mode *mode, long proj)
* ----------------------------------------------------------
*
ir_node *new_rd_NoMem (ir_graph *irg);
/** Constructor for a Mux node.
- *
- * Adds the node to the block in current_ir_block.
*
* @param *db A pointer for debug information.
* @param *irg The ir graph the node belong to.
ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode);
/** Constructor for a CopyB node.
- *
- * Adds the node to the block in current_ir_block.
*
* @param *db A pointer for debug information.
* @param *irg The ir graph the node belong to.
ir_node *new_rd_CopyB(dbg_info *db, ir_graph *irg, ir_node *block,
ir_node *store, ir_node *dst, ir_node *src, type *data_type);
+/** Constructor for a Bound node.
+ * Checks whether lower <= idx && idx < upper.
+ *
+ * @param *db A pointer for debug information.
+ * @param *irg The ir graph the node belong to.
+ * @param *block The block the node belong to.
+ * @param *store The current memory
+ * @param *idx The ir_node that represents an index.
+ * @param *lower The ir_node that represents the lower bound for the index.
+ * @param *upper The ir_node that represents the upper bound for the index.
+ */
+ir_node *new_rd_Bound(dbg_info *db, ir_graph *irg, ir_node *block,
+ ir_node *store, ir_node *idx, ir_node *lower, ir_node *upper);
+
/*-------------------------------------------------------------------------*/
/* The raw interface without debug support */
/*-------------------------------------------------------------------------*/
ir_node *new_r_NoMem (ir_graph *irg);
/** Constructor for a Mux node.
- *
- * Adds the node to the block in current_ir_block.
*
* @param *irg The ir graph the node belong to.
* @param *block The block the node belong to.
ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mode);
/** Constructor for a CopyB node.
- *
- * Adds the node to the block in current_ir_block.
*
* @param *irg The ir graph the node belong to.
* @param *block The block the node belong to.
ir_node *new_r_CopyB(ir_graph *irg, ir_node *block,
ir_node *store, ir_node *dst, ir_node *src, type *data_type);
+/** Constructor for a Bound node.
+ * Checks whether lower <= idx && idx < upper.
+ *
+ * @param *irg The ir graph the node belong to.
+ * @param *block The block the node belong to.
+ * @param *store The current memory
+ * @param *idx The ir_node that represents an index.
+ * @param *lower The ir_node that represents the lower bound for the index.
+ * @param *upper The ir_node that represents the upper bound for the index.
+ */
+ir_node *new_r_Bound(ir_graph *irg, ir_node *block,
+ ir_node *store, ir_node *idx, ir_node *lower, ir_node *upper);
+
/*-----------------------------------------------------------------------*/
/* The block oriented interface */
/*-----------------------------------------------------------------------*/
ir_node *new_d_NoMem (void);
/** Constructor for a Mux node.
- *
- * Adds the node to the block in current_ir_block.
*
* @param *db A pointer for debug information.
* @param *sel The ir_node that calculates the boolean select.
ir_node *ir_false, ir_node *ir_true, ir_mode *mode);
/** Constructor for a CopyB node.
- *
- * Adds the node to the block in current_ir_block.
*
* @param *db A pointer for debug information.
* @param *store The current memory
*/
ir_node *new_d_CopyB(dbg_info *db, ir_node *store, ir_node *dst, ir_node *src, type *data_type);
+/** Constructor for a Bound node.
+ * Checks whether lower <= idx && idx < upper.
+ *
+ * @param *db A pointer for debug information.
+ * @param *store The current memory
+ * @param *idx The ir_node that represents an index.
+ * @param *lower The ir_node that represents the lower bound for the index.
+ * @param *upper The ir_node that represents the upper bound for the index.
+ */
+ir_node *new_d_Bound(dbg_info *db, ir_node *store, ir_node *idx, ir_node *lower, ir_node *upper);
+
/*-----------------------------------------------------------------------*/
/* The block oriented interface without debug support */
/*-----------------------------------------------------------------------*/
*/
ir_node *new_CopyB(ir_node *store, ir_node *dst, ir_node *src, type *data_type);
+/** Constructor for a Bound node.
+ * Checks whether lower <= idx && idx < upper.
+ *
+ * Adds the node to the block in current_ir_block.
+ *
+ * @param *store The current memory
+ * @param *idx The ir_node that represents an index.
+ * @param *lower The ir_node that represents the lower bound for the index.
+ * @param *upper The ir_node that represents the upper bound for the index.
+ */
+ir_node *new_Bound(ir_node *store, ir_node *idx, ir_node *lower, ir_node *upper);
+
/*---------------------------------------------------------------------*/
/* The comfortable interface. */
/* Supports automatic Phi node construction. */
#undef X
};
+/** the lookup table for Proj(CopyB) names */
+static const pns_lookup_t copyb_lut[] = {
+#define X(a) { pn_CopyB_##a, #a }
+ X(M),
+ X(X_except),
+ X(M_except)
+#undef X
+};
+
+/** the lookup table for Proj(Bound) names */
+static const pns_lookup_t bound_lut[] = {
+#define X(a) { pn_Bound_##a, #a }
+ X(M),
+ X(X_except),
+ X(res),
+ X(M_except)
+#undef X
+};
/** the Proj lookup table */
static const proj_lookup_t proj_lut[] = {
{ iro_Mod, E(mod_lut) },
{ iro_Load, E(load_lut) },
{ iro_Store, E(store_lut) },
- { iro_Alloc, E(alloc_lut) }
+ { iro_Alloc, E(alloc_lut) },
+ { iro_CopyB, E(copyb_lut) },
+ { iro_Bound, E(bound_lut) }
#undef E
};
node->attr.copyb.data_type = data_type;
}
+/* Bound support */
+/* Returns the memory input of a Bound operation. */
+ir_node *get_Bound_mem(ir_node *bound) {
+ assert (bound->op == op_Bound);
+ return get_irn_n(bound, 0);
+}
+
+void set_Bound_mem (ir_node *bound, ir_node *mem) {
+ assert (bound->op == op_Bound);
+ set_irn_n(bound, 0, mem);
+}
+
+/* Returns the index input of a Bound operation. */
+ir_node *get_Bound_index(ir_node *bound) {
+ assert (bound->op == op_Bound);
+ return get_irn_n(bound, 1);
+}
+
+void set_Bound_index(ir_node *bound, ir_node *idx) {
+ assert (bound->op == op_Bound);
+ set_irn_n(bound, 1, idx);
+}
+
+/* Returns the lower bound input of a Bound operation. */
+ir_node *get_Bound_lower(ir_node *bound) {
+ assert (bound->op == op_Bound);
+ return get_irn_n(bound, 2);
+}
+
+void set_Bound_lower(ir_node *bound, ir_node *lower) {
+ assert (bound->op == op_Bound);
+ set_irn_n(bound, 2, lower);
+}
+
+/* Returns the upper bound input of a Bound operation. */
+ir_node *get_Bound_upper(ir_node *bound) {
+ assert (bound->op == op_Bound);
+ return get_irn_n(bound, 3);
+}
+
+void set_Bound_upper(ir_node *bound, ir_node *upper) {
+ assert (bound->op == op_Bound);
+ set_irn_n(bound, 3, upper);
+}
+
+/* returns the graph of a node */
ir_graph *
get_irn_irg(const ir_node *node) {
/*
ir_type *get_CopyB_type(ir_node *node);
void set_CopyB_type(ir_node *node, ir_type *data_type);
+/**
+ * Projection numbers for result of Bound node: use for Proj nodes!
+ */
+typedef enum {
+ pn_Bound_M_regular = 0, /**< The memory result. */
+ pn_Bound_X_except = 1, /**< The control flow result branching to the exception handler */
+ pn_Bound_res = 2, /**< The checked index. */
+ pn_Bound_M_except = 3, /**< The memory result in case the runtime function terminated with
+ an exception */
+ pn_Bound_max = 4 /**< number of projections from a Bound */
+} pn_Bound;
+#define pn_Bound_M pn_Bound_M_regular
+
+/** Returns the memory input of a Bound operation. */
+ir_node *get_Bound_mem(ir_node *bound);
+void set_Bound_mem (ir_node *bound, ir_node *mem);
+
+/** Returns the index input of a Bound operation. */
+ir_node *get_Bound_index(ir_node *bound);
+void set_Bound_index(ir_node *bound, ir_node *idx);
+
+/** Returns the lower bound input of a Bound operation. */
+ir_node *get_Bound_lower(ir_node *bound);
+void set_Bound_lower(ir_node *bound, ir_node *lower);
+
+/** Returns the upper bound input of a Bound operation. */
+ir_node *get_Bound_upper(ir_node *bound);
+void set_Bound_upper(ir_node *bound, ir_node *upper);
+
/*
*
* NAME Auxiliary routines
ir_type *data_type; /**< type of the copied entity */
} copyb_attr;
+/** Bound attribute */
+typedef struct {
+ except_attr exc; /**< the exception attribute. MUST be the first one. */
+} bound_attr;
+
/**
* Edge info to put into an irn.
*/
end_attr end; /**< For EndReg, EndExcept */
except_attr except; /**< For Phi node construction in case of exceptions */
copyb_attr copyb; /**< For CopyB operation */
+ bound_attr bound; /**< For Bound operation */
} attr;
ir_op *op_NoMem; ir_op *get_op_NoMem (void) { return op_NoMem; }
ir_op *op_Mux; ir_op *get_op_Mux (void) { return op_Mux; }
ir_op *op_CopyB; ir_op *get_op_CopyB (void) { return op_CopyB; }
+ir_op *op_Bound; ir_op *get_op_Bound (void) { return op_Bound; }
/*
op_NoMem = new_ir_op(iro_NoMem, "NoMem", op_pin_state_pinned, N, oparity_zero, -1, 0, NULL);
op_Mux = new_ir_op(iro_Mux, "Mux", op_pin_state_floats, N, oparity_trinary, -1, 0, NULL);
op_CopyB = new_ir_op(iro_CopyB, "CopyB", op_pin_state_mem_pinned, L|F|H, oparity_trinary, -1, sizeof(copyb_attr), NULL);
+ op_Bound = new_ir_op(iro_Bound, "Bound", op_pin_state_mem_pinned, L|F|H, oparity_trinary, -1, sizeof(bound_attr), NULL);
#undef H
#undef Y
free_ir_op (op_NoMem ); op_NoMem = NULL;
free_ir_op (op_Mux ); op_Mux = NULL;
free_ir_op (op_CopyB ); op_CopyB = NULL;
+ free_ir_op (op_Bound ); op_Bound = NULL;
}
/* Returns the string for the opcode. */
iro_Load, iro_Store, iro_Alloc, iro_Free, iro_Sync,
iro_Proj, iro_Tuple, iro_Id, iro_Bad, iro_Confirm,
iro_Unknown, iro_Filter, iro_Break, iro_CallBegin, iro_EndReg, iro_EndExcept,
- iro_NoMem, iro_Mux, iro_CopyB,
+ iro_NoMem, iro_Mux, iro_CopyB, iro_Bound,
iro_MaxOpcode
} opcode;
extern ir_op *op_NoMem; ir_op *get_op_NoMem (void);
extern ir_op *op_Mux; ir_op *get_op_Mux (void);
extern ir_op *op_CopyB; ir_op *get_op_CopyB (void);
+extern ir_op *op_Bound; ir_op *get_op_Bound (void);
/** Returns the ident for the opcode name */
ident *get_op_ident(const ir_op *op);
return 1;
}
+/**
+ * verify a Proj(CopyB) node
+ */
+static int verify_node_Proj_CopyB(ir_node *n, ir_node *p) {
+ ir_mode *mode = get_irn_mode(p);
+ long proj = get_Proj_proj(p);
+
+ ASSERT_AND_RET_DBG(
+ ((proj == pn_CopyB_M && mode == mode_M) ||
+ (proj == pn_CopyB_X_except && mode == mode_X)),
+ "wrong Proj from CopyB", 0,
+ show_proj_failure(p);
+ );
+ if (proj == pn_CopyB_X_except)
+ ASSERT_AND_RET(
+ get_irn_pinned(n) == op_pin_state_pinned,
+ "Exception Proj from unpinned CopyB", 0);
+ return 1;
+}
+
+/**
+ * verify a Proj(Bound) node
+ */
+static int verify_node_Proj_Bound(ir_node *n, ir_node *p) {
+ ir_mode *mode = get_irn_mode(p);
+ long proj = get_Proj_proj(p);
+
+ ASSERT_AND_RET_DBG(
+ ((proj == pn_Bound_M && mode == mode_M) ||
+ (proj == pn_Bound_X_except && mode == mode_X) ||
+ (proj == pn_Bound_res && mode == get_irn_mode(get_Bound_index(n)))),
+ "wrong Proj from Bound", 0,
+ show_proj_failure(p);
+ );
+ if (proj == pn_Bound_X_except)
+ ASSERT_AND_RET(
+ get_irn_pinned(n) == op_pin_state_pinned,
+ "Exception Proj from unpinned Bound", 0);
+ return 1;
+}
+
/**
* verify a Proj node
*/
return 1;
}
+/**
+ * verify a Bound node
+ */
+static int verify_node_Bound(ir_node *n, ir_graph *irg) {
+ ir_mode *mymode = get_irn_mode(n);
+ ir_mode *op1mode = get_irn_mode(get_Bound_mem(n));
+ ir_mode *op2mode = get_irn_mode(get_Bound_index(n));
+ ir_mode *op3mode = get_irn_mode(get_Bound_lower(n));
+ ir_mode *op4mode = get_irn_mode(get_Bound_upper(n));
+
+ /* Bound: BB x M x ref x ref --> M x X */
+ ASSERT_AND_RET(
+ mymode == mode_T &&
+ op1mode == mode_M &&
+ op2mode == op3mode &&
+ op3mode == op4mode &&
+ mode_is_int(op3mode),
+ "Bound node", 0 ); /* operand M x int x int x int */
+
+ /* NoMem nodes are only allowed as memory input if the Bound is NOT pinned.
+ This should happen RARELY, as Bound COPIES MEMORY */
+ ASSERT_AND_RET(
+ (get_irn_op(get_Bound_mem(n)) == op_NoMem) ||
+ (get_irn_op(get_Bound_mem(n)) != op_NoMem && get_irn_pinned(n) == op_pin_state_pinned),
+ "Bound node with wrong memory input", 0 );
+ return 1;
+}
+
/*
* Check dominance.
* For each usage of a node, it is checked, if the block of the
CASE(Confirm);
CASE(Mux);
CASE(CopyB);
+ CASE(Bound);
default:
/* leave NULL */;
}
CASE(CallBegin);
CASE(EndReg);
CASE(EndExcept);
+ CASE(CopyB);
+ CASE(Bound);
default:
/* leave NULL */;
}