1 /* jit/loop/graph.c - control flow graph
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Christopher Kruegel
29 Changes: Christian Thalinger
31 Contains the functions which build a list, that represents the
32 control flow graph of the procedure, that is being analyzed.
34 $Id: graph.c 1454 2004-11-05 14:19:32Z twisti $
41 #include "jit/loop/graph.h"
42 #include "jit/loop/loop.h"
43 #include "toolbox/memory.h"
46 void LoopContainerInit(methodinfo *m, struct LoopContainer *lc, int i)
48 struct LoopElement *le = DMNEW(struct LoopElement, 1);
54 lc->tree_right = NULL;
57 lc->exceptions = NULL;
60 le->node = lc->loop_head = i;
61 le->block = &m->basicblocks[i];
63 /* lc->nodes = (int *) malloc(sizeof(int)*m->basicblockcount);
71 depthFirst() builds the control flow graph out of the intermediate code of
72 the procedure, that is to be optimized and stores the list in the global
76 void depthFirst(methodinfo *m, loopdata *ld)
80 /* allocate memory and init gobal variables needed by function dF(m, int, int) */
82 ld->c_defnum = DMNEW(int, m->basicblockcount);
83 ld->c_numPre = DMNEW(int, m->basicblockcount);
84 ld->c_parent = DMNEW(int, m->basicblockcount);
85 ld->c_reverse = DMNEW(int, m->basicblockcount);
86 ld->c_pre = DMNEW(int *, m->basicblockcount);
87 ld->c_dTable = DMNEW(struct depthElement *, m->basicblockcount);
89 for (i = 0; i < m->basicblockcount; ++i) {
90 ld->c_defnum[i] = ld->c_parent[i] = -1;
91 ld->c_numPre[i] = ld->c_reverse[i] = 0;
93 ld->c_pre[i] = DMNEW(int, m->basicblockcount);
94 ld->c_dTable[i] = NULL;
97 ld->c_globalCount = 0;
98 ld->c_allLoops = NULL;
100 dF(m, ld, -1, 0); /* call helper function dF that traverses basic block structure */
105 dF starts from the first block of the given procedure and traverses the
106 control flow graph in a depth-first order, thereby building up the adeacency
110 void dF(methodinfo *m, loopdata *ld, int from, int blockIndex)
114 int high, low, count;
115 struct depthElement *hp;
116 struct LoopContainer *tmp;
120 /* the current basic block has a predecessor (ie. is not the first one) */
121 hp = DNEW(struct depthElement);/* create new depth element */
123 hp->next = ld->c_dTable[from]; /* insert values */
124 hp->value = blockIndex;
127 ld->c_dTable[from] = hp; /* insert into table */
130 if (from == blockIndex) { /* insert one node loops into loop container */
131 tmp = DNEW(struct LoopContainer);
132 LoopContainerInit(m, tmp, blockIndex);
133 tmp->next = ld->c_allLoops;
134 ld->c_allLoops = tmp;
138 if (blockIndex > m->basicblockcount) {
139 panic("DepthFirst: BlockIndex exceeded\n");
143 ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
144 /* set ip to last instruction */
146 if (ld->c_defnum[blockIndex] == -1) { /* current block has not been visited */
147 ld->c_defnum[blockIndex] = ld->c_globalCount; /* update global count */
148 ld->c_parent[blockIndex] = from; /* write parent block of current one */
149 ld->c_reverse[ld->c_globalCount] = blockIndex;
152 if (!m->basicblocks[blockIndex].icount) {
153 /* block does not contain instructions */
154 dF(m, ld, blockIndex, blockIndex+1);
156 else { /* for all successors, do */
157 switch (ip->opc) { /* check type of last instruction */
165 break; /* function returns -> end of graph */
182 case ICMD_IF_ACMPNE: /* branch -> check next block */
183 dF(m, ld, blockIndex, blockIndex + 1);
187 dF(m, ld, blockIndex, m->basicblockindex[ip->op1]);
188 break; /* visit branch (goto) target */
190 case ICMD_TABLESWITCH: /* switch statement */
193 dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
200 count = (high-low+1);
202 while (--count >= 0) {
204 dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
208 case ICMD_LOOKUPSWITCH: /* switch statement */
211 dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
216 while (--count >= 0) {
217 dF(m, ld, blockIndex, m->basicblockindex[s4ptr[1]]);
223 ld->c_last_jump = blockIndex;
224 dF(m, ld, blockIndex, m->basicblockindex[ip->op1]);
228 dF(m, ld, blockIndex, ld->c_last_jump+1);
232 dF(m, ld, blockIndex, blockIndex + 1);
238 for (ptr = ld->c_pre[blockIndex], cnt = 0; cnt < ld->c_numPre[blockIndex]; ++cnt, ++ptr)
244 if (cnt >= ld->c_numPre[blockIndex]) {
245 ld->c_pre[blockIndex][ld->c_numPre[blockIndex]] = from;
246 /* add predeccessors to list c_pre */
247 ld->c_numPre[blockIndex]++; /* increase number of predecessors */
254 a slightly modified version of dF(m, ld, int, int) that is used to traverse the part
255 of the control graph that is not reached by normal program flow but by the
256 raising of exceptions (code of catch blocks)
259 void dF_Exception(methodinfo *m, loopdata *ld, int from, int blockIndex)
263 int high, low, count;
264 struct depthElement *hp;
266 if (ld->c_exceptionVisit[blockIndex] < 0) /* has block been visited, return */
267 ld->c_exceptionVisit[blockIndex] = 1;
271 if (ld->c_dTable[blockIndex] != NULL) /* back to regular code section */
274 if (from >= 0) { /* build exception graph (in c_exceptionGraph) */
275 hp = DNEW(struct depthElement);
276 hp->next = ld->c_exceptionGraph[from];
277 hp->value = blockIndex;
280 ld->c_exceptionGraph[from] = hp;
284 if (blockIndex > m->basicblockcount) {
285 panic("DepthFirst: BlockIndex exceeded");
289 ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
291 if (!m->basicblocks[blockIndex].icount)
292 dF_Exception(m, ld, blockIndex, blockIndex+1);
320 dF_Exception(m, ld, blockIndex, blockIndex + 1);
324 dF_Exception(m, ld, blockIndex, m->basicblockindex[ip->op1]);
327 case ICMD_TABLESWITCH:
331 dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
338 count = (high-low+1);
340 while (--count >= 0) {
342 dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
346 case ICMD_LOOKUPSWITCH:
350 dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
355 while (--count >= 0) {
356 dF_Exception(m, ld, blockIndex, m->basicblockindex[s4ptr[1]]);
362 ld->c_last_jump = blockIndex;
363 dF_Exception(m, ld, blockIndex, m->basicblockindex[ip->op1]);
367 dF_Exception(m, ld, blockIndex, ld->c_last_jump+1);
371 dF_Exception(m, ld, blockIndex, blockIndex + 1);
380 Test function -> will be removed in final release
382 void resultPass1(methodinfo *m)
385 struct depthElement *hp;
390 printf("\n\n****** PASS 1 ******\n\n");
391 printf("Number of Nodes: %d\n\n", ld->c_globalCount);
393 printf("Predecessors:\n");
394 for (i=0; i<m->basicblockcount; ++i) {
395 printf("Block %d:\t", i);
396 for (j=0; j<ld->c_numPre[i]; ++j)
397 printf("%d ", ld->c_pre[i][j]);
403 for (i=0; i<m->basicblockcount; ++i) {
404 printf("Block %d:\t", i);
405 hp = ld->c_dTable[i];
408 printf("%d ", hp->value);
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