diff options
author | Michael Stapelberg <stapelberg@debian.org> | 2013-03-04 21:27:36 +0100 |
---|---|---|
committer | Michael Stapelberg <michael@stapelberg.de> | 2013-03-04 21:27:36 +0100 |
commit | 04b08da9af0c450d645ab7389d1467308cfc2db8 (patch) | |
tree | db247935fa4f2f94408edc3acd5d0d4f997aa0d8 /src/cmd/6l/pass.c | |
parent | 917c5fb8ec48e22459d77e3849e6d388f93d3260 (diff) | |
download | golang-04b08da9af0c450d645ab7389d1467308cfc2db8.tar.gz |
Imported Upstream version 1.1~hg20130304upstream/1.1_hg20130304
Diffstat (limited to 'src/cmd/6l/pass.c')
-rw-r--r-- | src/cmd/6l/pass.c | 91 |
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; |