1 /****************************** compiler.c *************************************
3 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5 See file COPYRIGHT for information on usage and disclaimer of warranties
7 Enth"alt die Funktionen mit denen die JavaVM - Methoden in Maschinencode
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.
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
17 Last Change: 1997/10/22
19 *******************************************************************************/
30 #include "threads/thread.h" /* schani */
33 /*************************** globale Schalter ********************************/
35 /************************** now all in newcomp.c
37 bool compileverbose = false;
38 bool showstack = false;
39 bool showintermediate = false;
40 bool showdisassemble = false;
41 int optimizelevel = 0;
43 bool checkbounds = true;
44 bool checknull = true;
45 bool checkfloats = true;
46 bool checksync = true;
48 bool getcompilingtime = false;
49 long int compilingtime = 0;
50 int has_ext_instr_set = 0;
52 bool statistics = false;
54 int count_jit_calls = 0;
55 int count_methods = 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;
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;
88 /************************ die Datentypen f"ur den Compiler *******************/
90 #include "comp/defines.c"
94 /******************* globale Variablen fuer den Compiler *********************/
96 static methodinfo *method; /* Zeiger auf die Methodenstruktur */
97 static utf *descriptor; /* Typbeschreibung der Methode */
98 static classinfo *class; /* Klasse, in der die Methode steht */
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 */
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 */
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- */
119 static bool isleafmethod; /* true, wenn die Methode KEINE weiteren
120 Unterprogramme mehr aufruft */
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 */
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 */
137 /************************ Subsysteme des Compilers ***************************/
140 #include "comp/tools.c" /* ein paar n"utzliche Hilfsfunktionen */
141 #include "comp/mcode.c" /* systemUNabh"angiger Teil des Codegenerators */
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 */
150 #include "gen.c" /* systemABh"angiger Codegenerator */
151 #include "disass.c" /* Disassembler (nur zu Debug-Zwecken) */
153 #include "comp/block.c" /* Verwaltung der basic blocks */
154 #include "comp/parse.c" /* JavaVM - parser */
159 /****** Die Dummy-Function (wird verwendet, wenn kein Code vorhanden ist) ****/
161 static void* do_nothing_function()
169 /******************************************************************************/
170 /*********************** eine Methode compilieren *****************************/
171 /******************************************************************************/
174 methodptr compiler_compile (methodinfo *m)
178 long int starttime=0,stoptime=0;
182 /*** Wenn schon ein Maschinencode vorliegt, dann sofort beenden ****/
184 count_jit_calls++; /* andi */
185 if (m->entrypoint) return m->entrypoint;
187 intsDisable(); /* schani */
190 /**************** Marke fuer den DUMP-Speicher aufheben *****************/
192 dumpsize = dump_size ();
195 /**************** Zeit messen *******************************************/
197 count_methods++; /* andi */
198 if (getcompilingtime) starttime=getcputime();
200 /*** Meldung ausgeben. Wenn kein JavaVM-Code vorhanden ist, beenden ****/
203 if (compileverbose) {
204 sprintf (logtext, "Compiling: ");
205 utf_sprint (logtext+strlen(logtext), m->class->name);
206 strcpy (logtext+strlen(logtext), ".");
207 utf_sprint (logtext+strlen(logtext), m->name);
208 utf_sprint (logtext+strlen(logtext), m->descriptor);
213 sprintf (logtext, "No code given for: ");
214 utf_sprint (logtext+strlen(logtext), m->class->name);
215 strcpy (logtext+strlen(logtext), ".");
216 utf_sprint (logtext+strlen(logtext), m->name);
217 utf_sprint (logtext+strlen(logtext), m->descriptor);
219 intsRestore(); /* schani */
220 return (methodptr) do_nothing_function;
224 /*********** Initialisieren der Variablen und Subsysteme *****************/
226 isleafmethod = true; /* bis sich das Gegenteil herausstellt */
229 descriptor = m->descriptor;
232 maxstack = m->maxstack;
233 maxlocals = m->maxlocals;
234 jcodelength = m->jcodelength;
236 count_tryblocks += (exceptiontablelength = m->exceptiontablelength);
237 extable = m->exceptiontable;
240 count_javacodesize += jcodelength + 18;
241 count_javaexcsize += exceptiontablelength * 8;
244 list_init (&reachedblocks, OFFSET(basicblock, linkage) );
245 list_init (&finishedblocks, OFFSET(basicblock, linkage) );
247 blocks = DMNEW (basicblock*, jcodelength);
248 for (i=0; i<jcodelength; i++) blocks[i] = NULL;
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);
262 uninitializedclasses = chain_new();
263 /* aktuelle Klasse zur Liste der m"oglicherweise zu
264 initialisierenden Klassen dazugeben */
265 compiler_addinitclass (m->class);
268 /************************ Compilieren ************************/
270 /* Fuer jedes Sprungziel einen eigenen Block erzeugen */
273 /* Den ersten Block als erreicht markieren, der Stack ist leer */
275 subroutine_set(NULL);
276 block_reach ( block_find(0) );
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;
284 pcmd_init ( &(b->pcmdlist) );
288 input_args_prealloc ();
290 /* F"ur alle Bl"ocke die Registerbelegung durchfuehren */
291 b = list_first (&finishedblocks);
294 b = list_next (&finishedblocks, b);
298 /* Registerbelegung fuer die lokalen JAVA-Variablen */
304 /**************** Maschinencode generieren **********************/
306 gen_computestackframe ();
310 for (i=0; i<jcodelength; i++) {
312 if (b) if (b->reached) block_genmcode (b);
315 b = list_first (&finishedblocks);
317 if (b->type != BLOCKTYPE_JAVA) block_genmcode (b);
318 b = list_next (&finishedblocks, b);
325 /*********** Zwischendarstellungen auf Wunsch ausgeben **********/
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]);
332 printf ("Max locals: %d\n", (int) maxlocals);
333 printf ("Max stack: %d\n", (int) maxstack);
335 for (i=0; i<jcodelength; i++) {
337 if (b) if (b->reached) block_display (b);
339 b = list_first (&finishedblocks);
341 if (b->type != BLOCKTYPE_JAVA) block_display (b);
342 b = list_next (&finishedblocks, b);
349 if (showdisassemble) {
351 disassemble ( (void*) (m->mcode + dseglen), mcodelen);
357 /***************** Dump-Speicher zurueckgeben *************/
359 dump_release (dumpsize);
362 /******************* Zeit messen **************************/
364 if (getcompilingtime) {
365 stoptime = getcputime();
366 compilingtime += (stoptime-starttime);
369 /******** Alle Klassen initialisieren, die gebraucht wurden *******/
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 */
378 class_init (c); /* ruft unter Umst"anden wieder */
379 /* den Compiler auf */
384 intsRestore(); /* schani */
388 /****** Return pointer to the methods entry point **********/
390 return m -> entrypoint;
396 /***************** Funktionen zum Initialisieren und Terminieren *************/
398 void compiler_init ()
402 has_ext_instr_set = ! has_no_x_instr_set();
404 for (i=0; i<256;i++) stdopdescriptors[i]=NULL;
406 for (i=0; i<sizeof(stdopdescriptortable)/sizeof(stdopdescriptor); i++) {
408 if (stdopdescriptortable[i].isfloat && checkfloats) {
409 stdopdescriptortable[i].supported = false;
412 stdopdescriptors[stdopdescriptortable[i].opcode] =
413 &(stdopdescriptortable[i]);
418 void compiler_close()