From cc043496045c5588cc969b5a75af60b084ecc69a Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Sun, 24 May 2020 12:43:03 -0700 Subject: feat: added prototype of type info --- sys/cmd/cc/ast.c | 142 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 50 deletions(-) (limited to 'sys/cmd/cc/ast.c') diff --git a/sys/cmd/cc/ast.c b/sys/cmd/cc/ast.c index dd9b03b..49e35fd 100644 --- a/sys/cmd/cc/ast.c +++ b/sys/cmd/cc/ast.c @@ -4,7 +4,8 @@ // helper macros #define alloc(ptr) (ptr) = mem·arenaalloc(C.heap, 1, sizeof *(ptr)) -#define movearray(dst, arr, n) (dst) = mem·arenaalloc(C.heap, (n), sizeof *(arr)), memcpy((dst), (arr), n * sizeof *(arr)), free(arr) +#define copyarray(dst, arr, n) (dst) = mem·arenaalloc(C.heap, (n), sizeof *(arr)), memcpy((dst), (arr), n * sizeof *(arr)) +#define movearray(dst, arr, n) copyarray(dst,arr,n), free(arr) #define attop(prs) ((uintptr)prs->sp == (uintptr)prs->spstk) #define peek(p, i) (p->tok[i]) @@ -1004,51 +1005,30 @@ Bad: // ----------------------------------------------------------------------- // declarations -/* see https://en.wikipedia.org/wiki/C_data_types */ -static uint64 validtypes[] = { - Tvoid, - Tbool, - - Tchar, - Tsign | Tchar, - Tunsign | Tchar, - - Tshort, Tshort | Tint, - Tsign | Tshort, Tsign | Tshort | Tint, - Tunsign | Tshort, Tunsign | Tshort | Tint, - - 0, Tint, - Tsign, Tsign | Tint, - Tunsign, Tunsign | Tint, - - Tlong, Tlong | Tint, - Tsign | Tlong, Tsign | Tlong | Tint, - Tunsign | Tlong, Tunsign | Tlong | Tint, - - Tvlong | Tlong, Tvlong | Tlong | Tint, - Tsign | Tvlong | Tlong, Tsign | Tvlong | Tlong | Tint, - Tunsign | Tvlong | Tlong, Tunsign | Tvlong | Tlong | Tint, - - Tfloat, - Tdouble, - Tlong | Tfloat, - - Timag, - Tcmplx, - - Tstruct, Tunion, Tenum, Tname, -}; - static error spec(Parser *p, Lexer *lx, uint64 *spec) { Token t; int n; + Sym *typ; uint64 s, sm; s = 0; - while (t = peek(p, 0), t.kind == Akeywd) { + 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; + } + sm = typ->typ - C.type.info; + s |= sm << 32; + continue; + } + + /* keyword */ switch (n = t.val.i) { case Kauto: case Kregister: case Kstatic: case Kextern: case Ktypedef: if (s & MaskMem) { @@ -1107,13 +1087,9 @@ spec(Parser *p, Lexer *lx, uint64 *spec) advance(p, lx); } - sm = (((s<<32)>>32) & ~(MaskQul | MaskMem)); - for (n = 0; n < arrlen(validtypes); n++) { - if (sm == validtypes[n]) { - *spec = s; - return 0; - } - } + *spec = s; + return 0; + /* TODO: serialize bitflags to string for nice error message */ errorat(lx->pos, "invalid type specifier: ''"); Bad: @@ -1122,6 +1098,35 @@ Bad: return 1; } +static +Type* +typespec(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]; + } + panicf("unreachable"); +} + + /* name declaration */ static error @@ -1131,11 +1136,11 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab) int n, k; uint64 s; Sym *sym; + Dtor *dt; Name *nm, *tmp; - /* i don't think i have to worry about multiple uses here */ - string args[100]; - Type types[100]; + /* max args = 100 */ + struct Obj args[100]; nm = *nmp; t = peek(p, 0); @@ -1251,24 +1256,61 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab) sym = lookupobj(p, t.val.s); if (!sym || (sym && sym->kind != Stype)) { while (t.kind == Aident) { - args[nm->sfx.call.n++] = t.val.s; + if (nm->sfx.call.n >= arrlen(args)) + panicf("out of ident buffer"); + args[nm->sfx.call.n++] = (struct Obj) { + .qual = 0, + .type = nil, + .name = t.val.s, + }; t = advance(p, lx); } if (nomatch(t, Arparen)) { errorat(t.pos, "token '%s' found in function parameter identifier list"); goto Bad; } + copyarray(nm->sfx.call.arg, args, nm->sfx.call.n); break; } goto Params; case Akeywd: - if (t.val.i < Kconst || t.val.i == Knoret || t.val.i == Kinline || t.val.i > Kenum) { + if (t.val.i < Kconst || t.val.i > Kenum) { 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); + goto Bad; + } + + pack(s, dt, &args[nm->sfx.call.n++]); + putdtor(p); + } while (t = peek(p, 0), t.kind == Acomma); + + if (t.kind == Aellip) { + nm->sfx.call.vararg = 1; + t = advance(p, lx); + } + + if (nomatch(t, Arparen)) { + errorat(t.pos, "token '%s' found in function parameter list"); + goto Bad; + } + copyarray(nm->sfx.call.arg, args, nm->sfx.call.n); + break; default: errorat(t.pos, "invalid token %s inside function call signature", tokens[t.kind]); -- cgit v1.2.1