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 extern int newcompiler;
36 methodptr new_compile (methodinfo *m); /* compile a method with new compiler */
38 /************************** no all in newcomp.c
40 bool compileverbose = false;
41 bool showstack = false;
42 bool showintermediate = false;
43 bool showdisassemble = false;
44 int optimizelevel = 0;
46 bool checkbounds = true;
47 bool checknull = true;
48 bool checkfloats = true;
49 bool checksync = true;
51 bool getcompilingtime = false;
52 long int compilingtime = 0;
53 int has_ext_instr_set = 0;
55 bool statistics = false;
57 int count_jit_calls = 0;
58 int count_methods = 0;
60 int count_pcmd_activ = 0;
61 int count_pcmd_drop = 0;
62 int count_pcmd_zero = 0;
63 int count_pcmd_const_store = 0;
64 int count_pcmd_const_alu = 0;
65 int count_pcmd_const_bra = 0;
66 int count_pcmd_load = 0;
67 int count_pcmd_move = 0;
68 int count_pcmd_store = 0;
69 int count_pcmd_store_comb = 0;
70 int count_pcmd_op = 0;
71 int count_pcmd_mem = 0;
72 int count_pcmd_met = 0;
73 int count_pcmd_bra = 0;
74 int count_pcmd_table = 0;
75 int count_pcmd_return = 0;
76 int count_pcmd_returnx = 0;
77 int count_check_null = 0;
78 int count_javainstr = 0;
79 int count_javacodesize = 0;
80 int count_javaexcsize = 0;
82 int count_tryblocks = 0;
83 int count_code_len = 0;
84 int count_data_len = 0;
85 int count_cstub_len = 0;
86 int count_nstub_len = 0;
91 /************************ die Datentypen f"ur den Compiler *******************/
93 #include "comp/defines.c"
97 /******************* globale Variablen fuer den Compiler *********************/
99 static methodinfo *method; /* Zeiger auf die Methodenstruktur */
100 static unicode *descriptor; /* Typbeschreibung der Methode */
101 static classinfo *class; /* Klasse, in der die Methode steht */
103 static s4 maxstack; /* maximale Gr"osse des JavaVM-Stacks */
104 static s4 maxlocals; /* maximale Anzahl der JavaVM-Variablen */
105 static u4 jcodelength; /* L"ange des JavaVM-Codes */
106 static u1 *jcode; /* Zeiger auf den JavaVM-Code */
107 static s4 exceptiontablelength; /* L"ange der Exceptiontable */
108 static exceptiontable *extable; /* Zeiger auf die Exceptiontable */
111 static list reachedblocks; /* Die Listenstruktur f"ur alle vom Parser
112 bereits irgendwie erreichten Bl"ocke */
113 static list finishedblocks; /* Die Listenstruktur f"ur alle Bl"ocke, die
114 vom Parser bereits durchgearbeitet wurden */
116 static basicblock **blocks; /* Eine Tabelle, so lang wie der JavaVM-Code, */
117 /* in der an jeder Stelle, an der ein */
118 /* Basicblock beginnt, der Zeiger auf die */
119 /* ensprechende Basicblock-Struktur einge- */
122 static bool isleafmethod; /* true, wenn die Methode KEINE weiteren
123 Unterprogramme mehr aufruft */
125 static s4 mparamnum; /* Die Anzahl der Parameter (incl. this) */
126 static u1 *mparamtypes; /* Die Typen aller Parameter (TYPE_INT,...) */
127 static s4 mreturntype; /* R"uckgabewert der Methode */
128 static varinfo **mparamvars; /* Die PCMD-Variablen, die die Parameter */
129 /* zu Methodenstart enthalten sollen */
132 static chain *uninitializedclasses;
133 /* Eine Tabelle aller von der Methode */
134 /* irgendwie ben"otigten Klassen, die */
135 /* vor dem Start der Methode initialisiert */
136 /* werden m"ussen (wenn sie es noch nicht */
140 /************************ Subsysteme des Compilers ***************************/
143 #include "comp/tools.c" /* ein paar n"utzliche Hilfsfunktionen */
144 #include "comp/mcode.c" /* systemUNabh"angiger Teil des Codegenerators */
146 #include "comp/reg.c" /* Registerverwaltung */
147 #include "comp/var.c" /* Die Verwaltung der PCMD-Variblen */
148 #include "comp/pcmd.c" /* Funktionen f"ur die Pseudocommandos (=PCMD) */
149 #include "comp/local.c" /* Verwaltung der lokalen JavaVM-Variablen */
150 #include "comp/stack.c" /* Verwaltung des JavaVM-Stacks */
151 #include "comp/regalloc.c" /* Registerallokator */
153 #include "sysdep/gen.c" /* systemABh"angiger Codegenerator */
154 #include "sysdep/disass.c" /* Disassembler (nur zu Debug-Zwecken) */
156 #include "comp/block.c" /* Verwaltung der basic blocks */
157 #include "comp/parse.c" /* JavaVM - parser */
162 /****** Die Dummy-Function (wird verwendet, wenn kein Code vorhanden ist) ****/
164 static void* do_nothing_function()
172 /******************************************************************************/
173 /*********************** eine Methode compilieren *****************************/
174 /******************************************************************************/
177 methodptr compiler_compile (methodinfo *m)
181 long int starttime=0,stoptime=0;
185 return new_compile(m);
188 /*** Wenn schon ein Maschinencode vorliegt, dann sofort beenden ****/
190 count_jit_calls++; /* andi */
191 if (m->entrypoint) return m->entrypoint;
193 intsDisable(); /* schani */
196 /**************** Marke fuer den DUMP-Speicher aufheben *****************/
198 dumpsize = dump_size ();
201 /**************** Zeit messen *******************************************/
203 count_methods++; /* andi */
204 if (getcompilingtime) starttime=getcputime();
206 /*** Meldung ausgeben. Wenn kein JavaVM-Code vorhanden ist, beenden ****/
209 if (compileverbose) {
210 sprintf (logtext, "Compiling: ");
211 unicode_sprint (logtext+strlen(logtext), m->class->name);
212 strcpy (logtext+strlen(logtext), ".");
213 unicode_sprint (logtext+strlen(logtext), m->name);
214 unicode_sprint (logtext+strlen(logtext), m->descriptor);
219 sprintf (logtext, "No code given for: ");
220 unicode_sprint (logtext+strlen(logtext), m->class->name);
221 strcpy (logtext+strlen(logtext), ".");
222 unicode_sprint (logtext+strlen(logtext), m->name);
223 unicode_sprint (logtext+strlen(logtext), m->descriptor);
225 intsRestore(); /* schani */
226 return (methodptr) do_nothing_function;
230 /*********** Initialisieren der Variablen und Subsysteme *****************/
232 isleafmethod = true; /* bis sich das Gegenteil herausstellt */
235 descriptor = m->descriptor;
238 maxstack = m->maxstack;
239 maxlocals = m->maxlocals;
240 jcodelength = m->jcodelength;
242 count_tryblocks += (exceptiontablelength = m->exceptiontablelength);
243 extable = m->exceptiontable;
246 count_javacodesize += jcodelength + 18;
247 count_javaexcsize += exceptiontablelength * 8;
250 list_init (&reachedblocks, OFFSET(basicblock, linkage) );
251 list_init (&finishedblocks, OFFSET(basicblock, linkage) );
253 blocks = DMNEW (basicblock*, jcodelength);
254 for (i=0; i<jcodelength; i++) blocks[i] = NULL;
257 descriptor2types (descriptor, (m->flags & ACC_STATIC) != 0,
258 &mparamnum, &mparamtypes, &mreturntype);
259 m->paramcount = mparamnum;
260 m->returntype = mreturntype;
261 mparamvars = DMNEW (varid, mparamnum);
268 uninitializedclasses = chain_new();
269 /* aktuelle Klasse zur Liste der m"oglicherweise zu
270 initialisierenden Klassen dazugeben */
271 compiler_addinitclass (m->class);
274 /************************ Compilieren ************************/
276 /* Fuer jedes Sprungziel einen eigenen Block erzeugen */
279 /* Den ersten Block als erreicht markieren, der Stack ist leer */
281 subroutine_set(NULL);
282 block_reach ( block_find(0) );
284 /* Alle schon erreichten Bl"ocke durchgehen und fertig machen */
285 while ( (b = list_first (&reachedblocks)) ) {
286 list_remove (&reachedblocks, b);
287 list_addlast (&finishedblocks, b);
288 b -> finished = true;
290 pcmd_init ( &(b->pcmdlist) );
294 input_args_prealloc ();
296 /* F"ur alle Bl"ocke die Registerbelegung durchfuehren */
297 b = list_first (&finishedblocks);
300 b = list_next (&finishedblocks, b);
304 /* Registerbelegung fuer die lokalen JAVA-Variablen */
310 /**************** Maschinencode generieren **********************/
312 gen_computestackframe ();
316 for (i=0; i<jcodelength; i++) {
318 if (b) if (b->reached) block_genmcode (b);
321 b = list_first (&finishedblocks);
323 if (b->type != BLOCKTYPE_JAVA) block_genmcode (b);
324 b = list_next (&finishedblocks, b);
331 /*********** Zwischendarstellungen auf Wunsch ausgeben **********/
333 if (showintermediate) {
334 printf ("Leaf-method: %s\n", isleafmethod ? "YES":"NO");
335 printf ("Parameters: ");
336 for (i=0; i<mparamnum; i++) var_display (mparamvars[i]);
338 printf ("Max locals: %d\n", (int) maxlocals);
339 printf ("Max stack: %d\n", (int) maxstack);
341 for (i=0; i<jcodelength; i++) {
343 if (b) if (b->reached) block_display (b);
345 b = list_first (&finishedblocks);
347 if (b->type != BLOCKTYPE_JAVA) block_display (b);
348 b = list_next (&finishedblocks, b);
355 if (showdisassemble) {
357 disassemble ( (void*) (m->mcode + dseglen), mcodelen);
363 /***************** Dump-Speicher zurueckgeben *************/
365 dump_release (dumpsize);
368 /******************* Zeit messen **************************/
370 if (getcompilingtime) {
371 stoptime = getcputime();
372 compilingtime += (stoptime-starttime);
375 /******** Alle Klassen initialisieren, die gebraucht wurden *******/
378 chain *u = uninitializedclasses; /* wegen reentrant-F"ahigkeit */
379 classinfo *c; /* d"urfen ab hier keine */
380 /* globalen Variablen verwendet */
381 while ( (c = chain_first(u)) ) { /* werden */
384 class_init (c); /* ruft unter Umst"anden wieder */
385 /* den Compiler auf */
390 intsRestore(); /* schani */
394 /****** Return pointer to the methods entry point **********/
396 return m -> entrypoint;
402 /***************** Funktionen zum Initialisieren und Terminieren *************/
404 void compiler_init ()
408 has_ext_instr_set = ! has_no_x_instr_set();
410 for (i=0; i<256;i++) stdopdescriptors[i]=NULL;
412 for (i=0; i<sizeof(stdopdescriptortable)/sizeof(stdopdescriptor); i++) {
414 if (stdopdescriptortable[i].isfloat && checkfloats) {
415 stdopdescriptortable[i].supported = false;
418 stdopdescriptors[stdopdescriptortable[i].opcode] =
419 &(stdopdescriptortable[i]);
424 void compiler_close()