irverify.c 44.5 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Matthias Braun's avatar
Matthias Braun committed
6
7
8
/**
 * @file
 * @brief    Check irnodes for correctness.
Matthias Braun's avatar
Matthias Braun committed
9
10
 * @author   Christian Schaefer, Goetz Lindenmaier, Till Riedel, Michael Beck,
 *           Matthias Braun
11
 */
12
#include "irnode_t.h"
13
14
15
#include "irprog.h"
#include "irop_t.h"
#include "irgraph_t.h"
16
#include "irverify_t.h"
17
18
19
20
21
22
#include "irgwalk.h"
#include "irdump.h"
#include "irdom_t.h"
#include "irprintf.h"
#include "irouts.h"
#include "irflag_t.h"
23
#include "irnodeset.h"
24
#include "ircons.h"
Christian Schäfer's avatar
Christian Schäfer committed
25

Matthias Braun's avatar
Matthias Braun committed
26
static void warn(const ir_node *n, const char *format, ...)
27
{
Matthias Braun's avatar
Matthias Braun committed
28
	FILE *out = stderr;
yb9976's avatar
yb9976 committed
29
	fputs("Verify warning: ", out);
Matthias Braun's avatar
Matthias Braun committed
30
	if (n != NULL) {
31
		ir_fprintf(out, "%+F(%+F): ", n, get_irn_irg(n));
32
	}
Matthias Braun's avatar
Matthias Braun committed
33
34
35
36
37
	va_list ap;
	va_start(ap, format);
	ir_vfprintf(out, format, ap);
	va_end(ap);
	fputc('\n', out);
38
39
}

40
/**
yb9976's avatar
yb9976 committed
41
 * Checks if node @p n has mode @p expected. Displays a message and returns
Matthias Braun's avatar
Matthias Braun committed
42
 * false in case of mismatch.
43
 */
Matthias Braun's avatar
Matthias Braun committed
44
static bool check_mode(const ir_node *n, const ir_mode *expected)
45
{
Matthias Braun's avatar
Matthias Braun committed
46
47
48
49
	ir_mode *mode = get_irn_mode(n);
	if (mode != expected) {
		warn(n, "expected mode %+F but found %+F", expected, mode);
		return false;
50
	}
Matthias Braun's avatar
Matthias Braun committed
51
	return true;
Michael Beck's avatar
Michael Beck committed
52
53
}

Matthias Braun's avatar
Matthias Braun committed
54
typedef int (*check_mode_func_ptr)(const ir_mode *mode);
Michael Beck's avatar
Michael Beck committed
55

Michael Beck's avatar
Michael Beck committed
56
/**
Matthias Braun's avatar
Matthias Braun committed
57
58
 * Checks if the mode of node @p fulfills the predicate function @p func.
 * Displays a message and returns false if predicate is not fulfilled.
Michael Beck's avatar
Michael Beck committed
59
 */
Matthias Braun's avatar
Matthias Braun committed
60
61
static bool check_mode_func(const ir_node *n, check_mode_func_ptr func,
                            const char *name)
62
{
Matthias Braun's avatar
Matthias Braun committed
63
64
65
66
	ir_mode *mode = get_irn_mode(n);
	if (!func(mode)) {
		warn(n, "expected %s mode but found %+F", name, mode);
		return false;
67
	}
Matthias Braun's avatar
Matthias Braun committed
68
	return true;
Michael Beck's avatar
Michael Beck committed
69
}
70

Michael Beck's avatar
Michael Beck committed
71
/**
Matthias Braun's avatar
Matthias Braun committed
72
73
 * Checks if input @p input of node @p n has mode @p expected. Displays a
 * message and returns false in case of mismatch.
Michael Beck's avatar
Michael Beck committed
74
 */
Matthias Braun's avatar
Matthias Braun committed
75
76
77
78
79
80
81
82
83
84
85
static bool check_input_mode(const ir_node *n, int input, const char *inputname,
                             const ir_mode *mode)
{
	ir_node *in      = get_irn_n(n, input);
	ir_mode *in_mode = get_irn_mode(in);
	if (in_mode != mode) {
		char num[16];
		if (inputname == NULL) {
			snprintf(num, sizeof(num), "input %d", input);
			inputname = num;
		}
86
87
		warn(n, "expected mode %+F for input '%s' but found %+F (%+F)",
		     mode, inputname, in_mode, in);
Matthias Braun's avatar
Matthias Braun committed
88
89
90
		return false;
	}
	return true;
Michael Beck's avatar
Michael Beck committed
91
92
93
}

/**
Matthias Braun's avatar
Matthias Braun committed
94
95
 * Checks if mode of input @p input of node @p n fulfills the predicate
 * functions @p func. Displays a message and returns false if unfulfilled.
Michael Beck's avatar
Michael Beck committed
96
 */
Matthias Braun's avatar
Matthias Braun committed
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
static bool check_input_func(const ir_node *n, int input, const char *inputname,
                             check_mode_func_ptr func, const char *modedescr)
{
	ir_node *in   = get_irn_n(n, input);
	ir_mode *mode = get_irn_mode(in);
	if (!func(mode)) {
		char num[16];
		if (inputname == NULL) {
			snprintf(num, sizeof(num), "input %d", input);
			inputname = num;
		}
		warn(n, "expected %s mode for input '%s' but found %+F (%+F)",
		     modedescr, inputname, mode, in);
		return false;
	}
	return true;
Michael Beck's avatar
Michael Beck committed
113
114
}

Matthias Braun's avatar
Matthias Braun committed
115
116
static bool check_mode_same_input(const ir_node *n, int input,
                                  const char *inputname)
117
{
Matthias Braun's avatar
Matthias Braun committed
118
119
120
121
122
123
124
125
126
127
128
129
130
131
	ir_mode *mode    = get_irn_mode(n);
	ir_node *in      = get_irn_n(n, input);
	ir_mode *in_mode = get_irn_mode(in);
	if (mode != in_mode) {
		char num[16];
		if (inputname == NULL) {
			snprintf(num, sizeof(num), "input %d", input);
			inputname = num;
		}
		warn(n, "mode of input '%s' different from output mode %+F",
		     inputname, mode);
		return false;
	}
	return true;
Michael Beck's avatar
Michael Beck committed
132
133
}

