X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firvrfy.c;h=722a7f357117baf1d71f1770895857fb36463aff;hb=cb91bddc9cacdab7c28e4336847bd3dc248aa549;hp=12104b66a8fd82e91e182be9eabaf2b8027df3ed;hpb=19a8e44d561f4eb9d766a790a007641086d00581;p=libfirm diff --git a/ir/ir/irvrfy.c b/ir/ir/irvrfy.c index 12104b66a..722a7f357 100644 --- a/ir/ir/irvrfy.c +++ b/ir/ir/irvrfy.c @@ -14,9 +14,11 @@ # include #endif +# include "irprog.h" # include "irgraph_t.h" # include "irvrfy.h" # include "irgwalk.h" +# include "irdump.h" #ifdef NDEBUG /* @@ -33,12 +35,13 @@ #else #define ASSERT_AND_RET(expr, string, ret) \ do { \ - bad_msg = #expr " && " string; \ - if (opt_do_node_verification == NODE_VERIFICATION_ON) \ - assert((expr) && string); \ + if (opt_do_node_verification == NODE_VERIFICATION_ON) {\ + if (!(expr)) 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"); \ + bad_msg = #expr " && " string; \ return (ret); \ } \ } while(0) @@ -58,30 +61,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; - -/** Borrowed from interprete.c -static entity *hunt_for_entity (ir_node *addr, ir_node *load) { - ir_op *op = get_irn_op(addr); - if (op == op_Sel) - return get_Sel_entity(addr); - if (op == op_Const) { - tarval *tv = get_Const_tarval(addr); - assert(tarval_is_entity(tv)); - return get_tarval_entity(tv); - } - - if(get_irn_opcode(load) == iro_Load) - return(NULL); - assert(0 && "unexpected address expression."); - return NULL; +/* enable verification of Load/Store entities */ +void vrfy_enable_entity_tests(int enable) +{ + vrfy_entities = enable; } -*/ + /** * little helper for NULL modes */ @@ -174,7 +168,7 @@ static void show_proj_failure_ent(ir_node *n, entity *ent) */ static void show_node_on_graph(ir_graph *irg, ir_node *n) { - entity *ent = get_irg_ent(irg); + entity *ent = get_irg_entity(irg); if (ent) fprintf(stderr, "\nFIRM: irn_vrfy_irg() of entity %s, node %ld %s%s\n", @@ -211,7 +205,7 @@ static void show_call_param(ir_node *n, type *mt) */ static void show_return_modes(ir_graph *irg, ir_node *n, type *mt, int i) { - entity *ent = get_irg_ent(irg); + entity *ent = get_irg_entity(irg); fprintf(stderr, "\nFIRM: irn_vrfy_irg() Return node %ld in entity \"%s\" mode %s different from type mode %s\n", get_irn_node_nr(n), get_entity_name(ent), @@ -225,7 +219,7 @@ static void show_return_modes(ir_graph *irg, ir_node *n, type *mt, int i) */ static void show_return_nres(ir_graph *irg, ir_node *n, type *mt) { - entity *ent = get_irg_ent(irg); + entity *ent = get_irg_entity(irg); fprintf(stderr, "\nFIRM: irn_vrfy_irg() Return node %ld in entity \"%s\" has %d results different from type %d\n", get_irn_node_nr(n), get_entity_name(ent), @@ -242,6 +236,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 */ @@ -251,8 +265,8 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { ir_mode *mode; int proj; - pred = skip_nop(get_Proj_pred(p)); - assert(get_irn_mode(pred) == mode_T); + pred = skip_Id(get_Proj_pred(p)); + ASSERT_AND_RET(get_irn_mode(pred) == mode_T, "mode of a 'projed' node is not Tuple", 0); mode = get_irn_mode(p); proj = get_Proj_proj(p); @@ -260,13 +274,13 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { case iro_Start: ASSERT_AND_RET_DBG( ( - (proj == pns_initial_exec && mode == mode_X) || - (proj == pns_global_store && mode == mode_M) || - (proj == pns_frame_base && mode_is_reference(mode)) || - (proj == pns_globals && mode_is_reference(mode)) || - (proj == pns_args && mode == mode_T) || - (proj == pns_value_arg_base && mode_is_reference(mode)) || - (proj == pns_value_arg_base && mode == mode_T) /* FIXME: only one of those */ + (proj == pn_Start_X_initial_exec && mode == mode_X) || + (proj == pn_Start_M && mode == mode_M) || + (proj == pn_Start_P_frame_base && mode_is_reference(mode)) || + (proj == pn_Start_P_globals && mode_is_reference(mode)) || + (proj == pn_Start_T_args && mode == mode_T) || + (proj == pn_Start_P_value_arg_base && mode_is_reference(mode)) || + (proj == pn_Start_P_value_arg_base && mode == mode_T) /* FIXME: only one of those */ ), "wrong Proj from Start", 0, show_proj_failure(p); @@ -275,9 +289,12 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { case iro_Cond: ASSERT_AND_RET_DBG( - (proj >= 0 && mode == mode_X), - "wrong Proj from Cond", 0, - show_proj_failure(p); + ( + (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); ); break; @@ -372,38 +389,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; @@ -412,7 +422,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; @@ -431,16 +441,16 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { case iro_Proj: { type *mt; /* A method type */ - long nr = get_Proj_proj(pred); + long nr = get_Proj_proj(pred); - pred = skip_nop(get_Proj_pred(pred)); + pred = skip_Id(get_Proj_pred(pred)); ASSERT_AND_RET((get_irn_mode(pred) == mode_T), "Proj from something not a tuple", 0); switch (get_irn_opcode(pred)) { case iro_Start: - mt = get_entity_type(get_irg_ent(irg)); + mt = get_entity_type(get_irg_entity(irg)); - if (nr == pns_args) { + if (nr == pn_Start_T_args) { ASSERT_AND_RET( (proj >= 0 && mode_is_data(mode)), "wrong Proj from Proj from Start", 0); @@ -455,7 +465,7 @@ vrfy_Proj_proj(ir_node *p, ir_graph *irg) { (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 == pns_value_arg_base) { + 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 @@ -563,12 +573,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; } @@ -647,7 +657,7 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) }; ASSERT_AND_RET( mymode == mode_X, "Result X", 0 ); /* result X */ /* Compare returned results with result types of method type */ - mt = get_entity_type(get_irg_ent(irg)); + mt = get_entity_type(get_irg_entity(irg)); ASSERT_AND_RET_DBG( get_Return_n_ress(n) == get_method_n_ress(mt), "Number of results for Return doesn't match number of results in type.", 0, show_return_nres(irg, n, mt);); @@ -681,16 +691,25 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) ); break; - case iro_Const: + 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; - + /* 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 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*/ (mode_is_int(mymode) || @@ -825,7 +844,7 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) op1mode = get_irn_mode(in[1]); ASSERT_AND_RET_DBG( /* Minus: BB x float --> float */ - op1mode == mymode && get_mode_sort(op1mode) == irms_float_number, "Minus node", 0, + op1mode == mymode && mode_is_float(op1mode), "Minus node", 0, show_unop_failure(n , "/* Minus: BB x float --> float */"); ); op_is_symmetric = 2; @@ -996,6 +1015,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)) @@ -1007,7 +1038,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]); @@ -1045,6 +1076,18 @@ int irn_vrfy_irg(ir_node *n, ir_graph *irg) "Store node", 0 ); ASSERT_AND_RET(mymode == mode_T, "Store node", 0); + + entity *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: @@ -1135,9 +1178,9 @@ int irg_vrfy(ir_graph *irg) rem = current_ir_graph; current_ir_graph = irg; - assert(get_irg_pinned(irg) == pinned); + 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; @@ -1167,3 +1210,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; +}