diff options
Diffstat (limited to 'src/cmd/5g/cgen.c')
-rw-r--r-- | src/cmd/5g/cgen.c | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c index 2d260e72d..9011b2022 100644 --- a/src/cmd/5g/cgen.c +++ b/src/cmd/5g/cgen.c @@ -254,6 +254,7 @@ cgen(Node *n, Node *res) case OOR: case OXOR: case OADD: + case OADDPTR: case OMUL: a = optoas(n->op, nl->type); goto sbop; @@ -604,6 +605,7 @@ agen(Node *n, Node *res) // The generated code is just going to panic, so it need not // be terribly efficient. See issue 3670. tempname(&n1, n->type); + gvardef(&n1); clearfat(&n1); regalloc(&n2, types[tptr], res); gins(AMOVW, &n1, &n2); @@ -1410,10 +1412,11 @@ stkof(Node *n) void sgen(Node *n, Node *res, int64 w) { - Node dst, src, tmp, nend; + Node dst, src, tmp, nend, r0, r1, r2, *f; int32 c, odst, osrc; int dir, align, op; Prog *p, *ploop; + NodeList *l; if(debug['g']) { print("\nsgen w=%lld\n", w); @@ -1439,6 +1442,13 @@ sgen(Node *n, Node *res, int64 w) return; } + // If copying .args, that's all the results, so record definition sites + // for them for the liveness analysis. + if(res->op == ONAME && strcmp(res->sym->name, ".args") == 0) + for(l = curfn->dcl; l != nil; l = l->next) + if(l->n->class == PPARAMOUT) + gvardef(l->n); + // Avoid taking the address for simple enough types. if(componentgen(n, res)) return; @@ -1480,18 +1490,59 @@ sgen(Node *n, Node *res, int64 w) } if(osrc%align != 0 || odst%align != 0) fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align); + // if we are copying forward on the stack and // the src and dst overlap, then reverse direction dir = align; if(osrc < odst && odst < osrc+w) dir = -dir; + if(op == AMOVW && dir > 0 && c >= 4 && c <= 128) { + r0.op = OREGISTER; + r0.val.u.reg = REGALLOC_R0; + r1.op = OREGISTER; + r1.val.u.reg = REGALLOC_R0 + 1; + r2.op = OREGISTER; + r2.val.u.reg = REGALLOC_R0 + 2; + + regalloc(&src, types[tptr], &r1); + regalloc(&dst, types[tptr], &r2); + if(n->ullman >= res->ullman) { + // eval n first + agen(n, &src); + if(res->op == ONAME) + gvardef(res); + agen(res, &dst); + } else { + // eval res first + if(res->op == ONAME) + gvardef(res); + agen(res, &dst); + agen(n, &src); + } + regalloc(&tmp, types[tptr], &r0); + f = sysfunc("duffcopy"); + p = gins(ADUFFCOPY, N, f); + afunclit(&p->to, f); + // 8 and 128 = magic constants: see ../../pkg/runtime/asm_arm.s + p->to.offset = 8*(128-c); + + regfree(&tmp); + regfree(&src); + regfree(&dst); + return; + } + if(n->ullman >= res->ullman) { agenr(n, &dst, res); // temporarily use dst regalloc(&src, types[tptr], N); gins(AMOVW, &dst, &src); + if(res->op == ONAME) + gvardef(res); agen(res, &dst); } else { + if(res->op == ONAME) + gvardef(res); agenr(res, &dst, res); agenr(n, &src, N); } @@ -1624,8 +1675,17 @@ componentgen(Node *nr, Node *nl) freer = 1; } + // nl and nr are 'cadable' which basically means they are names (variables) now. + // If they are the same variable, don't generate any code, because the + // VARDEF we generate will mark the old value as dead incorrectly. + // (And also the assignments are useless.) + if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr) + goto yes; + switch(nl->type->etype) { case TARRAY: + if(nl->op == ONAME) + gvardef(nl); nodl.xoffset += Array_array; nodl.type = ptrto(nl->type->type); @@ -1656,6 +1716,8 @@ componentgen(Node *nr, Node *nl) goto yes; case TSTRING: + if(nl->op == ONAME) + gvardef(nl); nodl.xoffset += Array_array; nodl.type = ptrto(types[TUINT8]); @@ -1677,6 +1739,8 @@ componentgen(Node *nr, Node *nl) goto yes; case TINTER: + if(nl->op == ONAME) + gvardef(nl); nodl.xoffset += Array_array; nodl.type = ptrto(types[TUINT8]); |