yb9976's avatar
yb9976 committed
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
static bool check_mode_same_size_input(const ir_node *n, int input,
                                       const char *inputname)
{
	ir_mode  *mode         = get_irn_mode(n);
	unsigned  mode_size    = get_mode_size_bits(mode);
	ir_node  *in           = get_irn_n(n, input);
	ir_mode  *in_mode      = get_irn_mode(in);
	unsigned  in_mode_size = get_mode_size_bits(in_mode);
	if (mode_size != in_mode_size) {
		char num[16];
		if (inputname == NULL) {
			snprintf(num, sizeof(num), "input %d", input);
			inputname = num;
		}
		warn(n, "mode size of input '%s' different from output mode size",
		     inputname);
		return false;
	}
	return true;
}

Michael Beck's avatar
Michael Beck committed
155
/**
Matthias Braun's avatar
Matthias Braun committed
156
 * Displays error message that a wrong proj number was found and returns false.
Michael Beck's avatar
Michael Beck committed
157
 */
Matthias Braun's avatar
Matthias Braun committed
158
static bool invalid_proj(const ir_node *proj)
159
{
160
161
	warn(proj, "invalid proj number %u for predecessor %+F",
	     get_Proj_num(proj), get_Proj_pred(proj));
Matthias Braun's avatar
Matthias Braun committed
162
	return false;
Michael Beck's avatar
Michael Beck committed
163
164
}

165
static int verify_node_Proj_Start(const ir_node *p)
166
{
167
	switch ((pn_Start)get_Proj_num(p)) {
168
169
170
	case pn_Start_M:            return check_mode(p, mode_M);
	case pn_Start_P_frame_base: return check_mode_func(p, mode_is_reference, "reference");
	case pn_Start_T_args:       return check_mode(p, mode_T);
Matthias Braun's avatar
Matthias Braun committed
171
172
	}
	return invalid_proj(p);
Michael Beck's avatar
Michael Beck committed
173
}
174

175
static int verify_node_Proj_Cond(const ir_node *p)
176
{
177
	switch ((pn_Cond)get_Proj_num(p)) {
Matthias Braun's avatar
Matthias Braun committed
178
179
180
181
	case pn_Cond_true:
	case pn_Cond_false: return check_mode(p, mode_X);
	}
	return invalid_proj(p);
Michael Beck's avatar
Michael Beck committed
182
}
183

Matthias Braun's avatar
Matthias Braun committed
184
185
static int verify_node_Proj_Switch(const ir_node *p)
{
186
	unsigned pn   = get_Proj_num(p);
Matthias Braun's avatar
Matthias Braun committed
187
	ir_node *pred = get_Proj_pred(p);
Matthias Braun's avatar
Matthias Braun committed
188
	bool     fine = check_mode(p, mode_X);
189
190
	if (pn >= get_Switch_n_outs(pred)) {
		warn(p, "invalid proj number %u for predecessor %+F", pn, pred);
Matthias Braun's avatar
Matthias Braun committed
191
192
193
		fine = false;
	}
	return fine;
Matthias Braun's avatar
Matthias Braun committed
194
195
}

196
static int verify_node_Proj_Raise(const ir_node *p)
197
{
198
	switch ((pn_Raise)get_Proj_num(p)) {
Matthias Braun's avatar
Matthias Braun committed
199
200
201
202
	case pn_Raise_X: return check_mode(p, mode_X);
	case pn_Raise_M: return check_mode(p, mode_M);
	}
	return invalid_proj(p);
Michael Beck's avatar
Michael Beck committed
203
}
204

205
static int verify_node_Proj_Call(const ir_node *p)
206
{
207
	switch ((pn_Call)get_Proj_num(p)) {
Matthias Braun's avatar
Matthias Braun committed
208
209
210
211
	case pn_Call_M:         return check_mode(p, mode_M);
	case pn_Call_X_except:  return check_mode(p, mode_X);
	case pn_Call_X_regular: return check_mode(p, mode_X);
	case pn_Call_T_result:  return check_mode(p, mode_T);
Matthias Braun's avatar
Matthias Braun committed
212
	}
Matthias Braun's avatar
Matthias Braun committed
213
	return invalid_proj(p);
Michael Beck's avatar
Michael Beck committed
214
}
215

216
static int verify_node_Proj_Div(const ir_node *p)
217
{
218
	switch ((pn_Div)get_Proj_num(p)) {
Matthias Braun's avatar
Matthias Braun committed
219
220
221
222
223
224
	case pn_Div_M:         return check_mode(p, mode_M);
	case pn_Div_X_regular: return check_mode(p, mode_X);
	case pn_Div_X_except:  return check_mode(p, mode_X);
	case pn_Div_res:       return check_mode(p, get_Div_resmode(get_Proj_pred(p)));
	}
	return invalid_proj(p);
Michael Beck's avatar
Michael Beck committed
225
}
Michael Beck's avatar
Michael Beck committed
226

227
static int verify_node_Proj_Mod(const ir_node *p)
228
{
229
	switch ((pn_Mod)get_Proj_num(p)) {
Matthias Braun's avatar
Matthias Braun committed
230
231
232
233
234
235
	case pn_Mod_M:         return check_mode(p, mode_M);
	case pn_Mod_X_regular: return check_mode(p, mode_X);
	case pn_Mod_X_except:  return check_mode(p, mode_X);
	case pn_Mod_res:       return check_mode(p, get_Mod_resmode(get_Proj_pred(p)));
	}
	return invalid_proj(p);
Michael Beck's avatar
Michael Beck committed
236
}
237

238
static int verify_node_Proj_Load(const ir_node *p)
239
{
240
	switch ((pn_Load)get_Proj_num(p)) {
Matthias Braun's avatar
Matthias Braun committed
241
242
243
244
245
246
	case pn_Load_M:         return check_mode(p, mode_M);
	case pn_Load_X_regular: return check_mode(p, mode_X);
	case pn_Load_X_except:  return check_mode(p, mode_X);
	case pn_Load_res:       return check_mode(p, get_Load_mode(get_Proj_pred(p)));
	}
	return invalid_proj(p);
Michael Beck's avatar
Michael Beck committed
247
}
248

