summaryrefslogtreecommitdiff
path: root/6/isel.c
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-01-25 14:35:28 -0800
committerOri Bernstein <ori@eigenstate.org>2015-01-25 14:35:28 -0800
commit063b2a4e134589a8a1d635708eb0eb39d5a76bfb (patch)
tree75bb6fc8c0393f624fe76c5edd5377fc867378ba /6/isel.c
parentbd0724eccecfb0ea9651cf8d5b5f8d6bfaca6e4c (diff)
downloadmc-063b2a4e134589a8a1d635708eb0eb39d5a76bfb.tar.gz
Clear structs.
When creating stack structs, clear them. TODO: only clear uninitialized values.
Diffstat (limited to '6/isel.c')
-rw-r--r--6/isel.c62
1 files changed, 50 insertions, 12 deletions
diff --git a/6/isel.c b/6/isel.c
index f2da224..ec29ce4 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -345,29 +345,31 @@ static Loc *memloc(Isel *s, Node *e, Mode m)
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 blit(Isel *s, Loc *to, Loc *from, size_t dstoff, size_t srcoff, size
}
+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;
@@ -700,6 +733,11 @@ Loc *selexpr(Isel *s, Node *n)
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 */
case Otrunc:
a = selexpr(s, args[0]);