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