diff options
Diffstat (limited to 'src/cmd/internal/obj/x86/obj6.go')
-rw-r--r-- | src/cmd/internal/obj/x86/obj6.go | 24 |
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) |