249
static int verify_node_Proj_Store(const ir_node *p)
250
{
251
	switch ((pn_Store)get_Proj_num(p)) {
Matthias Braun's avatar
Matthias Braun committed
252
253
254
	case pn_Store_M:         return check_mode(p, mode_M);
	case pn_Store_X_regular: return check_mode(p, mode_X);
	case pn_Store_X_except:  return check_mode(p, mode_X);
255
	}
Matthias Braun's avatar
Matthias Braun committed
256
	return invalid_proj(p);
Michael Beck's avatar
Michael Beck committed
257
258
}

259
static int verify_node_Proj_Alloc(const ir_node *p)
260
{
261
	switch ((pn_Alloc)get_Proj_num(p)) {
Matthias Braun's avatar
Matthias Braun committed
262
263
264
265
266
	case pn_Alloc_M:   return check_mode(p, mode_M);
	case pn_Alloc_res: return check_mode_func(p, mode_is_reference, "reference");
	}
	return invalid_proj(p);
}
Michael Beck's avatar
Michael Beck committed
267

Matthias Braun's avatar
Matthias Braun committed
268
269
270
271
272
273
static int verify_node_Proj_Proj_Start(const ir_node *p)
{
	ir_graph *irg = get_irn_irg(p);
	ir_type  *mt  = get_entity_type(get_irg_entity(irg));
	if (!is_Method_type(mt))
		return true;
274
275
276
	unsigned pn = get_Proj_num(p);
	if (pn >= get_method_n_params(mt)) {
		warn(p, "invalid proj number %u after Proj(%+F)", pn,
Matthias Braun's avatar
Matthias Braun committed
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
		     get_Proj_pred(get_Proj_pred(p)));
		return false;
	}
	if (!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND)) {
		ir_type *param_type = get_method_param_type(mt, pn);
		return check_mode(p, get_type_mode(param_type));
	}
	return true;
}

static int verify_node_Proj_Proj_Call(const ir_node *p)
{
	ir_node *pred = get_Proj_pred(p);
	ir_node *call = get_Proj_pred(pred);
	ir_type *mt   = get_Call_type(call);
	if (!is_Method_type(mt))
		return true;
294
295
296
	unsigned pn = get_Proj_num(p);
	if (pn >= get_method_n_ress(mt)) {
		warn(p, "invalid proj number %u after %+F", pn, call);
Matthias Braun's avatar
Matthias Braun committed
297
298
299
		return false;
	}
	ir_type *type = get_method_res_type(mt, pn);
300
	ir_mode *mode = is_aggregate_type(type) ? mode_P : get_type_mode(type);
Matthias Braun's avatar
Matthias Braun committed
301
	return check_mode(p, mode);
Michael Beck's avatar
Michael Beck committed
302
}
303

304
static int verify_node_Proj_Proj(const ir_node *p)
305
{
306
307
308
	ir_node *pred     = get_Proj_pred(p);
	ir_node *predpred = get_Proj_pred(pred);
	switch (get_irn_opcode(predpred)) {
Matthias Braun's avatar
Matthias Braun committed
309
310
311
	case iro_Start: return verify_node_Proj_Proj_Start(p);
	case iro_Call:  return verify_node_Proj_Proj_Call(p);
	default:        return true;
312
	}
313
}
314

315
static int verify_node_Proj_Tuple(const ir_node *p)
316
{
Matthias Braun's avatar
Matthias Braun committed
317
	ir_node *tuple = get_Proj_pred(p);
318
319
	unsigned pn    = get_Proj_num(p);
	if (pn >= (unsigned)get_irn_arity(tuple)) {
Matthias Braun's avatar
Matthias Braun committed
320
321
322
323
324
		warn(p, "invalid proj number on %+F", tuple);
		return false;
	}
	ir_node *in = get_irn_n(tuple, pn);
	return check_mode(p, get_irn_mode(in));
Michael Beck's avatar
Michael Beck committed
325
}
Christian Schäfer's avatar
Christian Schäfer committed
326

Matthias Braun's avatar
Matthias Braun committed
327
static bool verify_node_Proj_fragile(const ir_node *node)
328
{
Matthias Braun's avatar
Matthias Braun committed
329
330
331
332
333
334
335
336
337
338
339
340
	ir_node *pred = get_Proj_pred(node);
	if (!is_fragile_op(pred))
		return true;

	if (!is_x_except_Proj(node) && !is_x_regular_Proj(node))
		return true;
	int throws_exception = ir_throws_exception(pred);
	if (!throws_exception) {
		warn(node, "exception Proj on %+F which is not marked as throwing exceptions", pred);
		return false;
	}
	return true;
341
342
}

