fatal("sgen UINF");
}
+ if(isslice(n->type))
+ if(isslice(ns->type))
+ if(n->addable)
+ if(ns->addable)
+ if(n->op != OINDREG)
+ if(ns->op != OINDREG)
+ if(n->op != OREGISTER)
+ if(ns->op != OREGISTER) {
+ // slices are done component by component
+ // to keep from confusing optimization
+ nodl = *ns;
+ nodl.xoffset += Array_array;
+ nodl.type = types[TUINT64];
+ nodr = *n;
+ nodr.xoffset += Array_array;
+ nodr.type = types[TUINT64];
+ gmove(&nodr, &nodl);
+
+ nodl = *ns;
+ nodl.xoffset += Array_nel;
+ nodl.type = types[TUINT32];
+ nodr = *n;
+ nodr.xoffset += Array_nel;
+ nodr.type = types[TUINT32];
+ gmove(&nodr, &nodl);
+
+ nodl = *ns;
+ nodl.xoffset += Array_cap;
+ nodl.type = types[TUINT32];
+ nodr = *n;
+ nodr.xoffset += Array_cap;
+ nodr.type = types[TUINT32];
+ gmove(&nodr, &nodl);
+
+ return;
+ }
+
if(w < 0)
fatal("sgen copy %d", w);
if(debug['g'])
dump("\nclearfat", nl);
+ if(isslice(nl->type))
+ if(nl->addable)
+ if(nl->op != OINDREG)
+ if(nl->op != OREGISTER) {
+ // slices are done component by component
+ // to keep from confusing optimization
+
+ n1 = *nl;
+ n1.xoffset += Array_array;
+ n1.type = types[TUINT64];
+ nodconst(&ax, types[TUINT64], 0);
+ gmove(&ax, &n1);
+
+ n1 = *nl;
+ n1.xoffset += Array_nel;
+ n1.type = types[TUINT32];
+ nodconst(&ax, types[TUINT32], 0);
+ gmove(&ax, &n1);
+
+ n1 = *nl;
+ n1.xoffset += Array_cap;
+ n1.type = types[TUINT32];
+ nodconst(&ax, types[TUINT32], 0);
+ gmove(&ax, &n1);
+
+ return;
+ }
+
w = nl->type->width;
c = w % 8; // bytes
q = w / 8; // quads
enum
{
- ODynam = 1<<0,
+ ODynam = 1<<0,
+ OAddable = 1<<1,
};
static Node clean[20];
static int cleani = 0;
+int
+xgen(Node *n, Node *a, int o)
+{
+ regalloc(a, types[tptr], N);
+
+ if(o & ODynam)
+ if(n->addable)
+ if(n->op != OINDREG)
+ if(n->op != OREGISTER)
+ return 1;
+
+ agen(n, a);
+ return 0;
+}
+
void
sudoclean(void)
{
if(l->type->etype != TARRAY)
fatal("not ary");
if(l->type->bound < 0)
- o += ODynam;
+ o |= ODynam;
w = n->type->width;
if(isconst(r, CTINT))
// load the array (reg)
if(l->ullman > r->ullman) {
- regalloc(reg, types[tptr], N);
- agen(l, reg);
+ if(xgen(l, reg, o))
+ o |= OAddable;
}
// load the index (reg1)
// load the array (reg)
if(l->ullman <= r->ullman) {
- regalloc(reg, types[tptr], N);
- agen(l, reg);
+ if(xgen(l, reg, o))
+ o |= OAddable;
}
if(!(o & ODynam) && l->type->width >= unmappedzero && l->op == OIND) {
// cannot rely on page protections to
// catch array ptr == 0, so dereference.
n2 = *reg;
+ n2.xoffset = 0;
n2.op = OINDREG;
n2.type = types[TUINT8];
- n2.xoffset = 0;
gins(ATESTB, nodintconst(0), &n2);
}
n4.op = OXXX;
t = types[TUINT32];
if(o & ODynam) {
- n2 = *reg;
- n2.op = OINDREG;
- n2.type = types[TUINT32];
- n2.xoffset = Array_nel;
- if(is64(r->type)) {
- t = types[TUINT64];
- regalloc(&n4, t, N);
- gmove(&n2, &n4);
- n2 = n4;
+ if(o & OAddable) {
+ n2 = *l;
+ n2.xoffset += Array_nel;
+ n2.type = types[TUINT32];
+ if(is64(r->type)) {
+ t = types[TUINT64];
+ regalloc(&n4, t, N);
+ gmove(&n2, &n4);
+ n2 = n4;
+ }
+ } else {
+ n2 = *reg;
+ n2.xoffset = Array_nel;
+ n2.op = OINDREG;
+ n2.type = types[TUINT32];
+ if(is64(r->type)) {
+ t = types[TUINT64];
+ regalloc(&n4, t, N);
+ gmove(&n2, &n4);
+ n2 = n4;
+ }
}
} else {
if(is64(r->type))
}
if(o & ODynam) {
- n2 = *reg;
- n2.op = OINDREG;
- n2.type = types[tptr];
- n2.xoffset = Array_array;
- gmove(&n2, reg);
+ if(o & OAddable) {
+ n2 = *l;
+ n2.xoffset += Array_array;
+ n2.type = types[TUINT64];
+ gmove(&n2, reg);
+ } else {
+ n2 = *reg;
+ n2.xoffset = Array_array;
+ n2.op = OINDREG;
+ n2.type = types[tptr];
+ gmove(&n2, reg);
+ }
}
- naddr(reg1, a, 1);
- a->offset = 0;
- a->scale = w;
- a->index = a->type;
- a->type = reg->val.u.reg + D_INDIR;
+ if(o & OAddable) {
+ naddr(reg1, a, 1);
+ a->offset = 0;
+ a->scale = w;
+ a->index = a->type;
+ a->type = reg->val.u.reg + D_INDIR;
+ } else {
+ naddr(reg1, a, 1);
+ a->offset = 0;
+ a->scale = w;
+ a->index = a->type;
+ a->type = reg->val.u.reg + D_INDIR;
+ }
goto yes;