1 /* src/vm/jit/cfg.c - build a control-flow graph
3 Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 #include "mm/memory.h"
35 #include "vm/global.h"
37 #include "vm/jit/jit.h"
38 #include "vm/jit/stack.h"
41 /* cfg_allocate_predecessors ***************************************************
43 Allocates the predecessor array, if there is none, and resets the
46 *******************************************************************************/
48 static void cfg_allocate_predecessors(basicblock *bptr)
50 if (bptr->predecessors == NULL) {
51 bptr->predecessors = DMNEW(basicblock*, bptr->predecessorcount);
53 bptr->predecessorcount = 0;
58 /* cfg_allocate_successors *****************************************************
60 Allocates the succecessor array, if there is none, and resets the
63 *******************************************************************************/
65 static void cfg_allocate_successors(basicblock *bptr)
67 if (bptr->successors == NULL) {
68 bptr->successors = DMNEW(basicblock*, bptr->successorcount);
70 bptr->successorcount = 0;
75 /* cfg_insert_predecessor ******************************************************
77 Inserts a predecessor into the array, but checks for duplicate
78 entries. This is used for TABLESWITCH and LOOKUPSWITCH.
80 *******************************************************************************/
82 static void cfg_insert_predecessors(basicblock *bptr, basicblock *pbptr)
87 tbptr = bptr->predecessors;
89 /* check if the predecessors is already stored in the array */
91 for (i = 0; i < bptr->predecessorcount; i++, tbptr++)
95 /* not found, insert it */
97 bptr->predecessors[bptr->predecessorcount] = pbptr;
98 bptr->predecessorcount++;
101 static void cfg_insert_successors(basicblock *bptr, basicblock *pbptr)
106 tbptr = bptr->successors;
108 /* check if the successor is already stored in the array */
110 for (i = 0; i < bptr->successorcount; i++, tbptr++)
114 /* not found, insert it */
116 bptr->successors[bptr->successorcount] = pbptr;
117 bptr->successorcount++;
121 /* cfg_build *******************************************************************
123 Build a control-flow graph in finding all predecessors and
124 successors for the basic blocks.
126 *******************************************************************************/
128 bool cfg_build(jitdata *jd)
134 branch_target_t *table;
135 lookup_target_t *lookup;
137 bool has_fallthrough;
139 /* process all basic blocks to find the predecessor/successor counts */
141 bptr = jd->basicblocks;
143 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
144 if ((bptr->icount == 0) || (bptr->flags == BBUNDEF))
147 iptr = bptr->iinstr + bptr->icount - 1;
149 /* skip NOPs at the end of the block */
151 while (iptr->opc == ICMD_NOP) {
152 if (iptr == bptr->iinstr)
157 if (iptr->opc == ICMD_GOTO) {
160 This is needed for the following special case caused by
161 stack_reach_next_block:
162 I.e. there might be instructions causing control flow before
166 129: 192: IFEQ Ti102 0 (0x00000000) --> L052
171 bptr->successorcount++;
173 tbptr = iptr->dst.block;
174 tbptr->predecessorcount++;
176 if (iptr == bptr->iinstr) {
182 while (iptr->opc == ICMD_NOP) {
183 if (iptr == bptr->iinstr) {
189 has_fallthrough = false;
191 has_fallthrough = true;
194 switch (icmd_table[iptr->opc].controlflow) {
201 bptr->successorcount += 2;
203 tbptr = iptr->dst.block;
204 tbptr->predecessorcount++;
206 if (has_fallthrough) {
208 ntbptr->predecessorcount++;
213 bptr->successorcount++;
215 tbptr = iptr->sx.s23.s3.jsrtarget.block;
216 tbptr->predecessorcount++;
221 bptr->successorcount++;
223 tbptr = iptr->dst.block;
224 tbptr->predecessorcount++;
228 table = iptr->dst.table;
230 bptr->successorcount++;
232 tbptr = table->block;
233 tbptr->predecessorcount++;
236 i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
239 bptr->successorcount++;
241 tbptr = table->block;
242 tbptr->predecessorcount++;
248 lookup = iptr->dst.lookup;
250 bptr->successorcount++;
252 tbptr = iptr->sx.s23.s3.lookupdefault.block;
253 tbptr->predecessorcount++;
255 i = iptr->sx.s23.s2.lookupcount;
258 bptr->successorcount++;
260 tbptr = lookup->target.block;
261 tbptr->predecessorcount++;
267 if (has_fallthrough) {
268 bptr->successorcount++;
272 /* An exception handler has no predecessors. */
274 if (tbptr->type != BBTYPE_EXH)
275 tbptr->predecessorcount++;
281 /* Second iteration to allocate the arrays and insert the basic
284 bptr = jd->basicblocks;
286 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
287 if ((bptr->icount == 0) || (bptr->flags == BBUNDEF))
290 iptr = bptr->iinstr + bptr->icount - 1;
292 /* skip NOPs at the end of the block */
294 while (iptr->opc == ICMD_NOP) {
295 if (iptr == bptr->iinstr)
300 if (iptr->opc == ICMD_GOTO) {
301 tbptr = iptr->dst.block;
303 cfg_allocate_successors(bptr);
305 cfg_insert_successors(bptr, tbptr);
307 cfg_allocate_predecessors(tbptr);
309 cfg_insert_predecessors(tbptr, bptr);
311 if (iptr == bptr->iinstr) {
317 while (iptr->opc == ICMD_NOP) {
318 if (iptr == bptr->iinstr) {
324 has_fallthrough = false;
327 has_fallthrough = true;
330 switch (icmd_table[iptr->opc].controlflow) {
337 tbptr = iptr->dst.block;
340 cfg_allocate_successors(bptr);
342 cfg_insert_successors(bptr, tbptr);
343 if (has_fallthrough) {
344 cfg_insert_successors(bptr, ntbptr);
347 cfg_allocate_predecessors(tbptr);
348 if (has_fallthrough) {
349 cfg_allocate_predecessors(ntbptr);
352 cfg_insert_predecessors(tbptr, bptr);
353 if (has_fallthrough) {
354 cfg_insert_predecessors(ntbptr, bptr);
359 tbptr = iptr->sx.s23.s3.jsrtarget.block;
365 tbptr = iptr->dst.block;
367 cfg_allocate_successors(bptr);
369 cfg_insert_successors(bptr, tbptr);
371 cfg_allocate_predecessors(tbptr);
373 cfg_insert_predecessors(tbptr, bptr);
377 table = iptr->dst.table;
379 tbptr = table->block;
382 cfg_allocate_successors(bptr);
384 cfg_insert_successors(bptr, tbptr);
386 cfg_allocate_predecessors(tbptr);
388 cfg_insert_predecessors(tbptr, bptr);
390 i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
393 tbptr = table->block;
396 cfg_insert_successors(bptr, tbptr);
398 cfg_allocate_predecessors(tbptr);
399 cfg_insert_predecessors(tbptr, bptr);
404 lookup = iptr->dst.lookup;
406 tbptr = iptr->sx.s23.s3.lookupdefault.block;
408 cfg_allocate_successors(bptr);
410 cfg_insert_successors(bptr, tbptr);
412 cfg_allocate_predecessors(tbptr);
414 cfg_insert_predecessors(tbptr, bptr);
416 i = iptr->sx.s23.s2.lookupcount;
419 tbptr = lookup->target.block;
422 cfg_insert_successors(bptr, tbptr);
424 cfg_allocate_predecessors(tbptr);
425 cfg_insert_predecessors(tbptr, bptr);
430 if (has_fallthrough) {
433 cfg_allocate_successors(bptr);
435 bptr->successors[0] = tbptr;
436 bptr->successorcount++;
438 /* An exception handler has no predecessors. */
440 if (tbptr->type != BBTYPE_EXH) {
441 cfg_allocate_predecessors(tbptr);
443 tbptr->predecessors[tbptr->predecessorcount] = bptr;
444 tbptr->predecessorcount++;
451 /* everything's ok */
456 /* cfg_add_root ****************************************************************
458 Adds an empty root basicblock.
459 The numbers of all other basicblocks are set off by one.
460 Needed for some analyses that require the root basicblock to have no
461 predecessors and to perform special initializations.
463 *******************************************************************************/
465 void cfg_add_root(jitdata *jd) {
466 basicblock *root, *zero, *it;
468 zero = jd->basicblocks;
470 root = DNEW(basicblock);
471 MZERO(root, basicblock, 1);
473 root->successorcount = 1;
474 root->successors = DMNEW(basicblock *, 1);
475 root->successors[0] = zero;
478 root->type = BBTYPE_STD;
480 if (zero->predecessorcount == 0) {
481 zero->predecessors = DNEW(basicblock *);
483 zero->predecessors = DMREALLOC(zero->predecessors, basicblock *, zero->predecessorcount, zero->predecessorcount + 1);
485 zero->predecessors[zero->predecessorcount] = root;
486 zero->predecessorcount += 1;
488 jd->basicblocks = root;
489 jd->basicblockcount += 1;
491 for (it = zero; it; it = it->next) {
496 #if defined(ENABLE_SSA)
498 /* cfg_add_exceptional_edges ***************************************************
500 Edges from basicblocks to their exception handlers and from exception
501 handlers to the blocks they handle exceptions for are added. Further
502 the number of potentially throwing instructions in the basicblocks are
505 We don't consider nor do we determine the types of exceptions thrown. Edges
506 are added from every block to every potential handler.
508 *******************************************************************************/
510 void cfg_add_exceptional_edges(jitdata *jd) {
515 /* Count the number of exceptional exits for every block.
516 * Every PEI is an exceptional out.
519 FOR_EACH_BASICBLOCK(jd, bptr) {
521 if (bptr->flags == BBUNDEF) {
525 FOR_EACH_INSTRUCTION(bptr, iptr) {
526 if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
532 /* Count the number of exception handlers for every block. */
534 for (ee = jd->exceptiontable; ee; ee = ee->down) {
535 for (bptr = ee->start; bptr != ee->end; bptr = bptr->next) {
536 /* Linking a block with a handler, even if there are no exceptional exits
537 breaks stuff in other passes. */
538 if (bptr->exouts > 0) {
539 bptr->exhandlercount += 1;
540 ee->handler->expredecessorcount += 1;
545 /* Allocate and fill exception handler arrays. */
547 for (ee = jd->exceptiontable; ee; ee = ee->down) {
548 for (bptr = ee->start; bptr != ee->end; bptr = bptr->next) {
549 if (bptr->exouts > 0) {
551 if (bptr->exhandlers == NULL) {
552 bptr->exhandlers = DMNEW(basicblock *, bptr->exhandlercount);
553 /* Move pointer past the end of the array,
554 * It will be filled in the reverse order.
556 bptr->exhandlers += bptr->exhandlercount;
559 bptr->exhandlers -= 1;
560 *(bptr->exhandlers) = ee->handler;
562 if (ee->handler->expredecessors == NULL) {
563 ee->handler->expredecessors = DMNEW(basicblock *, ee->handler->expredecessorcount);
564 ee->handler->expredecessors += ee->handler->expredecessorcount;
567 ee->handler->expredecessors -= 1;
568 *(ee->handler->expredecessors) = bptr;
577 * These are local overrides for various environment variables in Emacs.
578 * Please do not remove this and leave it at the end of the file, where
579 * Emacs will automagically detect them.
580 * ---------------------------------------------------------------------
583 * indent-tabs-mode: t
587 * vim:noexpandtab:sw=4:ts=4: