github.com/bir3/gocompiler@v0.3.205/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 "github.com/bir3/gocompiler/src/cmd/compile/internal/abi" 9 "github.com/bir3/gocompiler/src/cmd/compile/internal/base" 10 "github.com/bir3/gocompiler/src/cmd/compile/internal/types" 11 "github.com/bir3/gocompiler/src/cmd/internal/src" 12 "fmt" 13 "math" 14 "strings" 15 ) 16 17 // A Func represents a Go func declaration (or function literal) and its body. 18 // This package compiles each Func independently. 19 // Funcs are single-use; a new Func must be created for every compiled function. 20 type Func struct { 21 Config *Config // architecture information 22 Cache *Cache // re-usable cache 23 fe Frontend // frontend state associated with this Func, callbacks into compiler frontend 24 pass *pass // current pass information (name, options, etc.) 25 Name string // e.g. NewFunc or (*Func).NumBlocks (no package prefix) 26 Type *types.Type // type signature of the function. 27 Blocks []*Block // unordered set of all basic blocks (note: not indexable by ID) 28 Entry *Block // the entry basic block 29 30 bid idAlloc // block ID allocator 31 vid idAlloc // value ID allocator 32 33 HTMLWriter *HTMLWriter // html writer, for debugging 34 PrintOrHtmlSSA bool // true if GOSSAFUNC matches, true even if fe.Log() (spew phase results to stdout) is false. There's an odd dependence on this in debug.go for method logf. 35 ruleMatches map[string]int // number of times countRule was called during compilation for any given string 36 ABI0 *abi.ABIConfig // A copy, for no-sync access 37 ABI1 *abi.ABIConfig // A copy, for no-sync access 38 ABISelf *abi.ABIConfig // ABI for function being compiled 39 ABIDefault *abi.ABIConfig // ABI for rtcall and other no-parsed-signature/pragma functions. 40 41 scheduled bool // Values in Blocks are in final order 42 laidout bool // Blocks are ordered 43 NoSplit bool // true if function is marked as nosplit. Used by schedule check pass. 44 dumpFileSeq uint8 // the sequence numbers of dump file. (%s_%02d__%s.dump", funcname, dumpFileSeq, phaseName) 45 46 // when register allocation is done, maps value ids to locations 47 RegAlloc []Location 48 49 // temporary registers allocated to rare instructions 50 tempRegs map[ID]*Register 51 52 // map from LocalSlot to set of Values that we want to store in that slot. 53 NamedValues map[LocalSlot][]*Value 54 // Names is a copy of NamedValues.Keys. We keep a separate list 55 // of keys to make iteration order deterministic. 56 Names []*LocalSlot 57 // Canonicalize root/top-level local slots, and canonicalize their pieces. 58 // Because LocalSlot pieces refer to their parents with a pointer, this ensures that equivalent slots really are equal. 59 CanonicalLocalSlots map[LocalSlot]*LocalSlot 60 CanonicalLocalSplits map[LocalSlotSplitKey]*LocalSlot 61 62 // RegArgs is a slice of register-memory pairs that must be spilled and unspilled in the uncommon path of function entry. 63 RegArgs []Spill 64 // AuxCall describing parameters and results for this function. 65 OwnAux *AuxCall 66 67 // WBLoads is a list of Blocks that branch on the write 68 // barrier flag. Safe-points are disabled from the OpLoad that 69 // reads the write-barrier flag until the control flow rejoins 70 // below the two successors of this block. 71 WBLoads []*Block 72 73 freeValues *Value // free Values linked by argstorage[0]. All other fields except ID are 0/nil. 74 freeBlocks *Block // free Blocks linked by succstorage[0].b. All other fields except ID are 0/nil. 75 76 cachedPostorder []*Block // cached postorder traversal 77 cachedIdom []*Block // cached immediate dominators 78 cachedSdom SparseTree // cached dominator tree 79 cachedLoopnest *loopnest // cached loop nest information 80 cachedLineStarts *xposmap // cached map/set of xpos to integers 81 82 auxmap auxmap // map from aux values to opaque ids used by CSE 83 constants map[int64][]*Value // constants cache, keyed by constant value; users must check value's Op and Type 84 } 85 86 type LocalSlotSplitKey struct { 87 parent *LocalSlot 88 Off int64 // offset of slot in N 89 Type *types.Type // type of slot 90 } 91 92 // NewFunc returns a new, empty function object. 93 // Caller must set f.Config and f.Cache before using f. 94 func NewFunc(fe Frontend) *Func { 95 return &Func{fe: fe, NamedValues: make(map[LocalSlot][]*Value), CanonicalLocalSlots: make(map[LocalSlot]*LocalSlot), CanonicalLocalSplits: make(map[LocalSlotSplitKey]*LocalSlot)} 96 } 97 98 // NumBlocks returns an integer larger than the id of any Block in the Func. 99 func (f *Func) NumBlocks() int { 100 return f.bid.num() 101 } 102 103 // NumValues returns an integer larger than the id of any Value in the Func. 104 func (f *Func) NumValues() int { 105 return f.vid.num() 106 } 107 108 // newSparseSet returns a sparse set that can store at least up to n integers. 109 func (f *Func) newSparseSet(n int) *sparseSet { 110 return f.Cache.allocSparseSet(n) 111 } 112 113 // retSparseSet returns a sparse set to the config's cache of sparse 114 // sets to be reused by f.newSparseSet. 115 func (f *Func) retSparseSet(ss *sparseSet) { 116 f.Cache.freeSparseSet(ss) 117 } 118 119 // newSparseMap returns a sparse map that can store at least up to n integers. 120 func (f *Func) newSparseMap(n int) *sparseMap { 121 return f.Cache.allocSparseMap(n) 122 } 123 124 // retSparseMap returns a sparse map to the config's cache of sparse 125 // sets to be reused by f.newSparseMap. 126 func (f *Func) retSparseMap(ss *sparseMap) { 127 f.Cache.freeSparseMap(ss) 128 } 129 130 // newSparseMapPos returns a sparse map that can store at least up to n integers. 131 func (f *Func) newSparseMapPos(n int) *sparseMapPos { 132 return f.Cache.allocSparseMapPos(n) 133 } 134 135 // retSparseMapPos returns a sparse map to the config's cache of sparse 136 // sets to be reused by f.newSparseMapPos. 137 func (f *Func) retSparseMapPos(ss *sparseMapPos) { 138 f.Cache.freeSparseMapPos(ss) 139 } 140 141 // newPoset returns a new poset from the internal cache 142 func (f *Func) newPoset() *poset { 143 if len(f.Cache.scrPoset) > 0 { 144 po := f.Cache.scrPoset[len(f.Cache.scrPoset)-1] 145 f.Cache.scrPoset = f.Cache.scrPoset[:len(f.Cache.scrPoset)-1] 146 return po 147 } 148 return newPoset() 149 } 150 151 // retPoset returns a poset to the internal cache 152 func (f *Func) retPoset(po *poset) { 153 f.Cache.scrPoset = append(f.Cache.scrPoset, po) 154 } 155 156 func (f *Func) localSlotAddr(slot LocalSlot) *LocalSlot { 157 a, ok := f.CanonicalLocalSlots[slot] 158 if !ok { 159 a = new(LocalSlot) 160 *a = slot // don't escape slot 161 f.CanonicalLocalSlots[slot] = a 162 } 163 return a 164 } 165 166 func (f *Func) SplitString(name *LocalSlot) (*LocalSlot, *LocalSlot) { 167 ptrType := types.NewPtr(types.Types[types.TUINT8]) 168 lenType := types.Types[types.TINT] 169 // Split this string up into two separate variables. 170 p := f.SplitSlot(name, ".ptr", 0, ptrType) 171 l := f.SplitSlot(name, ".len", ptrType.Size(), lenType) 172 return p, l 173 } 174 175 func (f *Func) SplitInterface(name *LocalSlot) (*LocalSlot, *LocalSlot) { 176 n := name.N 177 u := types.Types[types.TUINTPTR] 178 t := types.NewPtr(types.Types[types.TUINT8]) 179 // Split this interface up into two separate variables. 180 sfx := ".itab" 181 if n.Type().IsEmptyInterface() { 182 sfx = ".type" 183 } 184 c := f.SplitSlot(name, sfx, 0, u) // see comment in typebits.Set 185 d := f.SplitSlot(name, ".data", u.Size(), t) 186 return c, d 187 } 188 189 func (f *Func) SplitSlice(name *LocalSlot) (*LocalSlot, *LocalSlot, *LocalSlot) { 190 ptrType := types.NewPtr(name.Type.Elem()) 191 lenType := types.Types[types.TINT] 192 p := f.SplitSlot(name, ".ptr", 0, ptrType) 193 l := f.SplitSlot(name, ".len", ptrType.Size(), lenType) 194 c := f.SplitSlot(name, ".cap", ptrType.Size()+lenType.Size(), lenType) 195 return p, l, c 196 } 197 198 func (f *Func) SplitComplex(name *LocalSlot) (*LocalSlot, *LocalSlot) { 199 s := name.Type.Size() / 2 200 var t *types.Type 201 if s == 8 { 202 t = types.Types[types.TFLOAT64] 203 } else { 204 t = types.Types[types.TFLOAT32] 205 } 206 r := f.SplitSlot(name, ".real", 0, t) 207 i := f.SplitSlot(name, ".imag", t.Size(), t) 208 return r, i 209 } 210 211 func (f *Func) SplitInt64(name *LocalSlot) (*LocalSlot, *LocalSlot) { 212 var t *types.Type 213 if name.Type.IsSigned() { 214 t = types.Types[types.TINT32] 215 } else { 216 t = types.Types[types.TUINT32] 217 } 218 if f.Config.BigEndian { 219 return f.SplitSlot(name, ".hi", 0, t), f.SplitSlot(name, ".lo", t.Size(), types.Types[types.TUINT32]) 220 } 221 return f.SplitSlot(name, ".hi", t.Size(), t), f.SplitSlot(name, ".lo", 0, types.Types[types.TUINT32]) 222 } 223 224 func (f *Func) SplitStruct(name *LocalSlot, i int) *LocalSlot { 225 st := name.Type 226 return f.SplitSlot(name, st.FieldName(i), st.FieldOff(i), st.FieldType(i)) 227 } 228 func (f *Func) SplitArray(name *LocalSlot) *LocalSlot { 229 n := name.N 230 at := name.Type 231 if at.NumElem() != 1 { 232 base.FatalfAt(n.Pos(), "bad array size") 233 } 234 et := at.Elem() 235 return f.SplitSlot(name, "[0]", 0, et) 236 } 237 238 func (f *Func) SplitSlot(name *LocalSlot, sfx string, offset int64, t *types.Type) *LocalSlot { 239 lssk := LocalSlotSplitKey{name, offset, t} 240 if als, ok := f.CanonicalLocalSplits[lssk]; ok { 241 return als 242 } 243 // Note: the _ field may appear several times. But 244 // have no fear, identically-named but distinct Autos are 245 // ok, albeit maybe confusing for a debugger. 246 ls := f.fe.SplitSlot(name, sfx, offset, t) 247 f.CanonicalLocalSplits[lssk] = &ls 248 return &ls 249 } 250 251 // newValue allocates a new Value with the given fields and places it at the end of b.Values. 252 func (f *Func) newValue(op Op, t *types.Type, b *Block, pos src.XPos) *Value { 253 var v *Value 254 if f.freeValues != nil { 255 v = f.freeValues 256 f.freeValues = v.argstorage[0] 257 v.argstorage[0] = nil 258 } else { 259 ID := f.vid.get() 260 if int(ID) < len(f.Cache.values) { 261 v = &f.Cache.values[ID] 262 v.ID = ID 263 } else { 264 v = &Value{ID: ID} 265 } 266 } 267 v.Op = op 268 v.Type = t 269 v.Block = b 270 if notStmtBoundary(op) { 271 pos = pos.WithNotStmt() 272 } 273 v.Pos = pos 274 b.Values = append(b.Values, v) 275 return v 276 } 277 278 // newValueNoBlock allocates a new Value with the given fields. 279 // The returned value is not placed in any block. Once the caller 280 // decides on a block b, it must set b.Block and append 281 // the returned value to b.Values. 282 func (f *Func) newValueNoBlock(op Op, t *types.Type, pos src.XPos) *Value { 283 var v *Value 284 if f.freeValues != nil { 285 v = f.freeValues 286 f.freeValues = v.argstorage[0] 287 v.argstorage[0] = nil 288 } else { 289 ID := f.vid.get() 290 if int(ID) < len(f.Cache.values) { 291 v = &f.Cache.values[ID] 292 v.ID = ID 293 } else { 294 v = &Value{ID: ID} 295 } 296 } 297 v.Op = op 298 v.Type = t 299 v.Block = nil // caller must fix this. 300 if notStmtBoundary(op) { 301 pos = pos.WithNotStmt() 302 } 303 v.Pos = pos 304 return v 305 } 306 307 // LogStat writes a string key and int value as a warning in a 308 // tab-separated format easily handled by spreadsheets or awk. 309 // file names, lines, and function names are included to provide enough (?) 310 // context to allow item-by-item comparisons across runs. 311 // For example: 312 // awk 'BEGIN {FS="\t"} $3~/TIME/{sum+=$4} END{print "t(ns)=",sum}' t.log 313 func (f *Func) LogStat(key string, args ...interface{}) { 314 value := "" 315 for _, a := range args { 316 value += fmt.Sprintf("\t%v", a) 317 } 318 n := "missing_pass" 319 if f.pass != nil { 320 n = strings.Replace(f.pass.name, " ", "_", -1) 321 } 322 f.Warnl(f.Entry.Pos, "\t%s\t%s%s\t%s", n, key, value, f.Name) 323 } 324 325 // unCacheLine removes v from f's constant cache "line" for aux, 326 // resets v.InCache when it is found (and removed), 327 // and returns whether v was found in that line. 328 func (f *Func) unCacheLine(v *Value, aux int64) bool { 329 vv := f.constants[aux] 330 for i, cv := range vv { 331 if v == cv { 332 vv[i] = vv[len(vv)-1] 333 vv[len(vv)-1] = nil 334 f.constants[aux] = vv[0 : len(vv)-1] 335 v.InCache = false 336 return true 337 } 338 } 339 return false 340 } 341 342 // unCache removes v from f's constant cache. 343 func (f *Func) unCache(v *Value) { 344 if v.InCache { 345 aux := v.AuxInt 346 if f.unCacheLine(v, aux) { 347 return 348 } 349 if aux == 0 { 350 switch v.Op { 351 case OpConstNil: 352 aux = constNilMagic 353 case OpConstSlice: 354 aux = constSliceMagic 355 case OpConstString: 356 aux = constEmptyStringMagic 357 case OpConstInterface: 358 aux = constInterfaceMagic 359 } 360 if aux != 0 && f.unCacheLine(v, aux) { 361 return 362 } 363 } 364 f.Fatalf("unCached value %s not found in cache, auxInt=0x%x, adjusted aux=0x%x", v.LongString(), v.AuxInt, aux) 365 } 366 } 367 368 // freeValue frees a value. It must no longer be referenced or have any args. 369 func (f *Func) freeValue(v *Value) { 370 if v.Block == nil { 371 f.Fatalf("trying to free an already freed value") 372 } 373 if v.Uses != 0 { 374 f.Fatalf("value %s still has %d uses", v, v.Uses) 375 } 376 if len(v.Args) != 0 { 377 f.Fatalf("value %s still has %d args", v, len(v.Args)) 378 } 379 // Clear everything but ID (which we reuse). 380 id := v.ID 381 if v.InCache { 382 f.unCache(v) 383 } 384 *v = Value{} 385 v.ID = id 386 v.argstorage[0] = f.freeValues 387 f.freeValues = v 388 } 389 390 // NewBlock allocates a new Block of the given kind and places it at the end of f.Blocks. 391 func (f *Func) NewBlock(kind BlockKind) *Block { 392 var b *Block 393 if f.freeBlocks != nil { 394 b = f.freeBlocks 395 f.freeBlocks = b.succstorage[0].b 396 b.succstorage[0].b = nil 397 } else { 398 ID := f.bid.get() 399 if int(ID) < len(f.Cache.blocks) { 400 b = &f.Cache.blocks[ID] 401 b.ID = ID 402 } else { 403 b = &Block{ID: ID} 404 } 405 } 406 b.Kind = kind 407 b.Func = f 408 b.Preds = b.predstorage[:0] 409 b.Succs = b.succstorage[:0] 410 b.Values = b.valstorage[:0] 411 f.Blocks = append(f.Blocks, b) 412 f.invalidateCFG() 413 return b 414 } 415 416 func (f *Func) freeBlock(b *Block) { 417 if b.Func == nil { 418 f.Fatalf("trying to free an already freed block") 419 } 420 // Clear everything but ID (which we reuse). 421 id := b.ID 422 *b = Block{} 423 b.ID = id 424 b.succstorage[0].b = f.freeBlocks 425 f.freeBlocks = b 426 } 427 428 // NewValue0 returns a new value in the block with no arguments and zero aux values. 429 func (b *Block) NewValue0(pos src.XPos, op Op, t *types.Type) *Value { 430 v := b.Func.newValue(op, t, b, pos) 431 v.AuxInt = 0 432 v.Args = v.argstorage[:0] 433 return v 434 } 435 436 // NewValue0I returns a new value in the block with no arguments and an auxint value. 437 func (b *Block) NewValue0I(pos src.XPos, op Op, t *types.Type, auxint int64) *Value { 438 v := b.Func.newValue(op, t, b, pos) 439 v.AuxInt = auxint 440 v.Args = v.argstorage[:0] 441 return v 442 } 443 444 // NewValue0A returns a new value in the block with no arguments and an aux value. 445 func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux Aux) *Value { 446 v := b.Func.newValue(op, t, b, pos) 447 v.AuxInt = 0 448 v.Aux = aux 449 v.Args = v.argstorage[:0] 450 return v 451 } 452 453 // NewValue0IA returns a new value in the block with no arguments and both an auxint and aux values. 454 func (b *Block) NewValue0IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux) *Value { 455 v := b.Func.newValue(op, t, b, pos) 456 v.AuxInt = auxint 457 v.Aux = aux 458 v.Args = v.argstorage[:0] 459 return v 460 } 461 462 // NewValue1 returns a new value in the block with one argument and zero aux values. 463 func (b *Block) NewValue1(pos src.XPos, op Op, t *types.Type, arg *Value) *Value { 464 v := b.Func.newValue(op, t, b, pos) 465 v.AuxInt = 0 466 v.Args = v.argstorage[:1] 467 v.argstorage[0] = arg 468 arg.Uses++ 469 return v 470 } 471 472 // NewValue1I returns a new value in the block with one argument and an auxint value. 473 func (b *Block) NewValue1I(pos src.XPos, op Op, t *types.Type, auxint int64, arg *Value) *Value { 474 v := b.Func.newValue(op, t, b, pos) 475 v.AuxInt = auxint 476 v.Args = v.argstorage[:1] 477 v.argstorage[0] = arg 478 arg.Uses++ 479 return v 480 } 481 482 // NewValue1A returns a new value in the block with one argument and an aux value. 483 func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux Aux, arg *Value) *Value { 484 v := b.Func.newValue(op, t, b, pos) 485 v.AuxInt = 0 486 v.Aux = aux 487 v.Args = v.argstorage[:1] 488 v.argstorage[0] = arg 489 arg.Uses++ 490 return v 491 } 492 493 // NewValue1IA returns a new value in the block with one argument and both an auxint and aux values. 494 func (b *Block) NewValue1IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux, arg *Value) *Value { 495 v := b.Func.newValue(op, t, b, pos) 496 v.AuxInt = auxint 497 v.Aux = aux 498 v.Args = v.argstorage[:1] 499 v.argstorage[0] = arg 500 arg.Uses++ 501 return v 502 } 503 504 // NewValue2 returns a new value in the block with two arguments and zero aux values. 505 func (b *Block) NewValue2(pos src.XPos, op Op, t *types.Type, arg0, arg1 *Value) *Value { 506 v := b.Func.newValue(op, t, b, pos) 507 v.AuxInt = 0 508 v.Args = v.argstorage[:2] 509 v.argstorage[0] = arg0 510 v.argstorage[1] = arg1 511 arg0.Uses++ 512 arg1.Uses++ 513 return v 514 } 515 516 // NewValue2A returns a new value in the block with two arguments and one aux values. 517 func (b *Block) NewValue2A(pos src.XPos, op Op, t *types.Type, aux Aux, arg0, arg1 *Value) *Value { 518 v := b.Func.newValue(op, t, b, pos) 519 v.AuxInt = 0 520 v.Aux = aux 521 v.Args = v.argstorage[:2] 522 v.argstorage[0] = arg0 523 v.argstorage[1] = arg1 524 arg0.Uses++ 525 arg1.Uses++ 526 return v 527 } 528 529 // NewValue2I returns a new value in the block with two arguments and an auxint value. 530 func (b *Block) NewValue2I(pos src.XPos, op Op, t *types.Type, auxint int64, arg0, arg1 *Value) *Value { 531 v := b.Func.newValue(op, t, b, pos) 532 v.AuxInt = auxint 533 v.Args = v.argstorage[:2] 534 v.argstorage[0] = arg0 535 v.argstorage[1] = arg1 536 arg0.Uses++ 537 arg1.Uses++ 538 return v 539 } 540 541 // NewValue2IA returns a new value in the block with two arguments and both an auxint and aux values. 542 func (b *Block) NewValue2IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux, arg0, arg1 *Value) *Value { 543 v := b.Func.newValue(op, t, b, pos) 544 v.AuxInt = auxint 545 v.Aux = aux 546 v.Args = v.argstorage[:2] 547 v.argstorage[0] = arg0 548 v.argstorage[1] = arg1 549 arg0.Uses++ 550 arg1.Uses++ 551 return v 552 } 553 554 // NewValue3 returns a new value in the block with three arguments and zero aux values. 555 func (b *Block) NewValue3(pos src.XPos, op Op, t *types.Type, arg0, arg1, arg2 *Value) *Value { 556 v := b.Func.newValue(op, t, b, pos) 557 v.AuxInt = 0 558 v.Args = v.argstorage[:3] 559 v.argstorage[0] = arg0 560 v.argstorage[1] = arg1 561 v.argstorage[2] = arg2 562 arg0.Uses++ 563 arg1.Uses++ 564 arg2.Uses++ 565 return v 566 } 567 568 // NewValue3I returns a new value in the block with three arguments and an auxint value. 569 func (b *Block) NewValue3I(pos src.XPos, op Op, t *types.Type, auxint int64, arg0, arg1, arg2 *Value) *Value { 570 v := b.Func.newValue(op, t, b, pos) 571 v.AuxInt = auxint 572 v.Args = v.argstorage[:3] 573 v.argstorage[0] = arg0 574 v.argstorage[1] = arg1 575 v.argstorage[2] = arg2 576 arg0.Uses++ 577 arg1.Uses++ 578 arg2.Uses++ 579 return v 580 } 581 582 // NewValue3A returns a new value in the block with three argument and an aux value. 583 func (b *Block) NewValue3A(pos src.XPos, op Op, t *types.Type, aux Aux, arg0, arg1, arg2 *Value) *Value { 584 v := b.Func.newValue(op, t, b, pos) 585 v.AuxInt = 0 586 v.Aux = aux 587 v.Args = v.argstorage[:3] 588 v.argstorage[0] = arg0 589 v.argstorage[1] = arg1 590 v.argstorage[2] = arg2 591 arg0.Uses++ 592 arg1.Uses++ 593 arg2.Uses++ 594 return v 595 } 596 597 // NewValue4 returns a new value in the block with four arguments and zero aux values. 598 func (b *Block) NewValue4(pos src.XPos, op Op, t *types.Type, arg0, arg1, arg2, arg3 *Value) *Value { 599 v := b.Func.newValue(op, t, b, pos) 600 v.AuxInt = 0 601 v.Args = []*Value{arg0, arg1, arg2, arg3} 602 arg0.Uses++ 603 arg1.Uses++ 604 arg2.Uses++ 605 arg3.Uses++ 606 return v 607 } 608 609 // NewValue4I returns a new value in the block with four arguments and auxint value. 610 func (b *Block) NewValue4I(pos src.XPos, op Op, t *types.Type, auxint int64, arg0, arg1, arg2, arg3 *Value) *Value { 611 v := b.Func.newValue(op, t, b, pos) 612 v.AuxInt = auxint 613 v.Args = []*Value{arg0, arg1, arg2, arg3} 614 arg0.Uses++ 615 arg1.Uses++ 616 arg2.Uses++ 617 arg3.Uses++ 618 return v 619 } 620 621 // constVal returns a constant value for c. 622 func (f *Func) constVal(op Op, t *types.Type, c int64, setAuxInt bool) *Value { 623 if f.constants == nil { 624 f.constants = make(map[int64][]*Value) 625 } 626 vv := f.constants[c] 627 for _, v := range vv { 628 if v.Op == op && v.Type.Compare(t) == types.CMPeq { 629 if setAuxInt && v.AuxInt != c { 630 panic(fmt.Sprintf("cached const %s should have AuxInt of %d", v.LongString(), c)) 631 } 632 return v 633 } 634 } 635 var v *Value 636 if setAuxInt { 637 v = f.Entry.NewValue0I(src.NoXPos, op, t, c) 638 } else { 639 v = f.Entry.NewValue0(src.NoXPos, op, t) 640 } 641 f.constants[c] = append(vv, v) 642 v.InCache = true 643 return v 644 } 645 646 // These magic auxint values let us easily cache non-numeric constants 647 // using the same constants map while making collisions unlikely. 648 // These values are unlikely to occur in regular code and 649 // are easy to grep for in case of bugs. 650 const ( 651 constSliceMagic = 1122334455 652 constInterfaceMagic = 2233445566 653 constNilMagic = 3344556677 654 constEmptyStringMagic = 4455667788 655 ) 656 657 // ConstBool returns an int constant representing its argument. 658 func (f *Func) ConstBool(t *types.Type, c bool) *Value { 659 i := int64(0) 660 if c { 661 i = 1 662 } 663 return f.constVal(OpConstBool, t, i, true) 664 } 665 func (f *Func) ConstInt8(t *types.Type, c int8) *Value { 666 return f.constVal(OpConst8, t, int64(c), true) 667 } 668 func (f *Func) ConstInt16(t *types.Type, c int16) *Value { 669 return f.constVal(OpConst16, t, int64(c), true) 670 } 671 func (f *Func) ConstInt32(t *types.Type, c int32) *Value { 672 return f.constVal(OpConst32, t, int64(c), true) 673 } 674 func (f *Func) ConstInt64(t *types.Type, c int64) *Value { 675 return f.constVal(OpConst64, t, c, true) 676 } 677 func (f *Func) ConstFloat32(t *types.Type, c float64) *Value { 678 return f.constVal(OpConst32F, t, int64(math.Float64bits(float64(float32(c)))), true) 679 } 680 func (f *Func) ConstFloat64(t *types.Type, c float64) *Value { 681 return f.constVal(OpConst64F, t, int64(math.Float64bits(c)), true) 682 } 683 684 func (f *Func) ConstSlice(t *types.Type) *Value { 685 return f.constVal(OpConstSlice, t, constSliceMagic, false) 686 } 687 func (f *Func) ConstInterface(t *types.Type) *Value { 688 return f.constVal(OpConstInterface, t, constInterfaceMagic, false) 689 } 690 func (f *Func) ConstNil(t *types.Type) *Value { 691 return f.constVal(OpConstNil, t, constNilMagic, false) 692 } 693 func (f *Func) ConstEmptyString(t *types.Type) *Value { 694 v := f.constVal(OpConstString, t, constEmptyStringMagic, false) 695 v.Aux = StringToAux("") 696 return v 697 } 698 func (f *Func) ConstOffPtrSP(t *types.Type, c int64, sp *Value) *Value { 699 v := f.constVal(OpOffPtr, t, c, true) 700 if len(v.Args) == 0 { 701 v.AddArg(sp) 702 } 703 return v 704 705 } 706 707 func (f *Func) Frontend() Frontend { return f.fe } 708 func (f *Func) Warnl(pos src.XPos, msg string, args ...interface{}) { f.fe.Warnl(pos, msg, args...) } 709 func (f *Func) Logf(msg string, args ...interface{}) { f.fe.Logf(msg, args...) } 710 func (f *Func) Log() bool { return f.fe.Log() } 711 712 func (f *Func) Fatalf(msg string, args ...interface{}) { 713 stats := "crashed" 714 if f.Log() { 715 f.Logf(" pass %s end %s\n", f.pass.name, stats) 716 printFunc(f) 717 } 718 if f.HTMLWriter != nil { 719 f.HTMLWriter.WritePhase(f.pass.name, fmt.Sprintf("%s <span class=\"stats\">%s</span>", f.pass.name, stats)) 720 f.HTMLWriter.flushPhases() 721 } 722 f.fe.Fatalf(f.Entry.Pos, msg, args...) 723 } 724 725 // postorder returns the reachable blocks in f in a postorder traversal. 726 func (f *Func) postorder() []*Block { 727 if f.cachedPostorder == nil { 728 f.cachedPostorder = postorder(f) 729 } 730 return f.cachedPostorder 731 } 732 733 func (f *Func) Postorder() []*Block { 734 return f.postorder() 735 } 736 737 // Idom returns a map from block ID to the immediate dominator of that block. 738 // f.Entry.ID maps to nil. Unreachable blocks map to nil as well. 739 func (f *Func) Idom() []*Block { 740 if f.cachedIdom == nil { 741 f.cachedIdom = dominators(f) 742 } 743 return f.cachedIdom 744 } 745 746 // Sdom returns a sparse tree representing the dominator relationships 747 // among the blocks of f. 748 func (f *Func) Sdom() SparseTree { 749 if f.cachedSdom == nil { 750 f.cachedSdom = newSparseTree(f, f.Idom()) 751 } 752 return f.cachedSdom 753 } 754 755 // loopnest returns the loop nest information for f. 756 func (f *Func) loopnest() *loopnest { 757 if f.cachedLoopnest == nil { 758 f.cachedLoopnest = loopnestfor(f) 759 } 760 return f.cachedLoopnest 761 } 762 763 // invalidateCFG tells f that its CFG has changed. 764 func (f *Func) invalidateCFG() { 765 f.cachedPostorder = nil 766 f.cachedIdom = nil 767 f.cachedSdom = nil 768 f.cachedLoopnest = nil 769 } 770 771 // DebugHashMatch returns 772 // 773 // base.DebugHashMatch(this function's package.name) 774 // 775 // for use in bug isolation. The return value is true unless 776 // environment variable GOSSAHASH is set, in which case "it depends". 777 // See [base.DebugHashMatch] for more information. 778 func (f *Func) DebugHashMatch() bool { 779 if !base.HasDebugHash() { 780 return true 781 } 782 name := f.fe.MyImportPath() + "." + f.Name 783 return base.DebugHashMatch(name) 784 } 785 786 func (f *Func) spSb() (sp, sb *Value) { 787 initpos := src.NoXPos // These are originally created with no position in ssa.go; if they are optimized out then recreated, should be the same. 788 for _, v := range f.Entry.Values { 789 if v.Op == OpSB { 790 sb = v 791 } 792 if v.Op == OpSP { 793 sp = v 794 } 795 if sb != nil && sp != nil { 796 return 797 } 798 } 799 if sb == nil { 800 sb = f.Entry.NewValue0(initpos.WithNotStmt(), OpSB, f.Config.Types.Uintptr) 801 } 802 if sp == nil { 803 sp = f.Entry.NewValue0(initpos.WithNotStmt(), OpSP, f.Config.Types.Uintptr) 804 } 805 return 806 } 807 808 // useFMA allows targeted debugging w/ GOFMAHASH 809 // If you have an architecture-dependent FP glitch, this will help you find it. 810 func (f *Func) useFMA(v *Value) bool { 811 if !f.Config.UseFMA { 812 return false 813 } 814 if base.FmaHash == nil { 815 return true 816 } 817 ctxt := v.Block.Func.Config.Ctxt() 818 return base.FmaHash.DebugHashMatchPos(ctxt, v.Pos) 819 }