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
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)
122 branch_target_t *table;
123 lookup_target_t *lookup;
126 /* get required compiler data */
130 /* process all basic blocks to find the predecessor/successor counts */
132 bptr = jd->new_basicblocks;
134 for (i = 0; i < jd->new_basicblockcount; i++, bptr++) {
135 if (bptr->icount == 0)
138 iptr = bptr->iinstr + bptr->icount - 1;
170 bptr->successorcount += 2;
172 tbptr = BLOCK_OF(iptr->dst.insindex);
175 tbptr->predecessorcount++;
176 ntbptr->predecessorcount++;
180 bptr->successorcount++;
182 tbptr = BLOCK_OF(iptr->dst.insindex);
183 tbptr->predecessorcount++;
186 case ICMD_TABLESWITCH:
187 table = iptr->dst.table;
189 bptr->successorcount++;
191 tbptr = BLOCK_OF((table++)->insindex);
192 tbptr->predecessorcount++;
194 j = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
197 bptr->successorcount++;
199 tbptr = BLOCK_OF((table++)->insindex);
200 tbptr->predecessorcount++;
204 case ICMD_LOOKUPSWITCH:
205 lookup = iptr->dst.lookup;
207 bptr->successorcount++;
209 tbptr = BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex);
210 tbptr->predecessorcount++;
212 j = iptr->sx.s23.s2.lookupcount;
215 bptr->successorcount++;
217 tbptr = BLOCK_OF((lookup++)->target.insindex);
218 tbptr->predecessorcount++;
223 bptr->successorcount++;
226 tbptr->predecessorcount++;
231 /* Second iteration to allocate the arrays and insert the basic
234 bptr = jd->new_basicblocks;
236 for (i = 0; i < jd->new_basicblockcount; i++, bptr++) {
237 if (bptr->icount == 0)
240 iptr = bptr->iinstr + bptr->icount - 1;
272 tbptr = BLOCK_OF(iptr->dst.insindex);
275 cfg_allocate_successors(bptr);
277 bptr->successors[0] = tbptr;
278 bptr->successors[1] = ntbptr;
279 bptr->successorcount += 2;
281 cfg_allocate_predecessors(tbptr);
282 cfg_allocate_predecessors(ntbptr);
284 tbptr->predecessors[tbptr->predecessorcount] = bptr;
285 tbptr->predecessorcount++;
287 ntbptr->predecessors[ntbptr->predecessorcount] = bptr;
288 ntbptr->predecessorcount++;
292 tbptr = BLOCK_OF(iptr->dst.insindex);
294 cfg_allocate_successors(bptr);
296 bptr->successors[0] = tbptr;
297 bptr->successorcount++;
299 cfg_allocate_predecessors(tbptr);
301 tbptr->predecessors[tbptr->predecessorcount] = bptr;
302 tbptr->predecessorcount++;
305 case ICMD_TABLESWITCH:
306 table = iptr->dst.table;
308 tbptr = BLOCK_OF((table++)->insindex);
310 cfg_allocate_successors(bptr);
312 bptr->successors[0] = tbptr;
313 bptr->successorcount++;
315 cfg_allocate_predecessors(tbptr);
317 tbptr->predecessors[tbptr->predecessorcount] = bptr;
318 tbptr->predecessorcount++;
320 j = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
323 tbptr = BLOCK_OF((table++)->insindex);
325 bptr->successors[bptr->successorcount] = tbptr;
326 bptr->successorcount++;
328 cfg_allocate_predecessors(tbptr);
329 cfg_insert_predecessors(tbptr, bptr);
333 case ICMD_LOOKUPSWITCH:
334 lookup = iptr->dst.lookup;
336 tbptr = BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex);
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 j = iptr->sx.s23.s2.lookupcount;
351 tbptr = BLOCK_OF((lookup++)->target.insindex);
353 bptr->successors[bptr->successorcount] = tbptr;
354 bptr->successorcount++;
356 cfg_allocate_predecessors(tbptr);
357 cfg_insert_predecessors(tbptr, bptr);
364 cfg_allocate_successors(bptr);
366 bptr->successors[0] = tbptr;
367 bptr->successorcount++;
369 cfg_allocate_predecessors(tbptr);
371 tbptr->predecessors[tbptr->predecessorcount] = bptr;
372 tbptr->predecessorcount++;
377 /* everything's ok */
384 * These are local overrides for various environment variables in Emacs.
385 * Please do not remove this and leave it at the end of the file, where
386 * Emacs will automagically detect them.
387 * ---------------------------------------------------------------------
390 * indent-tabs-mode: t
394 * vim:noexpandtab:sw=4:ts=4: