trvrfy.c 12.3 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

Michael Beck's avatar
Michael Beck committed
20
21
22
23
24
25
/**
 * @file    tr_inheritance.c
 * @brief   Check types and entities for correctness.
 * @date    29.1.2003
 * @author  Michael Beck, Goetz Lindenmaier
 * @version $Id$
26
 */
Michael Beck's avatar
Michael Beck committed
27
#include "config.h"
Götz Lindenmaier's avatar
new.  
Götz Lindenmaier committed
28

29
#include "irgraph_t.h"
30
31
32
#include "irflag_t.h"
#include "irprintf.h"
#include "irgwalk.h"
Matthias Braun's avatar
Matthias Braun committed
33
34
#include "error.h"
#include "tv.h"
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

#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)

/*
 * 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_vrfy_failure_msg = #expr " && " string; \
    return (ret); \
  } \
} while(0)

#define ASSERT_AND_RET_DBG(expr, string, ret, blk) \
do { \
  if (!(expr)) { \
    firm_vrfy_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 */
Götz Lindenmaier's avatar
new.  
Götz Lindenmaier committed
76

77
78
79
80
#ifndef NDEBUG

static const char *firm_vrfy_failure_msg;

81
82
83
84
/**
 * Show diagnostic if an entity overwrites another one not
 * in direct superclasses.
 */
Michael Beck's avatar
Michael Beck committed
85
86
87
88
89
90
91
92
93
94
95
96
97
98
static void show_ent_not_supertp(ir_entity *ent, ir_entity *ovw) {
	ir_type *owner = get_entity_owner(ent);
	ir_type *ov_own = get_entity_owner(ovw);
	int 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);
	}
99
100
101
}

/**
Michael Beck's avatar
Michael Beck committed
102
 * Show diagnostic if an entity overwrites a wrong number of things.
103
 */
Michael Beck's avatar
Michael Beck committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
static void show_ent_overwrite_cnt(ir_entity *ent) {
	ir_type *owner = get_entity_owner(ent);
	int i, j, k, found, show_stp = 0;

	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);

		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 = 0;
		for (j = get_class_n_supertypes(owner) - 1; j >= 0; --j) {
			if (ov_own == get_class_supertype(owner, j)) {
				show_stp = found = 1;
				break;
			}
		}
		if (! found)
			ir_fprintf(stderr, "  ->%t not in super types of %t\n", ov_own, 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);
		}
	}
139
140
}

141
142
#endif /* #ifndef NDEBUG */

143
144
145
/**
 * Check a class
 */
146
static int check_class(ir_type *tp) {
Michael Beck's avatar
Michael Beck committed
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
	int i, j, k;
	int found;

	for (i = get_class_n_members(tp) - 1; i >= 0; --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 %d 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)
		);

		for (j = get_entity_n_overwrites(mem) - 1; j >= 0; --j) {
			ir_entity *ovw = get_entity_overwrites(mem, j);
			/*printf(" overwrites: "); DDME(ovw);*/
			/* Check whether ovw is member of one of tp's supertypes. If so,
			the representation is correct. */
			found = 0;
			for (k = get_class_n_supertypes(tp) - 1; k >= 0; --k) {
				if (get_class_member_index(get_class_supertype(tp, k), ovw) >= 0) {
					found = 1;
					break;
				}
			}
			ASSERT_AND_RET_DBG(
				found,
				"overwrites an entity not contained in direct supertype",
				error_ent_not_cont,
				show_ent_not_supertp(mem, ovw)
			);
		}
	}
	return 0;
Götz Lindenmaier's avatar
new.  
Götz Lindenmaier committed
194
195
}

196
197
198
/**
 * Check an array.
 */
199
static int check_array(ir_type *tp) {
Michael Beck's avatar
Michael Beck committed
200
201
202
203
204
205
206
207
208
209
210
	int 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 %d\n", tp, i)
		);
	}
	return 0;
211
212
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
213
214
215
216

/**
 * Check a primitive.
 */
217
static int check_primitive(ir_type *tp) {
Michael Beck's avatar
Michael Beck committed
218
219
220
221
222
223
224
	ASSERT_AND_RET_DBG(
		is_mode(get_type_mode(tp)),
		"Primitive type without mode",
		1,
		ir_fprintf(stderr, "%+F\n", tp)
	);
	return 0;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
225
226
227
}


228
/*
229
230
 * Checks a type.
 *
231
232
 * return
 *  0   if no error encountered
233
 */
234
int check_type(ir_type *tp) {
Michael Beck's avatar
Michael Beck committed
235
236
237
238
239
240
241
242
243
244
	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;
	}
	return 0;
Götz Lindenmaier's avatar
new.  
Götz Lindenmaier committed
245
246
}

247
248
249
250
/**
 * checks the visited flag
 */
static int check_visited_flag(ir_graph *irg, ir_node *n) {
Michael Beck's avatar
Michael Beck committed
251
252
253
254
255
256
257
	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;
258
259
}

260
261
262
/**
 * helper environment struct for constant_on_wrong_obstack()
 */
263
struct myenv {
Michael Beck's avatar
Michael Beck committed
264
265
	int res;
	ir_graph *irg;
266
267
};

268
269
270
271
/**
 * called by the walker
 */
