github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/cmd/compile/internal/ssa/func.go (about)

     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  	"fmt"
     9  	"math"
    10  	"strings"
    11  )
    12  
    13  // A Func represents a Go func declaration (or function literal) and
    14  // its body. This package compiles each Func independently.
    15  type Func struct {
    16  	Config     *Config     // architecture information
    17  	pass       *pass       // current pass information (name, options, etc.)
    18  	Name       string      // e.g. bytes·Compare
    19  	Type       Type        // type signature of the function.
    20  	StaticData interface{} // associated static data, untouched by the ssa package
    21  	Blocks     []*Block    // unordered set of all basic blocks (note: not indexable by ID)
    22  	Entry      *Block      // the entry basic block
    23  	bid        idAlloc     // block ID allocator
    24  	vid        idAlloc     // value ID allocator
    25  
    26  	scheduled bool // Values in Blocks are in final order
    27  
    28  	// when register allocation is done, maps value ids to locations
    29  	RegAlloc []Location
    30  
    31  	// map from LocalSlot to set of Values that we want to store in that slot.
    32  	NamedValues map[LocalSlot][]*Value
    33  	// Names is a copy of NamedValues.Keys. We keep a separate list
    34  	// of keys to make iteration order deterministic.
    35  	Names []LocalSlot
    36  
    37  	freeValues *Value // free Values linked by argstorage[0].  All other fields except ID are 0/nil.
    38  	freeBlocks *Block // free Blocks linked by succstorage[0].b.  All other fields except ID are 0/nil.
    39  
    40  	cachedPostorder []*Block   // cached postorder traversal
    41  	cachedIdom      []*Block   // cached immediate dominators
    42  	cachedSdom      SparseTree // cached dominator tree
    43  	cachedLoopnest  *loopnest  // cached loop nest information
    44  
    45  	constants map[int64][]*Value // constants cache, keyed by constant value; users must check value's Op and Type
    46  }
    47  
    48  // NumBlocks returns an integer larger than the id of any Block in the Func.
    49  func (f *Func) NumBlocks() int {
    50  	return f.bid.num()
    51  }
    52  
    53  // NumValues returns an integer larger than the id of any Value in the Func.
    54  func (f *Func) NumValues() int {
    55  	return f.vid.num()
    56  }
    57  
    58  // newSparseSet returns a sparse set that can store at least up to n integers.
    59  func (f *Func) newSparseSet(n int) *sparseSet {
    60  	for i, scr := range f.Config.scrSparse {
    61  		if scr != nil && scr.cap() >= n {
    62  			f.Config.scrSparse[i] = nil
    63  			scr.clear()
    64  			return scr
    65  		}
    66  	}
    67  	return newSparseSet(n)
    68  }
    69  
    70  // retSparseSet returns a sparse set to the config's cache of sparse sets to be reused by f.newSparseSet.
    71  func (f *Func) retSparseSet(ss *sparseSet) {
    72  	for i, scr := range f.Config.scrSparse {
    73  		if scr == nil {
    74  			f.Config.scrSparse[i] = ss
    75  			return
    76  		}
    77  	}
    78  	f.Config.scrSparse = append(f.Config.scrSparse, ss)
    79  }
    80  
    81  // newValue allocates a new Value with the given fields and places it at the end of b.Values.
    82  func (f *Func) newValue(op Op, t Type, b *Block, line int32) *Value {
    83  	var v *Value
    84  	if f.freeValues != nil {
    85  		v = f.freeValues
    86  		f.freeValues = v.argstorage[0]
    87  		v.argstorage[0] = nil
    88  	} else {
    89  		ID := f.vid.get()
    90  		if int(ID) < len(f.Config.values) {
    91  			v = &f.Config.values[ID]
    92  		} else {
    93  			v = &Value{ID: ID}
    94  		}
    95  	}
    96  	v.Op = op
    97  	v.Type = t
    98  	v.Block = b
    99  	v.Line = line
   100  	b.Values = append(b.Values, v)
   101  	return v
   102  }
   103  
   104  // logPassStat writes a string key and int value as a warning in a
   105  // tab-separated format easily handled by spreadsheets or awk.
   106  // file names, lines, and function names are included to provide enough (?)
   107  // context to allow item-by-item comparisons across runs.
   108  // For example:
   109  // awk 'BEGIN {FS="\t"} $3~/TIME/{sum+=$4} END{print "t(ns)=",sum}' t.log
   110  func (f *Func) LogStat(key string, args ...interface{}) {
   111  	value := ""
   112  	for _, a := range args {
   113  		value += fmt.Sprintf("\t%v", a)
   114  	}
   115  	n := "missing_pass"
   116  	if f.pass != nil {
   117  		n = strings.Replace(f.pass.name, " ", "_", -1)
   118  	}
   119  	f.Config.Warnl(f.Entry.Line, "\t%s\t%s%s\t%s", n, key, value, f.Name)
   120  }
   121  
   122  // freeValue frees a value. It must no longer be referenced.
   123  func (f *Func) freeValue(v *Value) {
   124  	if v.Block == nil {
   125  		f.Fatalf("trying to free an already freed value")
   126  	}
   127  	if v.Uses != 0 {
   128  		f.Fatalf("value %s still has %d uses", v, v.Uses)
   129  	}
   130  	// Clear everything but ID (which we reuse).
   131  	id := v.ID
   132  
   133  	// Zero argument values might be cached, so remove them there.
   134  	nArgs := opcodeTable[v.Op].argLen
   135  	if nArgs == 0 {
   136  		vv := f.constants[v.AuxInt]
   137  		for i, cv := range vv {
   138  			if v == cv {
   139  				vv[i] = vv[len(vv)-1]
   140  				f.constants[v.AuxInt] = vv[0 : len(vv)-1]
   141  				break
   142  			}
   143  		}
   144  	}
   145  	*v = Value{}
   146  	v.ID = id
   147  	v.argstorage[0] = f.freeValues
   148  	f.freeValues = v
   149  }
   150  
   151  // newBlock allocates a new Block of the given kind and places it at the end of f.Blocks.
   152  func (f *Func) NewBlock(kind BlockKind) *Block {
   153  	var b *Block
   154  	if f.freeBlocks != nil {
   155  		b = f.freeBlocks
   156  		f.freeBlocks = b.succstorage[0].b
   157  		b.succstorage[0].b = nil
   158  	} else {
   159  		ID := f.bid.get()
   160  		if int(ID) < len(f.Config.blocks) {
   161  			b = &f.Config.blocks[ID]
   162  		} else {
   163  			b = &Block{ID: ID}
   164  		}
   165  	}
   166  	b.Kind = kind
   167  	b.Func = f
   168  	b.Preds = b.predstorage[:0]
   169  	b.Succs = b.succstorage[:0]
   170  	b.Values = b.valstorage[:0]
   171  	f.Blocks = append(f.Blocks, b)
   172  	f.invalidateCFG()
   173  	return b
   174  }
   175  
   176  func (f *Func) freeBlock(b *Block) {
   177  	if b.Func == nil {
   178  		f.Fatalf("trying to free an already freed block")
   179  	}
   180  	// Clear everything but ID (which we reuse).
   181  	id := b.ID
   182  	*b = Block{}
   183  	b.ID = id
   184  	b.succstorage[0].b = f.freeBlocks
   185  	f.freeBlocks = b
   186  }
   187  
   188  // NewValue0 returns a new value in the block with no arguments and zero aux values.
   189  func (b *Block) NewValue0(line int32, op Op, t Type) *Value {
   190  	v := b.Func.newValue(op, t, b, line)
   191  	v.AuxInt = 0
   192  	v.Args = v.argstorage[:0]
   193  	return v
   194  }
   195  
   196  // NewValue returns a new value in the block with no arguments and an auxint value.
   197  func (b *Block) NewValue0I(line int32, op Op, t Type, auxint int64) *Value {
   198  	v := b.Func.newValue(op, t, b, line)
   199  	v.AuxInt = auxint
   200  	v.Args = v.argstorage[:0]
   201  	return v
   202  }
   203  
   204  // NewValue returns a new value in the block with no arguments and an aux value.
   205  func (b *Block) NewValue0A(line int32, op Op, t Type, aux interface{}) *Value {
   206  	if _, ok := aux.(int64); ok {
   207  		// Disallow int64 aux values. They should be in the auxint field instead.
   208  		// Maybe we want to allow this at some point, but for now we disallow it
   209  		// to prevent errors like using NewValue1A instead of NewValue1I.
   210  		b.Fatalf("aux field has int64 type op=%s type=%s aux=%v", op, t, aux)
   211  	}
   212  	v := b.Func.newValue(op, t, b, line)
   213  	v.AuxInt = 0
   214  	v.Aux = aux
   215  	v.Args = v.argstorage[:0]
   216  	return v
   217  }
   218  
   219  // NewValue returns a new value in the block with no arguments and both an auxint and aux values.
   220  func (b *Block) NewValue0IA(line int32, op Op, t Type, auxint int64, aux interface{}) *Value {
   221  	v := b.Func.newValue(op, t, b, line)
   222  	v.AuxInt = auxint
   223  	v.Aux = aux
   224  	v.Args = v.argstorage[:0]
   225  	return v
   226  }
   227  
   228  // NewValue1 returns a new value in the block with one argument and zero aux values.
   229  func (b *Block) NewValue1(line int32, op Op, t Type, arg *Value) *Value {
   230  	v := b.Func.newValue(op, t, b, line)
   231  	v.AuxInt = 0
   232  	v.Args = v.argstorage[:1]
   233  	v.argstorage[0] = arg
   234  	arg.Uses++
   235  	return v
   236  }
   237  
   238  // NewValue1I returns a new value in the block with one argument and an auxint value.
   239  func (b *Block) NewValue1I(line int32, op Op, t Type, auxint int64, arg *Value) *Value {
   240  	v := b.Func.newValue(op, t, b, line)
   241  	v.AuxInt = auxint
   242  	v.Args = v.argstorage[:1]
   243  	v.argstorage[0] = arg
   244  	arg.Uses++
   245  	return v
   246  }
   247  
   248  // NewValue1A returns a new value in the block with one argument and an aux value.
   249  func (b *Block) NewValue1A(line int32, op Op, t Type, aux interface{}, arg *Value) *Value {
   250  	v := b.Func.newValue(op, t, b, line)
   251  	v.AuxInt = 0
   252  	v.Aux = aux
   253  	v.Args = v.argstorage[:1]
   254  	v.argstorage[0] = arg
   255  	arg.Uses++
   256  	return v
   257  }
   258  
   259  // NewValue1IA returns a new value in the block with one argument and both an auxint and aux values.
   260  func (b *Block) NewValue1IA(line int32, op Op, t Type, auxint int64, aux interface{}, arg *Value) *Value {
   261  	v := b.Func.newValue(op, t, b, line)
   262  	v.AuxInt = auxint
   263  	v.Aux = aux
   264  	v.Args = v.argstorage[:1]
   265  	v.argstorage[0] = arg
   266  	arg.Uses++
   267  	return v
   268  }
   269  
   270  // NewValue2 returns a new value in the block with two arguments and zero aux values.
   271  func (b *Block) NewValue2(line int32, op Op, t Type, arg0, arg1 *Value) *Value {
   272  	v := b.Func.newValue(op, t, b, line)
   273  	v.AuxInt = 0
   274  	v.Args = v.argstorage[:2]
   275  	v.argstorage[0] = arg0
   276  	v.argstorage[1] = arg1
   277  	arg0.Uses++
   278  	arg1.Uses++
   279  	return v
   280  }
   281  
   282  // NewValue2I returns a new value in the block with two arguments and an auxint value.
   283  func (b *Block) NewValue2I(line int32, op Op, t Type, auxint int64, arg0, arg1 *Value) *Value {
   284  	v := b.Func.newValue(op, t, b, line)
   285  	v.AuxInt = auxint
   286  	v.Args = v.argstorage[:2]
   287  	v.argstorage[0] = arg0
   288  	v.argstorage[1] = arg1
   289  	arg0.Uses++
   290  	arg1.Uses++
   291  	return v
   292  }
   293  
   294  // NewValue3 returns a new value in the block with three arguments and zero aux values.
   295  func (b *Block) NewValue3(line int32, op Op, t Type, arg0, arg1, arg2 *Value) *Value {
   296  	v := b.Func.newValue(op, t, b, line)
   297  	v.AuxInt = 0
   298  	v.Args = v.argstorage[:3]
   299  	v.argstorage[0] = arg0
   300  	v.argstorage[1] = arg1
   301  	v.argstorage[2] = arg2
   302  	arg0.Uses++
   303  	arg1.Uses++
   304  	arg2.Uses++
   305  	return v
   306  }
   307  
   308  // NewValue3I returns a new value in the block with three arguments and an auxint value.
   309  func (b *Block) NewValue3I(line int32, op Op, t Type, auxint int64, arg0, arg1, arg2 *Value) *Value {
   310  	v := b.Func.newValue(op, t, b, line)
   311  	v.AuxInt = auxint
   312  	v.Args = v.argstorage[:3]
   313  	v.argstorage[0] = arg0
   314  	v.argstorage[1] = arg1
   315  	v.argstorage[2] = arg2
   316  	arg0.Uses++
   317  	arg1.Uses++
   318  	arg2.Uses++
   319  	return v
   320  }
   321  
   322  // NewValue4 returns a new value in the block with four arguments and zero aux values.
   323  func (b *Block) NewValue4(line int32, op Op, t Type, arg0, arg1, arg2, arg3 *Value) *Value {
   324  	v := b.Func.newValue(op, t, b, line)
   325  	v.AuxInt = 0
   326  	v.Args = []*Value{arg0, arg1, arg2, arg3}
   327  	arg0.Uses++
   328  	arg1.Uses++
   329  	arg2.Uses++
   330  	arg3.Uses++
   331  	return v
   332  }
   333  
   334  // constVal returns a constant value for c.
   335  func (f *Func) constVal(line int32, op Op, t Type, c int64, setAux bool) *Value {
   336  	if f.constants == nil {
   337  		f.constants = make(map[int64][]*Value)
   338  	}
   339  	vv := f.constants[c]
   340  	for _, v := range vv {
   341  		if v.Op == op && v.Type.Compare(t) == CMPeq {
   342  			if setAux && v.AuxInt != c {
   343  				panic(fmt.Sprintf("cached const %s should have AuxInt of %d", v.LongString(), c))
   344  			}
   345  			return v
   346  		}
   347  	}
   348  	var v *Value
   349  	if setAux {
   350  		v = f.Entry.NewValue0I(line, op, t, c)
   351  	} else {
   352  		v = f.Entry.NewValue0(line, op, t)
   353  	}
   354  	f.constants[c] = append(vv, v)
   355  	return v
   356  }
   357  
   358  // These magic auxint values let us easily cache non-numeric constants
   359  // using the same constants map while making collisions unlikely.
   360  // These values are unlikely to occur in regular code and
   361  // are easy to grep for in case of bugs.
   362  const (
   363  	constSliceMagic       = 1122334455
   364  	constInterfaceMagic   = 2233445566
   365  	constNilMagic         = 3344556677
   366  	constEmptyStringMagic = 4455667788
   367  )
   368  
   369  // ConstInt returns an int constant representing its argument.
   370  func (f *Func) ConstBool(line int32, t Type, c bool) *Value {
   371  	i := int64(0)
   372  	if c {
   373  		i = 1
   374  	}
   375  	return f.constVal(line, OpConstBool, t, i, true)
   376  }
   377  func (f *Func) ConstInt8(line int32, t Type, c int8) *Value {
   378  	return f.constVal(line, OpConst8, t, int64(c), true)
   379  }
   380  func (f *Func) ConstInt16(line int32, t Type, c int16) *Value {
   381  	return f.constVal(line, OpConst16, t, int64(c), true)
   382  }
   383  func (f *Func) ConstInt32(line int32, t Type, c int32) *Value {
   384  	return f.constVal(line, OpConst32, t, int64(c), true)
   385  }
   386  func (f *Func) ConstInt64(line int32, t Type, c int64) *Value {
   387  	return f.constVal(line, OpConst64, t, c, true)
   388  }
   389  func (f *Func) ConstFloat32(line int32, t Type, c float64) *Value {
   390  	return f.constVal(line, OpConst32F, t, int64(math.Float64bits(float64(float32(c)))), true)
   391  }
   392  func (f *Func) ConstFloat64(line int32, t Type, c float64) *Value {
   393  	return f.constVal(line, OpConst64F, t, int64(math.Float64bits(c)), true)
   394  }
   395  
   396  func (f *Func) ConstSlice(line int32, t Type) *Value {
   397  	return f.constVal(line, OpConstSlice, t, constSliceMagic, false)
   398  }
   399  func (f *Func) ConstInterface(line int32, t Type) *Value {
   400  	return f.constVal(line, OpConstInterface, t, constInterfaceMagic, false)
   401  }
   402  func (f *Func) ConstNil(line int32, t Type) *Value {
   403  	return f.constVal(line, OpConstNil, t, constNilMagic, false)
   404  }
   405  func (f *Func) ConstEmptyString(line int32, t Type) *Value {
   406  	v := f.constVal(line, OpConstString, t, constEmptyStringMagic, false)
   407  	v.Aux = ""
   408  	return v
   409  }
   410  
   411  func (f *Func) Logf(msg string, args ...interface{})   { f.Config.Logf(msg, args...) }
   412  func (f *Func) Log() bool                              { return f.Config.Log() }
   413  func (f *Func) Fatalf(msg string, args ...interface{}) { f.Config.Fatalf(f.Entry.Line, msg, args...) }
   414  
   415  func (f *Func) Free() {
   416  	// Clear cached CFG info.
   417  	f.invalidateCFG()
   418  
   419  	// Clear values.
   420  	n := f.vid.num()
   421  	if n > len(f.Config.values) {
   422  		n = len(f.Config.values)
   423  	}
   424  	for i := 1; i < n; i++ {
   425  		f.Config.values[i] = Value{}
   426  		f.Config.values[i].ID = ID(i)
   427  	}
   428  
   429  	// Clear blocks.
   430  	n = f.bid.num()
   431  	if n > len(f.Config.blocks) {
   432  		n = len(f.Config.blocks)
   433  	}
   434  	for i := 1; i < n; i++ {
   435  		f.Config.blocks[i] = Block{}
   436  		f.Config.blocks[i].ID = ID(i)
   437  	}
   438  
   439  	// Unregister from config.
   440  	if f.Config.curFunc != f {
   441  		f.Fatalf("free of function which isn't the last one allocated")
   442  	}
   443  	f.Config.curFunc = nil
   444  	*f = Func{} // just in case
   445  }
   446  
   447  // postorder returns the reachable blocks in f in a postorder traversal.
   448  func (f *Func) postorder() []*Block {
   449  	if f.cachedPostorder == nil {
   450  		f.cachedPostorder = postorder(f)
   451  	}
   452  	return f.cachedPostorder
   453  }
   454  
   455  // Idom returns a map from block ID to the immediate dominator of that block.
   456  // f.Entry.ID maps to nil. Unreachable blocks map to nil as well.
   457  func (f *Func) Idom() []*Block {
   458  	if f.cachedIdom == nil {
   459  		f.cachedIdom = dominators(f)
   460  	}
   461  	return f.cachedIdom
   462  }
   463  
   464  // sdom returns a sparse tree representing the dominator relationships
   465  // among the blocks of f.
   466  func (f *Func) sdom() SparseTree {
   467  	if f.cachedSdom == nil {
   468  		f.cachedSdom = newSparseTree(f, f.Idom())
   469  	}
   470  	return f.cachedSdom
   471  }
   472  
   473  // loopnest returns the loop nest information for f.
   474  func (f *Func) loopnest() *loopnest {
   475  	if f.cachedLoopnest == nil {
   476  		f.cachedLoopnest = loopnestfor(f)
   477  	}
   478  	return f.cachedLoopnest
   479  }
   480  
   481  // invalidateCFG tells f that its CFG has changed.
   482  func (f *Func) invalidateCFG() {
   483  	f.cachedPostorder = nil
   484  	f.cachedIdom = nil
   485  	f.cachedSdom = nil
   486  	f.cachedLoopnest = nil
   487  }