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;
138 /* process all basic blocks to find the predecessor/successor counts */
140 bptr = jd->basicblocks;
142 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
143 if ((bptr->icount == 0) || (bptr->flags == BBUNDEF))
146 iptr = bptr->iinstr + bptr->icount - 1;
148 /* skip NOPs at the end of the block */
150 while (iptr->opc == ICMD_NOP) {
151 if (iptr == bptr->iinstr)
156 switch (icmd_table[iptr->opc].controlflow) {
163 bptr->successorcount += 2;
165 tbptr = iptr->dst.block;
168 tbptr->predecessorcount++;
169 ntbptr->predecessorcount++;
173 bptr->successorcount++;
175 tbptr = iptr->sx.s23.s3.jsrtarget.block;
176 tbptr->predecessorcount++;
181 bptr->successorcount++;
183 tbptr = iptr->dst.block;
184 tbptr->predecessorcount++;
188 table = iptr->dst.table;
190 bptr->successorcount++;
192 tbptr = table->block;
193 tbptr->predecessorcount++;
196 i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
199 bptr->successorcount++;
201 tbptr = table->block;
202 tbptr->predecessorcount++;
208 lookup = iptr->dst.lookup;
210 bptr->successorcount++;
212 tbptr = iptr->sx.s23.s3.lookupdefault.block;
213 tbptr->predecessorcount++;
215 i = iptr->sx.s23.s2.lookupcount;
218 bptr->successorcount++;
220 tbptr = lookup->target.block;
221 tbptr->predecessorcount++;
227 bptr->successorcount++;
231 /* An exception handler has no predecessors. */
233 if (tbptr->type != BBTYPE_EXH)
234 tbptr->predecessorcount++;
239 /* Second iteration to allocate the arrays and insert the basic
242 bptr = jd->basicblocks;
244 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
245 if ((bptr->icount == 0) || (bptr->flags == BBUNDEF))
248 iptr = bptr->iinstr + bptr->icount - 1;
250 /* skip NOPs at the end of the block */
252 while (iptr->opc == ICMD_NOP) {
253 if (iptr == bptr->iinstr)
258 switch (icmd_table[iptr->opc].controlflow) {
265 tbptr = iptr->dst.block;
268 cfg_allocate_successors(bptr);
270 cfg_insert_successors(bptr, tbptr);
271 cfg_insert_successors(bptr, ntbptr);
273 cfg_allocate_predecessors(tbptr);
274 cfg_allocate_predecessors(ntbptr);
276 cfg_insert_predecessors(tbptr, bptr);
277 cfg_insert_predecessors(ntbptr, bptr);
281 tbptr = iptr->sx.s23.s3.jsrtarget.block;
287 tbptr = iptr->dst.block;
289 cfg_allocate_successors(bptr);
291 cfg_insert_successors(bptr, tbptr);
293 cfg_allocate_predecessors(tbptr);
295 cfg_insert_predecessors(tbptr, bptr);
299 table = iptr->dst.table;
301 tbptr = table->block;
304 cfg_allocate_successors(bptr);
306 cfg_insert_successors(bptr, tbptr);
308 cfg_allocate_predecessors(tbptr);
310 cfg_insert_predecessors(tbptr, bptr);
312 i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
315 tbptr = table->block;
318 cfg_insert_successors(bptr, tbptr);
320 cfg_allocate_predecessors(tbptr);
321 cfg_insert_predecessors(tbptr, bptr);
326 lookup = iptr->dst.lookup;
328 tbptr = iptr->sx.s23.s3.lookupdefault.block;
330 cfg_allocate_successors(bptr);
332 cfg_insert_successors(bptr, tbptr);
334 cfg_allocate_predecessors(tbptr);
336 cfg_insert_predecessors(tbptr, bptr);
338 i = iptr->sx.s23.s2.lookupcount;
341 tbptr = lookup->target.block;
344 cfg_insert_successors(bptr, tbptr);
346 cfg_allocate_predecessors(tbptr);
347 cfg_insert_predecessors(tbptr, bptr);
354 cfg_allocate_successors(bptr);
356 bptr->successors[0] = tbptr;
357 bptr->successorcount++;
359 /* An exception handler has no predecessors. */
361 if (tbptr->type != BBTYPE_EXH) {
362 cfg_allocate_predecessors(tbptr);
364 tbptr->predecessors[tbptr->predecessorcount] = bptr;
365 tbptr->predecessorcount++;
371 /* everything's ok */
376 /* cfg_add_root ****************************************************************
378 Adds an empty root basicblock.
379 The numbers of all other basicblocks are set off by one.
380 Needed for some analyses that require the root basicblock to have no
381 predecessors and to perform special initializations.
383 *******************************************************************************/
385 void cfg_add_root(jitdata *jd) {
386 basicblock *root, *zero, *it;
388 zero = jd->basicblocks;
390 root = DNEW(basicblock);
391 MZERO(root, basicblock, 1);
393 root->successorcount = 1;
394 root->successors = DMNEW(basicblock *, 1);
395 root->successors[0] = zero;
398 root->type = BBTYPE_STD;
400 if (zero->predecessorcount == 0) {
401 zero->predecessors = DNEW(basicblock *);
403 zero->predecessors = DMREALLOC(zero->predecessors, basicblock *, zero->predecessorcount, zero->predecessorcount + 1);
405 zero->predecessors[zero->predecessorcount] = root;
406 zero->predecessorcount += 1;
408 jd->basicblocks = root;
409 jd->basicblockcount += 1;
411 for (it = zero; it; it = it->next) {
417 * These are local overrides for various environment variables in Emacs.
418 * Please do not remove this and leave it at the end of the file, where
419 * Emacs will automagically detect them.
420 * ---------------------------------------------------------------------
423 * indent-tabs-mode: t
427 * vim:noexpandtab:sw=4:ts=4: