Changed the makefile system to autoconf/automake.
[cacao.git] / compiler.c
1 /****************************** compiler.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         Enth"alt die Funktionen mit denen die JavaVM - Methoden in Maschinencode
8         "ubersetzt werden.
9         Ein Aufruf vom compiler_compile "ubersetzt genau eine Methode.
10         Alle in diesem Modul global definierten Variablen gelten nur f"ur 
11         eben diese gerade in der "Ubersetzung befindlichen Methode.
12
13         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
14                  Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
15         Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
16
17         Last Change: 1997/10/22
18
19 *******************************************************************************/
20
21 #include "global.h"
22 #include "compiler.h"
23
24 #include "loader.h"
25 #include "tables.h"
26 #include "builtin.h"
27 #include "native.h"
28 #include "asmpart.h"
29
30 #include "threads/thread.h"              /* schani */
31
32
33 /*************************** globale Schalter ********************************/
34
35 /**************************  now all in newcomp.c
36
37 bool compileverbose = false;
38 bool showstack = false;
39 bool showintermediate = false;
40 bool showdisassemble = false; 
41 int  optimizelevel = 0;
42
43 bool checkbounds = true;
44 bool checknull = true;
45 bool checkfloats = true;
46 bool checksync = true;
47
48 bool getcompilingtime = false;
49 long int compilingtime = 0;
50 int  has_ext_instr_set = 0;
51
52 bool statistics = false;         
53
54 int count_jit_calls = 0;
55 int count_methods = 0;
56 int count_spills = 0;
57 int count_pcmd_activ = 0;
58 int count_pcmd_drop = 0;
59 int count_pcmd_zero = 0;
60 int count_pcmd_const_store = 0;
61 int count_pcmd_const_alu = 0;
62 int count_pcmd_const_bra = 0;
63 int count_pcmd_load = 0;
64 int count_pcmd_move = 0;
65 int count_pcmd_store = 0;
66 int count_pcmd_store_comb = 0;
67 int count_pcmd_op = 0;
68 int count_pcmd_mem = 0;
69 int count_pcmd_met = 0;
70 int count_pcmd_bra = 0;
71 int count_pcmd_table = 0;
72 int count_pcmd_return = 0;
73 int count_pcmd_returnx = 0;
74 int count_check_null = 0;
75 int count_javainstr = 0;
76 int count_javacodesize = 0;
77 int count_javaexcsize = 0;
78 int count_calls = 0;
79 int count_tryblocks = 0;
80 int count_code_len = 0;
81 int count_data_len = 0;
82 int count_cstub_len = 0;
83 int count_nstub_len = 0;
84
85 ********************/
86
87
88 /************************ die Datentypen f"ur den Compiler *******************/ 
89
90 #include "comp/defines.c"
91
92
93
94 /******************* globale Variablen fuer den Compiler *********************/
95
96 static methodinfo *method;      /* Zeiger auf die Methodenstruktur */
97 static unicode   *descriptor;   /* Typbeschreibung der Methode */
98 static classinfo *class;        /* Klasse, in der die Methode steht */
99         
100 static s4 maxstack;             /* maximale Gr"osse des JavaVM-Stacks */
101 static s4 maxlocals;            /* maximale Anzahl der JavaVM-Variablen */
102 static u4 jcodelength;          /* L"ange des JavaVM-Codes */
103 static u1 *jcode;               /* Zeiger auf den JavaVM-Code */
104 static s4 exceptiontablelength; /* L"ange der Exceptiontable */
105 static exceptiontable *extable; /* Zeiger auf die Exceptiontable */
106
107
108 static list reachedblocks;      /* Die Listenstruktur f"ur alle vom Parser 
109                                    bereits irgendwie erreichten Bl"ocke */
110 static list finishedblocks;     /* Die Listenstruktur f"ur alle Bl"ocke, die
111                                    vom Parser bereits durchgearbeitet wurden */
112
113 static basicblock **blocks;     /* Eine Tabelle, so lang wie der JavaVM-Code, */
114                                 /* in der an jeder Stelle, an der ein */
115                                 /* Basicblock beginnt, der Zeiger auf die */
116                                 /* ensprechende Basicblock-Struktur einge- */
117                                 /* tragen ist. */
118
119 static bool isleafmethod;       /* true, wenn die Methode KEINE weiteren 
120                                    Unterprogramme mehr aufruft */
121
122 static s4        mparamnum;     /* Die Anzahl der Parameter (incl. this) */
123 static u1       *mparamtypes;   /* Die Typen aller Parameter (TYPE_INT,...) */
124 static s4        mreturntype;   /* R"uckgabewert der Methode */
125 static varinfo **mparamvars;    /* Die PCMD-Variablen, die die Parameter */
126                                 /*   zu Methodenstart enthalten sollen */
127
128
129 static chain *uninitializedclasses;  
130                                 /* Eine Tabelle aller von der Methode */
131                                 /* irgendwie ben"otigten Klassen, die */
132                                 /* vor dem Start der Methode initialisiert */
133                                 /* werden m"ussen (wenn sie es noch nicht */
134                                 /* sind) */
135                                 
136
137 /************************ Subsysteme des Compilers ***************************/
138
139
140 #include "comp/tools.c"    /* ein paar n"utzliche Hilfsfunktionen */
141 #include "comp/mcode.c"    /* systemUNabh"angiger Teil des Codegenerators */
142
143 #include "comp/reg.c"      /* Registerverwaltung */
144 #include "comp/var.c"      /* Die Verwaltung der PCMD-Variblen */
145 #include "comp/pcmd.c"     /* Funktionen f"ur die Pseudocommandos (=PCMD) */
146 #include "comp/local.c"    /* Verwaltung der lokalen JavaVM-Variablen */
147 #include "comp/stack.c"    /* Verwaltung des JavaVM-Stacks */
148 #include "comp/regalloc.c" /* Registerallokator */
149
150 #include "gen.c"    /* systemABh"angiger Codegenerator */
151 #include "disass.c" /* Disassembler (nur zu Debug-Zwecken) */ 
152
153 #include "comp/block.c"    /* Verwaltung der basic blocks */ 
154 #include "comp/parse.c"    /* JavaVM - parser */
155
156
157
158
159 /****** Die Dummy-Function (wird verwendet, wenn kein Code vorhanden ist) ****/
160
161 static void* do_nothing_function() 
162 {
163         return NULL;
164 }
165
166
167
168
169 /******************************************************************************/
170 /*********************** eine Methode compilieren *****************************/
171 /******************************************************************************/
172
173
174 methodptr compiler_compile (methodinfo *m)
175 {
176         u4 i;
177         basicblock *b;
178         long int starttime=0,stoptime=0;
179         long int dumpsize;
180         
181
182         /*** Wenn schon ein Maschinencode vorliegt, dann sofort beenden ****/
183
184         count_jit_calls++;             /* andi   */
185         if (m->entrypoint) return m->entrypoint;
186
187         intsDisable();                 /* schani */
188         
189
190         /**************** Marke fuer den DUMP-Speicher aufheben *****************/
191
192         dumpsize = dump_size ();
193
194
195         /**************** Zeit messen *******************************************/
196
197         count_methods++;             /* andi   */
198         if (getcompilingtime) starttime=getcputime();
199
200         /*** Meldung ausgeben. Wenn kein JavaVM-Code vorhanden ist, beenden ****/
201
202         if (m->jcode) {
203                 if (compileverbose) {
204                         sprintf (logtext, "Compiling: ");
205                         unicode_sprint (logtext+strlen(logtext), m->class->name);
206                         strcpy (logtext+strlen(logtext), ".");
207                         unicode_sprint (logtext+strlen(logtext), m->name);
208                         unicode_sprint (logtext+strlen(logtext), m->descriptor);
209                         dolog ();
210                         }
211                 }
212         else {
213                 sprintf (logtext, "No code given for: ");
214                 unicode_sprint (logtext+strlen(logtext), m->class->name);
215                 strcpy (logtext+strlen(logtext), ".");
216                 unicode_sprint (logtext+strlen(logtext), m->name);
217                 unicode_sprint (logtext+strlen(logtext), m->descriptor);
218                 dolog ();
219                 intsRestore();           /* schani */
220                 return (methodptr) do_nothing_function;
221                 }
222
223
224         /*********** Initialisieren der Variablen und Subsysteme *****************/
225
226         isleafmethod = true;              /* bis sich das Gegenteil herausstellt */
227
228         method = m;
229         descriptor = m->descriptor;
230         class = m->class;
231         
232         maxstack = m->maxstack;
233         maxlocals = m->maxlocals;
234         jcodelength = m->jcodelength;
235         jcode = m->jcode;
236         count_tryblocks += (exceptiontablelength = m->exceptiontablelength);
237         extable = m->exceptiontable;
238
239 #ifdef STATISTICS
240         count_javacodesize += jcodelength + 18;
241         count_javaexcsize += exceptiontablelength * 8;
242 #endif
243
244         list_init (&reachedblocks,   OFFSET(basicblock, linkage) );
245         list_init (&finishedblocks,  OFFSET(basicblock, linkage) );
246
247         blocks = DMNEW (basicblock*, jcodelength);
248         for (i=0; i<jcodelength; i++) blocks[i] = NULL;
249
250
251         descriptor2types (descriptor, (m->flags & ACC_STATIC) != 0,
252                           &mparamnum, &mparamtypes, &mreturntype);
253         m->paramcount = mparamnum;
254         m->returntype = mreturntype;
255         mparamvars = DMNEW (varid, mparamnum);
256
257         reg_init ();
258         mcode_init ();
259         var_init();
260         local_init();
261
262         uninitializedclasses = chain_new(); 
263                 /* aktuelle Klasse zur Liste der m"oglicherweise zu 
264                    initialisierenden Klassen dazugeben */
265         compiler_addinitclass (m->class);
266
267
268         /************************ Compilieren  ************************/
269         
270             /* Fuer jedes Sprungziel einen eigenen Block erzeugen */
271         block_firstscann ();
272
273                         /* Den ersten Block als erreicht markieren, der Stack ist leer */
274         stack_init();
275         subroutine_set(NULL);
276         block_reach ( block_find(0) );
277         
278                         /* Alle schon erreichten Bl"ocke durchgehen und fertig machen */
279         while ( (b = list_first (&reachedblocks)) ) {
280                 list_remove (&reachedblocks, b);
281                 list_addlast (&finishedblocks, b);
282                 b -> finished = true;
283
284                 pcmd_init ( &(b->pcmdlist) );
285                 parse (b);
286                 }
287         
288         input_args_prealloc ();
289
290                         /* F"ur alle Bl"ocke die Registerbelegung durchfuehren */
291         b = list_first (&finishedblocks);
292         while (b) {
293                 regalloc (b);
294                 b = list_next (&finishedblocks, b);
295                 }
296
297
298                     /* Registerbelegung fuer die lokalen JAVA-Variablen */
299         local_regalloc ();
300
301         
302
303         
304         /**************** Maschinencode generieren **********************/
305
306         gen_computestackframe ();
307         gen_header ();
308
309
310         for (i=0; i<jcodelength; i++) {
311                 b = blocks[i];
312                 if (b) if (b->reached) block_genmcode (b);
313                 }
314         
315         b = list_first (&finishedblocks);
316         while (b) {
317                 if (b->type != BLOCKTYPE_JAVA) block_genmcode (b);
318                 b = list_next (&finishedblocks, b);
319                 }
320
321         
322         mcode_finish ();
323
324         
325         /*********** Zwischendarstellungen auf Wunsch ausgeben **********/
326                 
327         if (showintermediate) {
328                 printf ("Leaf-method: %s\n", isleafmethod ? "YES":"NO");
329                 printf ("Parameters: ");
330                 for (i=0; i<mparamnum; i++) var_display (mparamvars[i]);
331                 printf ("\n");
332                 printf ("Max locals: %d\n", (int) maxlocals);
333                 printf ("Max stack:  %d\n", (int) maxstack);
334
335                 for (i=0; i<jcodelength; i++) {
336                         b = blocks[i];
337                         if (b) if (b->reached) block_display (b);
338                         }
339                 b = list_first (&finishedblocks);
340                 while (b) {
341                         if (b->type != BLOCKTYPE_JAVA) block_display (b);
342                         b = list_next (&finishedblocks, b);
343                         }
344                         
345                 var_displayall();
346                 fflush (stdout);
347                 }
348
349         if (showdisassemble) {
350                 dseg_display ();
351                 disassemble ( (void*) (m->mcode + dseglen), mcodelen);
352                 fflush (stdout);
353                 }
354
355
356
357         /***************** Dump-Speicher zurueckgeben *************/
358
359         dump_release (dumpsize);
360
361
362         /******************* Zeit messen **************************/
363         
364         if (getcompilingtime) {
365                 stoptime = getcputime();
366                 compilingtime += (stoptime-starttime); 
367                 }
368
369         /******** Alle Klassen initialisieren, die gebraucht wurden *******/
370
371         {
372                 chain *u = uninitializedclasses;    /* wegen reentrant-F"ahigkeit */ 
373                 classinfo *c;                       /* d"urfen ab hier keine */
374                                                     /* globalen Variablen verwendet */
375                 while ( (c = chain_first(u)) ) {    /* werden */
376                         chain_remove (u);
377                         
378                         class_init (c);                         /* ruft unter Umst"anden wieder */
379                                                         /* den Compiler auf */
380                         }
381                 chain_free (u);
382         }
383
384         intsRestore();                   /* schani */
385
386
387
388         /****** Return pointer to the methods entry point **********/
389                 
390         return m -> entrypoint;
391
392 }
393
394
395
396 /***************** Funktionen zum Initialisieren und Terminieren *************/
397
398 void compiler_init ()
399 {
400         u4 i;
401
402         has_ext_instr_set = ! has_no_x_instr_set();
403
404         for (i=0; i<256;i++) stdopdescriptors[i]=NULL;
405
406         for (i=0; i<sizeof(stdopdescriptortable)/sizeof(stdopdescriptor); i++) {
407                 
408                 if (stdopdescriptortable[i].isfloat && checkfloats) {
409                         stdopdescriptortable[i].supported = false;
410                         }
411
412                 stdopdescriptors[stdopdescriptortable[i].opcode] = 
413                    &(stdopdescriptortable[i]);
414                 }
415 }
416
417
418 void compiler_close()
419 {
420         reg_close ();
421         mcode_close();
422 }
423