55package ssa
66
77import (
8+ "cmd/compile/internal/base"
89 "cmd/internal/src"
910 "fmt"
1011 "hash/crc32"
@@ -17,7 +18,9 @@ import (
1718 "regexp"
1819 "runtime"
1920 "sort"
21+ "strconv"
2022 "strings"
23+ "sync"
2124 "time"
2225)
2326
@@ -202,12 +205,14 @@ type pass struct {
202205 fn func (* Func )
203206 required bool
204207 disabled bool
205- time bool // report time to run pass
206- mem bool // report mem stats to run pass
207- stats int // pass reports own "stats" (e.g., branches removed)
208- debug int // pass performs some debugging. =1 should be in error-testing-friendly Warnl format.
209- test int // pass-specific ad-hoc option, perhaps useful in development
210- dump map [string ]bool // dump if function name matches
208+ time bool // report time to run pass
209+ mem bool // report mem stats to run pass
210+ stats int // pass reports own "stats" (e.g., branches removed)
211+ debug int // pass performs some debugging. =1 should be in error-testing-friendly Warnl format.
212+ test int // pass-specific ad-hoc option, perhaps useful in development
213+ dump map [string ]bool // dump if function name matches
214+ keywords map [string ]int64 // ad hoc parameters, typically for experiments/tuning
215+ usedKW map [string ]bool // if a keyword is supplied to a phase, note that it was used.
211216}
212217
213218func (p * pass ) addDump (s string ) {
@@ -224,6 +229,21 @@ func (p *pass) String() string {
224229 return p .name
225230}
226231
232+ var kwMu sync.Mutex
233+
234+ func (p * pass ) Val (kw string , ifUnset int64 ) int64 {
235+ if p == nil || p .keywords == nil {
236+ return ifUnset
237+ }
238+ if v , ok := p .keywords [kw ]; ok {
239+ kwMu .Lock ()
240+ p .usedKW [kw ] = true
241+ kwMu .Unlock ()
242+ return v
243+ }
244+ return ifUnset
245+ }
246+
227247// Run consistency checker between each phase
228248var (
229249 checkEnabled = false
@@ -283,7 +303,7 @@ where:
283303` + phasenames + `
284304
285305- <flag> is one of:
286- on, off, debug, mem, time, test, stats, dump, seed
306+ on, off, debug, mem, time, test, stats, dump, seed, @<keyword>
287307
288308- <value> defaults to 1
289309
@@ -438,7 +458,19 @@ commas. For example:
438458 case "dump" :
439459 p .addDump (valString )
440460 default :
441- return fmt .Sprintf ("Did not find a flag matching %s in -d=ssa/%s debug option" , flag , phase )
461+ if flag != "" && flag [0 ] == '@' {
462+ if p .keywords == nil {
463+ p .keywords = make (map [string ]int64 )
464+ p .usedKW = make (map [string ]bool )
465+ }
466+ val64 , err := strconv .ParseInt (valString , 10 , 64 )
467+ if err != nil {
468+ return fmt .Sprintf ("Failed to parse %s as integer value in -d=ssa/%s/%s=%s option" , valString , phase , flag , valString )
469+ }
470+ p .keywords [flag [1 :]] = int64 (val64 )
471+ } else {
472+ return fmt .Sprintf ("Did not find a flag matching %s in -d=ssa/%s debug option" , flag , phase )
473+ }
442474 }
443475 if p .disabled && p .required {
444476 return fmt .Sprintf ("Cannot disable required SSA phase %s using -d=ssa/%s debug option" , phase , phase )
@@ -612,6 +644,20 @@ var passOrder = [...]constraint{
612644 {"prove" , "known bits" },
613645}
614646
647+ func PostCompile () {
648+ for _ , c := range passes {
649+ if c .keywords != nil {
650+ for k := range c .keywords {
651+ if ! c .usedKW [k ] {
652+ // If someone specified a debugging keyword that was not
653+ // consumed, they might want to know about this.
654+ base .Warn ("Keyword %s for pass %s was not used" , k , c .name )
655+ }
656+ }
657+ }
658+ }
659+ }
660+
615661func init () {
616662 for _ , c := range passOrder {
617663 a , b := c .a , c .b
0 commit comments