]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/5l/pass.c
upas/fs: remove useless loop in rf822()
[plan9front.git] / sys / src / cmd / 5l / pass.c
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 }