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 1203 2004-06-22 23:14:55Z 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
75 void depthFirst(methodinfo *m)
79 /* allocate memory and init gobal variables needed by function dF(m, int, int) */
81 c_defnum = DMNEW(int, m->basicblockcount);
82 c_numPre = DMNEW(int, m->basicblockcount);
83 c_parent = DMNEW(int, m->basicblockcount);
84 c_reverse = DMNEW(int, m->basicblockcount);
85 c_pre = DMNEW(int *, m->basicblockcount);
86 c_dTable = DMNEW(struct depthElement *, m->basicblockcount);
88 for (i = 0; i < m->basicblockcount; ++i) {
89 c_defnum[i] = c_parent[i] = -1;
90 c_numPre[i] = c_reverse[i] = 0;
92 c_pre[i] = DMNEW(int, m->basicblockcount);
99 dF(m, -1, 0); /* call helper function dF that traverses basic block structure */
104 dF starts from the first block of the given procedure and traverses the
105 control flow graph in a depth-first order, thereby building up the adeacency
108 void dF(methodinfo *m, int from, int blockIndex)
112 int high, low, count;
113 struct depthElement *hp;
114 struct LoopContainer *tmp;
118 /* the current basic block has a predecessor (ie. is not the first one) */
119 /* if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL) */
121 hp = DNEW(struct depthElement);/* create new depth element */
123 hp->next = c_dTable[from]; /* insert values */
124 hp->value = blockIndex;
127 c_dTable[from] = hp; /* insert into table */
130 if (from == blockIndex) { /* insert one node loops into loop container */
131 /* if ((tmp = (struct LoopContainer *) malloc(sizeof(struct LoopContainer))) == NULL) */
133 tmp = DNEW(struct LoopContainer);
134 LoopContainerInit(m, tmp, blockIndex);
135 tmp->next = c_allLoops;
140 if (blockIndex > m->basicblockcount) {
141 panic("DepthFirst: BlockIndex exceeded\n");
145 ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
146 /* set ip to last instruction */
148 if (c_defnum[blockIndex] == -1) { /* current block has not been visited */
149 c_defnum[blockIndex] = c_globalCount; /* update global count */
150 c_parent[blockIndex] = from; /* write parent block of current one */
151 c_reverse[c_globalCount] = blockIndex;
154 if (!m->basicblocks[blockIndex].icount) {
155 /* block does not contain instructions */
156 dF(m, blockIndex, blockIndex+1);
158 else { /* for all successors, do */
159 switch (ip->opc) { /* check type of last instruction */
167 break; /* function returns -> end of graph */
184 case ICMD_IF_ACMPNE: /* branch -> check next block */
185 dF(m, blockIndex, blockIndex + 1);
189 dF(m, blockIndex, m->basicblockindex[ip->op1]);
190 break; /* visit branch (goto) target */
192 case ICMD_TABLESWITCH: /* switch statement */
195 dF(m, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
202 count = (high-low+1);
204 while (--count >= 0) {
206 dF(m, blockIndex, m->basicblockindex[*s4ptr]);
210 case ICMD_LOOKUPSWITCH: /* switch statement */
213 dF(m, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
218 while (--count >= 0) {
219 dF(m, blockIndex, m->basicblockindex[s4ptr[1]]);
225 c_last_jump = blockIndex;
226 dF(m, blockIndex, m->basicblockindex[ip->op1]);
230 dF(m, blockIndex, c_last_jump+1);
234 dF(m, blockIndex, blockIndex + 1);
240 for (ptr = c_pre[blockIndex], cnt = 0; cnt < c_numPre[blockIndex]; ++cnt, ++ptr)
246 if (cnt >= c_numPre[blockIndex]) {
247 c_pre[blockIndex][c_numPre[blockIndex]] = from;
248 /* add predeccessors to list c_pre */
249 c_numPre[blockIndex]++; /* increase number of predecessors */
255 a slightly modified version of dF(m, int, int) that is used to traverse the part
256 of the control graph that is not reached by normal program flow but by the
257 raising of exceptions (code of catch blocks)
259 void dF_Exception(methodinfo *m, int from, int blockIndex)
263 int high, low, count;
264 struct depthElement *hp;
266 if (c_exceptionVisit[blockIndex] < 0) /* has block been visited, return */
267 c_exceptionVisit[blockIndex] = 1;
271 if (c_dTable[blockIndex] != NULL) /* back to regular code section */
274 if (from >= 0) { /* build exception graph (in c_exceptionGraph) */
275 /* if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL) */
277 hp = DNEW(struct depthElement);
278 hp->next = c_exceptionGraph[from];
279 hp->value = blockIndex;
282 c_exceptionGraph[from] = hp;
286 if (blockIndex > m->basicblockcount) {
287 panic("DepthFirst: BlockIndex exceeded");
291 ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
293 if (!m->basicblocks[blockIndex].icount)
294 dF_Exception(m, blockIndex, blockIndex+1);
322 dF_Exception(m, blockIndex, blockIndex + 1);
326 dF_Exception(m, blockIndex, m->basicblockindex[ip->op1]);
329 case ICMD_TABLESWITCH:
333 dF_Exception(m, blockIndex, m->basicblockindex[*s4ptr]);
340 count = (high-low+1);
342 while (--count >= 0) {
344 dF_Exception(m, blockIndex, m->basicblockindex[*s4ptr]);
348 case ICMD_LOOKUPSWITCH:
352 dF_Exception(m, blockIndex, m->basicblockindex[*s4ptr]);
357 while (--count >= 0) {
358 dF_Exception(m, blockIndex, m->basicblockindex[s4ptr[1]]);
364 c_last_jump = blockIndex;
365 dF_Exception(m, blockIndex, m->basicblockindex[ip->op1]);
369 dF_Exception(m, blockIndex, c_last_jump+1);
373 dF_Exception(m, blockIndex, blockIndex + 1);
382 Test function -> will be removed in final release
387 struct depthElement *hp;
389 printf("\n\n****** PASS 1 ******\n\n");
390 printf("Number of Nodes: %d\n\n", c_globalCount);
392 printf("Predecessors:\n");
393 for (i=0; i<m->basicblockcount; ++i) {
394 printf("Block %d:\t", i);
395 for (j=0; j<c_numPre[i]; ++j)
396 printf("%d ", c_pre[i][j]);
402 for (i=0; i<m->basicblockcount; ++i) {
403 printf("Block %d:\t", i);
407 printf("%d ", hp->value);
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