Initial revision
[cacao.git] / comp / pcmd.c
1 /********************************** comp/pcmd.c ********************************
2
3         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
4
5         See file COPYRIGHT for information on usage and disclaimer of warranties
6
7         contains the parser functions which generate pseude commands and
8         eliminating unnecessary copy instructions
9
10         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
11                  Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
12
13         Last Change: 1997/09/22
14
15 *******************************************************************************/
16
17
18 list *pcmdlist;  /* list of pseudo commands */
19
20
21 /***************************** support functions ******************************/
22
23 static void pcmd_init (list *pl)
24 {
25         pcmdlist = pl;
26 }
27
28
29 static void pcmd_realmove (u2 type, varid source, varid dest)
30 {
31         pcmd *c = DNEW(pcmd);
32         c -> tag = TAG_MOVE;
33         c -> opcode = CMD_MOVE;
34         c -> source1 = source;
35         c -> source2 = NOVAR;
36         c -> source3 = NOVAR;
37         c -> dest = dest;
38         c -> u.move.type = type;
39         list_addlast (pcmdlist, c);
40 #ifdef STATISTICS
41         count_pcmd_move++;
42 #endif
43 }
44
45
46 static void pcmd_invalidatevar (varid v)
47 {
48         varid c;
49         
50         if (!var_isoriginal(v) ) {
51                 var_unlinkcopy (v);
52                 }
53         else {
54                 while ( (c = var_nextcopy (v)) != NULL) {
55                         pcmd_realmove (var_type(v), v,c);
56                         var_unlinkcopy (c);
57                         }
58                         
59                 }
60 }
61
62
63 static void pcmd_untievar (varid v)
64 {
65         varid c;
66         
67         if (!var_isoriginal(v)) {
68                 pcmd_realmove (var_type(v), var_findoriginal(v), v);
69                 var_unlinkcopy (v);
70                 }
71         else {
72                 while ( (c = var_nextcopy(v)) != NULL) {
73                         pcmd_realmove (var_type(v), v, c);
74                         var_unlinkcopy (c);
75                         }
76                 }
77 }
78
79
80 static void pcmd_untieall ()
81 {
82         varid v;
83         
84         while ( (v = var_nextcopiedvar()) != NULL) {
85                 pcmd_realmove (var_type(v), var_findoriginal(v), v);
86                 var_unlinkcopy (v);
87                 }
88 }
89
90
91 /********************** generation of pseudo commands *************************/
92
93 static void pcmd_drop (varid var)
94 {
95         pcmd *c = DNEW(pcmd);
96
97         if (var_isoriginal(var)) {
98                 pcmd_invalidatevar (var);
99         
100                 c -> tag = TAG_DROP;
101                 c -> opcode = CMD_DROP;
102                 c -> dest = var;
103                 c -> source1 = c -> source2 = c -> source3 = NOVAR;
104                 list_addlast (pcmdlist, c);
105 #ifdef STATISTICS
106         count_pcmd_drop++;
107 #endif
108                 }
109         else {
110                 pcmd_invalidatevar (var);
111                 }
112 }
113
114
115 static void pcmd_activate (varid var)
116 {
117         pcmd *c = DNEW(pcmd);
118         
119         pcmd_untieall();
120
121         c -> tag = TAG_ACTIVATE;
122         c -> opcode = CMD_ACTIVATE;
123         c -> dest = var;
124         c -> source1 = c -> source2 = c -> source3 = NOVAR;
125         list_addlast (pcmdlist, c);
126
127 #ifdef STATISTICS
128         count_pcmd_activ++;
129 #endif
130 }
131
132
133 static void pcmd_loadconst_i (s4 val, varid var)
134 {
135         pcmd *c = DNEW (pcmd);
136         c -> tag = TAG_LOADCONST_I;
137         c -> opcode = CMD_LOADCONST_I;
138         c -> dest = var;
139         c -> source1 = c -> source2 = c -> source3 = NOVAR;     
140         c -> u.i.value = val;
141
142         pcmd_invalidatevar (var);
143         list_addlast (pcmdlist, c);
144
145 #ifdef STATISTICS
146         if (val == 0)
147                 count_pcmd_zero++;
148         count_pcmd_load++;
149 #endif
150 }
151
152
153 static void pcmd_loadconst_l (s8 val, varid var)
154 {
155         pcmd *c = DNEW (pcmd);
156         c -> tag = TAG_LOADCONST_L;
157         c -> opcode = CMD_LOADCONST_L;
158         c -> dest = var;
159         c -> source1 = c -> source2 = c -> source3 = NOVAR;     
160         c -> u.l.value = val;
161
162         pcmd_invalidatevar (var);
163         list_addlast (pcmdlist, c);
164
165 #ifdef STATISTICS
166         if (val == 0)
167                 count_pcmd_zero++;
168         count_pcmd_load++;
169 #endif
170 }
171
172
173 static void pcmd_loadconst_f (float val, varid var)
174 {
175         pcmd *c = DNEW (pcmd);
176         c -> tag = TAG_LOADCONST_F;
177         c -> opcode = CMD_LOADCONST_F;
178         c -> dest = var;
179         c -> source1 = c -> source2 = c -> source3 = NOVAR;     
180         c -> u.f.value = val;
181
182         pcmd_invalidatevar (var);
183         list_addlast (pcmdlist, c);
184
185 #ifdef STATISTICS
186         count_pcmd_load++;
187 #endif
188 }
189
190
191 static void pcmd_loadconst_d (double val, varid var)
192 {
193         pcmd *c = DNEW (pcmd);
194         c -> tag = TAG_LOADCONST_D;
195         c -> opcode = CMD_LOADCONST_D;
196         c -> dest = var;
197         c -> source1 = c -> source2 = c -> source3 = NOVAR;     
198         c -> u.d.value = val;
199
200         pcmd_invalidatevar (var);
201         list_addlast (pcmdlist, c);
202
203 #ifdef STATISTICS
204         count_pcmd_load++;
205 #endif
206 }
207
208
209 static void pcmd_loadconst_a (void *val, varid var)
210 {
211         pcmd *c = DNEW (pcmd);
212         c -> tag = TAG_LOADCONST_A;
213         c -> opcode = CMD_LOADCONST_A;
214         c -> dest = var;
215         c -> source1 = c -> source2 = c -> source3 = NOVAR;     
216         c -> u.a.value = val;
217
218         pcmd_invalidatevar (var);
219         list_addlast (pcmdlist, c);
220
221 #ifdef STATISTICS
222         if (val == NULL)
223                 count_pcmd_zero++;
224         count_pcmd_load++;
225 #endif
226 }
227
228
229 static void pcmd_move (u2 type, varid source, varid dest)
230 {
231         pcmd_invalidatevar (dest);
232         var_makecopy ( var_findoriginal(source), dest);
233 }
234
235
236 static void pcmd_move_n_drop (u2 type, varid source, varid dest)
237 {
238         pcmd *c;
239         
240         pcmd_untievar (source);
241         pcmd_untievar (dest);
242
243 #ifdef STATISTICS
244         count_pcmd_store++;
245 #endif
246         c = list_last (pcmdlist);
247         while (c) {
248                 switch (c->tag) {
249                 case TAG_LOADCONST_I:
250                         if (c->dest == source) { c->dest = dest; return; }
251 #ifdef STATISTICS
252                                 count_pcmd_const_store++;
253 #endif
254                         goto nothingfound;
255                 case TAG_LOADCONST_L:
256                         if (c->dest == source) { c->dest = dest; return; }
257                         goto nothingfound;
258                 case TAG_LOADCONST_F:
259                         if (c->dest == source) { c->dest = dest; return; }
260                         goto nothingfound;
261                 case TAG_LOADCONST_D:
262                         if (c->dest == source) { c->dest = dest; return; }
263                         goto nothingfound;
264                 case TAG_LOADCONST_A:
265                         if (c->dest == source) { c->dest = dest; return; }
266                         goto nothingfound;
267                 case TAG_OP:    
268                         if (c->dest == source) { c->dest = dest; return; }
269                         goto nothingfound;
270                 case TAG_MEM:
271                         if (c->dest == source) { c->dest = dest; return; }
272                         goto nothingfound;
273
274                 case TAG_DROP:
275                         break;
276                 default:
277                         goto nothingfound;
278                 } /* end switch */
279                 
280                 c = list_prev (pcmdlist, c);
281                 }
282
283 nothingfound:
284         var_makecopy ( source, dest);
285         pcmd_drop (source);
286 #ifdef STATISTICS
287         count_pcmd_store_comb++;
288 #endif
289 }
290
291
292 static void pcmd_iinc (s4 val, varid sourcedest)
293 {
294         pcmd *c = DNEW (pcmd);
295
296         pcmd_invalidatevar (sourcedest);
297
298         c -> tag = TAG_OP;
299         c -> opcode = CMD_IINC;
300         c -> source1 = var_findoriginal(sourcedest);
301         c -> source2 = NOVAR;
302         c -> source3 = NOVAR;   
303         c -> dest = sourcedest;
304         c -> u.i.value = val;
305
306         list_addlast (pcmdlist, c);
307
308 #ifdef STATISTICS
309         count_pcmd_op++;
310 #endif
311 }
312
313
314 static void pcmd_op (u1 opcode, 
315              varid source1, varid source2, varid source3, varid dest)
316 {
317         pcmd *c;
318         
319 #ifdef STATISTICS
320         c = list_last (pcmdlist);
321         if (c && (c->tag == TAG_LOADCONST_I))
322                 switch (opcode) {
323                         case CMD_IASTORE:
324                         case CMD_BASTORE:
325                         case CMD_CASTORE:
326                         case CMD_SASTORE:
327                                 count_pcmd_const_store++;
328                                 break;
329                         case CMD_IADD:
330                         case CMD_ISUB:
331                         case CMD_IMUL:
332                         case CMD_ISHL:
333                         case CMD_ISHR:
334                         case CMD_IUSHR:
335                         case CMD_IAND:
336                         case CMD_IOR:
337                         case CMD_IXOR:
338                                 count_pcmd_const_alu++;
339                         }
340 #endif
341         c = DNEW(pcmd);
342         if (dest) pcmd_invalidatevar (dest);
343         
344         c -> tag = TAG_OP;
345         c -> opcode = opcode;
346         c -> source1 = source1 ? var_findoriginal(source1) : NOVAR;
347         c -> source2 = source2 ? var_findoriginal(source2) : NOVAR;
348         c -> source3 = source3 ? var_findoriginal(source3) : NOVAR;
349         c -> dest = dest;
350         list_addlast (pcmdlist, c);
351 #ifdef STATISTICS
352         count_pcmd_op++;
353 #endif
354 }
355
356
357 static void pcmd_mem (u1 opcode, u2 type, varid base, varid source, 
358                         varid dest, u2 offset) 
359 {
360         pcmd *c;
361
362 #ifdef STATISTICS
363         c = list_last (pcmdlist);
364         if (c && (c->tag == TAG_LOADCONST_I) && (opcode == CMD_PUTFIELD))
365                 count_pcmd_const_store++;
366 #endif
367         c = DNEW(pcmd);
368         if (dest) pcmd_invalidatevar (dest);
369         
370         c -> tag = TAG_MEM;
371         c -> opcode = opcode;
372         c -> source1 = base   ? var_findoriginal(base) : NOVAR;
373         c -> source2 = source ? var_findoriginal(source) : NOVAR;
374         c -> source3 = NOVAR;
375         c -> dest = dest;
376         c -> u.mem.type = type;
377         c -> u.mem.offset = offset;
378         list_addlast (pcmdlist, c);
379
380 #ifdef STATISTICS
381         count_pcmd_mem++;
382 #endif
383 }
384
385
386 static void pcmd_bra (u1 opcode, varid s1, varid s2, varid dest, basicblock *target)
387 {
388         pcmd *c;
389         varid or1,or2;
390         
391 #ifdef STATISTICS
392         c = list_last (pcmdlist);
393         if (c && (c->tag == TAG_LOADCONST_I))
394                 switch (opcode) {
395                         case CMD_IF_ICMPEQ:
396                         case CMD_IF_ICMPNE:
397                         case CMD_IF_ICMPLT:
398                         case CMD_IF_ICMPGT:
399                         case CMD_IF_ICMPLE:
400                         case CMD_IF_ICMPGE:
401                                 count_pcmd_const_bra++;
402                         }
403 #endif
404         c = DNEW(pcmd);
405         or1 = s1 ? var_findoriginal (s1) : NOVAR;
406         or2 = s2 ? var_findoriginal (s2) : NOVAR;
407         
408         pcmd_untieall();
409         
410         c -> tag = TAG_BRA;
411         c -> opcode = opcode;
412         c -> source1 = or1;
413         c -> source2 = or2;
414         c -> source3 = NOVAR;
415         c -> dest = dest;
416         c -> u.bra.target = target;
417         list_addlast (pcmdlist, c);
418
419 #ifdef STATISTICS
420         count_pcmd_bra++;
421 #endif
422 }
423
424
425 static void pcmd_trace (void *method)
426 {
427         pcmd *c;
428         
429         isleafmethod = false;
430         
431         c = DNEW(pcmd);
432         c -> tag = TAG_BRA;
433         c -> opcode = CMD_TRACEBUILT;
434         c -> source1 = NOVAR;
435         c -> source2 = NOVAR;
436         c -> source3 = NOVAR;
437         c -> dest = NOVAR;
438         c -> u.a.value = method;
439         list_addlast (pcmdlist, c);
440 }
441
442
443 static void pcmd_bra_n_drop (u1 opcode, varid s1, varid s2, varid dest, basicblock *target)
444 {
445         pcmd *c;
446         varid or1=NOVAR,or2=NOVAR;
447         bool isor1=false,isor2=false;
448         
449 #ifdef STATISTICS
450         c = list_last (pcmdlist);
451         if (c && (c->tag == TAG_LOADCONST_I))
452                 switch (opcode) {
453                         case CMD_IF_ICMPEQ:
454                         case CMD_IF_ICMPNE:
455                         case CMD_IF_ICMPLT:
456                         case CMD_IF_ICMPGT:
457                         case CMD_IF_ICMPLE:
458                         case CMD_IF_ICMPGE:
459                                 count_pcmd_const_bra++;
460                         }
461 #endif
462         c = DNEW(pcmd);
463         if (s1!=NOVAR) {
464                 or1 = var_findoriginal (s1); 
465             if (! (isor1 = var_isoriginal(s1)) ) var_unlinkcopy (s1);
466                 }
467         if (s2!=NOVAR) {
468                 or2 = var_findoriginal (s2);
469                 if (! (isor2 = var_isoriginal (s2)) ) var_unlinkcopy (s2);
470                 }
471
472         pcmd_untieall();
473
474         c -> tag = TAG_BRA;
475         c -> opcode = opcode;
476         c -> source1 = or1;
477         c -> source2 = or2;
478         c -> source3 = NOVAR;
479         c -> dest = dest;
480         c -> u.bra.target = target;
481         list_addlast (pcmdlist, c);
482         
483         if (isor1) pcmd_drop (s1);
484         if (isor2) pcmd_drop (s2);
485
486 #ifdef STATISTICS
487         count_pcmd_bra++;
488 #endif
489 }
490
491
492 static void pcmd_tablejump (varid s, u4 targetcount, basicblock **targets)
493 {
494         pcmd *c = DNEW(pcmd);
495         
496         pcmd_untieall();
497         
498         c -> tag = TAG_TABLEJUMP;
499         c -> opcode = CMD_TABLEJUMP;
500         c -> source1 = var_findoriginal(s);
501         c -> source2 = NOVAR;
502         c -> source3 = NOVAR;
503         c -> dest = NOVAR;
504         c -> u.tablejump.targetcount = targetcount;
505         c -> u.tablejump.targets = targets;
506         list_addlast (pcmdlist, c);
507
508 #ifdef STATISTICS
509         count_pcmd_table++;
510 #endif
511 }
512
513
514 /******* ATTENTION: Method does DROP automatically !!!!! ****/
515
516 static void pcmd_method (int opcode, methodinfo *mi, functionptr builtin, 
517                          int paramnum, varid *params, varid result, varid exceptionvar)
518 {
519         varid v;
520         int i;
521
522         pcmd *c = DNEW(pcmd);
523         
524         pcmd_untieall();
525                                         
526         isleafmethod = false;
527
528         reg_parlistinit();
529         for (i = 0; i < paramnum; i++) {
530                 v = params[i];
531                 var_proposereg(v, reg_parlistpar(var_type(v)));
532                 }
533                 
534         if (result) {
535                 var_proposereg(result, reg_parlistresult(var_type(result)));
536                 }
537         if (exceptionvar) {
538                 exceptionvar -> reg = reg_parlistexception();
539                 }
540
541         c -> tag = TAG_METHOD;
542         c -> opcode = opcode;
543         c -> source1 = c -> source2 = c -> source3 = NULL;
544         c -> dest = result;
545         c -> u.method.method = mi;
546         c -> u.method.builtin = builtin;
547         c -> u.method.paramnum = paramnum;
548         c -> u.method.params = params;
549         c -> u.method.exceptionvar = exceptionvar;
550         list_addlast (pcmdlist, c);
551         
552         for (i = 0; i < paramnum; i++) pcmd_drop(params[i]);
553         
554 #ifdef STATISTICS
555         count_pcmd_met++;
556 #endif
557 }
558
559
560
561 static void pcmd_builtin1 (functionptr builtin, varid v1, varid result)
562 {
563         varid *args = DMNEW (varid, 1);
564         args[0] = v1;
565         pcmd_method (CMD_BUILTIN, NULL, builtin, 1, args, result,NOVAR);
566 }
567
568 static void pcmd_builtin2 (functionptr builtin, varid v1, varid v2, varid result)
569 {
570         varid *args = DMNEW (varid, 2);
571         args[0] = v1;
572         args[1] = v2;
573         pcmd_method (CMD_BUILTIN, NULL, builtin, 2, args, result, NOVAR);
574 }
575
576 static void pcmd_builtin3 (functionptr builtin, varid v1, varid v2, varid v3, varid result)
577 {
578         varid *args = DMNEW (varid, 3);
579         args[0] = v1;
580         args[1] = v2;
581         args[2] = v3;
582         pcmd_method (CMD_BUILTIN, NULL, builtin, 3, args, result, NOVAR);
583 }
584
585
586 static void pcmd_display (pcmd *c)
587 {
588         int i;
589
590         switch (c -> tag) {
591                 case TAG_LOADCONST_I:
592                         printf ("   LOADCONST_I #%ld -> ", 
593                                          (long int) c -> u.i.value);
594                         var_display (c -> dest);
595                         printf ("\n");
596                         break;
597                 case TAG_LOADCONST_L:  
598 #if U8_AVAILABLE
599                         printf ("   LOADCONST_L #%ld -> ", (long int) c -> u.l.value);
600 #else
601                         printf ("   LOADCONST_L #HI: %ld LO: %ld -> ", 
602                           (long int) c->u.l.value.high, (long int) c->u.l.value.low );
603 #endif
604                         var_display (c -> dest);
605                         printf ("\n");
606                         break;
607                 case TAG_LOADCONST_F:  
608                         printf ("   LOADCONST_F #%f -> ", (double) c -> u.f.value);                             
609                         var_display (c -> dest);
610                         printf ("\n");
611                         break;
612                 case TAG_LOADCONST_D:  
613                         printf ("   LOADCONST_D #%f -> ", c ->  u.d.value);
614                         var_display (c -> dest);
615                         printf ("\n");
616                         break;
617                 case TAG_LOADCONST_A:  
618                         printf ("   LOADCONST_A #%p -> ", c ->  u.a.value);
619                         var_display (c -> dest);
620                         printf ("\n");
621                         break;
622                         
623                 case TAG_MOVE:
624                         printf ("   MOVE_%1d      ", c -> u.move.type);
625                         var_display (c-> source1);      
626                         printf (" -> ");
627                         var_display (c -> dest);
628                         printf ("\n");
629                         break;
630                         
631                 case TAG_OP:
632                         printf ("   OP%3d       ", c -> opcode);
633                         var_display (c -> source1);
634                         printf (", ");
635                         var_display (c -> source2);
636                         printf (", ");
637                         var_display (c -> source3);
638                         printf (" -> ");
639                         var_display (c -> dest );
640                         printf ("\n");
641                         break;
642
643                 case TAG_BRA:
644                         printf ("   BRA%3d     (", c -> opcode);
645                         var_display (c -> source1);
646                         printf (", ");
647                         var_display (c -> source2);
648                         printf (" -> ");
649                         var_display (c -> dest);
650                         if (c->u.bra.target) {
651                                 printf (") to pos %ld\n", 
652                                    (long int) c -> u.bra.target -> jpc );
653                                 }
654                         else printf (")\n");
655                         break;
656                         
657                 case TAG_TABLEJUMP:
658                         printf ("   TABLEJUMP     ");
659                         var_display (c -> source1);
660                         printf ("\n");
661                         for (i=0; i < (int) c->u.tablejump.targetcount; i++) {
662                                 printf ("      %d: to pos %ld\n", (int) i,
663                                    (long int) c ->u.tablejump.targets[i] -> jpc );
664                                 }
665                         break;
666
667                 case TAG_MEM:
668                         printf ("   MEM%3d_%d    ",  c -> opcode, c -> u.mem.type);
669                         var_display (c -> source2);
670                         printf ("/");
671                         var_display (c -> dest);
672                         printf ("  <->  ");
673                         printf ("%d [", (int) (c -> u.mem.offset) );
674                         var_display (c -> source1 );
675                         printf ("]\n");
676                         break;
677
678                 case TAG_METHOD:
679                         printf ("   METHOD%3d   ", c -> opcode);
680                         for (i=0; i < c -> u.method.paramnum; i++) {
681                            var_display (c -> u.method.params[i]);
682                            }
683                         printf (" -> ");
684                         var_display (c -> dest);
685                         printf ("/");
686                         var_display (c->u.method.exceptionvar);
687                         printf ("\n");
688                         break;
689
690                 case TAG_DROP:
691                         printf ("   [ DROP      ");
692                         var_display (c-> dest);
693                         printf (" ]\n");
694                         break;
695                 case TAG_ACTIVATE:
696                         printf ("   [ ACTIVATE      ");
697                         var_display (c-> dest);
698                         printf (" ]\n");
699                         break;
700
701                 default:
702                         printf ("   ???\n");
703                         break;
704                 }
705
706 }