343
static int verify_node_Proj(const ir_node *p)
344
{
Matthias Braun's avatar
Matthias Braun committed
345
	ir_graph *irg  = get_irn_irg(p);
Matthias Braun's avatar
Matthias Braun committed
346
347
	ir_node  *pred = get_Proj_pred(p);
	if (get_irn_mode(pred) != mode_T) {
Matthias Braun's avatar
Matthias Braun committed
348
		warn(p, "predecessor %+F does not have mode_T", pred);
Matthias Braun's avatar
Matthias Braun committed
349
		return false;
350
	}
Matthias Braun's avatar
Matthias Braun committed
351
352
353
	bool fine = true;
	if (get_irg_pinned(irg) != op_pin_state_floats
	    && get_nodes_block(pred) != get_nodes_block(p)) {
Matthias Braun's avatar
Matthias Braun committed
354
	    warn(p, "different block than predecessor %+F", pred);
Matthias Braun's avatar
Matthias Braun committed
355
356
357
	    fine = false;
	}
	fine &= verify_node_Proj_fragile(p);
358

Matthias Braun's avatar
Matthias Braun committed
359
	ir_op *op = get_irn_op(pred);
360
	if (op->ops.verify_proj_node)
Matthias Braun's avatar
Matthias Braun committed
361
		fine &= op->ops.verify_proj_node(p);
362

Matthias Braun's avatar
Matthias Braun committed
363
	return fine;
Michael Beck's avatar
Michael Beck committed
364
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
365

366
static int verify_node_Block(const ir_node *n)
367
{
Matthias Braun's avatar
Matthias Braun committed
368
369
370
	bool fine = check_mode(n, mode_BB);
	for (int i = 0, n_cfgpreds = get_Block_n_cfgpreds(n); i < n_cfgpreds; ++i) {
		fine &= check_input_mode(n, i, NULL, mode_X);
Matthias Braun's avatar
Matthias Braun committed
371
372
		ir_node *pred         = get_Block_cfgpred(n, i);
		ir_node *skipped_pred = skip_Proj(skip_Tuple(pred));
Matthias Braun's avatar
Matthias Braun committed
373
374
375
376
377
		if (!is_cfop(skipped_pred) && !is_Bad(skipped_pred)) {
			warn(n, "predecessor %d of block is not a cfop, but %+F", i,
			     skipped_pred);
			fine = false;
		}
378
379
380
381
382
383

		if (is_IJmp(skipped_pred) && get_Block_entity(n) == NULL) {
			warn(n, "succesor block of IJmp %+F has no entity assigned",
			     skipped_pred);
			fine = false;
		}
384
385
	}

Matthias Braun's avatar
Matthias Braun committed
386
387
388
389
390
391
	ir_graph *irg = get_irn_irg(n);
	if (n == get_irg_start_block(irg) && get_Block_n_cfgpreds(n) != 0) {
		warn(n, "start block mustn't have inputs");
		fine = false;
	} else if (n == get_irg_end_block(irg)
	           && !irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND)) {
392
		/* End block may only have Return, Raise or fragile ops as preds. */
Matthias Braun's avatar
Matthias Braun committed
393
394
395
396
397
398
399
400
401
402
		for (int i = 0, n_cfgpreds = get_Block_n_cfgpreds(n); i < n_cfgpreds;
		     ++i) {
		    ir_node *pred         = get_Block_cfgpred(n, i);
			ir_node *skipped_pred = skip_Proj(skip_Tuple(pred));
			if (!is_Return(skipped_pred) && !is_Bad(skipped_pred)
			    && !is_Raise(skipped_pred)) {
			    warn(n, "end block must have Return or Raise predecessor, found %+F",
			         skipped_pred);
			    fine = false;
			}
403
		}
404
	}
Matthias Braun's avatar
Matthias Braun committed
405
	return fine;
Michael Beck's avatar
Michael Beck committed
406
}
407

408
409
410
411
412
413
static int verify_node_Deleted(const ir_node *n)
{
	warn(n, "Deleted node %+F appears to be reachable");
	return false;
}

414
static int verify_node_Start(const ir_node *n)
415
{
Matthias Braun's avatar
Matthias Braun committed
416
	return check_mode(n, mode_T);
Michael Beck's avatar
Michael Beck committed
417
}
418

419
420
421
422
423
424
425
426
427
static int verify_node_End(const ir_node *n)
{
	bool fine = check_mode(n, mode_X);
	/* check that only blocks, PhiM and (noreturn) Call nodes are connected
	 * by keep-alive edges */
	ir_graph *irg = get_irn_irg(n);
	if (!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND)) {
		foreach_irn_in(n, i, kept) {
			/* endless loop handling may keep PhiM and Block nodes */
428
429
430
			if (is_Block(kept))
				continue;
			if (is_Phi(kept) && get_Phi_loop(kept))
431
432
433
434
435
436
				continue;
			/* noreturn calls are currently kept with keep-alive edges */
			if (is_Call(kept))
				continue;
			if (is_Bad(kept))
				continue;
437
			warn(n, "keep-alive edge only allowed on Block, PhiLoop and Call node, found %+F",
438
439
440
441
442
443
444
			     kept);
			fine = false;
		}
	}
	return fine;
}

445
static int verify_node_Jmp(const ir_node *n)
446
{
Matthias Braun's avatar
Matthias Braun committed
447
	return check_mode(n, mode_X);
Michael Beck's avatar
Michael Beck committed
448
}
449

450
static int verify_node_IJmp(const ir_node *n)
451
{
Matthias Braun's avatar
Matthias Braun committed
452
453
454
	bool fine = check_input_func(n, n_IJmp_target, "target", mode_is_reference, "reference");
	fine &= check_mode(n, mode_X);
	return fine;
Michael Beck's avatar
Michael Beck committed
455
456
}

457
static int verify_node_Cond(const ir_node *n)
458
{
Matthias Braun's avatar
Matthias Braun committed
459
460
461
	bool fine = check_mode(n, mode_T);
	fine &= check_input_mode(n, n_Cond_selector, "selector", mode_b);
	return fine;
Matthias Braun's avatar
Matthias Braun committed
462
463
}

Matthias Braun's avatar
Matthias Braun committed
464
static bool verify_switch_table(const ir_node *n)
Matthias Braun's avatar
Matthias Braun committed
465
{
Matthias Braun's avatar
Matthias Braun committed
466
467
468
469
470
	const ir_switch_table *table = get_Switch_table(n);
	if (table == NULL) {
		warn(n, "switch table is NULL");
		return false;
	}
471

Matthias Braun's avatar
Matthias Braun committed
472
473
474
475
476
477
	unsigned  n_outs   = get_Switch_n_outs(n);
	ir_node  *selector = get_Switch_selector(n);
	ir_mode  *mode     = get_irn_mode(selector);
	bool      fine     = true;
	for (size_t e = 0, n_entries = ir_switch_table_get_n_entries(table);
	     e < n_entries; ++e) {
Matthias Braun's avatar
Matthias Braun committed
478
479
480
481
		const ir_switch_table_entry *entry
			= ir_switch_table_get_entry_const(table, e);
		if (entry->pn == 0)
			continue;
Matthias Braun's avatar
Matthias Braun committed
482
483
484
485
486
487
488
489
490
491
		if (entry->min == NULL || entry->max == NULL) {
			warn(n, "switch table entry %zu without min+max value", e);
			fine = false;
		}
		if (mode_is_int(mode) && (get_tarval_mode(entry->min) != mode
		                       || get_tarval_mode(entry->max) != mode)) {
			warn(n, "switch table entry %zu has wrong mode for min or max value",
				 e);
			fine = false;
		} else if (tarval_cmp(entry->min, entry->max) == ir_relation_greater) {
492
			warn(n, "switch table entry %zu min is not less or equal than max", e);
Matthias Braun's avatar
Matthias Braun committed
493
494
			fine = false;
		}
495
		if (entry->pn >= n_outs) {
Matthias Braun's avatar
Matthias Braun committed
496
497
498
			warn(n, "switch table entry %zu has invalid proj number", e);
			fine = false;
		}
Matthias Braun's avatar
Matthias Braun committed
499
	}
Matthias Braun's avatar
Matthias Braun committed
500
	return fine;
Matthias Braun's avatar
Matthias Braun committed
501
}
502

