xref: /inferno-os/utils/vl/pass.c (revision d3641b487cf5cdc46e9b537d30eb37736e5c7b1a)
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 	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, s->version, p->from.offset);
139 		} else {
140 			if(p->from.name != D_NONE)
141 				continue;
142 			if(p->from.reg != NREG)
143 				continue;
144 			v = p->from.offset;
145 			if(v >= -0x7fff && v <= 0xffff)
146 				continue;
147 			if(!(v & 0xffff))
148 				continue;
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->line = p->line;
159 			p1->as = ADATA;
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 		nocache(p);
175 		continue;
176 	}
177 	while(orig & 7)
178 		orig++;
179 	/*
180 	 * pass 5
181 	 *	re-adjust offsets
182 	 */
183 	for(i=0; i<NHASH; i++)
184 	for(s = hash[i]; s != S; s = s->link) {
185 		t = s->type;
186 		if(t == SBSS) {
187 			s->value += orig;
188 			continue;
189 		}
190 		if(t == SDATA1) {
191 			s->type = SDATA;
192 			s->value += orig;
193 			continue;
194 		}
195 	}
196 	datsize += orig;
197 	xdefine("setR30", SDATA, 0L+BIG);
198 	xdefine("bdata", SDATA, 0L);
199 	xdefine("edata", SDATA, datsize);
200 	xdefine("end", SBSS, datsize+bsssize);
201 	xdefine("etext", STEXT, 0L);
202 }
203 
204 void
205 undef(void)
206 {
207 	int i;
208 	Sym *s;
209 
210 	for(i=0; i<NHASH; i++)
211 	for(s = hash[i]; s != S; s = s->link)
212 		if(s->type == SXREF)
213 			diag("%s: not defined", s->name);
214 }
215 
216 void
217 follow(void)
218 {
219 	if(debug['v'])
220 		Bprint(&bso, "%5.2f follow\n", cputime());
221 	Bflush(&bso);
222 
223 	firstp = prg();
224 	lastp = firstp;
225 	xfol(textp);
226 
227 	firstp = firstp->link;
228 	lastp->link = P;
229 }
230 
231 void
232 xfol(Prog *p)
233 {
234 	Prog *q, *r;
235 	int a, i;
236 
237 loop:
238 	if(p == P)
239 		return;
240 	a = p->as;
241 	if(a == ATEXT)
242 		curtext = p;
243 	if(a == AJMP) {
244 		q = p->cond;
245 		if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
246 			p->mark |= FOLL;
247 			lastp->link = p;
248 			lastp = p;
249 			p = p->link;
250 			xfol(p);
251 			p = q;
252 			if(p && !(p->mark & FOLL))
253 				goto loop;
254 			return;
255 		}
256 		if(q != P) {
257 			p->mark |= FOLL;
258 			p = q;
259 			if(!(p->mark & FOLL))
260 				goto loop;
261 		}
262 	}
263 	if(p->mark & FOLL) {
264 		for(i=0,q=p; i<4; i++,q=q->link) {
265 			if(q == lastp || (q->mark&NOSCHED))
266 				break;
267 			a = q->as;
268 			if(a == ANOP) {
269 				i--;
270 				continue;
271 			}
272 			if(a == AJMP || a == ARET || a == ARFE)
273 				goto copy;
274 			if(!q->cond || (q->cond->mark&FOLL))
275 				continue;
276 			if(a != ABEQ && a != ABNE)
277 				continue;
278 		copy:
279 			for(;;) {
280 				r = prg();
281 				*r = *p;
282 				if(!(r->mark&FOLL))
283 					print("cant happen 1\n");
284 				r->mark |= FOLL;
285 				if(p != q) {
286 					p = p->link;
287 					lastp->link = r;
288 					lastp = r;
289 					continue;
290 				}
291 				lastp->link = r;
292 				lastp = r;
293 				if(a == AJMP || a == ARET || a == ARFE)
294 					return;
295 				r->as = ABNE;
296 				if(a == ABNE)
297 					r->as = ABEQ;
298 				r->cond = p->link;
299 				r->link = p->cond;
300 				if(!(r->link->mark&FOLL))
301 					xfol(r->link);
302 				if(!(r->cond->mark&FOLL))
303 					print("cant happen 2\n");
304 				return;
305 			}
306 		}
307 		a = AJMP;
308 		q = prg();
309 		q->as = a;
310 		q->line = p->line;
311 		q->to.type = D_BRANCH;
312 		q->to.offset = p->pc;
313 		q->cond = p;
314 		p = q;
315 	}
316 	p->mark |= FOLL;
317 	lastp->link = p;
318 	lastp = p;
319 	if(a == AJMP || a == ARET || a == ARFE){
320 		if(p->mark & NOSCHED){
321 			p = p->link;
322 			goto loop;
323 		}
324 		return;
325 	}
326 	if(p->cond != P)
327 	if(a != AJAL && p->link != P) {
328 		xfol(p->link);
329 		p = p->cond;
330 		if(p == P || (p->mark&FOLL))
331 			return;
332 		goto loop;
333 	}
334 	p = p->link;
335 	goto loop;
336 }
337 
338 void
339 patch(void)
340 {
341 	long c, vexit;
342 	Prog *p, *q;
343 	Sym *s;
344 	int a;
345 
346 	if(debug['v'])
347 		Bprint(&bso, "%5.2f patch\n", cputime());
348 	Bflush(&bso);
349 	mkfwd();
350 	s = lookup("exit", 0);
351 	vexit = s->value;
352 	for(p = firstp; p != P; p = p->link) {
353 		a = p->as;
354 		if(a == ATEXT)
355 			curtext = p;
356 		if((a == AJAL || a == AJMP || a == ARET) &&
357 		   p->to.type != D_BRANCH && p->to.sym != S) {
358 			s = p->to.sym;
359 			if(s->type != STEXT) {
360 				diag("undefined: %s\n%P", s->name, p);
361 				s->type = STEXT;
362 				s->value = vexit;
363 			}
364 			p->to.offset = s->value;
365 			p->to.type = D_BRANCH;
366 		}
367 		if(p->to.type != D_BRANCH)
368 			continue;
369 		c = p->to.offset;
370 		for(q = firstp; q != P;) {
371 			if(q->forwd != P)
372 			if(c >= q->forwd->pc) {
373 				q = q->forwd;
374 				continue;
375 			}
376 			if(c == q->pc)
377 				break;
378 			q = q->link;
379 		}
380 		if(q == P) {
381 			diag("branch out of range %ld\n%P", c, p);
382 			p->to.type = D_NONE;
383 		}
384 		p->cond = q;
385 	}
386 
387 	for(p = firstp; p != P; p = p->link) {
388 		if(p->as == ATEXT)
389 			curtext = p;
390 		if(p->cond != P) {
391 			p->cond = brloop(p->cond);
392 			if(p->cond != P)
393 			if(p->to.type == D_BRANCH)
394 				p->to.offset = p->cond->pc;
395 		}
396 	}
397 }
398 
399 #define	LOG	5
400 void
401 mkfwd(void)
402 {
403 	Prog *p;
404 	long dwn[LOG], cnt[LOG], i;
405 	Prog *lst[LOG];
406 
407 	for(i=0; i<LOG; i++) {
408 		if(i == 0)
409 			cnt[i] = 1; else
410 			cnt[i] = LOG * cnt[i-1];
411 		dwn[i] = 1;
412 		lst[i] = P;
413 	}
414 	i = 0;
415 	for(p = firstp; p != P; p = p->link) {
416 		if(p->as == ATEXT)
417 			curtext = p;
418 		i--;
419 		if(i < 0)
420 			i = LOG-1;
421 		p->forwd = P;
422 		dwn[i]--;
423 		if(dwn[i] <= 0) {
424 			dwn[i] = cnt[i];
425 			if(lst[i] != P)
426 				lst[i]->forwd = p;
427 			lst[i] = p;
428 		}
429 	}
430 }
431 
432 Prog*
433 brloop(Prog *p)
434 {
435 	Prog *q;
436 	int c;
437 
438 	for(c=0; p!=P;) {
439 		if(p->as != AJMP || (p->mark&NOSCHED))
440 			return p;
441 		q = p->cond;
442 		if(q <= p) {
443 			c++;
444 			if(q == p || c > 5000)
445 				break;
446 		}
447 		p = q;
448 	}
449 	return P;
450 }
451 
452 long
453 atolwhex(char *s)
454 {
455 	long n;
456 	int f;
457 
458 	n = 0;
459 	f = 0;
460 	while(*s == ' ' || *s == '\t')
461 		s++;
462 	if(*s == '-' || *s == '+') {
463 		if(*s++ == '-')
464 			f = 1;
465 		while(*s == ' ' || *s == '\t')
466 			s++;
467 	}
468 	if(s[0]=='0' && s[1]){
469 		if(s[1]=='x' || s[1]=='X'){
470 			s += 2;
471 			for(;;){
472 				if(*s >= '0' && *s <= '9')
473 					n = n*16 + *s++ - '0';
474 				else if(*s >= 'a' && *s <= 'f')
475 					n = n*16 + *s++ - 'a' + 10;
476 				else if(*s >= 'A' && *s <= 'F')
477 					n = n*16 + *s++ - 'A' + 10;
478 				else
479 					break;
480 			}
481 		} else
482 			while(*s >= '0' && *s <= '7')
483 				n = n*8 + *s++ - '0';
484 	} else
485 		while(*s >= '0' && *s <= '9')
486 			n = n*10 + *s++ - '0';
487 	if(f)
488 		n = -n;
489 	return n;
490 }
491 
492 long
493 rnd(long v, long r)
494 {
495 	long c;
496 
497 	if(r <= 0)
498 		return v;
499 	v += r - 1;
500 	c = v % r;
501 	if(c < 0)
502 		c += r;
503 	v -= c;
504 	return v;
505 }
506