Commit 30fd44cf authored by Ken Thompson's avatar Ken Thompson

fix fat copy of overlapping data

R=r
OCL=14417
CL=14417
parent 2d697d67
...@@ -282,13 +282,6 @@ agen(Node *n, Node *res) ...@@ -282,13 +282,6 @@ agen(Node *n, Node *res)
fatal("agen: unknown op %N", n); fatal("agen: unknown op %N", n);
break; break;
// case ONAME:
// regalloc(&n1, types[tptr], res);
// gins(optoas(OADDR, types[tptr]), n, &n1);
// gmove(&n1, res);
// regfree(&n1);
// break;
case OCALLMETH: case OCALLMETH:
cgen_callmeth(n, 0); cgen_callmeth(n, 0);
cgen_aret(n, res); cgen_aret(n, res);
...@@ -330,8 +323,6 @@ agen(Node *n, Node *res) ...@@ -330,8 +323,6 @@ agen(Node *n, Node *res)
agen_inter(n, res); agen_inter(n, res);
break; break;
// case OINDREG:
case OINDEX: case OINDEX:
w = n->type->width; w = n->type->width;
if(nr->addable) if(nr->addable)
...@@ -585,11 +576,27 @@ ret: ...@@ -585,11 +576,27 @@ ret:
; ;
} }
int32
stkof(Node *n)
{
switch(n->op) {
case OS2I:
return 2*widthptr;
case OI2I:
return 1*widthptr;
case OINDREG:
return n->xoffset;
}
// botch - probably failing to recognize address
// arithmetic on the above. eg INDEX and DOT
return -1;
}
void void
sgen(Node *n, Node *ns, uint32 w) sgen(Node *n, Node *ns, uint32 w)
{ {
Node nodl, nodr; Node nodl, nodr;
int32 c; int32 c, q, odst, osrc;
if(debug['g']) { if(debug['g']) {
dump("\nsgen-res", ns); dump("\nsgen-res", ns);
...@@ -601,6 +608,14 @@ sgen(Node *n, Node *ns, uint32 w) ...@@ -601,6 +608,14 @@ sgen(Node *n, Node *ns, uint32 w)
fatal("sgen UINF"); fatal("sgen UINF");
} }
// offset on the stack
odst = stkof(ns);
osrc = stkof(n);
if(osrc < 0)
odst = odst;
if(odst < 0)
osrc = odst;
nodreg(&nodl, types[tptr], D_DI); nodreg(&nodl, types[tptr], D_DI);
nodreg(&nodr, types[tptr], D_SI); nodreg(&nodr, types[tptr], D_SI);
...@@ -611,20 +626,52 @@ sgen(Node *n, Node *ns, uint32 w) ...@@ -611,20 +626,52 @@ sgen(Node *n, Node *ns, uint32 w)
agen(ns, &nodl); agen(ns, &nodl);
agen(n, &nodr); agen(n, &nodr);
} }
gins(ACLD, N, N); // clear direction flag
c = w / 8; c = w % 8; // bytes
if(c > 0) { q = w / 8; // quads
gconreg(AMOVQ, c, D_CX);
gins(AREP, N, N); // repeat // if we are copying forward on the stack and
gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+ // the src and dst overlap, then reverse direction
} if(odst > osrc && odst-osrc < w) {
// reverse direction
gins(ASTD, N, N); // set direction flag
if(c > 0) {
gconreg(AADDQ, w-1, D_SI);
gconreg(AADDQ, w-1, D_DI);
gconreg(AMOVQ, c, D_CX);
gins(AREP, N, N); // repeat
gins(AMOVSB, N, N); // MOVB *(SI)-,*(DI)-
}
c = w % 8; if(q > 0) {
if(c > 0) { if(c > 0) {
gconreg(AMOVQ, c, D_CX); gconreg(AADDQ, -7, D_SI);
gins(AREP, N, N); // repeat gconreg(AADDQ, -7, D_DI);
gins(AMOVSB, N, N); // MOVB *(SI)+,*(DI)+ } else {
} gconreg(AADDQ, w-8, D_SI);
gconreg(AADDQ, w-8, D_DI);
}
gconreg(AMOVQ, q, D_CX);
gins(AREP, N, N); // repeat
gins(AMOVSQ, N, N); // MOVQ *(SI)-,*(DI)-
}
// for future optimization
// we leave with the flag clear
gins(ACLD, N, N);
} else {
// normal direction
gins(ACLD, N, N); // clear direction flag
if(q > 0) {
gconreg(AMOVQ, q, D_CX);
gins(AREP, N, N); // repeat
gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+
}
if(c > 0) {
gconreg(AMOVQ, c, D_CX);
gins(AREP, N, N); // repeat
gins(AMOVSB, N, N); // MOVB *(SI)+,*(DI)+
}
}
} }
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
%token LLSH LRSH LINC LDEC LSEND LRECV %token LLSH LRSH LINC LDEC LSEND LRECV
%token LIGNORE %token LIGNORE
%type <sym> sym sym1 sym2 key1 key2 laconst lname latype %type <sym> sym sym1 sym2 key laconst lname latype
%type <lint> chandir %type <lint> chandir
%type <node> xdcl xdcl_list_r oxdcl_list %type <node> xdcl xdcl_list_r oxdcl_list
%type <node> common_dcl Acommon_dcl Bcommon_dcl %type <node> common_dcl Acommon_dcl Bcommon_dcl
...@@ -836,18 +836,17 @@ sym: ...@@ -836,18 +836,17 @@ sym:
sym1: sym1:
sym sym
| key1 | key
sym2: sym2:
sym sym
| key1 | key
| key2
/* /*
* keywords that we can * keywords that we can
* use as variable/type names * use as variable/type names
*/ */
key1: key:
LNIL LNIL
| LTRUE | LTRUE
| LFALSE | LFALSE
...@@ -858,38 +857,7 @@ key1: ...@@ -858,38 +857,7 @@ key1:
| LNEW | LNEW
| LBASETYPE | LBASETYPE
| LTYPEOF | LTYPEOF
/*
* keywords that we can
* use as field names
*/
key2:
LPACKAGE
| LIMPORT
| LEXPORT
| LMAP
| LCHAN
| LINTERFACE
| LFUNC
| LSTRUCT
| LFALL
| LRETURN
| LVAR
| LTYPE
| LCONST
| LCONVERT | LCONVERT
| LSELECT
| LFOR
| LIF
| LELSE
| LSWITCH
| LCASE
| LDEFAULT
| LBREAK
| LCONTINUE
| LGO
| LGOTO
| LRANGE
name: name:
lname lname
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment