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