shithub: mc

Download patch

ref: b0bb18ea0c30216319410faf536cb09bc0f31e99
parent: 7f764bf844fa3630cbc8e2740fa2a1c8439c4067
parent: cd759a0aeddace73edb206608e24c8410b753273
author: Ori Bernstein <[email protected]>
date: Thu Jun 7 09:59:50 EDT 2012

Merge branch 'master' of git+ssh://mimir.eigenstate.org/git/ori/mc2

Conflicts:
	8/reduce.c

--- a/8/asm.h
+++ b/8/asm.h
@@ -54,6 +54,7 @@
             /* only one of lbldisp and constdisp may be used */
             char *lbldisp;
             long constdisp;
+            int scale;
             Reg base;
             Reg idx;
         } mem;
@@ -85,8 +86,11 @@
 Loc *locreg(Loc *l, Reg r);
 Loc *locmem(Loc *l, long disp, Reg base, Reg idx, Mode mode);
 Loc *locmeml(Loc *l, char *disp, Reg base, Reg idx, Mode mode);
+Loc *locmems(Loc *l, long disp, Reg base, Reg idx, int scale, Mode mode);
+Loc *locmemls(Loc *l, char *disp, Reg base, Reg idx, int scale, Mode mode);
 Loc *loclit(Loc *l, long val);
 
 /* useful functions */
 size_t size(Node *n);
 void breakhere();
+
--- a/8/insns.def
+++ b/8/insns.def
@@ -24,9 +24,16 @@
 
 Insn(Iadd,      "\tadd%t %r,%x\n",              0)
 Insn(Isub,      "\tsub%t %r,%x\n",              0)
-Insn(Iand,      "\tand%d %r,%x\n",              0)
-Insn(Ior,       "\tor%d %r,%x\n",               0)
-Insn(Ixor,      "\txor%d %r,%x\n",              0)
+Insn(Imul,      "\tmul%t %r\n",              0)
+Insn(Idiv,      "\tdiv%t %r\n",              0)
+Insn(Ineg,      "\tneg%t %r\n",              0)
+Insn(Iand,      "\tand%t %r,%x\n",              0)
+Insn(Ior,       "\tor%t %r,%x\n",               0)
+Insn(Ixor,      "\txor%t %r,%x\n",              0)
+Insn(Inot,      "\tnot%t %x\n",              0)
+Insn(Ishl,      "\tsal%1t %r,%x\n",              0)
+Insn(Isar,      "\tshr%1t %r,%x\n",              0)
+Insn(Ishr,      "\tshr%1t %r,%x\n",              0)
 
 Insn(Itest,     "\ttest%t %r,%r\n",             0)
 Insn(Icmp,      "\tcmp%t %r,%r\n",              0)
--- a/8/isel.c
+++ b/8/isel.c
@@ -121,9 +121,17 @@
     l->mem.constdisp = disp;
     l->mem.base = base;
     l->mem.idx = idx;
+    l->mem.scale = 0;
     return l;
 }
 
+Loc *locmems(Loc *l, long disp, Reg base, Reg idx, int scale, Mode mode)
+{
+    locmem(l, disp, base, idx, mode);
+    l->mem.scale = scale;
+    return l;
+}
+
 Loc *locmeml(Loc *l, char *disp, Reg base, Reg idx, Mode mode)
 {
     l->type = Locmem;
@@ -131,9 +139,18 @@
     l->mem.lbldisp = strdup(disp);
     l->mem.base = base;
     l->mem.idx = idx;
+    l->mem.scale = 0;
     return l;
 }
 
+Loc *locmemls(Loc *l, char *disp, Reg base, Reg idx, int scale, Mode mode)
+{
+    locmeml(l, disp, base, idx, mode);
+    l->mem.scale = scale;
+    return l;
+}
+
+
 Loc *loclit(Loc *l, long val)
 {
     l->type = Loclit;
@@ -343,6 +360,15 @@
         return inr(s, a);
 }
 
