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