7 void mark_backward (struct subroutine
*sub
, struct basicblock
*start
,
8 struct basicblock
*block
, int num
, int *count
)
14 el
= block
->node
.blockel
;
15 while (el
&& remaining
) {
16 struct basicblock
*block
= element_getvalue (el
);
17 if (block
== start
) break;
18 if (block
->mark1
== num
) {
20 ref
= list_head (block
->inrefs
);
22 struct basicedge
*edge
= element_getvalue (ref
);
23 struct basicblock
*next
= edge
->from
;
24 ref
= element_next (ref
);
26 if (next
->node
.dfsnum
>= block
->node
.dfsnum
)
27 if (!dom_isancestor (&block
->node
, &next
->node
) ||
28 !dom_isancestor (&block
->revnode
, &next
->revnode
))
30 if (next
->mark1
!= num
) {
38 el
= element_previous (el
);
43 void mark_forward (struct subroutine
*sub
, struct basicblock
*start
,
44 struct ctrlstruct
*loop
, int num
, int count
)
48 el
= start
->node
.blockel
;
50 struct basicblock
*block
= element_getvalue (el
);
51 if (block
->mark1
== num
) {
52 block
->loopst
= loop
; count
--;
53 ref
= list_head (block
->outrefs
);
55 struct basicedge
*edge
= element_getvalue (ref
);
56 struct basicblock
*next
= edge
->to
;
57 if (next
->mark1
!= num
) {
58 edge
->type
= EDGE_GOTO
;
59 next
->haslabel
= TRUE
;
60 if (!loop
->end
) loop
->end
= next
;
61 if (list_size (loop
->end
->inrefs
) < list_size (next
->inrefs
))
64 ref
= element_next (ref
);
68 el
= element_next (el
);
74 void mark_loop (struct subroutine
*sub
, struct ctrlstruct
*loop
)
77 int num
= ++sub
->temp
;
80 el
= list_head (loop
->info
.loopctrl
.edges
);
82 struct basicedge
*edge
= element_getvalue (el
);
83 struct basicblock
*block
= edge
->from
;
85 if (block
->mark1
!= num
) {
86 mark_backward (sub
, loop
->start
, block
, num
, &count
);
88 el
= element_next (el
);
91 mark_forward (sub
, loop
->start
, loop
, num
, count
);
94 loop
->end
->haslabel
= FALSE
;
95 el
= list_head (loop
->end
->inrefs
);
97 struct basicedge
*edge
= element_getvalue (el
);
98 struct basicblock
*block
= edge
->from
;
99 if (block
->loopst
== loop
) 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 ctrlstruct
*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
) {
129 loop
= fixedpool_alloc (sub
->code
->ctrlspool
);
131 loop
->type
= CONTROL_LOOP
;
132 loop
->info
.loopctrl
.edges
= list_alloc (sub
->code
->lstpool
);
134 list_inserttail (loop
->info
.loopctrl
.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_branches (struct subroutine
*sub
)
150 struct basicblock
*block
;
151 struct ctrlstruct
*st
;
155 unresolvedifs
= 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
)
168 st
= fixedpool_alloc (sub
->code
->ctrlspool
);
169 st
->type
= CONTROL_SWITCH
;
172 } else if (list_size (block
->outrefs
) == 2) {
173 struct basicedge
*edge1
, *edge2
;
175 st
= fixedpool_alloc (sub
->code
->ctrlspool
);
176 st
->type
= CONTROL_IF
;
179 edge1
= list_headvalue (block
->outrefs
);
180 edge2
= list_tailvalue (block
->outrefs
);
181 if (edge1
->type
== EDGE_UNKNOWN
&& edge2
->type
== EDGE_UNKNOWN
) {
184 list_inserthead (unresolvedifs
, block
);
185 domel
= list_head (block
->node
.domchildren
);
187 struct basicblocknode
*dom
= element_getvalue (domel
);
188 struct basicblock
*domblock
= element_getvalue (dom
->blockel
);
190 if (list_size (domblock
->inrefs
) > 1) {
191 block
->st
->info
.ifctrl
.isoutermost
= TRUE
;
192 while (list_size (unresolvedifs
) != 0) {
193 struct basicblock
*ifblock
= list_removehead (unresolvedifs
);
194 ifblock
->st
->end
= domblock
;
198 domel
= element_next (domel
);
200 } else if (edge1
->type
== EDGE_UNKNOWN
|| edge2
->type
== EDGE_UNKNOWN
) {
201 if (edge1
->type
== EDGE_UNKNOWN
) {
202 edge1
->type
= EDGE_IFEXIT
;
205 edge2
->type
= EDGE_IFEXIT
;
212 el
= element_previous (el
);
215 list_free (unresolvedifs
);
219 void structure_search (struct basicblock
*block
, int identsize
, struct ctrlstruct
*ifst
)
221 struct basicedge
*edge
;
222 struct basicblock
*ifend
= NULL
;
230 ifend
= block
->st
->end
;
235 if (block
->loopst
->start
== block
) {
237 if (block
->loopst
->end
) {
238 if (!block
->loopst
->end
->mark1
)
239 structure_search (block
->loopst
->end
, identsize
- 1, ifst
);
241 block
->loopst
->end
->haslabel
= TRUE
;
242 block
->loopst
->hasendgoto
= TRUE
;
249 if (block
->st
->end
&& block
->st
->info
.ifctrl
.isoutermost
) {
250 if (!block
->st
->end
->mark1
)
251 structure_search (block
->st
->end
, identsize
, ifst
);
253 block
->st
->end
->haslabel
= TRUE
;
254 block
->st
->hasendgoto
= TRUE
;
259 block
->identsize
= identsize
;
261 ref
= list_head (block
->outrefs
);
263 edge
= element_getvalue (ref
);
264 if (edge
->type
== EDGE_UNKNOWN
) {
265 if (edge
->to
->loopst
!= block
->loopst
) {
266 if (edge
->to
->loopst
) {
267 if (edge
->to
->loopst
->start
!= edge
->to
) {
268 edge
->type
= EDGE_GOTO
;
269 edge
->to
->haslabel
= TRUE
;
272 edge
->type
= EDGE_GOTO
;
273 edge
->to
->haslabel
= TRUE
;
278 if (edge
->type
== EDGE_UNKNOWN
) {
279 if (edge
->to
== ifend
) {
280 edge
->type
= EDGE_IFEXIT
;
282 if (edge
->to
->mark1
) {
283 edge
->type
= EDGE_GOTO
;
284 edge
->to
->haslabel
= TRUE
;
286 edge
->type
= EDGE_FOLLOW
;
288 structure_search (edge
->to
, identsize
+ 1, block
->st
);
290 structure_search (edge
->to
, identsize
, ifst
);
295 ref
= element_next (ref
);
299 void reset_marks (struct subroutine
*sub
)
301 element el
= list_head (sub
->blocks
);
303 struct basicblock
*block
= element_getvalue (el
);
304 block
->mark1
= block
->mark2
= 0;
305 el
= element_next (el
);
309 void extract_structures (struct subroutine
*sub
)
316 extract_branches (sub
);
319 el
= list_head (sub
->blocks
);
321 struct basicblock
*block
= element_getvalue (el
);
323 structure_search (block
, 0, NULL
);
324 el
= element_next (el
);