From c35069d6428d29b12088731aab35cbff1e504a28 Mon Sep 17 00:00:00 2001 From: Yury Smolsky Date: Tue, 24 Jul 2018 10:39:00 +0300 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/main.go | 4 ++ src/cmd/compile/internal/gc/ssa.go | 70 ++++++++++++------------- src/cmd/compile/internal/ssa/compile.go | 10 ++-- src/cmd/compile/internal/ssa/html.go | 11 +++- 4 files changed, 53 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 5d074114ec0..44cf75e7c98 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -428,6 +428,10 @@ func Main(archInit func(*Arch)) { } ssaDump = os.Getenv("GOSSAFUNC") + if strings.HasSuffix(ssaDump, "+") { + ssaDump = ssaDump[:len(ssaDump)-1] + ssaDumpStdout = true + } trackScopes = flagDWARF diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index cabcf17ed1c..2abd9448d4e 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -23,7 +23,8 @@ import ( var ssaConfig *ssa.Config 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" func initssaconfig() { @@ -125,7 +126,7 @@ func buildssa(fn *Node, worker int) *ssa.Func { fe := ssafn{ curfn: fn, - log: printssa, + log: printssa && ssaDumpStdout, } s.curfn = fn @@ -4873,7 +4874,8 @@ func genssa(f *ssa.Func, pp *Progs) { 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 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()) progToBlock = make(map[*obj.Prog]*ssa.Block, f.NumBlocks()) f.Logf("genssa %s\n", f.Name) @@ -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()) } - if f.HTMLWriter != nil { - // LineHist is defunct now - this code won't do - // anything. - // TODO: fix this (ideally without a global variable) - // saved := pp.Text.Ctxt.LineHist.PrintFilenameOnly - // pp.Text.Ctxt.LineHist.PrintFilenameOnly = true - var buf bytes.Buffer - buf.WriteString("") - buf.WriteString("
") - filename := "" - for p := pp.Text; p != nil; p = p.Link { - // Don't spam every line with the file name, which is often huge. - // Only print changes, and "unknown" is not a change. - if p.Pos.IsKnown() && p.InnermostFilename() != filename { - filename = p.InnermostFilename() - buf.WriteString("
") - buf.WriteString(html.EscapeString("# " + filename)) - buf.WriteString("
") - } - - buf.WriteString("
") - if v, ok := progToValue[p]; ok { - buf.WriteString(v.HTML()) - } else if b, ok := progToBlock[p]; ok { - buf.WriteString("" + b.HTML() + "") - } - buf.WriteString("
") - buf.WriteString("
") - buf.WriteString(fmt.Sprintf("%.5d (%s) %s", p.Pc, p.InnermostLineNumber(), p.InnermostLineNumberHTML(), html.EscapeString(p.InstructionString()))) + } + if f.HTMLWriter != nil { + var buf bytes.Buffer + buf.WriteString("") + buf.WriteString("
") + filename := "" + for p := pp.Text; p != nil; p = p.Link { + // Don't spam every line with the file name, which is often huge. + // Only print changes, and "unknown" is not a change. + if p.Pos.IsKnown() && p.InnermostFilename() != filename { + filename = p.InnermostFilename() + buf.WriteString("
") + buf.WriteString(html.EscapeString("# " + filename)) buf.WriteString("
") } - buf.WriteString("
") - buf.WriteString("
") - f.HTMLWriter.WriteColumn("genssa", "genssa", "ssa-prog", buf.String()) - // pp.Text.Ctxt.LineHist.PrintFilenameOnly = saved + + buf.WriteString("
") + if v, ok := progToValue[p]; ok { + buf.WriteString(v.HTML()) + } else if b, ok := progToBlock[p]; ok { + buf.WriteString("" + b.HTML() + "") + } + buf.WriteString("
") + buf.WriteString("
") + buf.WriteString(fmt.Sprintf("%.5d (%s) %s", p.Pc, p.InnermostLineNumber(), p.InnermostLineNumberHTML(), html.EscapeString(p.InstructionString()))) + buf.WriteString("
") } + buf.WriteString("
") + buf.WriteString("
") + f.HTMLWriter.WriteColumn("genssa", "genssa", "ssa-prog", buf.String()) } defframe(&s, e) @@ -5435,7 +5431,7 @@ type ssafn struct { scratchFpMem *Node // temp for floating point register / memory moves on some architectures stksize int64 // stack size for current frame 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 diff --git a/src/cmd/compile/internal/ssa/compile.go b/src/cmd/compile/internal/ssa/compile.go index 7f75dc4a03d..8b5d6d94e8d 100644 --- a/src/cmd/compile/internal/ssa/compile.go +++ b/src/cmd/compile/internal/ssa/compile.go @@ -42,7 +42,9 @@ func Compile(f *Func) { }() // Run all the passes - printFunc(f) + if f.Log() { + printFunc(f) + } f.HTMLWriter.WriteFunc("start", "start", f) if BuildDump != "" && BuildDump == f.Name { f.dumpFile("build") @@ -84,8 +86,10 @@ func Compile(f *Func) { stats = fmt.Sprintf("[%d ns]", time) } - f.Logf(" pass %s end %s\n", p.name, stats) - printFunc(f) + if f.Log() { + f.Logf(" pass %s end %s\n", p.name, stats) + printFunc(f) + } f.HTMLWriter.WriteFunc(phaseName, fmt.Sprintf("%s %s", phaseName, stats), f) } if p.time || p.mem { diff --git a/src/cmd/compile/internal/ssa/html.go b/src/cmd/compile/internal/ssa/html.go index 81259093492..2e48e8105b1 100644 --- a/src/cmd/compile/internal/ssa/html.go +++ b/src/cmd/compile/internal/ssa/html.go @@ -11,12 +11,14 @@ import ( "html" "io" "os" + "path/filepath" "strings" ) type HTMLWriter struct { Logger - w io.WriteCloser + w io.WriteCloser + path string } 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 { 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) return &html } @@ -439,6 +445,7 @@ func (w *HTMLWriter) Close() { io.WriteString(w.w, "") io.WriteString(w.w, "") w.w.Close() + fmt.Printf("dumped SSA to %v\n", w.path) } // WriteFunc writes f in a column headed by title.