+/**
+ * called by the walker
+ */
+static void on_irg_storage(ir_node *n, void *env)
+{
+ struct myenv *myenv = env;
+
+ /* We also test whether the setting of the visited flag is legal. */
+ myenv->res = node_is_in_irgs_storage(myenv->irg, n) &&
+ check_visited_flag(myenv->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)
+{
+ struct myenv env;
+
+ env.res = 1; /* on right obstack */
+ env.irg = get_const_code_irg();
+
+ irg_walk(n, on_irg_storage, NULL, (void *)&env);
+ return ! env.res;
+}
+
+static int initializer_constant_on_wrong_irg(ir_initializer_t *initializer)
+{
+ switch (get_initializer_kind(initializer)) {
+ case IR_INITIALIZER_NULL:
+ return 0;
+ case IR_INITIALIZER_TARVAL:
+ return 0;
+ case IR_INITIALIZER_CONST:
+ return constant_on_wrong_irg(get_initializer_const_value(initializer));
+ case IR_INITIALIZER_COMPOUND: {
+ int n = get_initializer_compound_n_entries(initializer);
+ int i;
+ for (i = 0; i < n; ++i) {
+ ir_initializer_t *sub
+ = get_initializer_compound_value(initializer, i);
+ if (initializer_constant_on_wrong_irg(sub))
+ return 1;
+ }
+ return 0;
+ }
+ }
+ 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)
+{
+ if (ent->initializer != NULL) {
+ return initializer_constant_on_wrong_irg(ent->initializer);
+ } else if (entity_has_compound_ent_values(ent)) {
+ int i;
+ for (i = get_compound_ent_n_values(ent) - 1; i >= 0; --i) {
+ if (constant_on_wrong_irg(get_compound_ent_value(ent, i)))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * 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 trvrfy_error_codes code
+ */
+int check_entity(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)
+ );
+ }
+
+ if (is_atomic_entity(ent) && ent->initializer != NULL) {
+ ir_mode *mode = NULL;
+ ir_initializer_t *initializer = ent->initializer;
+ switch (initializer->kind) {
+ case IR_INITIALIZER_CONST:
+ mode = get_irn_mode(get_initializer_const_value(initializer));
+ break;
+ case IR_INITIALIZER_TARVAL:
+ mode = get_tarval_mode(get_initializer_tarval_value(initializer));
+ break;
+ case IR_INITIALIZER_NULL:
+ 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))
+ );
+ }
+ return no_error;
+}
+
+/*
+ * check types and entities
+ */
+static void check_tore(type_or_ent tore, void *env)
+{
+ int *res = env;
+ assert(tore.ent);
+ if (is_type(tore.typ)) {
+ *res = check_type(tore.typ);
+ } else {
+ assert(is_entity(tore.ent));
+ *res = check_entity(tore.ent);
+ }
+}
+
+/*
+ * Verify types and entities.
+ */
+int tr_vrfy(void)
+{
+ int res = no_error;
+ ir_type *constructors;
+ ir_type *destructors;
+ ir_type *thread_locals;
+ int i;
+ static ident *empty = NULL;
+
+ if (empty == NULL)
+ empty = new_id_from_chars("", 0);
+
+ type_walk(check_tore, NULL, &res);
+
+ constructors = get_segment_type(IR_SEGMENT_CONSTRUCTORS);
+ for (i = get_compound_n_members(constructors)-1; i >= 0; --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);
+ /* 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);
+ }
+ destructors = get_segment_type(IR_SEGMENT_DESTRUCTORS);
+ for (i = get_compound_n_members(destructors)-1; i >= 0; --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);
+ /* 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);
+ }
+ thread_locals = get_segment_type(IR_SEGMENT_THREAD_LOCAL);
+ for (i = get_compound_n_members(thread_locals)-1; i >= 0; --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);
+ }