shithub: mc

Download patch

ref: 14aeadb41737f1765b6f3489f3b8da330aeccf39
parent: 0bd2678722f5f70a063190d54d12e62420f02b05
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Aug 21 14:54:53 EDT 2015

Get closer to the C ABI

--- a/6/asm.h
+++ b/6/asm.h
@@ -130,10 +130,14 @@
 struct Func {
     char *name;   /* function name */
     int   isexport; /* is this exported from the asm? */
-    size_t stksz; /* stack size */
     Type *type;   /* type of function */
+
+    Node **args;  /* argument list */
+    size_t nargs; /* number of args, including hidden ones */
     Htab *stkoff; /* Loc* -> int stackoff map */
+    size_t stksz; /* stack size */
     Node *ret;    /* return value */
+
     Cfg  *cfg;    /* flow graph */
 };
 
--- a/6/insns.def
+++ b/6/insns.def
@@ -304,7 +304,11 @@
 Insn(Icall,
     "\tcall %v\n",
     "\tCALL %V\n",
-    Use(.l={1}),
+    Use(.l={1}, .r={
+            Rrdi, Rrsi, Rrdx, Rrcx, Rr8, Rr9,
+            Rxmm0d, Rxmm1d, Rxmm2d, Rxmm3d,
+            Rxmm4d, Rxmm5d, Rxmm6d, Rxmm7d,
+    }),
     Def(.r={Rrax, Rrbx, Rrcx, Rrdx, Rrsi,
             Rrdi, Rr8,Rr9,Rr10,Rr11,
             Rxmm0d, Rxmm1d, Rxmm2d, Rxmm3d,
@@ -315,7 +319,11 @@
 Insn(Icallind,
     "\tcall *%v\n",
     "\tCALL *%V\n",
-    Use(.l={1}),
+    Use(.l={1}, .r={
+            Rrdi, Rrsi, Rrdx, Rrcx, Rr8, Rr9,
+            Rxmm0d, Rxmm1d, Rxmm2d, Rxmm3d,
+            Rxmm4d, Rxmm5d, Rxmm6d, Rxmm7d,
+    }),
     Def(.r={Rrax, Rrbx, Rrcx, Rrdx, Rrsi,
             Rrdi, Rr8,Rr9,Rr10,Rr11,
             Rxmm0d, Rxmm1d, Rxmm2d, Rxmm3d,
--- a/6/isel.c
+++ b/6/isel.c
@@ -19,6 +19,14 @@
 /* forward decls */
 Loc *selexpr(Isel *s, Node *n);
 
+#define Nfloatregargs 8
+#define Nintregargs 6
+regid floatargregs[] = {
+    Rxmm0d, Rxmm1d, Rxmm2d, Rxmm3d,
+    Rxmm4d, Rxmm5d, Rxmm6d, Rxmm7d,
+};
+regid intargregs[] = {Rrdi, Rrsi, Rrdx, Rrcx, Rr8, Rr9};
+
 /* used to decide which operator is appropriate
  * for implementing various conditional operators */
 struct {
@@ -50,14 +58,12 @@
     [Ofle] = {Icomis, Ijbe, Isetbe},
 };
 
-static Mode mode(Node *n)
+static Mode tymode(Type *t)
 {
-    Type *t;
-
-    t = tybase(exprtype(n));
     /* FIXME: What should the mode for, say, structs be when we have no
      * intention of loading /through/ the pointer? For now, we'll just say it's
      * the pointer mode, since we expect to address through the pointer */
+    t = tybase(t);
     switch (t->type) {
         case Tyflt32: return ModeF; break;
         case Tyflt64: return ModeD; break;
@@ -64,7 +70,7 @@
         default:
             if (stacktype(t))
                 return ModeQ;
-            switch (size(n)) {
+            switch (tysize(t)) {
                 case 1: return ModeB; break;
                 case 2: return ModeW; break;
                 case 4: return ModeL; break;
@@ -75,6 +81,16 @@
     return ModeQ;
 }
 
+static Mode mode(Node *n)
+{
+    if (n->type == Nexpr)
+        return tymode(exprtype(n));
+    else if (n->type == Ndecl)
+        return tymode(n->decl.type);
+    else
+        die("invalid node type");
+}
+
 static Loc *loc(Isel *s, Node *n)
 {
     ssize_t stkoff;
@@ -90,9 +106,11 @@
                 stkoff = ptoi(htget(s->stkoff, n));
                 l = locmem(-stkoff, locphysreg(Rrbp), NULL, mode(n));
             }  else {
-                if (!hthas(s->reglocs, n))
-                    htput(s->reglocs, n, locreg(mode(n)));
-                return htget(s->reglocs, n);
+                l = htget(s->reglocs, n);
+                if (!l) {
+                    l = locreg(mode(n));
+                    htput(s->reglocs, n, l);
+                }
             }
             break;
         case Olit:
@@ -471,14 +489,31 @@
     g(s, op, f, NULL);
 }
 
+static size_t countargs(Type *t)
+{
+    size_t nargs;
+
+    t = tybase(t);
+    nargs = t->nsub - 1;
+    if (stacktype(t->sub[0]))
+        nargs++;
+    /* valists are replaced with hidden type parameter,
+     * which we want on the stack for ease of ABI */
+    if (tybase(t->sub[t->nsub - 1])->type == Tyvalist)
+        nargs--;
+    return nargs;
+}
+
 static Loc *gencall(Isel *s, Node *n)
 {
     Loc *src, *dst, *arg;  /* values we reduced */
+    size_t argsz, argoff, nargs;
+    size_t nfloats, nints;
     Loc *retloc, *rsp, *ret;       /* hard-coded registers */
     Loc *stkbump;        /* calculated stack offset */
-    int argsz, argoff;
     size_t i, a;
-    Type *t;
+    int vararg;
+    Type *t, *fn;
 
     rsp = locphysreg(Rrsp);
     t = exprtype(n);
@@ -492,6 +527,10 @@
         retloc = coreg(Rrax, mode(n));
         ret = locreg(mode(n));
     }
+    fn = tybase(exprtype(n->expr.args[0]));
+    /* calculate the number of args we expect to see, adjust
+     * for a hidden return argument. */
+    nargs = countargs(fn);
     argsz = 0;
     /* Have to calculate the amount to bump the stack
      * pointer by in one pass first, otherwise if we push
@@ -510,20 +549,36 @@
 
     /* Now, we can evaluate the arguments */
     argoff = 0;
+    nfloats = 0;
+    nints = 0;
+    vararg = 0;
     for (i = 1; i < n->expr.nargs; i++) {
         arg = selexpr(s, n->expr.args[i]);
         argoff = align(argoff, min(size(n->expr.args[i]), Ptrsz));
+        if (i > nargs)
+            vararg = 1;
         if (stacknode(n->expr.args[i])) {
             src = locreg(ModeQ);
             g(s, Ilea, arg, src, NULL);
             a = alignto(1, n->expr.args[i]->expr.type);
             blit(s, rsp, src, argoff, 0, size(n->expr.args[i]), a);
+            argoff += size(n->expr.args[i]);
+        } else if (!vararg && isfloatmode(arg->mode) && nfloats < Nfloatregargs) {
+            dst = coreg(floatargregs[nfloats], arg->mode);
+            arg = inri(s, arg);
+            g(s, Imovs, arg, dst, NULL);
+            nfloats++;
+        } else if (!vararg && isintmode(arg->mode) && nints < Nintregargs) {
+            dst = coreg(intargregs[nints], arg->mode);
+            arg = inri(s, arg);
+            g(s, Imov, arg, dst, NULL);
+            nints++;
         } else {
             dst = locmem(argoff, rsp, NULL, arg->mode);
             arg = inri(s, arg);
             stor(s, arg, dst);
+            argoff += size(n->expr.args[i]);
         }
-        argoff += size(n->expr.args[i]);
     }
     call(s, n->expr.args[0]);
     if (argsz)
@@ -842,8 +897,48 @@
     Rnone
 };
 
-static void prologue(Isel *s, size_t sz)
+void addarglocs(Isel *s, Func *fn)
 {
+    size_t i, nints, nfloats, nargs;
+    size_t argoff;
+    int vararg;
+    Node *arg;
+    Loc *a, *l;
+
+    argoff = 0;
+    nfloats = 0;
+    nints = 0;
+    vararg = 0;
+    nargs = countargs(fn->type);
+    for (i = 0; i < fn->nargs; i++) {
+        arg = fn->args[i]; 
+        argoff = align(argoff, min(size(arg), Ptrsz));
+        if (i >= nargs)
+            vararg = 1;
+        if (stacknode(arg)) {
+            htput(s->stkoff, arg, itop(-(argoff + 2*Ptrsz)));
+            argoff += size(arg);
+        } else if (!vararg && isfloatmode(mode(arg)) && nfloats < Nfloatregargs) {
+            a = coreg(floatargregs[nfloats], mode(arg));
+            l = locreg(mode(arg));
+            g(s, Imovs, a, l, NULL);
+            htput(s->reglocs, arg, l);
+            nfloats++;
+        } else if (!vararg && isintmode(mode(arg)) && nints < Nintregargs) {
+            a = coreg(intargregs[nints], mode(arg));
+            l = locreg(mode(arg));
+            g(s, Imov, a, l, NULL);
+            htput(s->reglocs, arg, l);
+            nints++;
+        } else {
+            htput(s->stkoff, arg, itop(-(argoff + 2*Ptrsz)));
+            argoff += size(arg);
+        }
+    }
+}
+
+static void prologue(Isel *s, Func *fn, size_t sz)
+{
     Loc *rsp;
     Loc *rbp;
     Loc *stksz;
@@ -867,6 +962,7 @@
             g(s, Imov, phys, s->calleesave[i], NULL);
         }
     }
+    addarglocs(s, fn);
     s->nsaved = i;
     s->stksz = stksz; /* need to update if we spill */
 }
@@ -927,7 +1023,7 @@
         lappend(&is->bb, &is->nbb, mkasmbb(fn->cfg->bb[i]));
 
     is->curbb = is->bb[0];
-    prologue(is, fn->stksz);
+    prologue(is, fn, fn->stksz);
     for (j = 0; j < fn->cfg->nbb - 1; j++) {
         is->curbb = is->bb[j];
         if (!is->bb[j])
@@ -945,4 +1041,5 @@
     is->curbb = is->bb[is->nbb - 1];
     epilogue(is);
     regalloc(is);
+    is->stksz->lit = align(is->stksz->lit, 16);
 }
--- a/6/ra.c
+++ b/6/ra.c
@@ -919,6 +919,8 @@
 {
     if (s->nuses[r] == 0)
         return -1;
+    if (bshas(s->neverspill, r))
+        return -10000;
     return s->degree[r] * 100 / s->nuses[r];
 }
 
@@ -953,7 +955,6 @@
     if (!m) {
         for (i = 0; i < s->nwlspill; i++) {
             if (bshas(s->neverspill, s->wlspill[i]->reg.id)) {
-                printf("Not spilling %zd\n", s->wlspill[i]->reg.id);
                 continue;
             }
             m = s->wlspill[i];
--- a/6/simp.c
+++ b/6/simp.c
@@ -47,10 +47,13 @@
     /* location handling */
     Node **blobs;
     size_t nblobs;
-    size_t stksz;
-    size_t argsz;
     Htab *globls;
-    Htab *stkoff;
+
+    Htab *_stkoff;
+    size_t stksz;
+
+    Node **args;
+    size_t nargs;
 };
 
 static Node *simp(Simp *s, Node *n);
@@ -166,7 +169,7 @@
 static int addressable(Simp *s, Node *a)
 {
     if (a->type == Ndecl || (a->type == Nexpr && exprop(a) == Ovar))
-        return hthas(s->stkoff, a) || hthas(s->globls, a);
+        return hthas(s->_stkoff, a) || hthas(s->globls, a);
     else
         return stacknode(a);
 }
@@ -209,7 +212,7 @@
         dump(n, stdout);
         printf("declared at %zd, size = %zd\n", s->stksz, size(n));
     }
-    htput(s->stkoff, n, itop(s->stksz));
+    htput(s->_stkoff, n, itop(s->stksz));
 }
 
 static void declarelocal(Simp *s, Node *n)
@@ -1565,13 +1568,7 @@
 static void declarearg(Simp *s, Node *n)
 {
     assert(n->type == Ndecl || (n->type == Nexpr && exprop(n) == Ovar));
-    s->argsz = align(s->argsz, min(size(n), Ptrsz));
-    htput(s->stkoff, n, itop(-(s->argsz + 2*Ptrsz)));
-    if (debugopt['i']) {
-        dump(n, stdout);
-        printf("declared at %zd\n", -(s->argsz + 2*Ptrsz));
-    }
-    s->argsz += size(n);
+    lappend(&s->args, &s->nargs, n);
 }
 
 static int islbl(Node *n)
@@ -1724,10 +1721,13 @@
 
     fn = zalloc(sizeof(Func));
     fn->name = strdup(name);
+    fn->type = dcl->decl.type;
     fn->isexport = isexport(dcl);
     fn->stksz = align(s->stksz, 8);
-    fn->stkoff = s->stkoff;
+    fn->stkoff = s->_stkoff;
     fn->ret = s->ret;
+    fn->args = s->args;
+    fn->nargs = s->nargs;
     fn->cfg = cfg;
     return fn;
 }
@@ -1800,7 +1800,7 @@
 
     if (ismain(dcl))
         dcl->decl.vis = Vishidden;
-    s.stkoff = mkht(varhash, vareq);
+    s._stkoff = mkht(varhash, vareq);
     s.globls = globls;
     s.blobs = *blob;
     s.nblobs = *nblob;
--- a/libstd/syscall+freebsd-x64.s
+++ b/libstd/syscall+freebsd-x64.s
@@ -1,14 +1,5 @@
 .globl sys$syscall
 sys$syscall:
-	pushq %rbp
-	pushq %rdi
-	pushq %rsi
-	pushq %rdx
-	pushq %r10
-	pushq %r8
-	pushq %r9
-	pushq %rcx
-	pushq %r11
 	/*
 	hack: We load 6 args regardless of
 	how many we actually have. This may
@@ -16,24 +7,15 @@
 	doesn't use them, it's going to be
 	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 %rdi,%rax
+	movq %rsi,%rdi
+	movq %rdx,%rsi
+	movq %rcx,%rdx
+	movq %r8,%r10
+	movq %r9,%r8
+	movq 8(%rsp),%r9
 
 	syscall
 
-	popq %r11
-	popq %rcx
-	popq %r9
-	popq %r8
-	popq %r10
-	popq %rdx
-	popq %rsi
-	popq %rdi
-	popq %rbp
 	ret
 
--- a/libstd/syscall+linux-x64.s
+++ b/libstd/syscall+linux-x64.s
@@ -1,15 +1,5 @@
 .globl sys$syscall
 sys$syscall:
-	pushq %rbp 
-	pushq %rdi 
-	pushq %rsi 
-	pushq %rdx 
-	pushq %r10 
-	pushq %r8
-	pushq %r9
-	pushq %rcx 
-	pushq %r11 
-
 	/*
 	hack: We load 6 args regardless of
 	how many we actually have. This may
@@ -17,25 +7,16 @@
 	doesn't use them, it's going to be
 	harmless.
 	 */
-	movq 80 (%rsp),%rax
-	/* 88: hidden type arg */
-	movq 96 (%rsp),%rdi
-	movq 104(%rsp),%rsi
-	movq 112(%rsp),%rdx
-	movq 120(%rsp),%r10
-	movq 128(%rsp),%r8
-	movq 136(%rsp),%r9
+	movq %rdi,%rax
+        /* 8(%rsp): hidden type arg */
+	movq 16(%rsp),%rdi
+	movq 24(%rsp),%rsi
+	movq 32(%rsp),%rdx
+	movq 40(%rsp),%r10
+	movq 48(%rsp),%r8
+	movq 56(%rsp),%r9
 
 	syscall
 
-	popq %r11
-	popq %rcx
-	popq %r9
-	popq %r8
-	popq %r10
-	popq %rdx
-	popq %rsi
-	popq %rdi
-	popq %rbp
 	ret
 
--- a/libstd/syscall+osx-x64.s
+++ b/libstd/syscall+osx-x64.s
@@ -1,14 +1,6 @@
 .globl _sys$syscall
 _sys$syscall:
-	pushq %rbp
-	pushq %rdi
-	pushq %rsi
-	pushq %rdx
-	pushq %r10
-	pushq %r8
-	pushq %r9
-	pushq %rcx
-	pushq %r11
+
 	/*
 	hack: We load 6 args regardless of
 	how many we actually have. This may
@@ -16,14 +8,14 @@
 	doesn't use them, it's going to be
 	harmless.
 	 */
-	movq 80 (%rsp),%rax
-	/* 88: hidden type arg */
-	movq 96 (%rsp),%rdi
-	movq 104(%rsp),%rsi
-	movq 112(%rsp),%rdx
-	movq 120(%rsp),%r10
-	movq 128(%rsp),%r8
-	movq 136(%rsp),%r9
+	movq %rdi,%rax
+        /* 8(%rsp): hidden type arg */
+	movq 16(%rsp),%rdi
+	movq 24(%rsp),%rsi
+	movq 32(%rsp),%rdx
+	movq 40(%rsp),%r10
+	movq 48(%rsp),%r8
+	movq 56(%rsp),%r9
 
 	syscall
 	jae .success
@@ -30,15 +22,6 @@
 	negq %rax
 
 .success:
-	popq %r11
-	popq %rcx
-	popq %r9
-	popq %r8
-	popq %r10
-	popq %rdx
-	popq %rsi
-	popq %rdi
-	popq %rbp
 	ret
 
 /*
@@ -51,16 +34,6 @@
  */
 .globl _sys$__osx_fork
 _sys$__osx_fork:
-	pushq %rbp
-	pushq %rdi
-	pushq %rsi
-	pushq %rdx
-	pushq %r10
-	pushq %r8
-	pushq %r9
-	pushq %rcx
-	pushq %r11
-
 	movq $0x2000002,%rax
 	syscall
 
@@ -72,16 +45,6 @@
 	jz .isparent
 	xorq %rax,%rax
 .isparent:
-
-	popq %r11
-	popq %rcx
-	popq %r9
-	popq %r8
-	popq %r10
-	popq %rdx
-	popq %rsi
-	popq %rdi
-	popq %rbp
 	ret
 
 /*
@@ -91,16 +54,6 @@
  */
 .globl _sys$__osx_pipe
 _sys$__osx_pipe:
-	pushq %rbp
-	pushq %rdi
-	pushq %rsi
-	pushq %rdx
-	pushq %r10
-	pushq %r8
-	pushq %r9
-	pushq %rcx
-	pushq %r11
-
 	movq $0x200002a,%rax
 	syscall
 
@@ -112,30 +65,10 @@
 	movl %eax,(%rdi)
 	movl %edx,4(%rdi)
 	xorq %rax,%rax
-
-	popq %r11
-	popq %rcx
-	popq %r9
-	popq %r8
-	popq %r10
-	popq %rdx
-	popq %rsi
-	popq %rdi
-	popq %rbp
 	ret
 
 .globl _sys$__osx_lseek
 _sys$__osx_lseek:
-	pushq %rbp
-	pushq %rdi
-	pushq %rsi
-	pushq %rdx
-	pushq %r10
-	pushq %r8
-	pushq %r9
-	pushq %rcx
-	pushq %r11
-
 	movq $0x20000C7,%rax
 	syscall
 
@@ -146,31 +79,11 @@
 	movq 80(%rsp),%rdi
         shlq $32,%rdx
         orq  %rdx,%rax
-
-	popq %r11
-	popq %rcx
-	popq %r9
-	popq %r8
-	popq %r10
-	popq %rdx
-	popq %rsi
-	popq %rdi
-	popq %rbp
 	ret
 
 
 .globl _sys$__osx_gettimeofday
 _sys$__osx_gettimeofday:
-	pushq %rbp
-	pushq %rdi
-	pushq %rsi
-	pushq %rdx
-	pushq %r10
-	pushq %r8
-	pushq %r9
-	pushq %rcx
-	pushq %r11
-
 	movq $0x2000074,%rax
 	syscall
 
@@ -182,15 +95,5 @@
 	movq %rax, (%rdi)
 	movl %edx,8(%rdi)
 	xorq %rax,%rax
-
-	popq %r11
-	popq %rcx
-	popq %r9
-	popq %r8
-	popq %r10
-	popq %rdx
-	popq %rsi
-	popq %rdi
-	popq %rbp
 	ret
 
--- a/libstd/util+posixy-x64.s
+++ b/libstd/util+posixy-x64.s
@@ -56,10 +56,9 @@
 	pushq %rbx
 
 	movq 8(%rbp),%r15	/* ret addr */
-	movq 16(%rbp),%rbx	/* len */
 
 	/* get stack space */
-	subq %rbx,%rsp		/* get stack space */
+	subq %rdi,%rsp		/* get stack space */
 	movq %rsp,%rax		/* top of stack (return value) */
 	subq $31,%rsp		/* "unpop" the args for return */
 	andq $(~15),%rsp	/* align */
--- a/libstd/varargs.myr
+++ b/libstd/varargs.myr
@@ -77,6 +77,9 @@
 	-> sl
 }
 
+const inspectarg = {x
+}
+
 generic vanext = {ap -> @a
 	var v : @a
 	var ti
@@ -87,6 +90,7 @@
 
 	/* apply the alignment to the arg pointer */
 	align = ti.align castto(intptr)
+	inspectarg(align)
 	p = ap.args castto(intptr)
 	p = (p + align - 1) & ~(align - 1)
 	ap.args = p castto(byte#)
--- a/mbld/deps.myr
+++ b/mbld/deps.myr
@@ -14,6 +14,7 @@
 	var usepat	: regex.regex#
 ;;
 
+const Abiversion = 5
 var usepat	: regex.regex#
 
 type dep = union
@@ -234,12 +235,13 @@
 	| `std.None:	std.fatal("library {}: could not read usefile\n", lib)
 	;;
 	match bio.getbe32(f)
-	| `std.Some 4:	/* nothing: version matches. */
-	| `std.Some 3:	std.fput(1, "library {}: warning: old usefile version\n", lib)
-	| `std.Some 2:	std.fput(1, "library {}: warning: old usefile version\n", lib)
-	| `std.Some 1:	std.fput(1, "library {}: warning: old usefile version\n", lib)
-	| `std.Some 0:	std.fput(1, "library {}: warning: old usefile version\n", lib)
-	| `std.Some _:	std.fatal("library {}: usefile version unknown\n", lib)
+	| `std.Some Abiversion:	/* nothing: version matches. */
+	| `std.Some v:	
+		if v < Abiversion
+			std.fput(1, "library {}: warning: old abi version\n", lib)
+		else
+			std.fatal("library {}: usefile version unknown\n", lib)
+		;;
 	| `std.None:	std.fatal("library {}: corrutpt or invalid usefile\n", lib)
 	;;
 	std.slfree(rdstr(f))
--- a/muse/Makefile
+++ b/muse/Makefile
@@ -5,3 +5,4 @@
 DEPS=../parse/libparse.a
 
 include ../mk/c.mk
+include ../config.mk
--- a/muse/muse.c
+++ b/muse/muse.c
@@ -81,7 +81,7 @@
 
     lappend(&incpaths, &nincpaths, Instroot "/lib/myr");
     if (!outfile) {
-        fprintf(stderr, "Output file needed when merging usefiles.");
+        fprintf(stderr, "output file needed when merging usefiles.\n");
         exit(1);
     }
 
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -4,7 +4,7 @@
 #	define FATAL
 #endif
 
-#define Abiversion 4
+#define Abiversion 5
 
 typedef uint8_t         byte;
 typedef unsigned int    uint;
--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -10,7 +10,7 @@
 
 function build {
     rm -f $1 $1.o $1.s $1.use
-    ../mbld/mbld -b $1 -C../6/6m -M../muse/muse -I../libstd -r../rt/_myrrt.o $1.myr
+    mbld -b $1 -C../6/6m -M../muse/muse -I../libstd -r../rt/_myrrt.o $1.myr
 }
 
 function pass {