Skip to content

Commit 1c4cfd8

Browse files
committed
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 <[email protected]> Run-TryBot: Austin Clements <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: David Chase <[email protected]> Reviewed-by: Cherry Mui <[email protected]>
1 parent 0e5f287 commit 1c4cfd8

File tree

3 files changed

+187
-159
lines changed

3 files changed

+187
-159
lines changed

src/cmd/compile/internal/base/debug.go

Lines changed: 3 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,6 @@
66

77
package base
88

9-
import (
10-
"fmt"
11-
"log"
12-
"os"
13-
"reflect"
14-
"strconv"
15-
"strings"
16-
)
17-
189
// Debug holds the parsed debugging configuration values.
1910
var Debug DebugFlags
2011

@@ -26,7 +17,7 @@ var Debug DebugFlags
2617
// Each setting is name=value; for ints, name is short for name=1.
2718
type DebugFlags struct {
2819
Append int `help:"print information about append compilation"`
29-
Checkptr int `help:"instrument unsafe pointer conversions"`
20+
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"`
3021
Closure int `help:"print information about closure compilation"`
3122
DclStack int `help:"run internal dclstack check"`
3223
Defer int `help:"print information about defer compilation"`
@@ -40,7 +31,7 @@ type DebugFlags struct {
4031
LocationLists int `help:"print information about DWARF location list creation"`
4132
Nil int `help:"print information about nil checks"`
4233
NoOpenDefer int `help:"disable open-coded defers"`
43-
PCTab string `help:"print named pc-value table"`
34+
PCTab string `help:"print named pc-value table\nOne of: pctospadj, pctofile, pctoline, pctoinline, pctopcdata"`
4435
Panic int `help:"show all compiler panics"`
4536
Slice int `help:"print information about slice compilation"`
4637
SoftFloat int `help:"force compiler to emit soft-float code"`
@@ -52,141 +43,10 @@ type DebugFlags struct {
5243
WB int `help:"print information about write barriers"`
5344
ABIWrap int `help:"print information about ABI wrapper generation"`
5445

55-
any bool // set when any of the values have been set
56-
}
57-
58-
// Any reports whether any of the debug flags have been set.
59-
func (d *DebugFlags) Any() bool { return d.any }
60-
61-
type debugField struct {
62-
name string
63-
help string
64-
val interface{} // *int or *string
65-
}
66-
67-
var debugTab []debugField
68-
69-
func init() {
70-
v := reflect.ValueOf(&Debug).Elem()
71-
t := v.Type()
72-
for i := 0; i < t.NumField(); i++ {
73-
f := t.Field(i)
74-
if f.Name == "any" {
75-
continue
76-
}
77-
name := strings.ToLower(f.Name)
78-
help := f.Tag.Get("help")
79-
if help == "" {
80-
panic(fmt.Sprintf("base.Debug.%s is missing help text", f.Name))
81-
}
82-
ptr := v.Field(i).Addr().Interface()
83-
switch ptr.(type) {
84-
default:
85-
panic(fmt.Sprintf("base.Debug.%s has invalid type %v (must be int or string)", f.Name, f.Type))
86-
case *int, *string:
87-
// ok
88-
}
89-
debugTab = append(debugTab, debugField{name, help, ptr})
90-
}
46+
Any bool // set when any of the debug flags have been set
9147
}
9248

9349
// DebugSSA is called to set a -d ssa/... option.
9450
// If nil, those options are reported as invalid options.
9551
// If DebugSSA returns a non-empty string, that text is reported as a compiler error.
9652
var DebugSSA func(phase, flag string, val int, valString string) string
97-
98-
// parseDebug parses the -d debug string argument.
99-
func parseDebug(debugstr string) {
100-
// parse -d argument
101-
if debugstr == "" {
102-
return
103-
}
104-
Debug.any = true
105-
Split:
106-
for _, name := range strings.Split(debugstr, ",") {
107-
if name == "" {
108-
continue
109-
}
110-
// display help about the -d option itself and quit
111-
if name == "help" {
112-
fmt.Print(debugHelpHeader)
113-
maxLen := len("ssa/help")
114-
for _, t := range debugTab {
115-
if len(t.name) > maxLen {
116-
maxLen = len(t.name)
117-
}
118-
}
119-
for _, t := range debugTab {
120-
fmt.Printf("\t%-*s\t%s\n", maxLen, t.name, t.help)
121-
}
122-
// ssa options have their own help
123-
fmt.Printf("\t%-*s\t%s\n", maxLen, "ssa/help", "print help about SSA debugging")
124-
fmt.Print(debugHelpFooter)
125-
os.Exit(0)
126-
}
127-
val, valstring, haveInt := 1, "", true
128-
if i := strings.IndexAny(name, "=:"); i >= 0 {
129-
var err error
130-
name, valstring = name[:i], name[i+1:]
131-
val, err = strconv.Atoi(valstring)
132-
if err != nil {
133-
val, haveInt = 1, false
134-
}
135-
}
136-
for _, t := range debugTab {
137-
if t.name != name {
138-
continue
139-
}
140-
switch vp := t.val.(type) {
141-
case nil:
142-
// Ignore
143-
case *string:
144-
*vp = valstring
145-
case *int:
146-
if !haveInt {
147-
log.Fatalf("invalid debug value %v", name)
148-
}
149-
*vp = val
150-
default:
151-
panic("bad debugtab type")
152-
}
153-
continue Split
154-
}
155-
// special case for ssa for now
156-
if DebugSSA != nil && strings.HasPrefix(name, "ssa/") {
157-
// expect form ssa/phase/flag
158-
// e.g. -d=ssa/generic_cse/time
159-
// _ in phase name also matches space
160-
phase := name[4:]
161-
flag := "debug" // default flag is debug
162-
if i := strings.Index(phase, "/"); i >= 0 {
163-
flag = phase[i+1:]
164-
phase = phase[:i]
165-
}
166-
err := DebugSSA(phase, flag, val, valstring)
167-
if err != "" {
168-
log.Fatalf(err)
169-
}
170-
continue Split
171-
}
172-
log.Fatalf("unknown debug key -d %s\n", name)
173-
}
174-
}
175-
176-
const debugHelpHeader = `usage: -d arg[,arg]* and arg is <key>[=<value>]
177-
178-
<key> is one of:
179-
180-
`
181-
182-
const debugHelpFooter = `
183-
<value> is key-specific.
184-
185-
Key "checkptr" supports values:
186-
"0": instrumentation disabled
187-
"1": conversions involving unsafe.Pointer are instrumented
188-
"2": conversions to unsafe.Pointer force heap allocation
189-
190-
Key "pctab" supports values:
191-
"pctospadj", "pctofile", "pctoline", "pctoinline", "pctopcdata"
192-
`

src/cmd/compile/internal/base/flag.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,19 @@ type CmdFlags struct {
6464
// V is added by objabi.AddVersionFlag
6565
W CountFlag "help:\"debug parse tree after type checking\""
6666

67-
LowerC int "help:\"concurrency during compilation (1 means no concurrency)\""
68-
LowerD func(string) "help:\"enable debugging settings; try -d help\""
69-
LowerE CountFlag "help:\"no limit on number of errors reported\""
70-
LowerH CountFlag "help:\"halt on error\""
71-
LowerJ CountFlag "help:\"debug runtime-initialized variables\""
72-
LowerL CountFlag "help:\"disable inlining\""
73-
LowerM CountFlag "help:\"print optimization decisions\""
74-
LowerO string "help:\"write output to `file`\""
75-
LowerP *string "help:\"set expected package import `path`\"" // &Ctxt.Pkgpath, set below
76-
LowerR CountFlag "help:\"debug generated wrappers\""
77-
LowerT bool "help:\"enable tracing for debugging the compiler\""
78-
LowerW CountFlag "help:\"debug type checking\""
79-
LowerV *bool "help:\"increase debug verbosity\""
67+
LowerC int "help:\"concurrency during compilation (1 means no concurrency)\""
68+
LowerD flag.Value "help:\"enable debugging settings; try -d help\""
69+
LowerE CountFlag "help:\"no limit on number of errors reported\""
70+
LowerH CountFlag "help:\"halt on error\""
71+
LowerJ CountFlag "help:\"debug runtime-initialized variables\""
72+
LowerL CountFlag "help:\"disable inlining\""
73+
LowerM CountFlag "help:\"print optimization decisions\""
74+
LowerO string "help:\"write output to `file`\""
75+
LowerP *string "help:\"set expected package import `path`\"" // &Ctxt.Pkgpath, set below
76+
LowerR CountFlag "help:\"debug generated wrappers\""
77+
LowerT bool "help:\"enable tracing for debugging the compiler\""
78+
LowerW CountFlag "help:\"debug type checking\""
79+
LowerV *bool "help:\"increase debug verbosity\""
8080

8181
// Special characters
8282
Percent int "flag:\"%\" help:\"debug non-static initializers\""
@@ -145,7 +145,7 @@ func ParseFlags() {
145145
Flag.I = addImportDir
146146

147147
Flag.LowerC = 1
148-
Flag.LowerD = parseDebug
148+
Flag.LowerD = objabi.NewDebugFlag(&Debug, DebugSSA)
149149
Flag.LowerP = &Ctxt.Pkgpath
150150
Flag.LowerV = &Ctxt.Debugvlog
151151

@@ -331,7 +331,11 @@ func registerFlags() {
331331
f := v.Field(i).Interface().(func(string))
332332
objabi.Flagfn1(name, help, f)
333333
default:
334-
panic(fmt.Sprintf("base.Flag.%s has unexpected type %s", f.Name, f.Type))
334+
if val, ok := v.Field(i).Interface().(flag.Value); ok {
335+
flag.Var(val, name, help)
336+
} else {
337+
panic(fmt.Sprintf("base.Flag.%s has unexpected type %s", f.Name, f.Type))
338+
}
335339
}
336340
}
337341
}
@@ -359,7 +363,7 @@ func concurrentBackendAllowed() bool {
359363
// while writing the object file, and that is non-concurrent.
360364
// Adding Debug_vlog, however, causes Debug.S to also print
361365
// while flushing the plist, which happens concurrently.
362-
if Ctxt.Debugvlog || Debug.Any() || Flag.Live > 0 {
366+
if Ctxt.Debugvlog || Debug.Any || Flag.Live > 0 {
363367
return false
364368
}
365369
// TODO: Test and delete this condition.

0 commit comments

Comments
 (0)