+/* ensures that a location is within a reg or an imm */
+Loc inrm(Isel *s, Loc a)
+{
+    if (a.type == Locreg || a.type == Locmem)
+        return a;
+    else
+        return inr(s, a);
+}
+
 /* If we're testing equality, etc, it's a bit silly
  * to generate the test, store it to a bite, expand it
  * to the right width, and then test it again. Try to optimize
@@ -394,11 +420,29 @@
     return a;
 }
 
+static int ismergablemul(Node *n, int *r)
+{
+    int v;
+
+    if (exprop(n) != Omul)
+        return 0;
+    if (exprop(n->expr.args[1]) != Olit)
+        return 0;
+    if (n->expr.args[1]->expr.args[0]->type != Nlit)
+        return 0;
+    if (n->expr.args[1]->expr.args[0]->lit.littype != Lint)
+        return 0;
+    v = n->expr.args[1]->expr.args[0]->lit.intval;
+    if (v != 2 && v != 4 && v != 8)
+        return 0;
+    *r = v;
+    return 1;
+}
 /* We have a few common cases to optimize here:
  *    Oadd(
  *        reg,
  *        reg||const))
- * TODO:
+ * or:
  *    Oadd(
  *        reg,
  *        Omul(reg,
@@ -408,11 +452,16 @@
 {
     Node **args;
     Loc l, b, o; /* location, base, offset */
+    int scale;
 
