go/ssa: make *BuilderMode satisfy flag.Value

The BuilderModeFlag function does not work with flag packages (such as
Google's) that define their own FlagSet.  This change exposes a type
that satisifies flag.Value insted of a function.  That type
is *BuilderMode; there's no need for a separate wrapper type.

Change-Id: I8095b80de499e3c52a29a5c1996d1b1fe3799358
Reviewed-on: https://go-review.googlesource.com/20330
Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
Alan Donovan 2016-01-04 10:40:40 -05:00
parent 53f5cdeed1
commit 3d26f6847a
2 changed files with 46 additions and 61 deletions

View File

@ -23,8 +23,9 @@ import (
"golang.org/x/tools/go/ssa/ssautil" "golang.org/x/tools/go/ssa/ssautil"
) )
// flags
var ( var (
modeFlag = ssa.BuilderModeFlag(flag.CommandLine, "build", 0) mode = ssa.BuilderMode(0)
testFlag = flag.Bool("test", false, "Loads test code (*_test.go) for imported packages.") testFlag = flag.Bool("test", false, "Loads test code (*_test.go) for imported packages.")
@ -35,8 +36,15 @@ The value is a sequence of zero or more more of these letters:
R disable [R]ecover() from panic; show interpreter crash instead. R disable [R]ecover() from panic; show interpreter crash instead.
T [T]race execution of the program. Best for single-threaded programs! T [T]race execution of the program. Best for single-threaded programs!
`) `)
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
) )
func init() {
flag.Var(&mode, "build", ssa.BuilderModeDoc)
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
}
const usage = `SSA builder and interpreter. const usage = `SSA builder and interpreter.
Usage: ssadump [<flag> ...] <args> ... Usage: ssadump [<flag> ...] <args> ...
Use -help flag to display options. Use -help flag to display options.
@ -53,22 +61,6 @@ if clear, it runs the first package named main.
if set, it runs the tests of each package. if set, it runs the tests of each package.
` `
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
func init() {
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
// If $GOMAXPROCS isn't set, use the full capacity of the machine.
// For small machines, use at least 4 threads.
if os.Getenv("GOMAXPROCS") == "" {
n := runtime.NumCPU()
if n < 4 {
n = 4
}
runtime.GOMAXPROCS(n)
}
}
func main() { func main() {
if err := doMain(); err != nil { if err := doMain(); err != nil {
fmt.Fprintf(os.Stderr, "ssadump: %s\n", err) fmt.Fprintf(os.Stderr, "ssadump: %s\n", err)
@ -139,7 +131,7 @@ func doMain() error {
} }
// Create and build SSA-form program representation. // Create and build SSA-form program representation.
prog := ssautil.CreateProgram(iprog, *modeFlag) prog := ssautil.CreateProgram(iprog, mode)
// Build and display only the initial packages // Build and display only the initial packages
// (and synthetic wrappers), unless -run is specified. // (and synthetic wrappers), unless -run is specified.

View File

@ -8,11 +8,16 @@ package ssa
import ( import (
"bytes" "bytes"
"flag"
"fmt" "fmt"
) )
// BuilderMode is a bitmask of options for diagnostics and checking. // BuilderMode is a bitmask of options for diagnostics and checking.
//
// *BuilderMode satisfies the flag.Value interface. Example:
//
// var mode = ssa.BuilderMode(0)
// func init() { flag.Var(&mode, "build", ssa.BuilderModeDoc) }
//
type BuilderMode uint type BuilderMode uint
const ( const (
@ -26,7 +31,7 @@ const (
BareInits // Build init functions without guards or calls to dependent inits BareInits // Build init functions without guards or calls to dependent inits
) )
const modeFlagUsage = `Options controlling the SSA builder. const BuilderModeDoc = `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.
@ -38,20 +43,34 @@ N build [N]aive SSA form: don't replace local loads/stores with registers.
I build bare [I]nit functions: no init guards or calls to dependent inits. I build bare [I]nit functions: no init guards or calls to dependent inits.
` `
// BuilderModeFlag creates a new command line flag of type BuilderMode, func (m BuilderMode) String() string {
// adds it to the specified flag set, and returns it. var buf bytes.Buffer
// if m&GlobalDebug != 0 {
// Example: buf.WriteByte('D')
// var ssabuild = BuilderModeFlag(flag.CommandLine, "ssabuild", 0) }
// if m&PrintPackages != 0 {
func BuilderModeFlag(set *flag.FlagSet, name string, value BuilderMode) *BuilderMode { buf.WriteByte('P')
set.Var((*builderModeValue)(&value), name, modeFlagUsage) }
return &value if m&PrintFunctions != 0 {
buf.WriteByte('F')
}
if m&LogSource != 0 {
buf.WriteByte('S')
}
if m&SanityCheckFunctions != 0 {
buf.WriteByte('C')
}
if m&NaiveForm != 0 {
buf.WriteByte('N')
}
if m&BuildSerially != 0 {
buf.WriteByte('L')
}
return buf.String()
} }
type builderModeValue BuilderMode // satisfies flag.Value and flag.Getter. // Set parses the flag characters in s and updates *m.
func (m *BuilderMode) Set(s string) error {
func (v *builderModeValue) Set(s string) error {
var mode BuilderMode var mode BuilderMode
for _, c := range s { for _, c := range s {
switch c { switch c {
@ -73,35 +92,9 @@ func (v *builderModeValue) Set(s string) error {
return fmt.Errorf("unknown BuilderMode option: %q", c) return fmt.Errorf("unknown BuilderMode option: %q", c)
} }
} }
*v = builderModeValue(mode) *m = mode
return nil return nil
} }
func (v *builderModeValue) Get() interface{} { return BuilderMode(*v) } // Get returns m.
func (m BuilderMode) Get() interface{} { return m }
func (v *builderModeValue) String() string {
mode := BuilderMode(*v)
var buf bytes.Buffer
if mode&GlobalDebug != 0 {
buf.WriteByte('D')
}
if mode&PrintPackages != 0 {
buf.WriteByte('P')
}
if mode&PrintFunctions != 0 {
buf.WriteByte('F')
}
if mode&LogSource != 0 {
buf.WriteByte('S')
}
if mode&SanityCheckFunctions != 0 {
buf.WriteByte('C')
}
if mode&NaiveForm != 0 {
buf.WriteByte('N')
}
if mode&BuildSerially != 0 {
buf.WriteByte('L')
}
return buf.String()
}