Cleaned up, removed global File handle
[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_ent(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_ent(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_ent(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_nop(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 == pns_initial_exec   && mode == mode_X) ||
247            (proj == pns_global_store   && mode == mode_M) ||
248            (proj == pns_frame_base     && mode_is_reference(mode)) ||
249            (proj == pns_globals        && mode_is_reference(mode)) ||
250            (proj == pns_args           && mode == mode_T) ||
251            (proj == pns_value_arg_base && mode_is_reference(mode)) ||
252            (proj == pns_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_nop(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_ent(irg));
428
429         if (nr == pns_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 == pns_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_ent(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       tarval *tv = get_Const_tarval(n);
672       if (tarval_is_entity(tv))
673           ASSERT_AND_RET(
674                          (get_irn_irg(n) == get_const_code_irg()) ||
675                          (get_entity_peculiarity(get_tarval_entity(tv)) != peculiarity_description),
676                          "descriptions have no address", 0);
677           ASSERT_AND_RET(
678                          /* Const: BB --> data */
679                          (mode_is_data (mymode) ||
680                           mymode == mode_b)      /* we want boolean constants for static evaluation */
681                          ,"Const node", 0        /* of Cmp. */
682                          );
683      } break;
684
685     case iro_SymConst:
686       if (get_SymConst_kind(n) == symconst_addr_ent) {
687         entity *ent = get_SymConst_entity(n);
688         if (is_method_type(get_entity_type(ent)) &&
689             get_irn_irg(n) != get_const_code_irg()) {
690 #if 0
691           ASSERT_AND_RET((get_entity_peculiarity(ent) != peculiarity_description),
692                          "A constant must address an existing method.", 0);
693 #endif
694         }
695       }
696       ASSERT_AND_RET(
697                      /* SymConst: BB --> int*/
698                      (mode_is_int(mymode) ||
699                       /* SymConst: BB --> ref */
700                       mode_is_reference(mymode))
701                      ,"SymConst node", 0);
702       break;
703
704     case iro_Sel:
705       op1mode = get_irn_mode(in[1]);
706       op2mode = get_irn_mode(in[2]);
707       ASSERT_AND_RET_DBG(
708                          /* Sel: BB x M x ref x int^n --> ref */
709                          (op1mode == mode_M && op2mode == mymode && mode_is_reference(mymode)),
710                          "Sel node", 0, show_node_failure(n)
711                          );
712       for (i=3; i < get_irn_arity(n); i++)
713         {
714           ASSERT_AND_RET_DBG(mode_is_int(get_irn_mode(in[i])), "Sel node", 0, show_node_failure(n));
715         }
716       ent = get_Sel_entity(n);
717       ASSERT_AND_RET_DBG(ent, "Sel node with empty entity", 0, show_node_failure(n));
718       break;
719
720     case iro_InstOf:
721       ASSERT_AND_RET(mode_T == mymode, "mode of Instof is not a tuple", 0);
722       ASSERT_AND_RET(mode_is_data(op1mode), "Instof not on data", 0);
723       break;
724
725     case iro_Call:
726       op1mode = get_irn_mode(in[1]);
727       op2mode = get_irn_mode(in[2]);
728       /* Call: BB x M x ref x data1 x ... x datan
729          --> M x datan+1 x ... x data n+m */
730       ASSERT_AND_RET( op1mode == mode_M && mode_is_reference(op2mode), "Call node", 0 );  /* operand M x ref */
731       for (i=3; i < get_irn_arity(n); i++) {
732         ASSERT_AND_RET( mode_is_data(get_irn_mode(in[i])), "Call node", 0 );  /* operand datai */
733       };
734       ASSERT_AND_RET( mymode == mode_T, "Call result not a tuple", 0 );   /* result T */
735       /* Compare arguments of node with those of type */
736       mt = get_Call_type(n);
737
738       if (get_method_variadicity(mt) == variadicity_variadic) {
739         ASSERT_AND_RET_DBG(
740                            get_Call_n_params(n) >= get_method_n_params(mt),
741                            "Number of args for Call doesn't match number of args in variadic type.",
742                            0,
743                            fprintf(stderr, "Call has %d params, method %s type %d\n",
744                                    get_Call_n_params(n), get_type_name(mt), get_method_n_params(mt));
745                            );
746       }
747       else {
748         ASSERT_AND_RET(
749                        get_Call_n_params(n) == get_method_n_params(mt),
750                        "Number of args for Call doesn't match number of args in non variadic type.",
751                        0);
752       }
753
754       for (i = 0; i < get_method_n_params(mt); i++) {
755     type *t = get_method_param_type(mt, i);
756
757     if (is_atomic_type(t)) {
758       ASSERT_AND_RET_DBG(
759           get_irn_mode(get_Call_param(n, i)) == get_type_mode(t),
760           "Mode of arg for Call doesn't match mode of arg type.", 0,
761       show_call_param(n, mt);
762       );
763     }
764     else {
765       /* call with a compound type, mode must be reference */
766       ASSERT_AND_RET_DBG(
767           mode_is_reference(get_irn_mode(get_Call_param(n, i))),
768           "Mode of arg for Call doesn't match mode of arg type.", 0,
769       show_call_param(n, mt);
770       );
771     }
772       }
773       break;
774
775     case iro_Add:
776       op1mode = get_irn_mode(in[1]);
777       op2mode = get_irn_mode(in[2]);
778       ASSERT_AND_RET_DBG(
779                          (
780                           /* common Add: BB x numP x numP --> numP */
781                           (op1mode == mymode && op2mode == op1mode && mode_is_numP(mymode)) ||
782                           /* Pointer Add: BB x ref x int --> ref */
783                           (mode_is_reference(op1mode) && mode_is_int(op2mode) && op1mode == mymode) ||
784                           /* Pointer Add: BB x int x ref --> ref */
785                           (mode_is_int(op1mode) && op2mode == mymode && mode_is_reference(mymode))
786                           ),
787                          "Add node", 0,
788                          show_binop_failure(n, "/* common Add: BB x numP x numP --> numP */ |\n"
789                                             "/* Pointer Add: BB x ref x int --> ref */   |\n"
790                                             "/* Pointer Add: BB x int x ref --> ref */");
791                          );
792       if (mode_is_reference(op1mode) != mode_is_reference(op2mode)) {
793         /* BB x ref x int --> ref or BB x int x ref --> ref */
794         op_is_symmetric = 0;
795       } else {
796         /* BB x num x num --> num or BB x ref x ref */
797         op_is_symmetric = 2;
798       }
799       break;
800
801     case iro_Sub:
802       op1mode = get_irn_mode(in[1]);
803       op2mode = get_irn_mode(in[2]);
804       ASSERT_AND_RET_DBG(
805                          /* common Sub: BB x numP x numP --> numP */
806                          ((mymode ==op1mode && mymode == op2mode && mode_is_numP(op1mode)) ||
807                           /* Pointer Sub: BB x ref x int --> ref */
808                           (op1mode == mymode && mode_is_int(op2mode) && mode_is_reference(mymode)) ||
809                           /* Pointer Sub: BB x int x ref --> ref */
810                           (mode_is_int(op1mode) && op2mode == mymode && mode_is_reference(mymode)) ||
811                           /* Pointer Sub: BB x ref x ref --> int */
812                           (op1mode == op2mode && mode_is_reference(op2mode) && mode_is_int(mymode))),
813                          "Sub node", 0,
814                          show_binop_failure(n, "/* common Sub: BB x numP x numP --> numP */ |\n"
815                                             "/* Pointer Sub: BB x ref x int --> ref */   |\n"
816                                             "/* Pointer Sub: BB x int x ref --> ref */   |\n"
817                                             "/* Pointer Sub: BB x ref x ref --> int */" );
818                          );
819       if (mode_is_reference(op1mode) != mode_is_reference(op2mode)) {
820         op_is_symmetric = 0;
821       } else {
822         op_is_symmetric = 2;
823       }
824       break;
825
826     case iro_Minus:
827       op1mode = get_irn_mode(in[1]);
828       ASSERT_AND_RET_DBG(
829                          /* Minus: BB x float --> float */
830                          op1mode == mymode && get_mode_sort(op1mode) == irms_float_number, "Minus node", 0,
831                          show_unop_failure(n , "/* Minus: BB x float --> float */");
832                          );
833       op_is_symmetric = 2;
834       break;
835
836     case iro_Mul:
837       op1mode = get_irn_mode(in[1]);
838       op2mode = get_irn_mode(in[2]);
839       ASSERT_AND_RET_DBG(
840                          /* Mul: BB x int1 x int1 --> int2 */
841                          ((mode_is_int(op1mode)   && op2mode == op1mode && mode_is_int(mymode)) ||
842                          /* Mul: BB x float x float --> float */
843                           (mode_is_float(op1mode) && op2mode == op1mode && mymode == op1mode)),
844                          "Mul node",0,
845                          show_binop_failure(n, "/* Mul: BB x int1 x int1 --> int2 */ |\n"
846                                                "/* Mul: BB x float x float --> float */");
847                          );
848       op_is_symmetric = 2;
849       break;
850
851     case iro_Quot:
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_DBG(
856                          /* Quot: BB x M x float x float --> M x X x float */
857                          op1mode == mode_M && op2mode == op3mode &&
858                          get_mode_sort(op2mode) == irms_float_number &&
859                          mymode == mode_T,
860                          "Quot node",0,
861                          show_binop_failure(n, "/* Quot: BB x M x float x float --> M x X x float */");
862                          );
863       op_is_symmetric = 2;
864       break;
865
866     case iro_DivMod:
867       op1mode = get_irn_mode(in[1]);
868       op2mode = get_irn_mode(in[2]);
869       op3mode = get_irn_mode(in[3]);
870       ASSERT_AND_RET(
871                      /* DivMod: BB x M x int x int --> M x X x int x int */
872                      op1mode == mode_M &&
873                      mode_is_int(op2mode) &&
874                      op3mode == op2mode &&
875                      mymode == mode_T,
876                      "DivMod node", 0
877                      );
878       op_is_symmetric = 1;
879       break;
880
881     case iro_Div:
882     case iro_Mod:
883       op1mode = get_irn_mode(in[1]);
884       op2mode = get_irn_mode(in[2]);
885       op3mode = get_irn_mode(in[3]);
886       ASSERT_AND_RET(
887                      /* Div or Mod: BB x M x int x int --> M x X x int */
888                      op1mode == mode_M &&
889                      op2mode == op3mode &&
890                      mode_is_int(op2mode) &&
891                      mymode == mode_T,
892                      "Div or Mod node", 0
893                      );
894       op_is_symmetric = 1;
895       break;
896
897     case iro_Abs:
898       op1mode = get_irn_mode(in[1]);
899       ASSERT_AND_RET_DBG(
900                          /* Abs: BB x num --> num */
901                          op1mode == mymode &&
902                          mode_is_num (op1mode),
903                          "Abs node", 0,
904                          show_unop_failure(n, "/* Abs: BB x num --> num */");
905                          );
906       op_is_symmetric = 2;
907       break;
908
909     case iro_And:
910     case iro_Or:
911     case iro_Eor:
912       op1mode = get_irn_mode(in[1]);
913       op2mode = get_irn_mode(in[2]);
914       ASSERT_AND_RET_DBG(
915                          /* And or Or or Eor: BB x int x int --> int */
916                          mode_is_int(mymode) &&
917                          op2mode == op1mode &&
918                          mymode == op2mode,
919                          "And, Or or Eor node", 0,
920                          show_binop_failure(n, "/* And or Or or Eor: BB x int x int --> int */");
921                          );
922       op_is_symmetric = 2;
923       break;
924
925     case iro_Not:
926       op1mode = get_irn_mode(in[1]);
927       ASSERT_AND_RET_DBG(
928                          /* Not: BB x int --> int */
929                          mode_is_int(mymode) &&
930                          mymode == op1mode,
931                          "Not node", 0,
932                          show_unop_failure(n, "/* Not: BB x int --> int */");
933                          );
934       op_is_symmetric = 2;
935       break;
936
937
938     case iro_Cmp:
939       op1mode = get_irn_mode(in[1]);
940       op2mode = get_irn_mode(in[2]);
941       ASSERT_AND_RET_DBG(
942                          /* Cmp: BB x datab x datab --> b16 */
943                          mode_is_data (op1mode) &&
944                          op2mode == op1mode &&
945                          mymode == mode_T,
946                          "Cmp node", 0,
947                          show_binop_failure(n, "/* Cmp: BB x datab x datab --> b16 */");
948                          );
949       break;
950
951     case iro_Shl:
952     case iro_Shr:
953     case iro_Shrs:
954       op1mode = get_irn_mode(in[1]);
955       op2mode = get_irn_mode(in[2]);
956       ASSERT_AND_RET_DBG(
957                          /* Shl, Shr or Shrs: BB x int x int_u --> int */
958                          mode_is_int(op1mode) &&
959                          mode_is_int(op2mode) &&
960                          !mode_is_signed(op2mode) &&
961                          mymode == op1mode,
962                          "Shl, Shr, Shr or Rot node", 0,
963                          show_binop_failure(n, "/* Shl, Shr or Shrs: BB x int x int_u --> int */");
964                          );
965       break;
966
967     case iro_Rot:
968       op1mode = get_irn_mode(in[1]);
969       op2mode = get_irn_mode(in[2]);
970       ASSERT_AND_RET_DBG(
971                          /* Rot: BB x int x int --> int */
972                          mode_is_int(op1mode) &&
973                          mode_is_int(op2mode) &&
974                          mymode == op1mode,
975                          "Rot node", 0,
976                          show_binop_failure(n, "/* Rot: BB x int x int --> int */");
977                          );
978       break;
979
980     case iro_Conv:
981       op1mode = get_irn_mode(in[1]);
982       ASSERT_AND_RET_DBG(
983                          /* Conv: BB x datab1 --> datab2 */
984                          mode_is_datab(op1mode) && mode_is_data(mymode),
985                          "Conv node", 0,
986                          show_unop_failure(n, "/* Conv: BB x datab1 --> datab2 */");
987                          );
988       break;
989
990     case iro_Cast:
991       op1mode = get_irn_mode(in[1]);
992       ASSERT_AND_RET_DBG(
993                          /* Conv: BB x datab1 --> datab2 */
994                          mode_is_data(op1mode) && op1mode == mymode,
995                          "Cast node", 0,
996                          show_unop_failure(n, "/* Conv: BB x datab1 --> datab2 */");
997                          );
998       break;
999
1000     case iro_Phi:
1001       /* Phi: BB x dataM^n --> dataM */
1002       for (i = 1; i < get_irn_arity(n); i++) {
1003         if (!is_Bad(in[i]) && (get_irn_op(in[i]) != op_Unknown))
1004           ASSERT_AND_RET_DBG(
1005                              get_irn_mode(in[i]) == mymode,
1006                              "Phi node", 0,
1007                              show_phi_failure(n, in[i], i);
1008                              );
1009       };
1010       ASSERT_AND_RET( mode_is_dataM(mymode), "Phi node", 0 );
1011       break;
1012
1013     case iro_Load:
1014       op1mode = get_irn_mode(in[1]);
1015       op2mode = get_irn_mode(in[2]);
1016       ASSERT_AND_RET(
1017                      /* Load: BB x M x ref --> M x X x data */
1018                      op1mode == mode_M && mode_is_reference(op2mode),
1019                      "Load node", 0
1020                      );
1021       ASSERT_AND_RET( mymode == mode_T, "Load node", 0 );
1022
1023       /*
1024        * jack's gen_add_firm_code:simpleSel seems to build Load (Load
1025        * (Proj (Proj))) sometimes ...
1026
1027        * interprete.c:ai_eval seems to assume that this happens, too
1028
1029        * obset.c:get_abstval_any can't deal with this if the load has
1030        * mode_T
1031        *
1032       {
1033         entity *ent = hunt_for_entity (get_Load_ptr (n), n);
1034         assert ((NULL != ent) || (mymode != mode_T));
1035       }
1036       */
1037
1038       break;
1039
1040     case iro_Store:
1041       op1mode = get_irn_mode(in[1]);
1042       op2mode = get_irn_mode(in[2]);
1043       op3mode = get_irn_mode(in[3]);
1044       ASSERT_AND_RET(
1045                      /* Load: BB x M x ref data --> M x X */
1046                      op1mode == mode_M && mode_is_reference(op2mode) && mode_is_data(op3mode),
1047                      "Store node", 0
1048                      );
1049       ASSERT_AND_RET(mymode == mode_T, "Store node", 0);
1050       break;
1051
1052     case iro_Alloc:
1053       op1mode = get_irn_mode(in[1]);
1054       op2mode = get_irn_mode(in[2]);
1055       ASSERT_AND_RET_DBG(
1056                          /* Alloc: BB x M x int_u --> M x X x ref */
1057                          op1mode == mode_M &&
1058                          mode_is_int(op2mode) &&
1059                          !mode_is_signed(op2mode) &&
1060                          mymode == mode_T,
1061                          "Alloc node", 0,
1062                          show_binop_failure(n, "/* Alloc: BB x M x int_u --> M x X x ref */");
1063                          );
1064       break;
1065
1066     case iro_Free:
1067       op1mode = get_irn_mode(in[1]);
1068       op2mode = get_irn_mode(in[2]);
1069       ASSERT_AND_RET_DBG(
1070                          /* Free: BB x M x ref --> M */
1071                          op1mode == mode_M && mode_is_reference(op2mode) &&
1072                          mymode == mode_M,
1073                          "Free node", 0,
1074                          show_binop_failure(n, "/* Free: BB x M x ref --> M */");
1075                          );
1076       break;
1077
1078     case iro_Sync:
1079       /* Sync: BB x M^n --> M */
1080       for (i=1; i < get_irn_arity(n); i++) {
1081         ASSERT_AND_RET( get_irn_mode(in[i]) == mode_M, "Sync node", 0 );
1082       };
1083       ASSERT_AND_RET( mymode == mode_M, "Sync node", 0 );
1084       break;
1085
1086     case iro_Proj:
1087       return vrfy_Proj_proj(n, irg);
1088       break;
1089
1090     case iro_Confirm:
1091       op1mode = get_irn_mode(in[1]);
1092       op2mode = get_irn_mode(in[2]);
1093       ASSERT_AND_RET_DBG(
1094                          /* Confirm: BB x T x T --> T */
1095                          op1mode == mymode &&
1096                          op2mode == mymode,
1097                          "Confirm node", 0,
1098                          show_binop_failure(n, "/* Confirm: BB x T x T --> T */");
1099                          );
1100       break;
1101
1102     default:
1103       break;
1104     }
1105
1106   /* All went ok */
1107   return 1;
1108 }
1109
1110 int irn_vrfy(ir_node *n)
1111 {
1112   int res = 1;
1113 #ifdef DEBUG_libfirm
1114   res = irn_vrfy_irg(n, current_ir_graph);
1115 #endif
1116   return res;
1117 }
1118
1119 /*-----------------------------------------------------------------*/
1120 /* Verify the whole graph.                                         */
1121 /*-----------------------------------------------------------------*/
1122
1123 /* This *is* used, except gcc doesn't notice that */
1124 static void vrfy_wrap(ir_node *node, void *env)
1125 {
1126   int *res = env;
1127
1128   *res = irn_vrfy(node);
1129 }
1130
1131 int irg_vrfy(ir_graph *irg)
1132 {
1133   int res = 1;
1134 #ifdef DEBUG_libfirm
1135   ir_graph *rem;
1136
1137   rem = current_ir_graph;
1138   current_ir_graph = irg;
1139
1140   assert(get_irg_pinned(irg) == pinned);
1141
1142   irg_walk(irg->end, vrfy_wrap, NULL, &res);
1143
1144   current_ir_graph = rem;
1145
1146   if (opt_do_node_verification == NODE_VERIFICATION_REPORT && ! res) {
1147     entity *ent = get_irg_entity(current_ir_graph);
1148
1149     if (ent)
1150       fprintf(stderr, "irg_verify: Verifying graph %s failed\n", get_entity_name(ent));
1151     else
1152       fprintf(stderr, "irg_verify: Verifying graph %p failed\n", (void *)current_ir_graph);
1153   }
1154
1155 #endif
1156   return res;
1157 }
1158
1159 int irn_vrfy_irg_dump(ir_node *n, ir_graph *irg, const char **bad_string)
1160 {
1161   int res;
1162   node_verification_t old = opt_do_node_verification;
1163
1164   bad_msg = NULL;
1165   opt_do_node_verification = NODE_VERIFICATION_ERROR_ONLY;
1166   res = irn_vrfy_irg(n, irg);
1167   opt_do_node_verification = old;
1168   *bad_string = bad_msg;
1169
1170   return res;
1171 }