static void on_irg_storage(ir_node *n, void *env) {
Michael Beck's avatar
Michael Beck committed
272
	struct myenv *myenv = env;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
273

Michael Beck's avatar
Michael Beck committed
274
275
276
	/* 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);
277
278
}

279
/**
Michael Beck's avatar
Michael Beck committed
280
 * checks whether a given constant IR node is NOT on the
281
282
 * constant IR graph.
 */
Matthias Braun's avatar
Matthias Braun committed
283
284
static int constant_on_wrong_irg(ir_node *n)
{
Michael Beck's avatar
Michael Beck committed
285
	struct myenv env;
286

Michael Beck's avatar
Michael Beck committed
287
288
	env.res = 1;  /* on right obstack */
	env.irg = get_const_code_irg();
289

Michael Beck's avatar
Michael Beck committed
290
291
	irg_walk(n, on_irg_storage, NULL, (void *)&env);
	return ! env.res;
292
293
}

Matthias Braun's avatar
Matthias Braun committed
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
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");
}

Michael Beck's avatar
Michael Beck committed
318
/**
319
 * Check if constants node are NOT on the constant IR graph.
Michael Beck's avatar
Michael Beck committed
320
321
322
 *
 * @return NON-zero if an entity initializer constant is NOT on
 * the current_ir_graph's obstack.
323
 */
Matthias Braun's avatar
Matthias Braun committed
324
325
326
327
328
329
330
331
332
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;
Michael Beck's avatar
Michael Beck committed
333
334
335
		}
	}
	return 0;
336
}
Götz Lindenmaier's avatar
new.  
Götz Lindenmaier committed
337

338
339
340
341
342
/*
 * Check an entity. Currently, we check only if initialized constants
 * are build on the const irg graph.
 *
 * @return
Florian Liekweg's avatar
Florian Liekweg committed
343
 *  0   if no error encountered
344
 *  != 0    a trvrfy_error_codes code
345
 */
Matthias Braun's avatar
Matthias Braun committed
346
347
int check_entity(ir_entity *ent)
{
Michael Beck's avatar
Michael Beck committed
348
349
350
351
352
353
354
355
356
357
358
	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
Matthias Braun's avatar
Matthias Braun committed
359
360
361
362
	   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)) {
Michael Beck's avatar
Michael Beck committed
363

Matthias Braun's avatar
Matthias Braun committed
364
		ir_entity *impl = get_SymConst_entity(get_atomic_ent_value(ent));
Michael Beck's avatar
Michael Beck committed
365
		ASSERT_AND_RET_DBG(
Matthias Braun's avatar
Matthias Braun committed
366
367
368
369
			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)
Michael Beck's avatar
Michael Beck committed
370
371
372
		);
	}

Matthias Braun's avatar
Matthias Braun committed
373
374
375
376
377
378
379
380
381
382
383
384
385
	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;
Michael Beck's avatar
Michael Beck committed
386
		}
Matthias Braun's avatar
Matthias Braun committed
387
388
389
390
391
392
393
		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))
		);
Michael Beck's avatar
Michael Beck committed
394
395
	}
	return no_error;
Götz Lindenmaier's avatar
new.  
Götz Lindenmaier committed
396
397
}

398
399
400
/*
 * check types and entities
 */
401
static void check_tore(type_or_ent tore, void *env) {
Michael Beck's avatar
Michael Beck committed
402
	int *res = env;
403
404
405
	assert(tore.ent);
	if (is_type(tore.typ)) {
		*res = check_type(tore.typ);
Michael Beck's avatar
Michael Beck committed
406
	} else {
407
408
		assert(is_entity(tore.ent));
		*res = check_entity(tore.ent);
Michael Beck's avatar
Michael Beck committed
409
	}
Götz Lindenmaier's avatar
new.  
Götz Lindenmaier committed
410
411
}

412
413
414
/*
 * Verify types and entities.
 */
415
416
417
418
419
int tr_vrfy(void)
{
	int      res = no_error;
	ir_type *constructors;
	ir_type *destructors;
420
	ir_type *thread_locals;
421
	int      i;
422
423
424
425
	static ident *empty = NULL;

	if (empty == NULL)
		empty = new_id_from_chars("", 0);
Götz Lindenmaier's avatar
new.  
Götz Lindenmaier committed
426

Michael Beck's avatar
Michael Beck committed
427
	type_walk(check_tore, NULL, &res);
428
429
430

	constructors = get_segment_type(IR_SEGMENT_CONSTRUCTORS);
	for (i = get_compound_n_members(constructors)-1; i >= 0; --i) {
431
		const ir_entity *entity = get_compound_member(constructors, i);
432
433
434
		ASSERT_AND_RET(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER,
		               "entity without LINKAGE_HIDDEN_USER in constructors is pointless",
		               1);
435
436
		/* Mach-O doesn't like labels in this section */
		ASSERT_AND_RET(get_entity_ld_ident(entity),
437
		               "entity in constructors should have ld_ident=''", 1);
438
439
440
	}
	destructors = get_segment_type(IR_SEGMENT_DESTRUCTORS);
	for (i = get_compound_n_members(destructors)-1; i >= 0; --i) {
441
		const ir_entity *entity = get_compound_member(destructors, i);
442
443
444
		ASSERT_AND_RET(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER,
		               "entity without LINKAGE_HIDDEN_USER in destructors is pointless",
		               1);
445
446
		/* Mach-O doesn't like labels in this section */
		ASSERT_AND_RET(get_entity_ld_ident(entity),
447
448
449
450
451
452
453
454
455
456
		               "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_MERGE),
		               "IR_LINKAGE_MERGE currently not support for thread locals", 1);
457
458
	}

Michael Beck's avatar
Michael Beck committed
459
	return res;
Götz Lindenmaier's avatar
new.  
Götz Lindenmaier committed
460
}