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