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)