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