From 680d60678b273f1ff20b013b24954773f76b4e1d Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Fri, 29 May 2020 14:40:50 -0700 Subject: checkin: before fix of stale type pointer bug --- sys/cmd/cc/ast.c | 504 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 360 insertions(+), 144 deletions(-) (limited to 'sys/cmd/cc/ast.c') diff --git a/sys/cmd/cc/ast.c b/sys/cmd/cc/ast.c index 0547712..e471a32 100644 --- a/sys/cmd/cc/ast.c +++ b/sys/cmd/cc/ast.c @@ -31,14 +31,15 @@ nameof(Name *n) return nameof(n->sfx.name); } panicf("unreachable"); + return nil; } static void openscope(Parser *p) { - if (++p->sp == p->spstk + arrlen(p->spstk)) - panicf("too many nested scopes: crashing"); + if (++p->sp >= arrend(p->spstk)) + panicf("scope stack overflow"); } /* @@ -50,21 +51,22 @@ static void closescope(Parser *p) { - if (p->sp == p->spstk) - panicf("attempting to close the top level scope: crashing"); + if (p->sp <= p->spstk) + panicf("scope stack underflow"); forgetall(&p->sp->objs); forgetall(&p->sp->tags); p->sp--; } +/* temporary stack helpers */ static Dtor* getdtor(Parser *p) { - if (p->dt >= p->dtstk + arrlen(p->dtstk)) { - panicf("out of dtor buffer space"); - } + if (p->dt >= arrend(p->dtstk)) + panicf("dtor stack overflow"); + return p->dt++; } @@ -72,9 +74,8 @@ static void putdtor(Parser *p) { - if (p->dt == p->dtstk) { - panicf("too many frees of dtor buffer space"); - } + if (p->dt <= p->dtstk) + panicf("dtor stack underflow"); *p->dt-- = (Dtor){0}; } @@ -82,9 +83,8 @@ static Name* getname(Parser *p) { - if (p->nm >= p->nmstk + arrlen(p->nmstk)) { - panicf("out of dtor buffer space"); - } + if (p->nm >= arrend(p->nmstk)) + panicf("name stack overflow"); return p->nm++; } @@ -92,48 +92,44 @@ static void putname(Parser *p) { - if (p->nm == p->nmstk) { - panicf("too many frees of dtor buffer space"); - } + if (p->nm <= p->nmstk) + panicf("name stack underflow"); + *p->nm-- = (Name){0}; } -#if 0 static void declareobj(Parser *p, Decl *d) { Sym *sym; string ident; + uint32 kind; struct Decls *link; + kind = (d->spec & Mtype) ? Stype : Svar; + switch (d->kind) { case Dfunc: - ident = nameof(&d->func.name); - break; - - case Dvar: - ident = nameof(&d->var.name); - break; - - case Dtype: - ident = nameof(&d->type.name); + case Dobj: + ident = d->name; break; - case Dvars: - while (link = d->var.link, link != nil) { - ident = nameof(&link->name); + case Dobjs: + while (link = &d->objs, link != nil) { + ident = link->name; sym = lookup(&p->sp->objs, ident); if (sym) { errorat(peek(p, 0).pos, "redeclaration of name '%s' in object space", ident); return; } - define(&p->sp->objs, ident, Sobj); + sym = define(&p->sp->objs, ident, kind); + sym->obj = d; } - return; - default: - panicf("unrecognized node kind %d inside declaraction", d->kind); + break; + default: + panicf("unrecognized node kind %d inside declaration", d->kind); } sym = lookup(&p->sp->objs, ident); @@ -141,24 +137,43 @@ declareobj(Parser *p, Decl *d) errorat(peek(p, 0).pos, "redeclaration of name '%s' in object space", ident); return; } + sym = define(&p->sp->objs, ident, kind); + sym->obj = d; +} - define(&p->sp->objs, ident, Sobj); +/* enters the object identifier space */ +static +void +declareenum(Parser *p, int n, string *elts, Expr *vals) +{ + int i; + Sym *s; + + for (i = 0; i < n; i++) { + s = lookup(&p->sp->objs, elts[i]); + if (s) { + errorat(peek(p, 0).pos, "redeclaration of name %s in object space", elts[i]); + continue; + } + s = define(&p->sp->objs, elts[i], Senum); + s->val = vals + i; + } } static -Sym * -declaretag(Parser *p, Type *t) +void +declaretag(Parser *p, Type *t, string name) { Sym *sym; - sym = lookup(&p->sp->tags, t->ident); + sym = lookup(&p->sp->tags, name); if (sym) { - errorat(peek(p, 0).pos, "redeclaration of name '%s' in tag space", t->ident); - return sym; + errorat(peek(p, 0).pos, "redeclaration of name '%s' in tag space", name); + return; } - return define(&p->sp->tags, t->ident, Stype); + sym = define(&p->sp->tags, name, Stype); + sym->typ = t; } -#endif static Sym * @@ -206,7 +221,6 @@ nomatch(Token t, vlong kind) static error spec(Parser *, Lexer *, uint64 *); static error dtor(Parser *p, Lexer *lx, Dtor *d, int ab); -static Type *typeofspec(Parser *, Lexer *, uint64 *); static Type *typeofdtor(Dtor *, Type *); static Decl *decl(Parser *, Lexer *); @@ -1014,29 +1028,149 @@ Bad: } // ----------------------------------------------------------------------- -// declarations +// types + +Type * +ptrtype(Type *base, uint32 qual) +{ + Type *t; + + t = type(); + t->kind = Tptr; + t->ptr.base = base; + t->ptr.qual = qual; + t->size = pointer.size; + t->align = pointer.align; + t->sign = pointer.sign; + + return t; +} + +Type* +arraytype(Type *base, uint32 qual, Expr *ix) +{ + int n; + Type *t; + + /* TODO: evaluate the length */ + n = 10; + t = type(); + t->kind = Tarray; + t->ptr.base = base; + t->size = n * base->size; + t->align = base->align; + t->sign = 0; + + return t; +} + +Type* +functype(Type *ret, int n, Field *args, int dots) +{ + int i; + Type *t; + + t = type(); + t->kind = Tfunc; + t->size = pointer.size; + t->align = pointer.align; + t->sign = pointer.sign; + + t->func.ret = ret; + t->func.n = n; + t->func.arg = args; + t->func.dots = dots; + + return t; +} + +#define ALIGN_DOWN(n, a) ((n) & ~((a)-1)) +#define ALIGN_UP(n, a) ALIGN_DOWN((n) + (a)-1, (a)) +Type * +structtype(int n, Field *field, Expr *bits) +{ + Type *t; + Field *f, *e; + + t = type(); + t->kind = Tstruct; + t->size = 0; + t->align = 0; + for (f = field, e = field+n; f != e; ++f) { + t->size += f->type->size + ALIGN_UP(t->size, f->type->align); + t->align = MAX(t->align, f->type->align); + } + t->aggr.len = n; + t->aggr.f = field; + t->aggr.x = bits; + return t; +} + +Type * +uniontype(int n, Field *field, Expr *bits) +{ + Type *t; + Field *f, *e; + + t = type(); + t->kind = Tstruct; + t->size = 0; + t->align = 0; + for (f = field, e = field+n; f != e; ++f) { + t->size = MAX(t->size, f->type->size); + t->align = MAX(t->align, f->type->align); + } + t->aggr.len = n; + t->aggr.f = field; + t->aggr.x = bits; + + return t; +} + +Type * +enumtype(int n, string *elts, Expr *vals) +{ + Type *t; + Field *f, *e; + + t = type(); + t->kind = Tenum; + /* TODO: dont hardcode int32 */ + t->size = 4; + t->align = 4; + t->enm.len = n; + t->enm.elt = elts; + t->enm.val = vals; + + return t; +} +#undef ALIGN_UP +#undef ALIGN_DOWN + +/* unpacking C declarations into sensible types */ static Type * -typeofname(Name *name, Type *type) +typeofname(Name *name, Type *base) { switch (name->kind) { case Nident: - return type; + return base; case Nparen: - return typeofdtor(name->paren, type); + return typeofdtor(name->paren, base); case Nindex: - return typeofname(name->sfx.name, array(type, name->sfx.idx.q, name->sfx.idx.x)); + return typeofname(name->sfx.name, arraytype(base, name->sfx.idx.q, name->sfx.idx.x)); case Ncall: - return typeofname(name->sfx.name, func(type, name->sfx.call.n, name->sfx.call.arg, name->sfx.call.dots)); + return typeofname(name->sfx.name, functype(base, name->sfx.call.n, name->sfx.call.arg, name->sfx.call.dots)); default: panicf("unreachable"); } + return nil; } static Type * -typeofdtor(Dtor *decl, Type* type) +typeofdtor(Dtor *decl, Type* base) { int n; Ptr *p; @@ -1046,7 +1180,7 @@ typeofdtor(Dtor *decl, Type* type) p = &decl->ptr; b = p->kind; while (b & 1) { - type = ptr(type, b >> 1); + base = ptrtype(base, b >> 1); if (++n >= 8) { p = p->link; b = p->kind; @@ -1055,34 +1189,124 @@ typeofdtor(Dtor *decl, Type* type) } } - return typeofname(decl->name, type); + return typeofname(decl->name, base); } static -Type * -aggr(Parser *p, Lexer *lx, string name, int kind) +Type* +basetype(Parser *p, Lexer *lx, uint64 *s) { int n; + uint64 m; + + if (spec(p, lx, s)) { + errorat(lx->pos, "failed to parse type specifier"); + return nil; + } + + m = (((*s<<32)>>32) & ~(MaskQul | MaskMem)); + for (n = 0; n < arrlen(validtypespec); n++) { + if (validtypespec[n] == m) + if (indextypespec < 0) { + m = *s >> 32; + if (!m) { + errorat(lx->pos, "not a valid type identifier"); + return nil; + } + return C.type.info + m; + } + return C.type.info + indextypespec[n]; + } + + errorat(lx->pos, "invalid type specifier"); + return nil; +} + +static +string +namedecl(Parser *p, Lexer *lx, Type **base) +{ + Dtor *dt; + string name; + Type *t; + + dt = getdtor(p); + name = nil; + if (dtor(p, lx, dt, 0)) { + errorat(lx->pos, "invalid declarator"); + goto End; + } + name = nameof(dt->name); + *base = typeofdtor(dt, *base); +End: + putdtor(p); + return nil; +} + +// ----------------------------------------------------------------------- +// declarations + +static +Type * +enumerate(Parser *p, Lexer *lx, string name) +{ + int i, n; uint64 s; - Dtor *dt; Token tk; Type *t; - Type *fs[1024]; - byte *nm[1024]; - Expr *cx[1024]; + /* TODO: think of a better soln */ + string nm[1024], *elts; + Expr *cx[1024], *vals; - n = -1; - for (;tk.kind != Arbrace && n < arrlen(fs); n++) { - t = typeofspec(p, lx, &s); + for (n = 0; tk.kind != Arbrace && n < arrlen(nm); n++) { + if (tk.kind != Aident) { + errorat(tk.pos, "invalid token %s in enum declaration", tokens[tk.kind]); + goto Bad; + } + nm[n] = tk.val.s; + cx[n] = nil; - Field: - dt = getdtor(p); - dtor(p, lx, dt, 0); - fs[n] = typeofdtor(dt, t); - nm[n] = nameof(dt->name); - putdtor(p); + tk = advance(p, lx); + switch(tk.kind) { + case Aeq: + advance(p, lx); + cx[n] = expr(p, lx); + tk = peek(p, 0); + if (tk.kind != Acomma) + continue; + /* fallthrough */ + case Acomma: + tk = advance(p, lx); + } + } + copyarray(elts, nm, n); + copyarray(vals, cx, n); - tk = peek(p, 0); + t = enumtype(n, elts, vals); + declareenum(p, n, elts, vals); + return t; +Bad: + errorat(tk.pos, "failed to parse enum declaration"); + return nil; +} + +static +Type * +aggregate(Parser *p, Lexer *lx, string name, int kind) +{ + int n; + uint64 s; + Token tk; + /* TODO: think of a better soln */ + Field fs[1024], *f; + Expr *cx[1024], *x; + + for (n = 0; tk.kind != Arbrace && n < arrlen(fs); n++) { + fs[n].type = basetype(p, lx, &s); + fs[n].qual = (uint32)s; + Field: + fs[n].name = namedecl(p, lx, &fs[n].type); + tk = peek(p, 0); switch (tk.kind) { case Acolon: advance(p, lx); @@ -1111,7 +1335,9 @@ aggr(Parser *p, Lexer *lx, string name, int kind) goto Bad; } } - + copyarray(f, fs, n); + copyarray(x, cx, n); + return structtype(n, f, x); Bad: errorat(tk.pos, "failed to parse aggregate declaration"); return nil; @@ -1198,7 +1424,7 @@ spec(Parser *p, Lexer *lx, uint64 *spec) s += Bit(n); t = advance(p, lx); if (t.kind != Aident && t.kind != Albrace) { - errorat(t.pos, "struct specifier missing valid declaration"); + errorat(t.pos, "aggregate specifier missing valid declaration"); goto Bad; } @@ -1210,13 +1436,15 @@ spec(Parser *p, Lexer *lx, uint64 *spec) } if (t.kind == Albrace) { t = advance(p, lx); - tag = aggr(p, lx, name, s & (Tstruct | Tunion)); + tag = aggregate(p, lx, name, s & (Tstruct | Tunion)); if (nomatch(t, Arbrace)) { errorat(t.pos, "invalid token %s in struct/union declaration", tokens[t.kind]); goto Bad; } } + if (name) + declaretag(p, tag, name); break; case Kenum: @@ -1225,6 +1453,32 @@ spec(Parser *p, Lexer *lx, uint64 *spec) goto Bad; } s += Bit(n); + t = advance(p, lx); + if (t.kind != Aident && t.kind != Albrace) { + errorat(t.pos, "enum specifier missing valid declaration"); + goto Bad; + } + + name = nil; + tag = nil; + if (t.kind == Aident) { + name = t.val.s; + t = advance(p, lx); + } + if (t.kind == Albrace) { + t = advance(p, lx); + tag = enumerate(p, lx, name); + + if (nomatch(t, Arbrace)) { + errorat(t.pos, "invalid token %s in enum declaration", tokens[t.kind]); + goto Bad; + } + } + if (name) + declaretag(p, tag, name); + break; + + panicf("need to implement"); break; @@ -1247,37 +1501,6 @@ Bad: return 1; } -static -Type* -typeofspec(Parser *p, Lexer *lx, uint64 *s) -{ - int n; - uint64 m; - - if (spec(p, lx, s)) { - errorat(lx->pos, "failed to parse type specifier"); - return nil; - } - - m = (((*s<<32)>>32) & ~(MaskQul | MaskMem)); - for (n = 0; n < arrlen(validtypespec); n++) { - if (validtypespec[n] == m) - if (indextypespec < 0) { - m = *s >> 32; - if (!m) { - errorat(lx->pos, "not a valid type identifier"); - return nil; - } - return C.type.info + m; - } - return C.type.info + indextypespec[n]; - } - - errorat(lx->pos, "invalid type specifier"); - return nil; -} - - /* name declaration */ static error @@ -1286,12 +1509,11 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab) Token t; int n, k; uint64 s; - Sym *sym; - Dtor *dt; + Sym *sym; Name *nm, *tmp; /* max args = 100 */ - struct Obj args[100]; + struct Field args[100]; nm = *nmp; t = peek(p, 0); @@ -1408,8 +1630,8 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab) if (!sym || (sym && sym->kind != Stype)) { while (t.kind == Aident) { if (nm->sfx.call.n >= arrlen(args)) - panicf("out of ident buffer"); - args[nm->sfx.call.n++] = (struct Obj) { + panicf("ident stack overflow"); + args[nm->sfx.call.n++] = (struct Field) { .qual = 0, .type = nil, .name = t.val.s, @@ -1430,25 +1652,21 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab) errorat(t.pos, "invalid keyword %s inside function signature"); goto Bad; } + Params: do { if (nm->sfx.call.n >= arrlen(args)-1) panicf("out of argument buffer"); - if (spec(p, lx, &s)) { - errorat(lx->pos, "invalid type qualifier list in function signature"); - goto Bad; - } - - dt = getdtor(p); - if (dtor(p, lx, dt, 0)) { - errorat(lx->pos, "could not parse declarator of function argument"); - putdtor(p); + args[nm->sfx.call.n].type = basetype(p, lx, &s); + if (!args[nm->sfx.call.n].type) { + errorat(lx->pos, "could not parse base type in function call"); goto Bad; } + args[nm->sfx.call.n].qual = (uint32)s; + args[nm->sfx.call.n].name = namedecl(p, lx, &args[nm->sfx.call.n].type); - pack(s, dt, &args[nm->sfx.call.n++]); - putdtor(p); + nm->sfx.call.n++; } while (t = peek(p, 0), t.kind == Acomma); if (t.kind == Aellip) { @@ -1554,58 +1772,60 @@ decl(Parser *p, Lexer *lx) Token t; Decl *d; Expr *x; - Dtor *dt, *dt0; + Type *base, *type; + string name; struct Decls *ds; alloc(d); + d->kind = 0; d->pos.beg = lx->pos; - if (spec(p, lx, &s)) { - errorat(lx->pos, "invalid declaration specifier"); - goto Bad; - } - - dt = getdtor(p); - dt0 = dt; - if (dtor(p, lx, dt, 0)) { - errorat(lx->pos, "invalid declarator"); + base = basetype(p, lx, &s); + if (!base) { + errorat(lx->pos, "could not parse type declaration"); goto Bad; } x = nil; - ds = &d->vars; d->spec = (uint32)s; + d->type = base; + d->name = namedecl(p, lx, &d->type); switch (t = peek(p, 0), t.kind) { case Aeq: t = advance(p, lx); x = expr(p, lx); if (t.kind != Acomma) { - d->kind = Dvar; + d->kind = Dobj; d->init = x; break; } /* fallthrough */ case Acomma: - d->kind = Dvars; - d->vars.init = x; + d->kind = Dobjs; + d->objs.init = x; + /* move singleton data over */ + name = d->name; + type = d->type; + d->objs.name = name; + d->objs.type = type; + ds = &d->objs; + /* iterate until we hit end of list */ while (t.kind == Acomma) { + t = advance(p, lx); + alloc(ds->link); ds = ds->link; - - t = advance(p, lx); - dt = getdtor(p); - if (dtor(p, lx, dt, 0)) { - errorat(lx->pos, "invalid declarator"); - goto Bad; - } + ds->type = base; + ds->name = namedecl(p, lx, &ds->type); t = peek(p, 0); if (t.kind == Aeq) { t = advance(p, lx); ds->init = expr(p, lx); - } + } else + ds->init = nil; } break; @@ -1634,13 +1854,9 @@ decl(Parser *p, Lexer *lx) } d->pos.end = lx->pos; - // declareobj(p, d); - while (dt-- >= dt0) - putdtor(p); + declareobj(p, d); return d; Bad: - while (dt-- >= dt0) - putdtor(p); errorat(lx->pos, "failed to parse top level declaration"); return nil; } -- cgit v1.2.1