aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-05-24 12:43:03 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-05-24 12:43:03 -0700
commitcc043496045c5588cc969b5a75af60b084ecc69a (patch)
tree358c9e1c83122aa1e5f277f9b6d42f0469b145ae /sys
parentaf0c1d5ac3960776a4a485ca587744464630e634 (diff)
feat: added prototype of type info
Diffstat (limited to 'sys')
-rw-r--r--sys/cmd/cc/ast.c142
-rw-r--r--sys/cmd/cc/bits.c112
-rw-r--r--sys/cmd/cc/cc.c9
-rw-r--r--sys/cmd/cc/cc.h56
-rw-r--r--sys/cmd/cc/rules.mk1
5 files changed, 249 insertions, 71 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]);
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 = "<pointer>", .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