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 557 2003-11-02 22:51:59Z 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)
108 dF(-1, 0); /* call helper function dF that traverses basic block structure */
113 dF starts from the first block of the given procedure and traverses the
114 control flow graph in a depth-first order, thereby building up the adeacency
117 void dF(int from, int blockIndex)
121 int high, low, count;
122 struct depthElement *hp;
123 struct LoopContainer *tmp;
127 /* the current basic block has a predecessor (ie. is not the first one) */
128 if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL)
129 c_mem_error(); /* cretae new depth element */
131 hp->next = c_dTable[from]; /* insert values */
132 hp->value = blockIndex;
135 c_dTable[from] = hp; /* insert into table */
138 if (from == blockIndex) { /* insert one node loops into loop container */
139 if ((tmp = (struct LoopContainer *) malloc(sizeof(struct LoopContainer))) == NULL)
141 LoopContainerInit(tmp, blockIndex);
142 tmp->next = c_allLoops;
147 if (blockIndex > block_count) {
148 fprintf(stderr, "DepthFirst: BlockIndex exceeded\n");
153 ip = block[blockIndex].iinstr + block[blockIndex].icount -1;
154 /* set ip to last instruction */
156 if (c_defnum[blockIndex] == -1) { /* current block has not been visited */
157 c_defnum[blockIndex] = c_globalCount; /* update global count */
158 c_parent[blockIndex] = from; /* write parent block of current one */
159 c_reverse[c_globalCount] = blockIndex;
162 if (!block[blockIndex].icount) {
163 /* block does not contain instructions */
164 dF(blockIndex, blockIndex+1);
166 else { /* for all successors, do */
167 switch (ip->opc) { /* check type of last instruction */
175 break; /* function returns -> end of graph */
192 case ICMD_IF_ACMPNE: /* branch -> check next block */
193 dF(blockIndex, blockIndex + 1);
197 dF(blockIndex, block_index[ip->op1]);
198 break; /* visit branch (goto) target */
200 case ICMD_TABLESWITCH: /* switch statement */
203 dF(blockIndex, block_index[*s4ptr]); /* default branch */
210 count = (high-low+1);
212 while (--count >= 0) {
214 dF(blockIndex, block_index[*s4ptr]);
218 case ICMD_LOOKUPSWITCH: /* switch statement */
221 dF(blockIndex, block_index[*s4ptr]); /* default branch */
226 while (--count >= 0) {
227 dF(blockIndex, block_index[s4ptr[1]]);
233 c_last_jump = blockIndex;
234 dF(blockIndex, block_index[ip->op1]);
238 dF(blockIndex, c_last_jump+1);
242 dF(blockIndex, blockIndex + 1);
248 for (ptr = c_pre[blockIndex], cnt = 0; cnt < c_numPre[blockIndex]; ++cnt, ++ptr)
254 if (cnt >= c_numPre[blockIndex]) {
255 c_pre[blockIndex][c_numPre[blockIndex]] = from;
256 /* add predeccessors to list c_pre */
257 c_numPre[blockIndex]++; /* increase number of predecessors */
263 a slightly modified version of dF(int, int) that is used to traverse the part
264 of the control graph that is not reached by normal program flow but by the
265 raising of exceptions (code of catch blocks)
267 void dF_Exception(int from, int blockIndex)
271 int high, low, count;
272 struct depthElement *hp;
274 if (c_exceptionVisit[blockIndex] < 0) /* has block been visited, return */
275 c_exceptionVisit[blockIndex] = 1;
279 if (c_dTable[blockIndex] != NULL) /* back to regular code section */
282 if (from >= 0) { /* build exception graph (in c_exceptionGraph) */
283 if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL)
286 hp->next = c_exceptionGraph[from];
287 hp->value = blockIndex;
290 c_exceptionGraph[from] = hp;
294 if (blockIndex > block_count) {
295 fprintf(stderr, "DepthFirst: BlockIndex exceeded\n");
300 ip = block[blockIndex].iinstr + block[blockIndex].icount -1;
302 if (!block[blockIndex].icount)
303 dF_Exception(blockIndex, blockIndex+1);
331 dF_Exception(blockIndex, blockIndex + 1);
335 dF_Exception(blockIndex, block_index[ip->op1]);
338 case ICMD_TABLESWITCH:
342 dF_Exception(blockIndex, block_index[*s4ptr]);
349 count = (high-low+1);
351 while (--count >= 0) {
353 dF_Exception(blockIndex, block_index[*s4ptr]);
357 case ICMD_LOOKUPSWITCH:
361 dF_Exception(blockIndex, block_index[*s4ptr]);
366 while (--count >= 0) {
367 dF_Exception(blockIndex, block_index[s4ptr[1]]);
373 c_last_jump = blockIndex;
374 dF_Exception(blockIndex, block_index[ip->op1]);
378 dF_Exception(blockIndex, c_last_jump+1);
382 dF_Exception(blockIndex, blockIndex + 1);
390 Test function -> will be removed in final release
395 struct depthElement *hp;
397 printf("\n\n****** PASS 1 ******\n\n");
398 printf("Number of Nodes: %d\n\n", c_globalCount);
400 printf("Predecessors:\n");
401 for (i=0; i<block_count; ++i) {
402 printf("Block %d:\t", i);
403 for (j=0; j<c_numPre[i]; ++j)
404 printf("%d ", c_pre[i][j]);
410 for (i=0; i<block_count; ++i) {
411 printf("Block %d:\t", i);
415 printf("%d ", hp->value);
424 * These are local overrides for various environment variables in Emacs.
425 * Please do not remove this and leave it at the end of the file, where
426 * Emacs will automagically detect them.
427 * ---------------------------------------------------------------------
430 * indent-tabs-mode: t