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)
fatal("agen: unknown op %N", n);
break;
// case ONAME:
// regalloc(&n1, types[tptr], res);
// gins(optoas(OADDR, types[tptr]), n, &n1);
// gmove(&n1, res);
// regfree(&n1);
// break;
case OCALLMETH:
cgen_callmeth(n, 0);
cgen_aret(n, res);
......@@ -330,8 +323,6 @@ agen(Node *n, Node *res)
agen_inter(n, res);
break;
// case OINDREG:
case OINDEX:
w = n->type->width;
if(nr->addable)
......@@ -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
sgen(Node *n, Node *ns, uint32 w)
{
Node nodl, nodr;
int32 c;
int32 c, q, odst, osrc;
if(debug['g']) {
dump("\nsgen-res", ns);
......@@ -601,6 +608,14 @@ sgen(Node *n, Node *ns, uint32 w)
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(&nodr, types[tptr], D_SI);
......@@ -611,20 +626,52 @@ sgen(Node *n, Node *ns, uint32 w)
agen(ns, &nodl);
agen(n, &nodr);
}
gins(ACLD, N, N); // clear direction flag
c = w / 8;
c = w % 8; // bytes
q = w / 8; // quads
// if we are copying forward on the stack and
// 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)-
}
if(q > 0) {
if(c > 0) {
gconreg(AADDQ, -7, D_SI);
gconreg(AADDQ, -7, D_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)+
}
c = w % 8;
if(c > 0) {
gconreg(AMOVQ, c, D_CX);
gins(AREP, N, N); // repeat
gins(AMOVSB, N, N); // MOVB *(SI)+,*(DI)+
}
}
}
......@@ -28,7 +28,7 @@
%token LLSH LRSH LINC LDEC LSEND LRECV
%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 <node> xdcl xdcl_list_r oxdcl_list
%type <node> common_dcl Acommon_dcl Bcommon_dcl
......@@ -836,18 +836,17 @@ sym:
sym1:
sym
| key1
| key
sym2:
sym
| key1
| key2
| key
/*
* keywords that we can
* use as variable/type names
*/
key1:
key:
LNIL
| LTRUE
| LFALSE
......@@ -858,38 +857,7 @@ key1:
| LNEW
| LBASETYPE
| LTYPEOF
/*
* keywords that we can
* use as field names
*/
key2:
LPACKAGE
| LIMPORT
| LEXPORT
| LMAP
| LCHAN
| LINTERFACE
| LFUNC
| LSTRUCT
| LFALL
| LRETURN
| LVAR
| LTYPE
| LCONST
| LCONVERT
| LSELECT
| LFOR
| LIF
| LELSE
| LSWITCH
| LCASE
| LDEFAULT
| LBREAK
| LCONTINUE
| LGO
| LGOTO
| LRANGE
name:
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