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
31 $Id: cacao.c 4357 2006-01-22 23:33:38Z twisti $
42 #include "mm/memory.h"
43 #include "vm/jit/jit.h"
44 #include "vm/jit/stack.h"
47 /* cfg_allocate_predecessors ***************************************************
49 Allocates the predecessor array, if there is none, and resets the
52 *******************************************************************************/
54 static void cfg_allocate_predecessors(basicblock *bptr)
56 if (bptr->predecessors == NULL) {
57 bptr->predecessors = DMNEW(basicblock*, bptr->predecessorcount);
59 bptr->predecessorcount = 0;
64 /* cfg_allocate_successors *****************************************************
66 Allocates the succecessor array, if there is none, and resets the
69 *******************************************************************************/
71 static void cfg_allocate_successors(basicblock *bptr)
73 if (bptr->successors == NULL) {
74 bptr->successors = DMNEW(basicblock*, bptr->successorcount);
76 bptr->successorcount = 0;
81 /* cfg_insert_predecessor ******************************************************
83 Inserts a predecessor into the array, but checks for duplicate
84 entries. This is used for TABLESWITCH and LOOKUPSWITCH.
86 *******************************************************************************/
88 static void cfg_insert_predecessors(basicblock *bptr, basicblock *pbptr)
93 tbptr = bptr->predecessors;
95 /* check if the predecessors is already stored in the array */
97 for (i = 0; i < bptr->predecessorcount; i++, tbptr++)
101 /* not found, insert it */
103 bptr->predecessors[bptr->predecessorcount] = pbptr;
104 bptr->predecessorcount++;
108 /* cfg_build *******************************************************************
110 Build a control-flow graph in finding all predecessors and
111 successors for the basic blocks.
113 *******************************************************************************/
115 bool cfg_build(jitdata *jd)
121 branch_target_t *table;
122 lookup_target_t *lookup;
125 /* process all basic blocks to find the predecessor/successor counts */
127 bptr = jd->basicblocks;
129 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
130 if ((bptr->icount == 0) || (bptr->flags == BBUNDEF))
133 iptr = bptr->iinstr + bptr->icount - 1;
135 /* skip NOPs at the end of the block */
137 while (iptr->opc == ICMD_NOP) {
138 if (iptr == bptr->iinstr)
172 bptr->successorcount += 2;
174 tbptr = iptr->dst.block;
177 tbptr->predecessorcount++;
178 ntbptr->predecessorcount++;
182 bptr->successorcount++;
184 tbptr = iptr->sx.s23.s3.jsrtarget.block;
185 tbptr->predecessorcount++;
190 bptr->successorcount++;
192 tbptr = iptr->dst.block;
193 tbptr->predecessorcount++;
196 case ICMD_TABLESWITCH:
197 table = iptr->dst.table;
199 bptr->successorcount++;
201 tbptr = table->block;
202 tbptr->predecessorcount++;
205 i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
208 bptr->successorcount++;
210 tbptr = table->block;
211 tbptr->predecessorcount++;
216 case ICMD_LOOKUPSWITCH:
217 lookup = iptr->dst.lookup;
219 bptr->successorcount++;
221 tbptr = iptr->sx.s23.s3.lookupdefault.block;
222 tbptr->predecessorcount++;
224 i = iptr->sx.s23.s2.lookupcount;
227 bptr->successorcount++;
229 tbptr = lookup->target.block;
230 tbptr->predecessorcount++;
236 bptr->successorcount++;
240 /* An exception handler has no predecessors. */
242 if (tbptr->type != BBTYPE_EXH)
243 tbptr->predecessorcount++;
248 /* Second iteration to allocate the arrays and insert the basic
251 bptr = jd->basicblocks;
253 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
254 if ((bptr->icount == 0) || (bptr->flags == BBUNDEF))
257 iptr = bptr->iinstr + bptr->icount - 1;
259 /* skip NOPs at the end of the block */
261 while (iptr->opc == ICMD_NOP) {
262 if (iptr == bptr->iinstr)
296 tbptr = iptr->dst.block;
299 cfg_allocate_successors(bptr);
301 bptr->successors[0] = tbptr;
302 bptr->successors[1] = ntbptr;
303 bptr->successorcount += 2;
305 cfg_allocate_predecessors(tbptr);
306 cfg_allocate_predecessors(ntbptr);
308 tbptr->predecessors[tbptr->predecessorcount] = bptr;
309 tbptr->predecessorcount++;
311 ntbptr->predecessors[ntbptr->predecessorcount] = bptr;
312 ntbptr->predecessorcount++;
316 tbptr = iptr->sx.s23.s3.jsrtarget.block;
321 tbptr = iptr->dst.block;
323 cfg_allocate_successors(bptr);
325 bptr->successors[0] = tbptr;
326 bptr->successorcount++;
328 cfg_allocate_predecessors(tbptr);
330 tbptr->predecessors[tbptr->predecessorcount] = bptr;
331 tbptr->predecessorcount++;
334 case ICMD_TABLESWITCH:
335 table = iptr->dst.table;
337 tbptr = table->block;
340 cfg_allocate_successors(bptr);
342 bptr->successors[0] = tbptr;
343 bptr->successorcount++;
345 cfg_allocate_predecessors(tbptr);
347 tbptr->predecessors[tbptr->predecessorcount] = bptr;
348 tbptr->predecessorcount++;
350 i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
353 tbptr = table->block;
356 bptr->successors[bptr->successorcount] = tbptr;
357 bptr->successorcount++;
359 cfg_allocate_predecessors(tbptr);
360 cfg_insert_predecessors(tbptr, bptr);
364 case ICMD_LOOKUPSWITCH:
365 lookup = iptr->dst.lookup;
367 tbptr = iptr->sx.s23.s3.lookupdefault.block;
369 cfg_allocate_successors(bptr);
371 bptr->successors[0] = tbptr;
372 bptr->successorcount++;
374 cfg_allocate_predecessors(tbptr);
376 tbptr->predecessors[tbptr->predecessorcount] = bptr;
377 tbptr->predecessorcount++;
379 i = iptr->sx.s23.s2.lookupcount;
382 tbptr = lookup->target.block;
385 bptr->successors[bptr->successorcount] = tbptr;
386 bptr->successorcount++;
388 cfg_allocate_predecessors(tbptr);
389 cfg_insert_predecessors(tbptr, bptr);
396 cfg_allocate_successors(bptr);
398 bptr->successors[0] = tbptr;
399 bptr->successorcount++;
401 /* An exception handler has no predecessors. */
403 if (tbptr->type != BBTYPE_EXH) {
404 cfg_allocate_predecessors(tbptr);
406 tbptr->predecessors[tbptr->predecessorcount] = bptr;
407 tbptr->predecessorcount++;
413 /* everything's ok */
420 * These are local overrides for various environment variables in Emacs.
421 * Please do not remove this and leave it at the end of the file, where
422 * Emacs will automagically detect them.
423 * ---------------------------------------------------------------------
426 * indent-tabs-mode: t
430 * vim:noexpandtab:sw=4:ts=4: