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