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 576 2003-11-09 17:31:38Z twisti $
43 #include "toolbox/memory.h"
46 void LoopContainerInit(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 = &block[i];
63 /* lc->nodes = (int *) malloc(sizeof(int)*block_count);
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
79 /* allocate memory and init gobal variables needed by function dF(int, int) */
81 /* if ((c_defnum = (int *) malloc(block_count * sizeof(int))) == NULL) */
83 /* if ((c_numPre = (int *) malloc(block_count * sizeof(int))) == NULL) */
85 /* if ((c_parent = (int *) malloc(block_count * sizeof(int))) == NULL) */
87 /* if ((c_reverse = (int *) malloc(block_count * sizeof(int))) == NULL) */
90 /* if ((c_pre = (int **) malloc(block_count * sizeof(int *))) == NULL) */
93 /* if ((c_dTable = (struct depthElement **) malloc(block_count * sizeof(struct depthElement *))) == NULL) */
96 /* for (i = 0; i < block_count; ++i) { */
97 /* c_defnum[i] = c_parent[i] = -1; */
98 /* c_numPre[i] = c_reverse[i] = 0; */
100 /* if ((c_pre[i] = (int *) malloc(block_count * sizeof(int))) == NULL) */
102 /* c_dTable[i] = NULL; */
105 c_defnum = DMNEW(int, block_count);
106 c_numPre = DMNEW(int, block_count);
107 c_parent = DMNEW(int, block_count);
108 c_reverse = DMNEW(int, block_count);
109 c_pre = DMNEW(int *, block_count);
110 c_dTable = DMNEW(struct depthElement *, block_count);
112 for (i = 0; i < block_count; ++i) {
113 c_defnum[i] = c_parent[i] = -1;
114 c_numPre[i] = c_reverse[i] = 0;
116 c_pre[i] = DMNEW(int, block_count);
123 dF(-1, 0); /* call helper function dF that traverses basic block structure */
128 dF starts from the first block of the given procedure and traverses the
129 control flow graph in a depth-first order, thereby building up the adeacency
132 void dF(int from, int blockIndex)
136 int high, low, count;
137 struct depthElement *hp;
138 struct LoopContainer *tmp;
142 /* the current basic block has a predecessor (ie. is not the first one) */
143 /* if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL) */
145 hp = DNEW(struct depthElement);/* create new depth element */
147 hp->next = c_dTable[from]; /* insert values */
148 hp->value = blockIndex;
151 c_dTable[from] = hp; /* insert into table */
154 if (from == blockIndex) { /* insert one node loops into loop container */
155 /* if ((tmp = (struct LoopContainer *) malloc(sizeof(struct LoopContainer))) == NULL) */
157 tmp = DNEW(struct LoopContainer);
158 LoopContainerInit(tmp, blockIndex);
159 tmp->next = c_allLoops;
164 if (blockIndex > block_count) {
165 panic("DepthFirst: BlockIndex exceeded\n");
169 ip = block[blockIndex].iinstr + block[blockIndex].icount -1;
170 /* set ip to last instruction */
172 if (c_defnum[blockIndex] == -1) { /* current block has not been visited */
173 c_defnum[blockIndex] = c_globalCount; /* update global count */
174 c_parent[blockIndex] = from; /* write parent block of current one */
175 c_reverse[c_globalCount] = blockIndex;
178 if (!block[blockIndex].icount) {
179 /* block does not contain instructions */
180 dF(blockIndex, blockIndex+1);
182 else { /* for all successors, do */
183 switch (ip->opc) { /* check type of last instruction */
191 break; /* function returns -> end of graph */
208 case ICMD_IF_ACMPNE: /* branch -> check next block */
209 dF(blockIndex, blockIndex + 1);
213 dF(blockIndex, block_index[ip->op1]);
214 break; /* visit branch (goto) target */
216 case ICMD_TABLESWITCH: /* switch statement */
219 dF(blockIndex, block_index[*s4ptr]); /* default branch */
226 count = (high-low+1);
228 while (--count >= 0) {
230 dF(blockIndex, block_index[*s4ptr]);
234 case ICMD_LOOKUPSWITCH: /* switch statement */
237 dF(blockIndex, block_index[*s4ptr]); /* default branch */
242 while (--count >= 0) {
243 dF(blockIndex, block_index[s4ptr[1]]);
249 c_last_jump = blockIndex;
250 dF(blockIndex, block_index[ip->op1]);
254 dF(blockIndex, c_last_jump+1);
258 dF(blockIndex, blockIndex + 1);
264 for (ptr = c_pre[blockIndex], cnt = 0; cnt < c_numPre[blockIndex]; ++cnt, ++ptr)
270 if (cnt >= c_numPre[blockIndex]) {
271 c_pre[blockIndex][c_numPre[blockIndex]] = from;
272 /* add predeccessors to list c_pre */
273 c_numPre[blockIndex]++; /* increase number of predecessors */
279 a slightly modified version of dF(int, int) that is used to traverse the part
280 of the control graph that is not reached by normal program flow but by the
281 raising of exceptions (code of catch blocks)
283 void dF_Exception(int from, int blockIndex)
287 int high, low, count;
288 struct depthElement *hp;
290 if (c_exceptionVisit[blockIndex] < 0) /* has block been visited, return */
291 c_exceptionVisit[blockIndex] = 1;
295 if (c_dTable[blockIndex] != NULL) /* back to regular code section */
298 if (from >= 0) { /* build exception graph (in c_exceptionGraph) */
299 /* if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL) */
301 hp = DNEW(struct depthElement);
302 hp->next = c_exceptionGraph[from];
303 hp->value = blockIndex;
306 c_exceptionGraph[from] = hp;
310 if (blockIndex > block_count) {
311 panic("DepthFirst: BlockIndex exceeded");
315 ip = block[blockIndex].iinstr + block[blockIndex].icount -1;
317 if (!block[blockIndex].icount)
318 dF_Exception(blockIndex, blockIndex+1);
346 dF_Exception(blockIndex, blockIndex + 1);
350 dF_Exception(blockIndex, block_index[ip->op1]);
353 case ICMD_TABLESWITCH:
357 dF_Exception(blockIndex, block_index[*s4ptr]);
364 count = (high-low+1);
366 while (--count >= 0) {
368 dF_Exception(blockIndex, block_index[*s4ptr]);
372 case ICMD_LOOKUPSWITCH:
376 dF_Exception(blockIndex, block_index[*s4ptr]);
381 while (--count >= 0) {
382 dF_Exception(blockIndex, block_index[s4ptr[1]]);
388 c_last_jump = blockIndex;
389 dF_Exception(blockIndex, block_index[ip->op1]);
393 dF_Exception(blockIndex, c_last_jump+1);
397 dF_Exception(blockIndex, blockIndex + 1);
405 Test function -> will be removed in final release
410 struct depthElement *hp;
412 printf("\n\n****** PASS 1 ******\n\n");
413 printf("Number of Nodes: %d\n\n", c_globalCount);
415 printf("Predecessors:\n");
416 for (i=0; i<block_count; ++i) {
417 printf("Block %d:\t", i);
418 for (j=0; j<c_numPre[i]; ++j)
419 printf("%d ", c_pre[i][j]);
425 for (i=0; i<block_count; ++i) {
426 printf("Block %d:\t", i);
430 printf("%d ", hp->value);
439 * These are local overrides for various environment variables in Emacs.
440 * Please do not remove this and leave it at the end of the file, where
441 * Emacs will automagically detect them.
442 * ---------------------------------------------------------------------
445 * indent-tabs-mode: t