summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--6/asm.h1
-rw-r--r--6/gen.c24
-rw-r--r--6/gengas.c21
-rw-r--r--6/simp.c51
-rw-r--r--libstd/syscall+linux-x64.s13
-rw-r--r--libstd/varargs.myr5
-rw-r--r--parse/infer.c15
7 files changed, 104 insertions, 26 deletions
diff --git a/6/asm.h b/6/asm.h
index 50fe20a..31599b2 100644
--- a/6/asm.h
+++ b/6/asm.h
@@ -224,6 +224,7 @@ Loc *locmemls(char *disp, Loc *base, Loc *idx, int scale, Mode mode);
Loc *loclit(long val, Mode m);
Loc *loclitl(char *lbl);
char *asmname(Node *dcl);
+char *tydescid(char *buf, size_t bufsz, Type *ty);
Loc *coreg(Reg r, Mode m);
int isfloatmode(Mode m);
int isintmode(Mode m);
diff --git a/6/gen.c b/6/gen.c
index 2f1a937..d45cb40 100644
--- a/6/gen.c
+++ b/6/gen.c
@@ -74,6 +74,30 @@ char *asmname(Node *dcl)
return strdup(buf);
}
+char *tydescid(char *buf, size_t bufsz, Type *ty)
+{
+ char *sep, *ns;
+
+ sep = "";
+ ns = "";
+ if (ty->type == Tyname) {
+ if (ty->name->name.ns) {
+ ns = ty->name->name.ns;
+ sep = "$";
+ }
+ if (ty->vis == Visexport || ty->isimport)
+ snprintf(buf, bufsz, "_tydesc$%s%s%s", ns, sep, ty->name->name.name);
+ else
+ snprintf(buf, bufsz, "_tydesc$%s%s%s$%d", ns, sep, ty->name->name.name, ty->tid);
+ } else {
+ if (file->file.globls->name) {
+ ns = file->file.globls->name;
+ sep = "$";
+ }
+ snprintf(buf, bufsz, "_tydesc%s%s$%d",sep, ns, ty->tid);
+ }
+ return buf;
+}
void gen(Node *file, char *out)
{
diff --git a/6/gengas.c b/6/gengas.c
index 0cddd57..2013375 100644
--- a/6/gengas.c
+++ b/6/gengas.c
@@ -487,23 +487,6 @@ void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
writeasm(fd, &is, fn);
}
-static char *tydescid(char *buf, size_t bufsz, Type *ty)
-{
- char *sep, *ns;
-
- sep = "";
- ns = "";
- if (ty->name->name.ns) {
- ns = ty->name->name.ns;
- sep = "$";
- }
- if (ty->vis == Visexport || ty->isimport)
- snprintf(buf, bufsz, "_tydesc$%s%s%s", ns, sep, ty->name->name.name);
- else
- snprintf(buf, bufsz, "_tydesc$%d$%s%s%s", ty->tid, ns, sep, ty->name->name.name);
- return buf;
-}
-
static void genstructmemb(FILE *fd, Node *sdecl)
{
fprintf(fd, "\t.ascii \"%s\" /* struct member */\n", namestr(sdecl->decl.name));
@@ -567,6 +550,7 @@ static void gentydesc(FILE *fd, Type *ty)
gentydesc(fd, ty->sub[i]);
break;
case Tytuple:
+ fprintf(fd, "\t.byte %zd\n", ty->nsub);
for (i = 0; i < ty->nsub; i++)
gentydesc(fd, ty->sub[i]);
break;
@@ -588,15 +572,16 @@ void gentype(FILE *fd, Type *ty)
{
char buf[512];
+ tydescid(buf, sizeof buf, ty);
if (ty->type == Tyname) {
if (hasparams(ty))
return;
- tydescid(buf, sizeof buf, ty);
if (ty->vis == Visexport)
fprintf(fd, ".globl %s /* tid: %d */\n", buf, ty->tid);
fprintf(fd, "%s:\n", buf);
gentydesc(fd, ty->sub[0]);
} else {
+ fprintf(fd, "%s:\n", buf);
gentydesc(fd, ty);
}
}
diff --git a/6/simp.c b/6/simp.c
index 6ee4faa..2f8dc4b 100644
--- a/6/simp.c
+++ b/6/simp.c
@@ -1237,6 +1237,55 @@ static Node *compare(Simp *s, Node *n, int fields)
return r;
}
+static int isvariadic(Node *fn)
+{
+ Type *ty;
+
+ ty = exprtype(fn);
+ return tybase(ty->sub[ty->nsub - 1])->type == Tyvalist;
+}
+
+static void addvatype(Simp *s, Node *n)
+{
+ Node *ti, *tp, *td, *tn;
+ Type *ft, *vt, **st;
+ size_t nst, i;
+ char buf[1024];
+
+ st = NULL;
+ nst = 0;
+ ft = exprtype(n->expr.args[0]);
+ /* The structure of ft->sub:
+ * [return, normal, args, ...]
+ *
+ * The structure of n->expr.sub:
+ * [fn, normal, args, , variadic, args]
+ *
+ * We want to start at variadic, so we want
+ * to count from ft->nsub - 1, up to n->expr.nsub.
+ */
+ for (i = ft->nsub - 1; i < n->expr.nargs; i++)
+ lappend(&st, &nst, exprtype(n->expr.args[i]));
+ vt = mktytuple(n->loc, st, nst);
+ vt->isreflect = 1;
+
+ /* make the decl */
+ tn = mkname(Zloc, tydescid(buf, sizeof buf, vt));
+ td = mkdecl(Zloc, tn, mktype(n->loc, Tybyte));
+
+ /* and the var */
+ ti = mkexpr(Zloc, Ovar, tn, NULL);
+ ti->expr.type = td->decl.type;
+ ti->expr.did = td->decl.did;
+
+ /* and the pointer */
+ tp = mkexpr(Zloc, Oaddr, ti);
+ tp->expr.type = mktyptr(n->loc, td->decl.type);
+
+ linsert(&n->expr.args, &n->expr.nargs, ft->nsub - 1, tp);
+ htput(s->globls, td, asmname(td));
+}
+
static Node *rval(Simp *s, Node *n, Node *dst)
{
Node *t, *u, *v; /* temporary nodes */
@@ -1411,6 +1460,8 @@ static Node *rval(Simp *s, Node *n, Node *dst)
r = assign(s, args[0], args[1]);
break;
case Ocall:
+ if (isvariadic(n->expr.args[0]))
+ addvatype(s, n);
if (exprtype(n)->type != Tyvoid && stacktype(exprtype(n))) {
if (dst)
r = dst;
diff --git a/libstd/syscall+linux-x64.s b/libstd/syscall+linux-x64.s
index 7e639eb..d1a3086 100644
--- a/libstd/syscall+linux-x64.s
+++ b/libstd/syscall+linux-x64.s
@@ -9,6 +9,7 @@ sys$syscall:
pushq %r9
pushq %rcx
pushq %r11
+
/*
hack: We load 6 args regardless of
how many we actually have. This may
@@ -17,12 +18,12 @@ sys$syscall:
harmless.
*/
movq 80 (%rsp),%rax
- movq 88 (%rsp),%rdi
- movq 96 (%rsp),%rsi
- movq 104(%rsp),%rdx
- movq 112(%rsp),%r10
- movq 120(%rsp),%r8
- movq 128(%rsp),%r9
+ movq 96 (%rsp),%rdi
+ movq 104(%rsp),%rsi
+ movq 112(%rsp),%rdx
+ movq 120(%rsp),%r10
+ movq 128(%rsp),%r8
+ movq 136(%rsp),%r9
syscall
diff --git a/libstd/varargs.myr b/libstd/varargs.myr
index bcaac76..99d04d3 100644
--- a/libstd/varargs.myr
+++ b/libstd/varargs.myr
@@ -19,7 +19,10 @@ type valist = byte#
* force varargs onto the stack regardless.
*/
const vastart = {args
- -> args castto(valist)
+ var ap, dump : byte#
+
+ (dump, ap) = vanext(args castto(valist))
+ -> ap
}
generic vanext = {ap -> (@a, valist)
diff --git a/parse/infer.c b/parse/infer.c
index 1163a1d..217174f 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -133,6 +133,7 @@ static char *ctxstr(Inferstate *st, Node *n)
nargs = n->expr.nargs;
t1 = NULL;
t2 = NULL;
+ t3 = NULL;
if (exprop(n) == Ovar)
d = namestr(args[0]);
else
@@ -184,6 +185,7 @@ static char *ctxstr(Inferstate *st, Node *n)
free(t);
free(t1);
free(t2);
+ free(t3);
s = strdup(buf);
break;
}
@@ -469,6 +471,7 @@ static Type *tf(Inferstate *st, Type *orig)
int isgeneric;
Type *t;
+ assert(orig != NULL);
t = tysearch(orig);
isgeneric = t->type == Tygeneric;
st->ingeneric += isgeneric;
@@ -906,6 +909,14 @@ static Type *unify(Inferstate *st, Node *ctx, Type *u, Type *v)
return r;
}
+static void markvatypes(Type **types, size_t ntypes)
+{
+ size_t i;
+
+ for (i = 0; i < ntypes; i++)
+ types[i]->isreflect = 1;
+}
+
/* Applies unifications to function calls.
* Funciton application requires a slightly
* different approach to unification. */
@@ -933,8 +944,10 @@ static void unifycall(Inferstate *st, Node *n)
fatal(n, "%s arity mismatch (expected %zd args, got %zd)",
ctxstr(st, n->expr.args[0]), ft->nsub - 1, n->expr.nargs - 1);
- if (ft->sub[i]->type == Tyvalist)
+ if (ft->sub[i]->type == Tyvalist) {
+ markvatypes(&ft->sub[i], ft->nsub - i);
break;
+ }
inferexpr(st, &n->expr.args[i], NULL, NULL);
unify(st, n->expr.args[0], ft->sub[i], type(st, n->expr.args[i]));
}