go.tools/cmd/ssadump: print packages and functions to stdout, not stderr.

And serialize the printing of each item with a mutex.
It is the formatted output of this tool, after all.

Also: minor doc tweaks.

LGTM=gri
R=gri
CC=golang-codereviews
https://golang.org/cl/114620044
This commit is contained in:
Alan Donovan 2014-08-01 14:44:37 -04:00
parent 4228ee8063
commit 149e030318
6 changed files with 27 additions and 18 deletions

View File

@ -23,8 +23,8 @@ var buildFlag = flag.String("build", "", `Options controlling the SSA builder.
The value is a sequence of zero or more of these letters: The value is a sequence of zero or more of these letters:
C perform sanity [C]hecking of the SSA form. C perform sanity [C]hecking of the SSA form.
D include [D]ebug info for every function. D include [D]ebug info for every function.
P log [P]ackage inventory. P print [P]ackage inventory.
F log [F]unction SSA code. F print [F]unction SSA code.
S log [S]ource locations as SSA builder progresses. S log [S]ource locations as SSA builder progresses.
G use binary object files from gc to provide imports (no code). G use binary object files from gc to provide imports (no code).
L build distinct packages seria[L]ly instead of in parallel. L build distinct packages seria[L]ly instead of in parallel.
@ -105,9 +105,9 @@ func doMain() error {
case 'D': case 'D':
mode |= ssa.GlobalDebug mode |= ssa.GlobalDebug
case 'P': case 'P':
mode |= ssa.LogPackages | ssa.BuildSerially mode |= ssa.PrintPackages
case 'F': case 'F':
mode |= ssa.LogFunctions | ssa.BuildSerially mode |= ssa.PrintFunctions
case 'S': case 'S':
mode |= ssa.LogSource | ssa.BuildSerially mode |= ssa.LogSource | ssa.BuildSerially
case 'C': case 'C':

View File

@ -11,6 +11,7 @@ import (
"go/ast" "go/ast"
"go/token" "go/token"
"os" "os"
"sync"
"code.google.com/p/go.tools/go/loader" "code.google.com/p/go.tools/go/loader"
"code.google.com/p/go.tools/go/types" "code.google.com/p/go.tools/go/types"
@ -20,9 +21,9 @@ import (
type BuilderMode uint type BuilderMode uint
const ( const (
LogPackages BuilderMode = 1 << iota // Dump package inventory to stderr PrintPackages BuilderMode = 1 << iota // Print package inventory to stdout
LogFunctions // Dump function SSA code to stderr PrintFunctions // Print function SSA code to stdout
LogSource // Show source locations as SSA builder progresses LogSource // Log source locations as SSA builder progresses
SanityCheckFunctions // Perform sanity checking of function bodies SanityCheckFunctions // Perform sanity checking of function bodies
NaiveForm // Build naïve SSA form: don't replace local loads/stores with registers NaiveForm // Build naïve SSA form: don't replace local loads/stores with registers
BuildSerially // Build packages serially, not in parallel. BuildSerially // Build packages serially, not in parallel.
@ -237,8 +238,10 @@ func (prog *Program) CreatePackage(info *loader.PackageInfo) *Package {
p.SetDebugMode(true) p.SetDebugMode(true)
} }
if prog.mode&LogPackages != 0 { if prog.mode&PrintPackages != 0 {
p.WriteTo(os.Stderr) printMu.Lock()
p.WriteTo(os.Stdout)
printMu.Unlock()
} }
if info.Importable { if info.Importable {
@ -249,6 +252,9 @@ func (prog *Program) CreatePackage(info *loader.PackageInfo) *Package {
return p return p
} }
// printMu serializes printing of Packages/Functions to stdout
var printMu sync.Mutex
// AllPackages returns a new slice containing all packages in the // AllPackages returns a new slice containing all packages in the
// program prog in unspecified order. // program prog in unspecified order.
// //

View File

@ -338,8 +338,10 @@ func (f *Function) finishBody() {
numberRegisters(f) numberRegisters(f)
if f.Prog.mode&LogFunctions != 0 { if f.Prog.mode&PrintFunctions != 0 {
f.WriteTo(os.Stderr) printMu.Lock()
f.WriteTo(os.Stdout)
printMu.Unlock()
} }
if f.Prog.mode&SanityCheckFunctions != 0 { if f.Prog.mode&SanityCheckFunctions != 0 {
@ -439,9 +441,7 @@ func (f *Function) lookup(obj types.Object, escaping bool) Value {
return v return v
} }
// emit emits the specified instruction to function f, updating the // emit emits the specified instruction to function f.
// control-flow graph if required.
//
func (f *Function) emit(instr Instruction) Value { func (f *Function) emit(instr Instruction) Value {
return f.currentBlock.emit(instr) return f.currentBlock.emit(instr)
} }

View File

@ -54,7 +54,7 @@ func TestObjValueLookup(t *testing.T) {
return return
} }
prog := ssa.Create(iprog, 0 /*|ssa.LogFunctions*/) prog := ssa.Create(iprog, 0 /*|ssa.PrintFunctions*/)
mainInfo := iprog.Created[0] mainInfo := iprog.Created[0]
mainPkg := prog.Package(mainInfo.Pkg) mainPkg := prog.Package(mainInfo.Pkg)
mainPkg.SetDebugMode(true) mainPkg.SetDebugMode(true)

View File

@ -288,6 +288,7 @@ type Node interface {
// of the ast.FuncDecl.Name, if the function was explicit in the // of the ast.FuncDecl.Name, if the function was explicit in the
// source. Synthetic wrappers, for which Synthetic != "", may share // source. Synthetic wrappers, for which Synthetic != "", may share
// the same position as the function they wrap. // the same position as the function they wrap.
// Syntax.Pos() always returns the position of the declaring "func" token.
// //
// Type() returns the function's Signature. // Type() returns the function's Signature.
// //
@ -1371,7 +1372,7 @@ func (c *CallCommon) Description() string {
} }
// The CallInstruction interface, implemented by *Go, *Defer and *Call, // The CallInstruction interface, implemented by *Go, *Defer and *Call,
// exposes the common parts of function calling instructions, // exposes the common parts of function-calling instructions,
// yet provides a way back to the Value defined by *Call alone. // yet provides a way back to the Value defined by *Call alone.
// //
type CallInstruction interface { type CallInstruction interface {

View File

@ -149,8 +149,10 @@ func (prog *Program) CreateTestMainPackage(pkgs ...*Package) *Package {
testmain.Members["main"] = main testmain.Members["main"] = main
if prog.mode&LogPackages != 0 { if prog.mode&PrintPackages != 0 {
testmain.WriteTo(os.Stderr) printMu.Lock()
testmain.WriteTo(os.Stdout)
printMu.Unlock()
} }
if prog.mode&SanityCheckFunctions != 0 { if prog.mode&SanityCheckFunctions != 0 {