Matthias Braun's avatar
Matthias Braun committed
503
504
static int verify_node_Switch(const ir_node *n)
{
Matthias Braun's avatar
Matthias Braun committed
505
506
507
508
	bool fine = check_mode(n, mode_T);
	fine &= check_input_func(n, n_Switch_selector, "selector", mode_is_int, "int");
	fine &= verify_switch_table(n);
	return fine;
Michael Beck's avatar
Michael Beck committed
509
510
}

511
static int verify_node_Return(const ir_node *n)
512
{
Matthias Braun's avatar
Matthias Braun committed
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
	bool fine = check_mode(n, mode_X);
	fine &= check_input_mode(n, n_Return_mem, "mem", mode_M);

	ir_graph *irg = get_irn_irg(n);
	ir_type  *mt  = get_entity_type(get_irg_entity(irg));
	if (!is_Method_type(mt)) /* someone else should report that problem */
		return true;
	if ((size_t)get_Return_n_ress(n) != get_method_n_ress(mt)) {
		warn(n, "number of inputs does not match metho type (%zu inputs, %zu declared)",
		     get_Return_n_ress(n), get_method_n_ress(mt));
	} else {
		for (int i = get_Return_n_ress(n); i-- > 0; ) {
			ir_type *expected = get_method_res_type(mt, i);
			if (is_atomic_type(expected)) {
				ir_mode *mode = get_type_mode(expected);
				fine &= check_input_mode(n, n_Return_max+1+i, NULL, mode);
529
			} else {
Matthias Braun's avatar
Matthias Braun committed
530
				fine &= check_input_func(n, n_Return_max+1+i, NULL, mode_is_reference, "reference");
531
			}
532
533
		}
	}
Matthias Braun's avatar
Matthias Braun committed
534
	return fine;
Michael Beck's avatar
Michael Beck committed
535
536
}

537
static int verify_node_Raise(const ir_node *n)
538
{
Matthias Braun's avatar
Matthias Braun committed
539
540
541
542
	bool fine = check_mode(n, mode_X);
	fine &= check_input_func(n, n_Raise_exo_ptr, "exo_ptr", mode_is_reference, "reference");
	fine &= check_input_mode(n, n_Raise_mem, "mem", mode_M);
	return fine;
Michael Beck's avatar
Michael Beck committed
543
544
}

545
546
547
static int verify_node_Address(const ir_node *n)
{
	ir_entity *ent  = get_Address_entity(n);
548
	bool       fine = check_mode_func(n, mode_is_reference, "reference");
549
550
551
552
553
554
555
	if (!(get_entity_owner(ent)->flags & tf_segment) && !is_method_entity(ent)) {
		warn(n, "entity of %+F is not in a segment type but %+F", ent, get_entity_owner(ent));
		fine = false;
	}
	return fine;
}

556
static int verify_node_Const(const ir_node *n)
557
{
558
	bool     fine    = check_mode_func(n, mode_is_data, "data");
Matthias Braun's avatar
Matthias Braun committed
559
560
561
562
563
564
565
566
	ir_mode *mode    = get_irn_mode(n);
	ir_mode *tv_mode = get_tarval_mode(get_Const_tarval(n));
	if (fine && tv_mode != mode) {
		warn(n, "tarval mode (%+F) different from Const mode (%+F)", tv_mode,
		     mode);
		fine = false;
	}
	return fine;
Michael Beck's avatar
Michael Beck committed
567
568
}

569
static int verify_node_int(const ir_node *n)
Matthias Braun's avatar
Matthias Braun committed
570
{
571
	return check_mode_func(n, mode_is_int, "int");
572
573
}

574
static int verify_node_Sel(const ir_node *n)
575
{
Matthias Braun's avatar
Matthias Braun committed
576
577
	bool fine = check_mode_func(n, mode_is_reference, "reference");
	fine &= check_input_func(n, n_Sel_ptr, "ptr", mode_is_reference, "reference");
578
579
580
581
582
583
584
585
	fine &= check_input_func(n, n_Sel_index, "index", mode_is_int, "int");
	ir_type *type = get_Sel_type(n);
	if (type == NULL) {
		warn(n, "type is NULL");
		fine = false;
	} else if (!is_Array_type(type)) {
		warn(n, "type %+F is not an array type", type);
		fine = false;
586
	}
587
588
589
590
591
592
	return fine;
}

static int verify_node_Member(const ir_node *n)
{
	bool fine = check_mode_func(n, mode_is_reference, "reference");
593
594
595
596
597
	/* do not check in backend until beabi.c is gone */
	if (!irg_is_constrained(get_irn_irg(n), IR_GRAPH_CONSTRAINT_BACKEND)) {
		fine &= check_input_func(n, n_Member_ptr, "ptr", mode_is_reference,
		                         "reference");
	}
598
599
	ir_entity *entity = get_Member_entity(n);
	if (entity == NULL) {
Matthias Braun's avatar
Matthias Braun committed
600
601
		warn(n, "entity is NULL");
		fine = false;
602
603
	} else if (get_entity_owner(entity)->flags & tf_segment) {
		warn(n, "Member from entity with global/segment type owner");
Matthias Braun's avatar
Matthias Braun committed
604
605
606
		fine = false;
	}
	return fine;
607
608
}

