Added interprocedural view.
[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 void vrfy_Proj_proj(ir_node *p);
20
21 void
22 irn_vrfy (ir_node *n)
23 {
24   int i;
25   int opcode;
26   ir_mode *mymode, *op1mode, *op2mode, *op3mode;
27   int op_is_symmetric = 1;      /* 0: asymmetric
28                                    1: operands have identical modes
29                                    2: modes of operands == mode of this node */
30   type *mt; /* A method type */
31
32   ir_node **in;
33
34   opcode = get_irn_opcode (n);
35
36   if (opcode != iro_Phi && opcode != iro_Block)
37     for (i = 0; i < get_irn_arity(n); i++)
38       if (get_irn_opcode(get_irn_n(n, i)) == iro_Bad
39           || get_irn_opcode(get_irn_n(n, i)) == iro_Unknown)
40         return;
41
42   mymode = get_irn_mode (n);
43   in = get_irn_in (n);
44
45   switch (opcode) {
46
47   case iro_Start:
48     assert (
49             /* Start: BB --> X x M x P x data1 x ... x datan */
50             mymode == mode_T && "Start node"
51            );
52     break;
53   case iro_Jmp:
54     assert (
55             /* Jmp: BB --> X */
56             mymode == mode_X && "Jmp node"
57            );
58     break;
59   case iro_Cond:
60     op1mode = get_irn_mode(in[1]);
61     assert (
62             /* Cond: BB x b --> X x X */
63             (op1mode == mode_b
64             /* Cond: BB x Iu --> X^n */
65             || op1mode == mode_I) && "Cond node"
66            );
67     assert (mymode == mode_T);
68     break;
69   case iro_Return:
70     op1mode = get_irn_mode(in[1]);
71     /* Return: BB x M x data1 x ... x datan --> X */
72     /* printf("mode: %s, code %s\n", ID_TO_STR(n->mode->name), ID_TO_STR(n->op->name));*/
73     assert ( op1mode == mode_M  && "Return node" );  /* operand M */
74     for (i=2; i < get_irn_arity(n); i++) {
75       assert ( mode_is_data(get_irn_mode(in[i]))  && "Return node");  /* operand datai */
76     };
77     assert ( mymode == mode_X );   /* result X */
78     /* Compare returned results with result types of method type */
79     mt = get_entity_type(get_irg_ent(current_ir_graph));
80     assert(get_Return_n_res(n) == get_method_n_res(mt) &&
81              "Number of results for Return doesn't match number of results in type.");
82     for (i = 0; i < get_Return_n_res(n); i++)
83       assert((get_irn_mode(get_Return_res(n, i))
84               == get_type_mode(get_method_res_type(mt, i))) &&
85              "Mode of result for Return doesn't match mode of result type.");
86
87     break;
88   case iro_Raise:
89     op1mode = get_irn_mode(in[1]);
90     op2mode = get_irn_mode(in[2]);
91     assert (
92             /* Sel: BB x M x P --> X x M */
93             op1mode == mode_M && op2mode == mode_p
94             && mymode == mode_T && "Raise node"
95            );
96     break;
97   case iro_Const:
98     assert (
99             /* Const: BB --> data */
100             (mode_is_data (mymode) ||
101              mymode == mode_b)      /* we want boolean constants for static evaluation */
102              && "Const node"        /* of Cmp. */
103            );
104     break;
105   case iro_SymConst:
106     assert (
107             /* SymConst: BB --> Iu or
108                          BB --> P */
109             ((mymode == mode_I) || (mymode == mode_p))  && "SymConst node"
110            );
111     break;
112   case iro_Sel:
113     op1mode = get_irn_mode(in[1]);
114     op2mode = get_irn_mode(in[2]);
115     assert (
116             /* Sel: BB x M x P x Iu^n --> P */
117             op1mode == mode_M && op2mode == mode_p
118             && mymode == mode_p && "Sel node"
119            );
120     for (i=3; i < get_irn_arity(n); i++) {
121             assert (get_irn_mode(in[i]) == mode_I && "Sel node"); }
122     break;
123   case iro_Call:
124     op1mode = get_irn_mode(in[1]);
125     op2mode = get_irn_mode(in[2]);
126       /* Call: BB x M x P x data1 x ... x datan
127                  --> M x datan+1 x ... x data n+m */
128     assert ( op1mode == mode_M && op2mode == mode_p  && "Call node");  /* operand M x P */
129     for (i=3; i < get_irn_arity(n); i++) {
130       assert ( mode_is_data(get_irn_mode(in[i])) && "Call node");  /* operand datai */
131     };
132     assert ( mymode == mode_T );   /* result T */
133     /* Compare arguments of node with those of type */
134       mt = get_Call_type(n);
135       assert(get_Call_n_params(n) == get_method_n_params(mt) &&
136              "Number of args for Call doesn't match number of args in type.");
137       for (i = 0; i < get_Call_n_params(n); i++)
138         assert((get_irn_mode(get_Call_param(n, i))
139                 == get_type_mode(get_method_param_type(mt, i))) &&
140                "Mode of arg for Call doesn't match mode of arg type.");
141     break;
142   case iro_Add:
143     op1mode = get_irn_mode(in[1]);
144     op2mode = get_irn_mode(in[2]);
145     assert (
146             /* common Add: BB x num x num --> num */
147             ((mymode == op1mode && mymode == op2mode
148               && mode_is_num(mymode))
149              ||  /* Pointer Add: BB x P x Is --> P */
150              (op1mode == mode_p && op2mode == mode_i && mymode == mode_p)
151              ||  /* Pointer Add: BB x Is x P --> P */
152              (op1mode == mode_i && op2mode == mode_p && mymode == mode_p))
153             && "Add node"
154            );
155       if (op1mode == mode_p || op2mode == mode_p) {
156         /* BB x P x Is --> P or BB x Is x P --> P */
157         op_is_symmetric = 0; /* ArmRoq */
158       } else {
159         /* BB x num x num --> num */
160         op_is_symmetric = 2;
161       }
162     break;
163   case iro_Sub:
164     op1mode = get_irn_mode(in[1]);
165     op2mode = get_irn_mode(in[2]);
166     assert (
167             /* common Sub: BB x num x num --> num */
168             ((mymode ==op1mode && mymode == op2mode
169               && mode_is_num(op1mode))
170              ||  /* Pointer Sub: BB x P x Is --> P */
171              (op1mode == mode_p && op2mode == mode_i && mymode == mode_p)
172              ||  /* Pointer Sub: BB x Is x P --> P */
173              (op1mode == mode_i && op2mode == mode_p && mymode == mode_p)
174              ||  /* Pointer Sub: BB x P x P --> Is */
175              (op1mode == mode_p && op2mode == mode_p && mymode == mode_i))
176             && "Sub node"
177            );
178       if (op1mode == mode_p && op2mode == mode_p) {
179         op_is_symmetric = 1; /* ArmRoq */
180       } else if (op1mode == mode_p || op2mode == mode_p) {
181         op_is_symmetric = 0; /* ArmRoq */
182       } else {
183         op_is_symmetric = 2;
184       }
185     break;
186   case iro_Minus:
187     op1mode = get_irn_mode(in[1]);
188     assert (
189             /* Minus: BB x float --> float */
190             op1mode == mymode && mode_is_float (op1mode)  && "Minus node"
191            );
192     op_is_symmetric = 2;
193     break;
194   case iro_Mul:
195     op1mode = get_irn_mode(in[1]);
196     op2mode = get_irn_mode(in[2]);
197     assert (
198             /* Mul: BB x num x num --> num */
199             mymode == op1mode && mymode == op2mode
200             && mode_is_num (op1mode) && "Mul node"
201            );
202     op_is_symmetric = 2;
203     break;
204   case iro_Quot:
205     op1mode = get_irn_mode(in[1]);
206     op2mode = get_irn_mode(in[2]);
207     op3mode = get_irn_mode(in[3]);
208     assert (
209             /* Quot: BB x M x float x float --> M x X x float */
210             op1mode == mode_M && op2mode == op3mode
211             && mode_is_float(op2mode) && mymode == mode_T && "Quot node"
212            );
213     op_is_symmetric = 2;
214     break;
215   case iro_DivMod:;
216     op1mode = get_irn_mode(in[1]);
217     op2mode = get_irn_mode(in[2]);
218     op3mode = get_irn_mode(in[3]);
219     assert (
220             /* DivMod: BB x M x num x num --> M x X x Is x Is */
221             op1mode == mode_M && op2mode == op3mode
222             && mode_is_num (op2mode) && mymode == mode_T && "DivMod node"
223            );
224     op_is_symmetric = 1;
225     break;
226   case iro_Div:
227   case iro_Mod:
228     op1mode = get_irn_mode(in[1]);
229     op2mode = get_irn_mode(in[2]);
230     op3mode = get_irn_mode(in[3]);
231     assert (
232             /* Div or Mod: BB x M x num x num --> M x X x Is */
233             op1mode == mode_M && op2mode == op3mode &&
234             mode_is_num (op2mode) && mymode == mode_T && "Div or Mod node"
235            );
236     op_is_symmetric = 1;
237     break;
238   case iro_Abs:
239     op1mode = get_irn_mode(in[1]);
240     assert (
241             /* Abs: BB x num --> num */
242             op1mode == mymode && mode_is_num (op1mode) && "Abs node"
243            );
244     op_is_symmetric = 2;
245     break;
246   case iro_And:
247   case iro_Or:
248   case iro_Eor:
249     op1mode = get_irn_mode(in[1]);
250     op2mode = get_irn_mode(in[2]);
251     assert(
252            /* And or Or or Eor: BB x int x int --> int */
253            mymode == op1mode && mymode == op2mode
254            && mode_is_int (mymode) && "And, Or or Eor node"
255           );
256     op_is_symmetric = 2;
257     break;
258   case iro_Not:
259     op1mode = get_irn_mode(in[1]);
260     assert(
261            /* Not: BB x int --> int */
262            mymode == op1mode
263            && mode_is_int (mymode) && "Not node"
264           );
265     op_is_symmetric = 2;
266     break;
267
268   case iro_Cmp:
269     op1mode = get_irn_mode(in[1]);
270     op2mode = get_irn_mode(in[2]);
271     assert(
272            /* Cmp: BB x datab x datab --> b16 */
273            op1mode == op2mode && mode_is_data (op1mode)
274            && mymode == mode_T && "Cmp node"
275           );
276     break;
277   case iro_Shl:
278   case iro_Shr:
279   case iro_Shrs:
280   case iro_Rot:
281     op1mode = get_irn_mode(in[1]);
282     op2mode = get_irn_mode(in[2]);
283     assert(
284            /* Shl, Shr, Shrs or Rot: BB x int x Iu --> int */
285            mode_is_int (op1mode) && op2mode == mode_I
286            && op1mode == mymode && "Shl, Shr, Shr or Rot node"
287           );
288     break;
289   case iro_Conv:
290     op1mode = get_irn_mode(in[1]);
291     assert(
292            /* Conv: BB x datab1 --> datab2 */
293            mode_is_datab (op1mode)
294            && mode_is_data (mymode) && "Conv node"
295           );
296     break;
297   case iro_Phi:
298            /* Phi: BB x dataM^n --> dataM */
299     /* for some reason "<=" aborts. Is there a problem with get_store? */
300     for (i=1; i < get_irn_arity(n); i++) {
301       if (!is_Bad(in[i]))
302         assert ( get_irn_mode(in[i]) == mymode  && "Phi node");
303     };
304     assert ( mode_is_dataM(mymode)  && "Phi node");
305     break;
306   case iro_Load:
307     op1mode = get_irn_mode(in[1]);
308     op2mode = get_irn_mode(in[2]);
309     assert(
310            /* Load: BB x M x P --> M x X x data */
311            op1mode == mode_M && op2mode == mode_p  && "Load node"
312           );
313     assert ( mymode == mode_T  && "Load node");
314     break;
315   case iro_Store:
316     op1mode = get_irn_mode(in[1]);
317     op2mode = get_irn_mode(in[2]);
318     op3mode = get_irn_mode(in[3]);
319     assert(
320            /* Load: BB x M x P x data --> M x X */
321            op1mode == mode_M && op2mode == mode_p
322            && mode_is_data (op3mode) && "Store node"
323           );
324     assert(mymode == mode_T && "Store node");
325     break;
326   case iro_Alloc:
327     op1mode = get_irn_mode(in[1]);
328     op2mode = get_irn_mode(in[2]);
329     assert(
330            /* Alloc: BB x M x Iu --> M x X x P */
331            op1mode == mode_M && op2mode == mode_I
332            && mymode == mode_T && "Alloc node"
333           );
334     break;
335   case iro_Free:
336     op1mode = get_irn_mode(in[1]);
337     op2mode = get_irn_mode(in[2]);
338     op3mode = get_irn_mode(in[3]);
339     assert(
340            /* Free: BB x M x P x Iu --> M */
341            op1mode == mode_M && op2mode == mode_p && op3mode == mode_I
342            && mymode == mode_M && "Free node"
343           );
344     break;
345   case iro_Sync:
346            /* Sync: BB x M^n --> M */
347     for (i=1; i < get_irn_arity(n); i++) {
348       assert ( get_irn_mode(in[i]) == mode_M  && "Sync node");
349     };
350     assert ( mymode == mode_M  && "Sync node");
351     break;
352   case iro_Proj:
353     vrfy_Proj_proj(n);
354     break;
355   default: ;
356   }
357 }
358
359 void
360 vrfy_Proj_proj(ir_node *p) {
361   ir_node *pred;
362   ir_mode *mode;
363   int proj;
364
365   pred = skip_nop(get_Proj_pred(p));
366   assert(get_irn_mode(pred) == mode_T);
367   mode = get_irn_mode(p);
368   proj = get_Proj_proj(p);
369
370   switch (get_irn_opcode(pred)) {
371   case iro_Start:
372     assert ((proj == 0 && mode == mode_X) ||
373             (proj == 1 && mode == mode_M) ||
374             (proj == 2 && mode == mode_p) ||
375             (proj == 3 && mode == mode_p) ||
376             (proj == 4 && mode == mode_T) &&
377             "wrong Proj from Start"  );
378     break;
379   case iro_Cond:
380     assert ((proj >= 0 && mode == mode_X) &&
381             "wrong Proj from Cond");
382     break;
383   case iro_Raise:
384     assert ((proj == 0 && mode == mode_X) ||
385             (proj == 1 && mode == mode_M) &&
386             "wrong Proj from Raise" );
387     break;
388   case iro_Call:
389     assert ((proj == 0 && mode == mode_M) ||
390             (proj == 1 && mode == mode_X) ||
391             (proj == 2 && mode == mode_T) ||
392             (proj == 3 && mode == mode_M) &&
393             "wrong Proj from Call" );
394     break;
395   case iro_Quot:
396     assert ((proj == 0 && mode == mode_M) ||
397             (proj == 1 && mode == mode_X) ||
398             (proj == 2 && mode_is_float(mode)) &&
399             "wrong Proj from Quot");
400     break;
401   case iro_DivMod:
402     assert ((proj == 0 && mode == mode_M) ||
403             (proj == 1 && mode == mode_X) ||
404             (proj == 2 && mode == mode_i) ||
405             (proj == 3 && mode == mode_i) &&
406             "wrong Proj from DivMod" );
407     break;
408   case iro_Div:
409   case iro_Mod:
410     assert ((proj == 0 && mode == mode_M) ||
411             (proj == 1 && mode == mode_X) ||
412             (proj == 2 && mode == mode_i) &&
413             "wrong Proj from Div or Mod" );
414     break;
415   case iro_Cmp:
416     assert ((proj >= 0 && proj <= 15 && mode == mode_b) &&
417             "wrong Proj from Cmp");
418     break;
419   case iro_Load:
420     assert ((proj == 0 && mode == mode_M) ||
421             (proj == 1 && mode == mode_X) ||
422             (proj == 2 && mode_is_data(mode)) &&
423             "wrong Proj from Load");
424     break;
425   case iro_Store:
426     assert ((proj == 0 && mode == mode_M) ||
427             (proj == 1 && mode == mode_X) &&
428             "wrong Proj from Store");
429     break;
430   case iro_Alloc:
431     assert ((proj == 0 && mode == mode_M) ||
432             (proj == 1 /* && mode == mode_X*/) ||
433             (proj == 2 && mode == mode_p) &&
434             "wrong Proj from Alloc");
435     break;
436   case iro_Proj: {
437     type *mt; /* A method type */
438     pred = skip_nop(get_Proj_pred(pred));
439     assert(get_irn_mode(pred) == mode_T);
440     switch (get_irn_opcode(pred)) {
441     case iro_Start: {
442       assert (proj >= 0 && mode_is_data(mode) &&
443               "wrong Proj from Proj from Start");
444       mt = get_entity_type(get_irg_ent(current_ir_graph));
445       assert(proj < get_method_n_params(mt) &&
446              "More Projs for args than args in type");
447       assert(mode == get_type_mode(get_method_param_type(mt, proj)) &&
448       "Mode of Proj from Start doesn't match mode of param type.");
449     } break;
450     case iro_Call: {
451       assert (proj >= 0 && mode_is_data(mode) &&
452               "wrong Proj from Proj from Call");
453       mt = get_Call_type(pred);
454       assert(proj < get_method_n_res(mt) &&
455              "More Projs for results than results in type.");
456       assert(mode == get_type_mode(get_method_res_type(mt, proj)) &&
457       "Mode of Proj from Call doesn't match mode of result type.");
458     } break;
459     case iro_Tuple: ;
460       /* We don't test */
461       break;
462     default: assert(0);
463     } break;
464   }
465   case iro_Tuple:
466     /* We don't test */
467     break;
468   case iro_CallBegin:
469     break;
470   case iro_EndReg:
471     break;
472   case iro_EndExcept:
473     break;
474   default: assert(0);
475   }
476 }
477
478
479 /*******************************************************************/
480 /* Verify the whole graph.                                         */
481 /*******************************************************************/
482
483 void
484 vrfy_wrap (ir_node *node, void *env) {
485   irn_vrfy(node);
486 }
487
488 void
489 irg_vrfy (ir_graph *irg)
490 {
491   ir_graph *rem;
492   rem = current_ir_graph;
493   current_ir_graph = irg;
494
495   assert(get_irg_pinned(irg) == pinned);
496
497   irg_walk(irg->end, vrfy_wrap, NULL, NULL);
498
499   current_ir_graph = rem;
500 }