shithub: mc

Download patch

ref: 063b2a4e134589a8a1d635708eb0eb39d5a76bfb
parent: bd0724eccecfb0ea9651cf8d5b5f8d6bfaca6e4c
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Jan 25 09:35:28 EST 2015

Clear structs.

    When creating stack structs, clear them.

    TODO: only clear uninitialized values.

--- a/6/asm.h
+++ b/6/asm.h
@@ -241,8 +241,8 @@
 /* useful functions */
 size_t tysize(Type *t);
 size_t size(Node *n);
-size_t tyoffset(Type *ty, Node *memb);
-size_t offset(Node *aggr, Node *memb);
+ssize_t tyoffset(Type *ty, Node *memb);
+ssize_t offset(Node *aggr, Node *memb);
 int stacktype(Type *t);
 int floattype(Type *t);
 int stacknode(Node *n);
--- a/6/insns.def
+++ b/6/insns.def
@@ -46,24 +46,29 @@
     "\tMOV%1T%2TSX %X,%X\n",
     Use(.l={1}),
     Def(.l={2}))
+Insn(Irepstosb,
+    "\trep stosb\n",
+    "\tREP; STOSB\n",
+    Use(.r={Rrax,Rrcx,Rrsi,Rrdi}),
+    Def(None))
 Insn(Irepmovsb,
     "\trep movsb\n",
-    "\tREP MOVSB\n",
+    "\tREP; MOVSB\n",
     Use(.r={Rrcx,Rrsi,Rrdi}),
     Def(None))
 Insn(Irepmovsw,
     "\trep movsw\n",
-    "\tREP MOVSW\n",
+    "\tREP; MOVSW\n",
     Use(.r={Rrcx,Rrsi,Rrdi}),
     Def(None))
 Insn(Irepmovsl,
     "\trep movsl\n",
-    "\tREP MOVSL\n",
+    "\tREP; MOVSL\n",
     Use(.r={Rrcx,Rrsi,Rrdi}),
     Def(None))
 Insn(Irepmovsq,
     "\trep movsq\n",
-    "\tREP MOVSQ\n",
+    "\tREP; MOVSQ\n",
     Use(.r={Rrcx,Rrsi,Rrdi}),
     Def(None))
 Insn(Ilea,
--- a/6/isel.c
+++ b/6/isel.c
@@ -345,29 +345,31 @@
     return l;
 }
 
