aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/5l
diff options
context:
space:
mode:
authorShenghou Ma <minux.ma@gmail.com>2013-01-11 12:24:28 +0800
committerShenghou Ma <minux.ma@gmail.com>2013-01-11 12:24:28 +0800
commitd5d4ee47ed3e76ec707a44095d5da11415b0a8bf (patch)
treeac8e4ffec533a80440bd045b4ae8dc28ad3beea8 /src/cmd/5l
parent60abc6b577895e88f8e029772ff27f9e6917d23b (diff)
downloadgo-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.h3
-rw-r--r--src/cmd/5l/obj.c7
-rw-r--r--src/cmd/5l/pass.c67
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;
+ }
+ }
+}