1 #include "l.h"
2
3 void
dodata(void)4 dodata(void)
5 {
6 int i, t;
7 Sym *s;
8 Prog *p;
9 long orig, v;
10
11 if(debug['v'])
12 Bprint(&bso, "%5.2f dodata\n", cputime());
13 Bflush(&bso);
14 for(p = datap; p != P; p = p->link) {
15 s = p->from.sym;
16 if(p->as == ADYNT || p->as == AINIT)
17 s->value = dtype;
18 if(s->type == SBSS)
19 s->type = SDATA;
20 if(s->type != SDATA)
21 diag("initialize non-data (%d): %s\n%P",
22 s->type, s->name, p);
23 v = p->from.offset + p->reg;
24 if(v > s->value)
25 diag("initialize bounds (%lld): %s\n%P",
26 (vlong)s->value, s->name, p);
27 }
28
29 if(debug['t']) {
30 /*
31 * pull out string constants
32 */
33 for(p = datap; p != P; p = p->link) {
34 s = p->from.sym;
35 if(p->to.type == D_SCONST)
36 s->type = SSTRING;
37 }
38 }
39
40 /*
41 * pass 1
42 * assign 'small' variables to data segment
43 * (rationale is that data segment is more easily
44 * addressed through offset on REGSB)
45 */
46 orig = 0;
47 for(i=0; i<NHASH; i++)
48 for(s = hash[i]; s != S; s = s->link) {
49 t = s->type;
50 if(t != SDATA && t != SBSS)
51 continue;
52 v = s->value;
53 if(v == 0) {
54 diag("%s: no size", s->name);
55 v = 1;
56 }
57 v = rnd(v, 4);
58 s->value = v;
59 if(v > MINSIZ)
60 continue;
61 if(v >= 16)
62 orig = rnd(orig, 16);
63 else if(v >= 8)
64 orig = rnd(orig, 8);
65 s->value = orig;
66 orig += v;
67 s->type = SDATA1;
68 }
69
70 /*
71 * pass 2
72 * assign large 'data' variables to data segment
73 */
74 for(i=0; i<NHASH; i++)
75 for(s = hash[i]; s != S; s = s->link) {
76 t = s->type;
77 if(t != SDATA) {
78 if(t == SDATA1)
79 s->type = SDATA;
80 continue;
81 }
82 v = s->value;
83 if(v >= 16)
84 orig = rnd(orig, 16);
85 else if(v >= 8)
86 orig = rnd(orig, 8);
87 s->value = orig;
88 orig += v;
89 }
90
91 while(orig & 7)
92 orig++;
93 datsize = orig;
94
95 /*
96 * pass 3
97 * everything else to bss segment
98 */
99 for(i=0; i<NHASH; i++)
100 for(s = hash[i]; s != S; s = s->link) {
101 if(s->type != SBSS)
102 continue;
103 v = s->value;
104 if(v >= 16)
105 orig = rnd(orig, 16);
106 else if(v >= 8)
107 orig = rnd(orig, 8);
108 s->value = orig;
109 orig += v;
110 }
111 while(orig & 7)
112 orig++;
113 bsssize = orig-datsize;
114
115 xdefine("setSB", SDATA, 0L);
116 xdefine("bdata", SDATA, 0L);
117 xdefine("edata", SDATA, datsize);
118 xdefine("end", SBSS, datsize+bsssize);
119 xdefine("etext", STEXT, 0L);
120 }
121
122 Prog*
brchain(Prog * p)123 brchain(Prog *p)
124 {
125 int i;
126
127 for(i=0; i<20; i++) {
128 if(p == P || !isbranch(p->as))
129 return p;
130 p = p->cond;
131 }
132 return P;
133 }
134
135 void
follow(void)136 follow(void)
137 {
138 if(debug['v'])
139 Bprint(&bso, "%5.2f follow\n", cputime());
140 Bflush(&bso);
141
142 firstp = prg();
143 lastp = firstp;
144 xfol(textp);
145
146 firstp = firstp->link;
147 lastp->link = P;
148 }
149
150 void
xfol(Prog * p)151 xfol(Prog *p)
152 {
153 Prog *q, *r;
154 int a, i;
155
156 loop:
157 if(p == P)
158 return;
159 a = p->as;
160 if(a == ATEXT)
161 curtext = p;
162 if(isbranch(a)) {
163 q = p->cond;
164 if(q != P) {
165 p->mark |= FOLL;
166 p = q;
167 if(!(p->mark & FOLL))
168 goto loop;
169 }
170 }
171 if(p->mark & FOLL) {
172 for(i=0,q=p; i<4; i++,q=q->link) {
173 if(q == lastp)
174 break;
175 a = q->as;
176 if(a == ANOP) {
177 i--;
178 continue;
179 }
180 if(isbranch(a) || isreturn(a))
181 goto copy;
182 if(q->cond == nil || (q->cond->mark&FOLL))
183 continue;
184 if(a != ABEQ && a != ABNE)
185 continue;
186 copy:
187 for(;;) {
188 r = prg();
189 *r = *p;
190 if(!(r->mark&FOLL))
191 print("cant happen 1\n");
192 r->mark |= FOLL;
193 if(p != q) {
194 p = p->link;
195 lastp->link = r;
196 lastp = r;
197 continue;
198 }
199 lastp->link = r;
200 lastp = r;
201 if(isbranch(a) || isreturn(a))
202 return;
203 r->as = a == ABNE? ABEQ: ABNE;
204 r->cond = p->link;
205 r->link = p->cond;
206 if(!(r->link->mark&FOLL))
207 xfol(r->link);
208 if(!(r->cond->mark&FOLL))
209 print("cant happen 2\n");
210 return;
211 }
212 }
213 a = branchop();
214 q = prg();
215 q->as = a;
216 q->line = p->line;
217 q->to.type = D_BRANCH;
218 q->to.offset = p->pc;
219 q->cond = p;
220 p = q;
221 }
222 p->mark |= FOLL;
223 lastp->link = p;
224 lastp = p;
225 if(isbranch(a) || isreturn(a))
226 return;
227 if(p->cond != P)
228 if(!iscall(a) && p->link != P) {
229 q = brchain(p->link);
230 if(canfollow(a))
231 if(q != P && (q->mark&FOLL)) {
232 p->as = relinv(a);
233 p->link = p->cond;
234 p->cond = q;
235 }
236 xfol(p->link);
237 q = brchain(p->cond);
238 if(q == P)
239 q = p->cond;
240 if(q->mark&FOLL) {
241 p->cond = q;
242 return;
243 }
244 p = q;
245 goto loop;
246 }
247 p = p->link;
248 goto loop;
249 }
250
251 void
patch(void)252 patch(void)
253 {
254 long c, vexit;
255 Prog *p, *q;
256 Sym *s;
257 int a;
258
259 if(debug['v'])
260 Bprint(&bso, "%5.2f patch\n", cputime());
261 Bflush(&bso);
262 mkfwd();
263 s = lookup("exit", 0);
264 vexit = s->value;
265 for(p = firstp; p != P; p = p->link) {
266 a = p->as;
267 if(a == ATEXT)
268 curtext = p;
269 if((iscall(a) || isbranch(a) || isreturn(a)) &&
270 p->to.type != D_BRANCH && p->to.sym != S) {
271 s = p->to.sym;
272 switch(s->type) {
273 default:
274 diag("undefined: %s\n%P", s->name, p);
275 s->type = STEXT;
276 s->value = vexit;
277 break;
278 case STEXT:
279 p->to.offset = s->value;
280 break;
281 case SUNDEF:
282 if(!iscall(p->as))
283 diag("help: SUNDEF in AB || ARET");
284 p->to.offset = 0;
285 p->cond = UP;
286 break;
287 }
288 p->to.type = D_BRANCH;
289 }
290 if(p->cond == UP)
291 continue;
292 if(p->to.type == D_BRANCH)
293 c = p->to.offset;
294 else if(p->from.type == D_BRANCH)
295 c = p->from.offset;
296 else
297 continue;
298 for(q = firstp; q != P;) {
299 if(q->forwd != P)
300 if(c >= q->forwd->pc) {
301 q = q->forwd;
302 continue;
303 }
304 if(c == q->pc)
305 break;
306 q = q->link;
307 }
308 if(q == P) {
309 diag("branch out of range %ld\n%P", c, p);
310 p->to.type = D_NONE;
311 }
312 p->cond = q;
313 }
314
315 for(p = firstp; p != P; p = p->link) {
316 if(p->as == ATEXT)
317 curtext = p;
318 if(p->cond != P && p->cond != UP) {
319 p->cond = brloop(p->cond);
320 if(p->cond != P){
321 if(p->to.type == D_BRANCH)
322 p->to.offset = p->cond->pc;
323 if(p->from.type == D_BRANCH)
324 p->from.offset = p->cond->pc;
325 }
326 }
327 }
328 }
329
330 #define LOG 6
331 void
mkfwd(void)332 mkfwd(void)
333 {
334 Prog *p;
335 long dwn[LOG], cnt[LOG], i;
336 Prog *lst[LOG];
337
338 for(i=0; i<LOG; i++) {
339 if(i == 0)
340 cnt[i] = 1; else
341 cnt[i] = LOG * cnt[i-1];
342 dwn[i] = 1;
343 lst[i] = P;
344 }
345 i = 0;
346 for(p = firstp; p != P; p = p->link) {
347 if(p->as == ATEXT)
348 curtext = p;
349 i--;
350 if(i < 0)
351 i = LOG-1;
352 p->forwd = P;
353 dwn[i]--;
354 if(dwn[i] <= 0) {
355 dwn[i] = cnt[i];
356 if(lst[i] != P)
357 lst[i]->forwd = p;
358 lst[i] = p;
359 }
360 }
361 }
362
363 Prog*
brloop(Prog * p)364 brloop(Prog *p)
365 {
366 Prog *q;
367 int c;
368
369 for(c=0; p!=P;) {
370 if(!isbranch(p->as))
371 return p;
372 q = p->cond;
373 if(q <= p) {
374 c++;
375 if(q == p || c > 5000)
376 break;
377 }
378 p = q;
379 }
380 return P;
381 }
382