diff options
Diffstat (limited to 'src/cmd/5g/cgen.c')
-rw-r--r-- | src/cmd/5g/cgen.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c index cf701a50a..8072c3ceb 100644 --- a/src/cmd/5g/cgen.c +++ b/src/cmd/5g/cgen.c @@ -1053,11 +1053,32 @@ stkof(Node *n) { Type *t; Iter flist; + int32 off; switch(n->op) { case OINDREG: return n->xoffset; + case ODOT: + t = n->left->type; + if(isptr[t->etype]) + break; + off = stkof(n->left); + if(off == -1000 || off == 1000) + return off; + return off + n->xoffset; + + case OINDEX: + t = n->left->type; + if(!isfixedarray(t)) + break; + off = stkof(n->left); + if(off == -1000 || off == 1000) + return off; + if(isconst(n->right, CTINT)) + return off + t->type->width * mpgetfix(n->right->val.u.xval); + return 1000; + case OCALLMETH: case OCALLINTER: case OCALLFUNC: @@ -1106,6 +1127,17 @@ sgen(Node *n, Node *res, int32 w) osrc = stkof(n); odst = stkof(res); + if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) { + // osrc and odst both on stack, and at least one is in + // an unknown position. Could generate code to test + // for forward/backward copy, but instead just copy + // to a temporary location first. + tempname(&tmp, n->type); + sgen(n, &tmp, w); + sgen(&tmp, res, w); + return; + } + if(osrc % 4 != 0 || odst %4 != 0) fatal("sgen: non word(4) aligned offset src %d or dst %d", osrc, odst); |