mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile,cmd/internal/objabi: move -d flag parser to objabi
This moves and slightly generalizes the -d debug flag parser from cmd/compile/internal/base to cmd/internal/objabi so that we can use the same debug flag syntax in other tools. This makes a few minor tweaks to implementation details. The flag itself is now just a flag.Value that gets constructed explicitly, rather than at init time, and we've cleaned up the implementation a little (e.g., using a map instead of a linear search of a slice). The help text is now automatically alphabetized. Rather than describing the values of some flags in the help text footer, we simply include it in the flags' help text and make sure multi-line help text renders sensibly. For #48297. Change-Id: Id373ee3b767e456be483fb28c110d025149be532 Reviewed-on: https://go-review.googlesource.com/c/go/+/359956 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
0e5f287fde
commit
1c4cfd8010
3 changed files with 187 additions and 159 deletions
|
|
@ -6,15 +6,6 @@
|
|||
|
||||
package base
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Debug holds the parsed debugging configuration values.
|
||||
var Debug DebugFlags
|
||||
|
||||
|
|
@ -26,7 +17,7 @@ var Debug DebugFlags
|
|||
// Each setting is name=value; for ints, name is short for name=1.
|
||||
type DebugFlags struct {
|
||||
Append int `help:"print information about append compilation"`
|
||||
Checkptr int `help:"instrument unsafe pointer conversions"`
|
||||
Checkptr int `help:"instrument unsafe pointer conversions\n0: instrumentation disabled\n1: conversions involving unsafe.Pointer are instrumented\n2: conversions to unsafe.Pointer force heap allocation"`
|
||||
Closure int `help:"print information about closure compilation"`
|
||||
DclStack int `help:"run internal dclstack check"`
|
||||
Defer int `help:"print information about defer compilation"`
|
||||
|
|
@ -40,7 +31,7 @@ type DebugFlags struct {
|
|||
LocationLists int `help:"print information about DWARF location list creation"`
|
||||
Nil int `help:"print information about nil checks"`
|
||||
NoOpenDefer int `help:"disable open-coded defers"`
|
||||
PCTab string `help:"print named pc-value table"`
|
||||
PCTab string `help:"print named pc-value table\nOne of: pctospadj, pctofile, pctoline, pctoinline, pctopcdata"`
|
||||
Panic int `help:"show all compiler panics"`
|
||||
Slice int `help:"print information about slice compilation"`
|
||||
SoftFloat int `help:"force compiler to emit soft-float code"`
|
||||
|
|
@ -52,141 +43,10 @@ type DebugFlags struct {
|
|||
WB int `help:"print information about write barriers"`
|
||||
ABIWrap int `help:"print information about ABI wrapper generation"`
|
||||
|
||||
any bool // set when any of the values have been set
|
||||
}
|
||||
|
||||
// Any reports whether any of the debug flags have been set.
|
||||
func (d *DebugFlags) Any() bool { return d.any }
|
||||
|
||||
type debugField struct {
|
||||
name string
|
||||
help string
|
||||
val interface{} // *int or *string
|
||||
}
|
||||
|
||||
var debugTab []debugField
|
||||
|
||||
func init() {
|
||||
v := reflect.ValueOf(&Debug).Elem()
|
||||
t := v.Type()
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
f := t.Field(i)
|
||||
if f.Name == "any" {
|
||||
continue
|
||||
}
|
||||
name := strings.ToLower(f.Name)
|
||||
help := f.Tag.Get("help")
|
||||
if help == "" {
|
||||
panic(fmt.Sprintf("base.Debug.%s is missing help text", f.Name))
|
||||
}
|
||||
ptr := v.Field(i).Addr().Interface()
|
||||
switch ptr.(type) {
|
||||
default:
|
||||
panic(fmt.Sprintf("base.Debug.%s has invalid type %v (must be int or string)", f.Name, f.Type))
|
||||
case *int, *string:
|
||||
// ok
|
||||
}
|
||||
debugTab = append(debugTab, debugField{name, help, ptr})
|
||||
}
|
||||
Any bool // set when any of the debug flags have been set
|
||||
}
|
||||
|
||||
// DebugSSA is called to set a -d ssa/... option.
|
||||
// If nil, those options are reported as invalid options.
|
||||
// If DebugSSA returns a non-empty string, that text is reported as a compiler error.
|
||||
var DebugSSA func(phase, flag string, val int, valString string) string
|
||||
|
||||
// parseDebug parses the -d debug string argument.
|
||||
func parseDebug(debugstr string) {
|
||||
// parse -d argument
|
||||
if debugstr == "" {
|
||||
return
|
||||
}
|
||||
Debug.any = true
|
||||
Split:
|
||||
for _, name := range strings.Split(debugstr, ",") {
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
// display help about the -d option itself and quit
|
||||
if name == "help" {
|
||||
fmt.Print(debugHelpHeader)
|
||||
maxLen := len("ssa/help")
|
||||
for _, t := range debugTab {
|
||||
if len(t.name) > maxLen {
|
||||
maxLen = len(t.name)
|
||||
}
|
||||
}
|
||||
for _, t := range debugTab {
|
||||
fmt.Printf("\t%-*s\t%s\n", maxLen, t.name, t.help)
|
||||
}
|
||||
// ssa options have their own help
|
||||
fmt.Printf("\t%-*s\t%s\n", maxLen, "ssa/help", "print help about SSA debugging")
|
||||
fmt.Print(debugHelpFooter)
|
||||
os.Exit(0)
|
||||
}
|
||||
val, valstring, haveInt := 1, "", true
|
||||
if i := strings.IndexAny(name, "=:"); i >= 0 {
|
||||
var err error
|
||||
name, valstring = name[:i], name[i+1:]
|
||||
val, err = strconv.Atoi(valstring)
|
||||
if err != nil {
|
||||
val, haveInt = 1, false
|
||||
}
|
||||
}
|
||||
for _, t := range debugTab {
|
||||
if t.name != name {
|
||||
continue
|
||||
}
|
||||
switch vp := t.val.(type) {
|
||||
case nil:
|
||||
// Ignore
|
||||
case *string:
|
||||
*vp = valstring
|
||||
case *int:
|
||||
if !haveInt {
|
||||
log.Fatalf("invalid debug value %v", name)
|
||||
}
|
||||
*vp = val
|
||||
default:
|
||||
panic("bad debugtab type")
|
||||
}
|
||||
continue Split
|
||||
}
|
||||
// special case for ssa for now
|
||||
if DebugSSA != nil && strings.HasPrefix(name, "ssa/") {
|
||||
// expect form ssa/phase/flag
|
||||
// e.g. -d=ssa/generic_cse/time
|
||||
// _ in phase name also matches space
|
||||
phase := name[4:]
|
||||
flag := "debug" // default flag is debug
|
||||
if i := strings.Index(phase, "/"); i >= 0 {
|
||||
flag = phase[i+1:]
|
||||
phase = phase[:i]
|
||||
}
|
||||
err := DebugSSA(phase, flag, val, valstring)
|
||||
if err != "" {
|
||||
log.Fatalf(err)
|
||||
}
|
||||
continue Split
|
||||
}
|
||||
log.Fatalf("unknown debug key -d %s\n", name)
|
||||
}
|
||||
}
|
||||
|
||||
const debugHelpHeader = `usage: -d arg[,arg]* and arg is <key>[=<value>]
|
||||
|
||||
<key> is one of:
|
||||
|
||||
`
|
||||
|
||||
const debugHelpFooter = `
|
||||
<value> is key-specific.
|
||||
|
||||
Key "checkptr" supports values:
|
||||
"0": instrumentation disabled
|
||||
"1": conversions involving unsafe.Pointer are instrumented
|
||||
"2": conversions to unsafe.Pointer force heap allocation
|
||||
|
||||
Key "pctab" supports values:
|
||||
"pctospadj", "pctofile", "pctoline", "pctoinline", "pctopcdata"
|
||||
`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue