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