diff options
author | Nicholas Noll <nbnoll@eml.cc> | 2020-05-30 15:09:33 -0700 |
---|---|---|
committer | Nicholas Noll <nbnoll@eml.cc> | 2020-05-30 15:09:33 -0700 |
commit | cf65141f154651115028d6456a1d7582d30b2083 (patch) | |
tree | 731b1b1fe7e513e8e9410ad090687fa203838f43 /sys/cmd/cc/ast.c | |
parent | 038ea2d0a34fb362f577e6c9884c710ebaf4042e (diff) |
many bug fixes
Diffstat (limited to 'sys/cmd/cc/ast.c')
-rw-r--r-- | sys/cmd/cc/ast.c | 320 |
1 files changed, 194 insertions, 126 deletions
diff --git a/sys/cmd/cc/ast.c b/sys/cmd/cc/ast.c index df390ba..f5d7a42 100644 --- a/sys/cmd/cc/ast.c +++ b/sys/cmd/cc/ast.c @@ -22,6 +22,9 @@ string nameof(Name *n) { switch (n->kind) { + /* 0 corresponds to no state - i.e. an abstract name */ + case Nnil: + return nil; case Nident: return n->ident; case Nparen: @@ -61,43 +64,64 @@ closescope(Parser *p) /* temporary stack helpers */ static -Dtor* -getdtor(Parser *p) +Name* +getname(Parser *p) { - if (p->dt >= arrend(p->dtstk)) - panicf("dtor stack overflow"); - - return p->dt++; + if (p->nm >= arrend(p->nmstk)) + panicf("name stack overflow"); + return p->nm++; } +static void putdtor(Parser *p, Dtor *dt); + static void -putdtor(Parser *p) +putname(Parser *p, Name *n) { - if (p->dt <= p->dtstk) - panicf("dtor stack underflow"); - *p->dt-- = (Dtor){0}; + if (p->nm <= p->nmstk) + panicf("name stack underflow"); + + switch (n->kind) { + case Nnil: + case Nident: + break; + case Nparen: + putdtor(p, n->paren); + break; + case Nindex: + case Ncall: + putname(p, n->sfx.name); + break; + default: + panicf("unrecognized name kind"); + } + *p->nm-- = (Name){0}; } static -Name* -getname(Parser *p) +Dtor* +getdtor(Parser *p) { - if (p->nm >= arrend(p->nmstk)) - panicf("name stack overflow"); - return p->nm++; + if (p->dt >= arrend(p->dtstk)) + panicf("dtor stack overflow"); + + p->dt->name = getname(p); + return p->dt++; } static void -putname(Parser *p) +putdtor(Parser *p, Dtor *dt) { - if (p->nm <= p->nmstk) - panicf("name stack underflow"); + if (p->dt <= p->dtstk) + panicf("dtor stack underflow"); - *p->nm-- = (Name){0}; + /* the dtor could encompass multiple names hierarchically */ + putname(p, dt->name); + *p->dt-- = (Dtor){0}; } +/* TODO: This will fail for forward declarations */ static void declareobj(Parser *p, Decl *d) @@ -107,16 +131,24 @@ declareobj(Parser *p, Decl *d) uint32 kind; struct Decls *link; - kind = (d->spec & Mtype) ? Stype : Svar; - switch (d->kind) { case Dfunc: - case Dobj: + case Dvar: + kind = Svar; + goto one; + case Dtype: + kind = Stype; + one: ident = d->name; break; - case Dobjs: - while (link = &d->objs, link != nil) { + case Dvars: + kind = Svar; + goto many; + case Dtypes: + kind = Stype; + many: + while (link = &d->list, link != nil) { ident = link->name; sym = lookup(&p->sp->objs, ident); if (sym) { @@ -124,21 +156,26 @@ declareobj(Parser *p, Decl *d) return; } sym = define(&p->sp->objs, ident, kind); - sym->obj = d; + if (kind == Svar) + sym->obj = d; + else + sym->type = d->type; } break; default: - panicf("unrecognized node kind %d inside declaration", d->kind); + panicf("unrecognized node kind %d. expected declaration", d->kind); } - sym = lookup(&p->sp->objs, ident); if (sym) { errorat(peek(p, 0).pos, "redeclaration of name '%s' in object space", ident); return; } sym = define(&p->sp->objs, ident, kind); - sym->obj = d; + if (kind == Svar) + sym->obj = d; + else + sym->type = d->type; } /* enters the object identifier space */ @@ -212,7 +249,10 @@ nomatch(Token t, vlong kind) if (t.kind == kind) return 0; - errorat(t.pos, "expected token '%s', instead found '%s'", tokens[t.kind], tokens[kind]); + if (t.kind == Akeywd) + errorat(t.pos, "expected token '%s', instead found keyword '%s'", tokens[kind], keywords[t.val.i]); + else + errorat(t.pos, "expected token '%s', instead found '%s'", tokens[kind], tokens[t.kind]); return 1; } @@ -1275,6 +1315,8 @@ uint32 typeofname(Name *name, uint32 base) { switch (name->kind) { + /* Nnil corresponds to an abstract declarator (i.e. no identifier) */ + case Nnil: case Nident: return base; case Nparen: @@ -1325,10 +1367,10 @@ basetype(Parser *p, Lexer *lx, uint64 *s) return 0; } - m = (((*s<<32)>>32) & ~(MaskQul | MaskMem)); + m = (((*s<<32)>>32) & ~(MaskQul | MaskMem | MaskFcn)); for (n = 0; n < arrlen(validtypespec); n++) { - if (validtypespec[n] == m) - if (indextypespec < 0) { + if (validtypespec[n] == m) { + if (indextypespec[n] < 0) { m = *s >> 32; if (!m) { errorat(lx->pos, "not a valid type identifier"); @@ -1337,6 +1379,7 @@ basetype(Parser *p, Lexer *lx, uint64 *s) return m; } return indextypespec[n]; + } } errorat(lx->pos, "invalid type specifier"); @@ -1357,10 +1400,14 @@ namedecl(Parser *p, Lexer *lx, uint32 *base, int noname) errorat(lx->pos, "invalid declarator"); goto End; } - name = nameof(dt->name); + if (!noname || noname == 2 && dt->name->kind) + name = nameof(dt->name); + *base = typeofdtor(dt, *base); + putdtor(p, dt); + return name; End: - putdtor(p); + putdtor(p, dt); return nil; } @@ -1369,7 +1416,7 @@ End: static uint32 -enumerate(Parser *p, Lexer *lx, string name) +enumerate(Parser *p, Lexer *lx, string name, int kind) { int i, n; uint64 s; @@ -1419,12 +1466,14 @@ aggregate(Parser *p, Lexer *lx, string name, int kind) uint64 s; Token tk; /* TODO: think of a better soln */ - Field fs[1024], *f; - Expr *cx[1024], *x; + static Field fs[1024]; + Field *f; + static Expr *cx[1024]; + Expr *x; - for (n = 0; tk.kind != Arbrace && n < arrlen(fs); n++) { + for (n = 0, tk = peek(p, 0); tk.kind != Arbrace && n < arrlen(fs); n++) { fs[n].type = basetype(p, lx, &s); - fs[n].qual = (uint32)s; + fs[n].qual = (uint32)(s & ~(MaskTyp|MaskInt|MaskFlt)); Field: fs[n].name = namedecl(p, lx, &fs[n].type, 0); tk = peek(p, 0); @@ -1458,7 +1507,7 @@ aggregate(Parser *p, Lexer *lx, string name, int kind) } copyarray(f, fs, n); copyarray(x, cx, n); - return structtype(n, f, x); + return (kind == Tstruct) ? structtype(n, f, x) : uniontype(n, f, x); Bad: errorat(tk.pos, "failed to parse aggregate declaration"); return 0; @@ -1469,35 +1518,41 @@ error spec(Parser *p, Lexer *lx, uint64 *spec) { Token t; - int n; + int n, i; Sym *typ; string name; uint32 tag; uint64 s, sm; + static uint32 (*aggrfunc[2])(Parser *, Lexer *, string , int) = {aggregate, enumerate}; s = 0; while (t = peek(p, 0), t.kind >= Aident) { /* typename */ if (t.kind == Aident) { typ = lookupobj(p, t.val.s); - if (!typ || typ->kind != Stype) { - errorat(t.pos, "invalid type name '%s' in specifier", t.val.s); - goto Bad; - } + if (!typ || (typ && typ->kind != Stype)) + break; + sm = typ->type; - s |= sm << 32; + s |= (sm << 32 | Tname); + advance(p, lx); continue; } /* keyword */ switch (n = t.val.i) { - case Kauto: case Kregister: case Kstatic: case Kextern: case Ktypedef: + case Kauto: case Kregister: case Kstatic: case Kextern: case Ktypedef: case Ktls: if (s & MaskMem) { errorat(lx->pos, "multiple storage class specifiers: second was %s", keywords[n]); goto Bad; } break; + case Kinline: case Knoret: + if (s & Bit(n)) + warnat(lx->pos, "duplicate %s function specifier", keywords[n]); + break; + case Kconst: case Kvolatile: if (s & Bit(n)) warnat(lx->pos, "duplicate %s specifier found in declaration", keywords[n]); @@ -1527,6 +1582,7 @@ spec(Parser *p, Lexer *lx, uint64 *spec) goto Bad; } s += Bit(n); + t = advance(p, lx); continue; case Kvoid: case Kchar: case Kint: case Kfloat: case Kdouble: @@ -1534,46 +1590,18 @@ spec(Parser *p, Lexer *lx, uint64 *spec) errorat(lx->pos, "more than one base type specified"); goto Bad; } - s += Bit(n); break; case Kstruct: case Kunion: - if (s & (Tstruct | Tunion)) { - errorat(lx->pos, "more than one aggregate type specified"); - goto Bad; - } - s += Bit(n); - t = advance(p, lx); - if (t.kind != Aident && t.kind != Albrace) { - errorat(t.pos, "aggregate specifier missing valid declaration"); - goto Bad; - } - - name = nil; - tag = 0; - if (t.kind == Aident) { - name = t.val.s; - t = advance(p, lx); - } - if (t.kind == Albrace) { - t = advance(p, lx); - 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; - + i = 0; + goto Aggr; case Kenum: - if (s & Tenum) { - errorat(lx->pos, "more than one enum type specifier found"); + i = 1; + Aggr: + if (s & (Tstruct | Tunion | Tenum)) { + errorat(lx->pos, "more than one aggregate/enum type specified"); goto Bad; } - s += Bit(n); t = advance(p, lx); if (t.kind != Aident && t.kind != Albrace) { errorat(t.pos, "enum specifier missing valid declaration"); @@ -1588,10 +1616,11 @@ spec(Parser *p, Lexer *lx, uint64 *spec) } if (t.kind == Albrace) { t = advance(p, lx); - tag = enumerate(p, lx, name); + /* NOTE: This depends on the enum order. KEEP IN SYNC */ + tag = aggrfunc[i](p, lx, name, 1 << (n+1)); - if (nomatch(t, Arbrace)) { - errorat(t.pos, "invalid token %s in enum declaration", tokens[t.kind]); + if (t = peek(p, 0), nomatch(t, Arbrace)) { + errorat(t.pos, "invalid token %s in aggregate/enum declaration", tokens[t.kind]); goto Bad; } } @@ -1599,10 +1628,6 @@ spec(Parser *p, Lexer *lx, uint64 *spec) declaretag(p, tag, name); break; - - panicf("need to implement"); - break; - default: errorat(t.pos, "invalid keyword '%s' found in declaration specifier", keywords[n]); } @@ -1614,15 +1639,17 @@ spec(Parser *p, Lexer *lx, uint64 *spec) *spec = s; return 0; - /* TODO: serialize bitflags to string for nice error message */ - errorat(lx->pos, "invalid type specifier: ''"); Bad: + /* TODO: serialize bitflags to string for nice error message */ errorat(lx->pos, "ignoring specifier"); *spec = Sbad; return 1; } -/* name declaration */ +/* + * name declaration + * see dtor for valid values of ab + */ static error name(Parser *p, Lexer *lx, Name **nmp, int ab) @@ -1640,7 +1667,7 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab) t = peek(p, 0); switch (k = t.kind) { case Aident: - if (ab) { + if (ab == 1) { errorat(t.pos, "identifier not allowed in abstract declarator"); goto Bad; } @@ -1649,17 +1676,19 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab) break; case Alparen: + advance(p, lx); nm->kind = Nparen; nm->paren = getdtor(p); if (dtor(p, lx, nm->paren, ab)) { - putdtor(p); + putdtor(p, nm->paren); nm->paren = nil; errorat(lx->pos, "invalid declarator in parenthesis"); goto Bad; } + t = peek(p, 0); - if (t.kind != Arparen) { - putdtor(p); + if (nomatch(t, Arparen)) { + putdtor(p, nm->paren); nm->paren = nil; errorat(lx->pos, "missing closing paren in declarator"); goto Bad; @@ -1668,15 +1697,18 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab) case Albrakt: if (ab) - break; - + goto Sfx; errorat(lx->pos, "missing identifier in non-abstract declarator"); + /* fallthrough */ default: + if (ab) + goto Sfx; errorat(lx->pos, "invalid token '%s' in name declaration", tokens[k]); goto Bad; } t = advance(p, lx); +Sfx: for (;;) { switch (k = t.kind) { case Albrakt: @@ -1725,7 +1757,7 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab) t = peek(p, 0); if (nomatch(t, Arbrakt)) { - errorat(lx->pos, "unterminated index expression"); + errorat(t.pos, "unterminated index expression"); goto Bad; } @@ -1766,7 +1798,7 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab) copyarray(nm->sfx.call.arg, args, nm->sfx.call.n); break; } - goto Params; + goto ParamLoop; case Akeywd: if (t.val.i < Kconst || t.val.i > Kenum) { @@ -1774,21 +1806,24 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab) goto Bad; } - Params: - do { - if (nm->sfx.call.n >= arrlen(args)-1) - panicf("out of argument buffer"); + ParamLoop: + if (nm->sfx.call.n >= arrlen(args)-1) + panicf("out of argument buffer"); - 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, 0); + 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; + } - nm->sfx.call.n++; - } while (t = peek(p, 0), t.kind == Acomma); + args[nm->sfx.call.n].qual = (uint32)s & ~(MaskTyp|MaskInt|MaskFlt); + args[nm->sfx.call.n].name = namedecl(p, lx, &args[nm->sfx.call.n].type, 2); + + nm->sfx.call.n++; + if ((t = peek(p, 0)).kind == Acomma) { + advance(p, lx); + goto ParamLoop; + } if (t.kind == Aellip) { nm->sfx.call.dots = 1; @@ -1822,7 +1857,13 @@ Bad: return 1; } -/* pointer kind is partitioned into 8x6 regions */ +/* pointer kind is partitioned into 8x6 regions + * ab => abstract + * @ 0: must have identifier + * @ 1: must not have identifier + * @ 2: don't care + * else: undefined + */ static error dtor(Parser *p, Lexer *lx, Dtor *d, int ab) @@ -1840,10 +1881,11 @@ dtor(Parser *p, Lexer *lx, Dtor *d, int ab) ptr->link = nil; t = peek(p, 0); - if (t.kind != Astar) - if (t.kind == Aident || t.kind == Arparen) + if (t.kind != Astar) { + if (ab || t.kind == Aident || t.kind == Arparen) goto Name; goto Bad; + } Ptr: ptr->kind |= Bit(n); advance(p, lx); @@ -1851,7 +1893,7 @@ Key: t = peek(p, 0); switch (k = t.kind) { case Akeywd: - if (Kconst <= k && k <= Katomic) + if (Kconst <= t.val.i && t.val.i <= Katomic) ptr->kind |= Bit(6*n + (t.val.i - Kconst + 1)); else { errorat(lx->pos, "invalid keyword '%s' modifies pointer", keywords[t.val.i]); @@ -1876,6 +1918,8 @@ Key: goto Name; default: + if (ab) + goto Name; errorat(lx->pos, "invalid token '%s' modifies pointer specification", tokens[t.kind]); goto Bad; } @@ -1909,29 +1953,35 @@ decl(Parser *p, Lexer *lx) } x = nil; - d->spec = (uint32)s; + d->spec = (uint32)s & ~(MaskInt|MaskFlt|MaskTyp); d->type = base; d->name = namedecl(p, lx, &d->type, 0); + /* TODO: think about functions (both decls and defs) */ + d->kind = (s & Mtype) ? Dtype : Dvar; switch (t = peek(p, 0), t.kind) { case Aeq: + if (s & Mtype) { + errorat(d->pos.beg, "initialization of type not allowed"); + goto Bad; + } t = advance(p, lx); x = initx(p, lx); + d->kind = Dvar; if (t.kind != Acomma) { - d->kind = Dobj; d->init = x; - break; + goto Semi; } /* fallthrough */ case Acomma: - d->kind = Dobjs; - d->objs.init = x; + d->kind |= Dlist; + d->list.init = x; /* move singleton data over */ name = d->name; type = d->type; - d->objs.name = name; - d->objs.type = type; - ds = &d->objs; + d->list.name = name; + d->list.type = type; + ds = &d->list; /* iterate until we hit end of list */ while (t.kind == Acomma) { t = advance(p, lx); @@ -1948,7 +1998,7 @@ decl(Parser *p, Lexer *lx) } else ds->init = nil; } - break; + goto Semi; case Albrace: d->kind = Dfunc; @@ -1969,9 +2019,15 @@ decl(Parser *p, Lexer *lx) goto Bad; } closescope(p); + break; default: - ; + Semi: + if (nomatch(t, Asemi)) { + errorat(t.pos, "no semicolon after declaration"); + goto Bad; + } + t = advance(p, lx); } d->pos.end = lx->pos; @@ -1985,10 +2041,22 @@ Bad: // ----------------------------------------------------------------------- // top level api +void +setup(Parser *p, Lexer *lx) +{ + advance(p,lx); + advance(p,lx); + + /* define all builtin typedefs */ + declareobj(p, &C.builtin.vargs); +} + error parse(Parser *p, Lexer *lx) { Token tok; + + setup(p, lx); while ((tok = peek(p, 0)), tok.kind > Aeof) { if (p->ast.len >= p->ast.cap) { p->ast.cap += 20; |