Flag.Shared = &Ctxt.Flag_shared
Flag.WB = true
+ Debug.ConcurrentOk = true
Debug.InlFuncsWithClosures = 1
if buildcfg.Experiment.Unified {
Debug.Unified = 1
// while writing the object file, and that is non-concurrent.
// Adding Debug_vlog, however, causes Debug.S to also print
// while flushing the plist, which happens concurrently.
- if Ctxt.Debugvlog || Debug.Any || Flag.Live > 0 {
+ if Ctxt.Debugvlog || !Debug.ConcurrentOk || Flag.Live > 0 {
return false
}
// TODO: Test and delete this condition.
}
type debugField struct {
- name string
- help string
- val interface{} // *int or *string
+ name string
+ help string
+ concurrentOk bool // true if this field/flag is compatible with concurrent compilation
+ val interface{} // *int or *string
}
type DebugFlag struct {
- tab map[string]debugField
- any *bool
-
- debugSSA DebugSSA
+ tab map[string]debugField
+ concurrentOk *bool // this is non-nil only for compiler's DebugFlags, but only compiler has concurrent:ok fields
+ debugSSA DebugSSA // this is non-nil only for compiler's DebugFlags.
}
// A DebugSSA function is called to set a -d ssa/... option.
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
ptr := v.Field(i).Addr().Interface()
- if f.Name == "Any" {
+ if f.Name == "ConcurrentOk" {
switch ptr := ptr.(type) {
default:
- panic("debug.Any must have type bool")
+ panic("debug.ConcurrentOk must have type bool")
case *bool:
- flag.any = ptr
+ flag.concurrentOk = ptr
}
continue
}
if help == "" {
panic(fmt.Sprintf("debug.%s is missing help text", f.Name))
}
+ concurrent := f.Tag.Get("concurrent")
+
switch ptr.(type) {
default:
panic(fmt.Sprintf("debug.%s has invalid type %v (must be int or string)", f.Name, f.Type))
case *int, *string:
// ok
}
- flag.tab[name] = debugField{name, help, ptr}
+ flag.tab[name] = debugField{name, help, concurrent == "ok", ptr}
}
return flag
if debugstr == "" {
return nil
}
- if f.any != nil {
- *f.any = true
- }
for _, name := range strings.Split(debugstr, ",") {
if name == "" {
continue
default:
panic("bad debugtab type")
}
+ // assembler DebugFlags don't have a ConcurrentOk field to reset, so check against that.
+ if !t.concurrentOk && f.concurrentOk != nil {
+ *f.concurrentOk = false
+ }
} else if f.debugSSA != nil && strings.HasPrefix(name, "ssa/") {
// expect form ssa/phase/flag
// e.g. -d=ssa/generic_cse/time
if err != "" {
log.Fatalf(err)
}
+ // Setting this false for -d=ssa/... preserves old behavior
+ // of turning off concurrency for any debug flags.
+ // It's not known for sure if this is necessary, but it is safe.
+ *f.concurrentOk = false
+
} else {
return fmt.Errorf("unknown debug key %s\n", name)
}