X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firvrfy.c;h=f4ad315bfe8f2202a55c371d279514c497a65a8d;hb=8399216d8aebc713bbda04b6e3e250a1d52b20bf;hp=1c4776c48b5a8f33fb61cdf15b5a1179f97ad130;hpb=59ae89e83c171fcf0b40202bb3cfce8c7866ff6a;p=libfirm diff --git a/ir/ir/irvrfy.c b/ir/ir/irvrfy.c index 1c4776c48..f4ad315bf 100644 --- a/ir/ir/irvrfy.c +++ b/ir/ir/irvrfy.c @@ -11,13 +11,14 @@ */ #ifdef HAVE_CONFIG_H -# include +# include "config.h" #endif # include "irprog.h" # include "irgraph_t.h" # include "irvrfy.h" # include "irgwalk.h" +# include "irdump.h" #ifdef NDEBUG /* @@ -34,8 +35,10 @@ #else #define ASSERT_AND_RET(expr, string, ret) \ do { \ - if (opt_do_node_verification == NODE_VERIFICATION_ON) \ - assert((expr) && string); \ + if (opt_do_node_verification == NODE_VERIFICATION_ON) {\ + if (!(expr) && current_ir_graph != get_const_code_irg()) \ + dump_ir_block_graph(current_ir_graph, "-assert"); \ + assert((expr) && string); } \ if (!(expr)) { \ if (opt_do_node_verification == NODE_VERIFICATION_REPORT) \ fprintf(stderr, #expr " : " string "\n"); \ @@ -59,12 +62,21 @@ do { \ #endif +/** if this flag is set, verify entity types in Load & Store nodes */ +static int vrfy_entities = 0; + /* @@@ replace use of array "in" by access functions. */ ir_node **get_irn_in(ir_node *node); static node_verification_t opt_do_node_verification = NODE_VERIFICATION_ON; static const char *bad_msg; +/* enable verification of Load/Store entities */ +void vrfy_enable_entity_tests(int enable) +{ + vrfy_entities = enable; +} + /** * little helper for NULL modes */ @@ -225,6 +237,26 @@ static void show_phi_failure(ir_node *phi, ir_node *pred, int pos) get_irn_node_nr(pred), get_mode_name_ex(get_irn_mode(pred))); } +/** + * Show Phi inputs + */ +static void show_phi_inputs(ir_node *phi, ir_node *block) +{ + fprintf(stderr, "\nFIRM: irn_vrfy_irg() Phi node %ld has %d inputs, its Block %ld has %d\n", + get_irn_node_nr(phi), get_irn_arity(phi), + get_irn_node_nr(block), get_irn_arity(block)); +} + +/* If the address is Sel or SymConst, return the entity. */ +static entity *get_ptr_entity(ir_node *ptr) { + if (get_irn_op(ptr) == op_Sel) { + return get_Sel_entity(ptr); + } else if ((get_irn_op(ptr) == op_SymConst) && (get_SymConst_kind(ptr) == symconst_addr_ent)) { + return get_SymConst_entity(ptr); + } + return NULL; +} + /** * verify the Proj number */ @@ -258,10 +290,10 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { case iro_Cond: ASSERT_AND_RET_DBG( - ( - (proj >= 0 && mode == mode_X && get_irn_mode(get_Cond_selector(pred)) == mode_b) || /* compare */ - (mode == mode_X && mode_is_int(get_irn_mode(get_Cond_selector(pred)))) /* switch */ - ), + ( + (proj >= 0 && mode == mode_X && get_irn_mode(get_Cond_selector(pred)) == mode_b) || /* compare */ + (mode == mode_X && mode_is_int(get_irn_mode(get_Cond_selector(pred)))) /* switch */ + ), "wrong Proj from Cond", 0, show_proj_failure(p); ); @@ -293,18 +325,7 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { "wrong Proj from Call", 0, show_proj_failure(p); ); - break; - case iro_FuncCall: - ASSERT_AND_RET_DBG( - ((proj == pn_Call_M_regular && mode == mode_M) || - (proj == pn_Call_X_except && mode == mode_X) || - (proj == pn_Call_T_result && mode == mode_T) || - (proj == pn_Call_M_except && mode == mode_M) || - (proj == pn_Call_P_value_res_base && mode == mode_P)), - "wrong Proj from FuncCall", 0, - show_proj_failure(p); - ); break; case iro_Quot: @@ -334,7 +355,7 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { (proj == pn_Div_X_except && mode == mode_X) || (proj == pn_Div_res && mode_is_int(mode))), "wrong Proj from Div or Mod", 0, - show_proj_failure(p); + show_proj_failure(p); ); break; @@ -358,38 +379,31 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { case iro_Load: if (proj == pn_Load_res) { - ir_node *ptr = get_Load_ptr(pred); - entity *ent = NULL; - if (get_irn_op(ptr) == op_Sel) { - ent = get_Sel_entity(ptr); - } /* - We may not test this, after lowering and optimization the Const can - have an unexpected type. - else if ((get_irn_op(ptr) == op_Const) && - tarval_is_entity(get_Const_tarval(ptr))) { - ent = get_tarval_entity(get_Const_tarval(ptr)); - } */ - if (ent) { - ASSERT_AND_RET_DBG( - (mode == get_type_mode(get_entity_type(ent))), - "wrong data Proj from Load, entity type_mode failed", 0, - show_proj_failure_ent(p, ent); - ); - } - else { - ASSERT_AND_RET_DBG( - mode_is_data(mode), - "wrong data Proj from Load", 0, - show_proj_failure(p); - ); - } + ir_node *ptr = get_Load_ptr(pred); + entity *ent = get_ptr_entity(ptr); + + if (vrfy_entities && ent && get_irg_phase_state(current_ir_graph) == phase_high) { + /* do NOT check this for lowered phases, see comment on Store */ + ASSERT_AND_RET_DBG( + (mode == get_type_mode(get_entity_type(ent))), + "wrong data Proj from Load, entity type_mode failed", 0, + show_proj_failure_ent(p, ent); + ); + } + else { + ASSERT_AND_RET_DBG( + mode_is_data(mode) && mode == get_Load_mode(pred), + "wrong data Proj from Load", 0, + show_proj_failure(p); + ); + } } else { - ASSERT_AND_RET_DBG( - ((proj == pn_Load_M && mode == mode_M) || - (proj == pn_Load_X_except && mode == mode_X)), - "wrong Proj from Load", 0, - show_proj_failure(p); - ); + ASSERT_AND_RET_DBG( + ((proj == pn_Load_M && mode == mode_M) || + (proj == pn_Load_X_except && mode == mode_X)), + "wrong Proj from Load", 0, + show_proj_failure(p); + ); } break; @@ -398,7 +412,7 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { ((proj == pn_Store_M && mode == mode_M) || (proj == pn_Store_X_except && mode == mode_X)), "wrong Proj from Store", 0, - show_proj_failure(p); + show_proj_failure(p); ); break; @@ -426,31 +440,31 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { case iro_Start: mt = get_entity_type(get_irg_entity(irg)); - if (nr == pn_Start_T_args) { - ASSERT_AND_RET( - (proj >= 0 && mode_is_data(mode)), - "wrong Proj from Proj from Start", 0); - ASSERT_AND_RET( - (proj < get_method_n_params(mt)), - "More Projs for args than args in type", 0 - ); - if ((mode_is_reference(mode)) && is_compound_type(get_method_param_type(mt, proj))) - /* value argument */ break; - + if (nr == pn_Start_T_args) { + ASSERT_AND_RET( + (proj >= 0 && mode_is_data(mode)), + "wrong Proj from Proj from Start", 0); + ASSERT_AND_RET( + (proj < get_method_n_params(mt)), + "More Projs for args than args in type", 0 + ); + if ((mode_is_reference(mode)) && is_compound_type(get_method_param_type(mt, proj))) + /* value argument */ break; + + ASSERT_AND_RET( + (mode == get_type_mode(get_method_param_type(mt, proj))), + "Mode of Proj from Start doesn't match mode of param type.", 0); + } + else if (nr == pn_Start_P_value_arg_base) { ASSERT_AND_RET( - (mode == get_type_mode(get_method_param_type(mt, proj))), - "Mode of Proj from Start doesn't match mode of param type.", 0); + (proj >= 0 && mode_is_reference(mode)), + "wrong Proj from Proj from Start", 0 + ); + ASSERT_AND_RET( + (proj < get_method_n_params(mt)), + "More Projs for args than args in type", 0 + ); } - else if (nr == pn_Start_P_value_arg_base) { - ASSERT_AND_RET( - (proj >= 0 && mode_is_reference(mode)), - "wrong Proj from Proj from Start", 0 - ); - ASSERT_AND_RET( - (proj < get_method_n_params(mt)), - "More Projs for args than args in type", 0 - ); - } break; case iro_Call: @@ -471,28 +485,14 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { } break; - case iro_FuncCall: - { - ASSERT_AND_RET( - (proj >= 0 && mode_is_data(mode)), - "wrong Proj from Proj from FuncCall", 0); - mt = get_FuncCall_type(pred); - ASSERT_AND_RET( - (proj < get_method_n_ress(mt)), - "More Projs for results than results in type.", 0); - if ((mode_is_reference(mode)) && is_compound_type(get_method_res_type(mt, proj))) - /* value result */ break; - - ASSERT_AND_RET( - (mode == get_type_mode(get_method_res_type(mt, proj))), - "Mode of Proj from FuncCall doesn't match mode of result type.", 0); - } - break; - case iro_Tuple: /* We don't test */ break; + case iro_Bad: + /* hmm, optimization did not remove it */ + break; + default: ASSERT_AND_RET(0, "Unknown opcode", 0); } @@ -535,7 +535,7 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) if (!opt_do_node_verification) return 1; - if (! interprocedural_view) { + if (! get_interprocedural_view()) { /* * do NOT check placement in interprocedural view, as we don't always know * the "right" graph ... @@ -549,12 +549,12 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) opcode = get_irn_opcode(n); - /* We don't want to test nodes whose predecessors are Bad or Unknown, + /* We don't want to test nodes whose predecessors are Bad, as we would have to special case that for each operation. */ if (opcode != iro_Phi && opcode != iro_Block) for (i = 0; i < get_irn_arity(n); i++) { opcode1 = get_irn_opcode(get_irn_n(n, i)); - if (opcode1 == iro_Bad /*|| opcode1 == iro_Unknown*/) /* GL: for analyses mode must be correct. */ + if (opcode1 == iro_Bad) return 1; } @@ -585,7 +585,7 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) "End Block node", 0); } /* irg attr must == graph we are in. */ - if (! interprocedural_view) { + if (! get_interprocedural_view()) { ASSERT_AND_RET(((get_irn_irg(n) && get_irn_irg(n) == irg)), "Block node has wrong irg attribute", 0); } @@ -667,25 +667,24 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) ); break; - case iro_Const: { - ASSERT_AND_RET( - /* Const: BB --> data */ - (mode_is_data (mymode) || - mymode == mode_b) /* we want boolean constants for static evaluation */ - ,"Const node", 0 /* of Cmp. */ - ); - } break; - + case iro_Const: { + ASSERT_AND_RET( + /* Const: BB --> data */ + (mode_is_data (mymode) || + mymode == mode_b) /* we want boolean constants for static evaluation */ + ,"Const node", 0 /* of Cmp. */ + ); + } break; case iro_SymConst: if (get_SymConst_kind(n) == symconst_addr_ent) { - entity *ent = get_SymConst_entity(n); - if (is_method_type(get_entity_type(ent)) && - get_irn_irg(n) != get_const_code_irg()) { -#if 0 - ASSERT_AND_RET((get_entity_peculiarity(ent) != peculiarity_description), - "A constant must address an existing method.", 0); + entity *ent = get_SymConst_entity(n); + if (is_method_type(get_entity_type(ent)) && + get_irn_irg(n) != get_const_code_irg()) { +#if 1 + ASSERT_AND_RET((get_entity_peculiarity(ent) != peculiarity_description), + "A constant must address an existing method.", 0); #endif - } + } } ASSERT_AND_RET( /* SymConst: BB --> int*/ @@ -722,12 +721,17 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) /* Call: BB x M x ref x data1 x ... x datan --> M x datan+1 x ... x data n+m */ ASSERT_AND_RET( op1mode == mode_M && mode_is_reference(op2mode), "Call node", 0 ); /* operand M x ref */ + + mt = get_Call_type(n); + if(get_unknown_type() == mt) { + break; + } + for (i=3; i < get_irn_arity(n); i++) { ASSERT_AND_RET( mode_is_data(get_irn_mode(in[i])), "Call node", 0 ); /* operand datai */ }; ASSERT_AND_RET( mymode == mode_T, "Call result not a tuple", 0 ); /* result T */ /* Compare arguments of node with those of type */ - mt = get_Call_type(n); if (get_method_variadicity(mt) == variadicity_variadic) { ASSERT_AND_RET_DBG( @@ -746,24 +750,32 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) } for (i = 0; i < get_method_n_params(mt); i++) { - type *t = get_method_param_type(mt, i); + type *t = get_method_param_type(mt, i); - if (is_atomic_type(t)) { - ASSERT_AND_RET_DBG( - get_irn_mode(get_Call_param(n, i)) == get_type_mode(t), - "Mode of arg for Call doesn't match mode of arg type.", 0, - show_call_param(n, mt); - ); - } - else { - /* call with a compound type, mode must be reference */ - ASSERT_AND_RET_DBG( - mode_is_reference(get_irn_mode(get_Call_param(n, i))), - "Mode of arg for Call doesn't match mode of arg type.", 0, - show_call_param(n, mt); - ); - } + if (is_atomic_type(t)) { + ASSERT_AND_RET_DBG( + get_irn_mode(get_Call_param(n, i)) == get_type_mode(t), + "Mode of arg for Call doesn't match mode of arg type.", 0, + show_call_param(n, mt); + ); + } + else { + /* call with a compound type, mode must be reference */ + ASSERT_AND_RET_DBG( + mode_is_reference(get_irn_mode(get_Call_param(n, i))), + "Mode of arg for Call doesn't match mode of arg type.", 0, + show_call_param(n, mt); + ); + } } + +#if 0 + if (Call_has_callees(n)) { + for (i = 0; i < get_Call_n_callees(n); i++) { + ASSERT_AND_RET(is_entity(get_Call_callee(n, i)), "callee array must contain entities.", 0); + } + } +#endif break; case iro_Add: @@ -992,6 +1004,18 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) break; case iro_Phi: + { + ir_node *block = get_nodes_block(n); + + if (! is_Bad(block) && get_irg_phase_state(get_irn_irg(n)) != phase_building) { + /* a Phi node MUST have the same number of inputs as its block */ + ASSERT_AND_RET_DBG( + get_irn_arity(n) == get_irn_arity(block), + "wrong number of inputs in Phi node", 0, + show_phi_inputs(n, block); + ); + } + /* Phi: BB x dataM^n --> dataM */ for (i = 1; i < get_irn_arity(n); i++) { if (!is_Bad(in[i]) && (get_irn_op(in[i]) != op_Unknown)) @@ -1003,7 +1027,7 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) }; ASSERT_AND_RET( mode_is_dataM(mymode), "Phi node", 0 ); break; - + } case iro_Load: op1mode = get_irn_mode(in[1]); op2mode = get_irn_mode(in[2]); @@ -1031,7 +1055,9 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) break; - case iro_Store: + case iro_Store: { + entity *target; + op1mode = get_irn_mode(in[1]); op2mode = get_irn_mode(in[2]); op3mode = get_irn_mode(in[3]); @@ -1041,7 +1067,20 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) "Store node", 0 ); ASSERT_AND_RET(mymode == mode_T, "Store node", 0); + + target = get_ptr_entity(in[2]); + if (vrfy_entities && target && get_irg_phase_state(current_ir_graph) == phase_high) { + /* + * If lowered code, any Sels that add 0 may be removed, causing + * an direct access to entities of array or compound type. + * Prevent this by checking the phase. + */ + ASSERT_AND_RET( op3mode == get_type_mode(get_entity_type(target)), + "Store node", 0); + } + break; + } case iro_Alloc: op1mode = get_irn_mode(in[1]); @@ -1093,6 +1132,20 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) ); break; + case iro_Mux: + op1mode = get_irn_mode(in[1]); + op2mode = get_irn_mode(in[2]); + op3mode = get_irn_mode(in[3]); + ASSERT_AND_RET( + /* Mux: BB x b x numP x numP --> numP */ + op1mode == mode_b && + op2mode == mymode && + op3mode == mymode && + mode_is_numP(mymode), + "Mux node", 0 + ); + break; + default: break; } @@ -1133,7 +1186,7 @@ int irg_vrfy(ir_graph *irg) assert(get_irg_pinned(irg) == op_pin_state_pinned); - irg_walk(irg->end, vrfy_wrap, NULL, &res); + irg_walk_graph(irg, vrfy_wrap, NULL, &res); current_ir_graph = rem; @@ -1163,3 +1216,114 @@ int irn_vrfy_irg_dump(ir_node *n, ir_graph *irg, const char **bad_string) return res; } + + +typedef struct _vrfy_bad_env_t { + int flags; + int res; +} vrfy_bad_env_t; + +static void check_bads(ir_node *node, void *env) +{ + vrfy_bad_env_t *venv = env; + int i, arity = get_irn_arity(node); + + if (is_Block(node)) { + if ((venv->flags & BAD_CF) == 0) { + + /* check for Bad Block predecessor */ + for (i = 0; i < arity; ++i) { + ir_node *pred = get_irn_n(node, i); + + if (is_Bad(pred)) { + venv->res |= BAD_CF; + + if (opt_do_node_verification == NODE_VERIFICATION_REPORT) { + fprintf(stderr, "irg_vrfy_bads: Block %ld has Bad predecessor\n", get_irn_node_nr(node)); + } + if (opt_do_node_verification == NODE_VERIFICATION_ON) { + assert(0 && "Bad CF detected"); + } + } + } + } + } + else { + if ((venv->flags & BAD_BLOCK) == 0) { + + /* check for Bad Block */ + if (is_Bad(get_nodes_block(node))) { + venv->res |= BAD_BLOCK; + + if (opt_do_node_verification == NODE_VERIFICATION_REPORT) { + fprintf(stderr, "irg_vrfy_bads: node %ld has Bad Block\n", get_irn_node_nr(node)); + } + if (opt_do_node_verification == NODE_VERIFICATION_ON) { + assert(0 && "Bad CF detected"); + } + } + } + + if ((venv->flags & TUPLE) == 0) { + if (get_irn_op(node) == op_Tuple) { + venv->res |= TUPLE; + + if (opt_do_node_verification == NODE_VERIFICATION_REPORT) { + fprintf(stderr, "irg_vrfy_bads: node %ld is a Tuple\n", get_irn_node_nr(node)); + } + if (opt_do_node_verification == NODE_VERIFICATION_ON) { + assert(0 && "Tuple detected"); + } + } + } + + for (i = 0; i < arity; ++i) { + ir_node *pred = get_irn_n(node, i); + + if (is_Bad(pred)) { + /* check for Phi with Bad inputs */ + if (is_Phi(node) && !is_Bad(get_nodes_block(node)) && is_Bad(get_irn_n(get_nodes_block(node), i))) { + if (venv->flags & BAD_CF) + continue; + else { + venv->res |= BAD_CF; + + if (opt_do_node_verification == NODE_VERIFICATION_REPORT) { + fprintf(stderr, "irg_vrfy_bads: Phi %ld has Bad Input\n", get_irn_node_nr(node)); + } + if (opt_do_node_verification == NODE_VERIFICATION_ON) { + assert(0 && "Bad CF detected"); + } + } + } + + /* Bad node input */ + if ((venv->flags & BAD_DF) == 0) { + venv->res |= BAD_DF; + + if (opt_do_node_verification == NODE_VERIFICATION_REPORT) { + fprintf(stderr, "irg_vrfy_bads: node %ld has Bad Input\n", get_irn_node_nr(node)); + } + if (opt_do_node_verification == NODE_VERIFICATION_ON) { + assert(0 && "Bad NON-CF detected"); + } + } + } + } + } +} + +/* + * verify occurance of bad nodes + */ +int irg_vrfy_bads(ir_graph *irg, int flags) +{ + vrfy_bad_env_t env; + + env.flags = flags; + env.res = 0; + + irg_walk_graph(irg, check_bads, NULL, &env); + + return env.res; +}