ref: 3065ee64d255b9eca94efd48269cd291960d6c4e
parent: 6e422cdf9d119e0fb96626ef7f7e39611d6655b4
author: Ori Bernstein <[email protected]>
date: Tue Jun 5 20:12:28 EDT 2012
Make simple, zero-arg function calls work.
--- a/8/asm.h
+++ b/8/asm.h
@@ -76,9 +76,11 @@
size_t nn;
};
-void genasm(Func *fn, Htab *globls);
+/* entry points */
+void genasm(FILE *fd, Func *fn, Htab *globls);
void gen(Node *file, char *out);
+/* location generation */
Loc *loclbl(Loc *l, Node *lbl);
Loc *locreg(Loc *l, Reg r);
Loc *locmem(Loc *l, long disp, Reg base, Reg idx, Mode mode);
@@ -85,3 +87,5 @@
Loc *locmeml(Loc *l, char *disp, Reg base, Reg idx, Mode mode);
Loc *loclit(Loc *l, long val);
+/* useful functions */
+size_t size(Node *n);
--- a/8/insns.def
+++ b/8/insns.def
@@ -43,6 +43,7 @@
Insn(Isetge, "\tsetge\n", 0)
/* branch instructions */
+Insn(Icall, "\tcall %v\n", 0)
Insn(Ijmp, "\tjmp %v\n", 0)
Insn(Ijz, "\tjz %v\n", 0)
Insn(Ijnz, "\tjnz %v\n", 0)
--- a/8/isel.c
+++ b/8/isel.c
@@ -92,16 +92,20 @@
/* forward decls */
Loc selexpr(Isel *s, Node *n);
-
-Loc *loclbl(Loc *l, Node *lbl)
+Loc *locstrlbl(Loc *l, char *lbl)
{
- assert(lbl->type = Nlbl);
l->type = Loclbl;
l->mode = ModeL;
- l->lbl = strdup(lbl->lbl.name);
+ l->lbl = strdup(lbl);
return l;
}
+Loc *loclbl(Loc *l, Node *lbl)
+{
+ assert(lbl->type = Nlbl);
+ return locstrlbl(l, lbl->lbl.name);
+}
+
Loc *locreg(Loc *l, Reg r)
{
l->type = Locreg;
@@ -150,7 +154,7 @@
stkoff = (size_t)htget(s->locs, (void*)n->expr.did);
locmem(&l, stkoff, Resp, Rnone, ModeL);
} else if (hthas(s->globls, (void*)n->expr.did)) {
- loclbl(&l, htget(s->globls, (void*)n->expr.did));
+ locstrlbl(&l, htget(s->globls, (void*)n->expr.did));
} else {
die("%s (id=%ld) not found", namestr(n->expr.args[0]), n->expr.did);
}
@@ -423,6 +427,45 @@
return l;
}
+Loc gencall(Isel *s, Node *n)
+{
+ int argsz;
+ int i;
+ Loc eax, esp; /* hard-coded registers */
+ Loc stkbump; /* calculated stack offset */
+ Loc dst, arg, fn; /* values we reduced */
+
+ locreg(&esp, Resp);
+ locreg(&eax, Reax);
+ argsz = 0;
+ /* Have to calculate the amount to bump the stack
+ * pointer by in one pass first, otherwise if we push
+ * one at a time, we evaluate the args in reverse order.
+ * Not good.
+ *
+ * We skip the first operand, since it's the function itself */
+ for (i = 1; i < n->expr.nargs; i++)
+ argsz += size(n->expr.args[i]);
+ loclit(&stkbump, argsz);
+ if (argsz)
+ g(s, Isub, &stkbump, &esp, NULL);
+
+ /* Now, we can evaluate the arguments */
+ argsz = 0;
+ for (i = 1; i < n->expr.nargs; i++) {
+ argsz += size(n->expr.args[i]);
+ arg = selexpr(s, n->expr.args[i]);
+ arg = inri(s, arg);
+ locmem(&dst, argsz, Resp, Rnone, arg.mode);
+ stor(s, &arg, &dst);
+ }
+ fn = selexpr(s, n->expr.args[0]);
+ g(s, Icall, &fn, NULL);
+ if (argsz)
+ g(s, Iadd, &stkbump, &esp, NULL);
+ return eax;
+}
+
Loc selexpr(Isel *s, Node *n)
{
Loc a, b, c, r;
@@ -489,7 +532,9 @@
g(s, Imov, &b, &r, NULL);
break;
- case Ocall: die("Unimplemented op %s", opstr(exprop(n))); break;
+ case Ocall:
+ r = gencall(s, n);
+ break;
case Ocast: die("Unimplemented op %s", opstr(exprop(n))); break;
case Ojmp:
g(s, Ijmp, loclbl(&a, args[0]), NULL);
@@ -675,11 +720,10 @@
/* genasm requires all nodes in 'nl' to map cleanly to operations that are
* natively supported, as promised in the output of reduce(). No 64-bit
* operations on x32, no structures, and so on. */
-void genasm(Func *fn, Htab *globls)
+void genasm(FILE *fd, Func *fn, Htab *globls)
{
struct Isel is = {0,};
int i;
- FILE *fd;
is.locs = fn->locs;
is.globls = globls;
@@ -695,7 +739,5 @@
if (debug)
writeasm(fn, &is, stdout);
- fd = fopen("a.s", "w");
writeasm(fn, &is, fd);
- fclose(fd);
}
--- a/8/reduce.c
+++ b/8/reduce.c
@@ -522,7 +522,7 @@
append(s, s->endlbl);
}
-static void lowerfn(char *name, Node *n, Htab *globls)
+static void lowerfn(char *name, Node *n, Htab *globls, FILE *fd)
{
int i;
Simp s = {0,};
@@ -547,7 +547,7 @@
fn.ret = s.ret;
fn.nl = s.stmts;
fn.nn = s.nstmts;
- genasm(&fn, globls);
+ genasm(fd, &fn, globls);
}
void blobdump(Blob *b, FILE *fd)
@@ -566,11 +566,12 @@
void gen(Node *file, char *out)
{
+ FILE *fd;
Node **n;
int nn, i;
- Sym *s;
char *name;
Htab *globls;
+ Sym *s;
n = file->file.stmts;
nn = file->file.nstmts;
@@ -581,6 +582,9 @@
if (n[i]->type == Ndecl)
htput(globls, (void*)n[i]->decl.sym->id, asmname(n[i]->decl.sym->name));
+ fd = fopen(out, "w");
+ if (!fd)
+ die("Couldn't open fd %s", out);
for (i = 0; i < nn; i++) {
switch (n[i]->type) {
case Nuse: /* nothing to do */
@@ -589,7 +593,7 @@
s = n[i]->decl.sym;
name = asmname(s->name);
if (isconstfn(s)) {
- lowerfn(name, n[i]->decl.init, globls);
+ lowerfn(name, n[i]->decl.init, globls, fd);
free(name);
} else {
die("We don't lower globls yet...");
@@ -600,4 +604,6 @@
break;
}
}
+ if (fd)
+ fclose(fd);
}
--- a/parse/util.c
+++ b/parse/util.c
@@ -80,8 +80,9 @@
{
char *ret;
- ret = xalloc(len);
+ ret = xalloc(len + 1);
memcpy(ret, s, len);
+ ret[len] = '\0';
return ret;
}
--- a/test/build.sh
+++ b/test/build.sh
@@ -15,6 +15,7 @@
build struct_oneval
build struct
build array
+build call
build fib
exit 0
--- a/test/test.sh
+++ b/test/test.sh
@@ -23,4 +23,5 @@
returns struct_oneval 12
returns struct 42
returns array 7
+returns call 42
returns fib 8