Commit c35069d6 authored by Yury Smolsky's avatar Yury Smolsky Committed by Josh Bleecher Snyder

cmd/compile: clean the output of GOSSAFUNC

Since we print almost everything to ssa.html in the GOSSAFUNC mode,
there is a need to stop spamming stdout when user just wants to see
ssa.html.

This changes cleans output of the GOSSAFUNC debug mode.
To enable the dump of the debug data to stdout, one must
put suffix + after the function name like that:

GOSSAFUNC=Foo+

Otherwise gc will not print the IR and ASM to stdout after each phase.
AST IR is still sent to stdout because it is not included
into ssa.html. It will be fixed in a separate change.

The change adds printing out the full path to the ssa.html file.

Updates #25942

Change-Id: I711e145e05f0443c7df5459ca528dced273a62ee
Reviewed-on: https://go-review.googlesource.com/126603
Run-TryBot: Yury Smolsky <yury@smolsky.by>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarKeith Randall <khr@golang.org>
parent eeb8aebe
...@@ -428,6 +428,10 @@ func Main(archInit func(*Arch)) { ...@@ -428,6 +428,10 @@ func Main(archInit func(*Arch)) {
} }
ssaDump = os.Getenv("GOSSAFUNC") ssaDump = os.Getenv("GOSSAFUNC")
if strings.HasSuffix(ssaDump, "+") {
ssaDump = ssaDump[:len(ssaDump)-1]
ssaDumpStdout = true
}
trackScopes = flagDWARF trackScopes = flagDWARF
......
...@@ -23,7 +23,8 @@ import ( ...@@ -23,7 +23,8 @@ import (
var ssaConfig *ssa.Config var ssaConfig *ssa.Config
var ssaCaches []ssa.Cache var ssaCaches []ssa.Cache
var ssaDump string // early copy of $GOSSAFUNC; the func name to dump output for var ssaDump string // early copy of $GOSSAFUNC; the func name to dump output for
var ssaDumpStdout bool // whether to dump to stdout
const ssaDumpFile = "ssa.html" const ssaDumpFile = "ssa.html"
func initssaconfig() { func initssaconfig() {
...@@ -125,7 +126,7 @@ func buildssa(fn *Node, worker int) *ssa.Func { ...@@ -125,7 +126,7 @@ func buildssa(fn *Node, worker int) *ssa.Func {
fe := ssafn{ fe := ssafn{
curfn: fn, curfn: fn,
log: printssa, log: printssa && ssaDumpStdout,
} }
s.curfn = fn s.curfn = fn
...@@ -4873,7 +4874,8 @@ func genssa(f *ssa.Func, pp *Progs) { ...@@ -4873,7 +4874,8 @@ func genssa(f *ssa.Func, pp *Progs) {
var progToBlock map[*obj.Prog]*ssa.Block var progToBlock map[*obj.Prog]*ssa.Block
var valueToProgAfter []*obj.Prog // The first Prog following computation of a value v; v is visible at this point. var valueToProgAfter []*obj.Prog // The first Prog following computation of a value v; v is visible at this point.
var logProgs = e.log var logProgs = e.log
if logProgs { if f.HTMLWriter != nil {
// logProgs can be false, meaning that we do not dump to the Stdout.
progToValue = make(map[*obj.Prog]*ssa.Value, f.NumValues()) progToValue = make(map[*obj.Prog]*ssa.Value, f.NumValues())
progToBlock = make(map[*obj.Prog]*ssa.Block, f.NumBlocks()) progToBlock = make(map[*obj.Prog]*ssa.Block, f.NumBlocks())
f.Logf("genssa %s\n", f.Name) f.Logf("genssa %s\n", f.Name)
...@@ -5042,42 +5044,36 @@ func genssa(f *ssa.Func, pp *Progs) { ...@@ -5042,42 +5044,36 @@ func genssa(f *ssa.Func, pp *Progs) {
} }
f.Logf(" %-6s\t%.5d (%s)\t%s\n", s, p.Pc, p.InnermostLineNumber(), p.InstructionString()) f.Logf(" %-6s\t%.5d (%s)\t%s\n", s, p.Pc, p.InnermostLineNumber(), p.InstructionString())
} }
if f.HTMLWriter != nil { }
// LineHist is defunct now - this code won't do if f.HTMLWriter != nil {
// anything. var buf bytes.Buffer
// TODO: fix this (ideally without a global variable) buf.WriteString("<code>")
// saved := pp.Text.Ctxt.LineHist.PrintFilenameOnly buf.WriteString("<dl class=\"ssa-gen\">")
// pp.Text.Ctxt.LineHist.PrintFilenameOnly = true filename := ""
var buf bytes.Buffer for p := pp.Text; p != nil; p = p.Link {
buf.WriteString("<code>") // Don't spam every line with the file name, which is often huge.
buf.WriteString("<dl class=\"ssa-gen\">") // Only print changes, and "unknown" is not a change.
filename := "" if p.Pos.IsKnown() && p.InnermostFilename() != filename {
for p := pp.Text; p != nil; p = p.Link { filename = p.InnermostFilename()
// Don't spam every line with the file name, which is often huge. buf.WriteString("<dt class=\"ssa-prog-src\"></dt><dd class=\"ssa-prog\">")
// Only print changes, and "unknown" is not a change. buf.WriteString(html.EscapeString("# " + filename))
if p.Pos.IsKnown() && p.InnermostFilename() != filename {
filename = p.InnermostFilename()
buf.WriteString("<dt class=\"ssa-prog-src\"></dt><dd class=\"ssa-prog\">")
buf.WriteString(html.EscapeString("# " + filename))
buf.WriteString("</dd>")
}
buf.WriteString("<dt class=\"ssa-prog-src\">")
if v, ok := progToValue[p]; ok {
buf.WriteString(v.HTML())
} else if b, ok := progToBlock[p]; ok {
buf.WriteString("<b>" + b.HTML() + "</b>")
}
buf.WriteString("</dt>")
buf.WriteString("<dd class=\"ssa-prog\">")
buf.WriteString(fmt.Sprintf("%.5d <span class=\"l%v line-number\">(%s)</span> %s", p.Pc, p.InnermostLineNumber(), p.InnermostLineNumberHTML(), html.EscapeString(p.InstructionString())))
buf.WriteString("</dd>") buf.WriteString("</dd>")
} }
buf.WriteString("</dl>")
buf.WriteString("</code>") buf.WriteString("<dt class=\"ssa-prog-src\">")
f.HTMLWriter.WriteColumn("genssa", "genssa", "ssa-prog", buf.String()) if v, ok := progToValue[p]; ok {
// pp.Text.Ctxt.LineHist.PrintFilenameOnly = saved buf.WriteString(v.HTML())
} else if b, ok := progToBlock[p]; ok {
buf.WriteString("<b>" + b.HTML() + "</b>")
}
buf.WriteString("</dt>")
buf.WriteString("<dd class=\"ssa-prog\">")
buf.WriteString(fmt.Sprintf("%.5d <span class=\"l%v line-number\">(%s)</span> %s", p.Pc, p.InnermostLineNumber(), p.InnermostLineNumberHTML(), html.EscapeString(p.InstructionString())))
buf.WriteString("</dd>")
} }
buf.WriteString("</dl>")
buf.WriteString("</code>")
f.HTMLWriter.WriteColumn("genssa", "genssa", "ssa-prog", buf.String())
} }
defframe(&s, e) defframe(&s, e)
...@@ -5435,7 +5431,7 @@ type ssafn struct { ...@@ -5435,7 +5431,7 @@ type ssafn struct {
scratchFpMem *Node // temp for floating point register / memory moves on some architectures scratchFpMem *Node // temp for floating point register / memory moves on some architectures
stksize int64 // stack size for current frame stksize int64 // stack size for current frame
stkptrsize int64 // prefix of stack containing pointers stkptrsize int64 // prefix of stack containing pointers
log bool log bool // print ssa debug to the stdout
} }
// StringData returns a symbol (a *types.Sym wrapped in an interface) which // StringData returns a symbol (a *types.Sym wrapped in an interface) which
......
...@@ -42,7 +42,9 @@ func Compile(f *Func) { ...@@ -42,7 +42,9 @@ func Compile(f *Func) {
}() }()
// Run all the passes // Run all the passes
printFunc(f) if f.Log() {
printFunc(f)
}
f.HTMLWriter.WriteFunc("start", "start", f) f.HTMLWriter.WriteFunc("start", "start", f)
if BuildDump != "" && BuildDump == f.Name { if BuildDump != "" && BuildDump == f.Name {
f.dumpFile("build") f.dumpFile("build")
...@@ -84,8 +86,10 @@ func Compile(f *Func) { ...@@ -84,8 +86,10 @@ func Compile(f *Func) {
stats = fmt.Sprintf("[%d ns]", time) stats = fmt.Sprintf("[%d ns]", time)
} }
f.Logf(" pass %s end %s\n", p.name, stats) if f.Log() {
printFunc(f) f.Logf(" pass %s end %s\n", p.name, stats)
printFunc(f)
}
f.HTMLWriter.WriteFunc(phaseName, fmt.Sprintf("%s <span class=\"stats\">%s</span>", phaseName, stats), f) f.HTMLWriter.WriteFunc(phaseName, fmt.Sprintf("%s <span class=\"stats\">%s</span>", phaseName, stats), f)
} }
if p.time || p.mem { if p.time || p.mem {
......
...@@ -11,12 +11,14 @@ import ( ...@@ -11,12 +11,14 @@ import (
"html" "html"
"io" "io"
"os" "os"
"path/filepath"
"strings" "strings"
) )
type HTMLWriter struct { type HTMLWriter struct {
Logger Logger
w io.WriteCloser w io.WriteCloser
path string
} }
func NewHTMLWriter(path string, logger Logger, funcname string) *HTMLWriter { func NewHTMLWriter(path string, logger Logger, funcname string) *HTMLWriter {
...@@ -24,7 +26,11 @@ func NewHTMLWriter(path string, logger Logger, funcname string) *HTMLWriter { ...@@ -24,7 +26,11 @@ func NewHTMLWriter(path string, logger Logger, funcname string) *HTMLWriter {
if err != nil { if err != nil {
logger.Fatalf(src.NoXPos, "%v", err) logger.Fatalf(src.NoXPos, "%v", err)
} }
html := HTMLWriter{w: out, Logger: logger} pwd, err := os.Getwd()
if err != nil {
logger.Fatalf(src.NoXPos, "%v", err)
}
html := HTMLWriter{w: out, Logger: logger, path: filepath.Join(pwd, path)}
html.start(funcname) html.start(funcname)
return &html return &html
} }
...@@ -439,6 +445,7 @@ func (w *HTMLWriter) Close() { ...@@ -439,6 +445,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)
} }
// WriteFunc writes f in a column headed by title. // WriteFunc writes f in a column headed by title.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment