7 void mark_backward (struct subroutine
*sub
, struct basicblock
*block
, int num
, int end
)
12 el
= block
->node
.blockel
;
14 struct basicblock
*block
= element_getvalue (el
);
15 if (block
->node
.dfsnum
< end
) break;
16 if (block
->mark1
== num
) {
18 ref
= list_head (block
->inrefs
);
20 struct basicedge
*edge
= element_getvalue (ref
);
21 struct basicblock
*next
= edge
->from
;
22 if (next
->node
.dfsnum
>= end
&&
23 next
->node
.dfsnum
< block
->node
.dfsnum
) {
24 if (next
->mark1
!= num
) count
++;
27 ref
= element_next (ref
);
31 el
= element_previous (el
);
36 void mark_forward (struct subroutine
*sub
, struct basicblock
*block
,
37 struct loopstructure
*loop
, int num
, int end
)
41 el
= block
->node
.blockel
;
43 struct basicblock
*block
= element_getvalue (el
);
44 if (block
->node
.dfsnum
> end
) break;
45 if (block
->mark2
== num
) {
47 ref
= list_head (block
->outrefs
);
49 struct basicedge
*edge
= element_getvalue (ref
);
50 struct basicblock
*next
= edge
->to
;
51 if (next
->node
.dfsnum
> block
->node
.dfsnum
) {
52 if (next
->mark1
== num
) next
->mark2
= num
;
54 if (!loop
->end
) loop
->end
= next
;
55 if (list_size (loop
->end
->inrefs
) < list_size (next
->inrefs
))
59 ref
= element_next (ref
);
63 el
= element_next (el
);
69 void mark_loop (struct subroutine
*sub
, struct loopstructure
*loop
)
72 int num
= ++sub
->temp
;
75 el
= list_head (loop
->edges
);
77 struct basicedge
*edge
= element_getvalue (el
);
78 struct basicblock
*block
= edge
->from
;
80 if (maxdfs
< block
->node
.dfsnum
)
81 maxdfs
= block
->node
.dfsnum
;
83 if (block
->mark1
!= num
) {
85 mark_backward (sub
, block
, num
, loop
->start
->node
.dfsnum
);
87 el
= element_next (el
);
90 loop
->start
->mark2
= num
;
91 mark_forward (sub
, loop
->start
, loop
, num
, maxdfs
);
94 el
= list_head (loop
->end
->inrefs
);
96 struct basicedge
*edge
= element_getvalue (el
);
97 struct basicblock
*block
= edge
->from
;
98 if (block
->loopst
== loop
)
99 edge
->type
= EDGE_BREAK
;
100 el
= element_next (el
);
106 void extract_loops (struct subroutine
*sub
)
108 struct basicblock
*block
;
109 struct basicedge
*edge
;
110 struct loopstructure
*loop
;
113 el
= list_head (sub
->dfsblocks
);
115 block
= element_getvalue (el
);
118 ref
= list_head (block
->inrefs
);
120 edge
= element_getvalue (ref
);
121 if (edge
->from
->node
.dfsnum
>= block
->node
.dfsnum
) {
122 edge
->type
= EDGE_CONTINUE
;
123 if (!dom_isancestor (&block
->node
, &edge
->from
->node
)) {
124 error (__FILE__
": graph of sub 0x%08X is not reducible (using goto)", sub
->begin
->address
);
125 edge
->type
= EDGE_GOTO
;
126 edge
->to
->haslabel
= TRUE
;
127 } else if (block
->loopst
== edge
->from
->loopst
||
128 dom_isancestor (&block
->revnode
, &edge
->from
->revnode
)) {
130 loop
= fixedpool_alloc (sub
->code
->loopspool
);
132 loop
->edges
= list_alloc (sub
->code
->lstpool
);
134 list_inserttail (loop
->edges
, edge
);
136 edge
->type
= EDGE_GOTO
;
137 edge
->to
->haslabel
= TRUE
;
140 ref
= element_next (ref
);
142 if (loop
) mark_loop (sub
, loop
);
143 el
= element_next (el
);
148 void extract_ifs (struct subroutine
*sub
)
150 struct basicblock
*block
;
151 struct ifstructure
*ifst
;
155 unresolved
= list_alloc (sub
->code
->lstpool
);
157 el
= list_tail (sub
->dfsblocks
);
159 int hasswitch
= FALSE
;
160 block
= element_getvalue (el
);
162 if (block
->type
== BLOCK_SIMPLE
) {
163 if (block
->info
.simple
.jumploc
) {
164 if (block
->info
.simple
.jumploc
->cswitch
)
169 if (list_size (block
->outrefs
) == 2 && !hasswitch
) {
170 struct basicedge
*edge1
, *edge2
;
172 ifst
= fixedpool_alloc (sub
->code
->ifspool
);
175 edge1
= list_headvalue (block
->outrefs
);
176 edge2
= list_tailvalue (block
->outrefs
);
177 if (edge1
->type
== EDGE_UNKNOWN
|| edge2
->type
== EDGE_UNKNOWN
) {
180 list_inserthead (unresolved
, block
);
181 domel
= list_head (block
->node
.domchildren
);
184 struct basicblocknode
*dom
= element_getvalue (domel
);
185 struct basicblock
*domblock
= element_getvalue (dom
->blockel
);
188 ref
= list_head (domblock
->inrefs
);
190 struct basicedge
*edge
= element_getvalue (ref
);
191 if (edge
->from
->node
.dfsnum
< domblock
->node
.dfsnum
)
193 ref
= element_next (ref
);
197 block
->ifst
->outermost
= TRUE
;
198 while (list_size (unresolved
) != 0) {
199 struct basicblock
*ifblock
= list_removehead (unresolved
);
200 ifblock
->ifst
->end
= domblock
;
204 domel
= element_next (domel
);
209 el
= element_previous (el
);
212 list_free (unresolved
);
216 void structure_search (struct basicblock
*block
, int identsize
, struct ifstructure
*ifst
)
218 struct basicedge
*edge
;
219 struct basicblock
*ifend
= NULL
;
226 if (block
->ifst
->end
)
227 ifend
= block
->ifst
->end
;
232 if (block
->loopst
->start
== block
) {
234 if (block
->loopst
->end
) {
235 if (!block
->loopst
->end
->mark1
)
236 structure_search (block
->loopst
->end
, identsize
- 1, ifst
);
238 block
->loopst
->end
->haslabel
= TRUE
;
239 block
->loopst
->hasendgoto
= TRUE
;
246 if (block
->ifst
->end
&& block
->ifst
->outermost
) {
247 if (!block
->ifst
->end
->mark1
)
248 structure_search (block
->ifst
->end
, identsize
, ifst
);
250 block
->ifst
->end
->haslabel
= TRUE
;
251 block
->ifst
->hasendgoto
= TRUE
;
256 block
->identsize
= identsize
;
258 ref
= list_head (block
->outrefs
);
260 edge
= element_getvalue (ref
);
261 if (edge
->type
== EDGE_UNKNOWN
) {
262 if (edge
->to
->loopst
!= block
->loopst
) {
263 if (edge
->to
->loopst
) {
264 if (edge
->to
->loopst
->start
!= edge
->to
) {
265 edge
->type
= EDGE_GOTO
;
266 edge
->to
->haslabel
= TRUE
;
269 edge
->type
= EDGE_GOTO
;
270 edge
->to
->haslabel
= TRUE
;
275 if (edge
->type
== EDGE_UNKNOWN
) {
276 if (edge
->to
== ifend
) {
277 edge
->type
= EDGE_IFEXIT
;
279 if (edge
->to
->mark1
) {
280 edge
->type
= EDGE_GOTO
;
281 edge
->to
->haslabel
= TRUE
;
283 edge
->type
= EDGE_FOLLOW
;
285 structure_search (edge
->to
, identsize
+ 1, block
->ifst
);
287 structure_search (edge
->to
, identsize
, ifst
);
292 ref
= element_next (ref
);
296 void reset_marks (struct subroutine
*sub
)
298 element el
= list_head (sub
->blocks
);
300 struct basicblock
*block
= element_getvalue (el
);
301 block
->mark1
= block
->mark2
= 0;
302 el
= element_next (el
);
306 void extract_structures (struct subroutine
*sub
)
316 el
= list_head (sub
->blocks
);
318 struct basicblock
*block
= element_getvalue (el
);
320 structure_search (block
, 0, NULL
);
321 el
= element_next (el
);