1
0
mirror of https://github.com/golang/go synced 2024-09-30 14:28:33 -06:00

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"
)
// 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 [<flag> ...] <args> ...
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.

View File

@ -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 }