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