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