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