aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd')
-rw-r--r--sys/cmd/cc/ast.c167
-rw-r--r--sys/cmd/cc/cc.c3
-rw-r--r--sys/cmd/cc/cc.h42
-rw-r--r--sys/cmd/rules.mk4
4 files changed, 194 insertions, 22 deletions
diff --git a/sys/cmd/cc/ast.c b/sys/cmd/cc/ast.c
index 49e35fd..0547712 100644
--- a/sys/cmd/cc/ast.c
+++ b/sys/cmd/cc/ast.c
@@ -17,15 +17,20 @@
// -----------------------------------------------------------------------
// helper functions
+static
string
nameof(Name *n)
{
- if (n->kind & Nident)
+ switch (n->kind) {
+ case Nident:
return n->ident;
- if (n->kind & Nparen)
+ case Nparen:
return nameof(n->paren->name);
-
- panicf("ill-formed declarator name");
+ case Nindex:
+ case Ncall:
+ return nameof(n->sfx.name);
+ }
+ panicf("unreachable");
}
static
@@ -201,8 +206,12 @@ nomatch(Token t, vlong kind)
static error spec(Parser *, Lexer *, uint64 *);
static error dtor(Parser *p, Lexer *lx, Dtor *d, int ab);
+static Type *typeofspec(Parser *, Lexer *, uint64 *);
+static Type *typeofdtor(Dtor *, Type *);
+
static Decl *decl(Parser *, Lexer *);
static Expr *expr(Parser *, Lexer *);
+
static error blkstmt(Parser *, Lexer *, Stmt **);
#define MAKEX(x, state) alloc((x)), (x)->kind = X##state
@@ -434,6 +443,7 @@ Bad:
return nil;
}
+#if 0
static
Type*
type(Parser *p, Lexer *lx)
@@ -462,6 +472,7 @@ Bad:
errorat(lx->pos, "failed to parse type expression");
return nil;
}
+#endif
static
Expr*
@@ -1006,12 +1017,115 @@ Bad:
// declarations
static
+Type *
+typeofname(Name *name, Type *type)
+{
+ switch (name->kind) {
+ case Nident:
+ return type;
+ case Nparen:
+ return typeofdtor(name->paren, type);
+ case Nindex:
+ return typeofname(name->sfx.name, array(type, name->sfx.idx.q, name->sfx.idx.x));
+ case Ncall:
+ return typeofname(name->sfx.name, func(type, name->sfx.call.n, name->sfx.call.arg, name->sfx.call.dots));
+ default:
+ panicf("unreachable");
+ }
+}
+
+static
+Type *
+typeofdtor(Dtor *decl, Type* type)
+{
+ int n;
+ Ptr *p;
+ uint64 b, tmp;
+
+ n = 0;
+ p = &decl->ptr;
+ b = p->kind;
+ while (b & 1) {
+ type = ptr(type, b >> 1);
+ if (++n >= 8) {
+ p = p->link;
+ b = p->kind;
+ } else {
+ b >>= 6;
+ }
+ }
+
+ return typeofname(decl->name, type);
+}
+
+static
+Type *
+aggr(Parser *p, Lexer *lx, string name, int kind)
+{
+ int n;
+ uint64 s;
+ Dtor *dt;
+ Token tk;
+ Type *t;
+ Type *fs[1024];
+ byte *nm[1024];
+ Expr *cx[1024];
+
+ n = -1;
+ for (;tk.kind != Arbrace && n < arrlen(fs); n++) {
+ t = typeofspec(p, lx, &s);
+
+ Field:
+ dt = getdtor(p);
+ dtor(p, lx, dt, 0);
+ fs[n] = typeofdtor(dt, t);
+ nm[n] = nameof(dt->name);
+ putdtor(p);
+
+ tk = peek(p, 0);
+ switch (tk.kind) {
+ case Acolon:
+ advance(p, lx);
+ cx[n] = expr(p, lx);
+ tk = peek(p, 0);
+ if (tk.kind == Asemi) {
+ tk = advance(p, lx);
+ continue;
+ }
+ if (tk.kind != Acomma) {
+ errorat(tk.pos, "unrecognized token %s in struct field declaration", tokens[tk.kind]);
+ goto Bad;
+ }
+ /* fallthrough */
+ case Acomma:
+ advance(p, lx);
+ n++;
+ goto Field;
+
+ case Asemi:
+ tk = advance(p, lx);
+ continue;
+
+ default:
+ errorat(tk.pos, "unrecognized token %s in struct field declaration", tokens[tk.kind]);
+ goto Bad;
+ }
+ }
+
+Bad:
+ errorat(tk.pos, "failed to parse aggregate declaration");
+ return nil;
+}
+
+static
error
spec(Parser *p, Lexer *lx, uint64 *spec)
{
Token t;
int n;
Sym *typ;
+ string name;
+ Type *tag;
uint64 s, sm;
s = 0;
@@ -1073,11 +1187,46 @@ 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, "struct specifier missing valid declaration");
+ goto Bad;
+ }
+
+ name = nil;
+ tag = nil;
+ if (t.kind == Aident) {
+ name = t.val.s;
+ t = advance(p, lx);
+ }
+ if (t.kind == Albrace) {
+ t = advance(p, lx);
+ tag = aggr(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;
+ }
+ }
+ break;
+
case Kenum:
+ if (s & Tenum) {
+ errorat(lx->pos, "more than one enum type specifier found");
+ goto Bad;
+ }
+ s += Bit(n);
panicf("need to implement");
+ break;
default:
errorat(t.pos, "invalid keyword '%s' found in declaration specifier", keywords[n]);
@@ -1100,7 +1249,7 @@ Bad:
static
Type*
-typespec(Parser *p, Lexer *lx, uint64 *s)
+typeofspec(Parser *p, Lexer *lx, uint64 *s)
{
int n;
uint64 m;
@@ -1123,7 +1272,9 @@ typespec(Parser *p, Lexer *lx, uint64 *s)
}
return C.type.info + indextypespec[n];
}
- panicf("unreachable");
+
+ errorat(lx->pos, "invalid type specifier");
+ return nil;
}
@@ -1301,7 +1452,7 @@ name(Parser *p, Lexer *lx, Name **nmp, int ab)
} while (t = peek(p, 0), t.kind == Acomma);
if (t.kind == Aellip) {
- nm->sfx.call.vararg = 1;
+ nm->sfx.call.dots = 1;
t = advance(p, lx);
}
@@ -1362,7 +1513,7 @@ Key:
switch (k = t.kind) {
case Akeywd:
if (Kconst <= k && k <= Katomic)
- ptr->kind |= Bit(n + (t.val.i - Kconst + 1));
+ ptr->kind |= Bit(6*n + (t.val.i - Kconst + 1));
else {
errorat(lx->pos, "invalid keyword '%s' modifies pointer", keywords[t.val.i]);
goto Bad;
diff --git a/sys/cmd/cc/cc.c b/sys/cmd/cc/cc.c
index 24d8e45..d5cd995 100644
--- a/sys/cmd/cc/cc.c
+++ b/sys/cmd/cc/cc.c
@@ -92,6 +92,9 @@ END:
}
// -----------------------------------------------------------------------
+// type interning
+
+// -----------------------------------------------------------------------
// universal compiler builtins
#define KEYWORD(a, b) b,
diff --git a/sys/cmd/cc/cc.h b/sys/cmd/cc/cc.h
index e8ab05e..ce7eca7 100644
--- a/sys/cmd/cc/cc.h
+++ b/sys/cmd/cc/cc.h
@@ -374,7 +374,7 @@ enum
Dvar,
Dvars,
- /* names (shouldn't interact with base AST node enumeration */
+ /* names */
Nident,
Nparen,
Nindex,
@@ -577,7 +577,7 @@ struct Name
} idx;
struct {
int n;
- int vararg : 1;
+ int dots : 1;
Obj *arg;
} call;
};
@@ -641,7 +641,7 @@ struct Type
uintptr size;
uintptr max;
uint16 align : 8;
- uint16 sign : 2;
+ uint8 sign : 2;
union {
struct {
uint32 qual;
@@ -655,12 +655,17 @@ struct Type
int len;
Obj *f;
Expr *x;
- } agr;
+ } aggr;
struct {
int len;
string *s;
Expr *x;
} enm;
+ struct {
+ Type *ret;
+ int n;
+ Type **arg;
+ } func;
};
};
@@ -701,7 +706,7 @@ struct Parser
error parse(Parser *, Lexer *);
// -----------------------------------------------------------------------
-// global compiler
+// global compiler data
struct StrTab
{
@@ -714,14 +719,19 @@ struct StrTab
int32 *vals;
};
-/* cc.c string functions */
-int32 intern(byte **str);
-string internview(byte* beg, byte *end);
+struct TypeSet
+{
+ int32 n_buckets;
+ int32 size;
+ int32 n_occupied;
+ int32 upper_bound;
+ int32 *flags;
+ Type **keys;
+};
/* main data */
struct Compiler
{
- /* storage */
memĀ·Arena *heap;
StrTab strs;
string outfile;
@@ -739,15 +749,23 @@ struct Compiler
} inc;
struct {
+ struct TypeSet p; // pointer
+ struct TypeSet a; // array
+ struct TypeSet f; // funcs
+ struct TypeSet s; // structs
+ struct TypeSet u; // unions
+ struct TypeSet e; // enums
+
int cap;
int len;
Type *info;
} type;
-};
+};
extern Compiler C;
-/* cc.c compiler functions */
-void init();
+/* cc.c functions */
+void init();
+int32 intern(byte **str);
#undef iota
diff --git a/sys/cmd/rules.mk b/sys/cmd/rules.mk
index 4905a5f..81c1cbe 100644
--- a/sys/cmd/rules.mk
+++ b/sys/cmd/rules.mk
@@ -5,8 +5,8 @@ include share/push.mk
DIR := $(d)/cat
include $(DIR)/rules.mk
-DIR := $(d)/cc
-include $(DIR)/rules.mk
+# DIR := $(d)/cc
+# include $(DIR)/rules.mk
DIR := $(d)/rc
include $(DIR)/rules.mk