xref: /plan9-contrib/sys/src/cmd/ql/pass.c (revision a6a9e07217f318acf170f99684a55fba5200524f)
1 #include	"l.h"
2 
3 void
4 dodata(void)
5 {
6 	int i, t;
7 	Sym *s;
8 	Prog *p, *p1;
9 	long orig, orig1, 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 (%ld): %s\n%P",
26 				s->value, s->name, p);
27 	}
28 
29 	/*
30 	 * pass 1
31 	 *	assign 'small' variables to data segment
32 	 *	(rational is that data segment is more easily
33 	 *	 addressed through offset on REGSB)
34 	 */
35 	orig = 0;
36 	for(i=0; i<NHASH; i++)
37 	for(s = hash[i]; s != S; s = s->link) {
38 		t = s->type;
39 		if(t != SDATA && t != SBSS)
40 			continue;
41 		v = s->value;
42 		if(v == 0) {
43 			diag("%s: no size", s->name);
44 			v = 1;
45 		}
46 		while(v & 3)
47 			v++;
48 		s->value = v;
49 		if(v > MINSIZ)
50 			continue;
51 		if(v >= 8)
52 			while(orig & 7)
53 				orig++;
54 		s->value = orig;
55 		orig += v;
56 		s->type = SDATA1;
57 	}
58 	orig1 = orig;
59 
60 	/*
61 	 * pass 2
62 	 *	assign 'data' variables to data segment
63 	 */
64 	for(i=0; i<NHASH; i++)
65 	for(s = hash[i]; s != S; s = s->link) {
66 		t = s->type;
67 		if(t != SDATA) {
68 			if(t == SDATA1)
69 				s->type = SDATA;
70 			continue;
71 		}
72 		v = s->value;
73 		if(v >= 8)
74 			while(orig & 7)
75 				orig++;
76 		s->value = orig;
77 		orig += v;
78 		s->type = SDATA1;
79 	}
80 
81 	while(orig & 7)
82 		orig++;
83 	datsize = orig;
84 
85 	/*
86 	 * pass 3
87 	 *	everything else to bss segment
88 	 */
89 	for(i=0; i<NHASH; i++)
90 	for(s = hash[i]; s != S; s = s->link) {
91 		if(s->type != SBSS)
92 			continue;
93 		v = s->value;
94 		if(v >= 8)
95 			while(orig & 7)
96 				orig++;
97 		s->value = orig;
98 		orig += v;
99 	}
100 	while(orig & 7)
101 		orig++;
102 	bsssize = orig-datsize;
103 
104 	/*
105 	 * pass 4
106 	 *	add literals to all large values.
107 	 *	at this time:
108 	 *		small data is allocated DATA
109 	 *		large data is allocated DATA1
110 	 *		large bss is allocated BSS
111 	 *	the new literals are loaded between
112 	 *	small data and large data.
113 	 */
114 	orig = 0;
115 	for(p = firstp; p != P; p = p->link) {
116 		if(p->as != AMOVW)
117 			continue;
118 		if(p->from.type != D_CONST)
119 			continue;
120 		if(s = p->from.sym) {
121 			t = s->type;
122 			if(t != SDATA && t != SDATA1 && t != SBSS)
123 				continue;
124 			t = p->from.name;
125 			if(t != D_EXTERN && t != D_STATIC)
126 				continue;
127 			v = s->value + p->from.offset;
128 			if(v >= 0 && v <= 0xffff)
129 				continue;
130 			if(!strcmp(s->name, "setSB"))
131 				continue;
132 			/* size should be 19 max */
133 			if(strlen(s->name) >= 10)	/* has loader address */
134 				sprint(literal, "$%lux.%lux", (long)s, p->from.offset);
135 			else
136 				sprint(literal, "$%s.%d.%lux", s->name, s->version, p->from.offset);
137 		} else {
138 			if(p->from.name != D_NONE)
139 				continue;
140 			if(p->from.reg != NREG)
141 				continue;
142 			v = p->from.offset;
143 			if(v >= -0x7fff-1 && v <= 0x7fff)
144 				continue;
145 			if(!(v & 0xffff))
146 				continue;
147 			if(v)
148 				continue;	/* quicker to build it than load it */
149 			/* size should be 9 max */
150 			sprint(literal, "$%lux", v);
151 		}
152 		s = lookup(literal, 0);
153 		if(s->type == 0) {
154 			s->type = SDATA;
155 			s->value = orig1+orig;
156 			orig += 4;
157 			p1 = prg();
158 			p1->as = ADATA;
159 			p1->line = p->line;
160 			p1->from.type = D_OREG;
161 			p1->from.sym = s;
162 			p1->from.name = D_EXTERN;
163 			p1->reg = 4;
164 			p1->to = p->from;
165 			p1->link = datap;
166 			datap = p1;
167 		}
168 		if(s->type != SDATA)
169 			diag("literal not data: %s", s->name);
170 		p->from.type = D_OREG;
171 		p->from.sym = s;
172 		p->from.name = D_EXTERN;
173 		p->from.offset = 0;
174 		continue;
175 	}
176 	while(orig & 7)
177 		orig++;
178 	/*
179 	 * pass 5
180 	 *	re-adjust offsets
181 	 */
182 	for(i=0; i<NHASH; i++)
183 	for(s = hash[i]; s != S; s = s->link) {
184 		t = s->type;
185 		if(t == SBSS) {
186 			s->value += orig;
187 			continue;
188 		}
189 		if(t == SDATA1) {
190 			s->type = SDATA;
191 			s->value += orig;
192 			continue;
193 		}
194 	}
195 	datsize += orig;
196 	xdefine("setSB", SDATA, 0L+BIG);
197 	xdefine("bdata", SDATA, 0L);
198 	xdefine("edata", SDATA, datsize);
199 	xdefine("end", SBSS, datsize+bsssize);
200 	xdefine("etext", STEXT, 0L);
201 }
202 
203 void
204 undef(void)
205 {
206 	int i;
207 	Sym *s;
208 
209 	for(i=0; i<NHASH; i++)
210 	for(s = hash[i]; s != S; s = s->link)
211 		if(s->type == SXREF)
212 			diag("%s: not defined", s->name);
213 }
214 
215 int
216 relinv(int a)
217 {
218 
219 	switch(a) {
220 	case ABEQ:	return ABNE;
221 	case ABNE:	return ABEQ;
222 
223 	case ABGE:	return ABLT;
224 	case ABLT:	return ABGE;
225 
226 	case ABGT:	return ABLE;
227 	case ABLE:	return ABGT;
228 
229 	case ABVC:	return ABVS;
230 	case ABVS:	return ABVC;
231 	}
232 	return 0;
233 }
234 
235 void
236 follow(void)
237 {
238 
239 	if(debug['v'])
240 		Bprint(&bso, "%5.2f follow\n", cputime());
241 	Bflush(&bso);
242 
243 	firstp = prg();
244 	lastp = firstp;
245 
246 	xfol(textp);
247 
248 	firstp = firstp->link;
249 	lastp->link = P;
250 }
251 
252 void
253 xfol(Prog *p)
254 {
255 	Prog *q, *r;
256 	int a, b, i;
257 
258 loop:
259 	if(p == P)
260 		return;
261 	a = p->as;
262 	if(a == ATEXT)
263 		curtext = p;
264 	if(a == ABR) {
265 		q = p->cond;
266 		if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
267 			p->mark |= FOLL;
268 			lastp->link = p;
269 			lastp = p;
270 			p = p->link;
271 			xfol(p);
272 			p = q;
273 			if(p && !(p->mark & FOLL))
274 				goto loop;
275 			return;
276 		}
277 		if(q != P) {
278 			p->mark |= FOLL;
279 			p = q;
280 			if(!(p->mark & FOLL))
281 				goto loop;
282 		}
283 	}
284 	if(p->mark & FOLL) {
285 		for(i=0,q=p; i<4; i++,q=q->link) {
286 			if(q == lastp || (q->mark&NOSCHED))
287 				break;
288 			b = 0;		/* set */
289 			a = q->as;
290 			if(a == ANOP) {
291 				i--;
292 				continue;
293 			}
294 			if(a == ABR || a == ARETURN || a == ARFI)
295 				goto copy;
296 			if(!q->cond || (q->cond->mark&FOLL))
297 				continue;
298 			b = relinv(a);
299 			if(!b)
300 				continue;
301 		copy:
302 			for(;;) {
303 				r = prg();
304 				*r = *p;
305 				if(!(r->mark&FOLL))
306 					print("cant happen 1\n");
307 				r->mark |= FOLL;
308 				if(p != q) {
309 					p = p->link;
310 					lastp->link = r;
311 					lastp = r;
312 					continue;
313 				}
314 				lastp->link = r;
315 				lastp = r;
316 				if(a == ABR || a == ARETURN || a == ARFI)
317 					return;
318 				r->as = b;
319 				r->cond = p->link;
320 				r->link = p->cond;
321 				if(!(r->link->mark&FOLL))
322 					xfol(r->link);
323 				if(!(r->cond->mark&FOLL))
324 					print("cant happen 2\n");
325 				return;
326 			}
327 		}
328 
329 		a = ABR;
330 		q = prg();
331 		q->as = a;
332 		q->line = p->line;
333 		q->to.type = D_BRANCH;
334 		q->to.offset = p->pc;
335 		q->cond = p;
336 		p = q;
337 	}
338 	p->mark |= FOLL;
339 	lastp->link = p;
340 	lastp = p;
341 	if(a == ABR || a == ARETURN || a == ARFI){
342 		if(p->mark & NOSCHED){
343 			p = p->link;
344 			goto loop;
345 		}
346 		return;
347 	}
348 	if(p->cond != P)
349 	if(a != ABL && p->link != P) {
350 		xfol(p->link);
351 		p = p->cond;
352 		if(p == P || (p->mark&FOLL))
353 			return;
354 		goto loop;
355 	}
356 	p = p->link;
357 	goto loop;
358 }
359 
360 void
361 patch(void)
362 {
363 	long c, vexit;
364 	Prog *p, *q;
365 	Sym *s;
366 	int a;
367 
368 	if(debug['v'])
369 		Bprint(&bso, "%5.2f patch\n", cputime());
370 	Bflush(&bso);
371 	mkfwd();
372 	s = lookup("exit", 0);
373 	vexit = s->value;
374 	for(p = firstp; p != P; p = p->link) {
375 		a = p->as;
376 		if(a == ATEXT)
377 			curtext = p;
378 		if((a == ABL || a == ARETURN) && p->to.sym != S) {
379 			s = p->to.sym;
380 			if(s->type != STEXT) {
381 				diag("undefined: %s\n%P", s->name, p);
382 				s->type = STEXT;
383 				s->value = vexit;
384 			}
385 			p->to.offset = s->value;
386 			p->to.type = D_BRANCH;
387 		}
388 		if(p->to.type != D_BRANCH)
389 			continue;
390 		c = p->to.offset;
391 		for(q = firstp; q != P;) {
392 			if(q->forwd != P)
393 			if(c >= q->forwd->pc) {
394 				q = q->forwd;
395 				continue;
396 			}
397 			if(c == q->pc)
398 				break;
399 			q = q->link;
400 		}
401 		if(q == P) {
402 			diag("branch out of range %ld\n%P", c, p);
403 			p->to.type = D_NONE;
404 		}
405 		p->cond = q;
406 	}
407 
408 	for(p = firstp; p != P; p = p->link) {
409 		if(p->as == ATEXT)
410 			curtext = p;
411 		if(p->cond != P) {
412 			p->cond = brloop(p->cond);
413 			if(p->cond != P)
414 			if(p->to.type == D_BRANCH)
415 				p->to.offset = p->cond->pc;
416 		}
417 	}
418 }
419 
420 #define	LOG	5
421 void
422 mkfwd(void)
423 {
424 	Prog *p;
425 	long dwn[LOG], cnt[LOG], i;
426 	Prog *lst[LOG];
427 
428 	for(i=0; i<LOG; i++) {
429 		if(i == 0)
430 			cnt[i] = 1; else
431 			cnt[i] = LOG * cnt[i-1];
432 		dwn[i] = 1;
433 		lst[i] = P;
434 	}
435 	i = 0;
436 	for(p = firstp; p != P; p = p->link) {
437 		if(p->as == ATEXT)
438 			curtext = p;
439 		i--;
440 		if(i < 0)
441 			i = LOG-1;
442 		p->forwd = P;
443 		dwn[i]--;
444 		if(dwn[i] <= 0) {
445 			dwn[i] = cnt[i];
446 			if(lst[i] != P)
447 				lst[i]->forwd = p;
448 			lst[i] = p;
449 		}
450 	}
451 }
452 
453 Prog*
454 brloop(Prog *p)
455 {
456 	Prog *q;
457 	int c;
458 
459 	for(c=0; p!=P;) {
460 		if(p->as != ABR || (p->mark&NOSCHED))
461 			return p;
462 		q = p->cond;
463 		if(q <= p) {
464 			c++;
465 			if(q == p || c > 5000)
466 				break;
467 		}
468 		p = q;
469 	}
470 	return P;
471 }
472 
473 long
474 atolwhex(char *s)
475 {
476 	long n;
477 	int f;
478 
479 	n = 0;
480 	f = 0;
481 	while(*s == ' ' || *s == '\t')
482 		s++;
483 	if(*s == '-' || *s == '+') {
484 		if(*s++ == '-')
485 			f = 1;
486 		while(*s == ' ' || *s == '\t')
487 			s++;
488 	}
489 	if(s[0]=='0' && s[1]){
490 		if(s[1]=='x' || s[1]=='X'){
491 			s += 2;
492 			for(;;){
493 				if(*s >= '0' && *s <= '9')
494 					n = n*16 + *s++ - '0';
495 				else if(*s >= 'a' && *s <= 'f')
496 					n = n*16 + *s++ - 'a' + 10;
497 				else if(*s >= 'A' && *s <= 'F')
498 					n = n*16 + *s++ - 'A' + 10;
499 				else
500 					break;
501 			}
502 		} else
503 			while(*s >= '0' && *s <= '7')
504 				n = n*8 + *s++ - '0';
505 	} else
506 		while(*s >= '0' && *s <= '9')
507 			n = n*10 + *s++ - '0';
508 	if(f)
509 		n = -n;
510 	return n;
511 }
512 
513 long
514 rnd(long v, long r)
515 {
516 	long c;
517 
518 	if(r <= 0)
519 		return v;
520 	v += r - 1;
521 	c = v % r;
522 	if(c < 0)
523 		c += r;
524 	v -= c;
525 	return v;
526 }
527