xref: /plan9-contrib/sys/src/cmd/5l/pass.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
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\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 	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\n", 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\n", 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\n", 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 			if(s->type != STEXT) {
302 				diag("undefined: %s\n%P\n", s->name, p);
303 				s->type = STEXT;
304 				s->value = vexit;
305 			}
306 			p->to.offset = s->value;
307 			p->to.type = D_BRANCH;
308 		}
309 		if(p->to.type != D_BRANCH)
310 			continue;
311 		c = p->to.offset;
312 		if(reloc && p->as == ABL && c == -1) {
313 			p->cond = UP;
314 			continue;
315 		}
316 		for(q = firstp; q != P;) {
317 			if(q->forwd != P)
318 			if(c >= q->forwd->pc) {
319 				q = q->forwd;
320 				continue;
321 			}
322 			if(c == q->pc)
323 				break;
324 			q = q->link;
325 		}
326 		if(q == P) {
327 			diag("branch out of range %ld\n%P\n", c, p);
328 			p->to.type = D_NONE;
329 		}
330 		p->cond = q;
331 	}
332 
333 	for(p = firstp; p != P; p = p->link) {
334 		if(p->as == ATEXT)
335 			curtext = p;
336 		if(p->cond != P && p->cond != UP) {
337 			p->cond = brloop(p->cond);
338 			if(p->cond != P)
339 			if(p->to.type == D_BRANCH)
340 				p->to.offset = p->cond->pc;
341 		}
342 	}
343 }
344 
345 #define	LOG	5
346 void
347 mkfwd(void)
348 {
349 	Prog *p;
350 	long dwn[LOG], cnt[LOG], i;
351 	Prog *lst[LOG];
352 
353 	for(i=0; i<LOG; i++) {
354 		if(i == 0)
355 			cnt[i] = 1; else
356 			cnt[i] = LOG * cnt[i-1];
357 		dwn[i] = 1;
358 		lst[i] = P;
359 	}
360 	i = 0;
361 	for(p = firstp; p != P; p = p->link) {
362 		if(p->as == ATEXT)
363 			curtext = p;
364 		i--;
365 		if(i < 0)
366 			i = LOG-1;
367 		p->forwd = P;
368 		dwn[i]--;
369 		if(dwn[i] <= 0) {
370 			dwn[i] = cnt[i];
371 			if(lst[i] != P)
372 				lst[i]->forwd = p;
373 			lst[i] = p;
374 		}
375 	}
376 }
377 
378 Prog*
379 brloop(Prog *p)
380 {
381 	Prog *q;
382 	int c;
383 
384 	for(c=0; p!=P;) {
385 		if(p->as != AB)
386 			return p;
387 		q = p->cond;
388 		if(q <= p) {
389 			c++;
390 			if(q == p || c > 5000)
391 				break;
392 		}
393 		p = q;
394 	}
395 	return P;
396 }
397 
398 long
399 atolwhex(char *s)
400 {
401 	long n;
402 	int f;
403 
404 	n = 0;
405 	f = 0;
406 	while(*s == ' ' || *s == '\t')
407 		s++;
408 	if(*s == '-' || *s == '+') {
409 		if(*s++ == '-')
410 			f = 1;
411 		while(*s == ' ' || *s == '\t')
412 			s++;
413 	}
414 	if(s[0]=='0' && s[1]){
415 		if(s[1]=='x' || s[1]=='X'){
416 			s += 2;
417 			for(;;){
418 				if(*s >= '0' && *s <= '9')
419 					n = n*16 + *s++ - '0';
420 				else if(*s >= 'a' && *s <= 'f')
421 					n = n*16 + *s++ - 'a' + 10;
422 				else if(*s >= 'A' && *s <= 'F')
423 					n = n*16 + *s++ - 'A' + 10;
424 				else
425 					break;
426 			}
427 		} else
428 			while(*s >= '0' && *s <= '7')
429 				n = n*8 + *s++ - '0';
430 	} else
431 		while(*s >= '0' && *s <= '9')
432 			n = n*10 + *s++ - '0';
433 	if(f)
434 		n = -n;
435 	return n;
436 }
437 
438 long
439 rnd(long v, long r)
440 {
441 	long c;
442 
443 	if(r <= 0)
444 		return v;
445 	v += r - 1;
446 	c = v % r;
447 	if(c < 0)
448 		c += r;
449 	v -= c;
450 	return v;
451 }
452