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:
parent
53f5cdeed1
commit
3d26f6847a
|
@ -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.
|
||||||
|
|
|
@ -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()
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue