]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vl/pass.c
exec(2): fix prototypes
[plan9front.git] / sys / src / cmd / vl / pass.c
1 #include        "l.h"
2
3 void
4 dodata(void)
5 {
6         int i, t;
7         Sym *s;
8         Prog *p, *p1;
9         long orig, orig1, 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 R30)
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         orig1 = orig;
67
68         /*
69          * pass 2
70          *      assign 'data' variables to data segment
71          */
72         for(i=0; i<NHASH; i++)
73         for(s = hash[i]; s != S; s = s->link) {
74                 t = s->type;
75                 if(t != SDATA) {
76                         if(t == SDATA1)
77                                 s->type = SDATA;
78                         continue;
79                 }
80                 v = s->value;
81                 s->value = orig;
82                 orig += v;
83                 s->type = SDATA1;
84         }
85
86         while(orig & 7)
87                 orig++;
88         datsize = orig;
89
90         /*
91          * pass 3
92          *      everything else to bss segment
93          */
94         for(i=0; i<NHASH; i++)
95         for(s = hash[i]; s != S; s = s->link) {
96                 if(s->type != SBSS)
97                         continue;
98                 v = s->value;
99                 s->value = orig;
100                 orig += v;
101         }
102         while(orig & 7)
103                 orig++;
104         bsssize = orig-datsize;
105
106         /*
107          * pass 4
108          *      add literals to all large values.
109          *      at this time:
110          *              small data is allocated DATA
111          *              large data is allocated DATA1
112          *              large bss is allocated BSS
113          *      the new literals are loaded between
114          *      small data and large data.
115          */
116         orig = 0;
117         for(p = firstp; p != P; p = p->link) {
118                 if(p->as != AMOVW)
119                         continue;
120                 if(p->from.type != D_CONST)
121                         continue;
122                 if(s = p->from.sym) {
123                         t = s->type;
124                         if(t != SDATA && t != SDATA1 && t != SBSS)
125                                 continue;
126                         t = p->from.name;
127                         if(t != D_EXTERN && t != D_STATIC)
128                                 continue;
129                         v = s->value + p->from.offset;
130                         if(v >= 0 && v <= 0xffff)
131                                 continue;
132                         if(!strcmp(s->name, "setR30"))
133                                 continue;
134                         /* size should be 19 max */
135                         if(strlen(s->name) >= 10)       /* has loader address */ 
136                                 snprint(literal, sizeof literal, "$%p.%lux", s, p->from.offset);
137                         else
138                                 snprint(literal, sizeof literal, "$%s.%d.%lux", s->name, s->version, p->from.offset);
139                 } else {
140                         if(p->from.name != D_NONE)
141                                 continue;
142                         if(p->from.reg != NREG)
143                                 continue;
144                         v = p->from.offset;
145                         if(v >= -0x7fff && v <= 0xffff)
146                                 continue;
147                         if(!(v & 0xffff))
148                                 continue;
149                         /* size should be 9 max */
150                         snprint(literal, sizeof literal, "$%lux", v);
151                 }
152                 s = lookup(literal, 0);
153                 if(s->type == 0) {
154                         s->type = SDATA;
155                         s->value = orig1+orig;
156                         orig += 4;
157                         p1 = prg();
158                         p1->line = p->line;
159                         p1->as = ADATA;
160                         p1->from.type = D_OREG;
161                         p1->from.sym = s;
162                         p1->from.name = D_EXTERN;
163                         p1->reg = 4;
164                         p1->to = p->from;
165                         p1->link = datap;
166                         datap = p1;
167                 }
168                 if(s->type != SDATA)
169                         diag("literal not data: %s", s->name);
170                 p->from.type = D_OREG;
171                 p->from.sym = s;
172                 p->from.name = D_EXTERN;
173                 p->from.offset = 0;
174                 nocache(p);
175                 continue;
176         }
177         while(orig & 7)
178                 orig++;
179         /*
180          * pass 5
181          *      re-adjust offsets
182          */
183         for(i=0; i<NHASH; i++)
184         for(s = hash[i]; s != S; s = s->link) {
185                 t = s->type;
186                 if(t == SBSS) {
187                         s->value += orig;
188                         continue;
189                 }
190                 if(t == SDATA1) {
191                         s->type = SDATA;
192                         s->value += orig;
193                         continue;
194                 }
195         }
196         datsize += orig;
197         xdefine("setR30", SDATA, 0L+BIG);
198         xdefine("bdata", SDATA, 0L);
199         xdefine("edata", SDATA, datsize);
200         xdefine("end", SBSS, datsize+bsssize);
201         xdefine("etext", STEXT, 0L);
202 }
203
204 void
205 undef(void)
206 {
207         int i;
208         Sym *s;
209
210         for(i=0; i<NHASH; i++)
211         for(s = hash[i]; s != S; s = s->link)
212                 if(s->type == SXREF)
213                         diag("%s: not defined", s->name);
214 }
215
216 void
217 follow(void)
218 {
219         if(debug['v'])
220                 Bprint(&bso, "%5.2f follow\n", cputime());
221         Bflush(&bso);
222
223         firstp = prg();
224         lastp = firstp;
225         xfol(textp);
226
227         firstp = firstp->link;
228         lastp->link = P;
229 }
230
231 void
232 xfol(Prog *p)
233 {
234         Prog *q, *r;
235         int a, i;
236
237 loop:
238         if(p == P)
239                 return;
240         a = p->as;
241         if(a == ATEXT)
242                 curtext = p;
243         if(a == AJMP) {
244                 q = p->cond;
245                 if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
246                         p->mark |= FOLL;
247                         lastp->link = p;
248                         lastp = p;
249                         p = p->link;
250                         xfol(p);
251                         p = q;
252                         if(p && !(p->mark & FOLL))
253                                 goto loop;
254                         return;
255                 }
256                 if(q != P) {
257                         p->mark |= FOLL;
258                         p = q;
259                         if(!(p->mark & FOLL))
260                                 goto loop;
261                 }
262         }
263         if(p->mark & FOLL) {
264                 for(i=0,q=p; i<4; i++,q=q->link) {
265                         if(q == lastp || (q->mark&NOSCHED))
266                                 break;
267                         a = q->as;
268                         if(a == ANOP) {
269                                 i--;
270                                 continue;
271                         }
272                         if(a == AJMP || a == ARET || a == ARFE)
273                                 goto copy;
274                         if(!q->cond || (q->cond->mark&FOLL))
275                                 continue;
276                         if(a != ABEQ && a != ABNE)
277                                 continue;
278                 copy:
279                         for(;;) {
280                                 r = prg();
281                                 *r = *p;
282                                 if(!(r->mark&FOLL))
283                                         print("cant happen 1\n");
284                                 r->mark |= FOLL;
285                                 if(p != q) {
286                                         p = p->link;
287                                         lastp->link = r;
288                                         lastp = r;
289                                         continue;
290                                 }
291                                 lastp->link = r;
292                                 lastp = r;
293                                 if(a == AJMP || a == ARET || a == ARFE)
294                                         return;
295                                 r->as = ABNE;
296                                 if(a == ABNE)
297                                         r->as = ABEQ;
298                                 r->cond = p->link;
299                                 r->link = p->cond;
300                                 if(!(r->link->mark&FOLL))
301                                         xfol(r->link);
302                                 if(!(r->cond->mark&FOLL))
303                                         print("cant happen 2\n");
304                                 return;
305                         }
306                 }
307                 a = AJMP;
308                 q = prg();
309                 q->as = a;
310                 q->line = p->line;
311                 q->to.type = D_BRANCH;
312                 q->to.offset = p->pc;
313                 q->cond = p;
314                 p = q;
315         }
316         p->mark |= FOLL;
317         lastp->link = p;
318         lastp = p;
319         if(a == AJMP || a == ARET || a == ARFE){
320                 if(p->mark & NOSCHED){
321                         p = p->link;
322                         goto loop;
323                 }
324                 return;
325         }
326         if(p->cond != P)
327         if(a != AJAL && p->link != P) {
328                 xfol(p->link);
329                 p = p->cond;
330                 if(p == P || (p->mark&FOLL))
331                         return;
332                 goto loop;
333         }
334         p = p->link;
335         goto loop;
336 }
337
338 void
339 patch(void)
340 {
341         long c, vexit;
342         Prog *p, *q;
343         Sym *s;
344         int a;
345
346         if(debug['v'])
347                 Bprint(&bso, "%5.2f patch\n", cputime());
348         Bflush(&bso);
349         mkfwd();
350         s = lookup("exit", 0);
351         vexit = s->value;
352         for(p = firstp; p != P; p = p->link) {
353                 a = p->as;
354                 if(a == ATEXT)
355                         curtext = p;
356                 if((a == AJAL || a == AJMP || a == ARET) &&
357                    p->to.type != D_BRANCH && p->to.sym != S) {
358                         s = p->to.sym;
359                         if(s->type != STEXT) {
360                                 diag("undefined: %s\n%P", s->name, p);
361                                 s->type = STEXT;
362                                 s->value = vexit;
363                         }
364                         p->to.offset = s->value;
365                         p->to.type = D_BRANCH;
366                 }
367                 if(p->to.type != D_BRANCH)
368                         continue;
369                 c = p->to.offset;
370                 for(q = firstp; q != P;) {
371                         if(q->forwd != P)
372                         if(c >= q->forwd->pc) {
373                                 q = q->forwd;
374                                 continue;
375                         }
376                         if(c == q->pc)
377                                 break;
378                         q = q->link;
379                 }
380                 if(q == P) {
381                         diag("branch out of range %ld\n%P", c, p);
382                         p->to.type = D_NONE;
383                 }
384                 p->cond = q;
385         }
386
387         for(p = firstp; p != P; p = p->link) {
388                 if(p->as == ATEXT)
389                         curtext = p;
390                 if(p->cond != P) {
391                         p->cond = brloop(p->cond);
392                         if(p->cond != P)
393                         if(p->to.type == D_BRANCH)
394                                 p->to.offset = p->cond->pc;
395                 }
396         }
397 }
398
399 #define LOG     5
400 void
401 mkfwd(void)
402 {
403         Prog *p;
404         long dwn[LOG], cnt[LOG], i;
405         Prog *lst[LOG];
406
407         for(i=0; i<LOG; i++) {
408                 if(i == 0)
409                         cnt[i] = 1; else
410                         cnt[i] = LOG * cnt[i-1];
411                 dwn[i] = 1;
412                 lst[i] = P;
413         }
414         i = 0;
415         for(p = firstp; p != P; p = p->link) {
416                 if(p->as == ATEXT)
417                         curtext = p;
418                 i--;
419                 if(i < 0)
420                         i = LOG-1;
421                 p->forwd = P;
422                 dwn[i]--;
423                 if(dwn[i] <= 0) {
424                         dwn[i] = cnt[i];
425                         if(lst[i] != P)
426                                 lst[i]->forwd = p;
427                         lst[i] = p;
428                 }
429         }
430 }
431
432 Prog*
433 brloop(Prog *p)
434 {
435         Prog *q;
436         int c;
437
438         for(c=0; p!=P;) {
439                 if(p->as != AJMP || (p->mark&NOSCHED))
440                         return p;
441                 q = p->cond;
442                 if(q <= p) {
443                         c++;
444                         if(q == p || c > 5000)
445                                 break;
446                 }
447                 p = q;
448         }
449         return P;
450 }
451
452 long
453 atolwhex(char *s)
454 {
455         long n;
456         int f;
457
458         n = 0;
459         f = 0;
460         while(*s == ' ' || *s == '\t')
461                 s++;
462         if(*s == '-' || *s == '+') {
463                 if(*s++ == '-')
464                         f = 1;
465                 while(*s == ' ' || *s == '\t')
466                         s++;
467         }
468         if(s[0]=='0' && s[1]){
469                 if(s[1]=='x' || s[1]=='X'){
470                         s += 2;
471                         for(;;){
472                                 if(*s >= '0' && *s <= '9')
473                                         n = n*16 + *s++ - '0';
474                                 else if(*s >= 'a' && *s <= 'f')
475                                         n = n*16 + *s++ - 'a' + 10;
476                                 else if(*s >= 'A' && *s <= 'F')
477                                         n = n*16 + *s++ - 'A' + 10;
478                                 else
479                                         break;
480                         }
481                 } else
482                         while(*s >= '0' && *s <= '7')
483                                 n = n*8 + *s++ - '0';
484         } else
485                 while(*s >= '0' && *s <= '9')
486                         n = n*10 + *s++ - '0';
487         if(f)
488                 n = -n;
489         return n;
490 }
491
492 long
493 rnd(long v, long r)
494 {
495         long c;
496
497         if(r <= 0)
498                 return v;
499         v += r - 1;
500         c = v % r;
501         if(c < 0)
502                 c += r;
503         v -= c;
504         return v;
505 }