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