2 * Author: Humberto Naves (hsnaves@gmail.com)
9 void dfs_step (struct basicblock
*block
, int reverse
)
11 struct basicblock
*next
;
12 struct basicblocknode
*node
, *nextnode
;
17 node
= &block
->revnode
;
19 out
= block
->sub
->revdfsblocks
;
22 refs
= block
->outrefs
;
23 out
= block
->sub
->dfsblocks
;
27 el
= list_head (refs
);
29 struct basicedge
*edge
;
30 edge
= element_getvalue (el
);
33 nextnode
= &next
->revnode
;
36 nextnode
= &next
->node
;
39 if (!nextnode
->dfsnum
) {
40 nextnode
->parent
= node
;
41 list_inserttail (node
->children
, nextnode
);
42 dfs_step (next
, reverse
);
44 el
= element_next (el
);
47 node
->dfsnum
= block
->sub
->temp
--;
48 node
->blockel
= list_inserthead (out
, block
);
52 int cfg_dfs (struct subroutine
*sub
, int reverse
)
54 struct basicblock
*start
;
55 sub
->temp
= list_size (sub
->blocks
);
56 start
= reverse
? sub
->endblock
: sub
->startblock
;
58 dfs_step (start
, reverse
);
59 return (sub
->temp
== 0);
62 int dom_isancestor (struct basicblocknode
*ancestor
, struct basicblocknode
*node
)
64 return (ancestor
->domdfsnum
.first
<= node
->domdfsnum
.first
&&
65 ancestor
->domdfsnum
.last
<= node
->domdfsnum
.last
);
68 struct basicblocknode
*dom_common (struct basicblocknode
*n1
, struct basicblocknode
*n2
)
71 while (n1
->dfsnum
> n2
->dfsnum
) {
74 while (n2
->dfsnum
> n1
->dfsnum
) {
82 void dom_dfs_step (struct basicblocknode
*node
, struct intpair
*domdfsnum
)
84 struct basicblocknode
*next
;
87 node
->domdfsnum
.first
= (domdfsnum
->first
)++;
88 el
= list_head (node
->domchildren
);
90 next
= element_getvalue (el
);
91 if (!next
->domdfsnum
.first
)
92 dom_dfs_step (next
, domdfsnum
);
93 el
= element_next (el
);
95 node
->domdfsnum
.last
= (domdfsnum
->last
)--;
99 void cfg_dominance (struct subroutine
*sub
, int reverse
)
101 struct basicblock
*start
;
102 struct basicblocknode
*startnode
;
103 struct intpair domdfsnum
;
109 blocks
= sub
->revdfsblocks
;
110 start
= sub
->endblock
;
111 startnode
= start
->revnode
.dominator
= &start
->revnode
;
113 blocks
= sub
->dfsblocks
;
114 start
= sub
->startblock
;
115 startnode
= start
->node
.dominator
= &start
->node
;
120 el
= list_head (blocks
);
121 el
= element_next (el
);
123 struct basicblock
*block
;
124 struct basicblocknode
*node
, *dom
= NULL
;
127 block
= element_getvalue (el
);
128 refs
= (reverse
) ? block
->outrefs
: block
->inrefs
;
129 ref
= list_head (refs
);
131 struct basicblock
*bref
;
132 struct basicblocknode
*brefnode
;
133 struct basicedge
*edge
;
135 edge
= element_getvalue (ref
);
138 brefnode
= &bref
->revnode
;
141 brefnode
= &bref
->node
;
144 if (brefnode
->dominator
) {
148 dom
= dom_common (dom
, brefnode
);
152 ref
= element_next (ref
);
155 node
= (reverse
) ? &block
->revnode
: &block
->node
;
156 if (dom
!= node
->dominator
) {
157 node
->dominator
= dom
;
161 el
= element_next (el
);
165 el
= list_head (blocks
);
167 struct basicblock
*block
;
168 struct basicblocknode
*node
;
170 block
= element_getvalue (el
);
171 node
= (reverse
) ? &block
->revnode
: &block
->node
;
172 list_inserttail (node
->dominator
->domchildren
, node
);
174 el
= element_next (el
);
178 domdfsnum
.last
= list_size (blocks
);
179 dom_dfs_step (startnode
, &domdfsnum
);
183 void cfg_frontier (struct subroutine
*sub
, int reverse
)
185 struct basicblock
*block
;
186 struct basicblocknode
*blocknode
, *runner
;
190 el
= (reverse
) ? list_head (sub
->revdfsblocks
) : list_head (sub
->dfsblocks
);
193 block
= element_getvalue (el
);
195 refs
= block
->outrefs
;
196 blocknode
= &block
->revnode
;
198 refs
= block
->inrefs
;
199 blocknode
= &block
->node
;
201 if (list_size (refs
) >= 2) {
202 ref
= list_head (refs
);
204 struct basicedge
*edge
= element_getvalue (ref
);
205 runner
= (reverse
) ? &edge
->to
->revnode
: &edge
->from
->node
;
206 while (runner
!= blocknode
->dominator
) {
207 list_inserttail (runner
->frontier
, blocknode
);
208 runner
= runner
->dominator
;
210 ref
= element_next (ref
);
213 el
= element_next (el
);
217 void cfg_traverse (struct subroutine
*sub
, int reverse
)
220 if (!cfg_dfs (sub
, FALSE
)) {
221 error (__FILE__
": unreachable code at subroutine 0x%08X", sub
->begin
->address
);
222 sub
->haserror
= TRUE
;
226 if (!cfg_dfs (sub
, TRUE
)) {
227 error (__FILE__
": infinite loop at subroutine 0x%08X", sub
->begin
->address
);
228 sub
->haserror
= TRUE
;
233 cfg_dominance (sub
, reverse
);
234 cfg_frontier (sub
, reverse
);