shithub: mc

Download patch

ref: 18ad8af1fb596563dcc32e618f46b454efb94f75
parent: da885b02dd6178dd20ba7929b1d62aa07c0cfe8d
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Jul 26 21:32:42 EDT 2012

Make truncating casts not broken.

--- a/8/asm.h
+++ b/8/asm.h
@@ -178,7 +178,7 @@
 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);
--- a/8/isel.c
+++ b/8/isel.c
@@ -116,9 +116,9 @@
         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 @@
      * 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 @@
             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 @@
             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 @@
             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 @@
 
     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);
--- a/8/locs.c
+++ b/8/locs.c
@@ -53,7 +53,6 @@
     [Rebp] = {Rebp},
 };
 
-
 char *genlblstr(char *buf, size_t sz)
 {
     static int nextlbl;
@@ -171,13 +170,13 @@
 }
 
 
-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;
 }
--- a/8/regs.def
+++ b/8/regs.def
@@ -5,6 +5,12 @@
 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)
--- a/8/simp.c
+++ b/8/simp.c
@@ -648,6 +648,7 @@
 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 @@
         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 @@
     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 @@
                               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 @@
     return r;
 }
 
-static void reduce(Simp *s, Node *f)
+static void flatten(Simp *s, Node *f)
 {
     Node *dcl;
     Type *ty;
@@ -1126,7 +1144,7 @@
     /* 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++)
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -441,6 +441,8 @@
 
 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
         ;
 
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -664,6 +664,7 @@
         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;
     }
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -59,3 +59,6 @@
 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 */
--- a/test/tests
+++ b/test/tests
@@ -19,6 +19,9 @@
 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