ref: 7a0a1eb532018cf6db1d49a49667ae18a0ed643e
parent: 254736fb93f759fa95d4c89041aba062b383a5fc
author: Ori Bernstein <[email protected]>
date: Sun May 13 18:18:19 EDT 2012
Start generating code for struct members. The output asm is broken, but the compiler doesn't crash. Fixed type inference to unify returns properly, added instruction selection and simplification, rearranged utility functions.
--- a/8/insns.def
+++ b/8/insns.def
@@ -20,6 +20,7 @@
Insn(Imov, "\tmov%t %x,%x\n", 0)
Insn(Imovz, "\tmovz%0t%1t %x,%x\n", 0)
Insn(Imovs, "\tmovs%0t%1t %x,%x\n", 0)
+Insn(Ilea, "\tlea%t %x,%x\n", 0)
Insn(Iadd, "\tadd%t %r,%x\n", 0)
Insn(Isub, "\tsub%t %r,%x\n", 0)
--- a/8/isel.c
+++ b/8/isel.c
@@ -23,7 +23,7 @@
Htab *locs; /* Node => int stkoff */
/* 6 general purpose regs */
- Reg rtaken[Nreg];
+ int rtaken[Nreg];
};
/* string tables */
@@ -219,6 +219,7 @@
for (i = 0; i < Nmode; i++)
s->rtaken[reginterferes[l.reg][i]] = 1;
+ printf("Got reg %s\n", regnames[l.reg]);
return l;
}
@@ -281,9 +282,14 @@
void stor(Isel *s, Loc *a, Loc *b)
{
+ Loc l;
+
assert(a->type == Locreg || a->type == Loclit);
- assert(b->type == Loclit || b->type == Locmem || b->type == Loclbl);
- g(s, Imov, a, b, NULL);
+ if (b->type == Locreg)
+ locmem(&l, 0, b->reg, Rnone, b->mode);
+ else
+ l = *b;
+ g(s, Imov, a, &l, NULL);
}
/* ensures that a location is within a reg */
@@ -380,8 +386,12 @@
case Obsr: die("Unimplemented op %s", opstr(exprop(n))); break;
case Obnot: die("Unimplemented op %s", opstr(exprop(n))); break;
- case Oaddr: die("Unimplemented op %s", opstr(exprop(n))); break;
case Oderef: die("Unimplemented op %s", opstr(exprop(n))); break;
+ case Oaddr:
+ a = selexpr(s, args[0]);
+ r = getreg(s, ModeL);
+ g(s, Ilea, &a, &r, NULL);
+ break;
case Olnot:
a = selexpr(s, args[0]);
--- a/8/reduce.c
+++ b/8/reduce.c
@@ -214,6 +214,29 @@
}
}
+static size_t offsetof(Node *aggr, Node *memb)
+{
+ Type *ty;
+ Node **nl;
+ int nn, i;
+ size_t off;
+
+ if (aggr->expr.type->type == Typtr)
+ aggr = aggr->expr.args[0];
+ ty = aggr->expr.type;
+
+ assert(ty->type == Tystruct);
+ nl = aggrmemb(ty, &nn);
+ off = 0;
+ for (i = 0; i < nn; i++) {
+ if (!strcmp(namestr(memb), declname(nl[i])))
+ return off;
+ off += size(nl[i]);
+ }
+ die("Could not find member %s in struct", namestr(memb));
+ return -1;
+}
+
Node *lval(Simp *s, Node *n)
{
return rval(s, n);
@@ -246,10 +269,18 @@
switch (exprop(n)) {
case Obad:
case Olor: case Oland:
- case Obsreq: case Omemb:
case Oslice: case Oidx: case Osize:
die("Have not implemented lowering op %s", opstr(exprop(n)));
break;
+ case Omemb:
+ if (n->expr.type->type != Typtr)
+ t = mkexpr(-1, Oaddr, args[0], NULL);
+ else
+ t = args[0];
+ u = mkint(-1, offsetof(args[0], args[1]));
+ u = mkexpr(-1, Olit, u, NULL);
+ r = mkexpr(-1, Oadd, t, u, NULL);
+ break;
/* fused ops:
* foo ?= blah
@@ -256,7 +287,7 @@
* =>
* foo = foo ? blah*/
case Oaddeq: case Osubeq: case Omuleq: case Odiveq: case Omodeq:
- case Oboreq: case Obandeq: case Obxoreq: case Obsleq:
+ case Oboreq: case Obandeq: case Obxoreq: case Obsleq: case Obsreq:
assert(fusedmap[exprop(n)] != Obad);
u = rval(s, args[0]);
v = rval(s, args[1]);
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -28,17 +28,6 @@
st->super = super;
}
-static Node **aggrmemb(Type *t, int *n)
-{
- *n = t->nmemb;
- switch (t->type) {
- case Tystruct: return t->sdecls; break;
- case Tyunion: return t->udecls; break;
- case Tyenum: return t->edecls; break;
- default: return NULL;
- }
-}
-
static void tyresolve(Type *t)
{
int i, nn;
@@ -194,14 +183,13 @@
b = t;
}
+ printf("UNIFY %s ===> %s\n", tystr(a), tystr(b));
mergecstrs(ctx, a, b);
- if (a->type != b->type) {
+ if (a->type == Tyvar) {
if (a->type == Tyvar)
tytab[a->tid] = b;
- else
- fatal(ctx->line, "%s incompatible with %s near %s", tystr(a), tystr(b), ctxstr(ctx));
return b;
- } else {
+ } else if (a->type == b->type) {
for (i = 0; i < b->nsub; i++) {
/* types must have same arity */
if (i >= a->nsub)
@@ -213,6 +201,9 @@
*/
}
return b;
+ } else {
+ fatal(ctx->line, "%s incompatible with %s near %s", tystr(a), tystr(b), ctxstr(ctx));
+ return NULL;
}
}
@@ -326,15 +317,17 @@
die("casts not implemented");
break;
case Oret: /* -> @a -> void */
+ printf("INFERRING RET\n");
if (sawret)
*sawret = 1;
if (!ret)
fatal(n->line, "Not allowed to return value here");
if (nargs)
- t = unify(n, type(args[0]), ret);
+ t = unify(n, ret, type(args[0]));
else
t = unify(n, mkty(-1, Tyvoid), ret);
settype(n, t);
+ printf("DONE");
break;
case Ojmp: /* goto void* -> void */
settype(n, mkty(-1, Tyvoid));
@@ -342,7 +335,7 @@
case Ovar: /* a:@a -> @a */
s = getdcl(curstab(), args[0]);
if (!s)
- fatal(n->line, "Undeclared var %s", args[0]->name.parts[args[0]->name.nparts - 1]);
+ fatal(n->line, "Undeclared var %s", declname(args[0]));
else
settype(n, s->type);
n->expr.did = s->id;
@@ -373,10 +366,9 @@
for (i = 0; i < n->func.nargs; i++)
infernode(n->func.args[i], NULL, NULL);
infernode(n->func.body, n->func.type->sub[0], &sawret);
+ /* if there's no return stmt in the function, assume void ret */
if (!sawret)
unify(n, type(n)->sub[0], mkty(-1, Tyvoid));
- else
- printf("SAWRET!!!\n");
}
static void inferdecl(Node *n)
@@ -487,17 +479,13 @@
for (i = 0; i < t->nsub; i++)
t->sub[i] = tyfin(ctx, t->sub[i]);
}
- if (t->type == Tyvar)
- fatal(t->line, "underconstrained type %s near %s", tyfmt(buf, 1024, t), ctxstr(ctx));
+ if (t->type == Tyvar) {
+ dump(ctx, stdout);
+ fatal(t->line, "underconstrained type %s near %s", tyfmt(buf, 1024, t), ctxstr(ctx));
+ }
return t;
}
-static char *namestr(Node *name)
-{
- assert(name->type == Nname);
- return name->name.parts[0];
-}
-
static void infercompn(Node *file)
{
int i, j, nn;
@@ -506,18 +494,24 @@
Node *n;
Node **nl;
+ printf("COMPONENTS INFERRED\n");
for (i = 0; i < ncheckmemb; i++) {
n = checkmemb[i];
+ printf("EXPR TYPE: %s\n", tystr(type(n)));
+ if (n->expr.type->type == Typtr)
+ n = n->expr.args[0];
aggr = checkmemb[i]->expr.args[0];
memb = checkmemb[i]->expr.args[1];
nl = aggrmemb(aggr->expr.type, &nn);
for (j = 0; j < nn; j++) {
- if (!strcmp(namestr(memb), declname(nl[i])))
+ if (!strcmp(namestr(memb), declname(nl[j]))) {
+ unify(n, type(n), decltype(nl[j]));
break;
+ }
}
- unify(n, n->expr.type, decltype(nl[i]));
}
+ printf("DONE\n");
}
static void typesub(Node *n)
--- a/parse/node.c
+++ b/parse/node.c
@@ -241,3 +241,20 @@
return e->expr.op;
}
+Node **aggrmemb(Type *t, int *n)
+{
+ *n = t->nmemb;
+ switch (t->type) {
+ case Tystruct: return t->sdecls; break;
+ case Tyunion: return t->udecls; break;
+ case Tyenum: return t->edecls; break;
+ default: return NULL;
+ }
+}
+
+char *namestr(Node *name)
+{
+ assert(name->type == Nname);
+ return name->name.parts[0];
+}
+
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -325,6 +325,8 @@
void addstmt(Node *file, Node *stmt);
void setns(Node *n, char *name);
Op exprop(Node *n);
+Node **aggrmemb(Type *t, int *n);
+char *namestr(Node *name);
/* usefiles */
void readuse(Node *use, Stab *into);