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