// 6. gossahash should return a single function whose miscompilation
// causes the problem, and you can focus on that.
func DebugHashMatchPkgFunc(pkg, fn string) bool {
- return hashDebug.MatchPkgFunc(pkg, fn)
+ return hashDebug.MatchPkgFunc(pkg, fn, nil)
}
func DebugHashMatchPos(pos src.XPos) bool {
- return hashDebug.MatchPos(pos)
+ return hashDebug.MatchPos(pos, nil)
}
// HasDebugHash returns true if Flags.Gossahash is non-empty, which
// representation of the hash of pkg and fn. If the variable is not nil,
// then a true result is accompanied by stylized output to d.logfile, which
// is used for automated bug search.
-func (d *HashDebug) MatchPkgFunc(pkg, fn string) bool {
+func (d *HashDebug) MatchPkgFunc(pkg, fn string, note func() string) bool {
if d == nil {
return true
}
// Written this way to make inlining likely.
- return d.matchPkgFunc(pkg, fn)
+ return d.matchPkgFunc(pkg, fn, note)
}
-func (d *HashDebug) matchPkgFunc(pkg, fn string) bool {
+func (d *HashDebug) matchPkgFunc(pkg, fn string, note func() string) bool {
hash := bisect.Hash(pkg, fn)
- if d.bisect != nil {
- if d.bisect.ShouldPrint(hash) {
- d.log(d.name, hash, pkg+"."+fn)
- }
- return d.bisect.ShouldEnable(hash)
- }
-
- // TODO: Delete rest of function body when we switch to bisect-only.
- if m := d.match(hash); m != nil {
- d.log(m.name, hash, pkg+"."+fn)
- return true
- }
- return false
+ return d.matchAndLog(hash, func() string { return pkg + "." + fn }, note)
}
// MatchPos is similar to MatchPkgFunc, but for hash computation
// package name and path.
// Note that the default answer for no environment variable (d == nil)
// is "yes", do the thing.
-func (d *HashDebug) MatchPos(pos src.XPos) bool {
+func (d *HashDebug) MatchPos(pos src.XPos, desc func() string) bool {
if d == nil {
return true
}
// Written this way to make inlining likely.
- return d.matchPos(Ctxt, pos)
+ return d.matchPos(Ctxt, pos, desc)
}
-func (d *HashDebug) matchPos(ctxt *obj.Link, pos src.XPos) bool {
+func (d *HashDebug) matchPos(ctxt *obj.Link, pos src.XPos, note func() string) bool {
hash := d.hashPos(ctxt, pos)
+ return d.matchAndLog(hash, func() string { return d.fmtPos(ctxt, pos) }, note)
+}
+// matchAndLog is the core matcher. It reports whether the hash matches the pattern.
+// If a report needs to be printed, match prints that report to the log file.
+// The text func must be non-nil and should return a user-readable
+// representation of what was hashed. The note func may be nil; if non-nil,
+// it should return additional information to display to the user when this
+// change is selected.
+func (d *HashDebug) matchAndLog(hash uint64, text, note func() string) bool {
if d.bisect != nil {
if d.bisect.ShouldPrint(hash) {
- d.log(d.name, hash, d.fmtPos(ctxt, pos))
+ var t string
+ if !d.bisect.MarkerOnly() {
+ t = text()
+ if note != nil {
+ if n := note(); n != "" {
+ t += ": " + n
+ }
+ }
+ }
+ d.log(d.name, hash, t)
}
return d.bisect.ShouldEnable(hash)
}
// TODO: Delete rest of function body when we switch to bisect-only.
-
- // Return false for explicitly excluded hashes
if d.excluded(hash) {
return false
}
if m := d.match(hash); m != nil {
- d.log(m.name, hash, d.fmtPos(ctxt, pos))
+ d.log(m.name, hash, text())
return true
}
return false
if hd == nil {
t.Errorf("NewHashDebug should not return nil for GOSSASHASH=y")
}
- if !hd.MatchPkgFunc("anything", "anyfunc") {
+ if !hd.MatchPkgFunc("anything", "anyfunc", nil) {
t.Errorf("NewHashDebug should return yes for everything for GOSSASHASH=y")
}
}
if hd == nil {
t.Errorf("NewHashDebug should not return nil for GOSSASHASH=n")
}
- if hd.MatchPkgFunc("anything", "anyfunc") {
+ if hd.MatchPkgFunc("anything", "anyfunc", nil) {
t.Errorf("NewHashDebug should return no for everything for GOSSASHASH=n")
}
}
func TestHashMatch(t *testing.T) {
b := new(bytes.Buffer)
- hd := NewHashDebug("GOSSAHASH", "1110", b)
- check := hd.MatchPkgFunc("bar", "0")
+ hd := NewHashDebug("GOSSAHASH", "v1110", b)
+ check := hd.MatchPkgFunc("bar", "0", func() string { return "note" })
msg := b.String()
t.Logf("message was '%s'", msg)
if !check {
t.Errorf("GOSSAHASH=1110 should have matched for 'bar', '0'")
}
- wantPrefix(t, msg, "bar.0 [bisect-match ")
- wantContains(t, msg, "\nGOSSAHASH triggered bar.0 ")
+ wantPrefix(t, msg, "bar.0: note [bisect-match ")
+ wantContains(t, msg, "\nGOSSAHASH triggered bar.0: note ")
}
func TestYMatch(t *testing.T) {
b := new(bytes.Buffer)
- hd := NewHashDebug("GOSSAHASH", "y", b)
- check := hd.MatchPkgFunc("bar", "0")
+ hd := NewHashDebug("GOSSAHASH", "vy", b)
+ check := hd.MatchPkgFunc("bar", "0", nil)
msg := b.String()
t.Logf("message was '%s'", msg)
if !check {
func TestNMatch(t *testing.T) {
b := new(bytes.Buffer)
- hd := NewHashDebug("GOSSAHASH", "n", b)
- check := hd.MatchPkgFunc("bar", "0")
+ hd := NewHashDebug("GOSSAHASH", "vn", b)
+ check := hd.MatchPkgFunc("bar", "0", nil)
msg := b.String()
t.Logf("message was '%s'", msg)
if check {
func TestHashNoMatch(t *testing.T) {
b := new(bytes.Buffer)
hd := NewHashDebug("GOSSAHASH", "01110", b)
- check := hd.MatchPkgFunc("bar", "0")
+ check := hd.MatchPkgFunc("bar", "0", nil)
msg := b.String()
t.Logf("message was '%s'", msg)
if check {
b := new(bytes.Buffer)
hd := NewHashDebug("GOSSAHASH", "01110/11110", b)
- check := hd.MatchPkgFunc("bar", "0")
+ check := hd.MatchPkgFunc("bar", "0", nil)
msg := b.String()
t.Logf("message was '%s'", msg)
if !check {
// subject to hash-variable debugging.
maybeReplaceVar := func(k ir.Node, x *ir.RangeStmt) ir.Node {
if n, ok := k.(*ir.Name); ok && possiblyLeaked[n] {
- if base.LoopVarHash.MatchPos(n.Pos()) {
+ if base.LoopVarHash.MatchPos(n.Pos(), nil) {
// Rename the loop key, prefix body with assignment from loop key
transformed = append(transformed, VarAndLoop{n, x, lastPos})
tk := typecheck.Temp(n.Type())
forAllDefInInit(x, func(z ir.Node) {
if n, ok := z.(*ir.Name); ok && possiblyLeaked[n] {
// Hash on n.Pos() for most precise failure location.
- if base.LoopVarHash.MatchPos(n.Pos()) {
+ if base.LoopVarHash.MatchPos(n.Pos(), nil) {
leaked = append(leaked, n)
}
}
return string(b)
}
- m := f("001100110110110010100100")
+ m := f("v001100110110110010100100")
t.Logf(m)
mCount := strings.Count(m, "loopvarhash triggered cmd/compile/internal/loopvar/testdata/inlines/main.go:27:6 001100110110110010100100")
if base.FmaHash == nil {
return true
}
- return base.FmaHash.MatchPos(v.Pos)
+ return base.FmaHash.MatchPos(v.Pos, nil)
}