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(w == 16)
+ if(componentgen(n, ns))
+ return;
+
// offset on the stack
osrc = stkof(n);
odst = stkof(ns);
restx(&nodr, &oldr);
restx(&cx, &oldcx);
}
+
+/*
+ * copy a structure component by component
+ * return 1 if can do, 0 if cant.
+ * nr is N for copy zero
+ */
+int
+componentgen(Node *nr, Node *nl)
+{
+ Node nodl, nodr;
+ int free;
+
+ free = 0;
+ if(!nl->addable || nl->op != ONAME)
+ goto no;
+
+ nodl = *nl;
+ if(nr != N) {
+ if(!nr->addable || nr->op != ONAME)
+ goto no;
+ nodr = *nr;
+ if(nr->op != ONAME && nr->op != OINDREG) {
+ igen(nr, &nodr, N);
+ free = 1;
+ }
+ }
+
+ switch(nl->type->etype) {
+ case TARRAY:
+ if(!isslice(nl->type))
+ goto no;
+
+ nodl.xoffset += Array_array;
+ nodl.type = ptrto(nl->type->type);
+
+ if(nr != N) {
+ nodr.xoffset += Array_array;
+ nodr.type = nodl.type;
+ } else
+ nodconst(&nodr, nodl.type, 0);
+ gmove(&nodr, &nodl);
+
+ nodl.xoffset += Array_nel-Array_array;
+ nodl.type = types[TUINT32];
+
+ if(nr != N) {
+ nodr.xoffset += Array_nel-Array_array;
+ nodr.type = nodl.type;
+ } else
+ nodconst(&nodr, nodl.type, 0);
+ gmove(&nodr, &nodl);
+
+ nodl.xoffset += Array_cap-Array_nel;
+ nodl.type = types[TUINT32];
+
+ if(nr != N) {
+ nodr.xoffset += Array_cap-Array_nel;
+ nodr.type = nodl.type;
+ } else
+ nodconst(&nodr, nodl.type, 0);
+ gmove(&nodr, &nodl);
+
+ goto yes;
+
+ case TSTRING:
+
+ nodl.xoffset += Array_array;
+ nodl.type = ptrto(types[TUINT8]);
+
+ if(nr != N) {
+ nodr.xoffset += Array_array;
+ nodr.type = nodl.type;
+ } else
+ nodconst(&nodr, nodl.type, 0);
+ gmove(&nodr, &nodl);
+
+ nodl.xoffset += Array_nel-Array_array;
+ nodl.type = types[TUINT32];
+
+ if(nr != N) {
+ nodr.xoffset += Array_nel-Array_array;
+ nodr.type = nodl.type;
+ } else
+ nodconst(&nodr, nodl.type, 0);
+ gmove(&nodr, &nodl);
+
+ goto yes;
+
+ case TINTER:
+
+ nodl.xoffset += Array_array;
+ nodl.type = ptrto(types[TUINT8]);
+
+ if(nr != N) {
+ nodr.xoffset += Array_array;
+ nodr.type = nodl.type;
+ } else
+ nodconst(&nodr, nodl.type, 0);
+ gmove(&nodr, &nodl);
+
+ nodl.xoffset += Array_nel-Array_array;
+ nodl.type = ptrto(types[TUINT8]);
+
+ if(nr != N) {
+ nodr.xoffset += Array_nel-Array_array;
+ nodr.type = nodl.type;
+ } else
+ nodconst(&nodr, nodl.type, 0);
+ gmove(&nodr, &nodl);
+
+ goto yes;
+
+ case TSTRUCT:
+ goto no;
+ }
+
+no:
+ if(free)
+ regfree(&nodr);
+ return 0;
+
+yes:
+ if(free)
+ regfree(&nodr);
+ return 1;
+}
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;
+ if(w == 16)
+ if(componentgen(N, nl))
+ return;
+
c = w % 8; // bytes
q = w / 8; // quads