From 30fd44cf9d0fcfc07c08d21d01d0c8b9a431d2cc Mon Sep 17 00:00:00 2001 From: Ken Thompson Date: Thu, 21 Aug 2008 20:49:04 -0700 Subject: [PATCH] fix fat copy of overlapping data R=r OCL=14417 CL=14417 --- src/cmd/6g/cgen.c | 95 +++++++++++++++++++++++++++++++++++------------ src/cmd/gc/go.y | 40 ++------------------ 2 files changed, 75 insertions(+), 60 deletions(-) diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c index bbd904d4993..b4ae1dfb928 100644 --- a/src/cmd/6g/cgen.c +++ b/src/cmd/6g/cgen.c @@ -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; - if(c > 0) { - gconreg(AMOVQ, c, D_CX); - gins(AREP, N, N); // repeat - gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+ + 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)+ + } + + if(c > 0) { + gconreg(AMOVQ, c, D_CX); + gins(AREP, N, N); // repeat + gins(AMOVSB, N, N); // MOVB *(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)+ - } - } diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index 08c36642250..8f1b71a16d0 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -28,7 +28,7 @@ %token LLSH LRSH LINC LDEC LSEND LRECV %token LIGNORE -%type sym sym1 sym2 key1 key2 laconst lname latype +%type sym sym1 sym2 key laconst lname latype %type chandir %type xdcl xdcl_list_r oxdcl_list %type 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