2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief Check types and entities for correctness.
10 * @author Michael Beck, Goetz Lindenmaier
14 #include "irgraph_t.h"
22 static void report_error(const char *fmt, ...)
26 fprintf(stderr, "Verify warning: ");
28 ir_vfprintf(stderr, fmt, ap);
33 static bool check_class_member(const ir_type *tp, const ir_entity *entity)
36 if (get_entity_n_overwrites(entity) > get_class_n_supertypes(tp)) {
37 report_error("member %+F of %+F has too many overwrites", entity, tp);
43 static bool check_compound_type(const ir_type *tp)
46 bool is_class = is_Class_type(tp);
47 size_t n = get_compound_n_members(tp);
50 for (i = 0; i < n; ++i) {
51 ir_entity *member = get_compound_member(tp, i);
55 report_error("%+F has a NULL member\n", tp);
59 owner = get_entity_owner(member);
61 report_error("member %+F of %+F has owner %+F\n", member, tp, owner);
65 fine &= check_class_member(tp, member);
71 static bool check_array_type(const ir_type *tp)
74 size_t n_dim = get_array_n_dimensions(tp);
77 for (i = 0; i < n_dim; ++i) {
78 if (!has_array_lower_bound(tp, i) && !has_array_upper_bound(tp, i)) {
79 report_error("missing array bound in %+F in dimension %zu", tp, i);
86 static bool check_type_mode(const ir_type *tp)
89 if (get_type_mode(tp) == NULL) {
90 report_error("type %+F has no mode", tp);
96 static bool check_primitive_type(const ir_type *tp)
98 return check_type_mode(tp);
101 static bool check_pointer_type(const ir_type *tp)
103 return check_type_mode(tp);
106 int check_type(const ir_type *tp)
108 switch (get_type_tpop_code(tp)) {
111 case tpo_class: return check_compound_type(tp);
112 case tpo_array: return check_array_type(tp);
113 case tpo_primitive: return check_primitive_type(tp);
114 case tpo_pointer: return check_pointer_type(tp);
115 case tpo_enumeration:
117 case tpo_uninitialized:
126 static bool check_visited_flag(ir_graph *irg, ir_node *n)
129 if (get_irn_visited(n) > get_irg_visited(irg)) {
130 report_error("visited flag of %+F is larger than that of corresponding irg %+F", n, irg);
136 typedef struct myenv {
141 static void on_irg_storage(ir_node *n, void *data)
143 myenv *env = (myenv*)data;
145 /* We also test whether the setting of the visited flag is legal. */
146 env->fine &= node_is_in_irgs_storage(env->irg, n);
147 env->fine &= check_visited_flag(env->irg, n);
150 static bool constant_on_wrong_irg(ir_node *n)
155 env.irg = get_const_code_irg();
157 irg_walk(n, on_irg_storage, NULL, (void *)&env);
161 static bool initializer_constant_on_wrong_irg(const ir_initializer_t *initializer)
163 switch (get_initializer_kind(initializer)) {
164 case IR_INITIALIZER_NULL:
166 case IR_INITIALIZER_TARVAL:
168 case IR_INITIALIZER_CONST:
169 return constant_on_wrong_irg(get_initializer_const_value(initializer));
170 case IR_INITIALIZER_COMPOUND: {
172 size_t n = get_initializer_compound_n_entries(initializer);
174 for (i = 0; i < n; ++i) {
175 const ir_initializer_t *sub
176 = get_initializer_compound_value(initializer, i);
177 fine &= initializer_constant_on_wrong_irg(sub);
182 panic("invalid initializer");
185 static bool constants_on_wrong_irg(const ir_entity *ent)
187 if (ent->initializer != NULL) {
188 return initializer_constant_on_wrong_irg(ent->initializer);
193 static bool check_external_linkage(const ir_entity *entity, ir_linkage linkage,
194 const char *linkage_name)
197 if ((get_entity_linkage(entity) & linkage) == 0)
199 if (get_entity_visibility(entity) != ir_visibility_external) {
200 report_error("entity %+F has IR_LINKAGE_%s but is not externally visible", entity, linkage_name);
203 if (!entity_has_definition(entity)) {
204 report_error("entity %+F has IR_LINKAGE_%s but is just a declaration", entity, linkage_name);
210 int check_entity(const ir_entity *entity)
213 ir_type *tp = get_entity_type(entity);
214 ir_linkage linkage = get_entity_linkage(entity);
216 fine &= constants_on_wrong_irg(entity);
218 if (is_method_entity(entity)) {
219 ir_graph *irg = get_entity_irg(entity);
221 ir_entity *irg_entity = get_irg_entity(irg);
222 if (irg_entity != entity) {
223 report_error("entity(%+F)->irg->entity(%+F) relation invalid",
228 if (get_entity_peculiarity(entity) == peculiarity_existent) {
229 ir_entity *impl = get_SymConst_entity(get_atomic_ent_value(entity));
231 report_error("inherited method entity %+F must have constant pointing to existent entity.", entity);
237 if (linkage & IR_LINKAGE_NO_CODEGEN) {
238 if (!is_method_entity(entity)) {
239 report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not a function", entity);
241 } else if (get_entity_irg(entity) == NULL) {
242 report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but has no ir-graph anyway", entity);
245 if (get_entity_visibility(entity) != ir_visibility_external) {
246 report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not externally visible", entity);
250 check_external_linkage(entity, IR_LINKAGE_WEAK, "WEAK");
251 check_external_linkage(entity, IR_LINKAGE_GARBAGE_COLLECT,
253 check_external_linkage(entity, IR_LINKAGE_MERGE, "MERGE");
255 if (is_atomic_entity(entity) && entity->initializer != NULL) {
256 ir_mode *mode = NULL;
257 ir_initializer_t *initializer = entity->initializer;
258 switch (initializer->kind) {
259 case IR_INITIALIZER_CONST:
260 mode = get_irn_mode(get_initializer_const_value(initializer));
262 case IR_INITIALIZER_TARVAL:
263 mode = get_tarval_mode(get_initializer_tarval_value(initializer));
265 case IR_INITIALIZER_NULL:
266 case IR_INITIALIZER_COMPOUND:
269 if (mode != NULL && mode != get_type_mode(tp)) {
270 report_error("initializer of entity %+F has wrong mode.", entity);
277 static void check_tore(type_or_ent tore, void *env)
279 bool *fine = (bool*)env;
281 if (is_type(tore.typ)) {
282 *fine &= check_type(tore.typ);
284 assert(is_entity(tore.ent));
285 *fine &= check_entity(tore.ent);
292 ir_type *constructors;
293 ir_type *destructors;
294 ir_type *thread_locals;
298 type_walk(check_tore, NULL, &fine);
300 for (s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
301 const ir_type *type = get_segment_type(s);
303 for (e = 0; e < get_compound_n_members(type); ++e) {
304 ir_entity *entity = get_compound_member(type, e);
305 if (get_entity_ld_ident(entity) == NULL &&
306 get_entity_visibility(entity) != ir_visibility_private) {
307 report_error("public segment member %+F has no name",
314 constructors = get_segment_type(IR_SEGMENT_CONSTRUCTORS);
315 for (i = 0, n = get_compound_n_members(constructors); i < n; ++i) {
316 const ir_entity *entity = get_compound_member(constructors, i);
317 if ((get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER) == 0) {
318 report_error("entity %+F in constructors without LINKAGE_HIDDEN_USER",
322 /* Mach-O doesn't like labels in this section */
323 if (get_entity_ld_name(entity)[0] != '\0') {
324 report_error("entity %+F in constructors must not have an ld_name",
329 destructors = get_segment_type(IR_SEGMENT_DESTRUCTORS);
330 for (i = 0, n = get_compound_n_members(destructors); i < n; ++i) {
331 const ir_entity *entity = get_compound_member(destructors, i);
332 if ((get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER) == 0) {
333 report_error("entity %+F in destructors without LINKAGE_HIDDEN_USER",
337 /* Mach-O doesn't like labels in this section */
338 if (get_entity_ld_name(entity)[0] != '\0') {
339 report_error("entity %+F in destructors must not have an ld_name",
344 thread_locals = get_segment_type(IR_SEGMENT_THREAD_LOCAL);
345 for (i = 0, n = get_compound_n_members(thread_locals); i < n; ++i) {
346 const ir_entity *entity = get_compound_member(thread_locals, i);
347 /* this is odd and should not be allowed I think */
348 if (is_method_entity(entity)) {
349 report_error("method %+F in thread local segment");
352 if (get_entity_linkage(entity) & IR_LINKAGE_CONSTANT) {
353 report_error("entity %+F in thread local segment is constant");