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