Commit c7f92b19 authored by Michael Beck's avatar Michael Beck
Browse files

Bound operation added:

 high level bounds check for Java, Pascal, Modula-3

[r7214]
parent 1838facc
......@@ -964,6 +964,27 @@ new_bd_CopyB (dbg_info *db, ir_node *block,
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 */
/* --------------------------------------------- */
......@@ -1750,6 +1771,19 @@ ir_node *new_rd_CopyB(dbg_info *db, ir_graph *irg, ir_node *block,
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);
}
......@@ -1959,11 +1993,14 @@ ir_node *new_r_Mux (ir_graph *irg, ir_node *block,
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 */
......@@ -2591,7 +2628,7 @@ get_r_frag_value_internal (ir_node *block, ir_node *cfOp, int pos, ir_mode *mode
}
return res;
}
#endif
#endif /* PRECISE_EXC_CONTEXT */
/**
computes the predecessors for the real phi node, and then
......@@ -3311,6 +3348,17 @@ ir_node *new_d_CopyB(dbg_info *db,ir_node *store,
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. */
......@@ -3642,3 +3690,6 @@ ir_node *new_Mux (ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *mo
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);
}
......@@ -292,6 +292,7 @@
* 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);
......@@ -943,6 +944,12 @@
* 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)
* ----------------------------------------------------------
*
......@@ -1816,8 +1823,6 @@ ir_node *new_rd_Filter (dbg_info *db, ir_graph *irg, ir_node *block, ir_node *ar
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.
......@@ -1831,8 +1836,6 @@ ir_node *new_rd_Mux (dbg_info *db, ir_graph *irg, ir_node *block,
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.
......@@ -1845,6 +1848,20 @@ ir_node *new_rd_Mux (dbg_info *db, ir_graph *irg, ir_node *block,
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 */
/*-------------------------------------------------------------------------*/
......@@ -2517,8 +2534,6 @@ ir_node *new_r_Filter (ir_graph *irg, ir_node *block, ir_node *arg,
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.
......@@ -2531,8 +2546,6 @@ ir_node *new_r_Mux (ir_graph *irg, ir_node *block,
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.
......@@ -2544,6 +2557,19 @@ ir_node *new_r_Mux (ir_graph *irg, ir_node *block,
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 */
/*-----------------------------------------------------------------------*/
......@@ -3233,8 +3259,6 @@ ir_node *new_d_Filter (dbg_info *db, ir_node *arg, ir_mode *mode, long proj);
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.
......@@ -3246,8 +3270,6 @@ ir_node *new_d_Mux (dbg_info *db, 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 *store The current memory
......@@ -3257,6 +3279,17 @@ ir_node *new_d_Mux (dbg_info *db, ir_node *sel,
*/
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 */
/*-----------------------------------------------------------------------*/
......@@ -3869,6 +3902,18 @@ ir_node *new_Mux (ir_node *sel, ir_node *ir_false, ir_node *ir_true, ir_mode *m
*/
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. */
......
......@@ -858,6 +858,24 @@ static const pns_lookup_t alloc_lut[] = {
#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[] = {
......@@ -871,7 +889,9 @@ 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
};
......
......@@ -2076,7 +2076,53 @@ void set_CopyB_type(ir_node *node, ir_type *data_type) {
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) {
/*
......
......@@ -958,6 +958,35 @@ void set_CopyB_src (ir_node *node, ir_node *src);
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
......
......@@ -181,6 +181,11 @@ typedef struct {
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.
*/
......@@ -222,6 +227,7 @@ typedef union {
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;
......
......@@ -93,6 +93,7 @@ ir_op *op_EndExcept; ir_op *get_op_EndExcept (void) { return op_EndExcept; }
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; }
/*
......@@ -265,6 +266,7 @@ init_op(void)
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
......@@ -339,6 +341,7 @@ void finish_op(void) {
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. */
......
......@@ -74,7 +74,7 @@ typedef enum {
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;
......@@ -142,6 +142,7 @@ extern ir_op *op_EndExcept; ir_op *get_op_EndExcept (void);
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);
......
......@@ -693,6 +693,47 @@ static int verify_node_Proj_EndExcept(ir_node *n, ir_node *p) {
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
*/
......@@ -1581,6 +1622,34 @@ static int verify_node_CopyB(ir_node *n, ir_graph *irg) {
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
......@@ -1928,6 +1997,7 @@ void firm_set_default_verifyer(opcode code, ir_op_ops *ops)
CASE(Confirm);
CASE(Mux);
CASE(CopyB);
CASE(Bound);
default:
/* leave NULL */;
}
......@@ -1957,6 +2027,8 @@ void firm_set_default_verifyer(opcode code, ir_op_ops *ops)
CASE(CallBegin);
CASE(EndReg);
CASE(EndExcept);
CASE(CopyB);
CASE(Bound);
default:
/* leave NULL */;
}
......
Supports Markdown
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