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++;
102 /* cfg_build *******************************************************************
104 Build a control-flow graph in finding all predecessors and
105 successors for the basic blocks.
107 *******************************************************************************/
109 bool cfg_build(jitdata *jd)
115 branch_target_t *table;
116 lookup_target_t *lookup;
119 /* process all basic blocks to find the predecessor/successor counts */
121 bptr = jd->basicblocks;
123 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
124 if ((bptr->icount == 0) || (bptr->flags == BBUNDEF))
127 iptr = bptr->iinstr + bptr->icount - 1;
129 /* skip NOPs at the end of the block */
131 while (iptr->opc == ICMD_NOP) {
132 if (iptr == bptr->iinstr)
166 bptr->successorcount += 2;
168 tbptr = iptr->dst.block;
171 tbptr->predecessorcount++;
172 ntbptr->predecessorcount++;
176 bptr->successorcount++;
178 tbptr = iptr->sx.s23.s3.jsrtarget.block;
179 tbptr->predecessorcount++;
184 bptr->successorcount++;
186 tbptr = iptr->dst.block;
187 tbptr->predecessorcount++;
190 case ICMD_TABLESWITCH:
191 table = iptr->dst.table;
193 bptr->successorcount++;
195 tbptr = table->block;
196 tbptr->predecessorcount++;
199 i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
202 bptr->successorcount++;
204 tbptr = table->block;
205 tbptr->predecessorcount++;
210 case ICMD_LOOKUPSWITCH:
211 lookup = iptr->dst.lookup;
213 bptr->successorcount++;
215 tbptr = iptr->sx.s23.s3.lookupdefault.block;
216 tbptr->predecessorcount++;
218 i = iptr->sx.s23.s2.lookupcount;
221 bptr->successorcount++;
223 tbptr = lookup->target.block;
224 tbptr->predecessorcount++;
230 bptr->successorcount++;
234 /* An exception handler has no predecessors. */
236 if (tbptr->type != BBTYPE_EXH)
237 tbptr->predecessorcount++;
242 /* Second iteration to allocate the arrays and insert the basic
245 bptr = jd->basicblocks;
247 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
248 if ((bptr->icount == 0) || (bptr->flags == BBUNDEF))
251 iptr = bptr->iinstr + bptr->icount - 1;
253 /* skip NOPs at the end of the block */
255 while (iptr->opc == ICMD_NOP) {
256 if (iptr == bptr->iinstr)
290 tbptr = iptr->dst.block;
293 cfg_allocate_successors(bptr);
295 bptr->successors[0] = tbptr;
296 bptr->successors[1] = ntbptr;
297 bptr->successorcount += 2;
299 cfg_allocate_predecessors(tbptr);
300 cfg_allocate_predecessors(ntbptr);
302 tbptr->predecessors[tbptr->predecessorcount] = bptr;
303 tbptr->predecessorcount++;
305 ntbptr->predecessors[ntbptr->predecessorcount] = bptr;
306 ntbptr->predecessorcount++;
310 tbptr = iptr->sx.s23.s3.jsrtarget.block;
315 tbptr = iptr->dst.block;
317 cfg_allocate_successors(bptr);
319 bptr->successors[0] = tbptr;
320 bptr->successorcount++;
322 cfg_allocate_predecessors(tbptr);
324 tbptr->predecessors[tbptr->predecessorcount] = bptr;
325 tbptr->predecessorcount++;
328 case ICMD_TABLESWITCH:
329 table = iptr->dst.table;
331 tbptr = table->block;
334 cfg_allocate_successors(bptr);
336 bptr->successors[0] = tbptr;
337 bptr->successorcount++;
339 cfg_allocate_predecessors(tbptr);
341 tbptr->predecessors[tbptr->predecessorcount] = bptr;
342 tbptr->predecessorcount++;
344 i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
347 tbptr = table->block;
350 bptr->successors[bptr->successorcount] = tbptr;
351 bptr->successorcount++;
353 cfg_allocate_predecessors(tbptr);
354 cfg_insert_predecessors(tbptr, bptr);
358 case ICMD_LOOKUPSWITCH:
359 lookup = iptr->dst.lookup;
361 tbptr = iptr->sx.s23.s3.lookupdefault.block;
363 cfg_allocate_successors(bptr);
365 bptr->successors[0] = tbptr;
366 bptr->successorcount++;
368 cfg_allocate_predecessors(tbptr);
370 tbptr->predecessors[tbptr->predecessorcount] = bptr;
371 tbptr->predecessorcount++;
373 i = iptr->sx.s23.s2.lookupcount;
376 tbptr = lookup->target.block;
379 bptr->successors[bptr->successorcount] = tbptr;
380 bptr->successorcount++;
382 cfg_allocate_predecessors(tbptr);
383 cfg_insert_predecessors(tbptr, bptr);
390 cfg_allocate_successors(bptr);
392 bptr->successors[0] = tbptr;
393 bptr->successorcount++;
395 /* An exception handler has no predecessors. */
397 if (tbptr->type != BBTYPE_EXH) {
398 cfg_allocate_predecessors(tbptr);
400 tbptr->predecessors[tbptr->predecessorcount] = bptr;
401 tbptr->predecessorcount++;
407 /* everything's ok */
414 * These are local overrides for various environment variables in Emacs.
415 * Please do not remove this and leave it at the end of the file, where
416 * Emacs will automagically detect them.
417 * ---------------------------------------------------------------------
420 * indent-tabs-mode: t
424 * vim:noexpandtab:sw=4:ts=4: