13e12c5d1SDavid du Colombier #include "cc.h" 23e12c5d1SDavid du Colombier 33e12c5d1SDavid du Colombier Node* 43e12c5d1SDavid du Colombier dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n) 53e12c5d1SDavid du Colombier { 63e12c5d1SDavid du Colombier Sym *s; 73e12c5d1SDavid du Colombier Node *n1; 83e12c5d1SDavid du Colombier long v; 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier nearln = lineno; 113e12c5d1SDavid du Colombier lastfield = 0; 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier loop: 143e12c5d1SDavid du Colombier if(n != Z) 153e12c5d1SDavid du Colombier switch(n->op) { 163e12c5d1SDavid du Colombier default: 173e12c5d1SDavid du Colombier diag(n, "unknown declarator: %O", n->op); 183e12c5d1SDavid du Colombier break; 193e12c5d1SDavid du Colombier 203e12c5d1SDavid du Colombier case OARRAY: 213e12c5d1SDavid du Colombier t = typ(TARRAY, t); 223e12c5d1SDavid du Colombier t->width = 0; 233e12c5d1SDavid du Colombier n1 = n->right; 243e12c5d1SDavid du Colombier n = n->left; 253e12c5d1SDavid du Colombier if(n1 != Z) { 263e12c5d1SDavid du Colombier complex(n1); 273e12c5d1SDavid du Colombier v = -1; 283e12c5d1SDavid du Colombier if(n1->op == OCONST) 29*219b2ee8SDavid du Colombier v = n1->vconst; 303e12c5d1SDavid du Colombier if(v <= 0) { 313e12c5d1SDavid du Colombier diag(n, "array size must be a positive constant"); 323e12c5d1SDavid du Colombier v = 1; 333e12c5d1SDavid du Colombier } 343e12c5d1SDavid du Colombier t->width = v * t->link->width; 353e12c5d1SDavid du Colombier } 363e12c5d1SDavid du Colombier goto loop; 373e12c5d1SDavid du Colombier 383e12c5d1SDavid du Colombier case OIND: 393e12c5d1SDavid du Colombier t = typ(TIND, t); 403e12c5d1SDavid du Colombier n = n->left; 413e12c5d1SDavid du Colombier goto loop; 423e12c5d1SDavid du Colombier 433e12c5d1SDavid du Colombier case OFUNC: 443e12c5d1SDavid du Colombier t = typ(TFUNC, t); 453e12c5d1SDavid du Colombier t->down = fnproto(n); 463e12c5d1SDavid du Colombier n = n->left; 473e12c5d1SDavid du Colombier goto loop; 483e12c5d1SDavid du Colombier 493e12c5d1SDavid du Colombier case OBIT: 503e12c5d1SDavid du Colombier n1 = n->right; 513e12c5d1SDavid du Colombier complex(n1); 523e12c5d1SDavid du Colombier lastfield = -1; 533e12c5d1SDavid du Colombier if(n1->op == OCONST) 54*219b2ee8SDavid du Colombier lastfield = n1->vconst; 553e12c5d1SDavid du Colombier if(lastfield < 0) { 563e12c5d1SDavid du Colombier diag(n, "field width must be non-negative constant"); 573e12c5d1SDavid du Colombier lastfield = 1; 583e12c5d1SDavid du Colombier } 593e12c5d1SDavid du Colombier if(lastfield == 0) { 603e12c5d1SDavid du Colombier lastbit = 0; 613e12c5d1SDavid du Colombier firstbit = 1; 623e12c5d1SDavid du Colombier if(n->left != Z) { 633e12c5d1SDavid du Colombier diag(n, "zero width named field"); 643e12c5d1SDavid du Colombier lastfield = 1; 653e12c5d1SDavid du Colombier } 663e12c5d1SDavid du Colombier } 67*219b2ee8SDavid du Colombier if(!typei[t->etype]) { 683e12c5d1SDavid du Colombier diag(n, "field type must be int-like"); 693e12c5d1SDavid du Colombier t = tint; 703e12c5d1SDavid du Colombier lastfield = 1; 713e12c5d1SDavid du Colombier } 723e12c5d1SDavid du Colombier if(lastfield > tfield->width*8) { 733e12c5d1SDavid du Colombier diag(n, "field width larger than field unit"); 743e12c5d1SDavid du Colombier lastfield = 1; 753e12c5d1SDavid du Colombier } 763e12c5d1SDavid du Colombier lastbit += lastfield; 773e12c5d1SDavid du Colombier if(lastbit > tfield->width*8) { 783e12c5d1SDavid du Colombier lastbit = lastfield; 793e12c5d1SDavid du Colombier firstbit = 1; 803e12c5d1SDavid du Colombier } 813e12c5d1SDavid du Colombier n = n->left; 823e12c5d1SDavid du Colombier goto loop; 833e12c5d1SDavid du Colombier 843e12c5d1SDavid du Colombier case ONAME: 853e12c5d1SDavid du Colombier if(f == NODECL) 863e12c5d1SDavid du Colombier break; 873e12c5d1SDavid du Colombier s = n->sym; 883e12c5d1SDavid du Colombier (*f)(c, t, s); 893e12c5d1SDavid du Colombier if(s->class == CLOCAL) 903e12c5d1SDavid du Colombier s = mkstatic(s); 913e12c5d1SDavid du Colombier firstbit = 0; 923e12c5d1SDavid du Colombier n->sym = s; 933e12c5d1SDavid du Colombier n->type = s->type; 94*219b2ee8SDavid du Colombier n->xoffset = s->offset; 953e12c5d1SDavid du Colombier n->class = s->class; 963e12c5d1SDavid du Colombier n->etype = TVOID; 973e12c5d1SDavid du Colombier if(n->type != T) 983e12c5d1SDavid du Colombier n->etype = n->type->etype; 993e12c5d1SDavid du Colombier if(debug['d']) 1003e12c5d1SDavid du Colombier dbgdecl(s); 101*219b2ee8SDavid du Colombier acidvar(s); 1023e12c5d1SDavid du Colombier s->varlineno = lineno; 1033e12c5d1SDavid du Colombier break; 1043e12c5d1SDavid du Colombier } 1053e12c5d1SDavid du Colombier lastdcl = t; 1063e12c5d1SDavid du Colombier return n; 1073e12c5d1SDavid du Colombier } 1083e12c5d1SDavid du Colombier 1093e12c5d1SDavid du Colombier Sym* 1103e12c5d1SDavid du Colombier mkstatic(Sym *s) 1113e12c5d1SDavid du Colombier { 1123e12c5d1SDavid du Colombier Sym *s1; 1133e12c5d1SDavid du Colombier 1143e12c5d1SDavid du Colombier if(s->class != CLOCAL) 1153e12c5d1SDavid du Colombier return s; 116*219b2ee8SDavid du Colombier snprint(symb, NSYMB, "%s$%d", s->name, s->block); 1173e12c5d1SDavid du Colombier s1 = lookup(); 1183e12c5d1SDavid du Colombier if(s1->class != CSTATIC) { 1193e12c5d1SDavid du Colombier s1->type = s->type; 1203e12c5d1SDavid du Colombier s1->offset = s->offset; 1213e12c5d1SDavid du Colombier s1->block = s->block; 1223e12c5d1SDavid du Colombier s1->class = CSTATIC; 1233e12c5d1SDavid du Colombier } 1243e12c5d1SDavid du Colombier return s1; 1253e12c5d1SDavid du Colombier } 1263e12c5d1SDavid du Colombier 1273e12c5d1SDavid du Colombier /* 1283e12c5d1SDavid du Colombier * make a copy of a typedef 129*219b2ee8SDavid du Colombier * the problem is to split out incomplete 1303e12c5d1SDavid du Colombier * arrays so that it is in the variable 1313e12c5d1SDavid du Colombier * rather than the typedef. 1323e12c5d1SDavid du Colombier */ 1333e12c5d1SDavid du Colombier Type* 1343e12c5d1SDavid du Colombier tcopy(Type *t) 1353e12c5d1SDavid du Colombier { 1363e12c5d1SDavid du Colombier Type *tl, *tx; 1373e12c5d1SDavid du Colombier int et; 1383e12c5d1SDavid du Colombier 1393e12c5d1SDavid du Colombier if(t == T) 1403e12c5d1SDavid du Colombier return t; 1413e12c5d1SDavid du Colombier et = t->etype; 1423e12c5d1SDavid du Colombier if(typesu[et]) 1433e12c5d1SDavid du Colombier return t; 1443e12c5d1SDavid du Colombier tl = tcopy(t->link); 1453e12c5d1SDavid du Colombier if(tl != t->link || 1463e12c5d1SDavid du Colombier (et == TARRAY && t->width == 0)) { 1473e12c5d1SDavid du Colombier tx = typ(TXXX, 0); 1483e12c5d1SDavid du Colombier *tx = *t; 1493e12c5d1SDavid du Colombier tx->link = tl; 1503e12c5d1SDavid du Colombier return tx; 1513e12c5d1SDavid du Colombier } 1523e12c5d1SDavid du Colombier return t; 1533e12c5d1SDavid du Colombier } 1543e12c5d1SDavid du Colombier 1553e12c5d1SDavid du Colombier Node* 1563e12c5d1SDavid du Colombier doinit(Sym *s, Type *t, long o, Node *a) 1573e12c5d1SDavid du Colombier { 1583e12c5d1SDavid du Colombier Node *n; 1593e12c5d1SDavid du Colombier 1603e12c5d1SDavid du Colombier if(t == T) 1613e12c5d1SDavid du Colombier return Z; 1623e12c5d1SDavid du Colombier if(s->class == CEXTERN) { 1633e12c5d1SDavid du Colombier s->class = CGLOBL; 1643e12c5d1SDavid du Colombier if(debug['d']) 1653e12c5d1SDavid du Colombier dbgdecl(s); 1663e12c5d1SDavid du Colombier } 1673e12c5d1SDavid du Colombier if(debug['i']) { 1683e12c5d1SDavid du Colombier print("t = %T; o = %ld; n = %s\n", t, o, s->name); 1693e12c5d1SDavid du Colombier prtree(a, "doinit value"); 1703e12c5d1SDavid du Colombier } 1713e12c5d1SDavid du Colombier 1723e12c5d1SDavid du Colombier 1733e12c5d1SDavid du Colombier n = initlist; 1743e12c5d1SDavid du Colombier if(a->op == OINIT) 1753e12c5d1SDavid du Colombier a = a->left; 1763e12c5d1SDavid du Colombier initlist = a; 1773e12c5d1SDavid du Colombier 1783e12c5d1SDavid du Colombier a = init1(s, t, o, 0); 1793e12c5d1SDavid du Colombier if(initlist != Z) 1803e12c5d1SDavid du Colombier diag(initlist, "more initializers than structure: %s", 1813e12c5d1SDavid du Colombier s->name); 1823e12c5d1SDavid du Colombier initlist = n; 1833e12c5d1SDavid du Colombier 1843e12c5d1SDavid du Colombier return a; 1853e12c5d1SDavid du Colombier } 1863e12c5d1SDavid du Colombier 1873e12c5d1SDavid du Colombier /* 1883e12c5d1SDavid du Colombier * get next major operator, 1893e12c5d1SDavid du Colombier * dont advance initlist. 1903e12c5d1SDavid du Colombier */ 1913e12c5d1SDavid du Colombier Node* 1923e12c5d1SDavid du Colombier peekinit(void) 1933e12c5d1SDavid du Colombier { 1943e12c5d1SDavid du Colombier Node *a; 1953e12c5d1SDavid du Colombier 1963e12c5d1SDavid du Colombier a = initlist; 1973e12c5d1SDavid du Colombier 1983e12c5d1SDavid du Colombier loop: 1993e12c5d1SDavid du Colombier if(a == Z) 2003e12c5d1SDavid du Colombier return a; 2013e12c5d1SDavid du Colombier if(a->op == OLIST) { 2023e12c5d1SDavid du Colombier a = a->left; 2033e12c5d1SDavid du Colombier goto loop; 2043e12c5d1SDavid du Colombier } 2053e12c5d1SDavid du Colombier return a; 2063e12c5d1SDavid du Colombier } 2073e12c5d1SDavid du Colombier 2083e12c5d1SDavid du Colombier /* 2093e12c5d1SDavid du Colombier * consume and return next element on 2103e12c5d1SDavid du Colombier * initlist. expand strings. 2113e12c5d1SDavid du Colombier */ 2123e12c5d1SDavid du Colombier Node* 2133e12c5d1SDavid du Colombier nextinit(void) 2143e12c5d1SDavid du Colombier { 2153e12c5d1SDavid du Colombier Node *a, *b, *n; 2163e12c5d1SDavid du Colombier 2173e12c5d1SDavid du Colombier a = initlist; 2183e12c5d1SDavid du Colombier n = Z; 2193e12c5d1SDavid du Colombier 2203e12c5d1SDavid du Colombier loop: 2213e12c5d1SDavid du Colombier if(a == Z) 2223e12c5d1SDavid du Colombier return a; 2233e12c5d1SDavid du Colombier if(a->op == OLIST) { 2243e12c5d1SDavid du Colombier n = a->right; 2253e12c5d1SDavid du Colombier a = a->left; 2263e12c5d1SDavid du Colombier } 2273e12c5d1SDavid du Colombier if(a->op == OUSED) { 2283e12c5d1SDavid du Colombier a = a->left; 2293e12c5d1SDavid du Colombier b = new(OCONST, Z, Z); 2303e12c5d1SDavid du Colombier b->type = a->type->link; 2313e12c5d1SDavid du Colombier if(a->op == OSTRING) { 232*219b2ee8SDavid du Colombier b->vconst = convvtox(*a->cstring, TCHAR); 233*219b2ee8SDavid du Colombier a->cstring++; 2343e12c5d1SDavid du Colombier } 2353e12c5d1SDavid du Colombier if(a->op == OLSTRING) { 236*219b2ee8SDavid du Colombier b->vconst = convvtox(*a->rstring, TUSHORT); 237*219b2ee8SDavid du Colombier a->rstring++; 2383e12c5d1SDavid du Colombier } 2393e12c5d1SDavid du Colombier a->type->width -= b->type->width; 2403e12c5d1SDavid du Colombier if(a->type->width <= 0) 2413e12c5d1SDavid du Colombier initlist = n; 2423e12c5d1SDavid du Colombier return b; 2433e12c5d1SDavid du Colombier } 2443e12c5d1SDavid du Colombier initlist = n; 2453e12c5d1SDavid du Colombier return a; 2463e12c5d1SDavid du Colombier } 2473e12c5d1SDavid du Colombier 2483e12c5d1SDavid du Colombier int 2493e12c5d1SDavid du Colombier isstruct(Node *a, Type *t) 2503e12c5d1SDavid du Colombier { 2513e12c5d1SDavid du Colombier Node *n; 2523e12c5d1SDavid du Colombier 2533e12c5d1SDavid du Colombier switch(a->op) { 2543e12c5d1SDavid du Colombier case ODOTDOT: 2553e12c5d1SDavid du Colombier n = a->left; 2563e12c5d1SDavid du Colombier if(n && n->type && sametype(n->type, t)) 2573e12c5d1SDavid du Colombier return 1; 2583e12c5d1SDavid du Colombier case OSTRING: 2593e12c5d1SDavid du Colombier case OLSTRING: 2603e12c5d1SDavid du Colombier case OCONST: 2613e12c5d1SDavid du Colombier case OINIT: 262*219b2ee8SDavid du Colombier case OELEM: 2633e12c5d1SDavid du Colombier return 0; 2643e12c5d1SDavid du Colombier } 2653e12c5d1SDavid du Colombier 2663e12c5d1SDavid du Colombier n = new(ODOTDOT, Z, Z); 2673e12c5d1SDavid du Colombier *n = *a; 2683e12c5d1SDavid du Colombier 2693e12c5d1SDavid du Colombier /* 2703e12c5d1SDavid du Colombier * ODOTDOT is a flag for tcom 2713e12c5d1SDavid du Colombier * a second tcom will not be performed 2723e12c5d1SDavid du Colombier */ 2733e12c5d1SDavid du Colombier a->op = ODOTDOT; 2743e12c5d1SDavid du Colombier a->left = n; 2753e12c5d1SDavid du Colombier a->right = Z; 2763e12c5d1SDavid du Colombier 2773e12c5d1SDavid du Colombier if(tcom(n)) 2783e12c5d1SDavid du Colombier return 0; 2793e12c5d1SDavid du Colombier 2803e12c5d1SDavid du Colombier if(sametype(n->type, t)) 2813e12c5d1SDavid du Colombier return 1; 2823e12c5d1SDavid du Colombier return 0; 2833e12c5d1SDavid du Colombier } 2843e12c5d1SDavid du Colombier 2853e12c5d1SDavid du Colombier Node* 2863e12c5d1SDavid du Colombier init1(Sym *s, Type *t, long o, int exflag) 2873e12c5d1SDavid du Colombier { 2883e12c5d1SDavid du Colombier Node *a, *l, *r; 289*219b2ee8SDavid du Colombier Type *t1; 2903e12c5d1SDavid du Colombier long e, w, so, mw; 2913e12c5d1SDavid du Colombier 2923e12c5d1SDavid du Colombier a = peekinit(); 2933e12c5d1SDavid du Colombier if(a == Z) 2943e12c5d1SDavid du Colombier return Z; 2953e12c5d1SDavid du Colombier 2963e12c5d1SDavid du Colombier if(debug['i']) { 2973e12c5d1SDavid du Colombier print("t = %T; o = %ld; n = %s\n", t, o, s->name); 2983e12c5d1SDavid du Colombier prtree(a, "init1 value"); 2993e12c5d1SDavid du Colombier } 3003e12c5d1SDavid du Colombier 3013e12c5d1SDavid du Colombier if(exflag && a->op == OINIT) 3023e12c5d1SDavid du Colombier return doinit(s, t, o, nextinit()); 3033e12c5d1SDavid du Colombier 3043e12c5d1SDavid du Colombier switch(t->etype) { 3053e12c5d1SDavid du Colombier default: 3063e12c5d1SDavid du Colombier diag(Z, "unknown type in initialization: %T to: %s", t, s->name); 3073e12c5d1SDavid du Colombier return Z; 3083e12c5d1SDavid du Colombier 3093e12c5d1SDavid du Colombier case TCHAR: 3103e12c5d1SDavid du Colombier case TUCHAR: 3113e12c5d1SDavid du Colombier case TSHORT: 3123e12c5d1SDavid du Colombier case TUSHORT: 3133e12c5d1SDavid du Colombier case TLONG: 3143e12c5d1SDavid du Colombier case TULONG: 3153e12c5d1SDavid du Colombier case TVLONG: 3163e12c5d1SDavid du Colombier case TFLOAT: 3173e12c5d1SDavid du Colombier case TDOUBLE: 3183e12c5d1SDavid du Colombier case TIND: 3193e12c5d1SDavid du Colombier single: 320*219b2ee8SDavid du Colombier if(a->op == OARRAY || a->op == OELEM) 3213e12c5d1SDavid du Colombier return Z; 3223e12c5d1SDavid du Colombier 3233e12c5d1SDavid du Colombier a = nextinit(); 3243e12c5d1SDavid du Colombier if(a == Z) 3253e12c5d1SDavid du Colombier return Z; 3263e12c5d1SDavid du Colombier 3273e12c5d1SDavid du Colombier if(t->nbits) 3283e12c5d1SDavid du Colombier diag(Z, "cannot initialize bitfields"); 3293e12c5d1SDavid du Colombier if(s->class == CAUTO) { 3303e12c5d1SDavid du Colombier l = new(ONAME, Z, Z); 3313e12c5d1SDavid du Colombier l->sym = s; 3323e12c5d1SDavid du Colombier l->type = t; 3333e12c5d1SDavid du Colombier l->etype = TVOID; 3343e12c5d1SDavid du Colombier if(s->type) 3353e12c5d1SDavid du Colombier l->etype = s->type->etype; 336*219b2ee8SDavid du Colombier l->xoffset = s->offset + o; 3373e12c5d1SDavid du Colombier l->class = s->class; 3383e12c5d1SDavid du Colombier 3393e12c5d1SDavid du Colombier l = new(OAS, l, a); 3403e12c5d1SDavid du Colombier return l; 3413e12c5d1SDavid du Colombier } 3423e12c5d1SDavid du Colombier 3433e12c5d1SDavid du Colombier complex(a); 3443e12c5d1SDavid du Colombier if(a->type == T) 3453e12c5d1SDavid du Colombier return Z; 3463e12c5d1SDavid du Colombier 3473e12c5d1SDavid du Colombier if(a->op == OCONST) { 3483e12c5d1SDavid du Colombier if(!sametype(a->type, t)) { 3493e12c5d1SDavid du Colombier e = a->lineno; 3503e12c5d1SDavid du Colombier a = new(OCAST, a, Z); 3513e12c5d1SDavid du Colombier a->lineno = e; 3523e12c5d1SDavid du Colombier a->type = t; 3533e12c5d1SDavid du Colombier complex(a); 3543e12c5d1SDavid du Colombier } 3553e12c5d1SDavid du Colombier if(a->op != OCONST) { 3563e12c5d1SDavid du Colombier diag(a, "initializer is not a constant: %s", 3573e12c5d1SDavid du Colombier s->name); 3583e12c5d1SDavid du Colombier return Z; 3593e12c5d1SDavid du Colombier } 3603e12c5d1SDavid du Colombier if(vconst(a) == 0) 3613e12c5d1SDavid du Colombier return Z; 3623e12c5d1SDavid du Colombier goto gext; 3633e12c5d1SDavid du Colombier } 3643e12c5d1SDavid du Colombier if(t->etype == TIND) { 3653e12c5d1SDavid du Colombier while(a->op == OCAST) { 3663e12c5d1SDavid du Colombier warn(a, "CAST in initialization ignored"); 3673e12c5d1SDavid du Colombier a = a->left; 3683e12c5d1SDavid du Colombier } 3693e12c5d1SDavid du Colombier if(!sametype(t, a->type)) { 3703e12c5d1SDavid du Colombier diag(a, "initialization of incompatible pointers: %s", 3713e12c5d1SDavid du Colombier s->name); 3723e12c5d1SDavid du Colombier print("%T and %T\n", t, a->type); 3733e12c5d1SDavid du Colombier } 3743e12c5d1SDavid du Colombier if(a->op == OADDR) 3753e12c5d1SDavid du Colombier a = a->left; 3763e12c5d1SDavid du Colombier goto gext; 3773e12c5d1SDavid du Colombier } 378*219b2ee8SDavid du Colombier 3793e12c5d1SDavid du Colombier while(a->op == OCAST) 3803e12c5d1SDavid du Colombier a = a->left; 3813e12c5d1SDavid du Colombier if(a->op == OADDR) { 3823e12c5d1SDavid du Colombier warn(a, "initialize pointer to an integer", s->name); 3833e12c5d1SDavid du Colombier a = a->left; 3843e12c5d1SDavid du Colombier goto gext; 3853e12c5d1SDavid du Colombier } 3863e12c5d1SDavid du Colombier diag(a, "initializer is not a constant: %s", s->name); 3873e12c5d1SDavid du Colombier return Z; 3883e12c5d1SDavid du Colombier 3893e12c5d1SDavid du Colombier gext: 3903e12c5d1SDavid du Colombier gextern(s, a, o, t->width); 3913e12c5d1SDavid du Colombier 3923e12c5d1SDavid du Colombier return Z; 3933e12c5d1SDavid du Colombier 3943e12c5d1SDavid du Colombier case TARRAY: 3953e12c5d1SDavid du Colombier w = t->link->width; 3963e12c5d1SDavid du Colombier if(a->op == OSTRING || a->op == OLSTRING) 397*219b2ee8SDavid du Colombier if(typei[t->link->etype]) { 3983e12c5d1SDavid du Colombier /* 3993e12c5d1SDavid du Colombier * get rid of null if sizes match exactly 4003e12c5d1SDavid du Colombier */ 4013e12c5d1SDavid du Colombier a = nextinit(); 4023e12c5d1SDavid du Colombier mw = t->width/w; 4033e12c5d1SDavid du Colombier so = a->type->width/a->type->link->width; 4043e12c5d1SDavid du Colombier if(mw && so > mw) { 4053e12c5d1SDavid du Colombier if(so != mw+1) 4063e12c5d1SDavid du Colombier diag(a, "string initialization larger than array"); 4073e12c5d1SDavid du Colombier a->type->width -= a->type->link->width; 4083e12c5d1SDavid du Colombier } 4093e12c5d1SDavid du Colombier 4103e12c5d1SDavid du Colombier /* 4113e12c5d1SDavid du Colombier * arrange strings to be expanded 4123e12c5d1SDavid du Colombier * inside OINIT braces. 4133e12c5d1SDavid du Colombier */ 4143e12c5d1SDavid du Colombier a = new(OUSED, a, Z); 4153e12c5d1SDavid du Colombier return doinit(s, t, o, a); 4163e12c5d1SDavid du Colombier } 4173e12c5d1SDavid du Colombier 4183e12c5d1SDavid du Colombier mw = -w; 4193e12c5d1SDavid du Colombier l = Z; 4203e12c5d1SDavid du Colombier for(e=0;;) { 4213e12c5d1SDavid du Colombier /* 4223e12c5d1SDavid du Colombier * peek ahead for element initializer 4233e12c5d1SDavid du Colombier */ 4243e12c5d1SDavid du Colombier a = peekinit(); 4253e12c5d1SDavid du Colombier if(a == Z) 4263e12c5d1SDavid du Colombier break; 427*219b2ee8SDavid du Colombier if(a->op == OELEM && t->link->etype != TSTRUCT) 428*219b2ee8SDavid du Colombier break; 4293e12c5d1SDavid du Colombier if(a->op == OARRAY) { 4303e12c5d1SDavid du Colombier a = nextinit(); 4313e12c5d1SDavid du Colombier r = a->left; 4323e12c5d1SDavid du Colombier complex(r); 4333e12c5d1SDavid du Colombier if(r->op != OCONST) { 4343e12c5d1SDavid du Colombier diag(r, "initializer subscript must be constant"); 4353e12c5d1SDavid du Colombier return Z; 4363e12c5d1SDavid du Colombier } 437*219b2ee8SDavid du Colombier e = r->vconst; 4383e12c5d1SDavid du Colombier if(t->width != 0) 4393e12c5d1SDavid du Colombier if(e < 0 || e*w >= t->width) { 4403e12c5d1SDavid du Colombier diag(a, "initilization index out of range: %ld", e); 4413e12c5d1SDavid du Colombier e = 0; 4423e12c5d1SDavid du Colombier } 4433e12c5d1SDavid du Colombier continue; 4443e12c5d1SDavid du Colombier } 4453e12c5d1SDavid du Colombier 4463e12c5d1SDavid du Colombier so = e*w; 4473e12c5d1SDavid du Colombier if(so > mw) 4483e12c5d1SDavid du Colombier mw = so; 4493e12c5d1SDavid du Colombier if(t->width != 0) 4503e12c5d1SDavid du Colombier if(mw >= t->width) 4513e12c5d1SDavid du Colombier break; 4523e12c5d1SDavid du Colombier r = init1(s, t->link, o+so, 1); 4533e12c5d1SDavid du Colombier l = newlist(l, r); 4543e12c5d1SDavid du Colombier e++; 4553e12c5d1SDavid du Colombier } 4563e12c5d1SDavid du Colombier if(t->width == 0) 4573e12c5d1SDavid du Colombier t->width = mw+w; 4583e12c5d1SDavid du Colombier return l; 4593e12c5d1SDavid du Colombier 4603e12c5d1SDavid du Colombier case TUNION: 4613e12c5d1SDavid du Colombier case TSTRUCT: 4623e12c5d1SDavid du Colombier /* 4633e12c5d1SDavid du Colombier * peek ahead to find type of rhs. 4643e12c5d1SDavid du Colombier * if its a structure, then treat 4653e12c5d1SDavid du Colombier * this element as a variable 4663e12c5d1SDavid du Colombier * rather than an aggregate. 4673e12c5d1SDavid du Colombier */ 4683e12c5d1SDavid du Colombier if(isstruct(a, t)) 4693e12c5d1SDavid du Colombier goto single; 4703e12c5d1SDavid du Colombier 4713e12c5d1SDavid du Colombier if(t->width <= 0) { 4723e12c5d1SDavid du Colombier diag(Z, "incomplete structure: %s", s->name); 4733e12c5d1SDavid du Colombier return Z; 4743e12c5d1SDavid du Colombier } 4753e12c5d1SDavid du Colombier l = Z; 476*219b2ee8SDavid du Colombier 477*219b2ee8SDavid du Colombier again: 478*219b2ee8SDavid du Colombier for(t1 = t->link; t1 != T; t1 = t1->down) { 479*219b2ee8SDavid du Colombier if(a->op == OARRAY && t1->etype != TARRAY) 480*219b2ee8SDavid du Colombier break; 481*219b2ee8SDavid du Colombier if(a->op == OELEM) { 482*219b2ee8SDavid du Colombier if(t1->sym != a->sym) 483*219b2ee8SDavid du Colombier continue; 484*219b2ee8SDavid du Colombier nextinit(); 485*219b2ee8SDavid du Colombier } 486*219b2ee8SDavid du Colombier r = init1(s, t1, o+t1->offset, 1); 487*219b2ee8SDavid du Colombier l = newlist(l, r); 4883e12c5d1SDavid du Colombier a = peekinit(); 4893e12c5d1SDavid du Colombier if(a == Z) 4903e12c5d1SDavid du Colombier break; 491*219b2ee8SDavid du Colombier if(a->op == OELEM) 492*219b2ee8SDavid du Colombier goto again; 4933e12c5d1SDavid du Colombier } 494*219b2ee8SDavid du Colombier if(a && a->op == OELEM) 495*219b2ee8SDavid du Colombier diag(a, "structure element not found %F", a); 4963e12c5d1SDavid du Colombier return l; 4973e12c5d1SDavid du Colombier } 4983e12c5d1SDavid du Colombier } 4993e12c5d1SDavid du Colombier 5003e12c5d1SDavid du Colombier Node* 5013e12c5d1SDavid du Colombier newlist(Node *l, Node *r) 5023e12c5d1SDavid du Colombier { 5033e12c5d1SDavid du Colombier if(r == Z) 5043e12c5d1SDavid du Colombier return l; 5053e12c5d1SDavid du Colombier if(l == Z) 5063e12c5d1SDavid du Colombier return r; 5073e12c5d1SDavid du Colombier return new(OLIST, l, r); 5083e12c5d1SDavid du Colombier } 5093e12c5d1SDavid du Colombier 5103e12c5d1SDavid du Colombier void 5113e12c5d1SDavid du Colombier suallign(Type *t) 5123e12c5d1SDavid du Colombier { 5133e12c5d1SDavid du Colombier Type *l; 5143e12c5d1SDavid du Colombier long o, w; 5153e12c5d1SDavid du Colombier 5163e12c5d1SDavid du Colombier o = 0; 5173e12c5d1SDavid du Colombier switch(t->etype) { 5183e12c5d1SDavid du Colombier 5193e12c5d1SDavid du Colombier case TSTRUCT: 5203e12c5d1SDavid du Colombier t->offset = 0; 5213e12c5d1SDavid du Colombier w = 0; 5223e12c5d1SDavid du Colombier for(l = t->link; l != T; l = l->down) { 5233e12c5d1SDavid du Colombier if(l->nbits) { 5243e12c5d1SDavid du Colombier if(l->shift <= 0) { 5253e12c5d1SDavid du Colombier l->shift = -l->shift; 5263e12c5d1SDavid du Colombier w += round(w, tfield->width); 5273e12c5d1SDavid du Colombier o = w; 5283e12c5d1SDavid du Colombier w += tfield->width; 5293e12c5d1SDavid du Colombier } 5303e12c5d1SDavid du Colombier l->offset = o; 5313e12c5d1SDavid du Colombier } else { 5323e12c5d1SDavid du Colombier if(l->width <= 0) 5333e12c5d1SDavid du Colombier if(l->sym) 5343e12c5d1SDavid du Colombier diag(Z, "incomplete structure element: %s", 5353e12c5d1SDavid du Colombier l->sym->name); 5363e12c5d1SDavid du Colombier else 5373e12c5d1SDavid du Colombier diag(Z, "incomplete structure element"); 5383e12c5d1SDavid du Colombier w += round(w, allign(l)); 5393e12c5d1SDavid du Colombier l->offset = w; 5403e12c5d1SDavid du Colombier w += l->width; 5413e12c5d1SDavid du Colombier } 5423e12c5d1SDavid du Colombier } 5433e12c5d1SDavid du Colombier w += round(w, supad); 5443e12c5d1SDavid du Colombier t->width = w; 545*219b2ee8SDavid du Colombier acidtype(t); 5463e12c5d1SDavid du Colombier return; 5473e12c5d1SDavid du Colombier 5483e12c5d1SDavid du Colombier case TUNION: 5493e12c5d1SDavid du Colombier t->offset = 0; 5503e12c5d1SDavid du Colombier w = 0; 5513e12c5d1SDavid du Colombier for(l = t->link; l != T; l = l->down) { 5523e12c5d1SDavid du Colombier if(l->width <= 0) 5533e12c5d1SDavid du Colombier if(l->sym) 5543e12c5d1SDavid du Colombier diag(Z, "incomplete union element: %s", 5553e12c5d1SDavid du Colombier l->sym->name); 5563e12c5d1SDavid du Colombier else 5573e12c5d1SDavid du Colombier diag(Z, "incomplete union element"); 5583e12c5d1SDavid du Colombier l->offset = 0; 5593e12c5d1SDavid du Colombier l->shift = 0; 5603e12c5d1SDavid du Colombier if(l->width > w) 5613e12c5d1SDavid du Colombier w = l->width; 5623e12c5d1SDavid du Colombier } 5633e12c5d1SDavid du Colombier w += round(w, supad); 5643e12c5d1SDavid du Colombier t->width = w; 565*219b2ee8SDavid du Colombier acidtype(t); 5663e12c5d1SDavid du Colombier return; 5673e12c5d1SDavid du Colombier 5683e12c5d1SDavid du Colombier default: 5693e12c5d1SDavid du Colombier diag(Z, "unknown type in suallign: %T", t); 5703e12c5d1SDavid du Colombier break; 5713e12c5d1SDavid du Colombier } 5723e12c5d1SDavid du Colombier } 5733e12c5d1SDavid du Colombier 5743e12c5d1SDavid du Colombier int 5753e12c5d1SDavid du Colombier allign(Type *t) 5763e12c5d1SDavid du Colombier { 5773e12c5d1SDavid du Colombier int w; 5783e12c5d1SDavid du Colombier 5793e12c5d1SDavid du Colombier while(t->etype == TARRAY) 5803e12c5d1SDavid du Colombier t = t->link; 5813e12c5d1SDavid du Colombier w = ewidth[t->etype]; 5823e12c5d1SDavid du Colombier if(w <= 0 || w > suround) 5833e12c5d1SDavid du Colombier w = suround; 5843e12c5d1SDavid du Colombier return w; 5853e12c5d1SDavid du Colombier } 5863e12c5d1SDavid du Colombier 5873e12c5d1SDavid du Colombier int 5883e12c5d1SDavid du Colombier round(long v, long w) 5893e12c5d1SDavid du Colombier { 5903e12c5d1SDavid du Colombier int r; 5913e12c5d1SDavid du Colombier 5923e12c5d1SDavid du Colombier if(w <= 0) { 5933e12c5d1SDavid du Colombier diag(Z, "rounding by %d", w); 5943e12c5d1SDavid du Colombier w = 1; 5953e12c5d1SDavid du Colombier } 596*219b2ee8SDavid du Colombier if(w > types[TVLONG]->width) 597*219b2ee8SDavid du Colombier w = types[TVLONG]->width; 5983e12c5d1SDavid du Colombier r = v%w; 5993e12c5d1SDavid du Colombier if(r) 6003e12c5d1SDavid du Colombier r = w-r; 6013e12c5d1SDavid du Colombier return r; 6023e12c5d1SDavid du Colombier } 6033e12c5d1SDavid du Colombier 6043e12c5d1SDavid du Colombier Type* 6053e12c5d1SDavid du Colombier ofnproto(Node *n) 6063e12c5d1SDavid du Colombier { 6073e12c5d1SDavid du Colombier Type *tl, *tr, *t; 6083e12c5d1SDavid du Colombier 6093e12c5d1SDavid du Colombier loop: 6103e12c5d1SDavid du Colombier if(n == Z) 6113e12c5d1SDavid du Colombier return T; 6123e12c5d1SDavid du Colombier switch(n->op) { 6133e12c5d1SDavid du Colombier case OLIST: 6143e12c5d1SDavid du Colombier tl = ofnproto(n->left); 6153e12c5d1SDavid du Colombier tr = ofnproto(n->right); 6163e12c5d1SDavid du Colombier if(tl == T) 6173e12c5d1SDavid du Colombier return tr; 6183e12c5d1SDavid du Colombier tl->down = tr; 6193e12c5d1SDavid du Colombier return tl; 6203e12c5d1SDavid du Colombier 6213e12c5d1SDavid du Colombier case ONAME: 6223e12c5d1SDavid du Colombier t = typ(TXXX, T); 6233e12c5d1SDavid du Colombier *t = *n->sym->type; 6243e12c5d1SDavid du Colombier t->down = T; 6253e12c5d1SDavid du Colombier return t; 6263e12c5d1SDavid du Colombier } 6273e12c5d1SDavid du Colombier return T; 6283e12c5d1SDavid du Colombier } 6293e12c5d1SDavid du Colombier 6303e12c5d1SDavid du Colombier #define ANSIPROTO 1 6313e12c5d1SDavid du Colombier #define OLDPROTO 2 6323e12c5d1SDavid du Colombier 6333e12c5d1SDavid du Colombier void 6343e12c5d1SDavid du Colombier argmark(Node *n, int pass) 6353e12c5d1SDavid du Colombier { 6363e12c5d1SDavid du Colombier Type *t; 6373e12c5d1SDavid du Colombier 6383e12c5d1SDavid du Colombier autoffset = 0; 639*219b2ee8SDavid du Colombier if(passbypointer(thisfn->link->etype)) { 6403e12c5d1SDavid du Colombier autoffset += types[TIND]->width; 6413e12c5d1SDavid du Colombier autoffset += round(autoffset, tint->width); 6423e12c5d1SDavid du Colombier } 6433e12c5d1SDavid du Colombier stkoff = 0; 6443e12c5d1SDavid du Colombier for(; n->left != Z; n = n->left) { 6453e12c5d1SDavid du Colombier if(n->op != OFUNC || n->left->op != ONAME) 6463e12c5d1SDavid du Colombier continue; 6473e12c5d1SDavid du Colombier walkparam(n->right, pass); 6483e12c5d1SDavid du Colombier if(pass != 0 && anyproto(n->right) == OLDPROTO) { 6493e12c5d1SDavid du Colombier t = typ(TFUNC, n->left->sym->type->link); 6503e12c5d1SDavid du Colombier t->down = typ(TOLD, T); 6513e12c5d1SDavid du Colombier t->down->down = ofnproto(n->right); 6523e12c5d1SDavid du Colombier tmerge(t, n->left->sym); 6533e12c5d1SDavid du Colombier n->left->sym->type = t; 6543e12c5d1SDavid du Colombier } 6553e12c5d1SDavid du Colombier break; 6563e12c5d1SDavid du Colombier } 6573e12c5d1SDavid du Colombier autoffset = 0; 6583e12c5d1SDavid du Colombier stkoff = 0; 6593e12c5d1SDavid du Colombier } 6603e12c5d1SDavid du Colombier 6613e12c5d1SDavid du Colombier void 6623e12c5d1SDavid du Colombier walkparam(Node *n, int pass) 6633e12c5d1SDavid du Colombier { 6643e12c5d1SDavid du Colombier Sym *s; 665*219b2ee8SDavid du Colombier Node *n1; 6663e12c5d1SDavid du Colombier 6673e12c5d1SDavid du Colombier if(n != Z && n->op == OPROTO && n->left == Z && n->type == types[TVOID]) 6683e12c5d1SDavid du Colombier return; 6693e12c5d1SDavid du Colombier 6703e12c5d1SDavid du Colombier loop: 6713e12c5d1SDavid du Colombier if(n == Z) 6723e12c5d1SDavid du Colombier return; 6733e12c5d1SDavid du Colombier switch(n->op) { 6743e12c5d1SDavid du Colombier default: 6753e12c5d1SDavid du Colombier diag(n, "argument not a name/prototype: %O", n->op); 6763e12c5d1SDavid du Colombier break; 6773e12c5d1SDavid du Colombier 6783e12c5d1SDavid du Colombier case OLIST: 6793e12c5d1SDavid du Colombier walkparam(n->left, pass); 6803e12c5d1SDavid du Colombier n = n->right; 6813e12c5d1SDavid du Colombier goto loop; 6823e12c5d1SDavid du Colombier 6833e12c5d1SDavid du Colombier case OPROTO: 684*219b2ee8SDavid du Colombier for(n1 = n; n1 != Z; n1=n1->left) 685*219b2ee8SDavid du Colombier if(n1->op == ONAME) { 6863e12c5d1SDavid du Colombier if(pass == 0) { 687*219b2ee8SDavid du Colombier s = n1->sym; 6883e12c5d1SDavid du Colombier push1(s); 6893e12c5d1SDavid du Colombier s->offset = -1; 6903e12c5d1SDavid du Colombier break; 6913e12c5d1SDavid du Colombier } 692*219b2ee8SDavid du Colombier dodecl(pdecl, CPARAM, n->type, n->left); 6933e12c5d1SDavid du Colombier break; 6943e12c5d1SDavid du Colombier } 695*219b2ee8SDavid du Colombier if(n1) 696*219b2ee8SDavid du Colombier break; 697*219b2ee8SDavid du Colombier if(pass == 0) { 698*219b2ee8SDavid du Colombier /* 699*219b2ee8SDavid du Colombier * extension: 700*219b2ee8SDavid du Colombier * allow no name in argument declaration 701*219b2ee8SDavid du Colombier diag(Z, "no name in argument declaration"); 702*219b2ee8SDavid du Colombier */ 703*219b2ee8SDavid du Colombier break; 704*219b2ee8SDavid du Colombier } 705*219b2ee8SDavid du Colombier dodecl(NODECL, CPARAM, n->type, n->left); 706*219b2ee8SDavid du Colombier pdecl(CPARAM, lastdcl, S); 7073e12c5d1SDavid du Colombier break; 7083e12c5d1SDavid du Colombier 7093e12c5d1SDavid du Colombier case ODOTDOT: 7103e12c5d1SDavid du Colombier break; 7113e12c5d1SDavid du Colombier 7123e12c5d1SDavid du Colombier case ONAME: 7133e12c5d1SDavid du Colombier s = n->sym; 7143e12c5d1SDavid du Colombier if(pass == 0) { 7153e12c5d1SDavid du Colombier push1(s); 7163e12c5d1SDavid du Colombier s->offset = -1; 7173e12c5d1SDavid du Colombier break; 7183e12c5d1SDavid du Colombier } 7193e12c5d1SDavid du Colombier if(s->offset != -1) { 7203e12c5d1SDavid du Colombier if(autoffset == 0) { 7213e12c5d1SDavid du Colombier firstarg = s; 7223e12c5d1SDavid du Colombier firstargtype = s->type; 7233e12c5d1SDavid du Colombier } 7243e12c5d1SDavid du Colombier s->offset = autoffset; 7253e12c5d1SDavid du Colombier autoffset += s->type->width; 7263e12c5d1SDavid du Colombier autoffset += round(autoffset, tint->width); 7273e12c5d1SDavid du Colombier } else 7283e12c5d1SDavid du Colombier dodecl(pdecl, CXXX, tint, n); 7293e12c5d1SDavid du Colombier break; 7303e12c5d1SDavid du Colombier } 7313e12c5d1SDavid du Colombier } 7323e12c5d1SDavid du Colombier 7333e12c5d1SDavid du Colombier void 7343e12c5d1SDavid du Colombier markdcl(void) 7353e12c5d1SDavid du Colombier { 7363e12c5d1SDavid du Colombier Decl *d; 7373e12c5d1SDavid du Colombier 7383e12c5d1SDavid du Colombier blockno++; 7393e12c5d1SDavid du Colombier d = push(); 7403e12c5d1SDavid du Colombier d->val = DMARK; 7413e12c5d1SDavid du Colombier d->offset = autoffset; 7423e12c5d1SDavid du Colombier d->block = autobn; 7433e12c5d1SDavid du Colombier autobn = blockno; 7443e12c5d1SDavid du Colombier } 7453e12c5d1SDavid du Colombier 7463e12c5d1SDavid du Colombier void 7473e12c5d1SDavid du Colombier revertdcl(void) 7483e12c5d1SDavid du Colombier { 7493e12c5d1SDavid du Colombier Decl *d; 7503e12c5d1SDavid du Colombier Sym *s; 7513e12c5d1SDavid du Colombier 7523e12c5d1SDavid du Colombier for(;;) { 7533e12c5d1SDavid du Colombier d = dclstack; 7543e12c5d1SDavid du Colombier if(d == D) { 7553e12c5d1SDavid du Colombier diag(Z, "pop off dcl stack"); 7563e12c5d1SDavid du Colombier break; 7573e12c5d1SDavid du Colombier } 7583e12c5d1SDavid du Colombier dclstack = d->link; 7593e12c5d1SDavid du Colombier s = d->sym; 7603e12c5d1SDavid du Colombier switch(d->val) { 7613e12c5d1SDavid du Colombier case DMARK: 7623e12c5d1SDavid du Colombier autoffset = d->offset; 7633e12c5d1SDavid du Colombier autobn = d->block; 7643e12c5d1SDavid du Colombier return; 7653e12c5d1SDavid du Colombier 7663e12c5d1SDavid du Colombier case DAUTO: 7673e12c5d1SDavid du Colombier if(debug['d']) 7683e12c5d1SDavid du Colombier print("revert1 \"%s\"\n", s->name); 7693e12c5d1SDavid du Colombier if(s->aused == 0) { 7703e12c5d1SDavid du Colombier nearln = s->varlineno; 7713e12c5d1SDavid du Colombier if(s->class == CAUTO) 7723e12c5d1SDavid du Colombier warn(Z, "auto declared and not used: %s", s->name); 7733e12c5d1SDavid du Colombier if(s->class == CPARAM) 7743e12c5d1SDavid du Colombier warn(Z, "param declared and not used: %s", s->name); 7753e12c5d1SDavid du Colombier } 7763e12c5d1SDavid du Colombier s->type = d->type; 7773e12c5d1SDavid du Colombier s->class = d->class; 7783e12c5d1SDavid du Colombier s->offset = d->offset; 7793e12c5d1SDavid du Colombier s->block = d->block; 7803e12c5d1SDavid du Colombier s->varlineno = d->varlineno; 7813e12c5d1SDavid du Colombier s->aused = d->aused; 7823e12c5d1SDavid du Colombier break; 7833e12c5d1SDavid du Colombier 7843e12c5d1SDavid du Colombier case DSUE: 7853e12c5d1SDavid du Colombier if(debug['d']) 7863e12c5d1SDavid du Colombier print("revert2 \"%s\"\n", s->name); 7873e12c5d1SDavid du Colombier s->suetag = d->type; 7883e12c5d1SDavid du Colombier s->sueblock = d->block; 7893e12c5d1SDavid du Colombier break; 7903e12c5d1SDavid du Colombier 7913e12c5d1SDavid du Colombier case DLABEL: 7923e12c5d1SDavid du Colombier if(debug['d']) 7933e12c5d1SDavid du Colombier print("revert3 \"%s\"\n", s->name); 7943e12c5d1SDavid du Colombier s->label = Z; 7953e12c5d1SDavid du Colombier break; 7963e12c5d1SDavid du Colombier } 7973e12c5d1SDavid du Colombier } 7983e12c5d1SDavid du Colombier } 7993e12c5d1SDavid du Colombier 8003e12c5d1SDavid du Colombier Type* 8013e12c5d1SDavid du Colombier fnproto(Node *n) 8023e12c5d1SDavid du Colombier { 8033e12c5d1SDavid du Colombier int r; 8043e12c5d1SDavid du Colombier 8053e12c5d1SDavid du Colombier r = anyproto(n->right); 8063e12c5d1SDavid du Colombier if(r == 0 || (r & OLDPROTO)) { 8073e12c5d1SDavid du Colombier if(r & ANSIPROTO) 8083e12c5d1SDavid du Colombier diag(n, "mixed ansi/old function declaration: %F", n->left); 8093e12c5d1SDavid du Colombier return T; 8103e12c5d1SDavid du Colombier } 8113e12c5d1SDavid du Colombier return fnproto1(n->right); 8123e12c5d1SDavid du Colombier } 8133e12c5d1SDavid du Colombier 8143e12c5d1SDavid du Colombier int 8153e12c5d1SDavid du Colombier anyproto(Node *n) 8163e12c5d1SDavid du Colombier { 8173e12c5d1SDavid du Colombier int r; 8183e12c5d1SDavid du Colombier 8193e12c5d1SDavid du Colombier r = 0; 8203e12c5d1SDavid du Colombier 8213e12c5d1SDavid du Colombier loop: 8223e12c5d1SDavid du Colombier if(n == Z) 8233e12c5d1SDavid du Colombier return r; 8243e12c5d1SDavid du Colombier switch(n->op) { 8253e12c5d1SDavid du Colombier case OLIST: 8263e12c5d1SDavid du Colombier r |= anyproto(n->left); 8273e12c5d1SDavid du Colombier n = n->right; 8283e12c5d1SDavid du Colombier goto loop; 8293e12c5d1SDavid du Colombier 8303e12c5d1SDavid du Colombier case ODOTDOT: 8313e12c5d1SDavid du Colombier case OPROTO: 8323e12c5d1SDavid du Colombier return r | ANSIPROTO; 8333e12c5d1SDavid du Colombier } 8343e12c5d1SDavid du Colombier return r | OLDPROTO; 8353e12c5d1SDavid du Colombier } 8363e12c5d1SDavid du Colombier 8373e12c5d1SDavid du Colombier Type* 8383e12c5d1SDavid du Colombier fnproto1(Node *n) 8393e12c5d1SDavid du Colombier { 8403e12c5d1SDavid du Colombier Type *t; 8413e12c5d1SDavid du Colombier 8423e12c5d1SDavid du Colombier if(n == Z) 8433e12c5d1SDavid du Colombier return T; 8443e12c5d1SDavid du Colombier switch(n->op) { 8453e12c5d1SDavid du Colombier case OLIST: 8463e12c5d1SDavid du Colombier t = fnproto1(n->left); 8473e12c5d1SDavid du Colombier if(t != T) 8483e12c5d1SDavid du Colombier t->down = fnproto1(n->right); 8493e12c5d1SDavid du Colombier return t; 8503e12c5d1SDavid du Colombier 8513e12c5d1SDavid du Colombier case OPROTO: 8523e12c5d1SDavid du Colombier lastdcl = T; 8533e12c5d1SDavid du Colombier dodecl(NODECL, CXXX, n->type, n->left); 8543e12c5d1SDavid du Colombier t = typ(TXXX, T); 8553e12c5d1SDavid du Colombier if(lastdcl != T) 8563e12c5d1SDavid du Colombier *t = *paramconv(lastdcl, 1); 8573e12c5d1SDavid du Colombier return t; 8583e12c5d1SDavid du Colombier 8593e12c5d1SDavid du Colombier case ONAME: 8603e12c5d1SDavid du Colombier diag(n, "incomplete argument prototype"); 8613e12c5d1SDavid du Colombier return typ(tint->etype, T); 8623e12c5d1SDavid du Colombier 8633e12c5d1SDavid du Colombier case ODOTDOT: 8643e12c5d1SDavid du Colombier return typ(TDOT, T); 8653e12c5d1SDavid du Colombier } 8663e12c5d1SDavid du Colombier diag(n, "unknown op in fnproto"); 8673e12c5d1SDavid du Colombier return T; 8683e12c5d1SDavid du Colombier } 8693e12c5d1SDavid du Colombier 8703e12c5d1SDavid du Colombier void 8713e12c5d1SDavid du Colombier dbgdecl(Sym *s) 8723e12c5d1SDavid du Colombier { 8733e12c5d1SDavid du Colombier 8743e12c5d1SDavid du Colombier if(s->class == CAUTO) 875*219b2ee8SDavid du Colombier print("decl \"%s\": %s [%d:%ld] %T", 876*219b2ee8SDavid du Colombier s->name, cnames[s->class], s->block, s->offset, s->type); 877*219b2ee8SDavid du Colombier else 878*219b2ee8SDavid du Colombier print("decl \"%s\": %s [%d] %T\n", 879*219b2ee8SDavid du Colombier s->name, cnames[s->class], s->block, s->type); 8803e12c5d1SDavid du Colombier } 8813e12c5d1SDavid du Colombier 8823e12c5d1SDavid du Colombier Decl* 8833e12c5d1SDavid du Colombier push(void) 8843e12c5d1SDavid du Colombier { 8853e12c5d1SDavid du Colombier Decl *d; 8863e12c5d1SDavid du Colombier 8873e12c5d1SDavid du Colombier ALLOC(d, Decl); 8883e12c5d1SDavid du Colombier d->link = dclstack; 8893e12c5d1SDavid du Colombier dclstack = d; 8903e12c5d1SDavid du Colombier return d; 8913e12c5d1SDavid du Colombier } 8923e12c5d1SDavid du Colombier 8933e12c5d1SDavid du Colombier Decl* 8943e12c5d1SDavid du Colombier push1(Sym *s) 8953e12c5d1SDavid du Colombier { 8963e12c5d1SDavid du Colombier Decl *d; 8973e12c5d1SDavid du Colombier 8983e12c5d1SDavid du Colombier d = push(); 8993e12c5d1SDavid du Colombier d->sym = s; 9003e12c5d1SDavid du Colombier d->val = DAUTO; 9013e12c5d1SDavid du Colombier d->type = s->type; 9023e12c5d1SDavid du Colombier d->class = s->class; 9033e12c5d1SDavid du Colombier d->offset = s->offset; 9043e12c5d1SDavid du Colombier d->block = s->block; 9053e12c5d1SDavid du Colombier d->varlineno = s->varlineno; 9063e12c5d1SDavid du Colombier d->aused = s->aused; 9073e12c5d1SDavid du Colombier return d; 9083e12c5d1SDavid du Colombier } 9093e12c5d1SDavid du Colombier 9103e12c5d1SDavid du Colombier int 9113e12c5d1SDavid du Colombier sametype(Type *t1, Type *t2) 9123e12c5d1SDavid du Colombier { 9133e12c5d1SDavid du Colombier 9143e12c5d1SDavid du Colombier if(t1 == t2) 9153e12c5d1SDavid du Colombier return 1; 9163e12c5d1SDavid du Colombier return rsametype(t1, t2, 5); 9173e12c5d1SDavid du Colombier } 9183e12c5d1SDavid du Colombier 9193e12c5d1SDavid du Colombier int 9203e12c5d1SDavid du Colombier rsametype(Type *t1, Type *t2, int n) 9213e12c5d1SDavid du Colombier { 9223e12c5d1SDavid du Colombier int et; 9233e12c5d1SDavid du Colombier 9243e12c5d1SDavid du Colombier n--; 9253e12c5d1SDavid du Colombier for(;;) { 9263e12c5d1SDavid du Colombier if(t1 == t2) 9273e12c5d1SDavid du Colombier return 1; 9283e12c5d1SDavid du Colombier if(t1 == T || t2 == T) 9293e12c5d1SDavid du Colombier return 0; 9303e12c5d1SDavid du Colombier if(n <= 0) 9313e12c5d1SDavid du Colombier return 1; 9323e12c5d1SDavid du Colombier et = t1->etype; 9333e12c5d1SDavid du Colombier if(et != t2->etype) 9343e12c5d1SDavid du Colombier return 0; 9353e12c5d1SDavid du Colombier if(et == TFUNC) { 9363e12c5d1SDavid du Colombier if(!rsametype(t1->link, t2->link, n)) 9373e12c5d1SDavid du Colombier return 0; 9383e12c5d1SDavid du Colombier t1 = t1->down; 9393e12c5d1SDavid du Colombier t2 = t2->down; 9403e12c5d1SDavid du Colombier while(t1 != T && t2 != T) { 9413e12c5d1SDavid du Colombier if(t1->etype == TOLD) { 9423e12c5d1SDavid du Colombier t1 = t1->down; 9433e12c5d1SDavid du Colombier continue; 9443e12c5d1SDavid du Colombier } 9453e12c5d1SDavid du Colombier if(t2->etype == TOLD) { 9463e12c5d1SDavid du Colombier t2 = t2->down; 9473e12c5d1SDavid du Colombier continue; 9483e12c5d1SDavid du Colombier } 9493e12c5d1SDavid du Colombier while(t1 != T || t2 != T) { 9503e12c5d1SDavid du Colombier if(!rsametype(t1, t2, n)) 9513e12c5d1SDavid du Colombier return 0; 9523e12c5d1SDavid du Colombier t1 = t1->down; 9533e12c5d1SDavid du Colombier t2 = t2->down; 9543e12c5d1SDavid du Colombier } 9553e12c5d1SDavid du Colombier break; 9563e12c5d1SDavid du Colombier } 9573e12c5d1SDavid du Colombier return 1; 9583e12c5d1SDavid du Colombier } 9593e12c5d1SDavid du Colombier t1 = t1->link; 9603e12c5d1SDavid du Colombier t2 = t2->link; 9613e12c5d1SDavid du Colombier if(typesu[et]) 9623e12c5d1SDavid du Colombier for(;;) { 9633e12c5d1SDavid du Colombier if(t1 == t2) 9643e12c5d1SDavid du Colombier return 1; 9653e12c5d1SDavid du Colombier if(!rsametype(t1, t2, n)) 9663e12c5d1SDavid du Colombier return 0; 9673e12c5d1SDavid du Colombier t1 = t1->down; 9683e12c5d1SDavid du Colombier t2 = t2->down; 9693e12c5d1SDavid du Colombier } 9703e12c5d1SDavid du Colombier if(et == TIND) 9713e12c5d1SDavid du Colombier if(t1->etype == TVOID || t2->etype == TVOID) 9723e12c5d1SDavid du Colombier return 1; 9733e12c5d1SDavid du Colombier } 9743e12c5d1SDavid du Colombier } 9753e12c5d1SDavid du Colombier 976*219b2ee8SDavid du Colombier Type* 9773e12c5d1SDavid du Colombier dotag(Sym *s, int et, int bn) 9783e12c5d1SDavid du Colombier { 9793e12c5d1SDavid du Colombier Decl *d; 9803e12c5d1SDavid du Colombier 9813e12c5d1SDavid du Colombier if(bn != 0 && bn != s->sueblock) { 9823e12c5d1SDavid du Colombier d = push(); 9833e12c5d1SDavid du Colombier d->sym = s; 9843e12c5d1SDavid du Colombier d->val = DSUE; 9853e12c5d1SDavid du Colombier d->type = s->suetag; 9863e12c5d1SDavid du Colombier d->block = s->sueblock; 9873e12c5d1SDavid du Colombier s->suetag = T; 9883e12c5d1SDavid du Colombier } 9893e12c5d1SDavid du Colombier if(s->suetag == T) { 9903e12c5d1SDavid du Colombier s->suetag = typ(et, T); 9913e12c5d1SDavid du Colombier s->sueblock = autobn; 9923e12c5d1SDavid du Colombier } 9933e12c5d1SDavid du Colombier if(s->suetag->etype != et) 9943e12c5d1SDavid du Colombier diag(Z, "tag used for more than one type: %s", 9953e12c5d1SDavid du Colombier s->name); 9963e12c5d1SDavid du Colombier if(s->suetag->tag == S) 9973e12c5d1SDavid du Colombier s->suetag->tag = s; 998*219b2ee8SDavid du Colombier return s->suetag; 9993e12c5d1SDavid du Colombier } 10003e12c5d1SDavid du Colombier 10013e12c5d1SDavid du Colombier Node* 10023e12c5d1SDavid du Colombier dcllabel(Sym *s, int f) 10033e12c5d1SDavid du Colombier { 10043e12c5d1SDavid du Colombier Decl *d, d1; 10053e12c5d1SDavid du Colombier Node *n; 10063e12c5d1SDavid du Colombier 10073e12c5d1SDavid du Colombier n = s->label; 10083e12c5d1SDavid du Colombier if(n != Z) { 10093e12c5d1SDavid du Colombier if(f) { 10103e12c5d1SDavid du Colombier if(n->complex) 10113e12c5d1SDavid du Colombier diag(Z, "label reused: %s", s->name); 10123e12c5d1SDavid du Colombier n->complex = 1; 10133e12c5d1SDavid du Colombier } 10143e12c5d1SDavid du Colombier return n; 10153e12c5d1SDavid du Colombier } 10163e12c5d1SDavid du Colombier 10173e12c5d1SDavid du Colombier d = push(); 10183e12c5d1SDavid du Colombier d->sym = s; 10193e12c5d1SDavid du Colombier d->val = DLABEL; 10203e12c5d1SDavid du Colombier dclstack = d->link; 10213e12c5d1SDavid du Colombier 10223e12c5d1SDavid du Colombier d1 = *firstdcl; 10233e12c5d1SDavid du Colombier *firstdcl = *d; 10243e12c5d1SDavid du Colombier *d = d1; 10253e12c5d1SDavid du Colombier 10263e12c5d1SDavid du Colombier firstdcl->link = d; 10273e12c5d1SDavid du Colombier firstdcl = d; 10283e12c5d1SDavid du Colombier 10293e12c5d1SDavid du Colombier n = new(OXXX, Z, Z); 10303e12c5d1SDavid du Colombier n->sym = s; 10313e12c5d1SDavid du Colombier n->complex = f; 10323e12c5d1SDavid du Colombier s->label = n; 10333e12c5d1SDavid du Colombier 10343e12c5d1SDavid du Colombier if(debug['d']) 10353e12c5d1SDavid du Colombier dbgdecl(s); 10363e12c5d1SDavid du Colombier return n; 10373e12c5d1SDavid du Colombier } 10383e12c5d1SDavid du Colombier 10393e12c5d1SDavid du Colombier Type* 10403e12c5d1SDavid du Colombier paramconv(Type *t, int f) 10413e12c5d1SDavid du Colombier { 10423e12c5d1SDavid du Colombier 10433e12c5d1SDavid du Colombier switch(t->etype) { 10443e12c5d1SDavid du Colombier case TARRAY: 10453e12c5d1SDavid du Colombier t = typ(TIND, t->link); 10463e12c5d1SDavid du Colombier t->width = types[TIND]->width; 10473e12c5d1SDavid du Colombier break; 10483e12c5d1SDavid du Colombier 10493e12c5d1SDavid du Colombier case TFUNC: 10503e12c5d1SDavid du Colombier t = typ(TIND, t); 10513e12c5d1SDavid du Colombier t->width = types[TIND]->width; 10523e12c5d1SDavid du Colombier break; 10533e12c5d1SDavid du Colombier 10543e12c5d1SDavid du Colombier case TFLOAT: 10553e12c5d1SDavid du Colombier if(!f) 10563e12c5d1SDavid du Colombier t = types[TDOUBLE]; 10573e12c5d1SDavid du Colombier break; 10583e12c5d1SDavid du Colombier 10593e12c5d1SDavid du Colombier case TCHAR: 10603e12c5d1SDavid du Colombier case TSHORT: 10613e12c5d1SDavid du Colombier if(!f) 10623e12c5d1SDavid du Colombier t = tint; 10633e12c5d1SDavid du Colombier break; 10643e12c5d1SDavid du Colombier 10653e12c5d1SDavid du Colombier case TUCHAR: 10663e12c5d1SDavid du Colombier case TUSHORT: 10673e12c5d1SDavid du Colombier if(!f) 10683e12c5d1SDavid du Colombier t = tuint; 10693e12c5d1SDavid du Colombier break; 10703e12c5d1SDavid du Colombier } 10713e12c5d1SDavid du Colombier return t; 10723e12c5d1SDavid du Colombier } 10733e12c5d1SDavid du Colombier 10743e12c5d1SDavid du Colombier void 10753e12c5d1SDavid du Colombier adecl(int c, Type *t, Sym *s) 10763e12c5d1SDavid du Colombier { 10773e12c5d1SDavid du Colombier 10783e12c5d1SDavid du Colombier if(c == CSTATIC) 10793e12c5d1SDavid du Colombier c = CLOCAL; 10803e12c5d1SDavid du Colombier if(t->etype == TFUNC) { 10813e12c5d1SDavid du Colombier if(c == CXXX) 10823e12c5d1SDavid du Colombier c = CEXTERN; 10833e12c5d1SDavid du Colombier if(c == CLOCAL) 10843e12c5d1SDavid du Colombier c = CSTATIC; 10853e12c5d1SDavid du Colombier if(c == CAUTO || c == CEXREG) 10863e12c5d1SDavid du Colombier diag(Z, "function cannot be %s %s", cnames[c], s->name); 10873e12c5d1SDavid du Colombier } 10883e12c5d1SDavid du Colombier if(c == CXXX) 10893e12c5d1SDavid du Colombier c = CAUTO; 1090*219b2ee8SDavid du Colombier if(s) { 1091*219b2ee8SDavid du Colombier if(s->class == CSTATIC) 1092*219b2ee8SDavid du Colombier if(c == CEXTERN || c == CGLOBL) 1093*219b2ee8SDavid du Colombier c = CSTATIC; 10943e12c5d1SDavid du Colombier if(s->class == CAUTO || s->class == CPARAM || s->class == CLOCAL) 10953e12c5d1SDavid du Colombier if(s->block == autobn) 10963e12c5d1SDavid du Colombier diag(Z, "auto redeclaration of: %s", s->name); 10973e12c5d1SDavid du Colombier if(c != CPARAM) 10983e12c5d1SDavid du Colombier push1(s); 10993e12c5d1SDavid du Colombier s->block = autobn; 11003e12c5d1SDavid du Colombier s->offset = 0; 11013e12c5d1SDavid du Colombier s->type = t; 11023e12c5d1SDavid du Colombier s->class = c; 11033e12c5d1SDavid du Colombier s->aused = 0; 1104*219b2ee8SDavid du Colombier } 11053e12c5d1SDavid du Colombier 11063e12c5d1SDavid du Colombier if(c != CAUTO && c != CPARAM) 11073e12c5d1SDavid du Colombier return; 11083e12c5d1SDavid du Colombier if(c == CPARAM && autoffset == 0) { 11093e12c5d1SDavid du Colombier firstarg = s; 11103e12c5d1SDavid du Colombier firstargtype = t; 11113e12c5d1SDavid du Colombier } 11123e12c5d1SDavid du Colombier if(t->width < tint->width) 11133e12c5d1SDavid du Colombier autoffset += endian(t->width); 1114*219b2ee8SDavid du Colombier if(s) 11153e12c5d1SDavid du Colombier s->offset = autoffset; 11163e12c5d1SDavid du Colombier autoffset += t->width; 11173e12c5d1SDavid du Colombier autoffset += round(autoffset, tint->width); 11183e12c5d1SDavid du Colombier if(c == CAUTO) 11193e12c5d1SDavid du Colombier s->offset = -autoffset; 11203e12c5d1SDavid du Colombier if(autoffset > stkoff) { 11213e12c5d1SDavid du Colombier stkoff = autoffset; 11223e12c5d1SDavid du Colombier stkoff += round(stkoff, types[TLONG]->width); 11233e12c5d1SDavid du Colombier } 11243e12c5d1SDavid du Colombier } 11253e12c5d1SDavid du Colombier 11263e12c5d1SDavid du Colombier void 11273e12c5d1SDavid du Colombier pdecl(int c, Type *t, Sym *s) 11283e12c5d1SDavid du Colombier { 1129*219b2ee8SDavid du Colombier if(s && s->offset != -1) { 11303e12c5d1SDavid du Colombier diag(Z, "not a parameter: %s", s->name); 11313e12c5d1SDavid du Colombier return; 11323e12c5d1SDavid du Colombier } 11333e12c5d1SDavid du Colombier t = paramconv(t, c==CPARAM); 11343e12c5d1SDavid du Colombier if(c == CXXX) 11353e12c5d1SDavid du Colombier c = CPARAM; 11363e12c5d1SDavid du Colombier if(c != CPARAM) { 11373e12c5d1SDavid du Colombier diag(Z, "parameter cannot have class: %s", s->name); 11383e12c5d1SDavid du Colombier c = CPARAM; 11393e12c5d1SDavid du Colombier } 11403e12c5d1SDavid du Colombier adecl(c, t, s); 11413e12c5d1SDavid du Colombier } 11423e12c5d1SDavid du Colombier 11433e12c5d1SDavid du Colombier void 11443e12c5d1SDavid du Colombier xdecl(int c, Type *t, Sym *s) 11453e12c5d1SDavid du Colombier { 11463e12c5d1SDavid du Colombier long o; 11473e12c5d1SDavid du Colombier 11483e12c5d1SDavid du Colombier o = 0; 11493e12c5d1SDavid du Colombier if(c == CEXREG) { 11503e12c5d1SDavid du Colombier o = exreg(t); 11513e12c5d1SDavid du Colombier if(o == 0) 11523e12c5d1SDavid du Colombier c = CEXTERN; 11533e12c5d1SDavid du Colombier } 11543e12c5d1SDavid du Colombier if(c == CXXX) { 11553e12c5d1SDavid du Colombier c = CGLOBL; 11563e12c5d1SDavid du Colombier if(s->class == CEXTERN) 11573e12c5d1SDavid du Colombier s->class = c; 11583e12c5d1SDavid du Colombier } 11593e12c5d1SDavid du Colombier if(c == CEXTERN) 11603e12c5d1SDavid du Colombier if(s->class == CGLOBL) 11613e12c5d1SDavid du Colombier c = CGLOBL; 11623e12c5d1SDavid du Colombier if(c == CAUTO) { 11633e12c5d1SDavid du Colombier diag(Z, "external declaration cannot be auto: %s", s->name); 11643e12c5d1SDavid du Colombier c = CEXTERN; 11653e12c5d1SDavid du Colombier } 11663e12c5d1SDavid du Colombier if(s->class == CSTATIC) 11673e12c5d1SDavid du Colombier if(c == CEXTERN || c == CGLOBL) 11683e12c5d1SDavid du Colombier c = CSTATIC; 11693e12c5d1SDavid du Colombier if(s->type != T) 11703e12c5d1SDavid du Colombier if(s->class != c || !sametype(t, s->type) || t->etype == TENUM) { 11713e12c5d1SDavid du Colombier diag(Z, "external redeclaration of: %s", s->name); 11723e12c5d1SDavid du Colombier print(" %T; %T\n", t, s->type); 11733e12c5d1SDavid du Colombier } 11743e12c5d1SDavid du Colombier tmerge(t, s); 11753e12c5d1SDavid du Colombier s->type = t; 11763e12c5d1SDavid du Colombier s->class = c; 11773e12c5d1SDavid du Colombier s->block = 0; 11783e12c5d1SDavid du Colombier s->offset = o; 11793e12c5d1SDavid du Colombier } 11803e12c5d1SDavid du Colombier 11813e12c5d1SDavid du Colombier void 11823e12c5d1SDavid du Colombier tmerge(Type *t1, Sym *s) 11833e12c5d1SDavid du Colombier { 11843e12c5d1SDavid du Colombier Type *ta, *tb, *t2; 11853e12c5d1SDavid du Colombier 11863e12c5d1SDavid du Colombier t2 = s->type; 11873e12c5d1SDavid du Colombier /*print("merge %T; %T\n", t1, t2);/**/ 11883e12c5d1SDavid du Colombier for(;;) { 11893e12c5d1SDavid du Colombier if(t1 == T || t2 == T || t1 == t2) 11903e12c5d1SDavid du Colombier break; 11913e12c5d1SDavid du Colombier if(t1->etype != t2->etype) 11923e12c5d1SDavid du Colombier break; 11933e12c5d1SDavid du Colombier switch(t1->etype) { 11943e12c5d1SDavid du Colombier case TFUNC: 11953e12c5d1SDavid du Colombier ta = t1->down; 11963e12c5d1SDavid du Colombier tb = t2->down; 11973e12c5d1SDavid du Colombier if(ta == T) { 11983e12c5d1SDavid du Colombier t1->down = tb; 11993e12c5d1SDavid du Colombier break; 12003e12c5d1SDavid du Colombier } 12013e12c5d1SDavid du Colombier if(tb == T) 12023e12c5d1SDavid du Colombier break; 12033e12c5d1SDavid du Colombier while(ta != T && tb != T) { 12043e12c5d1SDavid du Colombier if(ta == tb) 12053e12c5d1SDavid du Colombier break; 12063e12c5d1SDavid du Colombier /* ignore old-style flag */ 12073e12c5d1SDavid du Colombier if(ta->etype == TOLD) { 12083e12c5d1SDavid du Colombier ta = ta->down; 12093e12c5d1SDavid du Colombier continue; 12103e12c5d1SDavid du Colombier } 12113e12c5d1SDavid du Colombier if(tb->etype == TOLD) { 12123e12c5d1SDavid du Colombier tb = tb->down; 12133e12c5d1SDavid du Colombier continue; 12143e12c5d1SDavid du Colombier } 12153e12c5d1SDavid du Colombier /* checking terminated by ... */ 12163e12c5d1SDavid du Colombier if(ta->etype == TDOT && tb->etype == TDOT) { 12173e12c5d1SDavid du Colombier ta = T; 12183e12c5d1SDavid du Colombier tb = T; 12193e12c5d1SDavid du Colombier break; 12203e12c5d1SDavid du Colombier } 12213e12c5d1SDavid du Colombier if(!sametype(ta, tb)) 12223e12c5d1SDavid du Colombier break; 12233e12c5d1SDavid du Colombier ta = ta->down; 12243e12c5d1SDavid du Colombier tb = tb->down; 12253e12c5d1SDavid du Colombier } 12263e12c5d1SDavid du Colombier if(ta != tb) 12273e12c5d1SDavid du Colombier diag(Z, "function inconsistently declared: %s", s->name); 12283e12c5d1SDavid du Colombier 12293e12c5d1SDavid du Colombier /* take new-style over old-style */ 12303e12c5d1SDavid du Colombier ta = t1->down; 12313e12c5d1SDavid du Colombier tb = t2->down; 12323e12c5d1SDavid du Colombier if(ta != T && ta->etype == TOLD) 12333e12c5d1SDavid du Colombier if(tb != T && tb->etype != TOLD) 12343e12c5d1SDavid du Colombier t1->down = tb; 12353e12c5d1SDavid du Colombier break; 12363e12c5d1SDavid du Colombier 12373e12c5d1SDavid du Colombier case TARRAY: 12383e12c5d1SDavid du Colombier /* should we check array size change? */ 12393e12c5d1SDavid du Colombier if(t2->width > t1->width) 12403e12c5d1SDavid du Colombier t1->width = t2->width; 12413e12c5d1SDavid du Colombier break; 12423e12c5d1SDavid du Colombier 12433e12c5d1SDavid du Colombier case TUNION: 12443e12c5d1SDavid du Colombier case TSTRUCT: 12453e12c5d1SDavid du Colombier return; 12463e12c5d1SDavid du Colombier } 12473e12c5d1SDavid du Colombier t1 = t1->link; 12483e12c5d1SDavid du Colombier t2 = t2->link; 12493e12c5d1SDavid du Colombier } 12503e12c5d1SDavid du Colombier } 12513e12c5d1SDavid du Colombier 12523e12c5d1SDavid du Colombier void 12533e12c5d1SDavid du Colombier edecl(int c, Type *t, Sym *s) 12543e12c5d1SDavid du Colombier { 12553e12c5d1SDavid du Colombier Type *t1; 12563e12c5d1SDavid du Colombier 12573e12c5d1SDavid du Colombier if(s == S) { 12583e12c5d1SDavid du Colombier if(!typesu[t->etype]) 12593e12c5d1SDavid du Colombier diag(Z, "unnamed structure element must be struct/union"); 12603e12c5d1SDavid du Colombier if(c != CXXX) 12613e12c5d1SDavid du Colombier diag(Z, "unnamed structure element cannot have class"); 12623e12c5d1SDavid du Colombier } else 12633e12c5d1SDavid du Colombier if(c != CXXX) 12643e12c5d1SDavid du Colombier diag(Z, "structure element cannot have class: %s", s->name); 12653e12c5d1SDavid du Colombier t1 = t; 12663e12c5d1SDavid du Colombier t = typ(TXXX, T); 12673e12c5d1SDavid du Colombier *t = *t1; 12683e12c5d1SDavid du Colombier t->sym = s; 12693e12c5d1SDavid du Colombier t->down = T; 12703e12c5d1SDavid du Colombier if(lastfield) { 12713e12c5d1SDavid du Colombier t->shift = lastbit - lastfield; 12723e12c5d1SDavid du Colombier t->nbits = lastfield; 12733e12c5d1SDavid du Colombier if(firstbit) 12743e12c5d1SDavid du Colombier t->shift = -t->shift; 12753e12c5d1SDavid du Colombier } 12763e12c5d1SDavid du Colombier if(strf == T) 12773e12c5d1SDavid du Colombier strf = t; 12783e12c5d1SDavid du Colombier else 12793e12c5d1SDavid du Colombier strl->down = t; 12803e12c5d1SDavid du Colombier strl = t; 12813e12c5d1SDavid du Colombier } 12823e12c5d1SDavid du Colombier 12833e12c5d1SDavid du Colombier /* 1284*219b2ee8SDavid du Colombier * this routine is very suspect. 1285*219b2ee8SDavid du Colombier * ansi requires the enum type to 1286*219b2ee8SDavid du Colombier * be represented as an 'int' 1287*219b2ee8SDavid du Colombier * this means that 0x81234567 1288*219b2ee8SDavid du Colombier * would be illegal. this routine 1289*219b2ee8SDavid du Colombier * makes signed and unsigned go 1290*219b2ee8SDavid du Colombier * to unsigned. 12913e12c5d1SDavid du Colombier */ 1292*219b2ee8SDavid du Colombier Type* 1293*219b2ee8SDavid du Colombier maxtype(Type *t1, Type *t2) 1294*219b2ee8SDavid du Colombier { 1295*219b2ee8SDavid du Colombier 1296*219b2ee8SDavid du Colombier if(t1 == T) 1297*219b2ee8SDavid du Colombier return t2; 1298*219b2ee8SDavid du Colombier if(t2 == T) 1299*219b2ee8SDavid du Colombier return t1; 1300*219b2ee8SDavid du Colombier if(t1->etype > t2->etype) 1301*219b2ee8SDavid du Colombier return t1; 1302*219b2ee8SDavid du Colombier return t2; 13033e12c5d1SDavid du Colombier } 13043e12c5d1SDavid du Colombier 13053e12c5d1SDavid du Colombier void 13063e12c5d1SDavid du Colombier doenum(Sym *s, Node *n) 13073e12c5d1SDavid du Colombier { 13083e12c5d1SDavid du Colombier 13093e12c5d1SDavid du Colombier if(n) { 13103e12c5d1SDavid du Colombier complex(n); 1311*219b2ee8SDavid du Colombier if(n->op != OCONST) { 1312*219b2ee8SDavid du Colombier diag(n, "enum not a constant: %s", s->name); 13133e12c5d1SDavid du Colombier return; 13143e12c5d1SDavid du Colombier } 1315*219b2ee8SDavid du Colombier en.cenum = n->type; 1316*219b2ee8SDavid du Colombier en.tenum = maxtype(en.cenum, en.tenum); 1317*219b2ee8SDavid du Colombier 1318*219b2ee8SDavid du Colombier if(!typefd[en.cenum->etype]) 1319*219b2ee8SDavid du Colombier en.lastenum = n->vconst; 1320*219b2ee8SDavid du Colombier else 1321*219b2ee8SDavid du Colombier en.floatenum = n->fconst; 13223e12c5d1SDavid du Colombier } 13233e12c5d1SDavid du Colombier if(dclstack) 13243e12c5d1SDavid du Colombier push1(s); 13253e12c5d1SDavid du Colombier xdecl(CXXX, types[TENUM], s); 1326*219b2ee8SDavid du Colombier 1327*219b2ee8SDavid du Colombier if(en.cenum == T) { 1328*219b2ee8SDavid du Colombier en.tenum = tint; 1329*219b2ee8SDavid du Colombier en.cenum = tint; 1330*219b2ee8SDavid du Colombier en.lastenum = 0; 1331*219b2ee8SDavid du Colombier } 1332*219b2ee8SDavid du Colombier s->tenum = en.cenum; 1333*219b2ee8SDavid du Colombier 1334*219b2ee8SDavid du Colombier if(!typefd[s->tenum->etype]) { 1335*219b2ee8SDavid du Colombier s->vconst = convvtox(en.lastenum, s->tenum->etype); 1336*219b2ee8SDavid du Colombier en.lastenum++; 1337*219b2ee8SDavid du Colombier } else { 1338*219b2ee8SDavid du Colombier s->fconst = en.floatenum; 1339*219b2ee8SDavid du Colombier en.floatenum++; 1340*219b2ee8SDavid du Colombier } 1341*219b2ee8SDavid du Colombier 13423e12c5d1SDavid du Colombier if(debug['d']) 13433e12c5d1SDavid du Colombier dbgdecl(s); 13443e12c5d1SDavid du Colombier } 13453e12c5d1SDavid du Colombier 13463e12c5d1SDavid du Colombier void 13473e12c5d1SDavid du Colombier symadjust(Sym *s, Node *n, long del) 13483e12c5d1SDavid du Colombier { 13493e12c5d1SDavid du Colombier 13503e12c5d1SDavid du Colombier switch(n->op) { 13513e12c5d1SDavid du Colombier default: 13523e12c5d1SDavid du Colombier if(n->left) 13533e12c5d1SDavid du Colombier symadjust(s, n->left, del); 13543e12c5d1SDavid du Colombier if(n->right) 13553e12c5d1SDavid du Colombier symadjust(s, n->right, del); 13563e12c5d1SDavid du Colombier return; 13573e12c5d1SDavid du Colombier 13583e12c5d1SDavid du Colombier case ONAME: 13593e12c5d1SDavid du Colombier if(n->sym == s) 1360*219b2ee8SDavid du Colombier n->xoffset -= del; 13613e12c5d1SDavid du Colombier return; 13623e12c5d1SDavid du Colombier 13633e12c5d1SDavid du Colombier case OCONST: 13643e12c5d1SDavid du Colombier case OSTRING: 13653e12c5d1SDavid du Colombier case OLSTRING: 13663e12c5d1SDavid du Colombier case OINDREG: 13673e12c5d1SDavid du Colombier case OREGISTER: 13683e12c5d1SDavid du Colombier return; 13693e12c5d1SDavid du Colombier } 13703e12c5d1SDavid du Colombier } 13713e12c5d1SDavid du Colombier 13723e12c5d1SDavid du Colombier Node* 13733e12c5d1SDavid du Colombier contig(Sym *s, Node *n, long v) 13743e12c5d1SDavid du Colombier { 13753e12c5d1SDavid du Colombier Node *p, *r, *q, *m; 13763e12c5d1SDavid du Colombier long w; 13773e12c5d1SDavid du Colombier 13783e12c5d1SDavid du Colombier if(n == Z) 13793e12c5d1SDavid du Colombier goto no; 13803e12c5d1SDavid du Colombier w = s->type->width; 13813e12c5d1SDavid du Colombier 13823e12c5d1SDavid du Colombier /* 13833e12c5d1SDavid du Colombier * nightmare: an automatic array whose size 13843e12c5d1SDavid du Colombier * increases when it is initialized 13853e12c5d1SDavid du Colombier */ 13863e12c5d1SDavid du Colombier if(v != w) { 13873e12c5d1SDavid du Colombier if(v != 0) 13883e12c5d1SDavid du Colombier diag(n, "automatic adjustable array: %s", s->name); 13893e12c5d1SDavid du Colombier v = s->offset; 13903e12c5d1SDavid du Colombier autoffset += w; 13913e12c5d1SDavid du Colombier autoffset += round(autoffset, tint->width); 13923e12c5d1SDavid du Colombier s->offset = -autoffset; 13933e12c5d1SDavid du Colombier if(autoffset > stkoff) { 13943e12c5d1SDavid du Colombier stkoff = autoffset; 13953e12c5d1SDavid du Colombier stkoff += round(stkoff, types[TLONG]->width); 13963e12c5d1SDavid du Colombier } 13973e12c5d1SDavid du Colombier symadjust(s, n, v - s->offset); 13983e12c5d1SDavid du Colombier } 13993e12c5d1SDavid du Colombier if(w <= 4) 14003e12c5d1SDavid du Colombier goto no; 14013e12c5d1SDavid du Colombier if(n->op == OAS) 14023e12c5d1SDavid du Colombier if(n->left->type) 14033e12c5d1SDavid du Colombier if(n->left->type->width == w) 14043e12c5d1SDavid du Colombier goto no; 14053e12c5d1SDavid du Colombier while(w & 3) 14063e12c5d1SDavid du Colombier w++; /* is this a bug?? */ 14073e12c5d1SDavid du Colombier /* 14083e12c5d1SDavid du Colombier * insert the following code 14093e12c5d1SDavid du Colombier * 14103e12c5d1SDavid du Colombier *(long**)&X = (long*)((char*)X + sizeof(X)); 14113e12c5d1SDavid du Colombier do { 14123e12c5d1SDavid du Colombier *(long**)&X -= 1; 14133e12c5d1SDavid du Colombier **(long**)&X = 0; 14143e12c5d1SDavid du Colombier } while(*(long**)&X); 14153e12c5d1SDavid du Colombier */ 14163e12c5d1SDavid du Colombier 14173e12c5d1SDavid du Colombier for(q=n; q->op != ONAME; q=q->left) 14183e12c5d1SDavid du Colombier ; 14193e12c5d1SDavid du Colombier 14203e12c5d1SDavid du Colombier p = new(ONAME, Z, Z); 14213e12c5d1SDavid du Colombier *p = *q; 14223e12c5d1SDavid du Colombier p->type = typ(TIND, types[TLONG]); 1423*219b2ee8SDavid du Colombier p->xoffset = s->offset; 14243e12c5d1SDavid du Colombier 14253e12c5d1SDavid du Colombier r = new(ONAME, Z, Z); 14263e12c5d1SDavid du Colombier *r = *p; 14273e12c5d1SDavid du Colombier r = new(OPOSTDEC, r, Z); 14283e12c5d1SDavid du Colombier 14293e12c5d1SDavid du Colombier q = new(ONAME, Z, Z); 14303e12c5d1SDavid du Colombier *q = *p; 14313e12c5d1SDavid du Colombier q = new(OIND, q, Z); 14323e12c5d1SDavid du Colombier 14333e12c5d1SDavid du Colombier m = new(OCONST, Z, Z); 1434*219b2ee8SDavid du Colombier m->vconst = 0; 14353e12c5d1SDavid du Colombier m->type = types[TLONG]; 14363e12c5d1SDavid du Colombier 14373e12c5d1SDavid du Colombier q = new(OAS, q, m); 14383e12c5d1SDavid du Colombier 14393e12c5d1SDavid du Colombier r = new(OLIST, r, q); 14403e12c5d1SDavid du Colombier 14413e12c5d1SDavid du Colombier q = new(ONAME, Z, Z); 14423e12c5d1SDavid du Colombier *q = *p; 14433e12c5d1SDavid du Colombier r = new(ODWHILE, q, r); 14443e12c5d1SDavid du Colombier 14453e12c5d1SDavid du Colombier q = new(ONAME, Z, Z); 14463e12c5d1SDavid du Colombier *q = *p; 14473e12c5d1SDavid du Colombier q->type = q->type->link; 1448*219b2ee8SDavid du Colombier q->xoffset += w; 14493e12c5d1SDavid du Colombier q = new(OADDR, q, 0); 14503e12c5d1SDavid du Colombier 14513e12c5d1SDavid du Colombier q = new(OAS, p, q); 14523e12c5d1SDavid du Colombier r = new(OLIST, q, r); 14533e12c5d1SDavid du Colombier 14543e12c5d1SDavid du Colombier n = new(OLIST, r, n); 14553e12c5d1SDavid du Colombier 14563e12c5d1SDavid du Colombier no: 14573e12c5d1SDavid du Colombier return n; 14583e12c5d1SDavid du Colombier } 1459