From 1d523ad26cd541494c1e6cd8dc4b0736f0adc2cf Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Thu, 26 Apr 2012 19:58:08 +0200 Subject: [PATCH] trverify: cleanup, check irg.entity == entity.irg --- include/libfirm/typerep.h | 33 +-- ir/tr/entity.c | 2 +- ir/tr/trverify.c | 473 ++++++++++++++------------------------ 3 files changed, 178 insertions(+), 330 deletions(-) diff --git a/include/libfirm/typerep.h b/include/libfirm/typerep.h index 4a8341d0e..55e4f8ab3 100644 --- a/include/libfirm/typerep.h +++ b/include/libfirm/typerep.h @@ -227,11 +227,9 @@ FIRM_API ir_entity *new_d_parameter_entity(ir_type *owner, size_t pos, * Check an entity. Currently, we check only if initialized constants * are build on the const irg graph. * - * @return - * 0 if no error encountered - * != 0 a trverify_error_codes code + * @return non-zero if no errors were found */ -FIRM_API int check_entity(ir_entity *ent); +FIRM_API int check_entity(const ir_entity *ent); /** * Copies the entity if the new_owner is different from the @@ -482,7 +480,7 @@ FIRM_API int is_irn_const_expression(ir_node *n); FIRM_API ir_node *copy_const_value(dbg_info *dbg, ir_node *n, ir_node *to_block); /** Returns initial value of entity with atomic type @p ent. */ -FIRM_API ir_node *get_atomic_ent_value(ir_entity *ent); +FIRM_API ir_node *get_atomic_ent_value(const ir_entity *ent); /** Sets initial value of entity with atomic type @p ent to node @p val. * @note @p val must be a node in the const_code graph */ FIRM_API void set_atomic_ent_value(ir_entity *ent, ir_node *val); @@ -1032,29 +1030,12 @@ FIRM_API void set_irp_class_cast_state(ir_class_cast_state state); /** Returns class cast state for the whole program. */ FIRM_API ir_class_cast_state get_irp_class_cast_state(void); -/** - * possible trverify() error codes - */ -enum trverify_error_codes { - no_error = 0, /**< no error */ - error_ent_not_cont, /**< overwritten entity not in superclass */ - error_null_mem, /**< compound contains NULL member */ - error_const_on_wrong_irg, /**< constant placed on wrong IRG */ - error_existent_entity_without_irg, /**< Method entities with pecularity_exist must have an irg */ - error_wrong_ent_overwrites, /**< number of entity overwrites exceeds number of class overwrites */ - error_inherited_ent_without_const, /**< inherited method entity not pointing to existent entity */ - error_glob_ent_allocation, /**< wrong allocation of a global entity */ - error_ent_const_mode, /**< Mode of constant in entity did not match entities type. */ - error_ent_wrong_owner /**< Mode of constant in entity did not match entities type. */ -}; - /** * Checks a type. * - * @return - * 0 if no error encountered + * @return non-zero if no errors were found */ -FIRM_API int check_type(ir_type *tp); +FIRM_API int check_type(const ir_type *tp); /** * Walks the type information and performs a set of sanity checks. @@ -1064,9 +1045,7 @@ FIRM_API int check_type(ir_type *tp); * - class types: doesn't have NULL members * - class types: all overwrites are existent in the super type * - * @return - * 0 if graph is correct - * else error code. + * @return 0 if no error encountered */ FIRM_API int tr_verify(void); diff --git a/ir/tr/entity.c b/ir/tr/entity.c index 5981e3cda..1e58292ad 100644 --- a/ir/tr/entity.c +++ b/ir/tr/entity.c @@ -492,7 +492,7 @@ void (set_entity_usage)(ir_entity *ent, ir_entity_usage flags) _set_entity_usage(ent, flags); } -ir_node *get_atomic_ent_value(ir_entity *entity) +ir_node *get_atomic_ent_value(const ir_entity *entity) { ir_initializer_t *initializer = get_entity_initializer(entity); diff --git a/ir/tr/trverify.c b/ir/tr/trverify.c index 6ba25245b..71577e913 100644 --- a/ir/tr/trverify.c +++ b/ir/tr/trverify.c @@ -33,279 +33,146 @@ #include "tv.h" #include "ircons.h" -#ifdef NDEBUG -/* - * in RELEASE mode, returns ret if the expression expr evaluates to zero - * in ASSERT mode, asserts the expression expr (and the string string). - */ -#define ASSERT_AND_RET(expr, string, ret) if (!(expr)) return (ret) +static void report_error(const char *fmt, ...) +{ + va_list ap; -/* - * in RELEASE mode, returns ret if the expression expr evaluates to zero - * in ASSERT mode, executes blk if the expression expr evaluates to zero and asserts expr - */ -#define ASSERT_AND_RET_DBG(expr, string, ret, blk) if (!(expr)) return (ret) -#else -#define ASSERT_AND_RET(expr, string, ret) \ -do { \ - if (opt_do_node_verification == FIRM_VERIFICATION_ON) {\ - assert((expr) && string); } \ - if (!(expr)) { \ - if (opt_do_node_verification == FIRM_VERIFICATION_REPORT) \ - fprintf(stderr, #expr " : " string "\n"); \ - firm_verify_failure_msg = #expr " && " string; \ - return (ret); \ - } \ -} while (0) - -#define ASSERT_AND_RET_DBG(expr, string, ret, blk) \ -do { \ - if (!(expr)) { \ - firm_verify_failure_msg = #expr " && " string; \ - if (opt_do_node_verification != FIRM_VERIFICATION_ERROR_ONLY) { blk; } \ - if (opt_do_node_verification == FIRM_VERIFICATION_REPORT) \ - fprintf(stderr, #expr " : " string "\n"); \ - else if (opt_do_node_verification == FIRM_VERIFICATION_ON) { \ - assert((expr) && string); \ - } \ - return (ret); \ - } \ -} while (0) - -#endif /* NDEBUG */ - -#ifndef NDEBUG - -static const char *firm_verify_failure_msg; - -#if 0 -/** - * Show diagnostic if an entity overwrites another one not - * in direct superclasses. - */ -static void show_ent_not_supertp(ir_entity *ent, ir_entity *ovw) + fprintf(stderr, "Verify warning: "); + va_start(ap, fmt); + ir_vfprintf(stderr, fmt, ap); + va_end(ap); + fputc('\n', stderr); +} + +static bool check_class_member(const ir_type *tp, const ir_entity *entity) { - ir_type *owner = get_entity_owner(ent); - ir_type *ov_own = get_entity_owner(ovw); - size_t i; - - fprintf(stderr, "Type verification error:\n"); - ir_fprintf(stderr, "Entity %+F::%+e owerwrites ", owner, ent); - ir_fprintf(stderr, "Entity %+F::%+e\n", ov_own, ovw); - - ir_fprintf(stderr, "Supertypes of %+F:\n", owner); - for (i = 0; i < get_class_n_supertypes(owner); ++i) { - ir_type *super = get_class_supertype(owner, i); - ir_fprintf(stderr, " %+F:\n", super); + bool fine = true; + if (get_entity_n_overwrites(entity) > get_class_n_supertypes(tp)) { + report_error("member %+F of %+F has too many overwrites", entity, tp); + fine = false; } + return fine; } -#endif -/** - * Show diagnostic if an entity overwrites a wrong number of things. - */ -static void show_ent_overwrite_cnt(ir_entity *ent) +static bool check_compound_type(const ir_type *tp) { - ir_type *owner = get_entity_owner(ent); + bool fine = true; + bool is_class = is_Class_type(tp); + size_t n = get_compound_n_members(tp); size_t i; - size_t j; - size_t k; - bool found; - bool show_stp = false; - - fprintf(stderr, "Type verification error:\n"); - ir_fprintf(stderr, "Entity %t::%e owerwrites\n", owner, ent); - for (i = 0; i < get_entity_n_overwrites(ent); ++i) { - ir_entity *ovw = get_entity_overwrites(ent, i); - ir_type *ov_own = get_entity_owner(ovw); - size_t n_supertypes = get_class_n_supertypes(owner); - - ir_fprintf(stderr, " %t::%e\n", ov_own, ovw); - for (k = 0; k < i; ++k) { - if (ovw == get_entity_overwrites(ent, k)) { - ir_fprintf(stderr, " ->%t::%e entered more than once\n", ov_own, ovw); - break; - } - } - found = false; - for (j = 0; j < n_supertypes; ++j) { - if (ov_own == get_class_supertype(owner, j)) { - show_stp = found = true; - break; - } - } - if (! found) - ir_fprintf(stderr, " ->%t not in super types of %t\n", ov_own, owner); - } + for (i = 0; i < n; ++i) { + ir_entity *member = get_compound_member(tp, i); + ir_type *owner; - if (show_stp) { - ir_fprintf(stderr, "Supertypes of %t:\n", owner); - for (i = 0; i < get_class_n_supertypes(owner); ++i) { - ir_type *super = get_class_supertype(owner, i); - ir_fprintf(stderr, " %t:\n", super); + if (member == NULL) { + report_error("%+F has a NULL member\n", tp); + fine = false; + continue; + } + owner = get_entity_owner(member); + if (owner != tp) { + report_error("member %+F of %+F has owner %+F\n", member, tp, owner); + fine = false; + } + if (is_class) { + fine &= check_class_member(tp, member); } } + return fine; } -#endif /* #ifndef NDEBUG */ - -/** - * Check a class - */ -static int check_class(ir_type *tp) +static bool check_array_type(const ir_type *tp) { - size_t i, n; - - for (i = 0, n = get_class_n_members(tp); i < n; ++i) { - ir_entity *mem = get_class_member(tp, i); - - ASSERT_AND_RET_DBG( - tp == get_entity_owner(mem), - "class member with wrong owner", - error_ent_wrong_owner, - ir_fprintf(stderr, "Type verification error:\n%+F %+e(owner %+F)\n",tp, mem, get_entity_owner(mem)) - ); - ASSERT_AND_RET_DBG( - mem, - "NULL members not allowed", - error_null_mem, - ir_fprintf(stderr, "Type verification error:\n%+F member %zu is NULL\n", tp, i) - ); - - ASSERT_AND_RET_DBG( - get_entity_n_overwrites(mem) <= get_class_n_supertypes(tp), - "wrong number of entity overwrites", - error_wrong_ent_overwrites, - show_ent_overwrite_cnt(mem) - ); - -#if 0 - { - size_t j, m; - /* check if the overwrite relation is flat, i.e. every overwrite - * is visible in every direct superclass. */ - for (j = 0, m = get_entity_n_overwrites(mem); j < m; ++j) { - ir_entity *ovw = get_entity_overwrites(mem, j); - size_t k, n_super; - - /* Check whether ovw is member of one of tp's supertypes. If so, - the representation is correct. */ - for (k = 0, n_super = get_class_n_supertypes(tp); k < n_super; ++k) { - if (get_class_member_index(get_class_supertype(tp, k), ovw) != INVALID_MEMBER_INDEX) { - ASSERT_AND_RET_DBG( - 0, - "overwrites an entity not contained in direct supertype", - error_ent_not_cont, - show_ent_not_supertp(mem, ovw) - ); - break; - } - } - } + bool fine = true; + size_t n_dim = get_array_n_dimensions(tp); + size_t i; + + for (i = 0; i < n_dim; ++i) { + if (!has_array_lower_bound(tp, i) && !has_array_upper_bound(tp, i)) { + report_error("missing array bound in %+F in dimension %zu", tp, i); + fine = false; } -#endif } - return 0; + return fine; } -/** - * Check an array. - */ -static int check_array(const ir_type *tp) +static bool check_type_mode(const ir_type *tp) { - size_t i, n_dim = get_array_n_dimensions(tp); - - for (i = 0; i < n_dim; ++i) { - ASSERT_AND_RET_DBG( - has_array_lower_bound(tp, i) || has_array_upper_bound(tp, i), - "array bound missing", - 1, - ir_fprintf(stderr, "%+F in dimension %zu\n", tp, i) - ); + bool fine = true; + if (get_type_mode(tp) == NULL) { + report_error("type %+F has no mode", tp); + fine = false; } - return 0; + return fine; } +static bool check_primitive_type(const ir_type *tp) +{ + return check_type_mode(tp); +} -/** - * Check a primitive. - */ -static int check_primitive(ir_type *tp) +static bool check_pointer_type(const ir_type *tp) { - ASSERT_AND_RET_DBG( - is_mode(get_type_mode(tp)), - "Primitive type without mode", - 1, - ir_fprintf(stderr, "%+F\n", tp) - ); - return 0; + return check_type_mode(tp); } -int check_type(ir_type *tp) +int check_type(const ir_type *tp) { switch (get_type_tpop_code(tp)) { - case tpo_class: - return check_class(tp); - case tpo_array: - return check_array(tp); - case tpo_primitive: - return check_primitive(tp); - default: break; + case tpo_union: + case tpo_struct: + case tpo_class: return check_compound_type(tp); + case tpo_array: return check_array_type(tp); + case tpo_primitive: return check_primitive_type(tp); + case tpo_pointer: return check_pointer_type(tp); + case tpo_enumeration: + case tpo_method: + case tpo_uninitialized: + case tpo_unknown: + case tpo_none: + case tpo_code: + break; } - return 0; + return true; } -/** - * checks the visited flag - */ -static int check_visited_flag(ir_graph *irg, ir_node *n) +static bool check_visited_flag(ir_graph *irg, ir_node *n) { - ASSERT_AND_RET_DBG( - get_irn_visited(n) <= get_irg_visited(irg), - "Visited flag of node is larger than that of corresponding irg.", - 0, - ir_fprintf(stderr, "%+F in %+F\n", n, irg) - ); - return 1; + bool fine = true; + if (get_irn_visited(n) > get_irg_visited(irg)) { + report_error("visited flag of %+F is larger than that of corresponding irg %+F", n, irg); + fine = false; + } + return fine; } -/** - * helper environment struct for constant_on_wrong_obstack() - */ typedef struct myenv { - int res; ir_graph *irg; + bool fine; } myenv; -/** - * called by the walker - */ static void on_irg_storage(ir_node *n, void *data) { myenv *env = (myenv*)data; /* We also test whether the setting of the visited flag is legal. */ - env->res = node_is_in_irgs_storage(env->irg, n) && - check_visited_flag(env->irg, n); + env->fine &= node_is_in_irgs_storage(env->irg, n); + env->fine &= check_visited_flag(env->irg, n); } -/** - * checks whether a given constant IR node is NOT on the - * constant IR graph. - */ -static int constant_on_wrong_irg(ir_node *n) +static bool constant_on_wrong_irg(ir_node *n) { myenv env; - env.res = 1; /* on right obstack */ - env.irg = get_const_code_irg(); + env.fine = true; + env.irg = get_const_code_irg(); irg_walk(n, on_irg_storage, NULL, (void *)&env); - return ! env.res; + return env.fine; } -static int initializer_constant_on_wrong_irg(ir_initializer_t *initializer) +static bool initializer_constant_on_wrong_irg(const ir_initializer_t *initializer) { switch (get_initializer_kind(initializer)) { case IR_INITIALIZER_NULL: @@ -315,64 +182,60 @@ static int initializer_constant_on_wrong_irg(ir_initializer_t *initializer) case IR_INITIALIZER_CONST: return constant_on_wrong_irg(get_initializer_const_value(initializer)); case IR_INITIALIZER_COMPOUND: { - size_t i, n = get_initializer_compound_n_entries(initializer); + bool fine = true; + size_t n = get_initializer_compound_n_entries(initializer); + size_t i; for (i = 0; i < n; ++i) { - ir_initializer_t *sub + const ir_initializer_t *sub = get_initializer_compound_value(initializer, i); - if (initializer_constant_on_wrong_irg(sub)) - return 1; + fine &= initializer_constant_on_wrong_irg(sub); } - return 0; + return fine; } } panic("invalid initializer in initializer_on_wrong_irg"); } -/** - * Check if constants node are NOT on the constant IR graph. - * - * @return NON-zero if an entity initializer constant is NOT on - * the current_ir_graph's obstack. - */ -static int constants_on_wrong_irg(ir_entity *ent) +static bool constants_on_wrong_irg(const ir_entity *ent) { if (ent->initializer != NULL) { return initializer_constant_on_wrong_irg(ent->initializer); } else if (entity_has_compound_ent_values(ent)) { - size_t i, n; - for (i = 0, n = get_compound_ent_n_values(ent); i < n; ++i) { - if (constant_on_wrong_irg(get_compound_ent_value(ent, i))) - return 1; + bool fine = true; + size_t n = get_compound_ent_n_values(ent); + size_t i; + for (i = 0; i < n; ++i) { + fine &= constant_on_wrong_irg(get_compound_ent_value(ent, i)); } + return fine; } - return 0; + return true; } -int check_entity(ir_entity *ent) +int check_entity(const ir_entity *ent) { - ir_type *tp = get_entity_type(ent); - - current_ir_graph = get_const_code_irg(); - ASSERT_AND_RET_DBG( - constants_on_wrong_irg(ent) == 0, - "Contants placed on wrong IRG", - error_const_on_wrong_irg, - ir_fprintf(stderr, "%+e not on %+F\n", ent, current_ir_graph) - ); - - /* Originally, this test assumed, that only method entities have - pecularity_inherited. As I changed this, I have to test for method type - before doing the test. */ - if (get_entity_peculiarity(ent) == peculiarity_existent - && is_method_entity(ent)) { - - ir_entity *impl = get_SymConst_entity(get_atomic_ent_value(ent)); - ASSERT_AND_RET_DBG( - impl != NULL, - "inherited method entities must have constant pointing to existent entity.", - error_inherited_ent_without_const, - ir_fprintf(stderr, "%+e points to %+e\n", ent, impl) - ); + bool fine = true; + ir_type *tp = get_entity_type(ent); + + fine &= constants_on_wrong_irg(ent); + + if (is_method_entity(ent)) { + ir_graph *irg = get_entity_irg(ent); + if (irg != NULL) { + ir_entity *irg_entity = get_irg_entity(irg); + if (irg_entity != ent) { + report_error("entity(%+F)->irg->entity(%+F) relation invalid", + ent, irg_entity); + fine = false; + } + } + if (get_entity_peculiarity(ent) == peculiarity_existent) { + ir_entity *impl = get_SymConst_entity(get_atomic_ent_value(ent)); + if (impl == NULL) { + report_error("inherited method entity %+F must have constant pointing to existent entity.", ent); + fine = false; + } + } } if (is_atomic_entity(ent) && ent->initializer != NULL) { @@ -389,88 +252,94 @@ int check_entity(ir_entity *ent) case IR_INITIALIZER_COMPOUND: break; } - ASSERT_AND_RET_DBG( - mode == NULL || mode == get_type_mode(tp), - "Mode of constant in entity must match type.", - error_ent_const_mode, - ir_fprintf(stderr, "%+e, type %+F(%+F)\n", - ent, tp, get_type_mode(tp)) - ); + if (mode != NULL && mode != get_type_mode(tp)) { + report_error("initializer of entity %+F has wrong mode.", ent); + fine = false; + } } - return no_error; + return fine; } -/* - * check types and entities - */ static void check_tore(type_or_ent tore, void *env) { - int *res = (int*)env; - assert(tore.ent); + bool *fine = (bool*)env; + if (is_type(tore.typ)) { - *res = check_type(tore.typ); + *fine &= check_type(tore.typ); } else { assert(is_entity(tore.ent)); - *res = check_entity(tore.ent); + *fine &= check_entity(tore.ent); } } int tr_verify(void) { - static ident *empty = NULL; - int res = no_error; + bool fine = true; ir_type *constructors; ir_type *destructors; ir_type *thread_locals; size_t i, n; ir_segment_t s; - if (empty == NULL) - empty = new_id_from_chars("", 0); - - type_walk(check_tore, NULL, &res); + type_walk(check_tore, NULL, &fine); for (s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) { const ir_type *type = get_segment_type(s); size_t e; for (e = 0; e < get_compound_n_members(type); ++e) { ir_entity *entity = get_compound_member(type, e); - ASSERT_AND_RET(get_entity_ld_ident(entity) != NULL || - get_entity_visibility(entity) == ir_visibility_private, - "segment members must have a name or visibility_private", - 1); + if (get_entity_ld_ident(entity) == NULL && + get_entity_visibility(entity) != ir_visibility_private) { + report_error("public segment member %+F has no name", + entity); + fine = false; + } } } constructors = get_segment_type(IR_SEGMENT_CONSTRUCTORS); for (i = 0, n = get_compound_n_members(constructors); i < n; ++i) { const ir_entity *entity = get_compound_member(constructors, i); - ASSERT_AND_RET(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER, - "entity without LINKAGE_HIDDEN_USER in constructors is pointless", - 1); + if ((get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER) == 0) { + report_error("entity %+F in constructors without LINKAGE_HIDDEN_USER", + entity); + fine = false; + } /* Mach-O doesn't like labels in this section */ - ASSERT_AND_RET(get_entity_ld_ident(entity), - "entity in constructors should have ld_ident=''", 1); + if (get_entity_ld_name(entity)[0] != '\0') { + report_error("entity %+F in constructors must not have an ld_name", + entity); + fine = false; + } } destructors = get_segment_type(IR_SEGMENT_DESTRUCTORS); for (i = 0, n = get_compound_n_members(destructors); i < n; ++i) { const ir_entity *entity = get_compound_member(destructors, i); - ASSERT_AND_RET(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER, - "entity without LINKAGE_HIDDEN_USER in destructors is pointless", - 1); + if ((get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER) == 0) { + report_error("entity %+F in destructors without LINKAGE_HIDDEN_USER", + entity); + fine = false; + } /* Mach-O doesn't like labels in this section */ - ASSERT_AND_RET(get_entity_ld_ident(entity), - "entity in destructors should have ld_ident=''", 1); + if (get_entity_ld_name(entity)[0] != '\0') { + report_error("entity %+F in destructors must not have an ld_name", + entity); + fine = false; + } } thread_locals = get_segment_type(IR_SEGMENT_THREAD_LOCAL); for (i = 0, n = get_compound_n_members(thread_locals); i < n; ++i) { const ir_entity *entity = get_compound_member(thread_locals, i); /* this is odd and should not be allowed I think */ - ASSERT_AND_RET(!is_method_entity(entity), - "method in THREAD_LOCAL segment", 1); - ASSERT_AND_RET(! (get_entity_linkage(entity) & IR_LINKAGE_CONSTANT), - "thread locals must not be constant", 1); + if (is_method_entity(entity)) { + report_error("method %+F in thread local segment"); + fine = false; + } + if (get_entity_linkage(entity) & IR_LINKAGE_CONSTANT) { + report_error("entity %+F in thread local segment is constant"); + fine = false; + } } - return res; + return fine; } -- 2.20.1