#include "cc.h" Node*dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n, int gen){ Sym *s; Node *n1; long v; nearln = lineno; lastfield = 0; loop: if(n != Z) switch(n->op) { default: diag(n, "unknown declarator: %O", n->op); break; case OARRAY: t = typ(TARRAY, t); t->width = 0; n1 = n->right; n = n->left; if(n1 != Z) { complex(n1); v = -1; if(n1->op == OCONST) v = n1->vconst; if(v <= 0) { diag(n, "array size must be a positive constant"); v = 1; } t->width = v * t->link->width; t->nwidth = n1->left; } goto loop; case OIND: t = typ(TIND, t); t->garb = n->garb; n = n->left; goto loop; case OFUNC: t = typ(TFUNC, t); t->down = fnproto(n); n = n->left; goto loop; case OBIT: n1 = n->right; complex(n1); lastfield = -1; if(n1->op == OCONST) lastfield = n1->vconst; if(lastfield < 0) { diag(n, "field width must be non-negative constant"); lastfield = 1; } if(lastfield == 0) { lastbit = 0; firstbit = 1; if(n->left != Z) { diag(n, "zero width named field"); lastfield = 1; } } if(!typei[t->etype]) { diag(n, "field type must be int-like"); t = types[TINT]; lastfield = 1; } if(lastfield > tfield->width*8) { diag(n, "field width larger than field unit"); lastfield = 1; } lastbit += lastfield; if(lastbit > tfield->width*8) { lastbit = lastfield; firstbit = 1; } n = n->left; goto loop; case ONAME: if(f == NODECL) break; s = n->sym; (*f)(c, t, s); if(s->class == CLOCAL) s = mkstatic(s); firstbit = 0; n->sym = s; n->type = s->type; acidvar(s); if(gen) vtgen(n); break; } lastdcl = t; return n;} Sym*mkstatic(Sym *s){ Sym *s1; if(s->class != CLOCAL) return s; snprint(symb, NSYMB, "%s$%d", s->name, s->block); s1 = lookup(); if(s1->class != CSTATIC) { s1->type = s->type; s1->offset = s->offset; s1->block = s->block; s1->class = CSTATIC; } return s1;} /* * make a copy of a typedef * the problem is to split out incomplete * arrays so that it is in the variable * rather than the typedef. */Type*tcopy(Type *t){ Type *tl, *tx; int et; if(t == T) return t; et = t->etype; if(typesu[et]) return t; tl = tcopy(t->link); if(tl != t->link || (et == TARRAY && t->width == 0)) { tx = typ(TXXX, 0); *tx = *t; tx->link = tl; return tx; } return t;} Node*doinit(Sym *s, Type *t, long o, Node *a){ Node *n, *reta; if(t == T) return Z; if(s->class == CEXTERN) s->class = CGLOBL; if(0) { print("t = %T; o = %ld; n = %s\n", t, o, s->name); prtree(a, "doinit value"); } n = initlist; if(a->op == OINIT) a = a->left; initlist = a; reta = a; init1(s, t, o, 0); if(initlist != Z) diag(initlist, "more initializers than structure: %s", s->name); initlist = n; return reta;} /* * get next major operator, * dont advance initlist. */Node*peekinit(void){ Node *a; a = initlist; loop: if(a == Z) return a; if(a->op == OLIST) { a = a->left; goto loop; } return a;} /* * consume and return next element on * initlist. expand strings. */Node*nextinit(void){ Node *a, *n; a = initlist; n = Z; if(a == Z) return a; if(a->op == OLIST) { n = a->right; a = a->left; } initlist = n; return a;} intisstruct(Node *a, Type *t){ Node *n; switch(a->op) { case ODOTDOT: n = a->left; if(n && n->type && sametype(n->type, t)) return 1; case OSTRING: case OLSTRING: case OCONST: case OINIT: case OELEM: return 0; } n = new(ODOTDOT, Z, Z); *n = *a; /* * ODOTDOT is a flag for tcom * a second tcom will not be performed */ a->op = ODOTDOT; a->left = n; a->right = Z; if(tcom(n)) return 0; if(sametype(n->type, t)) return 1; return 0;} voidinit1(Sym *s, Type *t, long o, int exflag){ Node *a, *r, nod; Type *t1; long e, w, so, mw; a = peekinit(); if(a == Z) return; if(0) { print("t = %T; o = %ld; n = %s\n", t, o, s->name); prtree(a, "init1 value"); } if(exflag && a->op == OINIT){ doinit(s, t, o, nextinit()); return; } switch(t->etype) { default: diag(Z, "unknown type in initialization: %T to: %s", t, s->name); return; case TCHAR: case TUCHAR: case TINT: case TUINT: case TSHORT: case TUSHORT: case TLONG: case TULONG: case TVLONG: case TUVLONG: case TFLOAT: case TDOUBLE: case TIND: single: if(a->op == OARRAY || a->op == OELEM) return; a = nextinit(); if(a == Z) return; if(t->nbits) diag(Z, "cannot initialize bitfields"); if(0 && s->class == CAUTO) return; complex(a); if(a->type == T) return; if(a->op == OCONST) { if(!sametype(a->type, t)) { /* hoop jumping to save malloc */ if(nodcast == Z) nodcast = new(OCAST, Z, Z); nod = *nodcast; nod.left = a; nod.type = t; nod.lineno = a->lineno; complex(&nod); if(nod.type) *a = nod; } if(a->op != OCONST) {/* diag(a, "initializer is not a constant: %s", s->name);*/ return; } if(vconst(a) == 0) return; return; } if(t->etype == TIND) { while(a->op == OCAST) { warn(a, "CAST in initialization ignored"); a = a->left; } if(0 && !sametype(t, a->type)) { diag(a, "initialization of incompatible pointers: %s", s->name); print("%T and %T\n", t, a->type); }/* if(a->op == OADDR) a = a->left;*/ return; } while(a->op == OCAST) a = a->left; if(a->op == OADDR) { warn(a, "initialize pointer to an integer: %s", s->name); /* a = a->left; */ return; } /* diag(a, "initializer is not a constant: %s", s->name); */ return; case TARRAY: w = t->link->width; if(a->op == OSTRING || a->op == OLSTRING) if(typei[t->link->etype]) { /* * get rid of null if sizes match exactly */ a = nextinit(); /* mw = t->width/w; */ so = a->type->width/a->type->link->width; if(t->width <= 0) t->width = w*(so-1); USED(a); return; } mw = -w; for(e=0;;) { /* * peek ahead for element initializer */ a = peekinit(); if(a == Z) break; if(a->op == OELEM && t->link->etype != TSTRUCT) break; if(a->op == OARRAY) { if(e && exflag) break; a = nextinit(); r = a->left; complex(r); if(r->op != OCONST) { diag(r, "initializer subscript must be constant"); return; } e = r->vconst; if(t->width != 0) if(e < 0 || e*w >= t->width) { diag(a, "initialization index out of range: %ld", e); continue; } } so = e*w; if(so > mw) mw = so; if(t->width != 0) if(mw >= t->width) break; init1(s, t->link, o+so, 1); e++; } if(t->width == 0) t->width = mw+w; return; case TUNION: case TSTRUCT: /* * peek ahead to find type of rhs. * if its a structure, then treat * this element as a variable * rather than an aggregate. */ if(isstruct(a, t)) goto single; if(t->width <= 0) { diag(Z, "incomplete structure: %s", s->name); return; } again: for(t1 = t->link; t1 != T; t1 = t1->down) { if(a->op == OARRAY && t1->etype != TARRAY) break; if(a->op == OELEM) { if(t1->sym != a->sym) continue; nextinit(); } init1(s, t1, o+t1->offset, 1); a = peekinit(); if(a == Z) break; if(a->op == OELEM) goto again; } if(a && a->op == OELEM) diag(a, "structure element not found %F", a); return; }} /*Node*newlist(Node *l, Node *r){ if(r == Z) return l; if(l == Z) return r; return new(OLIST, l, r);}*/ voidsuallign(Type *t){ Type *l; long o, w; o = 0; switch(t->etype) { case TSTRUCT: t->offset = 0; w = 0; for(l = t->link; l != T; l = l->down) { if(l->nbits) { if(l->shift <= 0) { l->shift = -l->shift; w = round(w, tfield->width); o = w; w += tfield->width; } l->offset = o; } else { if(l->width <= 0) if(l->sym) diag(Z, "incomplete structure element: %s", l->sym->name);Lines 1–500 of 1387. Load more
#include "cc.h" Node* dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n, int gen) { Sym *s; Node *n1; long v; nearln = lineno; lastfield = 0; loop: if(n != Z) switch(n->op) { default: diag(n, "unknown declarator: %O", n->op); break; case OARRAY: t = typ(TARRAY, t); t->width = 0; n1 = n->right; n = n->left; if(n1 != Z) { complex(n1); v = -1; if(n1->op == OCONST) v = n1->vconst; if(v <= 0) { diag(n, "array size must be a positive constant"); v = 1; } t->width = v * t->link->width; t->nwidth = n1->left; } goto loop; case OIND: t = typ(TIND, t); t->garb = n->garb; n = n->left; goto loop; case OFUNC: t = typ(TFUNC, t); t->down = fnproto(n); n = n->left; goto loop; case OBIT: n1 = n->right; complex(n1); lastfield = -1; if(n1->op == OCONST) lastfield = n1->vconst; if(lastfield < 0) { diag(n, "field width must be non-negative constant"); lastfield = 1; } if(lastfield == 0) { lastbit = 0; firstbit = 1; if(n->left != Z) { diag(n, "zero width named field"); lastfield = 1; } } if(!typei[t->etype]) { diag(n, "field type must be int-like"); t = types[TINT]; lastfield = 1; } if(lastfield > tfield->width*8) { diag(n, "field width larger than field unit"); lastfield = 1; } lastbit += lastfield; if(lastbit > tfield->width*8) { lastbit = lastfield; firstbit = 1; } n = n->left; goto loop; case ONAME: if(f == NODECL) break; s = n->sym; (*f)(c, t, s); if(s->class == CLOCAL) s = mkstatic(s); firstbit = 0; n->sym = s; n->type = s->type; acidvar(s); if(gen) vtgen(n); break; } lastdcl = t; return n; } Sym* mkstatic(Sym *s) { Sym *s1; if(s->class != CLOCAL) return s; snprint(symb, NSYMB, "%s$%d", s->name, s->block); s1 = lookup(); if(s1->class != CSTATIC) { s1->type = s->type; s1->offset = s->offset; s1->block = s->block; s1->class = CSTATIC; } return s1; } /* * make a copy of a typedef * the problem is to split out incomplete * arrays so that it is in the variable * rather than the typedef. */ Type* tcopy(Type *t) { Type *tl, *tx; int et; if(t == T) return t; et = t->etype; if(typesu[et]) return t; tl = tcopy(t->link); if(tl != t->link || (et == TARRAY && t->width == 0)) { tx = typ(TXXX, 0); *tx = *t; tx->link = tl; return tx; } return t; } Node* doinit(Sym *s, Type *t, long o, Node *a) { Node *n, *reta; if(t == T) return Z; if(s->class == CEXTERN) s->class = CGLOBL; if(0) { print("t = %T; o = %ld; n = %s\n", t, o, s->name); prtree(a, "doinit value"); } n = initlist; if(a->op == OINIT) a = a->left; initlist = a; reta = a; init1(s, t, o, 0); if(initlist != Z) diag(initlist, "more initializers than structure: %s", s->name); initlist = n; return reta; } /* * get next major operator, * dont advance initlist. */ Node* peekinit(void) { Node *a; a = initlist; loop: if(a == Z) return a; if(a->op == OLIST) { a = a->left; goto loop; } return a; } /* * consume and return next element on * initlist. expand strings. */ Node* nextinit(void) { Node *a, *n; a = initlist; n = Z; if(a == Z) return a; if(a->op == OLIST) { n = a->right; a = a->left; } initlist = n; return a; } int isstruct(Node *a, Type *t) { Node *n; switch(a->op) { case ODOTDOT: n = a->left; if(n && n->type && sametype(n->type, t)) return 1; case OSTRING: case OLSTRING: case OCONST: case OINIT: case OELEM: return 0; } n = new(ODOTDOT, Z, Z); *n = *a; /* * ODOTDOT is a flag for tcom * a second tcom will not be performed */ a->op = ODOTDOT; a->left = n; a->right = Z; if(tcom(n)) return 0; if(sametype(n->type, t)) return 1; return 0; } void init1(Sym *s, Type *t, long o, int exflag) { Node *a, *r, nod; Type *t1; long e, w, so, mw; a = peekinit(); if(a == Z) return; if(0) { print("t = %T; o = %ld; n = %s\n", t, o, s->name); prtree(a, "init1 value"); } if(exflag && a->op == OINIT){ doinit(s, t, o, nextinit()); return; } switch(t->etype) { default: diag(Z, "unknown type in initialization: %T to: %s", t, s->name); return; case TCHAR: case TUCHAR: case TINT: case TUINT: case TSHORT: case TUSHORT: case TLONG: case TULONG: case TVLONG: case TUVLONG: case TFLOAT: case TDOUBLE: case TIND: single: if(a->op == OARRAY || a->op == OELEM) return; a = nextinit(); if(a == Z) return; if(t->nbits) diag(Z, "cannot initialize bitfields"); if(0 && s->class == CAUTO) return; complex(a); if(a->type == T) return; if(a->op == OCONST) { if(!sametype(a->type, t)) { /* hoop jumping to save malloc */ if(nodcast == Z) nodcast = new(OCAST, Z, Z); nod = *nodcast; nod.left = a; nod.type = t; nod.lineno = a->lineno; complex(&nod); if(nod.type) *a = nod; } if(a->op != OCONST) { /* diag(a, "initializer is not a constant: %s", s->name); */ return; } if(vconst(a) == 0) return; return; } if(t->etype == TIND) { while(a->op == OCAST) { warn(a, "CAST in initialization ignored"); a = a->left; } if(0 && !sametype(t, a->type)) { diag(a, "initialization of incompatible pointers: %s", s->name); print("%T and %T\n", t, a->type); } /* if(a->op == OADDR) a = a->left; */ return; } while(a->op == OCAST) a = a->left; if(a->op == OADDR) { warn(a, "initialize pointer to an integer: %s", s->name); /* a = a->left; */ return; } /* diag(a, "initializer is not a constant: %s", s->name); */ return; case TARRAY: w = t->link->width; if(a->op == OSTRING || a->op == OLSTRING) if(typei[t->link->etype]) { /* * get rid of null if sizes match exactly */ a = nextinit(); /* mw = t->width/w; */ so = a->type->width/a->type->link->width; if(t->width <= 0) t->width = w*(so-1); USED(a); return; } mw = -w; for(e=0;;) { /* * peek ahead for element initializer */ a = peekinit(); if(a == Z) break; if(a->op == OELEM && t->link->etype != TSTRUCT) break; if(a->op == OARRAY) { if(e && exflag) break; a = nextinit(); r = a->left; complex(r); if(r->op != OCONST) { diag(r, "initializer subscript must be constant"); return; } e = r->vconst; if(t->width != 0) if(e < 0 || e*w >= t->width) { diag(a, "initialization index out of range: %ld", e); continue; } } so = e*w; if(so > mw) mw = so; if(t->width != 0) if(mw >= t->width) break; init1(s, t->link, o+so, 1); e++; } if(t->width == 0) t->width = mw+w; return; case TUNION: case TSTRUCT: /* * peek ahead to find type of rhs. * if its a structure, then treat * this element as a variable * rather than an aggregate. */ if(isstruct(a, t)) goto single; if(t->width <= 0) { diag(Z, "incomplete structure: %s", s->name); return; } again: for(t1 = t->link; t1 != T; t1 = t1->down) { if(a->op == OARRAY && t1->etype != TARRAY) break; if(a->op == OELEM) { if(t1->sym != a->sym) continue; nextinit(); } init1(s, t1, o+t1->offset, 1); a = peekinit(); if(a == Z) break; if(a->op == OELEM) goto again; } if(a && a->op == OELEM) diag(a, "structure element not found %F", a); return; } } /* Node* newlist(Node *l, Node *r) { if(r == Z) return l; if(l == Z) return r; return new(OLIST, l, r); } */ void suallign(Type *t) { Type *l; long o, w; o = 0; switch(t->etype) { case TSTRUCT: t->offset = 0; w = 0; for(l = t->link; l != T; l = l->down) { if(l->nbits) { if(l->shift <= 0) { l->shift = -l->shift; w = round(w, tfield->width); o = w; w += tfield->width; } l->offset = o; } else { if(l->width <= 0) if(l->sym) diag(Z, "incomplete structure element: %s", l->sym->name);