+    scale = 0;
     if (exprop(e) == Oadd) {
         args = e->expr.args;
         b = selexpr(s, args[0]);
-        o = selexpr(s, args[1]);
+        if (ismergablemul(args[1], &scale))
+            o = selexpr(s, args[1]->expr.args[0]);
+        else
+            o = selexpr(s, args[1]);
         if (b.type != Locreg)
             b = inr(s, b);
         if (o.type == Loclit) {
@@ -419,7 +468,7 @@
             locmem(&l, o.lit, b.reg, Rnone, m);
         } else if (o.type == Locreg) {
             b = inr(s, b);
-            locmem(&l, 0, b.reg, o.reg, m);
+            locmems(&l, 0, b.reg, o.reg, scale, m);
         }
     } else {
         l = selexpr(s, e);
@@ -472,27 +521,92 @@
 Loc selexpr(Isel *s, Node *n)
 {
     Loc a, b, c, r;
+    Loc eax, edx, cl; /* x86 wanst some hard-coded regs */
     Node **args;
 
     args = n->expr.args;
     r = (Loc){Locnone, };
+    locreg(&eax, Reax);
+    locreg(&edx, Redx);
+    locreg(&cl, Rcl);
     switch (exprop(n)) {
         case Oadd:      r = binop(s, Iadd, args[0], args[1]); break;
         case Osub:      r = binop(s, Isub, args[0], args[1]); break;
 
-        case Omul:      die("Unimplemented op %s", opstr(exprop(n))); break;
-        case Odiv:      die("Unimplemented op %s", opstr(exprop(n))); break;
-        case Omod:      die("Unimplemented op %s", opstr(exprop(n))); break;
-        case Oneg:      die("Unimplemented op %s", opstr(exprop(n))); break;
+        case Omul:
+            /* these get clobbered by the mul insn */
+            claimreg(s, Reax);
+            claimreg(s, Redx);
+            a = selexpr(s, args[0]);
+            b = selexpr(s, args[1]);
+            b = inr(s, b);
+            c = coreg(eax, mode(n));
+            g(s, Imov, &a, &c, NULL);
+            g(s, Imul, &b, NULL);
+            freereg(s, Redx);
+            r = eax;
+            break;
+        case Odiv:
+        case Omod:
+            /* these get clobbered by the div insn */
+            claimreg(s, Reax);
+            claimreg(s, Redx);
+            a = selexpr(s, args[0]);
+            b = selexpr(s, args[1]);
+            b = inr(s, b);
+            c = coreg(eax, mode(n));
+            g(s, Imov, &a, &c, NULL);
+            g(s, Ixor, &edx, &edx, NULL);
+            g(s, Idiv, &b, NULL);
+            freereg(s, Redx);
+            if (exprop(n) == Odiv)
+                r = eax;
+            else
+                r = edx;
+            break;
+        case Oneg:
+            r = selexpr(s, args[0]);
+            r = inr(s, r);
+            g(s, Ineg, &r, NULL);
+            break;
 
         case Obor:      r = binop(s, Ior,  args[0], args[1]); break;
         case Oband:     r = binop(s, Iand, args[0], args[1]); break;
         case Obxor:     r = binop(s, Ixor, args[0], args[1]); break;
-        case Obsl:      die("Unimplemented op %s", opstr(exprop(n))); break;
-        case Obsr:      die("Unimplemented op %s", opstr(exprop(n))); break;
-        case Obnot:     die("Unimplemented op %s", opstr(exprop(n))); break;
+        case Obsl:      
+        case Obsr:
+            claimreg(s, Rcl); /* shift requires cl as it's arg. stupid. */
+            a = selexpr(s, args[0]);
+            a = inr(s, a);
+            b = selexpr(s, args[1]);
+            c = coreg(cl, b.mode);
+            g(s, Imov, &b, &c, NULL);
+            if (exprop(n) == Obsr) {
+                if (istysigned(n->expr.type))
+                    g(s, Isar, &cl, &a, NULL);
+                else
+                    g(s, Ishr, &cl, &a, NULL);
+            } else {
+                g(s, Ishl, &cl, &a, NULL);
+            }
+            freeloc(s, cl);
+            freeloc(s, b);
+            r = a;
+            break;
+        case Obnot:
+            r = selexpr(s, args[0]);
+            r = inrm(s, r);
+            g(s, Inot, &r, NULL);
+            break;
 
-        case Oderef:    die("Unimplemented op %s", opstr(exprop(n))); break;
+        case Oderef:
+            a = selexpr(s, args[0]);
+            a = inr(s, a);
+            r = getreg(s, a.mode);
+            locmem(&c, 0, a.reg, Rnone, a.mode);
+            g(s, Imov, &c, &r, NULL);
+            break;
+
         case Oaddr:
             a = selexpr(s, args[0]);
             r = getreg(s, ModeL);
@@ -593,6 +707,8 @@
                 fprintf(fd, "(%s", regnames[l->mem.base]);
             if (l->mem.idx)
                 fprintf(fd, ",%s", regnames[l->mem.idx]);
+            if (l->mem.scale)
+                fprintf(fd, ",%d", l->mem.scale);
             if (l->mem.base)
                 fprintf(fd, ")");
             break;
--- a/8/reduce.c
+++ b/8/reduce.c
@@ -52,6 +52,7 @@
 Node *rval(Simp *s, Node *n);
 Node *lval(Simp *s, Node *n);
 void declarelocal(Simp *s, Node *n);
+size_t size(Node *n);
 
 void append(Simp *s, Node *n)
 {
@@ -89,18 +90,11 @@
     return s;
 }
 
-
-size_t size(Node *n)
+size_t tysize(Type *t)
 {
-    Type *t;
     size_t sz;
     int i;
 
-    if (n->type == Nexpr)
-        t = n->expr.type;
-    else
-        t = n->decl.sym->type;
-
     sz = 0;
     switch (t->type) {
         case Tyvoid:
@@ -131,7 +125,8 @@
         case Tyslice:
             return 8; /* len; ptr */
         case Tyarray:
-            return 42;
+            assert(exprop(t->asize) == Olit);
+            return t->asize->expr.args[0]->lit.intval * tysize(t->sub[0]);
         case Tytuple:
         case Tystruct:
             for (i = 0; i < t->nmemb; i++)
@@ -148,6 +143,18 @@
     return -1;
 }
 
+size_t size(Node *n)
+{
+    Type *t;
+
+    if (n->type == Nexpr)
+        t = n->expr.type;
+    else
+        t = n->decl.sym->type;
+
+    return tysize(t);
+}
+
 Node *genlbl(void)
 {
     char buf[128];
@@ -287,8 +294,10 @@
 
 static Node *idxaddr(Simp *s, Node *n)
 {
-    Node *t, *u, *r;
+    Node *t, *u, *v; /* temps */
+    Node *r; /* result */
     Node **args;
+    size_t sz;
 
     assert(exprop(n) == Oidx);
     args = n->expr.args;
@@ -299,23 +308,28 @@
     else
         die("Can't index type %s\n", tystr(n->expr.type));
     u = rval(s, args[1]);
-    r = mkexpr(-1, Oadd, t, u, NULL);
+    sz = size(n);
+    v = mkexpr(-1, Omul, u, mkexpr(-1, Olit, mkint(-1, sz), NULL));
+    r = mkexpr(-1, Oadd, t, v, NULL);
     return r;
 }
 
 static Node *slicebase(Simp *s, Node *n, Node *off)
 {
-    Node *t, *u;
+    Node *t, *u, *v;
+    int sz;
 
     t = rval(s, n);
     u = NULL;
     switch (n->expr.type->type) {
         case Typtr:     u = n;
-        case Tyarray:   u = mkexpr(-1, Oaddr, n, NULL); break;
-        case Tyslice:   u = mkexpr(-1, Oslbase, n, NULL); break;
+        case Tyarray:   u = mkexpr(-1, Oaddr, t, NULL); break;
+        case Tyslice:   u = mkexpr(-1, Oslbase, t, NULL); break;
         default: die("Unslicable type %s", tystr(n->expr.type));
     }
-    return mkexpr(-1, Oadd, u, off, NULL);
+    sz = tysize(n->expr.args[0]->expr.type->sub[0]);
+    v = mkexpr(-1, Omul, u, mkexpr(-1, Olit, mkint(-1, sz), NULL));
+    return mkexpr(-1, Oadd, u, v, NULL);
 }
 
 Node *lval(Simp *s, Node *n)
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -506,7 +506,6 @@
             t->sub[i] = tyfin(ctx, t->sub[i]);
     }
     if (t->type == Tyvar || t->type == Tyidxhack) {
-        dump(ctx, stdout);
         fatal(t->line, "underconstrained type %s near %s", tyfmt(buf, 1024, t), ctxstr(ctx));
     }
 
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -295,6 +295,7 @@
 Type *mktyenum(int line, Node **decls, size_t ndecls);
 Cstr *mkcstr(int line, char *name, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs);
 Type *tylike(Type *t, Ty ty); /* constrains tyvar t like it was builtin ty */
+int   istysigned(Type *t);
 
 /* type manipulation */
 int hascstr(Type *t, Cstr *c);
--- a/parse/tok.c
+++ b/parse/tok.c
@@ -358,7 +358,7 @@
         case '>':
                   if (match('=')) {
                       tt = Tge;
-                  } else if (match('<')) {
+                  } else if (match('>')) {
                       if (match('='))
                           tt = Tbsreq;
                       else
--- a/parse/type.c
+++ b/parse/type.c
@@ -187,6 +187,17 @@
     return t;
 }
 
+int istysigned(Type *t)
+{
+    switch (t->type) {
+        case Tyint8: case Tyint16: case Tyint:
+        case Tyint32: case Tyint64: case Tylong:
+            return 1;
+        default:
+            return 0;
+    }
+}
+
 void tlappend(Type ***tl, int *len, Type *t)
 {
     *tl = xrealloc(tl, (*len + 1)*sizeof(Type*));
--- a/test/Makefile
+++ b/test/Makefile
@@ -2,10 +2,12 @@
 all: 
 
 check:
-	./build.sh
 	./test.sh
 .PHONY: clean
 clean:
-	rm -f $(TESTBIN) $(TESTBIN:=.o) $(TESTBIN:=.s)
+	@for i in `awk '{print $$1}' tests`; do \
+	    echo rm -f $$i; \
+	    rm -f $$i; \
+	done
 
 install:
--- /dev/null
+++ b/test/bsr.myr
@@ -1,0 +1,3 @@
+const main = {
+	-> 42 >> 3
+}
--- a/test/build.sh
+++ /dev/null
@@ -1,24 +1,0 @@
-#!/bin/bash
-
-MC=../8/8m
-ASOPT="-g"
-
-function build {
-    rm $1
-    echo $MC $1.myr && \
-    $MC $1.myr && \
-    mv a.s $1.s && \
-    cc $ASOPT -m32 -o $1 $1.s
-}
-
-build main
-build add
-build struct_oneval
-build struct
-build array
-build call
-build loop
-build fib
-build slice
-
-exit 0
--- /dev/null
+++ b/test/call.myr
@@ -1,0 +1,7 @@
+const f = {
+	-> 21
+}
+
+const main = {
+	-> f() + f()
+}
--- /dev/null
+++ b/test/div.myr
@@ -1,0 +1,3 @@
+const main = {
+	-> 84 / 2
+}
--- /dev/null
+++ b/test/float.myr
@@ -1,0 +1,3 @@
+const main = {
+	-> 42.0 + 42.0
+}
--- /dev/null
+++ b/test/loop.myr
@@ -1,0 +1,10 @@
+const main = {
+	var i
+	var n
+
+	n = 0
+	for i = 0; i < 10; ++i
+		n += i
+	;;
+	-> n
+}
--- /dev/null
+++ b/test/mod.myr
@@ -1,0 +1,3 @@
+const main = {
+	-> 42 % 9
+}
--- /dev/null
+++ b/test/mul.myr
@@ -1,0 +1,3 @@
+const main = {
+	-> 42 * 2
+}
--- /dev/null
+++ b/test/struct1.myr
@@ -1,0 +1,9 @@
+type val = struct
+	a : int
+;;
+
+const main = {
+	var s : val
+	s.a = 12
+	-> s.a
+}
--- a/test/struct_oneval.myr
+++ /dev/null
@@ -1,9 +1,0 @@
-type val = struct
-	a : int
-;;
-
-const main = {
-	var s : val
-	s.a = 12
-	-> s.a
-}
--- a/test/test.sh
+++ b/test/test.sh
@@ -1,6 +1,16 @@
 #!/bin/bash
 export PATH=.:$PATH
+export MC=../8/8m
+export ASOPT="-g"
 
+function build {
+    rm -f $1
+    echo $MC $1.myr && \
+    $MC $1.myr && \
+    mv a.s $1.s && \
+    cc $ASOPT -m32 -o $1 $1.s
+}
+
 function prints {
     if [ `./$1` -ne $2 ]; then
         echo "FAIL: $1"
@@ -9,21 +19,31 @@
     fi
 }
 
-function returns {
-    ./$1
-    if [ $? -eq $2 ]; then
-        echo "PASS: $1"
+function exitswith {
+    if [ -e $1 ]; then
+        ./$1
+        if [ $? -eq $2 ]; then
+            echo "PASS: $1"
+        else
+            echo "FAIL: $1"
+        fi
     else
         echo "FAIL: $1"
     fi
 }
 
-returns main 0
-returns add 53
-returns struct_oneval 12
-returns struct 42
-returns array 7
-returns call 42
-returns loop 45
-returns fib 21
-returns slice 7
+for i in `awk '{print $1}' tests`; do
+    build $i
+done
+
+export IFS='
+'
+for i in `cat tests`; do
+    tst=`echo $i | awk '{print $1}'`
+    type=`echo $i | awk '{print $2}'`
+    val=`echo $i | awk '{print $3}'`
+    case $type in
+        E) exitswith $tst $val ;;
+        P) prints $tst $val ;;
+    esac
+done
--- /dev/null
+++ b/test/tests
@@ -1,0 +1,14 @@
+main	E	0
+add	E	53
+mul     E       84
+div     E       42
+mod     E       6
+bsr     E       5
+struct1	E	12
+struct	E	42
+array	E	7
+call	E	42
+loop	E	45
+fib	E	21
+slice	E	7
+float   E       1