diff --git a/src/cmd/compile/internal/amd64/galign.go b/src/cmd/compile/internal/amd64/galign.go index 461ef2ada1b..42915340a06 100644 --- a/src/cmd/compile/internal/amd64/galign.go +++ b/src/cmd/compile/internal/amd64/galign.go @@ -25,18 +25,16 @@ func betypeinit() { cmpptr = x86.ACMPL } - if gc.Ctxt.Flag_dynlink { - gc.Thearch.ReservedRegs = append(gc.Thearch.ReservedRegs, x86.REG_R15) + if gc.Ctxt.Flag_dynlink || obj.Getgoos() == "nacl" { + resvd = append(resvd, x86.REG_R15) } + if gc.Ctxt.Framepointer_enabled || obj.Getgoos() == "nacl" { + resvd = append(resvd, x86.REG_BP) + } + gc.Thearch.ReservedRegs = resvd } func Main() { - if obj.Getgoos() == "nacl" { - resvd = append(resvd, x86.REG_BP, x86.REG_R15) - } else if obj.Framepointer_enabled != 0 { - resvd = append(resvd, x86.REG_BP) - } - gc.Thearch.LinkArch = &x86.Linkamd64 if obj.Getgoarch() == "amd64p32" { gc.Thearch.LinkArch = &x86.Linkamd64p32 @@ -51,7 +49,6 @@ func Main() { gc.Thearch.FREGMIN = x86.REG_X0 gc.Thearch.FREGMAX = x86.REG_X15 gc.Thearch.MAXWIDTH = 1 << 50 - gc.Thearch.ReservedRegs = resvd gc.Thearch.AddIndex = addindex gc.Thearch.Betypeinit = betypeinit diff --git a/src/cmd/compile/internal/amd64/reg.go b/src/cmd/compile/internal/amd64/reg.go index 764f5c3a9e6..77720c855f1 100644 --- a/src/cmd/compile/internal/amd64/reg.go +++ b/src/cmd/compile/internal/amd64/reg.go @@ -32,7 +32,6 @@ package amd64 import ( "cmd/compile/internal/gc" - "cmd/internal/obj" "cmd/internal/obj/x86" ) @@ -121,7 +120,7 @@ func BtoR(b uint64) int { b &= 0xffff if gc.Nacl { b &^= (1<<(x86.REG_BP-x86.REG_AX) | 1<<(x86.REG_R15-x86.REG_AX)) - } else if obj.Framepointer_enabled != 0 { + } else if gc.Ctxt.Framepointer_enabled { // BP is part of the calling convention if framepointer_enabled. b &^= (1 << (x86.REG_BP - x86.REG_AX)) } diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index bd405225746..1eecd49c40c 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -106,7 +106,6 @@ package ssa import ( - "cmd/internal/obj" "fmt" "unsafe" ) @@ -456,7 +455,7 @@ func (s *regAllocState) init(f *Func) { s.allocatable = regMask(1)< 2 && name[:2] == "no" { + v = 0 + name = name[2:] + } for i := 0; i < len(exper); i++ { - if exper[i].name == s { + if exper[i].name == name { if exper[i].val != nil { - *exper[i].val = 1 + *exper[i].val = v } return } @@ -44,6 +51,7 @@ func addexp(s string) { } func init() { + framepointer_enabled = 1 // default for _, f := range strings.Split(goexperiment, ",") { if f != "" { addexp(f) @@ -51,6 +59,10 @@ func init() { } } +func Framepointer_enabled(goos, goarch string) bool { + return framepointer_enabled != 0 && goarch == "amd64" && goos != "nacl" +} + func Nopout(p *Prog) { p.As = ANOP p.Scond = 0 diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index eaf702533a1..b6861f4c1e5 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -664,6 +664,8 @@ type Link struct { Etextp *LSym Errors int + Framepointer_enabled bool + // state for writing objects Text []*LSym Data []*LSym diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go index 6f3542b3d4f..e974ca8c8af 100644 --- a/src/cmd/internal/obj/sym.go +++ b/src/cmd/internal/obj/sym.go @@ -106,6 +106,7 @@ func Linknew(arch *LinkArch) *Link { } ctxt.Flag_optimize = true + ctxt.Framepointer_enabled = Framepointer_enabled(Getgoos(), arch.Name) return ctxt } diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index 9230c9fdacb..414a4d34a55 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -3765,7 +3765,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ctxt.Diag("directly calling duff when dynamically linking Go") } - if obj.Framepointer_enabled != 0 && yt.zcase == Zcallduff && p.Mode == 64 { + if ctxt.Framepointer_enabled && yt.zcase == Zcallduff && p.Mode == 64 { // Maintain BP around call, since duffcopy/duffzero can't do it // (the call jumps into the middle of the function). // This makes it possible to see call sites for duffcopy/duffzero in @@ -3784,7 +3784,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { r.Siz = 4 ctxt.AsmBuf.PutInt32(0) - if obj.Framepointer_enabled != 0 && yt.zcase == Zcallduff && p.Mode == 64 { + if ctxt.Framepointer_enabled && yt.zcase == Zcallduff && p.Mode == 64 { // Pop BP pushed above. // MOVQ 0(BP), BP ctxt.AsmBuf.Put(bpduff2) diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index 0f1f28d36d6..5dad0bbb982 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -610,7 +610,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { } var bpsize int - if p.Mode == 64 && obj.Framepointer_enabled != 0 && autoffset > 0 && p.From3.Offset&obj.NOFRAME == 0 { + 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. diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index ca86e72d832..01747c54301 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -1558,7 +1558,7 @@ func writelines(prev *LSym) *LSym { if !haslinkregister() { offs -= int64(SysArch.PtrSize) } - if obj.Framepointer_enabled != 0 { + if obj.Framepointer_enabled(obj.Getgoos(), obj.Getgoarch()) { // The frame pointer is saved // between the CFA and the // autos. diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index da00de8547c..bab71fb3114 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -639,11 +639,17 @@ func loadlib() { // recording the value of GOARM. if SysArch.Family == sys.ARM { s := Linklookup(Ctxt, "runtime.goarm", 0) - s.Type = obj.SRODATA s.Size = 0 Adduint8(Ctxt, s, uint8(Ctxt.Goarm)) } + + if obj.Framepointer_enabled(obj.Getgoos(), obj.Getgoarch()) { + s := Linklookup(Ctxt, "runtime.framepointer_enabled", 0) + s.Type = obj.SRODATA + s.Size = 0 + Adduint8(Ctxt, s, 1) + } } else { // If OTOH the module does not contain the runtime package, // create a local symbol for the moduledata. diff --git a/src/runtime/proc.go b/src/runtime/proc.go index ee895471046..727c991a577 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -434,9 +434,6 @@ func schedinit() { sched.maxmcount = 10000 - // Cache the framepointer experiment. This affects stack unwinding. - framepointer_enabled = haveexperiment("framepointer") - tracebackinit() moduledataverify() stackinit() @@ -4163,6 +4160,9 @@ func setMaxThreads(in int) (out int) { } func haveexperiment(name string) bool { + if name == "framepointer" { + return framepointer_enabled // set by linker + } x := sys.Goexperiment for x != "" { xname := "" @@ -4175,6 +4175,9 @@ func haveexperiment(name string) bool { if xname == name { return true } + if len(xname) > 2 && xname[:2] == "no" && xname[2:] == name { + return false + } } return false } diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 71da504f1c0..6119e75203c 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -725,7 +725,8 @@ var ( support_avx bool support_avx2 bool - goarm uint8 // set by cmd/link on arm systems + goarm uint8 // set by cmd/link on arm systems + framepointer_enabled bool // set by cmd/link ) // Set by the linker so the runtime can determine the buildmode. diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 33d29f19a8c..8e344cdf035 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -155,9 +155,6 @@ var stackLarge struct { free [_MHeapMap_Bits]mSpanList // free lists by log_2(s.npages) } -// Cached value of haveexperiment("framepointer") -var framepointer_enabled bool - func stackinit() { if _StackCacheSize&_PageMask != 0 { throw("cache size must be a multiple of page size")