]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cc/dcl.c
968654165f7c14229cf4b8f4302e9b0a15deeac8
[plan9front.git] / sys / src / cmd / cc / dcl.c
1 #include "cc.h"
2
3 Node*
4 dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n)
5 {
6         Sym *s;
7         Node *n1;
8         long v;
9
10         nearln = lineno;
11         lastfield = 0;
12
13 loop:
14         if(n != Z)
15         switch(n->op) {
16         default:
17                 diag(n, "unknown declarator: %O", n->op);
18                 break;
19
20         case OARRAY:
21                 t = typ(TARRAY, t);
22                 t->width = 0;
23                 n1 = n->right;
24                 n = n->left;
25                 if(n1 != Z) {
26                         complex(n1);
27                         v = -1;
28                         if(n1->op == OCONST)
29                                 v = n1->vconst;
30                         if(v <= 0) {
31                                 diag(n, "array size must be a positive constant");
32                                 v = 1;
33                         }
34                         t->width = v * t->link->width;
35                 }
36                 goto loop;
37
38         case OIND:
39                 t = typ(TIND, t);
40                 t->garb = n->garb;
41                 n = n->left;
42                 goto loop;
43
44         case OFUNC:
45                 t = typ(TFUNC, t);
46                 t->down = fnproto(n);
47                 n = n->left;
48                 goto loop;
49
50         case OBIT:
51                 n1 = n->right;
52                 complex(n1);
53                 lastfield = -1;
54                 if(n1->op == OCONST)
55                         lastfield = n1->vconst;
56                 if(lastfield < 0) {
57                         diag(n, "field width must be non-negative constant");
58                         lastfield = 1;
59                 }
60                 if(lastfield == 0) {
61                         lastbit = 0;
62                         firstbit = 1;
63                         if(n->left != Z) {
64                                 diag(n, "zero width named field");
65                                 lastfield = 1;
66                         }
67                 }
68                 if(!typei[t->etype]) {
69                         diag(n, "field type must be int-like");
70                         t = types[TINT];
71                         lastfield = 1;
72                 }
73                 if(lastfield > tfield->width*8) {
74                         diag(n, "field width larger than field unit");
75                         lastfield = 1;
76                 }
77                 lastbit += lastfield;
78                 if(lastbit > tfield->width*8) {
79                         lastbit = lastfield;
80                         firstbit = 1;
81                 }
82                 n = n->left;
83                 goto loop;
84
85         case ONAME:
86                 if(f == NODECL)
87                         break;
88                 s = n->sym;
89                 (*f)(c, t, s);
90                 if(s->class == CLOCAL)
91                         s = mkstatic(s);
92                 firstbit = 0;
93                 n->sym = s;
94                 n->type = s->type;
95                 n->xoffset = s->offset;
96                 n->class = s->class;
97                 n->etype = TVOID;
98                 if(n->type != T)
99                         n->etype = n->type->etype;
100                 if(debug['d'])
101                         dbgdecl(s);
102                 acidvar(s);
103                 s->varlineno = lineno;
104                 break;
105         }
106         lastdcl = t;
107         return n;
108 }
109
110 Sym*
111 mkstatic(Sym *s)
112 {
113         Sym *s1;
114
115         if(s->class != CLOCAL)
116                 return s;
117         snprint(symb, NSYMB, "%s$%d", s->name, s->block);
118         s1 = lookup();
119         if(s1->class != CSTATIC) {
120                 s1->type = s->type;
121                 s1->offset = s->offset;
122                 s1->block = s->block;
123                 s1->class = CSTATIC;
124         }
125         return s1;
126 }
127
128 /*
129  * make a copy of a typedef
130  * the problem is to split out incomplete
131  * arrays so that it is in the variable
132  * rather than the typedef.
133  */
134 Type*
135 tcopy(Type *t)
136 {
137         Type *tl, *tx;
138         int et;
139
140         if(t == T)
141                 return t;
142         et = t->etype;
143         if(typesu[et])
144                 return t;
145         tl = tcopy(t->link);
146         if(tl != t->link ||
147           (et == TARRAY && t->width == 0)) {
148                 tx = copytyp(t);
149                 tx->link = tl;
150                 return tx;
151         }
152         return t;
153 }
154
155 Node*
156 doinit(Sym *s, Type *t, long o, Node *a)
157 {
158         Node *n;
159
160         if(t == T)
161                 return Z;
162         if(s->class == CEXTERN) {
163                 s->class = CGLOBL;
164                 if(debug['d'])
165                         dbgdecl(s);
166         }
167         if(debug['i']) {
168                 print("t = %T; o = %ld; n = %s\n", t, o, s->name);
169                 prtree(a, "doinit value");
170         }
171
172
173         n = initlist;
174         if(a->op == OINIT)
175                 a = a->left;
176         initlist = a;
177
178         a = init1(s, t, o, 0);
179         if(initlist != Z)
180                 diag(initlist, "more initializers than structure: %s",
181                         s->name);
182         initlist = n;
183
184         return a;
185 }
186
187 /*
188  * get next major operator,
189  * dont advance initlist.
190  */
191 Node*
192 peekinit(void)
193 {
194         Node *a;
195
196         a = initlist;
197
198 loop:
199         if(a == Z)
200                 return a;
201         if(a->op == OLIST) {
202                 a = a->left;
203                 goto loop;
204         }
205         return a;
206 }
207
208 /*
209  * consume and return next element on
210  * initlist. expand strings.
211  */
212 Node*
213 nextinit(void)
214 {
215         Node *a, *b, *n;
216
217         a = initlist;
218         n = Z;
219
220         if(a == Z)
221                 return a;
222         if(a->op == OLIST) {
223                 n = a->right;
224                 a = a->left;
225         }
226         if(a->op == OUSED) {
227                 a = a->left;
228                 b = new(OCONST, Z, Z);
229                 b->type = a->type->link;
230                 if(a->op == OSTRING) {
231                         b->vconst = convvtox(*a->cstring, TCHAR);
232                         a->cstring++;
233                 }
234                 if(a->op == OLSTRING) {
235                         b->vconst = convvtox(*a->rstring, TUSHORT);
236                         a->rstring++;
237                 }
238                 a->type->width -= b->type->width;
239                 if(a->type->width <= 0)
240                         initlist = n;
241                 return b;
242         }
243         initlist = n;
244         return a;
245 }
246
247 int
248 isstruct(Node *a, Type *t)
249 {
250         Node *n;
251
252         switch(a->op) {
253         case ODOTDOT:
254                 n = a->left;
255                 if(n && n->type && sametype(n->type, t))
256                         return 1;
257         case OSTRING:
258         case OLSTRING:
259         case OCONST:
260         case OINIT:
261         case OELEM:
262                 return 0;
263         }
264
265         n = new(ODOTDOT, Z, Z);
266         *n = *a;
267
268         /*
269          * ODOTDOT is a flag for tcom
270          * a second tcom will not be performed
271          */
272         a->op = ODOTDOT;
273         a->left = n;
274         a->right = Z;
275
276         if(tcom(n))
277                 return 0;
278
279         if(sametype(n->type, t))
280                 return 1;
281         return 0;
282 }
283
284 Node*
285 init1(Sym *s, Type *t, long o, int exflag)
286 {
287         Node *a, *l, *r, nod;
288         Type *t1;
289         long e, w, so, mw;
290
291         a = peekinit();
292         if(a == Z)
293                 return Z;
294
295         if(debug['i']) {
296                 print("t = %T; o = %ld; n = %s\n", t, o, s->name);
297                 prtree(a, "init1 value");
298         }
299
300         if(exflag && a->op == OINIT)
301                 return doinit(s, t, o, nextinit());
302
303         switch(t->etype) {
304         default:
305                 diag(Z, "unknown type in initialization: %T to: %s", t, s->name);
306                 return Z;
307
308         case TCHAR:
309         case TUCHAR:
310         case TINT:
311         case TUINT:
312         case TSHORT:
313         case TUSHORT:
314         case TLONG:
315         case TULONG:
316         case TVLONG:
317         case TUVLONG:
318         case TFLOAT:
319         case TDOUBLE:
320         case TIND:
321         single:
322                 if(a->op == OARRAY || a->op == OELEM)
323                         return Z;
324
325                 a = nextinit();
326                 if(a == Z)
327                         return Z;
328
329                 if(t->nbits)
330                         diag(Z, "cannot initialize bitfields");
331                 if(s->class == CAUTO) {
332                         l = new(ONAME, Z, Z);
333                         l->sym = s;
334                         l->type = t;
335                         l->etype = TVOID;
336                         if(s->type)
337                                 l->etype = s->type->etype;
338                         l->xoffset = s->offset + o;
339                         l->class = s->class;
340
341                         l = new(OASI, l, a);
342                         return l;
343                 }
344
345                 complex(a);
346                 if(a->type == T)
347                         return Z;
348
349                 if(a->op == OCONST) {
350                         if(vconst(a) && t->etype == TIND && a->type && a->type->etype != TIND){
351                                 diag(a, "initialize pointer to an integer: %s", s->name);
352                                 return Z;
353                         }
354                         if(!sametype(a->type, t)) {
355                                 /* hoop jumping to save malloc */
356                                 if(nodcast == Z)
357                                         nodcast = new(OCAST, Z, Z);
358                                 nod = *nodcast;
359                                 nod.left = a;
360                                 nod.type = t;
361                                 nod.lineno = a->lineno;
362                                 complex(&nod);
363                                 if(nod.type)
364                                         *a = nod;
365                         }
366                         if(a->op != OCONST) {
367                                 diag(a, "initializer is not a constant: %s",
368                                         s->name);
369                                 return Z;
370                         }
371                         if(vconst(a) == 0)
372                                 return Z;
373                         goto gext;
374                 }
375                 if(t->etype == TIND) {
376                         while(a->op == OCAST) {
377                                 warn(a, "CAST in initialization ignored");
378                                 a = a->left;
379                         }
380                         if(!sametype(t, a->type)) {
381                                 diag(a, "initialization of incompatible pointers: %s\n%T and %T",
382                                         s->name, t, a->type);
383                         }
384                         if(a->op == OADDR)
385                                 a = a->left;
386                         goto gext;
387                 }
388
389                 while(a->op == OCAST)
390                         a = a->left;
391                 if(a->op == OADDR) {
392                         warn(a, "initialize pointer to an integer: %s", s->name);
393                         a = a->left;
394                         goto gext;
395                 }
396                 diag(a, "initializer is not a constant: %s", s->name);
397                 return Z;
398
399         gext:
400                 gextern(s, a, o, t->width);
401
402                 return Z;
403
404         case TARRAY:
405                 w = t->link->width;
406                 if(a->op == OSTRING || a->op == OLSTRING)
407                 if(typei[t->link->etype]) {
408                         /*
409                          * get rid of null if sizes match exactly
410                          */
411                         a = nextinit();
412                         mw = t->width/w;
413                         so = a->type->width/a->type->link->width;
414                         if(mw && so > mw) {
415                                 if(so != mw+1)
416                                         diag(a, "string initialization larger than array");
417                                 a->type->width -= a->type->link->width;
418                         }
419
420                         /*
421                          * arrange strings to be expanded
422                          * inside OINIT braces.
423                          */
424                         a = new(OUSED, a, Z);
425                         return doinit(s, t, o, a);
426                 }
427
428                 mw = -w;
429                 l = Z;
430                 for(e=0;;) {
431                         /*
432                          * peek ahead for element initializer
433                          */
434                         a = peekinit();
435                         if(a == Z)
436                                 break;
437                         if(a->op == OELEM && t->link->etype != TSTRUCT)
438                                 break;
439                         if(a->op == OARRAY) {
440                                 if(e && exflag)
441                                         break;
442                                 a = nextinit();
443                                 r = a->left;
444                                 complex(r);
445                                 if(r->op != OCONST) {
446                                         diag(r, "initializer subscript must be constant");
447                                         return Z;
448                                 }
449                                 e = r->vconst;
450                                 if(t->width != 0)
451                                         if(e < 0 || e*w >= t->width) {
452                                                 diag(a, "initialization index out of range: %ld", e);
453                                                 continue;
454                                         }
455                         }
456
457                         so = e*w;
458                         if(so > mw)
459                                 mw = so;
460                         if(t->width != 0)
461                                 if(mw >= t->width)
462                                         break;
463                         r = init1(s, t->link, o+so, 1);
464                         l = newlist(l, r);
465                         e++;
466                 }
467                 if(t->width == 0)
468                         t->width = mw+w;
469                 return l;
470
471         case TUNION:
472         case TSTRUCT:
473                 /*
474                  * peek ahead to find type of rhs.
475                  * if its a structure, then treat
476                  * this element as a variable
477                  * rather than an aggregate.
478                  */
479                 if(isstruct(a, t))
480                         goto single;
481
482                 if(t->width <= 0) {
483                         diag(Z, "incomplete structure: %s", s->name);
484                         return Z;
485                 }
486                 l = Z;
487
488         again:
489                 for(t1 = t->link; t1 != T; t1 = t1->down) {
490                         if(a->op == OARRAY && t1->etype != TARRAY)
491                                 break;
492                         if(a->op == OELEM) {
493                                 if(t1->sym != a->sym)
494                                         continue;
495                                 nextinit();
496                         }
497                         r = init1(s, t1, o+t1->offset, 1);
498                         l = newlist(l, r);
499                         a = peekinit();
500                         if(a == Z)
501                                 break;
502                         if(a->op == OELEM)
503                                 goto again;
504                 }
505                 if(a && a->op == OELEM)
506                         diag(a, "structure element not found %F", a);
507                 return l;
508         }
509 }
510
511 Node*
512 newlist(Node *l, Node *r)
513 {
514         if(r == Z)
515                 return l;
516         if(l == Z)
517                 return r;
518         return new(OLIST, l, r);
519 }
520
521 void
522 sualign(Type *t)
523 {
524         Type *l;
525         long o, w;
526
527         o = 0;
528         switch(t->etype) {
529
530         case TSTRUCT:
531                 t->offset = 0;
532                 w = 0;
533                 for(l = t->link; l != T; l = l->down) {
534                         if(l->nbits) {
535                                 if(l->shift <= 0) {
536                                         l->shift = -l->shift;
537                                         w = round(w, tfield->width);
538                                         o = w;
539                                         w += tfield->width;
540                                 }
541                                 l->offset = o;
542                         } else {
543                                 if(l->width < 0 ||
544                                    l->width == 0 && l->down != T)
545                                         if(l->sym)
546                                                 diag(Z, "incomplete structure element: %s",
547                                                         l->sym->name);
548                                         else
549                                                 diag(Z, "incomplete structure element");
550                                 w = align(w, l, Ael1);
551                                 l->offset = w;
552                                 w = align(w, l, Ael2);
553                         }
554                 }
555                 w = align(w, t, Asu2);
556                 t->width = w;
557                 acidtype(t);
558                 pickletype(t);
559                 return;
560
561         case TUNION:
562                 t->offset = 0;
563                 w = 0;
564                 for(l = t->link; l != T; l = l->down) {
565                         if(l->width <= 0)
566                                 if(l->sym)
567                                         diag(Z, "incomplete union element: %s",
568                                                 l->sym->name);
569                                 else
570                                         diag(Z, "incomplete union element");
571                         l->offset = 0;
572                         l->shift = 0;
573                         o = align(align(0, l, Ael1), l, Ael2);
574                         if(o > w)
575                                 w = o;
576                 }
577                 w = align(w, t, Asu2);
578                 t->width = w;
579                 acidtype(t);
580                 pickletype(t);
581                 return;
582
583         default:
584                 diag(Z, "unknown type in sualign: %T", t);
585                 break;
586         }
587 }
588
589 long
590 round(long v, int w)
591 {
592         int r;
593
594         if(w <= 0 || w > 8) {
595                 diag(Z, "rounding by %d", w);
596                 w = 1;
597         }
598         r = v%w;
599         if(r)
600                 v += w-r;
601         return v;
602 }
603
604 Type*
605 ofnproto(Node *n)
606 {
607         Type *tl, *tr, *t;
608
609         if(n == Z)
610                 return T;
611         switch(n->op) {
612         case OLIST:
613                 tl = ofnproto(n->left);
614                 tr = ofnproto(n->right);
615                 if(tl == T)
616                         return tr;
617                 tl->down = tr;
618                 return tl;
619
620         case ONAME:
621                 t = copytyp(n->sym->type);
622                 t->down = T;
623                 return t;
624         }
625         return T;
626 }
627
628 #define ANSIPROTO       1
629 #define OLDPROTO        2
630
631 void
632 argmark(Node *n, int pass)
633 {
634         Type *t;
635
636         autoffset = align(0, thisfn->link, Aarg0);
637         stkoff = 0;
638         for(; n->left != Z; n = n->left) {
639                 if(n->op != OFUNC || n->left->op != ONAME)
640                         continue;
641                 walkparam(n->right, pass);
642                 if(pass != 0 && anyproto(n->right) == OLDPROTO) {
643                         t = typ(TFUNC, n->left->sym->type->link);
644                         t->down = typ(TOLD, T);
645                         t->down->down = ofnproto(n->right);
646                         tmerge(t, n->left->sym);
647                         n->left->sym->type = t;
648                 }
649                 break;
650         }
651         autoffset = 0;
652         stkoff = 0;
653 }
654
655 void
656 walkparam(Node *n, int pass)
657 {
658         Sym *s;
659         Node *n1;
660
661         if(n != Z && n->op == OPROTO && n->left == Z && n->type == types[TVOID])
662                 return;
663
664 loop:
665         if(n == Z)
666                 return;
667         switch(n->op) {
668         default:
669                 diag(n, "argument not a name/prototype: %O", n->op);
670                 break;
671
672         case OLIST:
673                 walkparam(n->left, pass);
674                 n = n->right;
675                 goto loop;
676
677         case OPROTO:
678                 for(n1 = n; n1 != Z; n1=n1->left)
679                         if(n1->op == ONAME) {
680                                 if(pass == 0) {
681                                         s = n1->sym;
682                                         push1(s);
683                                         s->offset = -1;
684                                         break;
685                                 }
686                                 dodecl(pdecl, CPARAM, n->type, n->left);
687                                 break;
688                         }
689                 if(n1)
690                         break;
691                 if(pass == 0) {
692                         /*
693                          * extension:
694                          *      allow no name in argument declaration
695                         diag(Z, "no name in argument declaration");
696                          */
697                         break;
698                 }
699                 dodecl(NODECL, CPARAM, n->type, n->left);
700                 pdecl(CPARAM, lastdcl, S);
701                 break;
702
703         case ODOTDOT:
704                 break;
705         
706         case ONAME:
707                 s = n->sym;
708                 if(pass == 0) {
709                         push1(s);
710                         s->offset = -1;
711                         break;
712                 }
713                 if(s->offset != -1) {
714                         if(autoffset == 0) {
715                                 firstarg = s;
716                                 firstargtype = s->type;
717                         }
718                         autoffset = align(autoffset, s->type, Aarg1);
719                         s->offset = autoffset;
720                         autoffset = align(autoffset, s->type, Aarg2);
721                 } else
722                         dodecl(pdecl, CXXX, types[TINT], n);
723                 break;
724         }
725 }
726
727 void
728 markdcl(void)
729 {
730         Decl *d;
731
732         blockno++;
733         d = push();
734         d->val = DMARK;
735         d->offset = autoffset;
736         d->block = autobn;
737         autobn = blockno;
738 }
739
740 Node*
741 revertdcl(void)
742 {
743         Decl *d;
744         Sym *s;
745         Node *n, *n1;
746
747         n = Z;
748         for(;;) {
749                 d = dclstack;
750                 if(d == D) {
751                         diag(Z, "pop off dcl stack");
752                         break;
753                 }
754                 dclstack = d->link;
755                 s = d->sym;
756                 switch(d->val) {
757                 case DMARK:
758                         autoffset = d->offset;
759                         autobn = d->block;
760                         return n;
761
762                 case DAUTO:
763                         if(debug['d'])
764                                 print("revert1 \"%s\"\n", s->name);
765                         if(s->aused == 0) {
766                                 nearln = s->varlineno;
767                                 if(s->class == CAUTO)
768                                         warn(Z, "auto declared and not used: %s", s->name);
769                                 if(s->class == CPARAM)
770                                         warn(Z, "param declared and not used: %s", s->name);
771                         }
772                         if(s->type && (s->type->garb & GVOLATILE)) {
773                                 n1 = new(ONAME, Z, Z);
774                                 n1->sym = s;
775                                 n1->type = s->type;
776                                 n1->etype = TVOID;
777                                 if(n1->type != T)
778                                         n1->etype = n1->type->etype;
779                                 n1->xoffset = s->offset;
780                                 n1->class = s->class;
781
782                                 n1 = new(OADDR, n1, Z);
783                                 n1 = new(OUSED, n1, Z);
784                                 if(n == Z)
785                                         n = n1;
786                                 else
787                                         n = new(OLIST, n1, n);
788                         }
789                         s->type = d->type;
790                         s->class = d->class;
791                         s->offset = d->offset;
792                         s->block = d->block;
793                         s->varlineno = d->varlineno;
794                         s->aused = d->aused;
795                         break;
796
797                 case DSUE:
798                         if(debug['d'])
799                                 print("revert2 \"%s\"\n", s->name);
800                         s->suetag = d->type;
801                         s->sueblock = d->block;
802                         break;
803
804                 case DLABEL:
805                         if(debug['d'])
806                                 print("revert3 \"%s\"\n", s->name);
807                         if(s->label && s->label->addable == 0)
808                                 warn(s->label, "label declared and not used \"%s\"", s->name);
809                         s->label = Z;
810                         break;
811                 }
812         }
813         return n;
814 }
815
816 Type*
817 fnproto(Node *n)
818 {
819         int r;
820
821         r = anyproto(n->right);
822         if(r == 0 || (r & OLDPROTO)) {
823                 if(r & ANSIPROTO)
824                         diag(n, "mixed ansi/old function declaration: %F", n->left);
825                 return T;
826         }
827         return fnproto1(n->right);
828 }
829
830 int
831 anyproto(Node *n)
832 {
833         int r;
834
835         r = 0;
836
837 loop:
838         if(n == Z)
839                 return r;
840         switch(n->op) {
841         case OLIST:
842                 r |= anyproto(n->left);
843                 n = n->right;
844                 goto loop;
845
846         case ODOTDOT:
847         case OPROTO:
848                 return r | ANSIPROTO;
849         }
850         return r | OLDPROTO;
851 }
852
853 Type*
854 fnproto1(Node *n)
855 {
856         Type *t;
857
858         if(n == Z)
859                 return T;
860         switch(n->op) {
861         case OLIST:
862                 t = fnproto1(n->left);
863                 if(t != T)
864                         t->down = fnproto1(n->right);
865                 return t;
866
867         case OPROTO:
868                 lastdcl = T;
869                 dodecl(NODECL, CXXX, n->type, n->left);
870                 t = typ(TXXX, T);
871                 if(lastdcl != T)
872                         *t = *paramconv(lastdcl, 1);
873                 return t;
874
875         case ONAME:
876                 diag(n, "incomplete argument prototype");
877                 return typ(TINT, T);
878
879         case ODOTDOT:
880                 return typ(TDOT, T);
881         }
882         diag(n, "unknown op in fnproto");
883         return T;
884 }
885
886 void
887 dbgdecl(Sym *s)
888 {
889         print("decl \"%s\": C=%s [B=%d:O=%ld] T=%T\n",
890                 s->name, cnames[s->class], s->block, s->offset, s->type);
891 }
892
893 Decl*
894 push(void)
895 {
896         Decl *d;
897
898         d = alloc(sizeof(*d));
899         d->link = dclstack;
900         dclstack = d;
901         return d;
902 }
903
904 Decl*
905 push1(Sym *s)
906 {
907         Decl *d;
908
909         d = push();
910         d->sym = s;
911         d->val = DAUTO;
912         d->type = s->type;
913         d->class = s->class;
914         d->offset = s->offset;
915         d->block = s->block;
916         d->varlineno = s->varlineno;
917         d->aused = s->aused;
918         return d;
919 }
920
921 int
922 sametype(Type *t1, Type *t2)
923 {
924
925         if(t1 == t2)
926                 return 1;
927         return rsametype(t1, t2, 5, 1);
928 }
929
930 int
931 rsametype(Type *t1, Type *t2, int n, int f)
932 {
933         int et;
934
935         n--;
936         for(;;) {
937                 if(t1 == t2)
938                         return 1;
939                 if(t1 == T || t2 == T)
940                         return 0;
941                 if(n <= 0)
942                         return 1;
943                 et = t1->etype;
944                 if(et != t2->etype)
945                         return 0;
946                 if(et == TFUNC) {
947                         if(!rsametype(t1->link, t2->link, n, 0))
948                                 return 0;
949                         t1 = t1->down;
950                         t2 = t2->down;
951                         while(t1 != T && t2 != T) {
952                                 if(t1->etype == TOLD) {
953                                         t1 = t1->down;
954                                         continue;
955                                 }
956                                 if(t2->etype == TOLD) {
957                                         t2 = t2->down;
958                                         continue;
959                                 }
960                                 while(t1 != T || t2 != T) {
961                                         if(!rsametype(t1, t2, n, 0))
962                                                 return 0;
963                                         t1 = t1->down;
964                                         t2 = t2->down;
965                                 }
966                                 break;
967                         }
968                         return 1;
969                 }
970                 if(et == TARRAY)
971                         if(t1->width != t2->width && t1->width != 0 && t2->width != 0)
972                                 return 0;
973                 if(typesu[et]) {
974                         if(t1->link == T)
975                                 snap(t1);
976                         if(t2->link == T)
977                                 snap(t2);
978                         if(t1 != t2 && t1->link == T && t2->link == T){
979                                 /* structs with missing or different tag names aren't considered equal */
980                                 if(t1->tag == nil || t2->tag == nil ||
981                                    strcmp(t1->tag->name, t2->tag->name) != 0)
982                                         return 0;
983                         }
984                         t1 = t1->link;
985                         t2 = t2->link;
986                         for(;;) {
987                                 if(t1 == t2)
988                                         return 1;
989                                 if(!rsametype(t1, t2, n, 0))
990                                         return 0;
991                                 t1 = t1->down;
992                                 t2 = t2->down;
993                         }
994                 }
995                 t1 = t1->link;
996                 t2 = t2->link;
997                 if((f || !debug['V']) && et == TIND) {
998                         if(t1 != T && t1->etype == TVOID)
999                                 return 1;
1000                         if(t2 != T && t2->etype == TVOID)
1001                                 return 1;
1002                 }
1003         }
1004 }
1005
1006 typedef struct Typetab Typetab;
1007
1008 struct Typetab{
1009         int n;
1010         Type **a;
1011 };
1012
1013 static int
1014 sigind(Type *t, Typetab *tt)
1015 {
1016         int n;
1017         Type **a, **na, **p, **e;
1018
1019         n = tt->n;
1020         a = tt->a;
1021         e = a+n;
1022         /* linear search seems ok */
1023         for(p = a ; p < e; p++)
1024                 if(sametype(*p, t))
1025                         return p-a;
1026         if((n&15) == 0){
1027                 na = malloc((n+16)*sizeof(Type*));
1028                 memmove(na, a, n*sizeof(Type*));
1029                 free(a);
1030                 a = tt->a = na;
1031         }
1032         a[tt->n++] = t;
1033         return -1;
1034 }
1035
1036 static ulong
1037 signat(Type *t, Typetab *tt)
1038 {
1039         int i;
1040         Type *t1;
1041         long s;
1042
1043         s = 0;
1044         for(; t; t=t->link) {
1045                 s = s*thash1 + thash[t->etype];
1046                 if(t->garb&GINCOMPLETE)
1047                         return s;
1048                 switch(t->etype) {
1049                 default:
1050                         return s;
1051                 case TARRAY:
1052                         s = s*thash2 + 0;       /* was t->width */
1053                         break;
1054                 case TFUNC:
1055                         for(t1=t->down; t1; t1=t1->down)
1056                                 s = s*thash3 + signat(t1, tt);
1057                         break;
1058                 case TSTRUCT:
1059                 case TUNION:
1060                         if((i = sigind(t, tt)) >= 0){
1061                                 s = s*thash2 + i;
1062                                 return s;
1063                         }
1064                         for(t1=t->link; t1; t1=t1->down)
1065                                 s = s*thash3 + signat(t1, tt);
1066                         return s;
1067                 case TIND:
1068                         break;
1069                 }
1070         }
1071         return s;
1072 }
1073
1074 ulong
1075 signature(Type *t)
1076 {
1077         ulong s;
1078         Typetab tt;
1079
1080         tt.n = 0;
1081         tt.a = nil;
1082         s = signat(t, &tt);
1083         free(tt.a);
1084         return s;
1085 }
1086
1087 ulong
1088 sign(Sym *s)
1089 {
1090         ulong v;
1091         Type *t;
1092
1093         if(s->sig == SIGINTERN)
1094                 return SIGNINTERN;
1095         if((t = s->type) == T)
1096                 return 0;
1097         v = signature(t);
1098         if(v == 0)
1099                 v = SIGNINTERN;
1100         return v;
1101 }
1102
1103 void
1104 snap(Type *t)
1105 {
1106         if(typesu[t->etype])
1107         if(t->link == T && t->tag && t->tag->suetag) {
1108                 t->link = t->tag->suetag->link;
1109                 t->width = t->tag->suetag->width;
1110         }
1111 }
1112
1113 Type*
1114 dotag(Sym *s, int et, int bn)
1115 {
1116         Decl *d;
1117
1118         if(bn != 0 && bn != s->sueblock) {
1119                 d = push();
1120                 d->sym = s;
1121                 d->val = DSUE;
1122                 d->type = s->suetag;
1123                 d->block = s->sueblock;
1124                 s->suetag = T;
1125         }
1126         if(s->suetag == T) {
1127                 s->suetag = typ(et, T);
1128                 s->sueblock = autobn;
1129         }
1130         if(s->suetag->etype != et)
1131                 diag(Z, "tag used for more than one type: %s",
1132                         s->name);
1133         if(s->suetag->tag == S)
1134                 s->suetag->tag = s;
1135         return s->suetag;
1136 }
1137
1138 Node*
1139 dcllabel(Sym *s, int f)
1140 {
1141         Decl *d, d1;
1142         Node *n;
1143
1144         n = s->label;
1145         if(n != Z) {
1146                 if(f) {
1147                         if(n->complex)
1148                                 diag(Z, "label reused: %s", s->name);
1149                         n->complex = 1; // declared
1150                 } else
1151                         n->addable = 1; // used
1152                 return n;
1153         }
1154
1155         d = push();
1156         d->sym = s;
1157         d->val = DLABEL;
1158         dclstack = d->link;
1159
1160         d1 = *firstdcl;
1161         *firstdcl = *d;
1162         *d = d1;
1163
1164         firstdcl->link = d;
1165         firstdcl = d;
1166
1167         n = new(OXXX, Z, Z);
1168         n->sym = s;
1169         n->complex = f;
1170         n->addable = !f;
1171         s->label = n;
1172
1173         if(debug['d'])
1174                 dbgdecl(s);
1175         return n;
1176 }
1177
1178 Type*
1179 paramconv(Type *t, int f)
1180 {
1181
1182         switch(t->etype) {
1183         case TARRAY:
1184                 t = typ(TIND, t->link);
1185                 t->width = types[TIND]->width;
1186                 break;
1187
1188         case TFUNC:
1189                 t = typ(TIND, t);
1190                 t->width = types[TIND]->width;
1191                 break;
1192
1193         case TFLOAT:
1194                 if(!f)
1195                         t = types[TDOUBLE];
1196                 break;
1197
1198         case TCHAR:
1199         case TSHORT:
1200                 if(!f)
1201                         t = types[TINT];
1202                 break;
1203
1204         case TUCHAR:
1205         case TUSHORT:
1206                 if(!f)
1207                         t = types[TUINT];
1208                 break;
1209         }
1210         return t;
1211 }
1212
1213 void
1214 adecl(int c, Type *t, Sym *s)
1215 {
1216
1217         if(c == CSTATIC)
1218                 c = CLOCAL;
1219         if(t->etype == TFUNC) {
1220                 if(c == CXXX)
1221                         c = CEXTERN;
1222                 if(c == CLOCAL)
1223                         c = CSTATIC;
1224                 if(c == CAUTO || c == CEXREG)
1225                         diag(Z, "function cannot be %s %s", cnames[c], s->name);
1226         }
1227         if(c == CXXX)
1228                 c = CAUTO;
1229         if(s) {
1230                 if(s->class == CSTATIC)
1231                         if(c == CEXTERN || c == CGLOBL) {
1232                                 warn(Z, "just say static: %s", s->name);
1233                                 c = CSTATIC;
1234                         }
1235                 if(s->class == CAUTO || s->class == CPARAM || s->class == CLOCAL)
1236                 if(s->block == autobn)
1237                         diag(Z, "auto redeclaration of: %s", s->name);
1238                 if(c != CPARAM)
1239                         push1(s);
1240                 s->block = autobn;
1241                 s->offset = 0;
1242                 s->type = t;
1243                 s->class = c;
1244                 s->aused = 0;
1245         }
1246         switch(c) {
1247         case CAUTO:
1248                 autoffset = align(autoffset, t, Aaut3);
1249                 stkoff = maxround(stkoff, autoffset);
1250                 s->offset = -autoffset;
1251                 break;
1252
1253         case CPARAM:
1254                 if(autoffset == 0) {
1255                         firstarg = s;
1256                         firstargtype = t;
1257                 }
1258                 autoffset = align(autoffset, t, Aarg1);
1259                 if(s)
1260                         s->offset = autoffset;
1261                 autoffset = align(autoffset, t, Aarg2);
1262                 break;
1263         }
1264 }
1265
1266 void
1267 pdecl(int c, Type *t, Sym *s)
1268 {
1269         if(s && s->offset != -1) {
1270                 diag(Z, "not a parameter: %s", s->name);
1271                 return;
1272         }
1273         t = paramconv(t, c==CPARAM);
1274         if(c == CXXX)
1275                 c = CPARAM;
1276         if(c != CPARAM) {
1277                 diag(Z, "parameter cannot have class: %s", s->name);
1278                 c = CPARAM;
1279         }
1280         if(typesu[t->etype] && t->width <= 0)
1281                 diag(Z, "incomplete structure: %s", t->tag->name);
1282         adecl(c, t, s);
1283 }
1284
1285 void
1286 xdecl(int c, Type *t, Sym *s)
1287 {
1288         long o;
1289
1290         o = 0;
1291         switch(c) {
1292         case CEXREG:
1293                 o = exreg(t);
1294                 if(o == 0)
1295                         c = CEXTERN;
1296                 if(s->class == CGLOBL)
1297                         c = CGLOBL;
1298                 break;
1299
1300         case CEXTERN:
1301                 if(s->class == CGLOBL)
1302                         c = CGLOBL;
1303                 break;
1304
1305         case CXXX:
1306                 c = CGLOBL;
1307                 if(s->class == CEXTERN)
1308                         s->class = CGLOBL;
1309                 break;
1310
1311         case CAUTO:
1312                 diag(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]);
1313                 c = CEXTERN;
1314                 break;
1315
1316         case CTYPESTR:
1317                 if(!typesuv[t->etype]) {
1318                         diag(Z, "typestr must be struct/union: %s", s->name);
1319                         break;
1320                 }
1321                 dclfunct(t, s);
1322                 break;
1323         }
1324
1325         if(s->class == CSTATIC)
1326                 if(c == CEXTERN || c == CGLOBL) {
1327                         warn(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]);
1328                         c = CSTATIC;
1329                 }
1330         if(s->type != T)
1331                 if(s->class != c || !sametype(t, s->type) || t->etype == TENUM) {
1332                         diag(Z, "external redeclaration of: %s", s->name);
1333                         Bprint(&diagbuf, "      %s %T %L\n", cnames[c], t, nearln);
1334                         Bprint(&diagbuf, "      %s %T %L\n", cnames[s->class], s->type, s->varlineno);
1335                 }
1336         tmerge(t, s);
1337         s->type = t;
1338         s->class = c;
1339         s->block = 0;
1340         s->offset = o;
1341 }
1342
1343 void
1344 tmerge(Type *t1, Sym *s)
1345 {
1346         Type *ta, *tb, *t2;
1347
1348         t2 = s->type;
1349 /*print("merge  %T; %T\n", t1, t2);/**/
1350         for(;;) {
1351                 if(t1 == T || t2 == T || t1 == t2)
1352                         break;
1353                 if(t1->etype != t2->etype)
1354                         break;
1355                 switch(t1->etype) {
1356                 case TFUNC:
1357                         ta = t1->down;
1358                         tb = t2->down;
1359                         if(ta == T) {
1360                                 t1->down = tb;
1361                                 break;
1362                         }
1363                         if(tb == T)
1364                                 break;
1365                         while(ta != T && tb != T) {
1366                                 if(ta == tb)
1367                                         break;
1368                                 /* ignore old-style flag */
1369                                 if(ta->etype == TOLD) {
1370                                         ta = ta->down;
1371                                         continue;
1372                                 }
1373                                 if(tb->etype == TOLD) {
1374                                         tb = tb->down;
1375                                         continue;
1376                                 }
1377                                 /* checking terminated by ... */
1378                                 if(ta->etype == TDOT && tb->etype == TDOT) {
1379                                         ta = T;
1380                                         tb = T;
1381                                         break;
1382                                 }
1383                                 if(!sametype(ta, tb))
1384                                         break;
1385                                 ta = ta->down;
1386                                 tb = tb->down;
1387                         }
1388                         if(ta != tb)
1389                                 diag(Z, "function inconsistently declared: %s", s->name);
1390
1391                         /* take new-style over old-style */
1392                         ta = t1->down;
1393                         tb = t2->down;
1394                         if(ta != T && ta->etype == TOLD)
1395                                 if(tb != T && tb->etype != TOLD)
1396                                         t1->down = tb;
1397                         break;
1398
1399                 case TARRAY:
1400                         /* should we check array size change? */
1401                         if(t2->width > t1->width)
1402                                 t1->width = t2->width;
1403                         break;
1404
1405                 case TUNION:
1406                 case TSTRUCT:
1407                         return;
1408                 }
1409                 t1 = t1->link;
1410                 t2 = t2->link;
1411         }
1412 }
1413
1414 void
1415 edecl(int c, Type *t, Sym *s)
1416 {
1417         Type *t1;
1418
1419         if(s == S) {
1420                 if(!typesu[t->etype])
1421                         diag(Z, "unnamed structure element must be struct/union");
1422                 if(c != CXXX)
1423                         diag(Z, "unnamed structure element cannot have class");
1424         } else
1425                 if(c != CXXX)
1426                         diag(Z, "structure element cannot have class: %s", s->name);
1427         t1 = t;
1428         t = copytyp(t1);
1429         t->sym = s;
1430         t->down = T;
1431         if(lastfield) {
1432                 t->shift = lastbit - lastfield;
1433                 t->nbits = lastfield;
1434                 if(firstbit)
1435                         t->shift = -t->shift;
1436                 if(typeu[t->etype])
1437                         t->etype = tufield->etype;
1438                 else
1439                         t->etype = tfield->etype;
1440         }
1441         if(strf == T)
1442                 strf = t;
1443         else
1444                 strl->down = t;
1445         strl = t;
1446 }
1447
1448 /*
1449  * this routine is very suspect.
1450  * ansi requires the enum type to
1451  * be represented as an 'int'
1452  * this means that 0x81234567
1453  * would be illegal. this routine
1454  * makes signed and unsigned go
1455  * to unsigned.
1456  */
1457 Type*
1458 maxtype(Type *t1, Type *t2)
1459 {
1460
1461         if(t1 == T)
1462                 return t2;
1463         if(t2 == T)
1464                 return t1;
1465         if(t1->etype > t2->etype)
1466                 return t1;
1467         return t2;
1468 }
1469
1470 void
1471 doenum(Sym *s, Node *n)
1472 {
1473
1474         if(n) {
1475                 complex(n);
1476                 if(n->op != OCONST) {
1477                         diag(n, "enum not a constant: %s", s->name);
1478                         return;
1479                 }
1480                 en.cenum = n->type;
1481                 en.tenum = maxtype(en.cenum, en.tenum);
1482
1483                 if(!typefd[en.cenum->etype])
1484                         en.lastenum = n->vconst;
1485                 else
1486                         en.floatenum = n->fconst;
1487         }
1488         if(dclstack)
1489                 push1(s);
1490         xdecl(CXXX, types[TENUM], s);
1491
1492         if(en.cenum == T) {
1493                 en.tenum = types[TINT];
1494                 en.cenum = types[TINT];
1495                 en.lastenum = 0;
1496         }
1497         s->tenum = en.cenum;
1498
1499         if(!typefd[s->tenum->etype]) {
1500                 s->vconst = convvtox(en.lastenum, s->tenum->etype);
1501                 en.lastenum++;
1502         } else {
1503                 s->fconst = en.floatenum;
1504                 en.floatenum++;
1505         }
1506
1507         if(debug['d'])
1508                 dbgdecl(s);
1509         acidvar(s);
1510 }
1511
1512 void
1513 symadjust(Sym *s, Node *n, long del)
1514 {
1515
1516         switch(n->op) {
1517         default:
1518                 if(n->left)
1519                         symadjust(s, n->left, del);
1520                 if(n->right)
1521                         symadjust(s, n->right, del);
1522                 return;
1523
1524         case ONAME:
1525                 if(n->sym == s)
1526                         n->xoffset -= del;
1527                 return;
1528
1529         case OCONST:
1530         case OSTRING:
1531         case OLSTRING:
1532         case OINDREG:
1533         case OREGISTER:
1534                 return;
1535         }
1536 }
1537
1538 Node*
1539 contig(Sym *s, Node *n, long v)
1540 {
1541         Node *p, *r, *q, *m;
1542         long w;
1543         Type *zt;
1544
1545         if(debug['i']) {
1546                 print("contig v = %ld; s = %s\n", v, s->name);
1547                 prtree(n, "doinit value");
1548         }
1549
1550         if(n == Z)
1551                 goto no;
1552         w = s->type->width;
1553
1554         /*
1555          * nightmare: an automatic array whose size
1556          * increases when it is initialized
1557          */
1558         if(v != w) {
1559                 if(v != 0)
1560                         diag(n, "automatic adjustable array: %s", s->name);
1561                 v = s->offset;
1562                 autoffset = align(autoffset, s->type, Aaut3);
1563                 s->offset = -autoffset;
1564                 stkoff = maxround(stkoff, autoffset);
1565                 symadjust(s, n, v - s->offset);
1566         }
1567         if(w <= ewidth[TIND])
1568                 goto no;
1569         if(n->op == OAS)
1570                 diag(Z, "oops in contig");
1571 /*ZZZ this appears incorrect
1572 need to check if the list completely covers the data.
1573 if not, bail
1574  */
1575         if(n->op == OLIST)
1576                 goto no;
1577         if(n->op == OASI)
1578                 if(n->left->type)
1579                 if(n->left->type->width == w)
1580                         goto no;
1581         while(w & (ewidth[TIND]-1))
1582                 w++;
1583 /*
1584  * insert the following code, where long becomes vlong if pointers are fat
1585  *
1586         *(long**)&X = (long*)((char*)X + sizeof(X));
1587         do {
1588                 *(long**)&X -= 1;
1589                 **(long**)&X = 0;
1590         } while(*(long**)&X);
1591  */
1592
1593         for(q=n; q->op != ONAME; q=q->left)
1594                 ;
1595
1596         zt = ewidth[TIND] > ewidth[TLONG]? types[TVLONG]: types[TLONG];
1597
1598         p = new(ONAME, Z, Z);
1599         *p = *q;
1600         p->type = typ(TIND, zt);
1601         p->xoffset = s->offset;
1602
1603         r = new(ONAME, Z, Z);
1604         *r = *p;
1605         r = new(OPOSTDEC, r, Z);
1606
1607         q = new(ONAME, Z, Z);
1608         *q = *p;
1609         q = new(OIND, q, Z);
1610
1611         m = new(OCONST, Z, Z);
1612         m->vconst = 0;
1613         m->type = zt;
1614
1615         q = new(OAS, q, m);
1616
1617         r = new(OLIST, r, q);
1618
1619         q = new(ONAME, Z, Z);
1620         *q = *p;
1621         r = new(ODWHILE, q, r);
1622
1623         q = new(ONAME, Z, Z);
1624         *q = *p;
1625         q->type = q->type->link;
1626         q->xoffset += w;
1627         q = new(OADDR, q, 0);
1628
1629         q = new(OASI, p, q);
1630         r = new(OLIST, q, r);
1631
1632         n = new(OLIST, r, n);
1633
1634 no:
1635         return n;
1636 }