some fixes for xml dumper / still buggy.
[libfirm] / ir / ir / irvrfy.c
1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
2  * All rights reserved.
3  *
4  * Authors: Christian Schaefer
5  *
6  *
7  */
8
9 /* $Id$ */
10
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14
15 # include "irgraph_t.h"
16 # include "irvrfy.h"
17 # include "irgwalk.h"
18
19 #ifdef NDEBUG
20 #define ASSERT_AND_RET(expr, string, ret)  if (!(expr)) return (ret)
21 #else
22 #define ASSERT_AND_RET(expr, string, ret)  do { assert((expr) && string); if (!(expr)) return (ret); } while(0)
23 #endif
24
25 /* @@@ replace use of array "in" by access functions. */
26 ir_node **get_irn_in(ir_node *node);
27
28 INLINE static int
29 vrfy_Proj_proj(ir_node *p, ir_graph *irg) {
30   ir_node *pred;
31   ir_mode *mode;
32   int proj;
33
34   pred = skip_nop(get_Proj_pred(p));
35   assert(get_irn_mode(pred) == mode_T);
36   mode = get_irn_mode(p);
37   proj = get_Proj_proj(p);
38
39   switch (get_irn_opcode(pred)) {
40     case iro_Start:
41       ASSERT_AND_RET(
42           (
43            (proj == pns_initial_exec   && mode == mode_X) ||
44            (proj == pns_global_store   && mode == mode_M) ||
45            (proj == pns_frame_base     && mode_is_reference(mode)) ||
46            (proj == pns_globals        && mode_is_reference(mode)) ||
47            (proj == pns_args           && mode == mode_T) ||
48            (proj == pns_value_arg_base && mode_is_reference(mode))
49           ),
50           "wrong Proj from Start", 0);
51       break;
52
53     case iro_Cond:
54       ASSERT_AND_RET( (proj >= 0 && mode == mode_X), "wrong Proj from Cond", 0);
55       break;
56
57     case iro_Raise:
58       ASSERT_AND_RET(
59           ((proj == 0 && mode == mode_X) ||
60            (proj == 1 && mode == mode_M)),
61           "wrong Proj from Raise", 0);
62       break;
63
64     case iro_InstOf:
65       ASSERT_AND_RET( (proj >= 0 && mode == mode_X), "wrong Proj from InstOf", 0);
66       break;
67
68     case iro_Call:
69       ASSERT_AND_RET(
70           ((proj == 0 && mode == mode_M) ||
71            (proj == 1 && mode == mode_X) ||
72            (proj == 2 && mode == mode_T) ||
73            (proj == 3 && mode == mode_M)),
74           "wrong Proj from Call", 0);
75       break;
76
77     case iro_Quot:
78       ASSERT_AND_RET(
79           ((proj == 0 && mode == mode_M) ||
80            (proj == 1 && mode == mode_X) ||
81            (proj == 2 && mode_is_float(mode))),
82           "wrong Proj from Quot", 0);
83       break;
84
85     case iro_DivMod:
86       ASSERT_AND_RET(
87           ((proj == 0 && mode == mode_M) ||
88            (proj == 1 && mode == mode_X) ||
89            (proj == 2 && mode == mode_Is) ||
90            (proj == 3 && mode_is_int(mode))),
91           "wrong Proj from DivMod", 0);
92       break;
93
94     case iro_Div:
95     case iro_Mod:
96       ASSERT_AND_RET(
97           ((proj == 0 && mode == mode_M) ||
98            (proj == 1 && mode == mode_X) ||
99            (proj == 2 && mode_is_int(mode))),
100           "wrong Proj from Div or Mod", 0);
101       break;
102
103     case iro_Cmp:
104       ASSERT_AND_RET(
105           (proj >= 0 && proj <= 15 && mode == mode_b),
106           "wrong Proj from Cmp", 0);
107       break;
108
109     case iro_Load:
110       ASSERT_AND_RET(
111           ((proj == 0 && mode == mode_M) ||
112            (proj == 1 && mode == mode_X) ||
113            (proj == 2 && mode_is_data(mode))),
114           "wrong Proj from Load", 0);
115       break;
116
117     case iro_Store:
118       ASSERT_AND_RET(
119           ((proj == 0 && mode == mode_M) ||
120            (proj == 1 && mode == mode_X)),
121           "wrong Proj from Store", 0);
122       break;
123
124     case iro_Alloc:
125       ASSERT_AND_RET(
126           (
127            (proj == 0 && mode == mode_M) ||
128            (proj == 1 /* && mode == mode_X*/) ||
129            (proj == 2 && mode_is_reference(mode))
130           ),
131           "wrong Proj from Alloc", 0);
132       break;
133
134     case iro_Proj:
135       {
136         type *mt; /* A method type */
137         pred = skip_nop(get_Proj_pred(pred));
138         ASSERT_AND_RET((get_irn_mode(pred) == mode_T), "Proj from something not a tuple", 0);
139         switch (get_irn_opcode(pred))
140         {
141           case iro_Start:
142             {
143               ASSERT_AND_RET(
144                   (proj >= 0 && mode_is_data(mode)),
145                   "wrong Proj from Proj from Start", 0);
146               mt = get_entity_type(get_irg_ent(irg));
147               ASSERT_AND_RET(
148                   (proj < get_method_n_params(mt)),
149                   "More Projs for args than args in type", 0);
150               if ((mode_is_reference(mode)) && is_compound_type(get_method_param_type(mt, proj)))
151                 /* value argument */ break;
152
153               ASSERT_AND_RET(
154                   (mode == get_type_mode(get_method_param_type(mt, proj))),
155                   "Mode of Proj from Start doesn't match mode of param type.", 0);
156             }
157             break;
158
159           case iro_Call:
160             {
161               ASSERT_AND_RET(
162                   (proj >= 0 && mode_is_data(mode)),
163                   "wrong Proj from Proj from Call", 0);
164               mt = get_Call_type(pred);
165               ASSERT_AND_RET(
166                   (proj < get_method_n_ress(mt)),
167                   "More Projs for results than results in type.", 0);
168               if ((mode_is_reference(mode)) && is_compound_type(get_method_res_type(mt, proj)))
169                 /* value result */ break;
170
171               ASSERT_AND_RET(
172                   (mode == get_type_mode(get_method_res_type(mt, proj))),
173                   "Mode of Proj from Call doesn't match mode of result type.", 0);
174             }
175             break;
176
177           case iro_Tuple:
178             /* We don't test */
179             break;
180
181           default:
182             ASSERT_AND_RET(0, "Unknown opcode", 0);
183         }
184         break;
185
186       }
187     case iro_Tuple:
188       /* We don't test */
189       break;
190
191     case iro_CallBegin:
192       break;
193
194     case iro_EndReg:
195       break;
196
197     case iro_EndExcept:
198       break;
199
200     default:
201       ASSERT_AND_RET(0, "Unknown opcode", 0);
202   }
203
204   /* all went ok */
205   return 1;
206 }
207
208 int irn_vrfy_irg(ir_node *n, ir_graph *irg)
209 {
210   int i;
211   int opcode, opcode1;
212   ir_mode *mymode, *op1mode = NULL, *op2mode, *op3mode;
213   int op_is_symmetric = 1;  /*  0: asymmetric
214 1: operands have identical modes
215 2: modes of operands == mode of this node */
216   type *mt; /* A method type */
217
218   ir_node **in;
219
220   if (! interprocedural_view) {
221     /*
222      * do NOT check placement in interprocedural view, as we don't always know
223      * the "right" graph ...
224      */
225     ASSERT_AND_RET(node_is_in_irgs_storage(irg, n), "Node is not stored on proper IR graph!", 0);
226   }
227
228   opcode = get_irn_opcode (n);
229
230   /* We don't want to test nodes whose predecessors are Bad or Unknown,
231      as we would have to special case that for each operation. */
232   if (opcode != iro_Phi && opcode != iro_Block)
233     for (i = 0; i < get_irn_arity(n); i++) {
234       opcode1 = get_irn_opcode(get_irn_n(n, i));
235       if (opcode1 == iro_Bad || opcode1 == iro_Unknown)
236         return 1;
237     }
238
239   mymode = get_irn_mode (n);
240   in = get_irn_in (n);
241
242   switch (opcode)
243   {
244     case iro_Start:
245       ASSERT_AND_RET(
246           /* Start: BB --> X x M x ref x data1 x ... x datan x ref */
247           mymode == mode_T, "Start node", 0
248           );
249       break;
250
251     case iro_Jmp:
252       ASSERT_AND_RET(
253           /* Jmp: BB --> X */
254           mymode == mode_X, "Jmp node", 0
255           );
256       break;
257
258     case iro_Break:
259       ASSERT_AND_RET(
260           /* Jmp: BB --> X */
261           mymode == mode_X, "Jmp node", 0
262           );
263       break;
264
265     case iro_Cond:
266       op1mode = get_irn_mode(in[1]);
267       ASSERT_AND_RET(
268           /* Cond: BB x b --> X x X */
269           (op1mode == mode_b ||
270            /* Cond: BB x int --> X^n */
271            mode_is_int(op1mode) ),  "Cond node", 0
272           );
273       ASSERT_AND_RET(mymode == mode_T, "Cond mode is not a tuple", 0);
274       break;
275
276     case iro_Return:
277       op1mode = get_irn_mode(in[1]);
278       /* Return: BB x M x data1 x ... x datan --> X */
279       /* printf("mode: %s, code %s\n", ID_TO_STR(n->mode->name), ID_TO_STR(n->op->name));*/
280       ASSERT_AND_RET( op1mode == mode_M, "Return node", 0 );  /* operand M */
281       for (i=2; i < get_irn_arity(n); i++) {
282         ASSERT_AND_RET( mode_is_data(get_irn_mode(in[i])), "Return node", 0 );  /* operand datai */
283       };
284       ASSERT_AND_RET( mymode == mode_X, "Result X", 0 );   /* result X */
285       /* Compare returned results with result types of method type */
286       mt = get_entity_type(get_irg_ent(irg));
287       ASSERT_AND_RET( get_Return_n_ress(n) == get_method_n_ress(mt),
288           "Number of results for Return doesn't match number of results in type.", 0 );
289       for (i = 0; i < get_Return_n_ress(n); i++)
290         ASSERT_AND_RET(
291             get_irn_mode(get_Return_res(n, i)) == get_type_mode(get_method_res_type(mt, i)),
292             "Mode of result for Return doesn't match mode of result type.", 0);
293       break;
294
295     case iro_Raise:
296       op1mode = get_irn_mode(in[1]);
297       op2mode = get_irn_mode(in[2]);
298       ASSERT_AND_RET(
299           /* Sel: BB x M x ref --> X x M */
300           op1mode == mode_M && mode_is_reference(op2mode) &&
301           mymode == mode_T, "Raise node", 0
302           );
303       break;
304
305     case iro_Const:
306       ASSERT_AND_RET(
307           /* Const: BB --> data */
308           (mode_is_data (mymode) ||
309            mymode == mode_b)      /* we want boolean constants for static evaluation */
310           ,"Const node", 0        /* of Cmp. */
311           );
312       break;
313
314     case iro_SymConst:
315       ASSERT_AND_RET(
316           /* SymConst: BB --> int*/
317           (mode_is_int(mymode) ||
318            /* SymConst: BB --> ref */
319            mode_is_reference(mymode))
320           ,"SymConst node", 0);
321       break;
322
323     case iro_Sel:
324       op1mode = get_irn_mode(in[1]);
325       op2mode = get_irn_mode(in[2]);
326       ASSERT_AND_RET(
327           /* Sel: BB x M x ref x int^n --> ref */
328           (op1mode == mode_M && op2mode == mymode && mode_is_reference(mymode)),
329           "Sel node", 0
330           );
331       for (i=3; i < get_irn_arity(n); i++)
332       {
333         ASSERT_AND_RET(mode_is_int(get_irn_mode(in[i])), "Sel node", 0);
334       }
335       break;
336
337     case iro_InstOf:
338       ASSERT_AND_RET(mode_T == mymode, "mode of Instof is not a tuple", 0);
339       ASSERT_AND_RET(mode_is_data(op1mode), "Instof not on data", 0);
340       break;
341
342     case iro_Call:
343       op1mode = get_irn_mode(in[1]);
344       op2mode = get_irn_mode(in[2]);
345       /* Call: BB x M x ref x data1 x ... x datan
346          --> M x datan+1 x ... x data n+m */
347       ASSERT_AND_RET( op1mode == mode_M && mode_is_reference(op2mode), "Call node", 0 );  /* operand M x ref */
348       for (i=3; i < get_irn_arity(n); i++) {
349         ASSERT_AND_RET( mode_is_data(get_irn_mode(in[i])), "Call node", 0 );  /* operand datai */
350       };
351       ASSERT_AND_RET( mymode == mode_T, "Call result not a tuple", 0 );   /* result T */
352       /* Compare arguments of node with those of type */
353       mt = get_Call_type(n);
354
355       if (get_method_variadicity(mt) == variadic) {
356         ASSERT_AND_RET(
357             get_Call_n_params(n) >= get_method_n_params(mt),
358             "Number of args for Call doesn't match number of args in variadic type.",
359             0);
360       }
361       else {
362         ASSERT_AND_RET(
363             get_Call_n_params(n) == get_method_n_params(mt),
364             "Number of args for Call doesn't match number of args in non variadic type.",
365             0);
366       }
367
368       for (i = 0; i < get_method_n_params(mt); i++) {
369         ASSERT_AND_RET(
370             get_irn_mode(get_Call_param(n, i)) == get_type_mode(get_method_param_type(mt, i)),
371             "Mode of arg for Call doesn't match mode of arg type.", 0);
372       }
373       break;
374
375     case iro_Add:
376       op1mode = get_irn_mode(in[1]);
377       op2mode = get_irn_mode(in[2]);
378       ASSERT_AND_RET(
379           (
380            /* common Add: BB x numP x numP --> numP */
381            (op1mode == mymode && op2mode == op1mode && mode_is_numP(mymode)) ||
382            /* Pointer Add: BB x ref x int --> ref */
383            (mode_is_reference(op1mode) && mode_is_int(op2mode) && op1mode == mymode) ||
384            /* Pointer Add: BB x int x ref --> ref */
385            (mode_is_int(op1mode) && op2mode == mymode && mode_is_reference(mymode))
386           ),
387           "Add node", 0
388           );
389       if (mode_is_reference(op1mode) != mode_is_reference(op2mode)) {
390         /* BB x ref x int --> ref or BB x int x ref --> ref */
391         op_is_symmetric = 0; /* ArmRoq */
392       } else {
393         /* BB x num x num --> num or BB x ref x ref */
394         op_is_symmetric = 2;
395       }
396       break;
397
398     case iro_Sub:
399       op1mode = get_irn_mode(in[1]);
400       op2mode = get_irn_mode(in[2]);
401       ASSERT_AND_RET(
402           /* common Sub: BB x numP x numP --> numP */
403           ((mymode ==op1mode && mymode == op2mode && mode_is_numP(op1mode)) ||
404            /* Pointer Sub: BB x ref x int --> ref */
405            (op1mode == mymode && mode_is_int(op2mode) && mode_is_reference(mymode)) ||
406            /* Pointer Sub: BB x int x ref --> ref */
407            (mode_is_int(op1mode) && op2mode == mymode && mode_is_reference(mymode)) ||
408            /* Pointer Sub: BB x ref x ref --> int */
409            (op1mode == op2mode && mode_is_reference(op2mode) && mode_is_int(mymode))),
410           "Sub node", 0
411           );
412       if (mode_is_reference(op1mode) != mode_is_reference(op2mode)) {
413         op_is_symmetric = 0; /* ArmRoq */
414       } else {
415         op_is_symmetric = 2;
416       }
417       break;
418
419     case iro_Minus:
420       op1mode = get_irn_mode(in[1]);
421       ASSERT_AND_RET(
422           /* Minus: BB x float --> float */
423           op1mode == mymode && get_mode_sort(op1mode) == irms_float_number, "Minus node", 0
424           );
425       op_is_symmetric = 2;
426       break;
427
428     case iro_Mul:
429       op1mode = get_irn_mode(in[1]);
430       op2mode = get_irn_mode(in[2]);
431       ASSERT_AND_RET(
432           /* Mul: BB x int1 x int1 --> int2 */
433           ((mode_is_int(op1mode)   && op2mode == op1mode && mode_is_int(mymode)) ||
434            (mode_is_float(op1mode) && op2mode == op1mode && mymode == op1mode)),
435           "Mul node",0
436           );
437       op_is_symmetric = 2;
438       break;
439
440     case iro_Quot:
441       op1mode = get_irn_mode(in[1]);
442       op2mode = get_irn_mode(in[2]);
443       op3mode = get_irn_mode(in[3]);
444       ASSERT_AND_RET(
445           /* Quot: BB x M x float x float --> M x X x float */
446           op1mode == mode_M && op2mode == op3mode &&
447           get_mode_sort(op2mode) == irms_float_number &&
448           mymode == mode_T,
449           "Quot node",0
450           );
451       op_is_symmetric = 2;
452       break;
453
454     case iro_DivMod:
455       op1mode = get_irn_mode(in[1]);
456       op2mode = get_irn_mode(in[2]);
457       op3mode = get_irn_mode(in[3]);
458       ASSERT_AND_RET(
459           /* DivMod: BB x M x int x int --> M x X x int x int */
460           op1mode == mode_M &&
461           mode_is_int(op2mode) &&
462           op3mode == op2mode &&
463           mymode == mode_T,
464           "DivMod node", 0
465           );
466       op_is_symmetric = 1;
467       break;
468
469     case iro_Div:
470     case iro_Mod:
471       op1mode = get_irn_mode(in[1]);
472       op2mode = get_irn_mode(in[2]);
473       op3mode = get_irn_mode(in[3]);
474       ASSERT_AND_RET(
475           /* Div or Mod: BB x M x int x int --> M x X x int */
476           op1mode == mode_M &&
477           op2mode == op3mode &&
478           mode_is_int(op2mode) &&
479           mymode == mode_T,
480           "Div or Mod node", 0
481           );
482       op_is_symmetric = 1;
483       break;
484
485     case iro_Abs:
486       op1mode = get_irn_mode(in[1]);
487       ASSERT_AND_RET(
488           /* Abs: BB x num --> num */
489           op1mode == mymode &&
490           mode_is_num (op1mode),
491           "Abs node",0
492           );
493       op_is_symmetric = 2;
494       break;
495
496     case iro_And:
497     case iro_Or:
498     case iro_Eor:
499       op1mode = get_irn_mode(in[1]);
500       op2mode = get_irn_mode(in[2]);
501       ASSERT_AND_RET(
502           /* And or Or or Eor: BB x int x int --> int */
503           mode_is_int(mymode) &&
504           op2mode == op1mode &&
505           mymode == op2mode,
506           "And, Or or Eor node", 0
507           );
508       op_is_symmetric = 2;
509       break;
510
511     case iro_Not:
512       op1mode = get_irn_mode(in[1]);
513       ASSERT_AND_RET(
514           /* Not: BB x int --> int */
515           mode_is_int(mymode) &&
516           mymode == op1mode,
517           "Not node", 0
518           );
519       op_is_symmetric = 2;
520       break;
521
522
523     case iro_Cmp:
524       op1mode = get_irn_mode(in[1]);
525       op2mode = get_irn_mode(in[2]);
526       ASSERT_AND_RET(
527           /* Cmp: BB x datab x datab --> b16 */
528           mode_is_data (op1mode) &&
529           op2mode == op1mode &&
530           mymode == mode_T,
531           "Cmp node", 0
532           );
533       break;
534
535     case iro_Shl:
536     case iro_Shr:
537     case iro_Shrs:
538       op1mode = get_irn_mode(in[1]);
539       op2mode = get_irn_mode(in[2]);
540       assert(
541           /* Shl, Shr or Shrs: BB x int x int_u --> int */
542           mode_is_int(op1mode) &&
543           mode_is_int(op2mode) &&
544           !mode_is_signed(op2mode) &&
545           mymode == op1mode &&
546           "Shl, Shr, Shr or Rot node"
547           );
548       break;
549
550     case iro_Rot:
551       op1mode = get_irn_mode(in[1]);
552       op2mode = get_irn_mode(in[2]);
553       ASSERT_AND_RET(
554           /* Rot: BB x int x int --> int */
555           mode_is_int(op1mode) &&
556           mode_is_int(op2mode) &&
557           mymode == op1mode,
558           "Rot node",0
559           );
560       break;
561
562     case iro_Conv:
563       op1mode = get_irn_mode(in[1]);
564       ASSERT_AND_RET(
565           /* Conv: BB x datab1 --> datab2 */
566           mode_is_datab(op1mode) && mode_is_data(mymode),
567           "Conv node", 0
568           );
569       break;
570
571     case iro_Phi:
572       /* Phi: BB x dataM^n --> dataM */
573       /* for some reason "<=" aborts. int there a problem with get_store? */
574       for (i=1; i < get_irn_arity(n); i++) {
575         if (!is_Bad(in[i]) && (get_irn_op(in[i]) != op_Unknown))
576           ASSERT_AND_RET( get_irn_mode(in[i]) == mymode, "Phi node", 0);
577       };
578       ASSERT_AND_RET( mode_is_dataM(mymode), "Phi node", 0 );
579       break;
580
581     case iro_Load:
582       op1mode = get_irn_mode(in[1]);
583       op2mode = get_irn_mode(in[2]);
584       ASSERT_AND_RET(
585           /* Load: BB x M x ref --> M x X x data */
586           op1mode == mode_M && mode_is_reference(op2mode),
587           "Load node", 0
588           );
589       ASSERT_AND_RET( mymode == mode_T, "Load node", 0 );
590       break;
591
592     case iro_Store:
593       op1mode = get_irn_mode(in[1]);
594       op2mode = get_irn_mode(in[2]);
595       op3mode = get_irn_mode(in[3]);
596       ASSERT_AND_RET(
597           /* Load: BB x M x ref data --> M x X */
598           op1mode == mode_M && mode_is_reference(op2mode) && mode_is_data(op3mode),
599           "Store node", 0
600           );
601       ASSERT_AND_RET(mymode == mode_T, "Store node", 0);
602       break;
603
604     case iro_Alloc:
605       op1mode = get_irn_mode(in[1]);
606       op2mode = get_irn_mode(in[2]);
607       ASSERT_AND_RET(
608           /* Alloc: BB x M x int_u --> M x X x ref */
609           op1mode == mode_M &&
610           mode_is_int(op2mode) &&
611           !mode_is_signed(op2mode) &&
612           mymode == mode_T,
613           "Alloc node", 0
614           );
615       break;
616
617     case iro_Free:
618       op1mode = get_irn_mode(in[1]);
619       op2mode = get_irn_mode(in[2]);
620       ASSERT_AND_RET(
621           /* Free: BB x M x ref --> M */
622           op1mode == mode_M && mode_is_reference(op2mode) &&
623           mymode == mode_M,
624           "Free node",0
625           );
626       break;
627
628     case iro_Sync:
629       /* Sync: BB x M^n --> M */
630       for (i=1; i < get_irn_arity(n); i++) {
631         ASSERT_AND_RET( get_irn_mode(in[i]) == mode_M, "Sync node", 0 );
632       };
633       ASSERT_AND_RET( mymode == mode_M, "Sync node", 0 );
634       break;
635
636     case iro_Proj:
637       return vrfy_Proj_proj(n, irg);
638       break;
639
640     default:
641       break;
642   }
643
644   /* All went ok */
645   return 1;
646 }
647
648 int irn_vrfy(ir_node *n)
649 {
650   return irn_vrfy_irg(n, current_ir_graph);
651 }
652
653 /*******************************************************************/
654 /* Verify the whole graph.                                         */
655 /*******************************************************************/
656
657 static void vrfy_wrap(ir_node *node, void *env)
658 {
659   int *res = env;
660
661   *res = irn_vrfy(node);
662 }
663
664 int irg_vrfy(ir_graph *irg)
665 {
666   int res = 1;
667   ir_graph *rem;
668
669   rem = current_ir_graph;
670   current_ir_graph = irg;
671
672   assert(get_irg_pinned(irg) == pinned);
673
674   irg_walk(irg->end, vrfy_wrap, NULL, &res);
675
676   current_ir_graph = rem;
677
678   return res;
679 }