Home | History | Annotate | Download | only in ssa
      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package ssa
      6 
      7 import (
      8 	"cmd/compile/internal/types"
      9 	"cmd/internal/src"
     10 	"crypto/sha1"
     11 	"fmt"
     12 	"io"
     13 	"math"
     14 	"os"
     15 	"strings"
     16 )
     17 
     18 type writeSyncer interface {
     19 	io.Writer
     20 	Sync() error
     21 }
     22 
     23 // A Func represents a Go func declaration (or function literal) and its body.
     24 // This package compiles each Func independently.
     25 // Funcs are single-use; a new Func must be created for every compiled function.
     26 type Func struct {
     27 	Config *Config     // architecture information
     28 	Cache  *Cache      // re-usable cache
     29 	fe     Frontend    // frontend state associated with this Func, callbacks into compiler frontend
     30 	pass   *pass       // current pass information (name, options, etc.)
     31 	Name   string      // e.g. bytesCompare
     32 	Type   *types.Type // type signature of the function.
     33 	Blocks []*Block    // unordered set of all basic blocks (note: not indexable by ID)
     34 	Entry  *Block      // the entry basic block
     35 	bid    idAlloc     // block ID allocator
     36 	vid    idAlloc     // value ID allocator
     37 
     38 	// Given an environment variable used for debug hash match,
     39 	// what file (if any) receives the yes/no logging?
     40 	logfiles   map[string]writeSyncer
     41 	HTMLWriter *HTMLWriter // html writer, for debugging
     42 	DebugTest  bool        // default true unless $GOSSAHASH != ""; as a debugging aid, make new code conditional on this and use GOSSAHASH to binary search for failing cases
     43 
     44 	scheduled bool // Values in Blocks are in final order
     45 	NoSplit   bool // true if function is marked as nosplit.  Used by schedule check pass.
     46 
     47 	// when register allocation is done, maps value ids to locations
     48 	RegAlloc []Location
     49 
     50 	// map from LocalSlot to set of Values that we want to store in that slot.
     51 	NamedValues map[LocalSlot][]*Value
     52 	// Names is a copy of NamedValues.Keys. We keep a separate list
     53 	// of keys to make iteration order deterministic.
     54 	Names []LocalSlot
     55 
     56 	freeValues *Value // free Values linked by argstorage[0].  All other fields except ID are 0/nil.
     57 	freeBlocks *Block // free Blocks linked by succstorage[0].b.  All other fields except ID are 0/nil.
     58 
     59 	cachedPostorder []*Block   // cached postorder traversal
     60 	cachedIdom      []*Block   // cached immediate dominators
     61 	cachedSdom      SparseTree // cached dominator tree
     62 	cachedLoopnest  *loopnest  // cached loop nest information
     63 
     64 	auxmap auxmap // map from aux values to opaque ids used by CSE
     65 
     66 	constants map[int64][]*Value // constants cache, keyed by constant value; users must check value's Op and Type
     67 }
     68 
     69 // NewFunc returns a new, empty function object.
     70 // Caller must set f.Config and f.Cache before using f.
     71 func NewFunc(fe Frontend) *Func {
     72 	return &Func{fe: fe, NamedValues: make(map[LocalSlot][]*Value)}
     73 }
     74 
     75 // NumBlocks returns an integer larger than the id of any Block in the Func.
     76 func (f *Func) NumBlocks() int {
     77 	return f.bid.num()
     78 }
     79 
     80 // NumValues returns an integer larger than the id of any Value in the Func.
     81 func (f *Func) NumValues() int {
     82 	return f.vid.num()
     83 }
     84 
     85 // newSparseSet returns a sparse set that can store at least up to n integers.
     86 func (f *Func) newSparseSet(n int) *sparseSet {
     87 	for i, scr := range f.Cache.scrSparse {
     88 		if scr != nil && scr.cap() >= n {
     89 			f.Cache.scrSparse[i] = nil
     90 			scr.clear()
     91 			return scr
     92 		}
     93 	}
     94 	return newSparseSet(n)
     95 }
     96 
     97 // retSparseSet returns a sparse set to the config's cache of sparse sets to be reused by f.newSparseSet.
     98 func (f *Func) retSparseSet(ss *sparseSet) {
     99 	for i, scr := range f.Cache.scrSparse {
    100 		if scr == nil {
    101 			f.Cache.scrSparse[i] = ss
    102 			return
    103 		}
    104 	}
    105 	f.Cache.scrSparse = append(f.Cache.scrSparse, ss)
    106 }
    107 
    108 // newValue allocates a new Value with the given fields and places it at the end of b.Values.
    109 func (f *Func) newValue(op Op, t *types.Type, b *Block, pos src.XPos) *Value {
    110 	var v *Value
    111 	if f.freeValues != nil {
    112 		v = f.freeValues
    113 		f.freeValues = v.argstorage[0]
    114 		v.argstorage[0] = nil
    115 	} else {
    116 		ID := f.vid.get()
    117 		if int(ID) < len(f.Cache.values) {
    118 			v = &f.Cache.values[ID]
    119 			v.ID = ID
    120 		} else {
    121 			v = &Value{ID: ID}
    122 		}
    123 	}
    124 	v.Op = op
    125 	v.Type = t
    126 	v.Block = b
    127 	v.Pos = pos
    128 	b.Values = append(b.Values, v)
    129 	return v
    130 }
    131 
    132 // newValueNoBlock allocates a new Value with the given fields.
    133 // The returned value is not placed in any block.  Once the caller
    134 // decides on a block b, it must set b.Block and append
    135 // the returned value to b.Values.
    136 func (f *Func) newValueNoBlock(op Op, t *types.Type, pos src.XPos) *Value {
    137 	var v *Value
    138 	if f.freeValues != nil {
    139 		v = f.freeValues
    140 		f.freeValues = v.argstorage[0]
    141 		v.argstorage[0] = nil
    142 	} else {
    143 		ID := f.vid.get()
    144 		if int(ID) < len(f.Cache.values) {
    145 			v = &f.Cache.values[ID]
    146 			v.ID = ID
    147 		} else {
    148 			v = &Value{ID: ID}
    149 		}
    150 	}
    151 	v.Op = op
    152 	v.Type = t
    153 	v.Block = nil // caller must fix this.
    154 	v.Pos = pos
    155 	return v
    156 }
    157 
    158 // logPassStat writes a string key and int value as a warning in a
    159 // tab-separated format easily handled by spreadsheets or awk.
    160 // file names, lines, and function names are included to provide enough (?)
    161 // context to allow item-by-item comparisons across runs.
    162 // For example:
    163 // awk 'BEGIN {FS="\t"} $3~/TIME/{sum+=$4} END{print "t(ns)=",sum}' t.log
    164 func (f *Func) LogStat(key string, args ...interface{}) {
    165 	value := ""
    166 	for _, a := range args {
    167 		value += fmt.Sprintf("\t%v", a)
    168 	}
    169 	n := "missing_pass"
    170 	if f.pass != nil {
    171 		n = strings.Replace(f.pass.name, " ", "_", -1)
    172 	}
    173 	f.Warnl(f.Entry.Pos, "\t%s\t%s%s\t%s", n, key, value, f.Name)
    174 }
    175 
    176 // freeValue frees a value. It must no longer be referenced or have any args.
    177 func (f *Func) freeValue(v *Value) {
    178 	if v.Block == nil {
    179 		f.Fatalf("trying to free an already freed value")
    180 	}
    181 	if v.Uses != 0 {
    182 		f.Fatalf("value %s still has %d uses", v, v.Uses)
    183 	}
    184 	if len(v.Args) != 0 {
    185 		f.Fatalf("value %s still has %d args", v, len(v.Args))
    186 	}
    187 	// Clear everything but ID (which we reuse).
    188 	id := v.ID
    189 
    190 	// Values with zero arguments and OpOffPtr values might be cached, so remove them there.
    191 	nArgs := opcodeTable[v.Op].argLen
    192 	if nArgs == 0 || v.Op == OpOffPtr {
    193 		vv := f.constants[v.AuxInt]
    194 		for i, cv := range vv {
    195 			if v == cv {
    196 				vv[i] = vv[len(vv)-1]
    197 				vv[len(vv)-1] = nil
    198 				f.constants[v.AuxInt] = vv[0 : len(vv)-1]
    199 				break
    200 			}
    201 		}
    202 	}
    203 	*v = Value{}
    204 	v.ID = id
    205 	v.argstorage[0] = f.freeValues
    206 	f.freeValues = v
    207 }
    208 
    209 // newBlock allocates a new Block of the given kind and places it at the end of f.Blocks.
    210 func (f *Func) NewBlock(kind BlockKind) *Block {
    211 	var b *Block
    212 	if f.freeBlocks != nil {
    213 		b = f.freeBlocks
    214 		f.freeBlocks = b.succstorage[0].b
    215 		b.succstorage[0].b = nil
    216 	} else {
    217 		ID := f.bid.get()
    218 		if int(ID) < len(f.Cache.blocks) {
    219 			b = &f.Cache.blocks[ID]
    220 			b.ID = ID
    221 		} else {
    222 			b = &Block{ID: ID}
    223 		}
    224 	}
    225 	b.Kind = kind
    226 	b.Func = f
    227 	b.Preds = b.predstorage[:0]
    228 	b.Succs = b.succstorage[:0]
    229 	b.Values = b.valstorage[:0]
    230 	f.Blocks = append(f.Blocks, b)
    231 	f.invalidateCFG()
    232 	return b
    233 }
    234 
    235 func (f *Func) freeBlock(b *Block) {
    236 	if b.Func == nil {
    237 		f.Fatalf("trying to free an already freed block")
    238 	}
    239 	// Clear everything but ID (which we reuse).
    240 	id := b.ID
    241 	*b = Block{}
    242 	b.ID = id
    243 	b.succstorage[0].b = f.freeBlocks
    244 	f.freeBlocks = b
    245 }
    246 
    247 // NewValue0 returns a new value in the block with no arguments and zero aux values.
    248 func (b *Block) NewValue0(pos src.XPos, op Op, t *types.Type) *Value {
    249 	v := b.Func.newValue(op, t, b, pos)
    250 	v.AuxInt = 0
    251 	v.Args = v.argstorage[:0]
    252 	return v
    253 }
    254 
    255 // NewValue returns a new value in the block with no arguments and an auxint value.
    256 func (b *Block) NewValue0I(pos src.XPos, op Op, t *types.Type, auxint int64) *Value {
    257 	v := b.Func.newValue(op, t, b, pos)
    258 	v.AuxInt = auxint
    259 	v.Args = v.argstorage[:0]
    260 	return v
    261 }
    262 
    263 // NewValue returns a new value in the block with no arguments and an aux value.
    264 func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux interface{}) *Value {
    265 	if _, ok := aux.(int64); ok {
    266 		// Disallow int64 aux values. They should be in the auxint field instead.
    267 		// Maybe we want to allow this at some point, but for now we disallow it
    268 		// to prevent errors like using NewValue1A instead of NewValue1I.
    269 		b.Fatalf("aux field has int64 type op=%s type=%s aux=%v", op, t, aux)
    270 	}
    271 	v := b.Func.newValue(op, t, b, pos)
    272 	v.AuxInt = 0
    273 	v.Aux = aux
    274 	v.Args = v.argstorage[:0]
    275 	return v
    276 }
    277 
    278 // NewValue returns a new value in the block with no arguments and both an auxint and aux values.
    279 func (b *Block) NewValue0IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}) *Value {
    280 	v := b.Func.newValue(op, t, b, pos)
    281 	v.AuxInt = auxint
    282 	v.Aux = aux
    283 	v.Args = v.argstorage[:0]
    284 	return v
    285 }
    286 
    287 // NewValue1 returns a new value in the block with one argument and zero aux values.
    288 func (b *Block) NewValue1(pos src.XPos, op Op, t *types.Type, arg *Value) *Value {
    289 	v := b.Func.newValue(op, t, b, pos)
    290 	v.AuxInt = 0
    291 	v.Args = v.argstorage[:1]
    292 	v.argstorage[0] = arg
    293 	arg.Uses++
    294 	return v
    295 }
    296 
    297 // NewValue1I returns a new value in the block with one argument and an auxint value.
    298 func (b *Block) NewValue1I(pos src.XPos, op Op, t *types.Type, auxint int64, arg *Value) *Value {
    299 	v := b.Func.newValue(op, t, b, pos)
    300 	v.AuxInt = auxint
    301 	v.Args = v.argstorage[:1]
    302 	v.argstorage[0] = arg
    303 	arg.Uses++
    304 	return v
    305 }
    306 
    307 // NewValue1A returns a new value in the block with one argument and an aux value.
    308 func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg *Value) *Value {
    309 	v := b.Func.newValue(op, t, b, pos)
    310 	v.AuxInt = 0
    311 	v.Aux = aux
    312 	v.Args = v.argstorage[:1]
    313 	v.argstorage[0] = arg
    314 	arg.Uses++
    315 	return v
    316 }
    317 
    318 // NewValue1IA returns a new value in the block with one argument and both an auxint and aux values.
    319 func (b *Block) NewValue1IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}, arg *Value) *Value {
    320 	v := b.Func.newValue(op, t, b, pos)
    321 	v.AuxInt = auxint
    322 	v.Aux = aux
    323 	v.Args = v.argstorage[:1]
    324 	v.argstorage[0] = arg
    325 	arg.Uses++
    326 	return v
    327 }
    328 
    329 // NewValue2 returns a new value in the block with two arguments and zero aux values.
    330 func (b *Block) NewValue2(pos src.XPos, op Op, t *types.Type, arg0, arg1 *Value) *Value {
    331 	v := b.Func.newValue(op, t, b, pos)
    332 	v.AuxInt = 0
    333 	v.Args = v.argstorage[:2]
    334 	v.argstorage[0] = arg0
    335 	v.argstorage[1] = arg1
    336 	arg0.Uses++
    337 	arg1.Uses++
    338 	return v
    339 }
    340 
    341 // NewValue2I returns a new value in the block with two arguments and an auxint value.
    342 func (b *Block) NewValue2I(pos src.XPos, op Op, t *types.Type, auxint int64, arg0, arg1 *Value) *Value {
    343 	v := b.Func.newValue(op, t, b, pos)
    344 	v.AuxInt = auxint
    345 	v.Args = v.argstorage[:2]
    346 	v.argstorage[0] = arg0
    347 	v.argstorage[1] = arg1
    348 	arg0.Uses++
    349 	arg1.Uses++
    350 	return v
    351 }
    352 
    353 // NewValue3 returns a new value in the block with three arguments and zero aux values.
    354 func (b *Block) NewValue3(pos src.XPos, op Op, t *types.Type, arg0, arg1, arg2 *Value) *Value {
    355 	v := b.Func.newValue(op, t, b, pos)
    356 	v.AuxInt = 0
    357 	v.Args = v.argstorage[:3]
    358 	v.argstorage[0] = arg0
    359 	v.argstorage[1] = arg1
    360 	v.argstorage[2] = arg2
    361 	arg0.Uses++
    362 	arg1.Uses++
    363 	arg2.Uses++
    364 	return v
    365 }
    366 
    367 // NewValue3I returns a new value in the block with three arguments and an auxint value.
    368 func (b *Block) NewValue3I(pos src.XPos, op Op, t *types.Type, auxint int64, arg0, arg1, arg2 *Value) *Value {
    369 	v := b.Func.newValue(op, t, b, pos)
    370 	v.AuxInt = auxint
    371 	v.Args = v.argstorage[:3]
    372 	v.argstorage[0] = arg0
    373 	v.argstorage[1] = arg1
    374 	v.argstorage[2] = arg2
    375 	arg0.Uses++
    376 	arg1.Uses++
    377 	arg2.Uses++
    378 	return v
    379 }
    380 
    381 // NewValue3A returns a new value in the block with three argument and an aux value.
    382 func (b *Block) NewValue3A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *Value) *Value {
    383 	v := b.Func.newValue(op, t, b, pos)
    384 	v.AuxInt = 0
    385 	v.Aux = aux
    386 	v.Args = v.argstorage[:3]
    387 	v.argstorage[0] = arg0
    388 	v.argstorage[1] = arg1
    389 	v.argstorage[2] = arg2
    390 	arg0.Uses++
    391 	arg1.Uses++
    392 	arg2.Uses++
    393 	return v
    394 }
    395 
    396 // NewValue4 returns a new value in the block with four arguments and zero aux values.
    397 func (b *Block) NewValue4(pos src.XPos, op Op, t *types.Type, arg0, arg1, arg2, arg3 *Value) *Value {
    398 	v := b.Func.newValue(op, t, b, pos)
    399 	v.AuxInt = 0
    400 	v.Args = []*Value{arg0, arg1, arg2, arg3}
    401 	arg0.Uses++
    402 	arg1.Uses++
    403 	arg2.Uses++
    404 	arg3.Uses++
    405 	return v
    406 }
    407 
    408 // constVal returns a constant value for c.
    409 func (f *Func) constVal(pos src.XPos, op Op, t *types.Type, c int64, setAuxInt bool) *Value {
    410 	// TODO remove unused pos parameter, both here and in *func.ConstXXX callers.
    411 	if f.constants == nil {
    412 		f.constants = make(map[int64][]*Value)
    413 	}
    414 	vv := f.constants[c]
    415 	for _, v := range vv {
    416 		if v.Op == op && v.Type.Compare(t) == types.CMPeq {
    417 			if setAuxInt && v.AuxInt != c {
    418 				panic(fmt.Sprintf("cached const %s should have AuxInt of %d", v.LongString(), c))
    419 			}
    420 			return v
    421 		}
    422 	}
    423 	var v *Value
    424 	if setAuxInt {
    425 		v = f.Entry.NewValue0I(src.NoXPos, op, t, c)
    426 	} else {
    427 		v = f.Entry.NewValue0(src.NoXPos, op, t)
    428 	}
    429 	f.constants[c] = append(vv, v)
    430 	return v
    431 }
    432 
    433 // These magic auxint values let us easily cache non-numeric constants
    434 // using the same constants map while making collisions unlikely.
    435 // These values are unlikely to occur in regular code and
    436 // are easy to grep for in case of bugs.
    437 const (
    438 	constSliceMagic       = 1122334455
    439 	constInterfaceMagic   = 2233445566
    440 	constNilMagic         = 3344556677
    441 	constEmptyStringMagic = 4455667788
    442 )
    443 
    444 // ConstInt returns an int constant representing its argument.
    445 func (f *Func) ConstBool(pos src.XPos, t *types.Type, c bool) *Value {
    446 	i := int64(0)
    447 	if c {
    448 		i = 1
    449 	}
    450 	return f.constVal(pos, OpConstBool, t, i, true)
    451 }
    452 func (f *Func) ConstInt8(pos src.XPos, t *types.Type, c int8) *Value {
    453 	return f.constVal(pos, OpConst8, t, int64(c), true)
    454 }
    455 func (f *Func) ConstInt16(pos src.XPos, t *types.Type, c int16) *Value {
    456 	return f.constVal(pos, OpConst16, t, int64(c), true)
    457 }
    458 func (f *Func) ConstInt32(pos src.XPos, t *types.Type, c int32) *Value {
    459 	return f.constVal(pos, OpConst32, t, int64(c), true)
    460 }
    461 func (f *Func) ConstInt64(pos src.XPos, t *types.Type, c int64) *Value {
    462 	return f.constVal(pos, OpConst64, t, c, true)
    463 }
    464 func (f *Func) ConstFloat32(pos src.XPos, t *types.Type, c float64) *Value {
    465 	return f.constVal(pos, OpConst32F, t, int64(math.Float64bits(float64(float32(c)))), true)
    466 }
    467 func (f *Func) ConstFloat64(pos src.XPos, t *types.Type, c float64) *Value {
    468 	return f.constVal(pos, OpConst64F, t, int64(math.Float64bits(c)), true)
    469 }
    470 
    471 func (f *Func) ConstSlice(pos src.XPos, t *types.Type) *Value {
    472 	return f.constVal(pos, OpConstSlice, t, constSliceMagic, false)
    473 }
    474 func (f *Func) ConstInterface(pos src.XPos, t *types.Type) *Value {
    475 	return f.constVal(pos, OpConstInterface, t, constInterfaceMagic, false)
    476 }
    477 func (f *Func) ConstNil(pos src.XPos, t *types.Type) *Value {
    478 	return f.constVal(pos, OpConstNil, t, constNilMagic, false)
    479 }
    480 func (f *Func) ConstEmptyString(pos src.XPos, t *types.Type) *Value {
    481 	v := f.constVal(pos, OpConstString, t, constEmptyStringMagic, false)
    482 	v.Aux = ""
    483 	return v
    484 }
    485 func (f *Func) ConstOffPtrSP(pos src.XPos, t *types.Type, c int64, sp *Value) *Value {
    486 	v := f.constVal(pos, OpOffPtr, t, c, true)
    487 	if len(v.Args) == 0 {
    488 		v.AddArg(sp)
    489 	}
    490 	return v
    491 
    492 }
    493 
    494 func (f *Func) Frontend() Frontend                                  { return f.fe }
    495 func (f *Func) Warnl(pos src.XPos, msg string, args ...interface{}) { f.fe.Warnl(pos, msg, args...) }
    496 func (f *Func) Logf(msg string, args ...interface{})                { f.fe.Logf(msg, args...) }
    497 func (f *Func) Log() bool                                           { return f.fe.Log() }
    498 func (f *Func) Fatalf(msg string, args ...interface{})              { f.fe.Fatalf(f.Entry.Pos, msg, args...) }
    499 
    500 // postorder returns the reachable blocks in f in a postorder traversal.
    501 func (f *Func) postorder() []*Block {
    502 	if f.cachedPostorder == nil {
    503 		f.cachedPostorder = postorder(f)
    504 	}
    505 	return f.cachedPostorder
    506 }
    507 
    508 func (f *Func) Postorder() []*Block {
    509 	return f.postorder()
    510 }
    511 
    512 // Idom returns a map from block ID to the immediate dominator of that block.
    513 // f.Entry.ID maps to nil. Unreachable blocks map to nil as well.
    514 func (f *Func) Idom() []*Block {
    515 	if f.cachedIdom == nil {
    516 		f.cachedIdom = dominators(f)
    517 	}
    518 	return f.cachedIdom
    519 }
    520 
    521 // sdom returns a sparse tree representing the dominator relationships
    522 // among the blocks of f.
    523 func (f *Func) sdom() SparseTree {
    524 	if f.cachedSdom == nil {
    525 		f.cachedSdom = newSparseTree(f, f.Idom())
    526 	}
    527 	return f.cachedSdom
    528 }
    529 
    530 // loopnest returns the loop nest information for f.
    531 func (f *Func) loopnest() *loopnest {
    532 	if f.cachedLoopnest == nil {
    533 		f.cachedLoopnest = loopnestfor(f)
    534 	}
    535 	return f.cachedLoopnest
    536 }
    537 
    538 // invalidateCFG tells f that its CFG has changed.
    539 func (f *Func) invalidateCFG() {
    540 	f.cachedPostorder = nil
    541 	f.cachedIdom = nil
    542 	f.cachedSdom = nil
    543 	f.cachedLoopnest = nil
    544 }
    545 
    546 // DebugHashMatch returns true if environment variable evname
    547 // 1) is empty (this is a special more-quickly implemented case of 3)
    548 // 2) is "y" or "Y"
    549 // 3) is a suffix of the sha1 hash of name
    550 // 4) is a suffix of the environment variable
    551 //    fmt.Sprintf("%s%d", evname, n)
    552 //    provided that all such variables are nonempty for 0 <= i <= n
    553 // Otherwise it returns false.
    554 // When true is returned the message
    555 //  "%s triggered %s\n", evname, name
    556 // is printed on the file named in environment variable
    557 //  GSHS_LOGFILE
    558 // or standard out if that is empty or there is an error
    559 // opening the file.
    560 func (f *Func) DebugHashMatch(evname, name string) bool {
    561 	evhash := os.Getenv(evname)
    562 	switch evhash {
    563 	case "":
    564 		return true // default behavior with no EV is "on"
    565 	case "y", "Y":
    566 		f.logDebugHashMatch(evname, name)
    567 		return true
    568 	case "n", "N":
    569 		return false
    570 	}
    571 	// Check the hash of the name against a partial input hash.
    572 	// We use this feature to do a binary search to
    573 	// find a function that is incorrectly compiled.
    574 	hstr := ""
    575 	for _, b := range sha1.Sum([]byte(name)) {
    576 		hstr += fmt.Sprintf("%08b", b)
    577 	}
    578 
    579 	if strings.HasSuffix(hstr, evhash) {
    580 		f.logDebugHashMatch(evname, name)
    581 		return true
    582 	}
    583 
    584 	// Iteratively try additional hashes to allow tests for multi-point
    585 	// failure.
    586 	for i := 0; true; i++ {
    587 		ev := fmt.Sprintf("%s%d", evname, i)
    588 		evv := os.Getenv(ev)
    589 		if evv == "" {
    590 			break
    591 		}
    592 		if strings.HasSuffix(hstr, evv) {
    593 			f.logDebugHashMatch(ev, name)
    594 			return true
    595 		}
    596 	}
    597 	return false
    598 }
    599 
    600 func (f *Func) logDebugHashMatch(evname, name string) {
    601 	if f.logfiles == nil {
    602 		f.logfiles = make(map[string]writeSyncer)
    603 	}
    604 	file := f.logfiles[evname]
    605 	if file == nil {
    606 		file = os.Stdout
    607 		if tmpfile := os.Getenv("GSHS_LOGFILE"); tmpfile != "" {
    608 			var err error
    609 			file, err = os.Create(tmpfile)
    610 			if err != nil {
    611 				f.Fatalf("could not open hash-testing logfile %s", tmpfile)
    612 			}
    613 		}
    614 		f.logfiles[evname] = file
    615 	}
    616 	fmt.Fprintf(file, "%s triggered %s\n", evname, name)
    617 	file.Sync()
    618 }
    619 
    620 func DebugNameMatch(evname, name string) bool {
    621 	return os.Getenv(evname) == name
    622 }
    623