1 /*-
2 * %sccs.include.proprietary.c%
3 */
4
5 #ifndef lint
6 static char sccsid[] = "@(#)3.loop.c 8.1 (Berkeley) 06/06/93";
7 #endif /* not lint */
8
9 #include <stdio.h>
10 #include "def.h"
11 #include "3.def.h"
12
13 #define ARCCOUNT(v) REACH(v)
14
15
fixhd(v,hd,head)16 fixhd(v,hd,head)
17 VERT v,hd,*head;
18 {
19 VERT w,newhd;
20 int i;
21 head[v] = hd;
22 newhd = (NTYPE(v) == ITERVX) ? v : hd;
23 for (i = 0; i < CHILDNUM(v); ++i)
24 for (w = LCHILD(v,i); DEFINED(w); w = RSIB(w))
25 fixhd(w,newhd,head);
26 }
27
getloop()28 getloop()
29 {
30 cntarcs();
31 fixloop(START);
32 }
33
34
cntarcs()35 cntarcs() /* count arcs entering each node */
36 {
37 VERT w,v;
38 int i;
39 for (v = 0; v < nodenum; ++v)
40 ARCCOUNT(v) = 0;
41 for (v = 0; v < nodenum; ++v)
42 for (i = 0; i < ARCNUM(v); ++i)
43 {
44 w = ARC(v,i);
45 if (!DEFINED(w)) continue;
46 ++ARCCOUNT(w);
47 }
48 }
49
50
fixloop(v)51 fixloop(v) /* find WHILE loops */
52 VERT v;
53 {
54 int recvar;
55 if (NTYPE(v) == LOOPVX)
56 {
57 ASSERT(DEFINED(ARC(v,0)),fixloop);
58 NXT(ARC(v,0)) = ARC(v,0);
59 if (!getwh(v))
60 getun(v);
61 }
62 else if (NTYPE(v) == IFVX && arbcase)
63 getswitch(v);
64 else if (NTYPE(v)==DOVX)
65 {
66 ASSERT(DEFINED(ARC(v,0)),fixloop);
67 NXT(ARC(v,0))=ARC(v,0);
68 }
69 RECURSE(fixloop,v,recvar);
70 }
71
72
getwh(v)73 getwh(v)
74 VERT v;
75 {
76 VERT vchild, vgrand,vgreat;
77 ASSERT(NTYPE(v) == LOOPVX,getwh);
78 vchild = LCHILD(v,0);
79 ASSERT(DEFINED(vchild),getwh);
80 ASSERT(NTYPE(vchild) == ITERVX,getwh);
81 vgrand = LCHILD(vchild,0);
82 if (!DEFINED(vgrand) || !IFTHEN(vgrand) )
83 return(FALSE);
84 vgreat = LCHILD(vgrand,THEN);
85 if (DEFINED(vgreat) && NTYPE(vgreat) == GOVX && ARC(vgreat,0) == BRK(vchild))
86 {
87 /* turn into WHILE */
88 NTYPE(v) = WHIVX;
89 NEG(vgrand) = !NEG(vgrand);
90 LPRED(vchild) = vgrand;
91 LCHILD(vchild,0) = RSIB(vgrand);
92 RSIB(vgrand) = UNDEFINED;
93 return(TRUE);
94 }
95 return(FALSE);
96 }
97
98
99
getun(v)100 getun(v) /* change loop to REPEAT UNTIL if possible */
101 VERT v;
102 {
103 VERT vchild, vgrand, vgreat, before, ch;
104 ASSERT(NTYPE(v) == LOOPVX,getun);
105 vchild = LCHILD(v,0);
106 ASSERT(DEFINED(vchild), getun);
107 if (ARCCOUNT(vchild) > 2)
108 return(FALSE); /* loop can be iterated without passing through predicate of UNTIL */
109 vgrand = ARC(vchild,0);
110 if (!DEFINED(vgrand))
111 return(FALSE);
112 for (ch = vgrand,before = UNDEFINED; DEFINED(RSIB(ch)); ch = RSIB(ch))
113 before = ch;
114 if (!IFTHEN(ch))
115 return(FALSE);
116 vgreat = LCHILD(ch,THEN);
117 if (DEFINED(vgreat) && NTYPE(vgreat) == GOVX && ARC(vgreat,0) == BRK(vchild))
118 {
119 /* create UNTIL node */
120 NTYPE(v) = UNTVX;
121 NXT(vchild) = ch;
122 LPRED(vchild)=ch;
123 RSIB(before) = UNDEFINED;
124 return(TRUE);
125 }
126 return(FALSE);
127 }
128
129
130 #define FORMCASE(w) (DEFINED(w) && !DEFINED(RSIB(w)) && NTYPE(w) == IFVX && ARCCOUNT(w) == 1)
131
getswitch(v)132 getswitch(v)
133 VERT v;
134 {
135 VERT ch, grand, temp;
136 /* must be of form if ... else if ... else if ... */
137 if (NTYPE(v) != IFVX) return(FALSE);
138 ch = LCHILD(v,ELSE);
139 if (!FORMCASE(ch)) return(FALSE);
140 grand = LCHILD(ch,ELSE);
141 if (!FORMCASE(grand)) return(FALSE);
142
143 temp = create(SWCHVX,0);
144 exchange(&graph[temp],&graph[v]); /* want arcs to enter switch, not first case*/
145 BEGCOM(v) = UNDEFINED;
146 RSIB(v) = RSIB(temp); /* statements which followed IFVX should follow switch */
147 EXP(v) = UNDEFINED;
148 LCHILD(v,0) = temp;
149 NTYPE(temp) = ACASVX;
150 for (ch = LCHILD(temp,ELSE); FORMCASE(ch); )
151 {
152 LCHILD(temp,ELSE) = UNDEFINED;
153 RSIB(temp) = ch;
154 NTYPE(ch) = ACASVX;
155 temp = ch;
156 ch = LCHILD(temp,ELSE);
157 }
158 ASSERT(!DEFINED(RSIB(temp)),getswitch);
159 return(TRUE);
160 }
161