1 /***************************** comp/block.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 Basic block handling functions.
9 Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
11 Last Change: 1997/01/18
13 *******************************************************************************/
16 static u2 creatornum; /* Fortlaufende Nummerierung f"ur vom Compiler
17 generierte BasicBlocks (nur zu Debug-Zwecken) */
19 static subroutineinfo *actual_subroutine;
20 static u2 subroutinecounter=0;
23 /********************** Funktion: block_new ***********************************
25 erzeugt eine neue 'basicblock'-Struktur und initialisiert alle
28 ******************************************************************************/
30 static basicblock *block_new (u2 type, u4 codepos)
32 basicblock *b = DNEW (basicblock);
36 b -> finished = false;
37 b -> subroutine = NULL;
40 list_init (&(b->pcmdlist), OFFSET (pcmd, linkage) );
50 /******************* Funktion: block_find *************************************
52 Sucht den Basicblock, der an einer gew"unschten Stelle im JavaVM-Code
54 Wenn dort kein Block anf"angt -> Fehler
56 ******************************************************************************/
58 static basicblock *block_find (u4 codepos)
60 basicblock *b = blocks[codepos];
61 if (!b) panic ("Accessed JAVA-Command on no block boundary");
66 /****************** Funktion: block_isany *************************************
68 "uberpr"uft, ob an einer Stelle ein Basicblock anf"angt
70 ******************************************************************************/
72 static bool block_isany (u4 codepos)
74 return (blocks[codepos] != NULL);
78 /***************** Funktion: block_reach **************************************
80 H"angt einen Basicblock in die Liste der schon erreichten Bl"ocke ein,
81 und setzt seinen Blockeintrittsstack auf den aktuellen Stack und
82 setzt den Unterprogramminfoblock auf das aktuelle Unterprogramminfo
84 Wenn der Block bereits vorher als erreicht markiert war (und er deshalb
85 schon einen definierten Stack hatte), dann wird im derzeit vom
86 Parser durchlaufenen Block (also dort, von wo dieser Block aus
87 angesprungen wird) ein entsprechende Codest"uck hinzugef"ugt, der
88 die beiden Stacks aufeinander abstimmt.
90 ******************************************************************************/
92 static void block_reach (basicblock *b)
95 list_addlast (&reachedblocks, b);
97 b -> subroutine = actual_subroutine;
98 b -> stack = stack_get();
101 if (b->subroutine != actual_subroutine)
102 panic ("Try to merge different subroutines");
103 stack_addjoincode (b->stack);
107 /*********************** Funktion: subroutine_set *****************************
109 setzt den aktuellen Subroutine-Infoblock
111 *******************************************************************************/
113 static void subroutine_set (subroutineinfo *s)
115 actual_subroutine = s;
120 /*********************** Funktion: subroutine_new *****************************
122 erzeugt einen neuen Subroutine-Infoblock
124 *******************************************************************************/
126 static subroutineinfo *subroutine_new ()
128 subroutineinfo *s = DNEW (subroutineinfo);
129 s -> returnfinished = false;
130 s -> returnstack = NULL;
131 s -> callers = chain_dnew();
132 s -> counter = subroutinecounter++;
141 /********************** Funktion: block_insert ********************************
143 Erzeugt einen neuen Block, der an einer gew"unschten JavaVM-Code- Stelle
145 Der Zeiger auf diesen Block wird im (globalen) 'blocks'-Array
148 ******************************************************************************/
150 static void block_insert (u4 codepos)
152 if (codepos>=jcodelength) {
153 sprintf (logtext,"Basic block border (%d) out of bounds",(int) codepos);
157 if (blocks[codepos]) return;
159 blocks[codepos] = block_new (BLOCKTYPE_JAVA, codepos);
164 /******************** Funktion: block_createexcreator *************************
166 erzeugt einen neuen Basicblock vom Typ EXCREATOR (=Exception Creator)
168 ******************************************************************************/
170 static basicblock *block_createexcreator (java_objectheader *exproto, u4 throwpos)
174 b = block_new (BLOCKTYPE_EXCREATOR, creatornum++);
177 list_addlast (&reachedblocks, b);
178 b -> subroutine = actual_subroutine;
179 b -> exproto = exproto;
180 b -> throwpos = throwpos;
185 /******************* Funktion: block_createexforwarder ***********************
187 erzeugt einen neuen Basicblock vom Typ EXFORWARDER (=Exception Forwarder)
189 *****************************************************************************/
191 static basicblock *block_createexforwarder (varid exvar, u4 throwpos)
195 b = block_new (BLOCKTYPE_EXFORWARDER, creatornum++);
198 list_addlast (&reachedblocks, b);
199 b -> subroutine = actual_subroutine;
201 b -> throwpos = throwpos;
206 /********************** Funktion: block_genmcode ******************************
208 generiert f"ur einen vom Parser fertig abgearbeiteten Block den
210 Hintereinanderliegende Bl"ocke durch die der Kontrollflu"s ohne
211 Sprungbefehle durchgeht, m"ussen hier auch hintereinander
214 ******************************************************************************/
216 /* definition of block_genmcode moved to gen.c for inlining by andi */
219 /************************ Funktion: block_firstscann **************************
221 Liest den JavaVM-Code der ganzen Methode durch und erzeugt soviele
222 neue Bl"ocke, wie es verschiedene Sprungziele gibt.
224 ******************************************************************************/
226 static void block_firstscann ()
239 for (i=0; i<exceptiontablelength; i++) block_insert(extable[i].handlerpc);
243 while (p<jcodelength) {
250 nextp = p + jcommandsize[opcode];
269 block_insert ( p + code_get_s2 (p+1) );
273 block_insert ( p + code_get_s2 (p+1) );
278 block_insert ( p + code_get_s4 (p+1) );
283 block_insert ( p + code_get_s2 (p+1) );
288 block_insert ( p + code_get_s4 (p+1) );
311 switch (code_get_u1(p+1)) {
312 case CMD_RET: nextp = p+4;
315 case CMD_IINC: nextp = p+6;
317 default: nextp = p+4;
322 case CMD_LOOKUPSWITCH:
324 p2 = ALIGN ((p+1),4);
325 num = code_get_u4 (p2+4);
326 nextp = p2 + 8 + 8*num;
328 block_insert ( p + code_get_s4(p2) );
329 for (i=0; i<num; i++)
330 block_insert ( p + code_get_s4(p2+12+8*i) );
336 case CMD_TABLESWITCH:
338 p2 = ALIGN ((p+1),4);
339 num= code_get_u4(p2+8) - code_get_u4 (p2+4) + 1;
340 nextp = p2 + 12 + 4*num;
342 block_insert ( p + code_get_s4(p2) );
344 for (i=0; i<num; i++)
345 block_insert ( p + code_get_s4(p2+12+4*i) );
352 i = code_get_u1(p+1);
353 goto pushconstantitem;
356 i = code_get_u2(p + 1);
358 if (class_constanttype(class, i) == CONSTANT_String) {
360 s = class_getconstant(class, i, CONSTANT_String);
361 (void) literalstring_new(s);
366 if (nextp > jcodelength) panic ("Command-sequence crosses code-boundary");
370 if (!blockend) panic ("Code does not end with branch/return/athrow - stmt");
376 /************* Funktion: block_display (nur zu Debug-Zwecken) ****************/
378 void block_display (basicblock *b)
383 printf ("\n%ld in subroutine: %d", (long int) b->jpc, (int) b->subroutine->counter);
386 printf ("\n%ld:", (long int) b->jpc);
390 case BLOCKTYPE_JAVA: printf ("(JavaVM code)\n"); break;
391 case BLOCKTYPE_EXCREATOR: printf ("(Exception creator)\n"); break;
392 case BLOCKTYPE_EXFORWARDER: printf ("(Exception forwarder)\n"); break;
395 printf ("binding of stack: ");
396 stack_display (b->stack); printf ("\n");
398 p = list_first (&(b->pcmdlist));
401 p = list_next (&(b->pcmdlist), p);