609
static int verify_node_Call(const ir_node *n)
610
{
Matthias Braun's avatar
Matthias Braun committed
611
612
613
	bool fine = check_mode(n, mode_T);
	fine &= check_input_mode(n, n_Call_mem, "mem", mode_M);
	fine &= check_input_func(n, n_Call_ptr, "ptr", mode_is_reference, "reference");
614

Matthias Braun's avatar
Matthias Braun committed
615
	ir_type *mt = get_Call_type(n);
Matthias Braun's avatar
Matthias Braun committed
616
617
618
	if (!is_Method_type(mt)) {
		warn(n, "call_type is not a method type");
		return false;
619
620
	}

Matthias Braun's avatar
Matthias Braun committed
621
	if ((size_t)get_Call_n_params(n) < get_method_n_params(mt)) {
622
		warn(n, "call has fewer arguments than method type");
Matthias Braun's avatar
Matthias Braun committed
623
624
625
626
627
		return false;
	} else if ((size_t)get_Call_n_params(n) > get_method_n_params(mt) &&
	    get_method_variadicity(mt) != variadicity_variadic) {
		warn(n, "call has more arguments than method type");
		return false;
628
	} else {
Matthias Braun's avatar
Matthias Braun committed
629
630
631
632
633
634
635
636
637
638
		for (int i = 0, n_params = get_Call_n_params(n); i < n_params; ++i) {
			if (i < (int)get_method_n_params(mt)) {
				const ir_type *param_type = get_method_param_type(mt, i);
				if (is_atomic_type(param_type)) {
					ir_mode *mode = get_type_mode(param_type);
					fine &= check_input_mode(n, n_Call_max+1+i, NULL, mode);
				} else {
					fine &= check_input_func(n, n_Call_max+1+i, NULL,
											 mode_is_reference, "reference");
				}
639
			} else {
Matthias Braun's avatar
Matthias Braun committed
640
641
				fine &= check_input_func(n, n_Call_max+1+i, NULL,
				                         mode_is_data, "data");
642
			}
643
644
		}
	}
Matthias Braun's avatar
Matthias Braun committed
645
	return fine;
Michael Beck's avatar
Michael Beck committed
646
}
647

648
static int verify_node_Add(const ir_node *n)
649
{
Matthias Braun's avatar
Matthias Braun committed
650
651
652
653
654
655
656
657
658
659
660
661
662
	bool     fine = true;
	ir_mode *mode = get_irn_mode(n);
	if (mode_is_num(mode)) {
		fine &= check_mode_same_input(n, n_Add_left, "left");
		fine &= check_mode_same_input(n, n_Add_right, "right");
	} else if (mode_is_reference(mode)) {
		ir_mode *left_mode  = get_irn_mode(get_Add_left(n));
		ir_mode *right_mode = get_irn_mode(get_Add_right(n));
		if (mode_is_int(left_mode)) {
			fine &= check_mode_same_input(n, n_Add_right, "right");
		} else if (mode_is_int(right_mode)) {
			fine &= check_mode_same_input(n, n_Add_left, "left");
		} else {
663
664
			warn(n, "AddP has no integer input");
			fine = false;
Matthias Braun's avatar
Matthias Braun committed
665
666
667
668
669
670
		}
	} else {
		warn(n, "mode must be numeric or reference but is %+F", mode);
		fine = false;
	}
	return fine;
Michael Beck's avatar
Michael Beck committed
671
}
672

673
static int verify_node_Sub(const ir_node *n)
674
{
Matthias Braun's avatar
Matthias Braun committed
675
676
677
678
679
680
681
	bool     fine = true;
	ir_mode *mode = get_irn_mode(n);
	if (mode_is_num(mode)) {
		ir_mode *mode_left = get_irn_mode(get_Sub_left(n));
		if (mode_is_reference(mode_left)) {
			fine &= check_input_func(n, n_Sub_left, "left", mode_is_reference, "reference");
			fine &= check_input_func(n, n_Sub_right, "right", mode_is_reference, "reference");
yb9976's avatar
yb9976 committed
682
683
			fine &= check_mode_same_size_input(n, n_Sub_left, "left");
			fine &= check_mode_same_size_input(n, n_Sub_right, "right");
Matthias Braun's avatar
Matthias Braun committed
684
685
686
687
688
689
690
691
692
		} else {
			fine &= check_mode_same_input(n, n_Sub_left, "left");
			fine &= check_mode_same_input(n, n_Sub_right, "right");
		}
	} else if (mode_is_reference(mode)) {
		fine &= check_mode_same_input(n, n_Sub_left, "left");
		fine &= check_input_func(n, n_Sub_right, "right", mode_is_int, "int");
	}
	return fine;
Michael Beck's avatar
Michael Beck committed
693
}
694

695
static int verify_node_Minus(const ir_node *n)
696
{
Matthias Braun's avatar
Matthias Braun committed
697
698
699
	bool fine = check_mode_func(n, mode_is_num, "numeric");
	fine &= check_mode_same_input(n, n_Minus_op, "op");
	return fine;
Michael Beck's avatar
Michael Beck committed
700
}
701

702
static int verify_node_Mul(const ir_node *n)
703
{
Matthias Braun's avatar
Matthias Braun committed
704
705
706
707
	bool fine = check_mode_func(n, mode_is_num, "numeric");
	fine &= check_mode_same_input(n, n_Mul_left, "left");
	fine &= check_mode_same_input(n, n_Mul_right, "right");
	return fine;
Michael Beck's avatar
Michael Beck committed
708
}
709

710
static int verify_node_Mulh(const ir_node *n)
711
{
Matthias Braun's avatar
Matthias Braun committed
712
713
714
715
	bool fine = check_mode_func(n, mode_is_int, "int");
	fine &= check_mode_same_input(n, n_Mulh_left, "left");
	fine &= check_mode_same_input(n, n_Mulh_right, "right");
	return fine;
Michael Beck's avatar
Michael Beck committed
716
717
}

718
static int verify_node_Div(const ir_node *n)
719
{
Matthias Braun's avatar
Matthias Braun committed
720
721
722
723
724
725
726
727
728
729
	bool fine = check_mode(n, mode_T);
	ir_mode *mode = get_Div_resmode(n);
	fine &= check_input_mode(n, n_Div_left, "left", mode);
	fine &= check_input_mode(n, n_Div_right, "right", mode);
	fine &= check_input_mode(n, n_Div_mem, "mem", mode_M);
	if (!mode_is_num(mode)) {
		warn(n, "div resmode is not a numeric mode");
		fine = false;
	}
	return fine;
Michael Beck's avatar
Michael Beck committed
730
}
731

