summaryrefslogtreecommitdiff
path: root/src/cmd/6l/pass.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/6l/pass.c')
-rw-r--r--src/cmd/6l/pass.c91
1 files changed, 77 insertions, 14 deletions
diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c
index c9b477627..0054b329f 100644
--- a/src/cmd/6l/pass.c
+++ b/src/cmd/6l/pass.c
@@ -79,6 +79,7 @@ nofollow(int a)
case ARETFL:
case ARETFQ:
case ARETFW:
+ case AUNDEF:
return 1;
}
return 0;
@@ -192,20 +193,34 @@ loop:
* recurse to follow one path.
* continue loop on the other.
*/
- q = brchain(p->link);
- if(q != P && q->mark)
- if(a != ALOOP) {
- p->as = relinv(a);
- p->link = p->pcond;
+ if((q = brchain(p->pcond)) != P)
p->pcond = q;
+ if((q = brchain(p->link)) != P)
+ p->link = q;
+ if(p->from.type == D_CONST) {
+ if(p->from.offset == 1) {
+ /*
+ * expect conditional jump to be taken.
+ * rewrite so that's the fall-through case.
+ */
+ p->as = relinv(a);
+ q = p->link;
+ p->link = p->pcond;
+ p->pcond = q;
+ }
+ } else {
+ q = p->link;
+ if(q->mark)
+ if(a != ALOOP) {
+ p->as = relinv(a);
+ p->link = p->pcond;
+ p->pcond = q;
+ }
}
xfol(p->link, last);
- q = brchain(p->pcond);
- if(q->mark) {
- p->pcond = q;
+ if(p->pcond->mark)
return;
- }
- p = q;
+ p = p->pcond;
goto loop;
}
p = p->link;
@@ -295,7 +310,8 @@ patch(void)
}
}
if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd
- || HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd) {
+ || HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd
+ || HEADTYPE == Hplan9x64) {
// ELF uses FS instead of GS.
if(p->from.type == D_INDIR+D_GS)
p->from.type = D_INDIR+D_FS;
@@ -307,7 +323,7 @@ patch(void)
if(s) {
if(debug['c'])
Bprint(&bso, "%s calls %s\n", TNAME, s->name);
- if((s->type&~SSUB) != STEXT) {
+ if((s->type&SMASK) != STEXT) {
/* diag prints TNAME first */
diag("undefined: %s", s->name);
s->type = STEXT;
@@ -405,7 +421,7 @@ dostkoff(void)
for(cursym = textp; cursym != nil; cursym = cursym->next) {
if(cursym->text == nil || cursym->text->link == nil)
- continue;
+ continue;
p = cursym->text;
parsetextconst(p->to.offset);
@@ -413,6 +429,14 @@ dostkoff(void)
if(autoffset < 0)
autoffset = 0;
+ if(autoffset < StackSmall && !(p->from.scale & NOSPLIT)) {
+ for(q = p; q != P; q = q->link)
+ if(q->as == ACALL)
+ goto noleaf;
+ p->from.scale |= NOSPLIT;
+ noleaf:;
+ }
+
q = P;
if((p->from.scale & NOSPLIT) && autoffset >= StackSmall)
diag("nosplit func likely to overflow stack");
@@ -421,7 +445,8 @@ dostkoff(void)
p = appendp(p); // load g into CX
p->as = AMOVQ;
if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd
- || HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd) // ELF uses FS
+ || HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd
+ || HEADTYPE == Hplan9x64) // ELF uses FS
p->from.type = D_INDIR+D_FS;
else
p->from.type = D_INDIR+D_GS;
@@ -579,6 +604,16 @@ dostkoff(void)
p->spadj = autoffset;
if(q != P)
q->pcond = p;
+ } else {
+ // zero-byte stack adjustment.
+ // Insert a fake non-zero adjustment so that stkcheck can
+ // recognize the end of the stack-splitting prolog.
+ p = appendp(p);
+ p->as = ANOP;
+ p->spadj = -PtrSize;
+ p = appendp(p);
+ p->as = ANOP;
+ p->spadj = PtrSize;
}
deltasp = autoffset;
@@ -618,6 +653,34 @@ dostkoff(void)
q1->pcond = p;
}
+ if(debug['Z'] && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
+ // 6l -Z means zero the stack frame on entry.
+ // This slows down function calls but can help avoid
+ // false positives in garbage collection.
+ p = appendp(p);
+ p->as = AMOVQ;
+ p->from.type = D_SP;
+ p->to.type = D_DI;
+
+ p = appendp(p);
+ p->as = AMOVQ;
+ p->from.type = D_CONST;
+ p->from.offset = autoffset/8;
+ p->to.type = D_CX;
+
+ p = appendp(p);
+ p->as = AMOVQ;
+ p->from.type = D_CONST;
+ p->from.offset = 0;
+ p->to.type = D_AX;
+
+ p = appendp(p);
+ p->as = AREP;
+
+ p = appendp(p);
+ p->as = ASTOSQ;
+ }
+
for(; p != P; p = p->link) {
pcsize = p->mode/8;
a = p->from.type;