Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"l.h"
2
 
3
void
4
dodata(void)
5
{
6
	int i;
7
	Sym *s;
8
	Prog *p;
9
	long t, u;
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
		t = p->from.offset + p->width;
24
		if(t > s->value)
25
			diag("initialize bounds (%ld): %s\n%P",
26
				s->value, s->name, p);
27
	}
28
	/* allocate small guys */
29
	datsize = 0;
30
	for(i=0; i<NHASH; i++)
31
	for(s = hash[i]; s != S; s = s->link) {
32
		if(s->type != SDATA)
33
		if(s->type != SBSS)
34
			continue;
35
		t = s->value;
36
		if(t == 0) {
37
			diag("%s: no size", s->name);
38
			t = 1;
39
		}
40
		t = rnd(t, 4);;
41
		s->value = t;
42
		if(t > MINSIZ)
43
			continue;
44
		s->value = datsize;
45
		datsize += t;
46
		s->type = SDATA1;
47
	}
48
 
49
	/* allocate the rest of the data */
50
	for(i=0; i<NHASH; i++)
51
	for(s = hash[i]; s != S; s = s->link) {
52
		if(s->type != SDATA) {
53
			if(s->type == SDATA1)
54
				s->type = SDATA;
55
			continue;
56
		}
57
		t = s->value;
58
		s->value = datsize;
59
		datsize += t;
60
	}
61
 
62
	if(debug['j']) {
63
		/*
64
		 * pad data with bss that fits up to next
65
		 * 8k boundary, then push data to 8k
66
		 */
67
		u = rnd(datsize, 8192);
68
		u -= datsize;
69
		for(i=0; i<NHASH; i++)
70
		for(s = hash[i]; s != S; s = s->link) {
71
			if(s->type != SBSS)
72
				continue;
73
			t = s->value;
74
			if(t > u)
75
				continue;
76
			u -= t;
77
			s->value = datsize;
78
			s->type = SDATA;
79
			datsize += t;
80
		}
81
		datsize += u;
82
	}
83
 
84
	/* now the bss */
85
	bsssize = 0;
86
	for(i=0; i<NHASH; i++)
87
	for(s = hash[i]; s != S; s = s->link) {
88
		if(s->type != SBSS)
89
			continue;
90
		t = s->value;
91
		s->value = bsssize + datsize;
92
		bsssize += t;
93
	}
94
	xdefine("bdata", SDATA, 0L);
95
	xdefine("edata", SBSS, datsize);
96
	xdefine("end", SBSS, bsssize + datsize);
97
	/* etext is defined in span.c */
98
}
99
 
100
Prog*
101
brchain(Prog *p)
102
{
103
	int i;
104
 
105
	for(i=0; i<20; i++) {
106
		if(p == P || p->as != AJMP)
107
			return p;
108
		p = p->pcond;
109
	}
110
	return P;
111
}
112
 
113
void
114
follow(void)
115
{
116
 
117
	if(debug['v'])
118
		Bprint(&bso, "%5.2f follow\n", cputime());
119
	Bflush(&bso);
120
	firstp = prg();
121
	lastp = firstp;
122
	xfol(textp);
123
	lastp->link = P;
124
	firstp = firstp->link;
125
}
126
 
127
void
128
xfol(Prog *p)
129
{
130
	Prog *q;
131
	int i;
132
	enum as a;
133
 
134
loop:
135
	if(p == P)
136
		return;
137
	if(p->as == ATEXT)
138
		curtext = p;
139
	if(p->as == AJMP)
140
	if((q = p->pcond) != P) {
141
		p->mark = 1;
142
		p = q;
143
		if(p->mark == 0)
144
			goto loop;
145
	}
146
	if(p->mark) {
147
		/* copy up to 4 instructions to avoid branch */
148
		for(i=0,q=p; i<4; i++,q=q->link) {
149
			if(q == P)
150
				break;
151
			if(q == lastp)
152
				break;
153
			a = q->as;
154
			if(a == ANOP) {
155
				i--;
156
				continue;
157
			}
158
			switch(a) {
159
			case AJMP:
160
			case ARET:
161
			case AIRETL:
162
 
163
			case APUSHL:
164
			case APUSHFL:
165
			case APUSHW:
166
			case APUSHFW:
167
			case APOPL:
168
			case APOPFL:
169
			case APOPW:
170
			case APOPFW:
171
				goto brk;
172
			}
173
			if(q->pcond == P || q->pcond->mark)
174
				continue;
175
			if(a == ACALL || a == ALOOP)
176
				continue;
177
			for(;;) {
178
				if(p->as == ANOP) {
179
					p = p->link;
180
					continue;
181
				}
182
				q = copyp(p);
183
				p = p->link;
184
				q->mark = 1;
185
				lastp->link = q;
186
				lastp = q;
187
				if(q->as != a || q->pcond == P || q->pcond->mark)
188
					continue;
189
 
190
				q->as = relinv(q->as);
191
				p = q->pcond;
192
				q->pcond = q->link;
193
				q->link = p;
194
				xfol(q->link);
195
				p = q->link;
196
				if(p->mark)
197
					return;
198
				goto loop;
199
			}
200
		} /* */
201
	brk:;
202
		q = prg();
203
		q->as = AJMP;
204
		q->line = p->line;
205
		q->to.type = D_BRANCH;
206
		q->to.offset = p->pc;
207
		q->pcond = p;
208
		p = q;
209
	}
210
	p->mark = 1;
211
	lastp->link = p;
212
	lastp = p;
213
	a = p->as;
214
	if(a == AJMP || a == ARET || a == AIRETL)
215
		return;
216
	if(p->pcond != P)
217
	if(a != ACALL) {
218
		q = brchain(p->link);
219
		if(q != P && q->mark)
220
		if(a != ALOOP) {
221
			p->as = relinv(a);
222
			p->link = p->pcond;
223
			p->pcond = q;
224
		}
225
		xfol(p->link);
226
		q = brchain(p->pcond);
227
		if(q->mark) {
228
			p->pcond = q;
229
			return;
230
		}
231
		p = q;
232
		goto loop;
233
	}
234
	p = p->link;
235
	goto loop;
236
}
237
 
238
int
239
relinv(int a)
240
{
241
 
242
	switch(a) {
243
	case AJEQ:	return AJNE;
244
	case AJNE:	return AJEQ;
245
	case AJLE:	return AJGT;
246
	case AJLS:	return AJHI;
247
	case AJLT:	return AJGE;
248
	case AJMI:	return AJPL;
249
	case AJGE:	return AJLT;
250
	case AJPL:	return AJMI;
251
	case AJGT:	return AJLE;
252
	case AJHI:	return AJLS;
253
	case AJCS:	return AJCC;
254
	case AJCC:	return AJCS;
255
	case AJPS:	return AJPC;
256
	case AJPC:	return AJPS;
257
	case AJOS:	return AJOC;
258
	case AJOC:	return AJOS;
259
	}
260
	diag("unknown relation: %s in %s", anames[a], TNAME);
261
	return a;
262
}
263
 
264
void
265
doinit(void)
266
{
267
	Sym *s;
268
	Prog *p;
269
	int x;
270
 
271
	for(p = datap; p != P; p = p->link) {
272
		x = p->to.type;
273
		if(x != D_EXTERN && x != D_STATIC)
274
			continue;
275
		s = p->to.sym;
276
		if(s->type == 0 || s->type == SXREF)
277
			diag("undefined %s initializer of %s",
278
				s->name, p->from.sym->name);
279
		p->to.offset += s->value;
280
		p->to.type = D_CONST;
281
		if(s->type == SDATA || s->type == SBSS)
282
			p->to.offset += INITDAT;
283
	}
284
}
285
 
286
void
287
patch(void)
288
{
289
	long c;
290
	Prog *p, *q;
291
	Sym *s;
292
	long vexit;
293
 
294
	if(debug['v'])
295
		Bprint(&bso, "%5.2f mkfwd\n", cputime());
296
	Bflush(&bso);
297
	mkfwd();
298
	if(debug['v'])
299
		Bprint(&bso, "%5.2f patch\n", cputime());
300
	Bflush(&bso);
301
	s = lookup("exit", 0);
302
	vexit = s->value;
303
	for(p = firstp; p != P; p = p->link) {
304
		if(p->as == ATEXT)
305
			curtext = p;
306
		if(p->as == ACALL || p->as == ARET) {
307
			s = p->to.sym;
308
			if(s) {
309
				if(debug['c'])
310
					Bprint(&bso, "%s calls %s\n", TNAME, s->name);
311
				switch(s->type) {
312
				default:
313
					/* diag prints TNAME first */
314
					diag("undefined: %s", s->name);
315
					s->type = STEXT;
316
					s->value = vexit;
317
					break;	/* or fall through to set offset? */
318
				case STEXT:
319
					p->to.offset = s->value;
320
					break;
321
				case SUNDEF:
322
					p->pcond = UP;
323
					p->to.offset = 0;
324
					break;
325
				}
326
				p->to.type = D_BRANCH;
327
			}
328
		}
329
		if(p->to.type != D_BRANCH || p->pcond == UP)
330
			continue;
331
		c = p->to.offset;
332
		for(q = firstp; q != P;) {
333
			if(q->forwd != P)
334
			if(c >= q->forwd->pc) {
335
				q = q->forwd;
336
				continue;
337
			}
338
			if(c == q->pc)
339
				break;
340
			q = q->link;
341
		}
342
		if(q == P) {
343
			diag("branch out of range in %s\n%P", TNAME, p);
344
			p->to.type = D_NONE;
345
		}
346
		p->pcond = q;
347
	}
348
 
349
	for(p = firstp; p != P; p = p->link) {
350
		if(p->as == ATEXT)
351
			curtext = p;
352
		p->mark = 0;	/* initialization for follow */
353
		if(p->pcond != P && p->pcond != UP) {
354
			p->pcond = brloop(p->pcond);
355
			if(p->pcond != P)
356
			if(p->to.type == D_BRANCH)
357
				p->to.offset = p->pcond->pc;
358
		}
359
	}
360
}
361
 
362
#define	LOG	5
363
void
364
mkfwd(void)
365
{
366
	Prog *p;
367
	int i;
368
	long dwn[LOG], cnt[LOG];
369
	Prog *lst[LOG];
370
 
371
	for(i=0; i<LOG; i++) {
372
		if(i == 0)
373
			cnt[i] = 1; else
374
			cnt[i] = LOG * cnt[i-1];
375
		dwn[i] = 1;
376
		lst[i] = P;
377
	}
378
	i = 0;
379
	for(p = firstp; p != P; p = p->link) {
380
		if(p->as == ATEXT)
381
			curtext = p;
382
		i--;
383
		if(i < 0)
384
			i = LOG-1;
385
		p->forwd = P;
386
		dwn[i]--;
387
		if(dwn[i] <= 0) {
388
			dwn[i] = cnt[i];
389
			if(lst[i] != P)
390
				lst[i]->forwd = p;
391
			lst[i] = p;
392
		}
393
	}
394
}
395
 
396
Prog*
397
brloop(Prog *p)
398
{
399
	int c;
400
	Prog *q;
401
 
402
	c = 0;
403
	for(q = p; q != P; q = q->pcond) {
404
		if(q->as != AJMP)
405
			break;
406
		c++;
407
		if(c >= 5000)
408
			return P;
409
	}
410
	return q;
411
}
412
 
413
void
414
dostkoff(void)
415
{
416
	Prog *p, *q;
417
	long autoffset, deltasp;
418
	int a, f, curframe, curbecome, maxbecome;
419
 
420
	curframe = 0;
421
	curbecome = 0;
422
	maxbecome = 0;
423
	curtext = 0;
424
	for(p = firstp; p != P; p = p->link) {
425
 
426
		/* find out how much arg space is used in this TEXT */
427
		if(p->to.type == (D_INDIR+D_SP))
428
			if(p->to.offset > curframe)
429
				curframe = p->to.offset;
430
 
431
		switch(p->as) {
432
		case ATEXT:
433
			if(curtext && curtext->from.sym) {
434
				curtext->from.sym->frame = curframe;
435
				curtext->from.sym->become = curbecome;
436
				if(curbecome > maxbecome)
437
					maxbecome = curbecome;
438
			}
439
			curframe = 0;
440
			curbecome = 0;
441
 
442
			curtext = p;
443
			break;
444
 
445
		case ARET:
446
			/* special form of RET is BECOME */
447
			if(p->from.type == D_CONST)
448
				if(p->from.offset > curbecome)
449
					curbecome = p->from.offset;
450
			break;
451
		}
452
	}
453
	if(curtext && curtext->from.sym) {
454
		curtext->from.sym->frame = curframe;
455
		curtext->from.sym->become = curbecome;
456
		if(curbecome > maxbecome)
457
			maxbecome = curbecome;
458
	}
459
 
460
	if(debug['b'])
461
		print("max become = %d\n", maxbecome);
462
	xdefine("ALEFbecome", STEXT, maxbecome);
463
 
464
	curtext = 0;
465
	for(p = firstp; p != P; p = p->link) {
466
		switch(p->as) {
467
		case ATEXT:
468
			curtext = p;
469
			break;
470
		case ACALL:
471
			if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
472
				f = maxbecome - curtext->from.sym->frame;
473
				if(f <= 0)
474
					break;
475
				/* calling a become or calling a variable */
476
				if(p->to.sym == S || p->to.sym->become) {
477
					curtext->to.offset += f;
478
					if(debug['b']) {
479
						curp = p;
480
						print("%D calling %D increase %d\n",
481
							&curtext->from, &p->to, f);
482
					}
483
				}
484
			}
485
			break;
486
		}
487
	}
488
 
489
	autoffset = 0;
490
	deltasp = 0;
491
	for(p = firstp; p != P; p = p->link) {
492
		if(p->as == ATEXT) {
493
			curtext = p;
494
			autoffset = p->to.offset;
495
			if(autoffset < 0)
496
				autoffset = 0;
497
			if(autoffset) {
498
				p = appendp(p);
499
				p->as = AADJSP;
500
				p->from.type = D_CONST;
501
				p->from.offset = autoffset;
502
			}
503
			deltasp = autoffset;
504
		}
505
		a = p->from.type;
506
		if(a == D_AUTO)
507
			p->from.offset += deltasp;
508
		if(a == D_PARAM)
509
			p->from.offset += deltasp + 4;
510
		a = p->to.type;
511
		if(a == D_AUTO)
512
			p->to.offset += deltasp;
513
		if(a == D_PARAM)
514
			p->to.offset += deltasp + 4;
515
 
516
		switch(p->as) {
517
		default:
518
			continue;
519
		case APUSHL:
520
		case APUSHFL:
521
			deltasp += 4;
522
			continue;
523
		case APUSHW:
524
		case APUSHFW:
525
			deltasp += 2;
526
			continue;
527
		case APOPL:
528
		case APOPFL:
529
			deltasp -= 4;
530
			continue;
531
		case APOPW:
532
		case APOPFW:
533
			deltasp -= 2;
534
			continue;
535
		case ARET:
536
			break;
537
		}
538
 
539
		if(autoffset != deltasp)
540
			diag("unbalanced PUSH/POP");
541
		if(p->from.type == D_CONST)
542
			goto become;
543
 
544
		if(autoffset) {
545
			q = p;
546
			p = appendp(p);
547
			p->as = ARET;
548
 
549
			q->as = AADJSP;
550
			q->from.type = D_CONST;
551
			q->from.offset = -autoffset;
552
		}
553
		continue;
554
 
555
	become:
556
		q = p;
557
		p = appendp(p);
558
		p->as = AJMP;
559
		p->to = q->to;
560
		p->pcond = q->pcond;
561
 
562
		q->as = AADJSP;
563
		q->from = zprg.from;
564
		q->from.type = D_CONST;
565
		q->from.offset = -autoffset;
566
		q->to = zprg.to;
567
		continue;
568
	}
569
}
570
 
571
long
572
atolwhex(char *s)
573
{
574
	long n;
575
	int f;
576
 
577
	n = 0;
578
	f = 0;
579
	while(*s == ' ' || *s == '\t')
580
		s++;
581
	if(*s == '-' || *s == '+') {
582
		if(*s++ == '-')
583
			f = 1;
584
		while(*s == ' ' || *s == '\t')
585
			s++;
586
	}
587
	if(s[0]=='0' && s[1]){
588
		if(s[1]=='x' || s[1]=='X'){
589
			s += 2;
590
			for(;;){
591
				if(*s >= '0' && *s <= '9')
592
					n = n*16 + *s++ - '0';
593
				else if(*s >= 'a' && *s <= 'f')
594
					n = n*16 + *s++ - 'a' + 10;
595
				else if(*s >= 'A' && *s <= 'F')
596
					n = n*16 + *s++ - 'A' + 10;
597
				else
598
					break;
599
			}
600
		} else
601
			while(*s >= '0' && *s <= '7')
602
				n = n*8 + *s++ - '0';
603
	} else
604
		while(*s >= '0' && *s <= '9')
605
			n = n*10 + *s++ - '0';
606
	if(f)
607
		n = -n;
608
	return n;
609
}
610
 
611
void
612
undef(void)
613
{
614
	int i;
615
	Sym *s;
616
 
617
	for(i=0; i<NHASH; i++)
618
	for(s = hash[i]; s != S; s = s->link)
619
		if(s->type == SXREF)
620
			diag("%s: not defined", s->name);
621
}
622
 