732
static int verify_node_Mod(const ir_node *n)
733
{
Matthias Braun's avatar
Matthias Braun committed
734
735
736
737
738
739
740
741
742
743
	bool fine = check_mode(n, mode_T);
	ir_mode *mode = get_Mod_resmode(n);
	fine &= check_input_mode(n, n_Mod_left, "left", mode);
	fine &= check_input_mode(n, n_Mod_right, "right", mode);
	fine &= check_input_mode(n, n_Mod_mem, "mem", mode_M);
	if (!mode_is_int(mode)) {
		warn(n, "mod resmode is not a int mode");
		fine = false;
	}
	return fine;
Michael Beck's avatar
Michael Beck committed
744
}
745

Matthias Braun's avatar
Matthias Braun committed
746
747
748
static int mode_is_intrefb(const ir_mode *mode)
{
	return mode_is_int(mode) || mode_is_reference(mode) || mode == mode_b;
Michael Beck's avatar
Michael Beck committed
749
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
750

751
752
static int verify_node_And(const ir_node *n)
{
Matthias Braun's avatar
Matthias Braun committed
753
754
755
756
	bool fine = check_mode_func(n, mode_is_intrefb, "int, reference or mode_b");
	fine &= check_mode_same_input(n, n_And_left, "left");
	fine &= check_mode_same_input(n, n_And_right, "right");
	return fine;
757
758
759
760
}

static int verify_node_Or(const ir_node *n)
{
Matthias Braun's avatar
Matthias Braun committed
761
762
763
764
	bool fine = check_mode_func(n, mode_is_intrefb, "int, reference or mode_b");
	fine &= check_mode_same_input(n, n_Or_left, "left");
	fine &= check_mode_same_input(n, n_Or_right, "right");
	return fine;
765
766
767
768
}

static int verify_node_Eor(const ir_node *n)
{
Matthias Braun's avatar
Matthias Braun committed
769
770
771
772
	bool fine = check_mode_func(n, mode_is_intrefb, "int, reference or mode_b");
	fine &= check_mode_same_input(n, n_Eor_left, "left");
	fine &= check_mode_same_input(n, n_Eor_right, "right");
	return fine;
773
}
Götz Lindenmaier's avatar
bugfix    
Götz Lindenmaier committed
774

Matthias Braun's avatar
Matthias Braun committed
775
static int mode_is_intb(const ir_mode *mode)
776
{
Matthias Braun's avatar
Matthias Braun committed
777
778
	return mode_is_int(mode) || mode == mode_b;
}
Michael Beck's avatar
Michael Beck committed
779

Matthias Braun's avatar
Matthias Braun committed
780
781
782
783
784
static int verify_node_Not(const ir_node *n)
{
	bool fine = check_mode_func(n, mode_is_intb, "int or mode_b");
	fine &= check_mode_same_input(n, n_Not_op, "op");
	return fine;
Michael Beck's avatar
Michael Beck committed
785
}
Michael Beck's avatar
Michael Beck committed
786

787
static int verify_node_Cmp(const ir_node *n)
788
{
Matthias Braun's avatar
Matthias Braun committed
789
	bool fine = check_mode(n, mode_b);
790
791
	fine &= check_input_func(n, n_Cmp_left, "left", mode_is_data, "data");
	fine &= check_input_func(n, n_Cmp_right, "right", mode_is_data, "data");
Matthias Braun's avatar
Matthias Braun committed
792
793
794
795
796
797
798
799
	ir_mode *model = get_irn_mode(get_Cmp_left(n));
	ir_mode *moder = get_irn_mode(get_Cmp_right(n));
	if (model != moder) {
		warn(n, "modes of left+right input are different: %+F and %+F", model,
		     moder);
		fine = false;
	}
	return fine;
Michael Beck's avatar
Michael Beck committed
800
}
Michael Beck's avatar
Michael Beck committed
801

Matthias Braun's avatar
Matthias Braun committed
802
803
804
static int mode_is_uint(const ir_mode *mode)
{
	return mode_is_int(mode) && !mode_is_signed(mode);
Michael Beck's avatar
Michael Beck committed
805
}
806

807
808
static int verify_node_Shl(const ir_node *n)
{
Matthias Braun's avatar
Matthias Braun committed
809
810
811
812
	bool fine = check_mode_func(n, mode_is_int, "int");
	fine &= check_mode_same_input(n, n_Shl_left, "left");
	fine &= check_input_func(n, n_Shl_right, "right", mode_is_uint, "unsigned int");
	return fine;
813
814
815
816
}

static int verify_node_Shr(const ir_node *n)
{
Matthias Braun's avatar
Matthias Braun committed
817
818
819
820
	bool fine = check_mode_func(n, mode_is_int, "int");
	fine &= check_mode_same_input(n, n_Shr_left, "left");
	fine &= check_input_func(n, n_Shr_right, "right", mode_is_uint, "unsigned int");
	return fine;
821
822
823
824
}

static int verify_node_Shrs(const ir_node *n)
{
Matthias Braun's avatar
Matthias Braun committed
825
826
827
828
	bool fine = check_mode_func(n, mode_is_int, "int");
	fine &= check_mode_same_input(n, n_Shrs_left, "left");
	fine &= check_input_func(n, n_Shrs_right, "right", mode_is_uint, "unsigned int");
	return fine;
829
}
830

831
static int verify_node_Conv(const ir_node *n)
832
{
Matthias Braun's avatar
Matthias Braun committed
833
834
835
836
	bool fine = check_mode_func(n, mode_is_data, "data");
	fine &= check_input_func(n, n_Conv_op, "op", mode_is_data, "data");
	return fine;
}
Michael Beck's avatar
Michael Beck committed
837

Matthias Braun's avatar
Matthias Braun committed
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
static int verify_node_Bitcast(const ir_node *n)
{
	bool fine = check_mode_func(n, mode_is_data, "data");
	ir_node *op       = get_Bitcast_op(n);
	ir_mode *src_mode = get_irn_mode(op);
	ir_mode *dst_mode = get_irn_mode(n);
	/* Note: This constraint is currently strict as you can use Conv
	 * for the other cases and we want to avoid having 2 nodes representing the
	 * same operation. We might loosen this constraint in the future. */
	if (get_mode_size_bits(src_mode) != get_mode_size_bits(dst_mode)
	    || get_mode_arithmetic(src_mode) == get_mode_arithmetic(dst_mode)) {
	    warn(n, "bitcast only allowed for modes with same size and different arithmetic");
	    fine = false;
	}
	return fine;
}

Matthias Braun's avatar
Matthias Braun committed
855
856
static int mode_is_dataMb(const ir_mode *mode)
{
857
	return mode_is_data(mode) || mode == mode_M;
Michael Beck's avatar
Michael Beck committed
858
}
859

860
static int verify_node_Phi(const ir_node *n)
861
{
862
863
864
	/* a Phi node MUST have the same number of inputs as its block
	 * Exception is a phi with 0 inputs which is used when (re)constructing the
	 * SSA form */
Matthias Braun's avatar
Matthias Braun committed
865
866
867
868
869
870
871
872
	bool      fine  = true;
	ir_node  *block = get_nodes_block(n);
	ir_graph *irg   = get_irn_irg(block);
	if (!is_Bad(block) && get_irn_arity(n) != get_irn_arity(block)
	    && (!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_CONSTRUCTION)
	        || get_irn_arity(n) != 0)) {
	    warn(n, "wrong number of inputs in Phi node");
	    fine = false;
873
874
	}

Matthias Braun's avatar
Matthias Braun committed
875
	/* Phi: BB x dataM --> dataM */
Matthias Braun's avatar
Matthias Braun committed
876
877
878
	fine &= check_mode_func(n, mode_is_dataMb, "data, memory or mode_b");
	for (int i = 0, n_preds = get_Phi_n_preds(n); i < n_preds; ++i) {
		fine &= check_mode_same_input(n, i, NULL);
879
	}
880
881
882

	if (get_Phi_loop(n))
		check_mode(n, mode_M);
Matthias Braun's avatar
Matthias Braun committed
883
	return fine;
Michael Beck's avatar
Michael Beck committed
884
}
885

