1 #include "l.h"
2
3 void
dodata(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*
brchain(Prog * p)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
follow(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
xfol(Prog * p)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
relinv(int a)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
doinit(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
patch(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
mkfwd(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*
brloop(Prog * p)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
dostkoff(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
atolwhex(char * s)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
undef(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
import(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
ckoff(Sym * s,long v)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*
newdata(Sym * s,int o,int w,int t)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
export(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 }
768