623
void
624
import(void)
625
{
626
	int i;
627
	Sym *s;
628
 
629
	for(i = 0; i < NHASH; i++)
630
		for(s = hash[i]; s != S; s = s->link)
631
			if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
632
				if(s->value != 0)
633
					diag("value != 0 on SXREF");
634
				undefsym(s);
635
				if(debug['X'])
636
					Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->name, s->sig, s->value);
637
				if(debug['S'])
638
					s->sig = 0;
639
			}
640
}
641
 
642
void
643
ckoff(Sym *s, long v)
644
{
645
	if(v < 0 || v >= 1<<Roffset)
646
		diag("relocation offset %ld for %s out of range", v, s->name);
647
}
648
 
649
static Prog*
650
newdata(Sym *s, int o, int w, int t)
651
{
652
	Prog *p;
653
 
654
	p = prg();
655
	if(edatap == P)
656
		datap = p;
657
	else
658
		edatap->link = p;
659
	edatap = p;
660
	p->as = ADATA;
661
	p->width = w;
662
	p->from.scale = w;
663
	p->from.type = t;
664
	p->from.sym = s;
665
	p->from.offset = o;
666
	p->to.type = D_CONST;
667
	return p;
668
}
669
 
670
void
671
export(void)
672
{
673
	int i, j, n, off, nb, sv, ne;
674
	Sym *s, *et, *str, **esyms;
675
	Prog *p;
676
	char buf[NSNAME], *t;
677
 
678
	n = 0;
679
	for(i = 0; i < NHASH; i++)
680
		for(s = hash[i]; s != S; s = s->link)
681
			if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport))
682
				n++;
683
	esyms = malloc(n*sizeof(Sym*));
684
	ne = n;
685
	n = 0;
686
	for(i = 0; i < NHASH; i++)
687
		for(s = hash[i]; s != S; s = s->link)
688
			if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport))
689
				esyms[n++] = s;
690
	for(i = 0; i < ne-1; i++)
691
		for(j = i+1; j < ne; j++)
692
			if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
693
				s = esyms[i];
694
				esyms[i] = esyms[j];
695
				esyms[j] = s;
696
			}
697
 
698
	nb = 0;
699
	off = 0;
700
	et = lookup(EXPTAB, 0);
701
	if(et->type != 0 && et->type != SXREF)
702
		diag("%s already defined", EXPTAB);
703
	et->type = SDATA;
704
	str = lookup(".string", 0);
705
	if(str->type == 0)
706
		str->type = SDATA;
707
	sv = str->value;
708
	for(i = 0; i < ne; i++){
709
		s = esyms[i];
710
		if(debug['S'])
711
			s->sig = 0;
712
		/* Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type); */
713
 
714
		/* signature */
715
		p = newdata(et, off, sizeof(long), D_EXTERN);
716
		off += sizeof(long);
717
		p->to.offset = s->sig;
718
 
719
		/* address */
720
		p = newdata(et, off, sizeof(long), D_EXTERN);
721
		off += sizeof(long);
722
		p->to.type = D_ADDR;
723
		p->to.index = D_EXTERN;
724
		p->to.sym = s;
725
 
726
		/* string */
727
		t = s->name;
728
		n = strlen(t)+1;
729
		for(;;){
730
			buf[nb++] = *t;
731
			sv++;
732
			if(nb >= NSNAME){
733
				p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
734
				p->to.type = D_SCONST;
735
				memmove(p->to.scon, buf, NSNAME);
736
				nb = 0;
737
			}
738
			if(*t++ == 0)
739
				break;
740
		}
741
 
742
		/* name */
743
		p = newdata(et, off, sizeof(long), D_EXTERN);
744
		off += sizeof(long);
745
		p->to.type = D_ADDR;
746
		p->to.index = D_STATIC;
747
		p->to.sym = str;
748
		p->to.offset = sv-n;
749
	}
750
 
751
	if(nb > 0){
752
		p = newdata(str, sv-nb, nb, D_STATIC);
753
		p->to.type = D_SCONST;
754
		memmove(p->to.scon, buf, nb);
755
	}
756
 
757
	for(i = 0; i < 3; i++){
758
		newdata(et, off, sizeof(long), D_EXTERN);
759
		off += sizeof(long);
760
	}
761
	et->value = off;
762
	if(sv == 0)
763
		sv = 1;
764
	str->value = sv;
765
	exports = ne;
766
	free(esyms);
767
}