1 /* src/vm/cfg.c - build a control-flow graph
3 Copyright (C) 2006 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
25 Contact: cacao@cacaojvm.org
27 Authors: Christian Thalinger
29 Changes: Edwin Steiner
40 #include "mm/memory.h"
41 #include "vm/jit/jit.h"
42 #include "vm/jit/stack.h"
45 /* cfg_allocate_predecessors ***************************************************
47 Allocates the predecessor array, if there is none, and resets the
50 *******************************************************************************/
52 static void cfg_allocate_predecessors(basicblock *bptr)
54 if (bptr->predecessors == NULL) {
55 bptr->predecessors = DMNEW(basicblock*, bptr->predecessorcount);
57 bptr->predecessorcount = 0;
62 /* cfg_allocate_successors *****************************************************
64 Allocates the succecessor array, if there is none, and resets the
67 *******************************************************************************/
69 static void cfg_allocate_successors(basicblock *bptr)
71 if (bptr->successors == NULL) {
72 bptr->successors = DMNEW(basicblock*, bptr->successorcount);
74 bptr->successorcount = 0;
79 /* cfg_insert_predecessor ******************************************************
81 Inserts a predecessor into the array, but checks for duplicate
82 entries. This is used for TABLESWITCH and LOOKUPSWITCH.
84 *******************************************************************************/
86 static void cfg_insert_predecessors(basicblock *bptr, basicblock *pbptr)
91 tbptr = bptr->predecessors;
93 /* check if the predecessors is already stored in the array */
95 for (i = 0; i < bptr->predecessorcount; i++, tbptr++)
99 /* not found, insert it */
101 bptr->predecessors[bptr->predecessorcount] = pbptr;
102 bptr->predecessorcount++;
106 /* cfg_build *******************************************************************
108 Build a control-flow graph in finding all predecessors and
109 successors for the basic blocks.
111 *******************************************************************************/
113 bool cfg_build(jitdata *jd)
119 branch_target_t *table;
120 lookup_target_t *lookup;
123 /* process all basic blocks to find the predecessor/successor counts */
125 bptr = jd->basicblocks;
127 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
128 if ((bptr->icount == 0) || (bptr->flags == BBUNDEF))
131 iptr = bptr->iinstr + bptr->icount - 1;
133 /* skip NOPs at the end of the block */
135 while (iptr->opc == ICMD_NOP) {
136 if (iptr == bptr->iinstr)
170 bptr->successorcount += 2;
172 tbptr = iptr->dst.block;
175 tbptr->predecessorcount++;
176 ntbptr->predecessorcount++;
180 bptr->successorcount++;
182 tbptr = iptr->sx.s23.s3.jsrtarget.block;
183 tbptr->predecessorcount++;
188 bptr->successorcount++;
190 tbptr = iptr->dst.block;
191 tbptr->predecessorcount++;
194 case ICMD_TABLESWITCH:
195 table = iptr->dst.table;
197 bptr->successorcount++;
199 tbptr = table->block;
200 tbptr->predecessorcount++;
203 i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
206 bptr->successorcount++;
208 tbptr = table->block;
209 tbptr->predecessorcount++;
214 case ICMD_LOOKUPSWITCH:
215 lookup = iptr->dst.lookup;
217 bptr->successorcount++;
219 tbptr = iptr->sx.s23.s3.lookupdefault.block;
220 tbptr->predecessorcount++;
222 i = iptr->sx.s23.s2.lookupcount;
225 bptr->successorcount++;
227 tbptr = lookup->target.block;
228 tbptr->predecessorcount++;
234 bptr->successorcount++;
238 /* An exception handler has no predecessors. */
240 if (tbptr->type != BBTYPE_EXH)
241 tbptr->predecessorcount++;
246 /* Second iteration to allocate the arrays and insert the basic
249 bptr = jd->basicblocks;
251 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
252 if ((bptr->icount == 0) || (bptr->flags == BBUNDEF))
255 iptr = bptr->iinstr + bptr->icount - 1;
257 /* skip NOPs at the end of the block */
259 while (iptr->opc == ICMD_NOP) {
260 if (iptr == bptr->iinstr)
294 tbptr = iptr->dst.block;
297 cfg_allocate_successors(bptr);
299 bptr->successors[0] = tbptr;
300 bptr->successors[1] = ntbptr;
301 bptr->successorcount += 2;
303 cfg_allocate_predecessors(tbptr);
304 cfg_allocate_predecessors(ntbptr);
306 tbptr->predecessors[tbptr->predecessorcount] = bptr;
307 tbptr->predecessorcount++;
309 ntbptr->predecessors[ntbptr->predecessorcount] = bptr;
310 ntbptr->predecessorcount++;
314 tbptr = iptr->sx.s23.s3.jsrtarget.block;
319 tbptr = iptr->dst.block;
321 cfg_allocate_successors(bptr);
323 bptr->successors[0] = tbptr;
324 bptr->successorcount++;
326 cfg_allocate_predecessors(tbptr);
328 tbptr->predecessors[tbptr->predecessorcount] = bptr;
329 tbptr->predecessorcount++;
332 case ICMD_TABLESWITCH:
333 table = iptr->dst.table;
335 tbptr = table->block;
338 cfg_allocate_successors(bptr);
340 bptr->successors[0] = tbptr;
341 bptr->successorcount++;
343 cfg_allocate_predecessors(tbptr);
345 tbptr->predecessors[tbptr->predecessorcount] = bptr;
346 tbptr->predecessorcount++;
348 i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
351 tbptr = table->block;
354 bptr->successors[bptr->successorcount] = tbptr;
355 bptr->successorcount++;
357 cfg_allocate_predecessors(tbptr);
358 cfg_insert_predecessors(tbptr, bptr);
362 case ICMD_LOOKUPSWITCH:
363 lookup = iptr->dst.lookup;
365 tbptr = iptr->sx.s23.s3.lookupdefault.block;
367 cfg_allocate_successors(bptr);
369 bptr->successors[0] = tbptr;
370 bptr->successorcount++;
372 cfg_allocate_predecessors(tbptr);
374 tbptr->predecessors[tbptr->predecessorcount] = bptr;
375 tbptr->predecessorcount++;
377 i = iptr->sx.s23.s2.lookupcount;
380 tbptr = lookup->target.block;
383 bptr->successors[bptr->successorcount] = tbptr;
384 bptr->successorcount++;
386 cfg_allocate_predecessors(tbptr);
387 cfg_insert_predecessors(tbptr, bptr);
394 cfg_allocate_successors(bptr);
396 bptr->successors[0] = tbptr;
397 bptr->successorcount++;
399 /* An exception handler has no predecessors. */
401 if (tbptr->type != BBTYPE_EXH) {
402 cfg_allocate_predecessors(tbptr);
404 tbptr->predecessors[tbptr->predecessorcount] = bptr;
405 tbptr->predecessorcount++;
411 /* everything's ok */
418 * These are local overrides for various environment variables in Emacs.
419 * Please do not remove this and leave it at the end of the file, where
420 * Emacs will automagically detect them.
421 * ---------------------------------------------------------------------
424 * indent-tabs-mode: t
428 * vim:noexpandtab:sw=4:ts=4: