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