diff options
| author | Shenghou Ma <minux.ma@gmail.com> | 2013-01-11 12:24:28 +0800 |
|---|---|---|
| committer | Shenghou Ma <minux.ma@gmail.com> | 2013-01-11 12:24:28 +0800 |
| commit | d5d4ee47ed3e76ec707a44095d5da11415b0a8bf (patch) | |
| tree | ac8e4ffec533a80440bd045b4ae8dc28ad3beea8 /src/cmd/5l | |
| parent | 60abc6b577895e88f8e029772ff27f9e6917d23b (diff) | |
| download | go-d5d4ee47ed3e76ec707a44095d5da11415b0a8bf.tar.xz | |
cmd/5l: support -Z (zero stack frame at function entry)
also added appropriate docs to cmd/ld/doc.go
(largely copied from Russ's CL 6938073).
R=rsc
CC=golang-dev
https://golang.org/cl/7004049
Diffstat (limited to 'src/cmd/5l')
| -rw-r--r-- | src/cmd/5l/l.h | 3 | ||||
| -rw-r--r-- | src/cmd/5l/obj.c | 7 | ||||
| -rw-r--r-- | src/cmd/5l/pass.c | 67 |
3 files changed, 75 insertions, 2 deletions
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h index 5b05932fdd..0ceafdd112 100644 --- a/src/cmd/5l/l.h +++ b/src/cmd/5l/l.h @@ -420,8 +420,9 @@ int32 immaddr(int32); int32 opbra(int, int); int brextra(Prog*); int isbranch(Prog*); -void fnptrs(void); +void fnptrs(void); void doelf(void); +void dozerostk(void); // used by -Z vlong addaddr(Sym *s, Sym *t); vlong addsize(Sym *s, Sym *t); diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c index a99f67d949..6a95a5e572 100644 --- a/src/cmd/5l/obj.c +++ b/src/cmd/5l/obj.c @@ -255,7 +255,12 @@ main(int argc, char *argv[]) doelf(); follow(); softfloat(); - noops(); + // 5l -Z means zero the stack frame on entry. + // This slows down function calls but can help avoid + // false positives in garbage collection. + if(debug['Z']) + dozerostk(); + noops(); // generate stack split prolog, handle div/mod, etc. dostkcheck(); span(); addexport(); diff --git a/src/cmd/5l/pass.c b/src/cmd/5l/pass.c index 50593ced97..c22b860858 100644 --- a/src/cmd/5l/pass.c +++ b/src/cmd/5l/pass.c @@ -333,3 +333,70 @@ rnd(int32 v, int32 r) v -= c; return v; } + +void +dozerostk(void) +{ + Prog *p, *pl; + int32 autoffset; + + for(cursym = textp; cursym != nil; cursym = cursym->next) { + if(cursym->text == nil || cursym->text->link == nil) + continue; + p = cursym->text; + autoffset = p->to.offset; + if(autoffset < 0) + autoffset = 0; + if(autoffset && !(p->reg&NOSPLIT)) { + // MOVW $4(R13), R1 + p = appendp(p); + p->as = AMOVW; + p->from.type = D_CONST; + p->from.reg = 13; + p->from.offset = 4; + p->to.type = D_REG; + p->to.reg = 1; + + // MOVW $n(R13), R2 + p = appendp(p); + p->as = AMOVW; + p->from.type = D_CONST; + p->from.reg = 13; + p->from.offset = 4 + autoffset; + p->to.type = D_REG; + p->to.reg = 2; + + // MOVW $0, R3 + p = appendp(p); + p->as = AMOVW; + p->from.type = D_CONST; + p->from.offset = 0; + p->to.type = D_REG; + p->to.reg = 3; + + // L: + // MOVW.P R3, 0(R1) +4 + // CMP R1, R2 + // BNE L + p = pl = appendp(p); + p->as = AMOVW; + p->from.type = D_REG; + p->from.reg = 3; + p->to.type = D_OREG; + p->to.reg = 1; + p->to.offset = 4; + p->scond |= C_PBIT; + + p = appendp(p); + p->as = ACMP; + p->from.type = D_REG; + p->from.reg = 1; + p->reg = 2; + + p = appendp(p); + p->as = ABNE; + p->to.type = D_BRANCH; + p->cond = pl; + } + } +} |
