mirror of
https://github.com/golang/go
synced 2024-11-18 09:34:53 -07:00
cmd/compile: adjust GOSSAFUNC html dumping to be more ABI-aware
Uses ,ABI instead of <ABI> because of problems with shell escaping and windows file names, however if someone goes to all the trouble of escaping the linker syntax and uses that instead, that works too. Examples: ``` GOSSAFUNC=runtime.exitsyscall go build main.go \# runtime dumped SSA for exitsyscall,0 to ../../src/loopvar/ssa.html dumped SSA for exitsyscall,1 to ../../src/loopvar/ssa.html GOSSADIR=`pwd` GOSSAFUNC=runtime.exitsyscall go build main.go \# runtime dumped SSA for exitsyscall,0 to ../../src/loopvar/runtime.exitsyscall,0.html dumped SSA for exitsyscall,1 to ../../src/loopvar/runtime.exitsyscall,1.html GOSSAFUNC=runtime.exitsyscall,0 go build main.go \# runtime dumped SSA for exitsyscall,0 to ../../src/loopvar/ssa.html GOSSAFUNC=runtime.exitsyscall\<1\> go build main.go \# runtime dumped SSA for exitsyscall,1 to ../../src/loopvar/ssa.html ``` Change-Id: Ia1138b61c797d0de49dbfae702dc306b9650a7f8 Reviewed-on: https://go-review.googlesource.com/c/go/+/532475 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Run-TryBot: David Chase <drchase@google.com>
This commit is contained in:
parent
0074125cef
commit
a903639608
@ -8,6 +8,7 @@ import (
|
|||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
"cmd/compile/internal/ir"
|
"cmd/compile/internal/ir"
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
|
"cmd/internal/obj"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
@ -261,12 +262,13 @@ type ABIConfig struct {
|
|||||||
// Do we need anything more than this?
|
// Do we need anything more than this?
|
||||||
offsetForLocals int64 // e.g., obj.(*Link).Arch.FixedFrameSize -- extra linkage information on some architectures.
|
offsetForLocals int64 // e.g., obj.(*Link).Arch.FixedFrameSize -- extra linkage information on some architectures.
|
||||||
regAmounts RegAmounts
|
regAmounts RegAmounts
|
||||||
|
which obj.ABI
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewABIConfig returns a new ABI configuration for an architecture with
|
// NewABIConfig returns a new ABI configuration for an architecture with
|
||||||
// iRegsCount integer/pointer registers and fRegsCount floating point registers.
|
// iRegsCount integer/pointer registers and fRegsCount floating point registers.
|
||||||
func NewABIConfig(iRegsCount, fRegsCount int, offsetForLocals int64) *ABIConfig {
|
func NewABIConfig(iRegsCount, fRegsCount int, offsetForLocals int64, which uint8) *ABIConfig {
|
||||||
return &ABIConfig{offsetForLocals: offsetForLocals, regAmounts: RegAmounts{iRegsCount, fRegsCount}}
|
return &ABIConfig{offsetForLocals: offsetForLocals, regAmounts: RegAmounts{iRegsCount, fRegsCount}, which: obj.ABI(which)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns config.
|
// Copy returns config.
|
||||||
@ -276,6 +278,11 @@ func (config *ABIConfig) Copy() *ABIConfig {
|
|||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Which returns the ABI number
|
||||||
|
func (config *ABIConfig) Which() obj.ABI {
|
||||||
|
return config.which
|
||||||
|
}
|
||||||
|
|
||||||
// LocalsOffset returns the architecture-dependent offset from SP for args and results.
|
// LocalsOffset returns the architecture-dependent offset from SP for args and results.
|
||||||
// In theory this is only used for debugging; it ought to already be incorporated into
|
// In theory this is only used for debugging; it ought to already be incorporated into
|
||||||
// results from the ABI-related methods
|
// results from the ABI-related methods
|
||||||
|
@ -361,8 +361,8 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize, softfloat boo
|
|||||||
c.floatParamRegs = nil // no FP registers in softfloat mode
|
c.floatParamRegs = nil // no FP registers in softfloat mode
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ABI0 = abi.NewABIConfig(0, 0, ctxt.Arch.FixedFrameSize)
|
c.ABI0 = abi.NewABIConfig(0, 0, ctxt.Arch.FixedFrameSize, 0)
|
||||||
c.ABI1 = abi.NewABIConfig(len(c.intParamRegs), len(c.floatParamRegs), ctxt.Arch.FixedFrameSize)
|
c.ABI1 = abi.NewABIConfig(len(c.intParamRegs), len(c.floatParamRegs), ctxt.Arch.FixedFrameSize, 1)
|
||||||
|
|
||||||
// On Plan 9, floating point operations are not allowed in note handler.
|
// On Plan 9, floating point operations are not allowed in note handler.
|
||||||
if buildcfg.GOOS == "plan9" {
|
if buildcfg.GOOS == "plan9" {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"cmd/compile/internal/ir"
|
"cmd/compile/internal/ir"
|
||||||
"cmd/compile/internal/typecheck"
|
"cmd/compile/internal/typecheck"
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
|
"cmd/internal/obj"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
@ -109,6 +110,21 @@ func (f *Func) NumValues() int {
|
|||||||
return f.vid.num()
|
return f.vid.num()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NameABI returns the function name followed by comma and the ABI number.
|
||||||
|
// This is intended for use with GOSSAFUNC and HTML dumps, and differs from
|
||||||
|
// the linker's "<1>" convention because "<" and ">" require shell quoting
|
||||||
|
// and are not legal file names (for use with GOSSADIR) on Windows.
|
||||||
|
func (f *Func) NameABI() string {
|
||||||
|
return FuncNameABI(f.Name, f.ABISelf.Which())
|
||||||
|
}
|
||||||
|
|
||||||
|
// FuncNameABI returns n followed by a comma and the value of a.
|
||||||
|
// This is a separate function to allow a single point encoding
|
||||||
|
// of the format, which is used in places where there's not a Func yet.
|
||||||
|
func FuncNameABI(n string, a obj.ABI) string {
|
||||||
|
return fmt.Sprintf("%s,%d", n, a)
|
||||||
|
}
|
||||||
|
|
||||||
// newSparseSet returns a sparse set that can store at least up to n integers.
|
// newSparseSet returns a sparse set that can store at least up to n integers.
|
||||||
func (f *Func) newSparseSet(n int) *sparseSet {
|
func (f *Func) newSparseSet(n int) *sparseSet {
|
||||||
return f.Cache.allocSparseSet(n)
|
return f.Cache.allocSparseSet(n)
|
||||||
|
@ -741,7 +741,7 @@ function toggleDarkMode() {
|
|||||||
</head>`)
|
</head>`)
|
||||||
w.WriteString("<body>")
|
w.WriteString("<body>")
|
||||||
w.WriteString("<h1>")
|
w.WriteString("<h1>")
|
||||||
w.WriteString(html.EscapeString(w.Func.Name))
|
w.WriteString(html.EscapeString(w.Func.NameABI()))
|
||||||
w.WriteString("</h1>")
|
w.WriteString("</h1>")
|
||||||
w.WriteString(`
|
w.WriteString(`
|
||||||
<a href="#" onclick="toggle_visibility('help');return false;" id="helplink">help</a>
|
<a href="#" onclick="toggle_visibility('help');return false;" id="helplink">help</a>
|
||||||
@ -784,7 +784,7 @@ func (w *HTMLWriter) Close() {
|
|||||||
io.WriteString(w.w, "</body>")
|
io.WriteString(w.w, "</body>")
|
||||||
io.WriteString(w.w, "</html>")
|
io.WriteString(w.w, "</html>")
|
||||||
w.w.Close()
|
w.w.Close()
|
||||||
fmt.Printf("dumped SSA to %v\n", w.path)
|
fmt.Printf("dumped SSA for %s to %v\n", w.Func.NameABI(), w.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WritePhase writes f in a column headed by title.
|
// WritePhase writes f in a column headed by title.
|
||||||
|
@ -314,12 +314,29 @@ func (s *state) emitOpenDeferInfo() {
|
|||||||
// worker indicates which of the backend workers is doing the processing.
|
// worker indicates which of the backend workers is doing the processing.
|
||||||
func buildssa(fn *ir.Func, worker int) *ssa.Func {
|
func buildssa(fn *ir.Func, worker int) *ssa.Func {
|
||||||
name := ir.FuncName(fn)
|
name := ir.FuncName(fn)
|
||||||
|
|
||||||
|
abiSelf := abiForFunc(fn, ssaConfig.ABI0, ssaConfig.ABI1)
|
||||||
|
|
||||||
printssa := false
|
printssa := false
|
||||||
if ssaDump != "" { // match either a simple name e.g. "(*Reader).Reset", package.name e.g. "compress/gzip.(*Reader).Reset", or subpackage name "gzip.(*Reader).Reset"
|
// match either a simple name e.g. "(*Reader).Reset", package.name e.g. "compress/gzip.(*Reader).Reset", or subpackage name "gzip.(*Reader).Reset"
|
||||||
pkgDotName := base.Ctxt.Pkgpath + "." + name
|
// optionally allows an ABI suffix specification in the GOSSAHASH, e.g. "(*Reader).Reset<0>" etc
|
||||||
printssa = name == ssaDump ||
|
if strings.Contains(ssaDump, name) { // in all the cases the function name is entirely contained within the GOSSAFUNC string.
|
||||||
strings.HasSuffix(pkgDotName, ssaDump) && (pkgDotName == ssaDump || strings.HasSuffix(pkgDotName, "/"+ssaDump))
|
nameOptABI := name
|
||||||
|
if strings.Contains(ssaDump, ",") { // ABI specification
|
||||||
|
nameOptABI = ssa.FuncNameABI(name, abiSelf.Which())
|
||||||
|
} else if strings.HasSuffix(ssaDump, ">") { // if they use the linker syntax instead....
|
||||||
|
l := len(ssaDump)
|
||||||
|
if l >= 3 && ssaDump[l-3] == '<' {
|
||||||
|
nameOptABI = ssa.FuncNameABI(name, abiSelf.Which())
|
||||||
|
ssaDump = ssaDump[:l-3] + "," + ssaDump[l-2:l-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pkgDotName := base.Ctxt.Pkgpath + "." + nameOptABI
|
||||||
|
printssa = nameOptABI == ssaDump || // "(*Reader).Reset"
|
||||||
|
pkgDotName == ssaDump || // "compress/gzip.(*Reader).Reset"
|
||||||
|
strings.HasSuffix(pkgDotName, ssaDump) && strings.HasSuffix(pkgDotName, "/"+ssaDump) // "gzip.(*Reader).Reset"
|
||||||
}
|
}
|
||||||
|
|
||||||
var astBuf *bytes.Buffer
|
var astBuf *bytes.Buffer
|
||||||
if printssa {
|
if printssa {
|
||||||
astBuf = &bytes.Buffer{}
|
astBuf = &bytes.Buffer{}
|
||||||
@ -366,10 +383,10 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func {
|
|||||||
if fn.Pragma&ir.Nosplit != 0 {
|
if fn.Pragma&ir.Nosplit != 0 {
|
||||||
s.f.NoSplit = true
|
s.f.NoSplit = true
|
||||||
}
|
}
|
||||||
s.f.ABI0 = ssaConfig.ABI0.Copy() // Make a copy to avoid racy map operations in type-register-width cache.
|
s.f.ABI0 = ssaConfig.ABI0
|
||||||
s.f.ABI1 = ssaConfig.ABI1.Copy()
|
s.f.ABI1 = ssaConfig.ABI1
|
||||||
s.f.ABIDefault = abiForFunc(nil, s.f.ABI0, s.f.ABI1)
|
s.f.ABIDefault = abiForFunc(nil, ssaConfig.ABI0, ssaConfig.ABI1)
|
||||||
s.f.ABISelf = abiForFunc(fn, s.f.ABI0, s.f.ABI1)
|
s.f.ABISelf = abiSelf
|
||||||
|
|
||||||
s.panics = map[funcLine]*ssa.Block{}
|
s.panics = map[funcLine]*ssa.Block{}
|
||||||
s.softFloat = s.config.SoftFloat
|
s.softFloat = s.config.SoftFloat
|
||||||
@ -381,7 +398,7 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func {
|
|||||||
if printssa {
|
if printssa {
|
||||||
ssaDF := ssaDumpFile
|
ssaDF := ssaDumpFile
|
||||||
if ssaDir != "" {
|
if ssaDir != "" {
|
||||||
ssaDF = filepath.Join(ssaDir, base.Ctxt.Pkgpath+"."+name+".html")
|
ssaDF = filepath.Join(ssaDir, base.Ctxt.Pkgpath+"."+s.f.NameABI()+".html")
|
||||||
ssaD := filepath.Dir(ssaDF)
|
ssaD := filepath.Dir(ssaDF)
|
||||||
os.MkdirAll(ssaD, 0755)
|
os.MkdirAll(ssaD, 0755)
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
// AMD64 registers available:
|
// AMD64 registers available:
|
||||||
// - integer: RAX, RBX, RCX, RDI, RSI, R8, R9, r10, R11
|
// - integer: RAX, RBX, RCX, RDI, RSI, R8, R9, r10, R11
|
||||||
// - floating point: X0 - X14
|
// - floating point: X0 - X14
|
||||||
var configAMD64 = abi.NewABIConfig(9, 15, 0)
|
var configAMD64 = abi.NewABIConfig(9, 15, 0, 1)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
ssagen.Arch.LinkArch = &x86.Linkamd64
|
ssagen.Arch.LinkArch = &x86.Linkamd64
|
||||||
|
Loading…
Reference in New Issue
Block a user