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 ++++++++++++++++++++++++++++++++++------------------ sys/cmd/cc/bits.c | 112 +++++++++++++++++++++++++++++++++++++++++ sys/cmd/cc/cc.c | 9 ++++ sys/cmd/cc/cc.h | 56 +++++++++++++-------- sys/cmd/cc/rules.mk | 1 + 5 files changed, 249 insertions(+), 71 deletions(-) create mode 100644 sys/cmd/cc/bits.c (limited to 'sys') 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]); diff --git a/sys/cmd/cc/bits.c b/sys/cmd/cc/bits.c new file mode 100644 index 0000000..19adf52 --- /dev/null +++ b/sys/cmd/cc/bits.c @@ -0,0 +1,112 @@ +#include "cc.h" + +// ----------------------------------------------------------------------- +// Architecture + +enum +{ + arch·x64, + numarch, +}; + +// ----------------------------------------------------------------------- +// Types + +/* + * enumerated type specifers + * see https://en.wikipedia.org/wiki/C_data_types + */ +#define VOID X(Tvoid, 0) + +#define BOOL X(Tbool, 1) +#define CHAR X(Tchar, 2) +#define SCHAR X(Tsign|Tchar, 3) +#define UCHAR X(Tunsign|Tchar, 4) + +#define SHORT X(Tshort, 5), X(Tshort|Tint, 5) +#define SSHORT X(Tsign|Tshort, 6), X(Tsign|Tshort|Tint, 6) +#define USHORT X(Tunsign|Tshort, 7), X(Tunsign|Tshort|Tint, 7) + +#define INT X(0, 8), X(Tint, 8) +#define SINT X(Tsign, 9), X(Tsign|Tint, 9) +#define UINT X(Tunsign, 10), X(Tunsign|Tint, 10) + +#define LONG X(Tlong, 11), X(Tlong|Tint, 11) +#define SLONG X(Tsign|Tlong, 12), X(Tsign|Tlong|Tint, 12) +#define ULONG X(Tunsign|Tlong, 13), X(Tunsign|Tlong|Tint, 13) + +#define VLONG X(Tvlong, 14), X(Tvlong|Tint, 14) +#define SVLONG X(Tsign|Tvlong, 15), X(Tsign|Tvlong|Tint, 15) +#define UVLONG X(Tunsign|Tvlong, 16), X(Tunsign|Tvlong|Tint, 16) + +#define FLOAT X(Tfloat, 17) +#define DOUBLE X(Tdouble, 18) +#define LONGDB X(Tlong|Tdouble, 19) +#define COMPLEX X(Tcmplx, 20) +#define IMAGINARY X(Timag, 21) + +/* fixed width definitions */ +#define DEF(name, sz, aln, mx, sgn) {.ident=#name, .size=sz, .align=aln, .max=mx, .sign=sgn } + +#define INT8(name) DEF(name, 1, 1, 0x7f, 0) +#define UINT8(name) DEF(name, 1, 1, 0xff, 1) + +#define INT16(name) DEF(name, 2, 2, 0x7fff, 0) +#define UINT16(name) DEF(name, 2, 2, 0xffff, 1) + +#define INT32(name) DEF(name, 4, 4, 0x7fffffff, 0) +#define UINT32(name) DEF(name, 4, 4, 0xffffffff, 1) + +#define INT64(name) DEF(name, 8, 8, 0x7fffffffffffffff, 0) +#define UINT64(name) DEF(name, 8, 8, 0xffffffffffffffff, 1) + +/* architecture specific definitions */ +// TODO: max value should be able to take floats +#define TYPES \ + TYPE(DEF(void, 0, 0, 0, 0), VOID) \ + TYPE(INT8(bool), BOOL) \ + TYPE(UINT8(char), CHAR) \ + TYPE(INT8(signed char), SCHAR) \ + TYPE(UINT8(unsigned char), UCHAR) \ + TYPE(INT16(short), SHORT) \ + TYPE(INT16(signed short), SSHORT) \ + TYPE(UINT16(unsigned short), USHORT) \ + TYPE(INT32(int), INT) \ + TYPE(INT32(signed int), SINT) \ + TYPE(UINT32(unsigned int), UINT) \ + TYPE(INT64(long), LONG) \ + TYPE(INT64(signed long), SLONG) \ + TYPE(UINT64(unsigned long), ULONG) \ + TYPE(INT64(long long), VLONG) \ + TYPE(INT64(signed long long), SVLONG) \ + TYPE(UINT64(unsigned long long), UVLONG) \ + TYPE(DEF(float, 4, 4, 0, 0), FLOAT) \ + TYPE(DEF(double, 8, 8, 0, 0), DOUBLE) \ + TYPE(DEF(long double, 16, 16, 0, 0), LONGDB) \ + TYPE(DEF(complex, 8, 8, 0, 0), COMPLEX) \ + TYPE(DEF(imaginary, 4, 4, 0, 0), IMAGINARY) \ + +Type pointer = {.ident = "", .size=8, .align=8, .max=0xffffffffffffffff, .sign=0}; + +/* pack architecture specific definitions into exported arrays */ +#define TYPE(a, ...) a, +Type basetypes[] = { + TYPES +}; +#undef TYPE + +#define TYPE(a, ...) __VA_ARGS__, +#define X(a, b) a +uint64 validtypespec[40] = { + TYPES + Tstruct, Tunion, Tenum, Tname, +}; +#undef X + +#define X(a, b) b +int indextypespec[40] = { + TYPES + -1, -1, -1, -1, +}; +#undef X +#undef TYPE diff --git a/sys/cmd/cc/cc.c b/sys/cmd/cc/cc.c index 02ff773..24d8e45 100644 --- a/sys/cmd/cc/cc.c +++ b/sys/cmd/cc/cc.c @@ -194,6 +194,15 @@ init(void) C.inc.dir[C.inc.len++] = "."; C.outfile = nil; + + /* type info */ + C.type.len = arrlen(basetypes); + C.type.cap = 100 + arrlen(basetypes); + C.type.info = calloc(C.type.cap, sizeof(*C.type.info)); + + memcpy(C.type.info, basetypes, C.type.len * sizeof(*C.type.info)); + for (i = 0; i < arrlen(basetypes); i++) + intern(&C.type.info[i].ident); } void diff --git a/sys/cmd/cc/cc.h b/sys/cmd/cc/cc.h index 4b61346..e8ab05e 100644 --- a/sys/cmd/cc/cc.h +++ b/sys/cmd/cc/cc.h @@ -19,10 +19,12 @@ typedef struct Scope Scope; typedef struct Parser Parser; -typedef struct Node Node; typedef struct Ptr Ptr; typedef struct Name Name; typedef struct Dtor Dtor; +typedef struct Obj Obj; + +typedef struct Node Node; typedef struct Decl Decl; typedef struct Stmt Stmt; typedef struct Expr Expr; @@ -40,12 +42,12 @@ typedef struct Compiler Compiler; KEYWORD(Kextern,"extern") \ KEYWORD(Ktls,"thread_local") \ KEYWORD(Ktypedef,"typedef") \ + KEYWORD(Kinline,"inline") \ + KEYWORD(Knoret,"_Noreturn") \ KEYWORD(Kconst,"const") \ KEYWORD(Kvolatile,"volatile") \ KEYWORD(Krestrict,"restrict") \ KEYWORD(Katomic,"_Atomic") \ - KEYWORD(Kinline,"inline") \ - KEYWORD(Knoret,"_Noreturn") \ KEYWORD(Ksigned,"signed") \ KEYWORD(Kunsigned,"unsigned") \ KEYWORD(Kvoid,"void") \ @@ -242,7 +244,7 @@ struct Sym union { string macro; Decl *obj; - Type *tag; + Type *typ; Stmt *blk; }; }; @@ -524,7 +526,6 @@ enum MaskSgn = Tsign | Tunsign, Tvoid = iota(Kvoid), - Tfloat = iota(Kfloat), Tdouble = iota(Kdouble), Tcmplx = iota(Kcomplex), @@ -561,20 +562,12 @@ struct Ptr Ptr *link; }; -struct Param -{ - uint32 qual; - Type *type; - string name; -}; - struct Name { uint32 kind; union { string ident; struct Dtor *paren; - /* This is bloated ! */ struct { Name *name; union { @@ -584,7 +577,8 @@ struct Name } idx; struct { int n; - struct Param *arg; + int vararg : 1; + Obj *arg; } call; }; } sfx; @@ -605,6 +599,14 @@ struct Decls }; /* final ast node */ + +struct Obj +{ + uint32 qual; + Type *type; + string name; +}; + struct Decl { struct Node; @@ -633,21 +635,26 @@ enum /* types */ struct Type { - Sym *sym; + uint32 kind; string ident; - uint64 kind; + Sym *sym; uintptr size; - uint16 align; + uintptr max; + uint16 align : 8; + uint16 sign : 2; union { - Type *ptr; + struct { + uint32 qual; + Type *base; + } ptr; struct { int len; Type *elt; } arr; struct { - int len; - Dtor *d; - Expr *x; + int len; + Obj *f; + Expr *x; } agr; struct { int len; @@ -657,6 +664,13 @@ struct Type }; }; +/* platform specific */ +extern Type pointer; +extern Type basetypes[22]; +/* mandated by C standard */ +extern uint64 validtypespec[40]; +extern int indextypespec[40]; + struct Scope { SymTab tags; diff --git a/sys/cmd/cc/rules.mk b/sys/cmd/cc/rules.mk index 2db1c56..34df34d 100644 --- a/sys/cmd/cc/rules.mk +++ b/sys/cmd/cc/rules.mk @@ -6,6 +6,7 @@ SRCS_$(d) := \ $(d)/pp.c \ $(d)/lex.c \ $(d)/ast.c \ + $(d)/bits.c \ $(d)/cc.c -- cgit v1.2.1