From 3d26f6847a824a26211a433ba4b7813cebd768c9 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Mon, 4 Jan 2016 10:40:40 -0500 Subject: [PATCH] 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 --- cmd/ssadump/main.go | 28 ++++++---------- go/ssa/mode.go | 79 +++++++++++++++++++++------------------------ 2 files changed, 46 insertions(+), 61 deletions(-) diff --git a/cmd/ssadump/main.go b/cmd/ssadump/main.go index bdc4d0a274..bf2bbf24df 100644 --- a/cmd/ssadump/main.go +++ b/cmd/ssadump/main.go @@ -23,8 +23,9 @@ import ( "golang.org/x/tools/go/ssa/ssautil" ) +// flags 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.") @@ -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. 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. Usage: ssadump [ ...] ... 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. ` -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() { if err := doMain(); err != nil { fmt.Fprintf(os.Stderr, "ssadump: %s\n", err) @@ -139,7 +131,7 @@ func doMain() error { } // Create and build SSA-form program representation. - prog := ssautil.CreateProgram(iprog, *modeFlag) + prog := ssautil.CreateProgram(iprog, mode) // Build and display only the initial packages // (and synthetic wrappers), unless -run is specified. diff --git a/go/ssa/mode.go b/go/ssa/mode.go index bbd613afad..d2a269893a 100644 --- a/go/ssa/mode.go +++ b/go/ssa/mode.go @@ -8,11 +8,16 @@ package ssa import ( "bytes" - "flag" "fmt" ) // 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 const ( @@ -26,7 +31,7 @@ const ( 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: C perform sanity [C]hecking of the SSA form. 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. ` -// BuilderModeFlag creates a new command line flag of type BuilderMode, -// adds it to the specified flag set, and returns it. -// -// Example: -// var ssabuild = BuilderModeFlag(flag.CommandLine, "ssabuild", 0) -// -func BuilderModeFlag(set *flag.FlagSet, name string, value BuilderMode) *BuilderMode { - set.Var((*builderModeValue)(&value), name, modeFlagUsage) - return &value +func (m BuilderMode) String() string { + var buf bytes.Buffer + if m&GlobalDebug != 0 { + buf.WriteByte('D') + } + if m&PrintPackages != 0 { + buf.WriteByte('P') + } + 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. - -func (v *builderModeValue) Set(s string) error { +// Set parses the flag characters in s and updates *m. +func (m *BuilderMode) Set(s string) error { var mode BuilderMode for _, c := range s { switch c { @@ -73,35 +92,9 @@ func (v *builderModeValue) Set(s string) error { return fmt.Errorf("unknown BuilderMode option: %q", c) } } - *v = builderModeValue(mode) + *m = mode return nil } -func (v *builderModeValue) Get() interface{} { return BuilderMode(*v) } - -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() -} +// Get returns m. +func (m BuilderMode) Get() interface{} { return m }