enhanced robustness: don't crash on NULL modes
[libfirm] / ir / ir / irvrfy.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ir/irvrfy.c
4  * Purpose:     Check irnodes for correctness.
5  * Author:      Christian Schaefer
6  * Modified by: Goetz Lindenmaier. Till Riedel
7  * Created:
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 1998-2003 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13 #ifdef HAVE_CONFIG_H
14 # include <config.h>
15 #endif
16
17 # include "irgraph_t.h"
18 # include "irvrfy.h"
19 # include "irgwalk.h"
20
21 #ifdef NDEBUG
22 /*
23  * in RELEASE mode, returns ret if the expression expr evaluates to zero
24  * in ASSERT mode, asserts the expression expr (and the string string).
25  */
26 #define ASSERT_AND_RET(expr, string, ret)       if (!(expr)) return (ret)
27
28 /*
29  * in RELEASE mode, returns ret if the expression expr evaluates to zero
30  * in ASSERT mode, executes blk if the expression expr evaluates to zero and asserts
31  */
32 #define ASSERT_AND_RET_DBG(expr, string, ret, blk)      if (!(expr)) return (ret)
33 #else
34 #define ASSERT_AND_RET(expr, string, ret) \
35 do { \
36   bad_msg = #expr " && " string; \
37   if (opt_do_node_verification == NODE_VERIFICATION_ON) \
38     assert((expr) && string); \
39   if (!(expr)) { \
40     if (opt_do_node_verification == NODE_VERIFICATION_REPORT) \
41       fprintf(stderr, #expr " : " string "\n"); \
42     return (ret); \
43   } \
44 } while(0)
45
46 #define ASSERT_AND_RET_DBG(expr, string, ret, blk) \
47 do { \
48   if (!(expr)) { \
49     bad_msg = #expr " && " string; \
50     if (opt_do_node_verification != NODE_VERIFICATION_ERROR_ONLY) { blk; } \
51     if (opt_do_node_verification == NODE_VERIFICATION_REPORT) \
52       fprintf(stderr, #expr " : " string "\n"); \
53     else if (opt_do_node_verification == NODE_VERIFICATION_ON) \
54       assert((expr) && string); \
55     return (ret); \
56   } \
57 } while(0)
58
59 #endif
60
61 /* @@@ replace use of array "in" by access functions. */
62 ir_node **get_irn_in(ir_node *node);
63
64 static node_verification_t opt_do_node_verification = NODE_VERIFICATION_ON;
65 static const char *bad_msg;
66
67 /**
68  * little helper for NULL modes
69  */
70 static const char *get_mode_name_ex(ir_mode *mode)
71 {
72   if (! mode)
73     return "<no mode>";
74   return get_mode_name(mode);
75 }
76
77 void do_node_verification(node_verification_t mode)
78 {
79   opt_do_node_verification = mode;
80 }
81
82 /**
83  * Prints a failure for a Node
84  */
85 static void show_node_failure(ir_node *n)
86 {
87   fprintf(stderr, "\nFIRM: irn_vrfy_irg() of node %ld %s%s\n" ,
88     get_irn_node_nr(n),
89     get_irn_opname(n), get_irn_modename(n)
90   );
91 }
92
93 /**
94  * Prints a failure message for a binop
95  */
96 static void show_binop_failure(ir_node *n, const char *text)
97 {
98   ir_node *left  = get_binop_left(n);
99   ir_node *right = get_binop_right(n);
100
101   fprintf(stderr, "\nFIRM: irn_vrfy_irg() of node %ld %s%s(%s%s, %s%s) did not match (%s)\n",
102       get_irn_node_nr(n),
103       get_irn_opname(n), get_irn_modename(n),
104       get_irn_opname(left), get_irn_modename(left),
105       get_irn_opname(right), get_irn_modename(right),
106       text);
107 }
108
109 /**
110  * Prints a failure message for an unop
111  */
112 static void show_unop_failure(ir_node *n, const char *text)
113 {
114   ir_node *op  = get_unop_op(n);
115
116   fprintf(stderr, "\nFIRM: irn_vrfy_irg() of node %ld %s%s(%s%s) did not match (%s)\n",
117       get_irn_node_nr(n),
118       get_irn_opname(n), get_irn_modename(n),
119       get_irn_opname(op), get_irn_modename(op),
120       text);
121 }
122
123 /**
124  * Prints a failure message for a proj
125  */
126 static void show_proj_failure(ir_node *n)
127 {
128   ir_node *op  = get_Proj_pred(n);
129   int proj     = get_Proj_proj(n);
130
131   fprintf(stderr, "\nFIRM: irn_vrfy_irg() of node %ld %s%s %d(%s%s) failed\n" ,
132       get_irn_node_nr(n),
133       get_irn_opname(n), get_irn_modename(n), proj,
134       get_irn_opname(op), get_irn_modename(op));
135 }
136
137 /**
138  * Prints a failure message for a proj
139  */
140 static void show_proj_failure_ent(ir_node *n, entity *ent)
141 {
142   ir_node *op  = get_Proj_pred(n);
143   int proj     = get_Proj_proj(n);
144   ir_mode *m   = get_type_mode(get_entity_type(ent));
145
146   fprintf(stderr, "\nFIRM: irn_vrfy_irg() of node %ld %s%s %d(%s%s) entity %s(type %s mode %s)failed\n" ,
147       get_irn_node_nr(n),
148       get_irn_opname(n), get_irn_modename(n), proj,
149       get_irn_opname(op), get_irn_modename(op),
150       get_entity_name(ent), get_type_name(get_entity_type(ent)),
151       get_mode_name_ex(m));
152 }
153
154 /**
155  * Show a node and a graph
156  */
157 static void show_node_on_graph(ir_graph *irg, ir_node *n)
158 {
159   entity *ent = get_irg_ent(irg);
160
161   if (ent)
162     fprintf(stderr, "\nFIRM: irn_vrfy_irg() of entity %s, node %ld %s%s\n",
163       get_entity_name(ent),
164       get_irn_node_nr(n), get_irn_opname(n), get_irn_modename(n));
165   else
166     fprintf(stderr, "\nFIRM: irn_vrfy_irg() of graph %p, node %ld %s%s\n",
167       (void *)irg,
168       get_irn_node_nr(n), get_irn_opname(n), get_irn_modename(n));
169 }
170
171 /**
172  * Show call params
173  */
174 static void show_call_param(ir_node *n, type *mt)
175 {
176   int i;
177
178   fprintf(stderr, "\nFIRM: irn_vrfy_irg() Call type-check failed: %s(", get_type_name(mt));
179   for (i = 0; i < get_method_n_params(mt); ++i) {
180     fprintf(stderr, "%s ", get_mode_name_ex(get_type_mode(get_method_param_type(mt, i))));
181   }
182   fprintf(stderr, ") != CALL(");
183
184   for (i = 0; i < get_Call_n_params(n); ++i) {
185     fprintf(stderr, "%s ", get_mode_name_ex(get_irn_mode(get_Call_param(n, i))));
186   }
187   fprintf(stderr, ")\n");
188
189 }
190
191 /**
192  * Show return modes
193  */
194 static void show_return_modes(ir_graph *irg, ir_node *n, type *mt, int i)
195 {
196   entity *ent = get_irg_ent(irg);
197
198   fprintf(stderr, "\nFIRM: irn_vrfy_irg() Return node %ld in entity \"%s\" mode %s different from type mode %s\n",
199     get_irn_node_nr(n), get_entity_name(ent),
200     get_mode_name_ex(get_irn_mode(get_Return_res(n, i))),
201     get_mode_name_ex(get_type_mode(get_method_res_type(mt, i)))
202   );
203 }
204
205 /**
206  * Show return number of results
207  */
208 static void show_return_nres(ir_graph *irg, ir_node *n, type *mt)
209 {
210   entity *ent = get_irg_ent(irg);
211
212   fprintf(stderr, "\nFIRM: irn_vrfy_irg() Return node %ld in entity \"%s\" has %d results different from type %d\n",
213     get_irn_node_nr(n), get_entity_name(ent),
214     get_Return_n_ress(n), get_method_n_ress(mt));
215 }
216
217 /**
218  * Show Phi input
219  */
220 static void show_phi_failure(ir_node *phi, ir_node *pred, int pos)
221 {
222   fprintf(stderr, "\nFIRM: irn_vrfy_irg() Phi node %ld has mode %s different from predeccessor node %ld mode %s\n",
223     get_irn_node_nr(phi), get_mode_name_ex(get_irn_mode(phi)),
224     get_irn_node_nr(pred), get_mode_name_ex(get_irn_mode(pred)));
225 }
226
227 INLINE static int
228 vrfy_Proj_proj(ir_node *p, ir_graph *irg) {
229   ir_node *pred;
230   ir_mode *mode;
231   int proj;
232
233   pred = skip_nop(get_Proj_pred(p));
234   assert(get_irn_mode(pred) == mode_T);
235   mode = get_irn_mode(p);
236   proj = get_Proj_proj(p);
237
238   switch (get_irn_opcode(pred)) {
239     case iro_Start:
240       ASSERT_AND_RET_DBG(
241           (
242            (proj == pns_initial_exec   && mode == mode_X) ||
243            (proj == pns_global_store   && mode == mode_M) ||
244            (proj == pns_frame_base     && mode_is_reference(mode)) ||
245            (proj == pns_globals        && mode_is_reference(mode)) ||
246            (proj == pns_args           && mode == mode_T) ||
247            (proj == pns_value_arg_base && mode_is_reference(mode)) ||
248            (proj == pns_value_arg_base && mode == mode_T)       /* FIXME: only one of those */
249           ),
250           "wrong Proj from Start", 0,
251       show_proj_failure(p);
252       );
253       break;
254
255     case iro_Cond:
256       ASSERT_AND_RET_DBG(
257         (proj >= 0 && mode == mode_X),
258     "wrong Proj from Cond", 0,
259     show_proj_failure(p);
260       );
261       break;
262
263     case iro_Raise:
264       ASSERT_AND_RET_DBG(
265         ((proj == pn_Raise_X && mode == mode_X) || (proj == pn_Raise_M && mode == mode_M)),
266         "wrong Proj from Raise", 0,
267     show_proj_failure(p);
268       );
269       break;
270
271     case iro_InstOf:
272       ASSERT_AND_RET_DBG(
273     (proj >= 0 && mode == mode_X),
274     "wrong Proj from InstOf", 0,
275     show_proj_failure(p);
276       );
277       break;
278
279     case iro_Call:
280       ASSERT_AND_RET_DBG(
281         ((proj == pn_Call_M_regular        && mode == mode_M) ||
282          (proj == pn_Call_X_except         && mode == mode_X) ||
283          (proj == pn_Call_T_result         && mode == mode_T) ||
284          (proj == pn_Call_M_except         && mode == mode_M) ||
285      (proj == pn_Call_P_value_res_base && mode == mode_P)),
286         "wrong Proj from Call", 0,
287         show_proj_failure(p);
288       );
289       break;
290
291     case iro_FuncCall:
292       ASSERT_AND_RET_DBG(
293         ((proj == pn_Call_M_regular        && mode == mode_M) ||
294          (proj == pn_Call_X_except         && mode == mode_X) ||
295          (proj == pn_Call_T_result         && mode == mode_T) ||
296          (proj == pn_Call_M_except         && mode == mode_M) ||
297      (proj == pn_Call_P_value_res_base && mode == mode_P)),
298         "wrong Proj from FuncCall", 0,
299         show_proj_failure(p);
300       );
301       break;
302
303     case iro_Quot:
304       ASSERT_AND_RET_DBG(
305         ((proj == pn_Quot_M        && mode == mode_M) ||
306          (proj == pn_Quot_X_except && mode == mode_X) ||
307          (proj == pn_Quot_res      && mode_is_float(mode))),
308         "wrong Proj from Quot", 0,
309     show_proj_failure(p);
310       );
311       break;
312
313     case iro_DivMod:
314       ASSERT_AND_RET_DBG(
315         ((proj == pn_DivMod_M        && mode == mode_M) ||
316          (proj == pn_DivMod_X_except && mode == mode_X) ||
317          (proj == pn_DivMod_res_div  && mode_is_int(mode)) ||
318          (proj == pn_DivMod_res_mod  && mode_is_int(mode))),
319         "wrong Proj from DivMod", 0,
320     show_proj_failure(p);
321       );
322       break;
323
324     case iro_Div:
325       ASSERT_AND_RET_DBG(
326         ((proj == pn_Div_M        && mode == mode_M) ||
327          (proj == pn_Div_X_except && mode == mode_X) ||
328          (proj == pn_Div_res      && mode_is_int(mode))),
329         "wrong Proj from Div or Mod", 0,
330     show_proj_failure(p);
331       );
332       break;
333
334     case iro_Mod:
335       ASSERT_AND_RET_DBG(
336         ((proj == pn_Mod_M        && mode == mode_M) ||
337          (proj == pn_Mod_X_except && mode == mode_X) ||
338          (proj == pn_Mod_res      && mode_is_int(mode))),
339         "wrong Proj from Div or Mod", 0,
340     show_proj_failure(p);
341       );
342       break;
343
344     case iro_Cmp:
345       ASSERT_AND_RET_DBG(
346         (proj >= 0 && proj <= 15 && mode == mode_b),
347         "wrong Proj from Cmp", 0,
348     show_proj_failure(p);
349       );
350       break;
351
352     case iro_Load:
353       if (proj == pn_Load_res) {
354     ir_node *ptr = get_Load_ptr(pred);
355     entity *ent = NULL;
356     if (get_irn_op(ptr) == op_Sel) {
357       ent = get_Sel_entity(ptr);
358     } /*
359         We may not test this, after lowering and optimization the Const can
360         have an unexpected type.
361     else if ((get_irn_op(ptr) == op_Const) &&
362            tarval_is_entity(get_Const_tarval(ptr))) {
363       ent = get_tarval_entity(get_Const_tarval(ptr));
364     } */
365     if (ent) {
366       ASSERT_AND_RET_DBG(
367         (mode == get_type_mode(get_entity_type(ent))),
368         "wrong data Proj from Load, entity type_mode failed", 0,
369         show_proj_failure_ent(p, ent);
370       );
371     }
372     else {
373       ASSERT_AND_RET_DBG(
374         mode_is_data(mode),
375        "wrong data Proj from Load", 0,
376        show_proj_failure(p);
377      );
378     }
379       } else {
380     ASSERT_AND_RET_DBG(
381       ((proj == pn_Load_M        && mode == mode_M) ||
382        (proj == pn_Load_X_except && mode == mode_X)),
383           "wrong Proj from Load", 0,
384       show_proj_failure(p);
385     );
386       }
387       break;
388
389     case iro_Store:
390       ASSERT_AND_RET_DBG(
391         ((proj == pn_Store_M        && mode == mode_M) ||
392          (proj == pn_Store_X_except && mode == mode_X)),
393         "wrong Proj from Store", 0,
394     show_proj_failure(p);
395       );
396       break;
397
398     case iro_Alloc:
399       ASSERT_AND_RET_DBG(
400         (
401          (proj == pn_Alloc_M        && mode == mode_M) ||
402          (proj == pn_Alloc_X_except /* && mode == mode_X*/) ||
403          (proj == pn_Alloc_res      && mode_is_reference(mode))
404         ),
405         "wrong Proj from Alloc", 0,
406         show_proj_failure(p);
407       );
408       break;
409
410     case iro_Proj:
411       {
412         type *mt; /* A method type */
413         long nr = get_Proj_proj(pred);
414
415         pred = skip_nop(get_Proj_pred(pred));
416         ASSERT_AND_RET((get_irn_mode(pred) == mode_T), "Proj from something not a tuple", 0);
417         switch (get_irn_opcode(pred))
418         {
419           case iro_Start:
420             mt = get_entity_type(get_irg_ent(irg));
421
422             if (nr == pns_args) {
423               ASSERT_AND_RET(
424                   (proj >= 0 && mode_is_data(mode)),
425                   "wrong Proj from Proj from Start", 0);
426               ASSERT_AND_RET(
427                 (proj < get_method_n_params(mt)),
428                 "More Projs for args than args in type", 0
429               );
430               if ((mode_is_reference(mode)) && is_compound_type(get_method_param_type(mt, proj)))
431                 /* value argument */ break;
432
433               ASSERT_AND_RET(
434                   (mode == get_type_mode(get_method_param_type(mt, proj))),
435                   "Mode of Proj from Start doesn't match mode of param type.", 0);
436             }
437             else if (nr == pns_value_arg_base) {
438               ASSERT_AND_RET(
439                   (proj >= 0 && mode_is_reference(mode)),
440                   "wrong Proj from Proj from Start", 0
441               );
442               ASSERT_AND_RET(
443                 (proj < get_method_n_params(mt)),
444                 "More Projs for args than args in type", 0
445               );
446             }
447             break;
448
449           case iro_Call:
450             {
451               ASSERT_AND_RET(
452                   (proj >= 0 && mode_is_data(mode)),
453                   "wrong Proj from Proj from Call", 0);
454               mt = get_Call_type(pred);
455               ASSERT_AND_RET(
456                   (proj < get_method_n_ress(mt)),
457                   "More Projs for results than results in type.", 0);
458               if ((mode_is_reference(mode)) && is_compound_type(get_method_res_type(mt, proj)))
459                 /* value result */ break;
460
461               ASSERT_AND_RET(
462                   (mode == get_type_mode(get_method_res_type(mt, proj))),
463                   "Mode of Proj from Call doesn't match mode of result type.", 0);
464             }
465             break;
466
467           case iro_FuncCall:
468             {
469               ASSERT_AND_RET(
470                   (proj >= 0 && mode_is_data(mode)),
471                   "wrong Proj from Proj from FuncCall", 0);
472               mt = get_FuncCall_type(pred);
473               ASSERT_AND_RET(
474                   (proj < get_method_n_ress(mt)),
475                   "More Projs for results than results in type.", 0);
476               if ((mode_is_reference(mode)) && is_compound_type(get_method_res_type(mt, proj)))
477                 /* value result */ break;
478
479               ASSERT_AND_RET(
480                   (mode == get_type_mode(get_method_res_type(mt, proj))),
481                   "Mode of Proj from FuncCall doesn't match mode of result type.", 0);
482             }
483             break;
484
485           case iro_Tuple:
486             /* We don't test */
487             break;
488
489           default:
490             ASSERT_AND_RET(0, "Unknown opcode", 0);
491         }
492         break;
493
494       }
495     case iro_Tuple:
496       /* We don't test */
497       break;
498
499     case iro_CallBegin:
500       break;
501
502     case iro_EndReg:
503       break;
504
505     case iro_EndExcept:
506       break;
507
508     default:
509       ASSERT_AND_RET(0, "Unknown opcode", 0);
510   }
511
512   /* all went ok */
513   return 1;
514 }
515
516 int irn_vrfy_irg(ir_node *n, ir_graph *irg)
517 {
518   int i;
519   int opcode, opcode1;
520   ir_mode *mymode, *op1mode = NULL, *op2mode, *op3mode;
521   int op_is_symmetric = 1;  /*  0: asymmetric
522                 1: operands have identical modes
523                 2: modes of operands == mode of this node */
524   type *mt;                 /* A method type */
525   entity *ent;
526
527   ir_node **in;
528
529   if (!opt_do_node_verification) return 1;
530
531   if (! interprocedural_view) {
532     /*
533      * do NOT check placement in interprocedural view, as we don't always know
534      * the "right" graph ...
535      */
536     ASSERT_AND_RET_DBG(
537       node_is_in_irgs_storage(irg, n),
538       "Node is not stored on proper IR graph!", 0,
539       show_node_on_graph(irg, n);
540     );
541   }
542
543   opcode = get_irn_opcode(n);
544
545   /* We don't want to test nodes whose predecessors are Bad or Unknown,
546      as we would have to special case that for each operation. */
547   if (opcode != iro_Phi && opcode != iro_Block)
548     for (i = 0; i < get_irn_arity(n); i++) {
549       opcode1 = get_irn_opcode(get_irn_n(n, i));
550       if (opcode1 == iro_Bad /*|| opcode1 == iro_Unknown*/)  /* GL: for analyses mode must be correct. */
551         return 1;
552     }
553
554   mymode = get_irn_mode(n);
555   in = get_irn_in(n);
556
557   switch (opcode)
558   {
559
560     case iro_Block:
561       for (i = 0; i < get_Block_n_cfgpreds(n); ++i) {
562     ir_node *pred =  get_Block_cfgpred(n, i);
563     ASSERT_AND_RET(
564       (is_Bad(pred)     ||
565        is_Unknown(pred) ||
566        (get_irn_mode(pred) == mode_X)
567       ), "Block node", 0);
568       }
569       /*  End block may only have Return, Raise or fragile ops as preds. */
570       if (n == get_irg_end_block(irg))
571     for (i = 0; i < get_Block_n_cfgpreds(n); ++i) {
572       ir_node *pred =  skip_Proj(get_Block_cfgpred(n, i));
573       if (is_Proj(pred) || get_irn_op(pred) == op_Tuple)
574         break;   /*  We can not test properly.  How many tuples are there? */
575       ASSERT_AND_RET(((get_irn_op(pred) == op_Return) ||
576               is_Bad(pred)                    ||
577               (get_irn_op(pred) == op_Raise)  ||
578               is_fragile_op(pred)               ),
579              "End Block node", 0);
580     }
581       /*  irg attr must == graph we are in. */
582       if (! interprocedural_view) {
583     ASSERT_AND_RET(((get_irn_irg(n) && get_irn_irg(n) == irg)), "Block node has wrong irg attribute", 0);
584       }
585
586       break;
587
588     case iro_Start:
589       ASSERT_AND_RET(
590           /* Start: BB --> X x M x ref x data1 x ... x datan x ref */
591           mymode == mode_T, "Start node", 0
592           );
593       break;
594
595     case iro_Jmp:
596       ASSERT_AND_RET(
597           /* Jmp: BB --> X */
598           mymode == mode_X, "Jmp node", 0
599           );
600       break;
601
602     case iro_Break:
603       ASSERT_AND_RET(
604           /* Jmp: BB --> X */
605           mymode == mode_X, "Jmp node", 0
606           );
607       break;
608
609     case iro_Cond:
610       op1mode = get_irn_mode(in[1]);
611       ASSERT_AND_RET(
612           /* Cond: BB x b --> X x X */
613           (op1mode == mode_b ||
614            /* Cond: BB x int --> X^n */
615            mode_is_int(op1mode) ),  "Cond node", 0
616           );
617       ASSERT_AND_RET(mymode == mode_T, "Cond mode is not a tuple", 0);
618       break;
619
620     case iro_Return:
621       op1mode = get_irn_mode(in[1]);
622       /* Return: BB x M x data1 x ... x datan --> X */
623       /* printf("mode: %s, code %s\n", ID_TO_STR(n->mode->name), ID_TO_STR(n->op->name));*/
624       ASSERT_AND_RET( op1mode == mode_M, "Return node", 0 );  /* operand M */
625       for (i = 2; i < get_irn_arity(n); i++) {
626         ASSERT_AND_RET( mode_is_data(get_irn_mode(in[i])), "Return node", 0 );  /* operand datai */
627       };
628       ASSERT_AND_RET( mymode == mode_X, "Result X", 0 );   /* result X */
629       /* Compare returned results with result types of method type */
630       mt = get_entity_type(get_irg_ent(irg));
631       ASSERT_AND_RET_DBG( get_Return_n_ress(n) == get_method_n_ress(mt),
632         "Number of results for Return doesn't match number of results in type.", 0,
633       show_return_nres(irg, n, mt););
634       for (i = 0; i < get_Return_n_ress(n); i++) {
635         type *res_type = get_method_res_type(mt, i);
636
637         if (is_atomic_type(res_type)) {
638           ASSERT_AND_RET_DBG(
639             get_irn_mode(get_Return_res(n, i)) == get_type_mode(res_type),
640             "Mode of result for Return doesn't match mode of result type.", 0,
641             show_return_modes(irg, n, mt, i);
642           );
643         }
644         else {
645           ASSERT_AND_RET_DBG(
646             mode_is_reference(get_irn_mode(get_Return_res(n, i))),
647             "Mode of result for Return doesn't match mode of result type.", 0,
648             show_return_modes(irg, n, mt, i);
649           );
650         }
651       }
652       break;
653
654     case iro_Raise:
655       op1mode = get_irn_mode(in[1]);
656       op2mode = get_irn_mode(in[2]);
657       ASSERT_AND_RET(
658           /* Sel: BB x M x ref --> X x M */
659           op1mode == mode_M && mode_is_reference(op2mode) &&
660           mymode == mode_T, "Raise node", 0
661           );
662       break;
663
664     case iro_Const:
665       ASSERT_AND_RET(
666           /* Const: BB --> data */
667           (mode_is_data (mymode) ||
668            mymode == mode_b)      /* we want boolean constants for static evaluation */
669           ,"Const node", 0        /* of Cmp. */
670           );
671       break;
672
673     case iro_SymConst:
674       ASSERT_AND_RET(
675           /* SymConst: BB --> int*/
676           (mode_is_int(mymode) ||
677            /* SymConst: BB --> ref */
678            mode_is_reference(mymode))
679           ,"SymConst node", 0);
680       break;
681
682     case iro_Sel:
683       op1mode = get_irn_mode(in[1]);
684       op2mode = get_irn_mode(in[2]);
685       ASSERT_AND_RET_DBG(
686           /* Sel: BB x M x ref x int^n --> ref */
687           (op1mode == mode_M && op2mode == mymode && mode_is_reference(mymode)),
688       "Sel node", 0, show_node_failure(n)
689           );
690       for (i=3; i < get_irn_arity(n); i++)
691       {
692         ASSERT_AND_RET_DBG(mode_is_int(get_irn_mode(in[i])), "Sel node", 0, show_node_failure(n));
693       }
694       ent = get_Sel_entity(n);
695       ASSERT_AND_RET_DBG(ent, "Sel node with empty entity", 0, show_node_failure(n));
696       break;
697
698     case iro_InstOf:
699       ASSERT_AND_RET(mode_T == mymode, "mode of Instof is not a tuple", 0);
700       ASSERT_AND_RET(mode_is_data(op1mode), "Instof not on data", 0);
701       break;
702
703     case iro_Call:
704       op1mode = get_irn_mode(in[1]);
705       op2mode = get_irn_mode(in[2]);
706       /* Call: BB x M x ref x data1 x ... x datan
707          --> M x datan+1 x ... x data n+m */
708       ASSERT_AND_RET( op1mode == mode_M && mode_is_reference(op2mode), "Call node", 0 );  /* operand M x ref */
709       for (i=3; i < get_irn_arity(n); i++) {
710         ASSERT_AND_RET( mode_is_data(get_irn_mode(in[i])), "Call node", 0 );  /* operand datai */
711       };
712       ASSERT_AND_RET( mymode == mode_T, "Call result not a tuple", 0 );   /* result T */
713       /* Compare arguments of node with those of type */
714       mt = get_Call_type(n);
715
716       if (get_method_variadicity(mt) == variadicity_variadic) {
717         ASSERT_AND_RET_DBG(
718             get_Call_n_params(n) >= get_method_n_params(mt),
719             "Number of args for Call doesn't match number of args in variadic type.",
720             0,
721         fprintf(stderr, "Call has %d params, method %s type %d\n",
722           get_Call_n_params(n), get_type_name(mt), get_method_n_params(mt));
723         );
724       }
725       else {
726         ASSERT_AND_RET(
727             get_Call_n_params(n) == get_method_n_params(mt),
728             "Number of args for Call doesn't match number of args in non variadic type.",
729             0);
730       }
731
732       for (i = 0; i < get_method_n_params(mt); i++) {
733         type *t = get_method_param_type(mt, i);
734
735         if (is_atomic_type(t)) {
736           ASSERT_AND_RET_DBG(
737               get_irn_mode(get_Call_param(n, i)) == get_type_mode(t),
738               "Mode of arg for Call doesn't match mode of arg type.", 0,
739           show_call_param(n, mt);
740           );
741         }
742         else {
743           /* call with a compound type, mode must be reference */
744           ASSERT_AND_RET_DBG(
745               mode_is_reference(get_irn_mode(get_Call_param(n, i))),
746               "Mode of arg for Call doesn't match mode of arg type.", 0,
747           show_call_param(n, mt);
748           );
749         }
750       }
751       break;
752
753     case iro_Add:
754       op1mode = get_irn_mode(in[1]);
755       op2mode = get_irn_mode(in[2]);
756       ASSERT_AND_RET_DBG(
757           (
758            /* common Add: BB x numP x numP --> numP */
759        (op1mode == mymode && op2mode == op1mode && mode_is_numP(mymode)) ||
760            /* Pointer Add: BB x ref x int --> ref */
761            (mode_is_reference(op1mode) && mode_is_int(op2mode) && op1mode == mymode) ||
762            /* Pointer Add: BB x int x ref --> ref */
763            (mode_is_int(op1mode) && op2mode == mymode && mode_is_reference(mymode))
764       ),
765           "Add node", 0,
766       show_binop_failure(n, "/* common Add: BB x numP x numP --> numP */ |\n"
767                             "/* Pointer Add: BB x ref x int --> ref */   |\n"
768                                 "/* Pointer Add: BB x int x ref --> ref */");
769           );
770       if (mode_is_reference(op1mode) != mode_is_reference(op2mode)) {
771         /* BB x ref x int --> ref or BB x int x ref --> ref */
772         op_is_symmetric = 0;
773       } else {
774         /* BB x num x num --> num or BB x ref x ref */
775         op_is_symmetric = 2;
776       }
777       break;
778
779     case iro_Sub:
780       op1mode = get_irn_mode(in[1]);
781       op2mode = get_irn_mode(in[2]);
782       ASSERT_AND_RET_DBG(
783           /* common Sub: BB x numP x numP --> numP */
784           ((mymode ==op1mode && mymode == op2mode && mode_is_numP(op1mode)) ||
785            /* Pointer Sub: BB x ref x int --> ref */
786            (op1mode == mymode && mode_is_int(op2mode) && mode_is_reference(mymode)) ||
787            /* Pointer Sub: BB x int x ref --> ref */
788            (mode_is_int(op1mode) && op2mode == mymode && mode_is_reference(mymode)) ||
789            /* Pointer Sub: BB x ref x ref --> int */
790            (op1mode == op2mode && mode_is_reference(op2mode) && mode_is_int(mymode))),
791           "Sub node", 0,
792       show_binop_failure(n, "/* common Sub: BB x numP x numP --> numP */ |\n"
793                             "/* Pointer Sub: BB x ref x int --> ref */   |\n"
794                             "/* Pointer Sub: BB x int x ref --> ref */   |\n"
795                             "/* Pointer Sub: BB x ref x ref --> int */" );
796           );
797       if (mode_is_reference(op1mode) != mode_is_reference(op2mode)) {
798         op_is_symmetric = 0;
799       } else {
800         op_is_symmetric = 2;
801       }
802       break;
803
804     case iro_Minus:
805       op1mode = get_irn_mode(in[1]);
806       ASSERT_AND_RET_DBG(
807           /* Minus: BB x float --> float */
808           op1mode == mymode && get_mode_sort(op1mode) == irms_float_number, "Minus node", 0,
809       show_unop_failure(n , "/* Minus: BB x float --> float */");
810           );
811       op_is_symmetric = 2;
812       break;
813
814     case iro_Mul:
815       op1mode = get_irn_mode(in[1]);
816       op2mode = get_irn_mode(in[2]);
817       ASSERT_AND_RET_DBG(
818           /* Mul: BB x int1 x int1 --> int2 */
819           ((mode_is_int(op1mode)   && op2mode == op1mode && mode_is_int(mymode)) ||
820        (mode_is_float(op1mode) && op2mode == op1mode && mymode == op1mode)),
821           "Mul node",0,
822       show_binop_failure(n, "/* Mul: BB x int1 x int1 --> int2 */");
823           );
824       op_is_symmetric = 2;
825       break;
826
827     case iro_Quot:
828       op1mode = get_irn_mode(in[1]);
829       op2mode = get_irn_mode(in[2]);
830       op3mode = get_irn_mode(in[3]);
831       ASSERT_AND_RET_DBG(
832           /* Quot: BB x M x float x float --> M x X x float */
833           op1mode == mode_M && op2mode == op3mode &&
834           get_mode_sort(op2mode) == irms_float_number &&
835           mymode == mode_T,
836           "Quot node",0,
837       show_binop_failure(n, "/* Quot: BB x M x float x float --> M x X x float */");
838           );
839       op_is_symmetric = 2;
840       break;
841
842     case iro_DivMod:
843       op1mode = get_irn_mode(in[1]);
844       op2mode = get_irn_mode(in[2]);
845       op3mode = get_irn_mode(in[3]);
846       ASSERT_AND_RET(
847           /* DivMod: BB x M x int x int --> M x X x int x int */
848           op1mode == mode_M &&
849           mode_is_int(op2mode) &&
850           op3mode == op2mode &&
851           mymode == mode_T,
852           "DivMod node", 0
853           );
854       op_is_symmetric = 1;
855       break;
856
857     case iro_Div:
858     case iro_Mod:
859       op1mode = get_irn_mode(in[1]);
860       op2mode = get_irn_mode(in[2]);
861       op3mode = get_irn_mode(in[3]);
862       ASSERT_AND_RET(
863           /* Div or Mod: BB x M x int x int --> M x X x int */
864           op1mode == mode_M &&
865           op2mode == op3mode &&
866           mode_is_int(op2mode) &&
867           mymode == mode_T,
868           "Div or Mod node", 0
869           );
870       op_is_symmetric = 1;
871       break;
872
873     case iro_Abs:
874       op1mode = get_irn_mode(in[1]);
875       ASSERT_AND_RET_DBG(
876     /* Abs: BB x num --> num */
877     op1mode == mymode &&
878     mode_is_num (op1mode),
879     "Abs node", 0,
880     show_unop_failure(n, "/* Abs: BB x num --> num */");
881       );
882       op_is_symmetric = 2;
883       break;
884
885     case iro_And:
886     case iro_Or:
887     case iro_Eor:
888       op1mode = get_irn_mode(in[1]);
889       op2mode = get_irn_mode(in[2]);
890       ASSERT_AND_RET_DBG(
891     /* And or Or or Eor: BB x int x int --> int */
892     mode_is_int(mymode) &&
893     op2mode == op1mode &&
894     mymode == op2mode,
895     "And, Or or Eor node", 0,
896     show_binop_failure(n, "/* And or Or or Eor: BB x int x int --> int */");
897       );
898       op_is_symmetric = 2;
899       break;
900
901     case iro_Not:
902       op1mode = get_irn_mode(in[1]);
903       ASSERT_AND_RET_DBG(
904     /* Not: BB x int --> int */
905     mode_is_int(mymode) &&
906     mymode == op1mode,
907     "Not node", 0,
908     show_unop_failure(n, "/* Not: BB x int --> int */");
909       );
910       op_is_symmetric = 2;
911       break;
912
913
914     case iro_Cmp:
915       op1mode = get_irn_mode(in[1]);
916       op2mode = get_irn_mode(in[2]);
917       ASSERT_AND_RET_DBG(
918     /* Cmp: BB x datab x datab --> b16 */
919     mode_is_data (op1mode) &&
920     op2mode == op1mode &&
921     mymode == mode_T,
922     "Cmp node", 0,
923     show_binop_failure(n, "/* Cmp: BB x datab x datab --> b16 */");
924       );
925       break;
926
927     case iro_Shl:
928     case iro_Shr:
929     case iro_Shrs:
930       op1mode = get_irn_mode(in[1]);
931       op2mode = get_irn_mode(in[2]);
932       ASSERT_AND_RET_DBG(
933     /* Shl, Shr or Shrs: BB x int x int_u --> int */
934     mode_is_int(op1mode) &&
935     mode_is_int(op2mode) &&
936     !mode_is_signed(op2mode) &&
937     mymode == op1mode,
938     "Shl, Shr, Shr or Rot node", 0,
939     show_binop_failure(n, "/* Shl, Shr or Shrs: BB x int x int_u --> int */");
940       );
941       break;
942
943     case iro_Rot:
944       op1mode = get_irn_mode(in[1]);
945       op2mode = get_irn_mode(in[2]);
946       ASSERT_AND_RET_DBG(
947     /* Rot: BB x int x int --> int */
948     mode_is_int(op1mode) &&
949     mode_is_int(op2mode) &&
950     mymode == op1mode,
951     "Rot node", 0,
952     show_binop_failure(n, "/* Rot: BB x int x int --> int */");
953       );
954       break;
955
956     case iro_Conv:
957       op1mode = get_irn_mode(in[1]);
958       ASSERT_AND_RET_DBG(
959     /* Conv: BB x datab1 --> datab2 */
960     mode_is_datab(op1mode) && mode_is_data(mymode),
961     "Conv node", 0,
962     show_unop_failure(n, "/* Conv: BB x datab1 --> datab2 */");
963       );
964       break;
965
966     case iro_Cast:
967       op1mode = get_irn_mode(in[1]);
968       ASSERT_AND_RET_DBG(
969     /* Conv: BB x datab1 --> datab2 */
970     mode_is_data(op1mode) && op1mode == mymode,
971     "Cast node", 0,
972     show_unop_failure(n, "/* Conv: BB x datab1 --> datab2 */");
973       );
974       break;
975
976     case iro_Phi:
977       /* Phi: BB x dataM^n --> dataM */
978       for (i = 1; i < get_irn_arity(n); i++) {
979         if (!is_Bad(in[i]) && (get_irn_op(in[i]) != op_Unknown))
980           ASSERT_AND_RET_DBG(
981           get_irn_mode(in[i]) == mymode,
982           "Phi node", 0,
983           show_phi_failure(n, in[i], i);
984       );
985       };
986       ASSERT_AND_RET( mode_is_dataM(mymode), "Phi node", 0 );
987       break;
988
989     case iro_Load:
990       op1mode = get_irn_mode(in[1]);
991       op2mode = get_irn_mode(in[2]);
992       ASSERT_AND_RET(
993           /* Load: BB x M x ref --> M x X x data */
994           op1mode == mode_M && mode_is_reference(op2mode),
995           "Load node", 0
996           );
997       ASSERT_AND_RET( mymode == mode_T, "Load node", 0 );
998       break;
999
1000     case iro_Store:
1001       op1mode = get_irn_mode(in[1]);
1002       op2mode = get_irn_mode(in[2]);
1003       op3mode = get_irn_mode(in[3]);
1004       ASSERT_AND_RET(
1005           /* Load: BB x M x ref data --> M x X */
1006           op1mode == mode_M && mode_is_reference(op2mode) && mode_is_data(op3mode),
1007           "Store node", 0
1008           );
1009       ASSERT_AND_RET(mymode == mode_T, "Store node", 0);
1010       break;
1011
1012     case iro_Alloc:
1013       op1mode = get_irn_mode(in[1]);
1014       op2mode = get_irn_mode(in[2]);
1015       ASSERT_AND_RET_DBG(
1016     /* Alloc: BB x M x int_u --> M x X x ref */
1017     op1mode == mode_M &&
1018     mode_is_int(op2mode) &&
1019     !mode_is_signed(op2mode) &&
1020     mymode == mode_T,
1021     "Alloc node", 0,
1022     show_binop_failure(n, "/* Alloc: BB x M x int_u --> M x X x ref */");
1023       );
1024       break;
1025
1026     case iro_Free:
1027       op1mode = get_irn_mode(in[1]);
1028       op2mode = get_irn_mode(in[2]);
1029       ASSERT_AND_RET_DBG(
1030     /* Free: BB x M x ref --> M */
1031     op1mode == mode_M && mode_is_reference(op2mode) &&
1032     mymode == mode_M,
1033     "Free node", 0,
1034     show_binop_failure(n, "/* Free: BB x M x ref --> M */");
1035       );
1036       break;
1037
1038     case iro_Sync:
1039       /* Sync: BB x M^n --> M */
1040       for (i=1; i < get_irn_arity(n); i++) {
1041         ASSERT_AND_RET( get_irn_mode(in[i]) == mode_M, "Sync node", 0 );
1042       };
1043       ASSERT_AND_RET( mymode == mode_M, "Sync node", 0 );
1044       break;
1045
1046     case iro_Proj:
1047       return vrfy_Proj_proj(n, irg);
1048       break;
1049
1050     case iro_Confirm:
1051       op1mode = get_irn_mode(in[1]);
1052       op2mode = get_irn_mode(in[2]);
1053       ASSERT_AND_RET_DBG(
1054     /* Confirm: BB x T x T --> T */
1055     op1mode == mymode &&
1056     op2mode == mymode,
1057     "Confirm node", 0,
1058     show_binop_failure(n, "/* Confirm: BB x T x T --> T */");
1059       );
1060       break;
1061
1062     default:
1063       break;
1064   }
1065
1066   /* All went ok */
1067   return 1;
1068 }
1069
1070 int irn_vrfy(ir_node *n)
1071 {
1072   int res = 1;
1073 #ifdef DEBUG_libfirm
1074   res = irn_vrfy_irg(n, current_ir_graph);
1075 #endif
1076   return res;
1077 }
1078
1079 /*******************************************************************/
1080 /* Verify the whole graph.                                         */
1081 /*******************************************************************/
1082
1083 /* This *is* used, except gcc doesn't notice that */
1084 static void vrfy_wrap(ir_node *node, void *env)
1085 {
1086   int *res = env;
1087
1088   *res = irn_vrfy(node);
1089 }
1090
1091 int irg_vrfy(ir_graph *irg)
1092 {
1093   int res = 1;
1094 #ifdef DEBUG_libfirm
1095   ir_graph *rem;
1096
1097   rem = current_ir_graph;
1098   current_ir_graph = irg;
1099
1100   assert(get_irg_pinned(irg) == pinned);
1101
1102   irg_walk(irg->end, vrfy_wrap, NULL, &res);
1103
1104   current_ir_graph = rem;
1105
1106   if (opt_do_node_verification == NODE_VERIFICATION_REPORT && ! res) {
1107     entity *ent = get_irg_entity(current_ir_graph);
1108
1109     if (ent)
1110       fprintf(stderr, "irg_verify: Verifying graph %s failed\n", get_entity_name(ent));
1111     else
1112       fprintf(stderr, "irg_verify: Verifying graph %p failed\n", (void *)current_ir_graph);
1113   }
1114
1115 #endif
1116   return res;
1117 }
1118
1119 int irn_vrfy_irg_dump(ir_node *n, ir_graph *irg, const char **bad_string)
1120 {
1121   int res;
1122   node_verification_t old = opt_do_node_verification;
1123
1124   bad_msg = NULL;
1125   opt_do_node_verification = NODE_VERIFICATION_ERROR_ONLY;
1126   res = irn_vrfy_irg(n, irg);
1127   opt_do_node_verification = old;
1128   *bad_string = bad_msg;
1129
1130   return res;
1131 }