From: Michael Beck Date: Thu, 12 Jan 2006 01:00:21 +0000 (+0000) Subject: Bound operation added: X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=c7f92b19d9eb6777c6d98f35e7e8b0c08faeffc9;p=libfirm Bound operation added: high level bounds check for Java, Pascal, Modula-3 [r7214] --- diff --git a/ir/ir/ircons.c b/ir/ir/ircons.c index 85d1ec0e3..085ee137b 100644 --- a/ir/ir/ircons.c +++ b/ir/ir/ircons.c @@ -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); +} diff --git a/ir/ir/ircons.h b/ir/ir/ircons.h index 101387895..38ae196fd 100644 --- a/ir/ir/ircons.h +++ b/ir/ir/ircons.h @@ -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. */ diff --git a/ir/ir/irdump.c b/ir/ir/irdump.c index b8ee522a6..31030bfbd 100644 --- a/ir/ir/irdump.c +++ b/ir/ir/irdump.c @@ -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 }; diff --git a/ir/ir/irnode.c b/ir/ir/irnode.c index d2ed2643a..fca414d18 100644 --- a/ir/ir/irnode.c +++ b/ir/ir/irnode.c @@ -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) { /* diff --git a/ir/ir/irnode.h b/ir/ir/irnode.h index a3b4412de..469910a66 100644 --- a/ir/ir/irnode.h +++ b/ir/ir/irnode.h @@ -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 diff --git a/ir/ir/irnode_t.h b/ir/ir/irnode_t.h index 6a3f03e14..699d0b0df 100644 --- a/ir/ir/irnode_t.h +++ b/ir/ir/irnode_t.h @@ -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; diff --git a/ir/ir/irop.c b/ir/ir/irop.c index 23e9d8907..14654a476 100644 --- a/ir/ir/irop.c +++ b/ir/ir/irop.c @@ -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. */ diff --git a/ir/ir/irop.h b/ir/ir/irop.h index ac8eeaaee..c5471dfe8 100644 --- a/ir/ir/irop.h +++ b/ir/ir/irop.h @@ -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); diff --git a/ir/ir/irvrfy.c b/ir/ir/irvrfy.c index f5a6e957a..d366cf60b 100644 --- a/ir/ir/irvrfy.c +++ b/ir/ir/irvrfy.c @@ -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 */; }