aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/cc/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/cc/ast.c')
-rw-r--r--sys/cmd/cc/ast.c142
1 files changed, 92 insertions, 50 deletions
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]);