]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/1c/swt.c
grep: error if sbrk fails
[plan9front.git] / sys / src / cmd / 1c / swt.c
1 #include "gc.h"
2
3 int
4 swcmp(const void *a1, const void *a2)
5 {
6         C1 *p1, *p2;
7
8         p1 = (C1*)a1;
9         p2 = (C1*)a2;
10         if(p1->val < p2->val)
11                 return -1;
12         return p1->val > p2->val;
13 }
14
15 void
16 doswit(int g, Node *n)
17 {
18         Case *c;
19         C1 *q, *iq;
20         long def, nc, i;
21
22         def = 0;
23         nc = 0;
24         for(c = cases; c->link != C; c = c->link) {
25                 if(c->def) {
26                         if(def)
27                                 diag(n, "more than one default in switch");
28                         def = c->label;
29                         continue;
30                 }
31                 nc++;
32         }
33
34         iq = alloc(nc*sizeof(C1));
35         q = iq;
36         for(c = cases; c->link != C; c = c->link) {
37                 if(c->def)
38                         continue;
39                 q->label = c->label;
40                 q->val = c->val;
41                 q++;
42         }
43         qsort(iq, nc, sizeof(C1), swcmp);
44         if(def == 0)
45                 def = breakpc;
46         for(i=0; i<nc-1; i++)
47                 if(iq[i].val == iq[i+1].val)
48                         diag(n, "duplicate cases in switch %lld", iq[i].val);
49         swit1(iq, nc, def, g, n);
50 }
51
52 #define N1      4       /* ncase: always linear */
53                         /* else binary */
54 void
55 swit1(C1 *q, int nc, long def, int g, Node *n)
56 {
57         C1 *r;
58         int i;
59         long v;
60         Prog *sp1, *sp2;
61
62         /* note that g and g+1 are not allocated */
63         if(nc <= N1)
64                 goto linear;
65
66         /*
67          * divide and conquer
68          */
69         i = nc / 2;
70         r = q+i;
71         v = r->val;
72         /* compare median */
73         if(v >= -128 && v < 128) {
74                 gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
75                 gopcode(OEQ, n->type, g, n, g+1, n);
76         } else
77                 gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
78         gbranch(OLT);
79         sp1 = p;
80         gbranch(OGT);
81         sp2 = p;
82         gbranch(OGOTO);
83         patch(p, r->label);
84
85         patch(sp1, pc);
86         swit1(q, i, def, g, n);
87
88         patch(sp2, pc);
89         swit1(r+1, nc-i-1, def, g, n);
90         return;
91
92 linear:
93         for(i=0; i<nc; i++) {
94                 v = q->val;
95                 if(v >= -128 && v < 128) {
96                         gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
97                         gopcode(OEQ, n->type, g+1, n, g, n);
98                 } else
99                         gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
100                 gbranch(OEQ);
101                 patch(p, q->label);
102                 q++;
103         }
104         gbranch(OGOTO);
105         patch(p, def);
106 }
107
108 void
109 casf(void)
110 {
111         Case *c;
112
113         c = alloc(sizeof(*c));
114         c->link = cases;
115         cases = c;
116 }
117
118
119 int
120 bitload(Node *b, int n1, int n2, int n3, Node *nn)
121 {
122         int sh, g, gs;
123         long v;
124         Node *l;
125         Type *t;
126
127         /*
128          * n1 gets adjusted/masked value
129          * n2 gets address of cell
130          * n3 gets contents of cell
131          */
132         gs = 0;
133         t = tfield;
134
135         l = b->left;
136         g = regalloc(t, n3);
137         if(n2 != D_NONE) {
138                 lcgen(l, n2, Z);
139                 n2 |= I_INDIR;
140                 gmove(t, t, n2, l, g, l);
141                 gmove(t, t, g, l, n1, l);
142         } else
143                 cgen(l, g, nn);
144         if(b->type->shift == 0 && typeu[b->type->etype]) {
145                 v = ~0 + (1L << b->type->nbits);
146                 gopcode(OAND, t, D_CONST, nodconst(v), g, l);
147         } else {
148                 sh = 32 - b->type->shift - b->type->nbits;
149                 if(sh > 0)
150                         if(sh >= 8) {
151                                 gs = regalloc(t, D_NONE);
152                                 gmove(t, t, D_CONST, nodconst(sh), gs, l);
153                                 gopcode(OASHL, t, gs, l, g, l);
154                                 if(b->type->shift)
155                                         regfree(gs);
156                         } else
157                                 gopcode(OASHL, t, D_CONST, nodconst(sh), g, l);
158                 sh += b->type->shift;
159                 if(sh > 0) {
160                         if(sh >= 8) {
161                                 if(b->type->shift) {
162                                         gs = regalloc(t, D_NONE);
163                                         gmove(t, t, D_CONST, nodconst(sh), gs, l);
164                                 }
165                                 if(typeu[b->type->etype])
166                                         gopcode(OLSHR, t, gs, l, g, l);
167                                 else
168                                         gopcode(OASHR, t, gs, l, g, l);
169                                 regfree(gs);
170                         } else {
171                                 if(typeu[b->type->etype])
172                                         gopcode(OLSHR, t, D_CONST, nodconst(sh), g, l);
173                                 else
174                                         gopcode(OASHR, t, D_CONST, nodconst(sh), g, l);
175                         }
176                 }
177         }
178         return g;
179 }
180
181 void
182 bitstore(Node *b, int n1, int n2, int n3, int result, Node *nn)
183 {
184         long v;
185         Node *l;
186         Type *t;
187         int sh, g, gs;
188
189         /*
190          * n1 has adjusted/masked value
191          * n2 has address of cell
192          * n3 has contents of cell
193          */
194         t = tfield;
195
196         l = b->left;
197         g = regalloc(t, D_NONE);
198         v = ~0 + (1L << b->type->nbits);
199         gopcode(OAND, t, D_CONST, nodconst(v), n1, l);
200         gmove(t, t, n1, l, g, l);
201         if(result != D_NONE)
202                 gmove(t, nn->type, n1, l, result, nn);
203         sh = b->type->shift;
204         if(sh > 0) {
205                 if(sh >= 8) {
206                         gs = regalloc(t, D_NONE);
207                         gmove(t, t, D_CONST, nodconst(sh), gs, l);
208                         gopcode(OASHL, t, gs, l, g, l);
209                         regfree(gs);
210                 } else
211                         gopcode(OASHL, t, D_CONST, nodconst(sh), g, l);
212         }
213         v <<= sh;
214         gopcode(OAND, t, D_CONST, nodconst(~v), n3, l);
215         gopcode(OOR, t, n3, l, g, l);
216         gmove(t, t, g, l, n2|I_INDIR, l);
217
218         regfree(g);
219         regfree(n1);
220         regfree(n2);
221         regfree(n3);
222 }
223
224 long
225 outstring(char *s, long n)
226 {
227         long r;
228
229         if(suppress)
230                 return nstring;
231         r = nstring;
232         while(n) {
233                 string[mnstring] = *s++;
234                 mnstring++;
235                 nstring++;
236                 if(mnstring >= NSNAME) {
237                         gpseudo(ADATA, symstring, D_SCONST, 0L);
238                         memmove(p->to.sval, string, NSNAME);
239                         p->from.offset = nstring - NSNAME;
240                         p->from.displace = NSNAME;
241                         mnstring = 0;
242                 }
243                 n--;
244         }
245         return r;
246 }
247
248 long
249 outlstring(Rune *s, long n)
250 {
251         char buf[sizeof(Rune)];
252         int c, i;
253         long r;
254
255         while(nstring % sizeof buf)
256                 outstring("", 1);
257         r = nstring;
258         while(n > 0) {
259                 c = *s++;
260                 if(align(0, types[TCHAR], Aarg1)) {
261                         for(i = sizeof buf; i > 0; c >>= 8)
262                                 buf[--i] = c;
263                 } else {
264                         for(i = 0; i < sizeof buf; c >>= 8)
265                                 buf[i++] = c;
266                 }
267                 outstring(buf, sizeof buf);
268                 n -= sizeof buf;
269         }
270         return r;
271 }
272
273 int
274 doinc(Node *n, int f)
275 {
276         Node *l;
277         int a;
278
279 loop:
280         if(n == Z)
281                 return 0;
282         l = n->left;
283         switch(n->op) {
284
285         case OPOSTINC:
286         case OPOSTDEC:
287                 if(f & POST) {
288                         a = n->addable;
289                         if(a >= INDEXED) {
290                                 if(f & TEST)
291                                         return 1;
292                                 n->addable = 0;
293                                 cgen(n, D_NONE, n);
294                                 n->addable = a;
295                         }
296                 }
297                 break;
298
299         case OAS:
300         case OASLMUL:
301         case OASLDIV:
302         case OASLMOD:
303         case OASMUL:
304         case OASDIV:
305         case OASMOD:
306         case OASXOR:
307         case OASOR:
308         case OASADD:
309         case OASSUB:
310         case OASLSHR:
311         case OASASHR:
312         case OASASHL:
313         case OASAND:
314
315         case OPREINC:
316         case OPREDEC:
317                 if(f & PRE) {
318                         a = n->addable;
319                         if(a >= INDEXED) {
320                                 if(f & TEST)
321                                         return 1;
322                                 n->addable = 0;
323                                 doinc(n, PRE);
324                                 cgen(n, D_NONE, n);
325                                 n->addable = a;
326                                 return 0;
327                         }
328                 }
329                 break;
330
331         case OFUNC:
332                 if(f & PRE)
333                         break;
334                 return 0;
335
336         case ONAME:
337         case OREGISTER:
338         case OSTRING:
339         case OCONST:
340
341         case OANDAND:
342         case OOROR:
343                 return 0;
344
345         case OCOND:
346                 return 0;
347
348         case OCOMMA:
349                 n = n->right;
350                 if(f & PRE)
351                         n = l;
352                 goto loop;
353         }
354         if(l != Z)
355                 if(doinc(l, f))
356                         return 1;
357         n = n->right;
358         goto loop;
359 }
360
361 void
362 setsp(void)
363 {
364
365         nextpc();
366         p->as = AADJSP;
367         p->from.type = D_CONST;
368         p->from.offset = 0;
369 }
370
371 void
372 adjsp(long o)
373 {
374
375         if(o != 0) {
376                 nextpc();
377                 p->as = AADJSP;
378                 p->from.type = D_CONST;
379                 p->from.offset = o;
380                 argoff += o;
381         }
382 }
383
384 int
385 simplv(Node *n)
386 {
387
388         if(n->addable <= INDEXED)
389                 return 0;
390         while(n->op == OIND)
391                 n = n->left;
392         if(n->op == ONAME)
393                 return 1;
394         return 0;
395 }
396
397 int
398 eval(Node *n, int g)
399 {
400
401         if(n->addable >= INDEXED)
402                 return D_TREE;
403         g = regalloc(n->type, g);
404         cgen(n, g, n);
405         return g;
406 }
407
408 void    outhist(Biobuf*);
409 void    zname(Biobuf*, Sym*, int);
410 void    zaddr(Biobuf*, Adr*, int);
411 void    zwrite(Biobuf*, Prog*, int, int);
412
413 void
414 outcode(void)
415 {
416         struct { Sym *sym; short type; } h[NSYM];
417         Prog *p;
418         Sym *s;
419         int f, sf, st, t, sym;
420         Biobuf b;
421
422         if(debug['S']) {
423                 for(p = firstp; p != P; p = p->link)
424                         if(p->as != ADATA && p->as != AGLOBL)
425                                 pc--;
426                 for(p = firstp; p != P; p = p->link) {
427                         print("%P\n", p);
428                         if(p->as != ADATA && p->as != AGLOBL)
429                                 pc++;
430                 }
431         }
432         f = open(outfile, OWRITE);
433         if(f < 0) {
434                 diag(Z, "cant open %s", outfile);
435                 errorexit();
436         }
437         Binit(&b, f, OWRITE);
438         Bseek(&b, 0L, 2);
439         outhist(&b);
440         for(sym=0; sym<NSYM; sym++) {
441                 h[sym].sym = S;
442                 h[sym].type = 0;
443         }
444         sym = 1;
445         for(p = firstp; p != P; p = p->link) {
446         jackpot:
447                 sf = 0;
448                 s = p->from.sym;
449                 while(s != S) {
450                         sf = s->sym;
451                         if(sf < 0 || sf >= NSYM)
452                                 sf = 0;
453                         t = p->from.type & D_MASK;
454                         if(h[sf].type == t)
455                         if(h[sf].sym == s)
456                                 break;
457                         s->sym = sym;
458                         zname(&b, s, t);
459                         h[sym].sym = s;
460                         h[sym].type = t;
461                         sf = sym;
462                         sym++;
463                         if(sym >= NSYM)
464                                 sym = 1;
465                         break;
466                 }
467                 st = 0;
468                 s = p->to.sym;
469                 while(s != S) {
470                         st = s->sym;
471                         if(st < 0 || st >= NSYM)
472                                 st = 0;
473                         t = p->to.type & D_MASK;
474                         if(h[st].type == t)
475                         if(h[st].sym == s)
476                                 break;
477                         s->sym = sym;
478                         zname(&b, s, t);
479                         h[sym].sym = s;
480                         h[sym].type = t;
481                         st = sym;
482                         sym++;
483                         if(sym >= NSYM)
484                                 sym = 1;
485                         if(st == sf)
486                                 goto jackpot;
487                         break;
488                 }
489                 zwrite(&b, p, sf, st);
490         }
491         Bflush(&b);
492         close(f);
493         firstp = P;
494         lastp = P;
495 }
496
497 void
498 zwrite(Biobuf *b, Prog *p, int sf, int st)
499 {
500         long l;
501
502         l = p->as;
503         Bputc(b, l);
504         Bputc(b, l>>8);
505         l = p->lineno;
506         Bputc(b, l);
507         Bputc(b, l>>8);
508         Bputc(b, l>>16);
509         Bputc(b, l>>24);
510         zaddr(b, &p->from, sf);
511         zaddr(b, &p->to, st);
512 }
513
514 void
515 zname(Biobuf *b, Sym *s, int t)
516 {
517         char *n;
518         ulong sig;
519
520         if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
521                 sig = sign(s);
522                 Bputc(b, ASIGNAME);
523                 Bputc(b, ASIGNAME>>8);
524                 Bputc(b, sig);
525                 Bputc(b, sig>>8);
526                 Bputc(b, sig>>16);
527                 Bputc(b, sig>>24);
528                 s->sig = SIGDONE;
529         }
530         else{
531                 Bputc(b, ANAME);        /* as */
532                 Bputc(b, ANAME>>8);     /* as */
533         }
534         Bputc(b, t);            /* type */
535         Bputc(b, s->sym);               /* sym */
536         n = s->name;
537         while(*n) {
538                 Bputc(b, *n);
539                 n++;
540         }
541         Bputc(b, 0);
542 }
543
544 void
545 zaddr(Biobuf *b, Adr *a, int s)
546 {
547         long l;
548         int i, t;
549         char *n;
550         Ieee e;
551
552         t = 0;
553         if(a->field)
554                 t |= T_FIELD;
555         if(s)
556                 t |= T_SYM;
557
558         switch(a->type) {
559         default:
560                 if(a->offset)
561                         t |= T_OFFSET;
562                 if(a->displace)
563                         t |= T_INDEX;
564                 if(a->type & ~0xff)
565                         t |= T_TYPE;
566                 break;
567         case D_FCONST:
568                 t |= T_FCONST;
569                 break;
570         case D_SCONST:
571                 t |= T_SCONST;
572                 break;
573         }
574         Bputc(b, t);
575
576         if(t & T_FIELD) {       /* implies field */
577                 i = a->field;
578                 Bputc(b, i);
579                 Bputc(b, i>>8);
580         }
581         if(t & T_INDEX) {       /* implies index, scale, displace */
582                 i = D_NONE;
583                 Bputc(b, i);
584                 Bputc(b, i>>8);
585                 Bputc(b, 0);
586                 l = a->displace;
587                 Bputc(b, l);
588                 Bputc(b, l>>8);
589                 Bputc(b, l>>16);
590                 Bputc(b, l>>24);
591         }
592         if(t & T_OFFSET) {      /* implies offset */
593                 l = a->offset;
594                 Bputc(b, l);
595                 Bputc(b, l>>8);
596                 Bputc(b, l>>16);
597                 Bputc(b, l>>24);
598         }
599         if(t & T_SYM)           /* implies sym */
600                 Bputc(b, s);
601         if(t & T_FCONST) {
602                 ieeedtod(&e, a->dval);
603                 l = e.l;
604                 Bputc(b, l);
605                 Bputc(b, l>>8);
606                 Bputc(b, l>>16);
607                 Bputc(b, l>>24);
608                 l = e.h;
609                 Bputc(b, l);
610                 Bputc(b, l>>8);
611                 Bputc(b, l>>16);
612                 Bputc(b, l>>24);
613                 return;
614         }
615         if(t & T_SCONST) {
616                 n = a->sval;
617                 for(i=0; i<NSNAME; i++) {
618                         Bputc(b, *n);
619                         n++;
620                 }
621                 return;
622         }
623         i = a->type;
624         Bputc(b, i);
625         if(t & T_TYPE)
626                 Bputc(b, i>>8);
627 }
628
629
630
631 void
632 outhist(Biobuf *b)
633 {
634         Hist *h;
635         char *p, *q, *op, c;
636         Prog pg;
637         int n;
638
639         pg = zprog;
640         pg.as = AHISTORY;
641         c = pathchar();
642         for(h = hist; h != H; h = h->link) {
643                 p = h->name;
644                 op = 0;
645                 /* on windows skip drive specifier in pathname */
646                 if(systemtype(Windows) && p && p[1] == ':'){
647                         p += 2;
648                         c = *p;
649                 }
650                 if(p && p[0] != c && h->offset == 0 && pathname){
651                         /* on windows skip drive specifier in pathname */
652                         if(systemtype(Windows) && pathname[1] == ':') {
653                                 op = p;
654                                 p = pathname+2;
655                                 c = *p;
656                         } else if(pathname[0] == c){
657                                 op = p;
658                                 p = pathname;
659                         }
660                 }
661                 while(p) {
662                         q = utfrune(p, c);
663                         if(q) {
664                                 n = q-p;
665                                 if(n == 0){
666                                         n = 1;  /* leading "/" */
667                                         *p = '/';       /* don't emit "\" on windows */
668                                 }
669                                 q++;
670                         } else {
671                                 n = strlen(p);
672                                 q = 0;
673                         }
674                         if(n) {
675                                 Bputc(b, ANAME);
676                                 Bputc(b, ANAME>>8);
677                                 Bputc(b, D_FILE);
678                                 Bputc(b, 1);
679                                 Bputc(b, '<');
680                                 Bwrite(b, p, n);
681                                 Bputc(b, 0);
682                         }
683                         p = q;
684                         if(p == 0 && op) {
685                                 p = op;
686                                 op = 0;
687                         }
688                 }
689                 pg.lineno = h->line;
690                 pg.to.type = zprog.to.type;
691                 pg.to.offset = h->offset;
692                 if(h->offset)
693                         pg.to.type = D_CONST;
694
695                 zwrite(b, &pg, 0, 0);
696         }
697 }
698
699 void
700 ieeedtod(Ieee *ieee, double native)
701 {
702         double fr, ho, f;
703         int exp;
704
705         if(native < 0) {
706                 ieeedtod(ieee, -native);
707                 ieee->h |= 0x80000000L;
708                 return;
709         }
710         if(native == 0) {
711                 ieee->l = 0;
712                 ieee->h = 0;
713                 return;
714         }
715         fr = frexp(native, &exp);
716         f = 2097152L;           /* shouldnt use fp constants here */
717         fr = modf(fr*f, &ho);
718         ieee->h = ho;
719         ieee->h &= 0xfffffL;
720         ieee->h |= (exp+1022L) << 20;
721         f = 65536L;
722         fr = modf(fr*f, &ho);
723         ieee->l = ho;
724         ieee->l <<= 16;
725         ieee->l |= (long)(fr*f);
726 }
727
728 int
729 nodalloc(Type *t, int g, Node *n)
730 {
731
732         n->type = t;
733         n->op = OREGISTER;
734         n->addable = 12;
735         n->complex = 0;
736         g = regaddr(g);
737         n->reg = g | I_INDIR;
738         n->xoffset = 0;
739         return g;
740 }
741
742 int
743 mulcon(Node *n, Node *c, int result, Node *nn)
744 {
745         long v;
746
747         if(typefd[n->type->etype])
748                 return 0;
749         v = c->vconst;
750         if(mulcon1(n, v, result, nn))
751                 return 1;
752         return 0;
753 }
754
755 int
756 shlcon(Node *n, Node *c, int result, Node *nn)
757 {
758         long v;
759
760         v = 1L << c->vconst;
761         return mulcon1(n, v, result, nn);
762 }
763
764 int
765 mulcon1(Node *n, long v, int result, Node *nn)
766 {
767         int g, g1, a1, a2, neg;
768         int o;
769         char code[10], *p;
770
771         if(result == D_NONE)
772                 return 0;
773         neg = 0;
774         if(v < 0) {
775                 v = -v;
776                 neg++;
777         }
778         a1 = 0;
779         a2 = multabsize;
780         for(;;) {
781                 if(a1 >= a2)
782                         return 0;
783                 g1 = (a2 + a1)/2;
784                 if(v < multab[g1].val) {
785                         a2 = g1;
786                         continue;
787                 }
788                 if(v > multab[g1].val) {
789                         a1 = g1+1;
790                         continue;
791                 }
792                 break;
793         }
794         strcpy(code, "0");
795         strncat(code, multab[g1].code, sizeof(multab[0].code));
796         p = code;
797         if(p[1] == 'i')
798                 p += 2;
799         g = regalloc(n->type, result);
800         cgen(n, g, n);
801         if(neg)
802                 gopcode(ONEG, n->type, D_NONE, n, g, n);
803         g1 = regalloc(n->type, D_NONE);
804 loop:
805         switch(*p) {
806         case 0:
807                 regfree(g1);
808                 gmove(n->type, nn->type, g, n, result, nn);
809                 regfree(g);
810                 return 1;
811         case '0':
812                 o = OAS;
813                 *p -= '0';
814                 goto com;
815         case '1':
816         case '2':
817                 o = OSUB;
818                 *p -= '1';
819                 goto com;
820         case '3':
821         case '4':
822         case '5':
823         case '6':
824                 o = OADD;
825                 *p -= '3';
826         com:
827                 a1 = g;
828                 if(*p == 1 || *p == 3)
829                         a1 = g1;
830                 a2 = g;
831                 if(*p == 0 || *p == 3)
832                         a2 = g1;
833                 gopcode(o, n->type, a1, n, a2, n);
834                 p++;
835                 break;
836         default:
837                 a1 = *p++ - 'a' + 1;
838                 a2 = g;
839                 if(a1 > 8) {
840                         a2 = g1;
841                         a1 -= 8;
842                 }
843                 gopcode(OASHL, n->type, D_CONST, nodconst(a1), a2, n);
844                 break;
845         }
846         goto loop;
847 }
848
849 void
850 nullwarn(Node *l, Node *r)
851 {
852         warn(Z, "result of operation not used");
853         if(l != Z)
854                 cgen(l, D_NONE, Z);
855         if(r != Z)
856                 cgen(r, D_NONE, Z);
857 }
858
859 void
860 sextern(Sym *s, Node *a, long o, long w)
861 {
862         long e, lw;
863
864         for(e=0; e<w; e+=NSNAME) {
865                 lw = NSNAME;
866                 if(w-e < lw)
867                         lw = w-e;
868                 gpseudo(ADATA, s, D_SCONST, 0L);
869                 p->from.offset += o+e;
870                 p->from.displace = lw;
871                 memmove(p->to.sval, a->cstring+e, lw);
872         }
873 }
874
875 void
876 gextern(Sym *s, Node *a, long o, long w)
877 {
878         if(a->op == OCONST && typev[a->type->etype]) {
879                 gpseudo(ADATA, s, D_CONST, (long)(a->vconst>>32));
880                 p->from.offset += o;
881                 p->from.displace = 4;
882                 gpseudo(ADATA, s, D_CONST, (long)(a->vconst));
883                 p->from.offset += o + 4;
884                 p->from.displace = 4;
885                 return;
886         }
887         gpseudotree(ADATA, s, a);
888         p->from.offset += o;
889         p->from.displace = w;
890 }
891
892 long
893 align(long i, Type *t, int op)
894 {
895         long o;
896         Type *v;
897         int w;
898
899         o = i;
900         w = 1;
901         switch(op) {
902         default:
903                 diag(Z, "unknown align opcode %d", op);
904                 break;
905
906         case Asu2:      /* padding at end of a struct */
907                 w = SZ_LONG;
908                 if(packflg)
909                         w = packflg;
910                 break;
911
912         case Ael1:      /* initial allign of struct element */
913                 for(v=t; v->etype==TARRAY; v=v->link)
914                         ;
915                 w = ewidth[v->etype];
916                 if(w <= 0 || w >= SZ_SHORT)
917                         w = SZ_SHORT;
918                 if(packflg)
919                         w = packflg;
920                 break;
921
922         case Ael2:      /* width of a struct element */
923                 o += t->width;
924                 break;
925
926         case Aarg0:     /* initial passbyptr argument in arg list */
927                 if(typesuv[t->etype]) {
928                         o = align(o, types[TIND], Aarg1);
929                         o = align(o, types[TIND], Aarg2);
930                 }
931                 break;
932
933         case Aarg1:     /* initial allign of parameter */
934                 w = ewidth[t->etype];
935                 if(w <= 0 || w >= SZ_LONG) {
936                         w = SZ_LONG;
937                         break;
938                 }
939                 o += SZ_LONG - w;       /* big endian adjustment */
940                 w = 1;
941                 break;
942
943         case Aarg2:     /* width of a parameter */
944                 o += t->width;
945                 w = SZ_LONG;
946                 break;
947
948         case Aaut3:     /* total allign of automatic */
949                 o = align(o, t, Ael1);
950                 o = align(o, t, Ael2);
951                 break;
952         }
953         o = round(o, w);
954         if(debug['A'])
955                 print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
956         return o;
957 }
958
959 long
960 maxround(long max, long v)
961 {
962         v += SZ_LONG-1;
963         if(v > max)
964                 max = round(v, SZ_LONG);
965         return max;
966 }