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