+static const Mode szmodes[] = {
+    [8] = ModeQ,
+    [4] = ModeL,
+    [2] = ModeW,
+    [1] = ModeB
+};
 static void blit(Isel *s, Loc *to, Loc *from, size_t dstoff, size_t srcoff, size_t sz, size_t align)
 {
-    static const Mode modes[] = {
-        [8] = ModeQ,
-        [4] = ModeL,
-        [2] = ModeW,
-        [1] = ModeB
-    };
     size_t i, modesz;
     Loc *sp, *dp, *len; /* pointers to src, dst */
     Loc *tmp, *src, *dst; /* source memory, dst memory */
 
-    assert(modes[align] != ModeNone);   /* make sure we have a valid alignment */
+    assert(szmodes[align] != ModeNone);   /* make sure we have a valid alignment */
     sp = inr(s, from);
     dp = inr(s, to);
 
     i = 0;
-    if (sz <= 64*align) { /* arbitrary threshold; should be tuned */
-        for (modesz = align; modes[modesz] != ModeNone; modesz /= 2) {
-            tmp = locreg(modes[modesz]);
+    if (align == 0)
+        align = 8;
+    if (sz <= 128) { /* arbitrary threshold; should be tuned */
+        for (modesz = align; szmodes[modesz] != ModeNone; modesz /= 2) {
+            tmp = locreg(szmodes[modesz]);
             while (i + modesz <= sz) {
-                src = locmem(i + srcoff, sp, NULL, modes[modesz]);
-                dst = locmem(i + dstoff, dp, NULL, modes[modesz]);
+                src = locmem(i + srcoff, sp, NULL, szmodes[modesz]);
+                dst = locmem(i + dstoff, dp, NULL, szmodes[modesz]);
                 g(s, Imov, src, tmp, NULL);
                 g(s, Imov, tmp, dst, NULL);
                 i += modesz;
@@ -395,6 +397,37 @@
         
 }
 
+static void clear(Isel *s, Loc *val, size_t sz, size_t align)
+{
+    Loc *dp, *len, *rax; /* pointers to src, dst */
+    Loc *zero, *dst; /* source memory, dst memory */
+    size_t modesz, i;
+
+    i = 0;
+    dp = inr(s, val);
+    rax = locphysreg(Rrax);
+    g(s, Ixor,  rax, rax, NULL);
+    if (align == 0)
+        align = 8;
+    if (sz <= 128) { /* arbitrary threshold; should be tuned */
+        for (modesz = align; szmodes[modesz] != ModeNone; modesz /= 2) {
+            zero = loclit(0, szmodes[modesz]);
+            while (i + modesz <= sz) {
+                zero = coreg(Rrax, szmodes[modesz]);
+                dst = locmem(i, dp, NULL, szmodes[modesz]);
+                g(s, Imov, zero, dst, NULL);
+                i += modesz;
+            }
+        }
+    } else {
+        len = loclit(sz, ModeQ);
+        /* length to blit */
+        g(s, Imov, len, locphysreg(Rrcx), NULL);
+        g(s, Imov, dp, locphysreg(Rrdi), NULL);
+        g(s, Irepstosb, NULL);
+    }
+}
+
 static int isconstfunc(Isel *s, Node *n)
 {
     Node *d;
@@ -698,6 +731,11 @@
             r = selexpr(s, args[1]);
             al = alignto(1, args[0]->expr.type->sub[0]);
             blit(s, a, r, 0, 0, args[2]->expr.args[0]->lit.intval, al);
+            break;
+
+        case Oclear:
+            a = selexpr(s, args[0]);
+            clear(s, a, args[1]->expr.args[0]->lit.intval, 0);
             break;
 
         /* cast operators that actually modify the values */
--- a/6/simp.c
+++ b/6/simp.c
@@ -1226,13 +1226,13 @@
     return r;
 }
 
-
 static Node *rval(Simp *s, Node *n, Node *dst)
 {
-    Node *r; /* expression result */
     Node *t, *u, *v; /* temporary nodes */
+    Node *r; /* expression result */
     Node **args;
     size_t i;
+    Type *ty;
     const Op fusedmap[Numops] = {
         [Oaddeq]        = Oadd,
         [Osubeq]        = Osub,
@@ -1297,6 +1297,10 @@
             if (!dst)
                 dst = temp(s, n);
             t = addr(s, dst, exprtype(dst));
+            ty = exprtype(n);
+            /* we only need to clear if we don't have things fully initialized */
+            if (tybase(ty)->nmemb != n->expr.nargs)
+                append(s, mkexpr(n->loc, Oclear, t, mkintlit(n->loc, size(n)), NULL));
             for (i = 0; i < n->expr.nargs; i++)
                 assignat(s, t, offset(n, n->expr.args[i]->expr.idx), n->expr.args[i]);
             r = dst;
--- a/6/typeinfo.c
+++ b/6/typeinfo.c
@@ -91,7 +91,7 @@
 }
 
 /* gets the byte offset of 'memb' within the aggregate type 'aggr' */
-size_t tyoffset(Type *ty, Node *memb)
+ssize_t tyoffset(Type *ty, Node *memb)
 {
     size_t i;
     size_t off;
@@ -108,7 +108,6 @@
             return off;
         off += size(ty->sdecls[i]);
     }
-    die("Could not find member %s in struct", namestr(memb));
     return -1;
 }
 
@@ -123,7 +122,7 @@
     return tysize(t);
 }
 
-size_t offset(Node *aggr, Node *memb)
+ssize_t offset(Node *aggr, Node *memb)
 {
     return tyoffset(exprtype(aggr), memb);
 }
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1375,13 +1375,13 @@
             break;
         case Obad: case Ocjmp: case Ojtab: case Oset:
         case Oslbase: case Osllen: case Outag:
-        case Oblit: case Numops:
+        case Oblit: case  Oclear: case Oudata:
         case Otrunc: case Oswiden: case Ozwiden:
         case Oint2flt: case Oflt2int: case Oflt2flt:
         case Ofadd: case Ofsub: case Ofmul: case Ofdiv: case Ofneg:
         case Ofeq: case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle:
         case Oueq: case Oune: case Ougt: case Ouge: case Oult: case Oule:
-        case Oudata:
+        case Numops:
             die("Should not see %s in fe", opstr[exprop(n)]);
             break;
     }
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -56,24 +56,25 @@
 O(Oarr,	        1,	OTmisc, NULL)
 
 /* all below this point are backend-only */
-O(Ocjmp,	1,	OTmisc, NULL)        /* conditional jump */
-O(Ojtab,	1,	OTmisc, NULL)		   /* jump table */
-O(Oset,	        1,	OTbin,  "=")         /* store to var */
-O(Osllen,	1,	OTpre,  "SLLEN")       /* size of slice */
-O(Oslbase,	1,	OTpre,  "SLBASE")      /* base of sice */
-O(Outag,	1,	OTpre,  "UTAG")		   /* tag of union */
-O(Oudata,	1,	OTpre,  "UDATA")       /* pointer to contents of union */
-O(Oblit,	1,	OTbin,  "BLIT")        /* blit memory */
+O(Ocjmp,	1,	OTmisc, NULL)           /* conditional jump */
+O(Ojtab,	1,	OTmisc, NULL)		/* jump table */
+O(Oset,	        1,	OTbin,  "=")            /* store to var */
+O(Osllen,	1,	OTpre,  "SLLEN")        /* size of slice */
+O(Oslbase,	1,	OTpre,  "SLBASE")       /* base of sice */
+O(Outag,	1,	OTpre,  "UTAG")	        /* tag of union */
+O(Oudata,	1,	OTpre,  "UDATA")        /* pointer to contents of union */
+O(Oblit,	1,	OTbin,  "BLIT")         /* blit memory */
+O(Oclear,       1,      OTpre,  "CLEAR")        /* zero */
 
 /* integer conversions */
-O(Otrunc,	1,	OTmisc, NULL)       /* truncating cast */
-O(Ozwiden,	1,	OTmisc, NULL)      /* zero-extending widening cast */
-O(Oswiden,	1,	OTmisc, NULL)      /* sign-extending widening cast */
+O(Otrunc,	1,	OTmisc, NULL)   /* truncating cast */
+O(Ozwiden,	1,	OTmisc, NULL)   /* zero-extending widening cast */
+O(Oswiden,	1,	OTmisc, NULL)   /* sign-extending widening cast */
 
 /* float conversions */
-O(Oflt2int,	1,	OTmisc, NULL)     /* float to int conversion */
-O(Oint2flt,	1,	OTmisc, NULL)     /* int to float conversion */
-O(Oflt2flt,	1,	OTmisc, NULL)     /* flt32<->flt64 conversion */
+O(Oflt2int,	1,	OTmisc, NULL)   /* float to int conversion */
+O(Oint2flt,	1,	OTmisc, NULL)   /* int to float conversion */
+O(Oflt2flt,	1,	OTmisc, NULL)   /* flt32<->flt64 conversion */
 
 /* floating arithmetic */
 O(Ofadd,	1,	OTmisc, NULL)