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