summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2012-07-27 01:32:42 -0400
committerOri Bernstein <ori@eigenstate.org>2012-07-27 01:32:42 -0400
commit18ad8af1fb596563dcc32e618f46b454efb94f75 (patch)
tree59cd4bc30c3b40a8551df5d39fecd1a3ac8f3cdb
parentda885b02dd6178dd20ba7929b1d62aa07c0cfe8d (diff)
downloadmc-18ad8af1fb596563dcc32e618f46b454efb94f75.tar.gz
Make truncating casts not broken.
-rw-r--r--8/asm.h2
-rw-r--r--8/isel.c35
-rw-r--r--8/locs.c5
-rw-r--r--8/regs.def6
-rw-r--r--8/simp.c30
-rw-r--r--parse/gram.y2
-rw-r--r--parse/infer.c1
-rw-r--r--parse/ops.def3
-rw-r--r--test/tests3
9 files changed, 69 insertions, 18 deletions
diff --git a/8/asm.h b/8/asm.h
index 433bb9e..ad7d34a 100644
--- a/8/asm.h
+++ b/8/asm.h
@@ -178,7 +178,7 @@ Loc *locmem(long disp, Loc *base, Loc *idx, Mode mode);
Loc *locmeml(char *disp, Loc *base, Loc *idx, Mode mode);
Loc *locmems(long disp, Loc *base, Loc *idx, int scale, Mode mode);
Loc *locmemls(char *disp, Loc *base, Loc *idx, int scale, Mode mode);
-Loc *loclit(long val);
+Loc *loclit(long val, Mode m);
Loc *loclitl(char *lbl);
void locprint(FILE *fd, Loc *l, char spec);
diff --git a/8/isel.c b/8/isel.c
index ce1d792..43fdaa2 100644
--- a/8/isel.c
+++ b/8/isel.c
@@ -116,9 +116,9 @@ static Loc *loc(Isel *s, Node *n)
case Olit:
v = n->expr.args[0];
switch (v->lit.littype) {
- case Lchr: l = loclit(v->lit.chrval); break;
- case Lbool: l = loclit(v->lit.boolval); break;
- case Lint: l = loclit(v->lit.intval); break;
+ case Lchr: l = loclit(v->lit.chrval, mode(n)); break;
+ case Lbool: l = loclit(v->lit.boolval, mode(n)); break;
+ case Lint: l = loclit(v->lit.intval, mode(n)); break;
default:
die("Literal type %s should be blob", litstr(v->lit.littype));
}
@@ -391,7 +391,7 @@ static Loc *gencall(Isel *s, Node *n)
* 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]);
- stkbump = loclit(argsz);
+ stkbump = loclit(argsz, ModeL);
if (argsz)
g(s, Isub, stkbump, esp, NULL);
@@ -448,7 +448,7 @@ Loc *selexpr(Isel *s, Node *n)
r = locreg(a->mode);
g(s, Imov, a, c, NULL);
g(s, Imul, b, NULL);
- g(s, Imov, eax, r, NULL);
+ g(s, Imov, coreg(Reax, mode(n)), r, NULL);
break;
case Odiv:
case Omod:
@@ -458,13 +458,17 @@ Loc *selexpr(Isel *s, Node *n)
b = inr(s, b);
c = coreg(Reax, mode(n));
r = locreg(a->mode);
+ if (r->mode == ModeB)
+ g(s, Ixor, eax, eax, NULL);
g(s, Imov, a, c, NULL);
g(s, Ixor, edx, edx, NULL);
g(s, Idiv, b, NULL);
if (exprop(n) == Odiv)
- d = eax;
+ d = coreg(Reax, mode(n));
+ else if (r->mode != ModeB)
+ d = coreg(Redx, mode(n));
else
- d = edx;
+ d = locphysreg(Rah);
g(s, Imov, d, r, NULL);
break;
case Oneg:
@@ -586,6 +590,21 @@ Loc *selexpr(Isel *s, Node *n)
blit(s, a, b, 0, 0, args[2]->expr.args[0]->lit.intval);
r = b;
break;
+ case Otrunc:
+ r = selexpr(s, args[0]);
+ r->mode = mode(n);
+ break;
+ case Ozwiden:
+ a = selexpr(s, args[0]);
+ b = locreg(mode(n));
+ g(s, Imovz, b, a, NULL);
+ r = b;
+ case Oswiden:
+ a = selexpr(s, args[0]);
+ b = locreg(mode(n));
+ g(s, Imovs, b, a, NULL);
+ r = b;
+ break;
/* These operators should never show up in the reduced trees,
* since they should have been replaced with more primitive
@@ -727,7 +746,7 @@ static void prologue(Isel *s, size_t sz)
esp = locphysreg(Resp);
ebp = locphysreg(Rebp);
- stksz = loclit(sz);
+ stksz = loclit(sz, ModeL);
g(s, Ipush, ebp, NULL);
g(s, Imov, esp, ebp, NULL);
g(s, Isub, stksz, esp, NULL);
diff --git a/8/locs.c b/8/locs.c
index 0b3178b..b9fa193 100644
--- a/8/locs.c
+++ b/8/locs.c
@@ -53,7 +53,6 @@ const Reg reginterferes[Nreg][Nmode + 1] = {
[Rebp] = {Rebp},
};
-
char *genlblstr(char *buf, size_t sz)
{
static int nextlbl;
@@ -171,13 +170,13 @@ Loc *locmemls(char *disp, Loc *base, Loc *idx, int scale, Mode mode)
}
-Loc *loclit(long val)
+Loc *loclit(long val, Mode m)
{
Loc *l;
l = zalloc(sizeof(Loc));
l->type = Loclit;
- l->mode = ModeL; /* FIXME: what do we do for mode? */
+ l->mode = m;
l->lit = val;
return l;
}
diff --git a/8/regs.def b/8/regs.def
index 2c1e789..75b9d6a 100644
--- a/8/regs.def
+++ b/8/regs.def
@@ -5,6 +5,12 @@ Reg(Rcl, "%cl", ModeB)
Reg(Rdl, "%dl", ModeB)
Reg(Rbl, "%bl", ModeB)
+/* high byte regs. We *NEVER* allocate these */
+Reg(Rah, "%ah", ModeB)
+Reg(Rch, "%ch", ModeB)
+Reg(Rdh, "%dh", ModeB)
+Reg(Rbh, "%bh", ModeB)
+
/* short regs */
Reg(Rax, "%ax", ModeS)
Reg(Rbx, "%bx", ModeS)
diff --git a/8/simp.c b/8/simp.c
index a2bffe9..b1cacbd 100644
--- a/8/simp.c
+++ b/8/simp.c
@@ -648,6 +648,7 @@ static Node *simplazy(Simp *s, Node *n, Node *r)
static Node *lowerslice(Simp *s, Node *n, Node *dst)
{
Node *t;
+ Node *start, *end;
Node *base, *sz, *len;
Node *stbase, *stlen;
@@ -657,7 +658,9 @@ static Node *lowerslice(Simp *s, Node *n, Node *dst)
t = temp(s, n);
/* *(&slice) = (void*)base + off*sz */
base = slicebase(s, n->expr.args[0], n->expr.args[1]);
- len = sub(n->expr.args[2], n->expr.args[1]);
+ start = rval(s, n->expr.args[1], NULL);
+ end = rval(s, n->expr.args[2], NULL);
+ len = sub(end, start);
stbase = store(addr(t, tyword), base);
/* *(&slice + ptrsz) = len */
sz = add(addr(t, tyword), ptrsz);
@@ -672,7 +675,10 @@ static Node *lowercast(Simp *s, Node *n)
Node **args;
Node *r;
Type *t;
+ int issigned;
+ size_t fromsz, tosz;
+ issigned = 0;
r = NULL;
args = n->expr.args;
switch (tybase(exprtype(n))->type) {
@@ -691,12 +697,24 @@ static Node *lowercast(Simp *s, Node *n)
tystr(exprtype(args[0])), tystr(exprtype(n)));
break;
case Tyint8: case Tyint16: case Tyint32: case Tyint64:
+ case Tyint: case Tylong:
+ issigned = 1;
case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint64:
- case Tyint: case Tyuint: case Tylong: case Tyulong:
- case Tychar: case Tybyte:
+ case Tyuint: case Tyulong: case Tychar: case Tybyte:
case Typtr:
- args[0]->expr.type = n->expr.type;
+ fromsz = size(args[0]);
+ tosz = size(n);
r = rval(s, args[0], NULL);
+ r->expr.type = n->expr.type;
+ if (fromsz > tosz) {
+ r = mkexpr(n->line, Otrunc, r, NULL);
+ } else if (tosz > fromsz) {
+ if (issigned)
+ r = mkexpr(n->line, Oswiden, r, NULL);
+ else
+ r = mkexpr(n->line, Ozwiden, r, NULL);
+ }
+ r->expr.type = n->expr.type;
break;
default:
fatal(n->line, "Bad cast from %s to %s",
@@ -1078,7 +1096,7 @@ static Node *simp(Simp *s, Node *n)
return r;
}
-static void reduce(Simp *s, Node *f)
+static void flatten(Simp *s, Node *f)
{
Node *dcl;
Type *ty;
@@ -1126,7 +1144,7 @@ static Func *lowerfn(Simp *s, char *name, Node *n, int export)
/* unwrap to the function body */
n = n->expr.args[0];
n = n->lit.fnval;
- reduce(s, n);
+ flatten(s, n);
if (debug)
for (i = 0; i < s->nstmts; i++)
diff --git a/parse/gram.y b/parse/gram.y
index 2eaaa69..98d955a 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -441,6 +441,8 @@ unionexpr
borexpr : borexpr Tbor bandexpr
{$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
+ | borexpr Tbxor bandexpr
+ {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
| bandexpr
;
diff --git a/parse/infer.c b/parse/infer.c
index 14a352c..c86333c 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -664,6 +664,7 @@ static void inferexpr(Inferstate *st, Node *n, Type *ret, int *sawret)
case Oload: case Ostor: case Oset:
case Oslbase: case Osllen:
case Oblit: case Numops:
+ case Otrunc: case Oswiden: case Ozwiden:
die("Should not see %s in fe", opstr(exprop(n)));
break;
}
diff --git a/parse/ops.def b/parse/ops.def
index 38bcb8a..05b65c5 100644
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -59,3 +59,6 @@ O(Oset, 1) /* store to var */
O(Osllen, 1) /* size of slice */
O(Oslbase, 1) /* base of sice */
O(Oblit, 1) /* block copy of memory */
+O(Otrunc, 1) /* truncating cast */
+O(Ozwiden, 1) /* zero-extending widening cast */
+O(Oswiden, 1) /* sign-extending widening cast */
diff --git a/test/tests b/test/tests
index 7370362..7af1747 100644
--- a/test/tests
+++ b/test/tests
@@ -19,6 +19,9 @@ B mul E 42
B div E 42
B mod E 6
B bsr E 5
+B trunccast E 15
+B zwidencast E 99
+B swidencast E 99
B ptrpreinc E 9
B struct1 E 12
B struct E 42