]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: adjust GOSSAFUNC html dumping to be more ABI-aware
authorDavid Chase <drchase@google.com>
Tue, 3 Oct 2023 16:14:53 +0000 (12:14 -0400)
committerDavid Chase <drchase@google.com>
Wed, 4 Oct 2023 15:11:40 +0000 (15:11 +0000)
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>

src/cmd/compile/internal/abi/abiutils.go
src/cmd/compile/internal/ssa/config.go
src/cmd/compile/internal/ssa/func.go
src/cmd/compile/internal/ssa/html.go
src/cmd/compile/internal/ssagen/ssa.go
src/cmd/compile/internal/test/abiutils_test.go

index 04b17fbcc55de2338ec92f1c52eec9afce903850..607d462493e9f0b17d3f365babe2a62141f05046 100644 (file)
@@ -8,6 +8,7 @@ import (
        "cmd/compile/internal/base"
        "cmd/compile/internal/ir"
        "cmd/compile/internal/types"
+       "cmd/internal/obj"
        "cmd/internal/src"
        "fmt"
        "math"
@@ -261,12 +262,13 @@ type ABIConfig struct {
        // Do we need anything more than this?
        offsetForLocals int64 // e.g., obj.(*Link).Arch.FixedFrameSize -- extra linkage information on some architectures.
        regAmounts      RegAmounts
+       which           obj.ABI
 }
 
 // NewABIConfig returns a new ABI configuration for an architecture with
 // iRegsCount integer/pointer registers and fRegsCount floating point registers.
-func NewABIConfig(iRegsCount, fRegsCount int, offsetForLocals int64) *ABIConfig {
-       return &ABIConfig{offsetForLocals: offsetForLocals, regAmounts: RegAmounts{iRegsCount, fRegsCount}}
+func NewABIConfig(iRegsCount, fRegsCount int, offsetForLocals int64, which uint8) *ABIConfig {
+       return &ABIConfig{offsetForLocals: offsetForLocals, regAmounts: RegAmounts{iRegsCount, fRegsCount}, which: obj.ABI(which)}
 }
 
 // Copy returns config.
@@ -276,6 +278,11 @@ func (config *ABIConfig) Copy() *ABIConfig {
        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.
 // In theory this is only used for debugging; it ought to already be incorporated into
 // results from the ABI-related methods
index 5bbc88aaaef246895df7cc4342f63eac8d35d756..da4294d8716c630b78cfdb10084ab24434b084c8 100644 (file)
@@ -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.ABI0 = abi.NewABIConfig(0, 0, ctxt.Arch.FixedFrameSize)
-       c.ABI1 = abi.NewABIConfig(len(c.intParamRegs), len(c.floatParamRegs), 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, 1)
 
        // On Plan 9, floating point operations are not allowed in note handler.
        if buildcfg.GOOS == "plan9" {
index 2aaf6e769eadb65878850327c3ce7c1af130f370..e94cb77f9230b8495685c2cfcc928d2da0dfd3ca 100644 (file)
@@ -10,6 +10,7 @@ import (
        "cmd/compile/internal/ir"
        "cmd/compile/internal/typecheck"
        "cmd/compile/internal/types"
+       "cmd/internal/obj"
        "cmd/internal/src"
        "fmt"
        "math"
@@ -109,6 +110,21 @@ func (f *Func) NumValues() int {
        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.
 func (f *Func) newSparseSet(n int) *sparseSet {
        return f.Cache.allocSparseSet(n)
index 7e5a097d7dda022af508ea72c91ffdd2ea8d908a..ea170fbcdba6892c6f52a61e0de2fabb72ab0268 100644 (file)
@@ -741,7 +741,7 @@ function toggleDarkMode() {
 </head>`)
        w.WriteString("<body>")
        w.WriteString("<h1>")
-       w.WriteString(html.EscapeString(w.Func.Name))
+       w.WriteString(html.EscapeString(w.Func.NameABI()))
        w.WriteString("</h1>")
        w.WriteString(`
 <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, "</html>")
        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.
index af3776c38fad430af555a316d0061d3dabc5df9b..366a9b3caabce9695dc7003fa134c1e6153364fe 100644 (file)
@@ -314,12 +314,29 @@ func (s *state) emitOpenDeferInfo() {
 // worker indicates which of the backend workers is doing the processing.
 func buildssa(fn *ir.Func, worker int) *ssa.Func {
        name := ir.FuncName(fn)
+
+       abiSelf := abiForFunc(fn, ssaConfig.ABI0, ssaConfig.ABI1)
+
        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"
-               pkgDotName := base.Ctxt.Pkgpath + "." + name
-               printssa = name == ssaDump ||
-                       strings.HasSuffix(pkgDotName, ssaDump) && (pkgDotName == ssaDump || strings.HasSuffix(pkgDotName, "/"+ssaDump))
+       // match either a simple name e.g. "(*Reader).Reset", package.name e.g. "compress/gzip.(*Reader).Reset", or subpackage name "gzip.(*Reader).Reset"
+       // optionally allows an ABI suffix specification in the GOSSAHASH, e.g. "(*Reader).Reset<0>" etc
+       if strings.Contains(ssaDump, name) { // in all the cases the function name is entirely contained within the GOSSAFUNC string.
+               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
        if printssa {
                astBuf = &bytes.Buffer{}
@@ -366,10 +383,10 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func {
        if fn.Pragma&ir.Nosplit != 0 {
                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.ABI1 = ssaConfig.ABI1.Copy()
-       s.f.ABIDefault = abiForFunc(nil, s.f.ABI0, s.f.ABI1)
-       s.f.ABISelf = abiForFunc(fn, s.f.ABI0, s.f.ABI1)
+       s.f.ABI0 = ssaConfig.ABI0
+       s.f.ABI1 = ssaConfig.ABI1
+       s.f.ABIDefault = abiForFunc(nil, ssaConfig.ABI0, ssaConfig.ABI1)
+       s.f.ABISelf = abiSelf
 
        s.panics = map[funcLine]*ssa.Block{}
        s.softFloat = s.config.SoftFloat
@@ -381,7 +398,7 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func {
        if printssa {
                ssaDF := ssaDumpFile
                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)
                        os.MkdirAll(ssaD, 0755)
                }
index dad7991b5d19c5a78a6f84cfe4195e3800a6571e..b500de9f18a872aa0e2535e942ad0333571ffac3 100644 (file)
@@ -22,7 +22,7 @@ import (
 // AMD64 registers available:
 // - integer: RAX, RBX, RCX, RDI, RSI, R8, R9, r10, R11
 // - floating point: X0 - X14
-var configAMD64 = abi.NewABIConfig(9, 15, 0)
+var configAMD64 = abi.NewABIConfig(9, 15, 0, 1)
 
 func TestMain(m *testing.M) {
        ssagen.Arch.LinkArch = &x86.Linkamd64