886
static int verify_node_Load(const ir_node *n)
887
{
Matthias Braun's avatar
Matthias Braun committed
888
889
890
	bool fine = check_mode(n, mode_T);
	fine &= check_input_mode(n, n_Load_mem, "mem", mode_M);
	ir_graph *irg = get_irn_irg(n);
891
	if (!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND)) {
Matthias Braun's avatar
Matthias Braun committed
892
		fine &= check_input_func(n, n_Load_ptr, "ptr", mode_is_reference, "reference");
893
	}
Matthias Braun's avatar
Matthias Braun committed
894
895
896
897
898
899
	ir_mode *loadmode = get_Load_mode(n);
	if (!mode_is_data(loadmode)) {
		warn(n, "load mode is not a data mode, but %+F", loadmode);
		fine = false;
	}
	return fine;
Michael Beck's avatar
Michael Beck committed
900
901
}

902
static int verify_node_Store(const ir_node *n)
903
{
Matthias Braun's avatar
Matthias Braun committed
904
905
	bool fine = check_mode(n, mode_T);
	fine &= check_input_mode(n, n_Store_mem, "mem", mode_M);
Matthias Braun's avatar
Matthias Braun committed
906
	ir_graph *irg = get_irn_irg(n);
907
	if (!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND)) {
Matthias Braun's avatar
Matthias Braun committed
908
		fine &= check_input_func(n, n_Store_ptr, "ptr", mode_is_reference, "reference");
909
	}
Matthias Braun's avatar
Matthias Braun committed
910
911
912
913
914
915
	ir_mode *storemode = get_irn_mode(get_Store_value(n));
	if (!mode_is_data(storemode)) {
		warn(n, "store mode is not a data mode, but %+F", storemode);
		fine = false;
	}
	return fine;
Michael Beck's avatar
Michael Beck committed
916
917
}

918
static int verify_node_Alloc(const ir_node *n)
919
{
Matthias Braun's avatar
Matthias Braun committed
920
921
922
923
	bool fine = check_mode(n, mode_T);
	fine &= check_input_mode(n, n_Alloc_mem, "mem", mode_M);
	fine &= check_input_func(n, n_Alloc_size, "size", mode_is_uint, "unsigned int");
	return fine;
Michael Beck's avatar
Michael Beck committed
924
925
}

926
static int verify_node_Free(const ir_node *n)
927
{
Matthias Braun's avatar
Matthias Braun committed
928
929
930
931
	bool fine = check_mode(n, mode_M);
	fine &= check_input_mode(n, n_Free_mem, "mem", mode_M);
	fine &= check_input_func(n, n_Free_ptr, "ptr", mode_is_reference, "reference");
	return fine;
Michael Beck's avatar
Michael Beck committed
932
933
}

934
static int verify_node_Sync(const ir_node *n)
935
{
Matthias Braun's avatar
Matthias Braun committed
936
937
938
	bool fine = check_mode(n, mode_M);
	for (int i = 0, n_preds = get_Sync_n_preds(n); i < n_preds; ++i) {
		fine &= check_input_mode(n, i, NULL, mode_M);
939
	}
Matthias Braun's avatar
Matthias Braun committed
940
	return fine;
Michael Beck's avatar
Michael Beck committed
941
942
}

943
static int verify_node_Confirm(const ir_node *n)
944
{
Matthias Braun's avatar
Matthias Braun committed
945
946
947
	bool fine = check_mode_same_input(n, n_Confirm_value, "value");
	fine &= check_mode_same_input(n, n_Confirm_bound, "bound");
	return fine;
Michael Beck's avatar
Michael Beck committed
948
949
}

950
static int verify_node_Mux(const ir_node *n)
951
{
952
	bool fine = check_mode_func(n, mode_is_data, "data");
Matthias Braun's avatar
Matthias Braun committed
953
954
955
956
	fine &= check_input_mode(n, n_Mux_sel, "sel", mode_b);
	fine &= check_mode_same_input(n, n_Mux_true, "true");
	fine &= check_mode_same_input(n, n_Mux_false, "false");
	return fine;
Michael Beck's avatar
Michael Beck committed
957
958
}

959
static int verify_node_CopyB(const ir_node *n)
960
{
Matthias Braun's avatar
Matthias Braun committed
961
962
	bool      fine = check_mode(n, mode_M);
	ir_graph *irg  = get_irn_irg(n);
963
	if (!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND))