xref: /inferno-os/utils/5l/pass.c (revision 06155dbb53eb0585800b239acd6e45b946c6e0cf)
1 #include	"l.h"
2 
3 void
4 dodata(void)
5 {
6 	int i, t;
7 	Sym *s;
8 	Prog *p;
9 	long orig, 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 R12)
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 
67 	/*
68 	 * pass 2
69 	 *	assign large 'data' variables to data segment
70 	 */
71 	for(i=0; i<NHASH; i++)
72 	for(s = hash[i]; s != S; s = s->link) {
73 		t = s->type;
74 		if(t != SDATA) {
75 			if(t == SDATA1)
76 				s->type = SDATA;
77 			continue;
78 		}
79 		v = s->value;
80 		s->value = orig;
81 		orig += v;
82 	}
83 
84 	while(orig & 7)
85 		orig++;
86 	datsize = orig;
87 
88 	/*
89 	 * pass 3
90 	 *	everything else to bss segment
91 	 */
92 	for(i=0; i<NHASH; i++)
93 	for(s = hash[i]; s != S; s = s->link) {
94 		if(s->type != SBSS)
95 			continue;
96 		v = s->value;
97 		s->value = orig;
98 		orig += v;
99 	}
100 	while(orig & 7)
101 		orig++;
102 	bsssize = orig-datsize;
103 
104 	xdefine("setR12", SDATA, 0L+BIG);
105 	xdefine("bdata", SDATA, 0L);
106 	xdefine("edata", SDATA, datsize);
107 	xdefine("end", SBSS, datsize+bsssize);
108 	xdefine("etext", STEXT, 0L);
109 }
110 
111 void
112 undef(void)
113 {
114 	int i;
115 	Sym *s;
116 
117 	for(i=0; i<NHASH; i++)
118 	for(s = hash[i]; s != S; s = s->link)
119 		if(s->type == SXREF)
120 			diag("%s: not defined", s->name);
121 }
122 
123 Prog*
124 brchain(Prog *p)
125 {
126 	int i;
127 
128 	for(i=0; i<20; i++) {
129 		if(p == P || p->as != AB)
130 			return p;
131 		p = p->cond;
132 	}
133 	return P;
134 }
135 
136 int
137 relinv(int a)
138 {
139 	switch(a) {
140 	case ABEQ:	return ABNE;
141 	case ABNE:	return ABEQ;
142 	case ABCS:	return ABCC;
143 	case ABHS:	return ABLO;
144 	case ABCC:	return ABCS;
145 	case ABLO:	return ABHS;
146 	case ABMI:	return ABPL;
147 	case ABPL:	return ABMI;
148 	case ABVS:	return ABVC;
149 	case ABVC:	return ABVS;
150 	case ABHI:	return ABLS;
151 	case ABLS:	return ABHI;
152 	case ABGE:	return ABLT;
153 	case ABLT:	return ABGE;
154 	case ABGT:	return ABLE;
155 	case ABLE:	return ABGT;
156 	}
157 	diag("unknown relation: %s", anames[a]);
158 	return a;
159 }
160 
161 void
162 follow(void)
163 {
164 	if(debug['v'])
165 		Bprint(&bso, "%5.2f follow\n", cputime());
166 	Bflush(&bso);
167 
168 	firstp = prg();
169 	lastp = firstp;
170 	xfol(textp);
171 
172 	firstp = firstp->link;
173 	lastp->link = P;
174 }
175 
176 void
177 xfol(Prog *p)
178 {
179 	Prog *q, *r;
180 	int a, i;
181 
182 loop:
183 	if(p == P)
184 		return;
185 	a = p->as;
186 	if(a == ATEXT)
187 		curtext = p;
188 	if(a == AB) {
189 		q = p->cond;
190 		if(q != P) {
191 			p->mark |= FOLL;
192 			p = q;
193 			if(!(p->mark & FOLL))
194 				goto loop;
195 		}
196 	}
197 	if(p->mark & FOLL) {
198 		for(i=0,q=p; i<4; i++,q=q->link) {
199 			if(q == lastp)
200 				break;
201 			a = q->as;
202 			if(a == ANOP) {
203 				i--;
204 				continue;
205 			}
206 			if(a == AB || (a == ARET && q->scond == 14) || a == ARFE)
207 				goto copy;
208 			if(!q->cond || (q->cond->mark&FOLL))
209 				continue;
210 			if(a != ABEQ && a != ABNE)
211 				continue;
212 		copy:
213 			for(;;) {
214 				r = prg();
215 				*r = *p;
216 				if(!(r->mark&FOLL))
217 					print("cant happen 1\n");
218 				r->mark |= FOLL;
219 				if(p != q) {
220 					p = p->link;
221 					lastp->link = r;
222 					lastp = r;
223 					continue;
224 				}
225 				lastp->link = r;
226 				lastp = r;
227 				if(a == AB || (a == ARET && q->scond == 14) || a == ARFE)
228 					return;
229 				r->as = ABNE;
230 				if(a == ABNE)
231 					r->as = ABEQ;
232 				r->cond = p->link;
233 				r->link = p->cond;
234 				if(!(r->link->mark&FOLL))
235 					xfol(r->link);
236 				if(!(r->cond->mark&FOLL))
237 					print("cant happen 2\n");
238 				return;
239 			}
240 		}
241 		a = AB;
242 		q = prg();
243 		q->as = a;
244 		q->line = p->line;
245 		q->to.type = D_BRANCH;
246 		q->to.offset = p->pc;
247 		q->cond = p;
248 		p = q;
249 	}
250 	p->mark |= FOLL;
251 	lastp->link = p;
252 	lastp = p;
253 	if(a == AB || (a == ARET && p->scond == 14) || a == ARFE){
254 		return;
255 	}
256 	if(p->cond != P)
257 	if(a != ABL && p->link != P) {
258 		q = brchain(p->link);
259 		if(a != ATEXT && a != ABCASE)
260 		if(q != P && (q->mark&FOLL)) {
261 			p->as = relinv(a);
262 			p->link = p->cond;
263 			p->cond = q;
264 		}
265 		xfol(p->link);
266 		q = brchain(p->cond);
267 		if(q == P)
268 			q = p->cond;
269 		if(q->mark&FOLL) {
270 			p->cond = q;
271 			return;
272 		}
273 		p = q;
274 		goto loop;
275 	}
276 	p = p->link;
277 	goto loop;
278 }
279 
280 void
281 patch(void)
282 {
283 	long c, vexit;
284 	Prog *p, *q;
285 	Sym *s;
286 	int a;
287 
288 	if(debug['v'])
289 		Bprint(&bso, "%5.2f patch\n", cputime());
290 	Bflush(&bso);
291 	mkfwd();
292 	s = lookup("exit", 0);
293 	vexit = s->value;
294 	for(p = firstp; p != P; p = p->link) {
295 		a = p->as;
296 		if(a == ATEXT)
297 			curtext = p;
298 		if((a == ABL || a == AB || a == ARET) &&
299 		   p->to.type != D_BRANCH && p->to.sym != S) {
300 			s = p->to.sym;
301 			switch(s->type) {
302 			default:
303 				diag("undefined: %s\n%P", s->name, p);
304 				s->type = STEXT;
305 				s->value = vexit;
306 				break;
307 			case STEXT:
308 				p->to.offset = s->value;
309 				p->to.type = D_BRANCH;
310 				break;
311 			case SUNDEF:
312 				if(p->as != ABL)
313 					diag("help: SUNDEF in AB || ARET");
314 				p->to.offset = 0;
315 				p->to.type = D_BRANCH;
316 				p->cond = UP;
317 				break;
318 			}
319 		}
320 		if(p->to.type != D_BRANCH || p->cond == UP)
321 			continue;
322 		c = p->to.offset;
323 		for(q = firstp; q != P;) {
324 			if(q->forwd != P)
325 			if(c >= q->forwd->pc) {
326 				q = q->forwd;
327 				continue;
328 			}
329 			if(c == q->pc)
330 				break;
331 			q = q->link;
332 		}
333 		if(q == P) {
334 			diag("branch out of range %ld\n%P", c, p);
335 			p->to.type = D_NONE;
336 		}
337 		p->cond = q;
338 	}
339 
340 	for(p = firstp; p != P; p = p->link) {
341 		if(p->as == ATEXT)
342 			curtext = p;
343 		if(p->cond != P && p->cond != UP) {
344 			p->cond = brloop(p->cond);
345 			if(p->cond != P)
346 			if(p->to.type == D_BRANCH)
347 				p->to.offset = p->cond->pc;
348 		}
349 	}
350 }
351 
352 #define	LOG	5
353 void
354 mkfwd(void)
355 {
356 	Prog *p;
357 	long dwn[LOG], cnt[LOG], i;
358 	Prog *lst[LOG];
359 
360 	for(i=0; i<LOG; i++) {
361 		if(i == 0)
362 			cnt[i] = 1; else
363 			cnt[i] = LOG * cnt[i-1];
364 		dwn[i] = 1;
365 		lst[i] = P;
366 	}
367 	i = 0;
368 	for(p = firstp; p != P; p = p->link) {
369 		if(p->as == ATEXT)
370 			curtext = p;
371 		i--;
372 		if(i < 0)
373 			i = LOG-1;
374 		p->forwd = P;
375 		dwn[i]--;
376 		if(dwn[i] <= 0) {
377 			dwn[i] = cnt[i];
378 			if(lst[i] != P)
379 				lst[i]->forwd = p;
380 			lst[i] = p;
381 		}
382 	}
383 }
384 
385 Prog*
386 brloop(Prog *p)
387 {
388 	Prog *q;
389 	int c;
390 
391 	for(c=0; p!=P;) {
392 		if(p->as != AB)
393 			return p;
394 		q = p->cond;
395 		if(q <= p) {
396 			c++;
397 			if(q == p || c > 5000)
398 				break;
399 		}
400 		p = q;
401 	}
402 	return P;
403 }
404 
405 long
406 atolwhex(char *s)
407 {
408 	long n;
409 	int f;
410 
411 	n = 0;
412 	f = 0;
413 	while(*s == ' ' || *s == '\t')
414 		s++;
415 	if(*s == '-' || *s == '+') {
416 		if(*s++ == '-')
417 			f = 1;
418 		while(*s == ' ' || *s == '\t')
419 			s++;
420 	}
421 	if(s[0]=='0' && s[1]){
422 		if(s[1]=='x' || s[1]=='X'){
423 			s += 2;
424 			for(;;){
425 				if(*s >= '0' && *s <= '9')
426 					n = n*16 + *s++ - '0';
427 				else if(*s >= 'a' && *s <= 'f')
428 					n = n*16 + *s++ - 'a' + 10;
429 				else if(*s >= 'A' && *s <= 'F')
430 					n = n*16 + *s++ - 'A' + 10;
431 				else
432 					break;
433 			}
434 		} else
435 			while(*s >= '0' && *s <= '7')
436 				n = n*8 + *s++ - '0';
437 	} else
438 		while(*s >= '0' && *s <= '9')
439 			n = n*10 + *s++ - '0';
440 	if(f)
441 		n = -n;
442 	return n;
443 }
444 
445 long
446 rnd(long v, long r)
447 {
448 	long c;
449 
450 	if(r <= 0)
451 		return v;
452 	v += r - 1;
453 	c = v % r;
454 	if(c < 0)
455 		c += r;
456 	v -= c;
457 	return v;
458 }
459 
460 void
461 import(void)
462 {
463 	int i;
464 	Sym *s;
465 
466 	for(i = 0; i < NHASH; i++)
467 		for(s = hash[i]; s != S; s = s->link)
468 			if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
469 				undefsym(s);
470 				Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->name, s->sig, s->value);
471 			}
472 }
473 
474 void
475 ckoff(Sym *s, long v)
476 {
477 	if(v < 0 || v >= 1<<Roffset)
478 		diag("relocation offset %ld for %s out of range", v, s->name);
479 }
480 
481 static Prog*
482 newdata(Sym *s, int o, int w, int t)
483 {
484 	Prog *p;
485 
486 	p = prg();
487 	p->link = datap;
488 	datap = p;
489 	p->as = ADATA;
490 	p->reg = w;
491 	p->from.type = D_OREG;
492 	p->from.name = t;
493 	p->from.sym = s;
494 	p->from.offset = o;
495 	p->to.type = D_CONST;
496 	p->to.name = D_NONE;
497 	return p;
498 }
499 
500 void
501 export(void)
502 {
503 	int i, j, n, off, nb, sv, ne;
504 	Sym *s, *et, *str, **esyms;
505 	Prog *p;
506 	char buf[NSNAME], *t;
507 
508 	n = 0;
509 	for(i = 0; i < NHASH; i++)
510 		for(s = hash[i]; s != S; s = s->link)
511 			if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
512 				n++;
513 	esyms = malloc(n*sizeof(Sym*));
514 	ne = n;
515 	n = 0;
516 	for(i = 0; i < NHASH; i++)
517 		for(s = hash[i]; s != S; s = s->link)
518 			if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
519 				esyms[n++] = s;
520 	for(i = 0; i < ne-1; i++)
521 		for(j = i+1; j < ne; j++)
522 			if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
523 				s = esyms[i];
524 				esyms[i] = esyms[j];
525 				esyms[j] = s;
526 			}
527 
528 	nb = 0;
529 	off = 0;
530 	et = lookup(EXPTAB, 0);
531 	if(et->type != 0 && et->type != SXREF)
532 		diag("%s already defined", EXPTAB);
533 	et->type = SDATA;
534 	str = lookup(".string", 0);
535 	if(str->type == 0)
536 		str->type = SDATA;
537 	sv = str->value;
538 	for(i = 0; i < ne; i++){
539 		s = esyms[i];
540 		Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type);
541 
542 		/* signature */
543 		p = newdata(et, off, sizeof(long), D_EXTERN);
544 		off += sizeof(long);
545 		p->to.offset = s->sig;
546 
547 		/* address */
548 		p = newdata(et, off, sizeof(long), D_EXTERN);
549 		off += sizeof(long);
550 		p->to.name = D_EXTERN;
551 		p->to.sym = s;
552 
553 		/* string */
554 		t = s->name;
555 		n = strlen(t)+1;
556 		for(;;){
557 			buf[nb++] = *t;
558 			sv++;
559 			if(nb >= NSNAME){
560 				p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
561 				p->to.type = D_SCONST;
562 				p->to.sval = malloc(NSNAME);
563 				memmove(p->to.sval, buf, NSNAME);
564 				nb = 0;
565 			}
566 			if(*t++ == 0)
567 				break;
568 		}
569 
570 		/* name */
571 		p = newdata(et, off, sizeof(long), D_EXTERN);
572 		off += sizeof(long);
573 		p->to.name = D_STATIC;
574 		p->to.sym = str;
575 		p->to.offset = sv-n;
576 	}
577 
578 	if(nb > 0){
579 		p = newdata(str, sv-nb, nb, D_STATIC);
580 		p->to.type = D_SCONST;
581 		p->to.sval = malloc(NSNAME);
582 		memmove(p->to.sval, buf, nb);
583 	}
584 
585 	for(i = 0; i < 3; i++){
586 		newdata(et, off, sizeof(long), D_EXTERN);
587 		off += sizeof(long);
588 	}
589 	et->value = off;
590 	if(sv == 0)
591 		sv = 1;
592 	str->value = sv;
593 	exports = ne;
594 	free(esyms);
595 }
596