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