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