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