aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj/x86/obj6.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/obj/x86/obj6.go')
-rw-r--r--src/cmd/internal/obj/x86/obj6.go24
1 files changed, 20 insertions, 4 deletions
diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go
index 102d8c3c4f..eb6f867ca7 100644
--- a/src/cmd/internal/obj/x86/obj6.go
+++ b/src/cmd/internal/obj/x86/obj6.go
@@ -632,11 +632,27 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
autoffset = 0
}
+ hasCall := false
+ for q := p; q != nil; q = q.Link {
+ if q.As == obj.ACALL || q.As == obj.ADUFFCOPY || q.As == obj.ADUFFZERO {
+ hasCall = true
+ break
+ }
+ }
+
var bpsize int
- if p.Mode == 64 && ctxt.Framepointer_enabled && autoffset > 0 && p.From3.Offset&obj.NOFRAME == 0 {
- // Make room for to save a base pointer. If autoffset == 0,
- // this might do something special like a tail jump to
- // another function, so in that case we omit this.
+ if p.Mode == 64 && ctxt.Framepointer_enabled &&
+ p.From3.Offset&obj.NOFRAME == 0 && // (1) below
+ !(autoffset == 0 && p.From3.Offset&obj.NOSPLIT != 0) && // (2) below
+ !(autoffset == 0 && !hasCall) { // (3) below
+ // Make room to save a base pointer.
+ // There are 2 cases we must avoid:
+ // 1) If noframe is set (which we do for functions which tail call).
+ // 2) Scary runtime internals which would be all messed up by frame pointers.
+ // We detect these using a heuristic: frameless nosplit functions.
+ // TODO: Maybe someday we label them all with NOFRAME and get rid of this heuristic.
+ // For performance, we also want to avoid:
+ // 3) Frameless leaf functions
bpsize = ctxt.Arch.PtrSize
autoffset += int32(bpsize)
p.To.Offset += int64(bpsize)