6 void dfs_step (struct basicblock
*block
, int reverse
)
8 struct basicblock
*next
;
9 struct basicblocknode
*node
, *nextnode
;
14 node
= &block
->revnode
;
16 out
= block
->sub
->revdfsblocks
;
19 refs
= block
->outrefs
;
20 out
= block
->sub
->dfsblocks
;
24 el
= list_head (refs
);
26 struct basicedge
*edge
;
27 edge
= element_getvalue (el
);
30 nextnode
= &next
->revnode
;
33 nextnode
= &next
->node
;
36 if (!nextnode
->dfsnum
) {
37 nextnode
->parent
= node
;
38 list_inserttail (node
->children
, nextnode
);
39 dfs_step (next
, reverse
);
41 el
= element_next (el
);
44 node
->dfsnum
= block
->sub
->temp
--;
45 node
->blockel
= list_inserthead (out
, block
);
49 int cfg_dfs (struct subroutine
*sub
, int reverse
)
51 struct basicblock
*start
;
52 sub
->temp
= list_size (sub
->blocks
);
53 start
= reverse
? sub
->endblock
: sub
->startblock
;
55 dfs_step (start
, reverse
);
56 return (sub
->temp
== 0);
59 int dom_isancestor (struct basicblocknode
*ancestor
, struct basicblocknode
*node
)
61 return (ancestor
->domdfsnum
.first
<= node
->domdfsnum
.first
&&
62 ancestor
->domdfsnum
.last
<= node
->domdfsnum
.last
);
65 struct basicblocknode
*dom_common (struct basicblocknode
*n1
, struct basicblocknode
*n2
)
68 while (n1
->dfsnum
> n2
->dfsnum
) {
71 while (n2
->dfsnum
> n1
->dfsnum
) {
79 void dom_dfs_step (struct basicblocknode
*node
, struct intpair
*domdfsnum
)
81 struct basicblocknode
*next
;
84 node
->domdfsnum
.first
= (domdfsnum
->first
)++;
85 el
= list_head (node
->domchildren
);
87 next
= element_getvalue (el
);
88 if (!next
->domdfsnum
.first
)
89 dom_dfs_step (next
, domdfsnum
);
90 el
= element_next (el
);
92 node
->domdfsnum
.last
= (domdfsnum
->last
)--;
96 void cfg_dominance (struct subroutine
*sub
, int reverse
)
98 struct basicblock
*start
;
99 struct basicblocknode
*startnode
;
100 struct intpair domdfsnum
;
106 blocks
= sub
->revdfsblocks
;
107 start
= sub
->endblock
;
108 startnode
= start
->revnode
.dominator
= &start
->revnode
;
110 blocks
= sub
->dfsblocks
;
111 start
= sub
->startblock
;
112 startnode
= start
->node
.dominator
= &start
->node
;
117 el
= list_head (blocks
);
118 el
= element_next (el
);
120 struct basicblock
*block
;
121 struct basicblocknode
*node
, *dom
= NULL
;
124 block
= element_getvalue (el
);
125 refs
= (reverse
) ? block
->outrefs
: block
->inrefs
;
126 ref
= list_head (refs
);
128 struct basicblock
*bref
;
129 struct basicblocknode
*brefnode
;
130 struct basicedge
*edge
;
132 edge
= element_getvalue (ref
);
135 brefnode
= &bref
->revnode
;
138 brefnode
= &bref
->node
;
141 if (brefnode
->dominator
) {
145 dom
= dom_common (dom
, brefnode
);
149 ref
= element_next (ref
);
152 node
= (reverse
) ? &block
->revnode
: &block
->node
;
153 if (dom
!= node
->dominator
) {
154 node
->dominator
= dom
;
158 el
= element_next (el
);
162 el
= list_head (blocks
);
164 struct basicblock
*block
;
165 struct basicblocknode
*node
;
167 block
= element_getvalue (el
);
168 node
= (reverse
) ? &block
->revnode
: &block
->node
;
169 list_inserttail (node
->dominator
->domchildren
, node
);
171 el
= element_next (el
);
175 domdfsnum
.last
= list_size (blocks
);
176 dom_dfs_step (startnode
, &domdfsnum
);
180 void cfg_frontier (struct subroutine
*sub
, int reverse
)
182 struct basicblock
*block
;
183 struct basicblocknode
*blocknode
, *runner
;
187 el
= (reverse
) ? list_head (sub
->revdfsblocks
) : list_head (sub
->dfsblocks
);
190 block
= element_getvalue (el
);
192 refs
= block
->outrefs
;
193 blocknode
= &block
->revnode
;
195 refs
= block
->inrefs
;
196 blocknode
= &block
->node
;
198 if (list_size (refs
) >= 2) {
199 ref
= list_head (refs
);
201 struct basicedge
*edge
= element_getvalue (ref
);
202 runner
= (reverse
) ? &edge
->to
->revnode
: &edge
->from
->node
;
203 while (runner
!= blocknode
->dominator
) {
204 list_inserttail (runner
->frontier
, blocknode
);
205 runner
= runner
->dominator
;
207 ref
= element_next (ref
);
210 el
= element_next (el
);
214 void cfg_traverse (struct subroutine
*sub
, int reverse
)
217 if (!cfg_dfs (sub
, FALSE
)) {
218 error (__FILE__
": unreachable code at subroutine 0x%08X", sub
->begin
->address
);
219 sub
->haserror
= TRUE
;
223 if (!cfg_dfs (sub
, TRUE
)) {
224 error (__FILE__
": infinite loop at subroutine 0x%08X", sub
->begin
->address
);
225 sub
->haserror
= TRUE
;
230 cfg_dominance (sub
, reverse
);
231 cfg_frontier (sub
, reverse
);