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 }