github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/go/ssa/func14.go (about) 1 // Copyright 2013 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 // +build !go1.5 6 7 package ssa 8 9 // This file implements the Function and BasicBlock types. 10 11 import ( 12 "bytes" 13 "fmt" 14 "go/ast" 15 "go/token" 16 "io" 17 "os" 18 "strings" 19 20 "golang.org/x/tools/go/types" 21 ) 22 23 // addEdge adds a control-flow graph edge from from to to. 24 func addEdge(from, to *BasicBlock) { 25 from.Succs = append(from.Succs, to) 26 to.Preds = append(to.Preds, from) 27 } 28 29 // Parent returns the function that contains block b. 30 func (b *BasicBlock) Parent() *Function { return b.parent } 31 32 // String returns a human-readable label of this block. 33 // It is not guaranteed unique within the function. 34 // 35 func (b *BasicBlock) String() string { 36 return fmt.Sprintf("%d", b.Index) 37 } 38 39 // emit appends an instruction to the current basic block. 40 // If the instruction defines a Value, it is returned. 41 // 42 func (b *BasicBlock) emit(i Instruction) Value { 43 i.setBlock(b) 44 b.Instrs = append(b.Instrs, i) 45 v, _ := i.(Value) 46 return v 47 } 48 49 // predIndex returns the i such that b.Preds[i] == c or panics if 50 // there is none. 51 func (b *BasicBlock) predIndex(c *BasicBlock) int { 52 for i, pred := range b.Preds { 53 if pred == c { 54 return i 55 } 56 } 57 panic(fmt.Sprintf("no edge %s -> %s", c, b)) 58 } 59 60 // hasPhi returns true if b.Instrs contains φ-nodes. 61 func (b *BasicBlock) hasPhi() bool { 62 _, ok := b.Instrs[0].(*Phi) 63 return ok 64 } 65 66 // phis returns the prefix of b.Instrs containing all the block's φ-nodes. 67 func (b *BasicBlock) phis() []Instruction { 68 for i, instr := range b.Instrs { 69 if _, ok := instr.(*Phi); !ok { 70 return b.Instrs[:i] 71 } 72 } 73 return nil // unreachable in well-formed blocks 74 } 75 76 // replacePred replaces all occurrences of p in b's predecessor list with q. 77 // Ordinarily there should be at most one. 78 // 79 func (b *BasicBlock) replacePred(p, q *BasicBlock) { 80 for i, pred := range b.Preds { 81 if pred == p { 82 b.Preds[i] = q 83 } 84 } 85 } 86 87 // replaceSucc replaces all occurrences of p in b's successor list with q. 88 // Ordinarily there should be at most one. 89 // 90 func (b *BasicBlock) replaceSucc(p, q *BasicBlock) { 91 for i, succ := range b.Succs { 92 if succ == p { 93 b.Succs[i] = q 94 } 95 } 96 } 97 98 // removePred removes all occurrences of p in b's 99 // predecessor list and φ-nodes. 100 // Ordinarily there should be at most one. 101 // 102 func (b *BasicBlock) removePred(p *BasicBlock) { 103 phis := b.phis() 104 105 // We must preserve edge order for φ-nodes. 106 j := 0 107 for i, pred := range b.Preds { 108 if pred != p { 109 b.Preds[j] = b.Preds[i] 110 // Strike out φ-edge too. 111 for _, instr := range phis { 112 phi := instr.(*Phi) 113 phi.Edges[j] = phi.Edges[i] 114 } 115 j++ 116 } 117 } 118 // Nil out b.Preds[j:] and φ-edges[j:] to aid GC. 119 for i := j; i < len(b.Preds); i++ { 120 b.Preds[i] = nil 121 for _, instr := range phis { 122 instr.(*Phi).Edges[i] = nil 123 } 124 } 125 b.Preds = b.Preds[:j] 126 for _, instr := range phis { 127 phi := instr.(*Phi) 128 phi.Edges = phi.Edges[:j] 129 } 130 } 131 132 // Destinations associated with unlabelled for/switch/select stmts. 133 // We push/pop one of these as we enter/leave each construct and for 134 // each BranchStmt we scan for the innermost target of the right type. 135 // 136 type targets struct { 137 tail *targets // rest of stack 138 _break *BasicBlock 139 _continue *BasicBlock 140 _fallthrough *BasicBlock 141 } 142 143 // Destinations associated with a labelled block. 144 // We populate these as labels are encountered in forward gotos or 145 // labelled statements. 146 // 147 type lblock struct { 148 _goto *BasicBlock 149 _break *BasicBlock 150 _continue *BasicBlock 151 } 152 153 // labelledBlock returns the branch target associated with the 154 // specified label, creating it if needed. 155 // 156 func (f *Function) labelledBlock(label *ast.Ident) *lblock { 157 lb := f.lblocks[label.Obj] 158 if lb == nil { 159 lb = &lblock{_goto: f.newBasicBlock(label.Name)} 160 if f.lblocks == nil { 161 f.lblocks = make(map[*ast.Object]*lblock) 162 } 163 f.lblocks[label.Obj] = lb 164 } 165 return lb 166 } 167 168 // addParam adds a (non-escaping) parameter to f.Params of the 169 // specified name, type and source position. 170 // 171 func (f *Function) addParam(name string, typ types.Type, pos token.Pos) *Parameter { 172 v := &Parameter{ 173 name: name, 174 typ: typ, 175 pos: pos, 176 parent: f, 177 } 178 f.Params = append(f.Params, v) 179 return v 180 } 181 182 func (f *Function) addParamObj(obj types.Object) *Parameter { 183 name := obj.Name() 184 if name == "" { 185 name = fmt.Sprintf("arg%d", len(f.Params)) 186 } 187 param := f.addParam(name, obj.Type(), obj.Pos()) 188 param.object = obj 189 return param 190 } 191 192 // addSpilledParam declares a parameter that is pre-spilled to the 193 // stack; the function body will load/store the spilled location. 194 // Subsequent lifting will eliminate spills where possible. 195 // 196 func (f *Function) addSpilledParam(obj types.Object) { 197 param := f.addParamObj(obj) 198 spill := &Alloc{Comment: obj.Name()} 199 spill.setType(types.NewPointer(obj.Type())) 200 spill.setPos(obj.Pos()) 201 f.objects[obj] = spill 202 f.Locals = append(f.Locals, spill) 203 f.emit(spill) 204 f.emit(&Store{Addr: spill, Val: param}) 205 } 206 207 // startBody initializes the function prior to generating SSA code for its body. 208 // Precondition: f.Type() already set. 209 // 210 func (f *Function) startBody() { 211 f.currentBlock = f.newBasicBlock("entry") 212 f.objects = make(map[types.Object]Value) // needed for some synthetics, e.g. init 213 } 214 215 // createSyntacticParams populates f.Params and generates code (spills 216 // and named result locals) for all the parameters declared in the 217 // syntax. In addition it populates the f.objects mapping. 218 // 219 // Preconditions: 220 // f.startBody() was called. 221 // Postcondition: 222 // len(f.Params) == len(f.Signature.Params) + (f.Signature.Recv() ? 1 : 0) 223 // 224 func (f *Function) createSyntacticParams(recv *ast.FieldList, functype *ast.FuncType) { 225 // Receiver (at most one inner iteration). 226 if recv != nil { 227 for _, field := range recv.List { 228 for _, n := range field.Names { 229 f.addSpilledParam(f.Pkg.info.Defs[n]) 230 } 231 // Anonymous receiver? No need to spill. 232 if field.Names == nil { 233 f.addParamObj(f.Signature.Recv()) 234 } 235 } 236 } 237 238 // Parameters. 239 if functype.Params != nil { 240 n := len(f.Params) // 1 if has recv, 0 otherwise 241 for _, field := range functype.Params.List { 242 for _, n := range field.Names { 243 f.addSpilledParam(f.Pkg.info.Defs[n]) 244 } 245 // Anonymous parameter? No need to spill. 246 if field.Names == nil { 247 f.addParamObj(f.Signature.Params().At(len(f.Params) - n)) 248 } 249 } 250 } 251 252 // Named results. 253 if functype.Results != nil { 254 for _, field := range functype.Results.List { 255 // Implicit "var" decl of locals for named results. 256 for _, n := range field.Names { 257 f.namedResults = append(f.namedResults, f.addLocalForIdent(n)) 258 } 259 } 260 } 261 } 262 263 // numberRegisters assigns numbers to all SSA registers 264 // (value-defining Instructions) in f, to aid debugging. 265 // (Non-Instruction Values are named at construction.) 266 // 267 func numberRegisters(f *Function) { 268 v := 0 269 for _, b := range f.Blocks { 270 for _, instr := range b.Instrs { 271 switch instr.(type) { 272 case Value: 273 instr.(interface { 274 setNum(int) 275 }).setNum(v) 276 v++ 277 } 278 } 279 } 280 } 281 282 // buildReferrers populates the def/use information in all non-nil 283 // Value.Referrers slice. 284 // Precondition: all such slices are initially empty. 285 func buildReferrers(f *Function) { 286 var rands []*Value 287 for _, b := range f.Blocks { 288 for _, instr := range b.Instrs { 289 rands = instr.Operands(rands[:0]) // recycle storage 290 for _, rand := range rands { 291 if r := *rand; r != nil { 292 if ref := r.Referrers(); ref != nil { 293 *ref = append(*ref, instr) 294 } 295 } 296 } 297 } 298 } 299 } 300 301 // finishBody() finalizes the function after SSA code generation of its body. 302 func (f *Function) finishBody() { 303 f.objects = nil 304 f.currentBlock = nil 305 f.lblocks = nil 306 307 // Don't pin the AST in memory (except in debug mode). 308 if n := f.syntax; n != nil && !f.debugInfo() { 309 f.syntax = extentNode{n.Pos(), n.End()} 310 } 311 312 // Remove from f.Locals any Allocs that escape to the heap. 313 j := 0 314 for _, l := range f.Locals { 315 if !l.Heap { 316 f.Locals[j] = l 317 j++ 318 } 319 } 320 // Nil out f.Locals[j:] to aid GC. 321 for i := j; i < len(f.Locals); i++ { 322 f.Locals[i] = nil 323 } 324 f.Locals = f.Locals[:j] 325 326 optimizeBlocks(f) 327 328 buildReferrers(f) 329 330 buildDomTree(f) 331 332 if f.Prog.mode&NaiveForm == 0 { 333 // For debugging pre-state of lifting pass: 334 // numberRegisters(f) 335 // f.WriteTo(os.Stderr) 336 lift(f) 337 } 338 339 f.namedResults = nil // (used by lifting) 340 341 numberRegisters(f) 342 343 if f.Prog.mode&PrintFunctions != 0 { 344 printMu.Lock() 345 f.WriteTo(os.Stdout) 346 printMu.Unlock() 347 } 348 349 if f.Prog.mode&SanityCheckFunctions != 0 { 350 mustSanityCheck(f, nil) 351 } 352 } 353 354 // removeNilBlocks eliminates nils from f.Blocks and updates each 355 // BasicBlock.Index. Use this after any pass that may delete blocks. 356 // 357 func (f *Function) removeNilBlocks() { 358 j := 0 359 for _, b := range f.Blocks { 360 if b != nil { 361 b.Index = j 362 f.Blocks[j] = b 363 j++ 364 } 365 } 366 // Nil out f.Blocks[j:] to aid GC. 367 for i := j; i < len(f.Blocks); i++ { 368 f.Blocks[i] = nil 369 } 370 f.Blocks = f.Blocks[:j] 371 } 372 373 // SetDebugMode sets the debug mode for package pkg. If true, all its 374 // functions will include full debug info. This greatly increases the 375 // size of the instruction stream, and causes Functions to depend upon 376 // the ASTs, potentially keeping them live in memory for longer. 377 // 378 func (pkg *Package) SetDebugMode(debug bool) { 379 // TODO(adonovan): do we want ast.File granularity? 380 pkg.debug = debug 381 } 382 383 // debugInfo reports whether debug info is wanted for this function. 384 func (f *Function) debugInfo() bool { 385 return f.Pkg != nil && f.Pkg.debug 386 } 387 388 // addNamedLocal creates a local variable, adds it to function f and 389 // returns it. Its name and type are taken from obj. Subsequent 390 // calls to f.lookup(obj) will return the same local. 391 // 392 func (f *Function) addNamedLocal(obj types.Object) *Alloc { 393 l := f.addLocal(obj.Type(), obj.Pos()) 394 l.Comment = obj.Name() 395 f.objects[obj] = l 396 return l 397 } 398 399 func (f *Function) addLocalForIdent(id *ast.Ident) *Alloc { 400 return f.addNamedLocal(f.Pkg.info.Defs[id]) 401 } 402 403 // addLocal creates an anonymous local variable of type typ, adds it 404 // to function f and returns it. pos is the optional source location. 405 // 406 func (f *Function) addLocal(typ types.Type, pos token.Pos) *Alloc { 407 v := &Alloc{} 408 v.setType(types.NewPointer(typ)) 409 v.setPos(pos) 410 f.Locals = append(f.Locals, v) 411 f.emit(v) 412 return v 413 } 414 415 // lookup returns the address of the named variable identified by obj 416 // that is local to function f or one of its enclosing functions. 417 // If escaping, the reference comes from a potentially escaping pointer 418 // expression and the referent must be heap-allocated. 419 // 420 func (f *Function) lookup(obj types.Object, escaping bool) Value { 421 if v, ok := f.objects[obj]; ok { 422 if alloc, ok := v.(*Alloc); ok && escaping { 423 alloc.Heap = true 424 } 425 return v // function-local var (address) 426 } 427 428 // Definition must be in an enclosing function; 429 // plumb it through intervening closures. 430 if f.parent == nil { 431 panic("no ssa.Value for " + obj.String()) 432 } 433 outer := f.parent.lookup(obj, true) // escaping 434 v := &FreeVar{ 435 name: obj.Name(), 436 typ: outer.Type(), 437 pos: outer.Pos(), 438 outer: outer, 439 parent: f, 440 } 441 f.objects[obj] = v 442 f.FreeVars = append(f.FreeVars, v) 443 return v 444 } 445 446 // emit emits the specified instruction to function f. 447 func (f *Function) emit(instr Instruction) Value { 448 return f.currentBlock.emit(instr) 449 } 450 451 // RelString returns the full name of this function, qualified by 452 // package name, receiver type, etc. 453 // 454 // The specific formatting rules are not guaranteed and may change. 455 // 456 // Examples: 457 // "math.IsNaN" // a package-level function 458 // "(*bytes.Buffer).Bytes" // a declared method or a wrapper 459 // "(*bytes.Buffer).Bytes$thunk" // thunk (func wrapping method; receiver is param 0) 460 // "(*bytes.Buffer).Bytes$bound" // bound (func wrapping method; receiver supplied by closure) 461 // "main.main$1" // an anonymous function in main 462 // "main.init#1" // a declared init function 463 // "main.init" // the synthesized package initializer 464 // 465 // When these functions are referred to from within the same package 466 // (i.e. from == f.Pkg.Object), they are rendered without the package path. 467 // For example: "IsNaN", "(*Buffer).Bytes", etc. 468 // 469 // All non-synthetic functions have distinct package-qualified names. 470 // (But two methods may have the same name "(T).f" if one is a synthetic 471 // wrapper promoting a non-exported method "f" from another package; in 472 // that case, the strings are equal but the identifiers "f" are distinct.) 473 // 474 func (f *Function) RelString(from *types.Package) string { 475 // Anonymous? 476 if f.parent != nil { 477 // An anonymous function's Name() looks like "parentName$1", 478 // but its String() should include the type/package/etc. 479 parent := f.parent.RelString(from) 480 for i, anon := range f.parent.AnonFuncs { 481 if anon == f { 482 return fmt.Sprintf("%s$%d", parent, 1+i) 483 } 484 } 485 486 return f.name // should never happen 487 } 488 489 // Method (declared or wrapper)? 490 if recv := f.Signature.Recv(); recv != nil { 491 return f.relMethod(from, recv.Type()) 492 } 493 494 // Thunk? 495 if f.method != nil { 496 return f.relMethod(from, f.method.Recv()) 497 } 498 499 // Bound? 500 if len(f.FreeVars) == 1 && strings.HasSuffix(f.name, "$bound") { 501 return f.relMethod(from, f.FreeVars[0].Type()) 502 } 503 504 // Package-level function? 505 // Prefix with package name for cross-package references only. 506 if p := f.pkg(); p != nil && p != from { 507 return fmt.Sprintf("%s.%s", p.Path(), f.name) 508 } 509 510 // Unknown. 511 return f.name 512 } 513 514 func (f *Function) relMethod(from *types.Package, recv types.Type) string { 515 return fmt.Sprintf("(%s).%s", relType(recv, from), f.name) 516 } 517 518 // writeSignature writes to buf the signature sig in declaration syntax. 519 func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *types.Signature, params []*Parameter) { 520 buf.WriteString("func ") 521 if recv := sig.Recv(); recv != nil { 522 buf.WriteString("(") 523 if n := params[0].Name(); n != "" { 524 buf.WriteString(n) 525 buf.WriteString(" ") 526 } 527 types.WriteType(buf, params[0].Type(), types.RelativeTo(from)) 528 buf.WriteString(") ") 529 } 530 buf.WriteString(name) 531 types.WriteSignature(buf, sig, types.RelativeTo(from)) 532 } 533 534 func (f *Function) pkg() *types.Package { 535 if f.Pkg != nil { 536 return f.Pkg.Pkg 537 } 538 return nil 539 } 540 541 var _ io.WriterTo = (*Function)(nil) // *Function implements io.Writer 542 543 func (f *Function) WriteTo(w io.Writer) (int64, error) { 544 var buf bytes.Buffer 545 WriteFunction(&buf, f) 546 n, err := w.Write(buf.Bytes()) 547 return int64(n), err 548 } 549 550 // WriteFunction writes to buf a human-readable "disassembly" of f. 551 func WriteFunction(buf *bytes.Buffer, f *Function) { 552 fmt.Fprintf(buf, "# Name: %s\n", f.String()) 553 if f.Pkg != nil { 554 fmt.Fprintf(buf, "# Package: %s\n", f.Pkg.Pkg.Path()) 555 } 556 if syn := f.Synthetic; syn != "" { 557 fmt.Fprintln(buf, "# Synthetic:", syn) 558 } 559 if pos := f.Pos(); pos.IsValid() { 560 fmt.Fprintf(buf, "# Location: %s\n", f.Prog.Fset.Position(pos)) 561 } 562 563 if f.parent != nil { 564 fmt.Fprintf(buf, "# Parent: %s\n", f.parent.Name()) 565 } 566 567 if f.Recover != nil { 568 fmt.Fprintf(buf, "# Recover: %s\n", f.Recover) 569 } 570 571 from := f.pkg() 572 573 if f.FreeVars != nil { 574 buf.WriteString("# Free variables:\n") 575 for i, fv := range f.FreeVars { 576 fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, fv.Name(), relType(fv.Type(), from)) 577 } 578 } 579 580 if len(f.Locals) > 0 { 581 buf.WriteString("# Locals:\n") 582 for i, l := range f.Locals { 583 fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, l.Name(), relType(deref(l.Type()), from)) 584 } 585 } 586 writeSignature(buf, from, f.Name(), f.Signature, f.Params) 587 buf.WriteString(":\n") 588 589 if f.Blocks == nil { 590 buf.WriteString("\t(external)\n") 591 } 592 593 // NB. column calculations are confused by non-ASCII 594 // characters and assume 8-space tabs. 595 const punchcard = 80 // for old time's sake. 596 const tabwidth = 8 597 for _, b := range f.Blocks { 598 if b == nil { 599 // Corrupt CFG. 600 fmt.Fprintf(buf, ".nil:\n") 601 continue 602 } 603 n, _ := fmt.Fprintf(buf, "%d:", b.Index) 604 bmsg := fmt.Sprintf("%s P:%d S:%d", b.Comment, len(b.Preds), len(b.Succs)) 605 fmt.Fprintf(buf, "%*s%s\n", punchcard-1-n-len(bmsg), "", bmsg) 606 607 if false { // CFG debugging 608 fmt.Fprintf(buf, "\t# CFG: %s --> %s --> %s\n", b.Preds, b, b.Succs) 609 } 610 for _, instr := range b.Instrs { 611 buf.WriteString("\t") 612 switch v := instr.(type) { 613 case Value: 614 l := punchcard - tabwidth 615 // Left-align the instruction. 616 if name := v.Name(); name != "" { 617 n, _ := fmt.Fprintf(buf, "%s = ", name) 618 l -= n 619 } 620 n, _ := buf.WriteString(instr.String()) 621 l -= n 622 // Right-align the type if there's space. 623 if t := v.Type(); t != nil { 624 buf.WriteByte(' ') 625 ts := relType(t, from) 626 l -= len(ts) + len(" ") // (spaces before and after type) 627 if l > 0 { 628 fmt.Fprintf(buf, "%*s", l, "") 629 } 630 buf.WriteString(ts) 631 } 632 case nil: 633 // Be robust against bad transforms. 634 buf.WriteString("<deleted>") 635 default: 636 buf.WriteString(instr.String()) 637 } 638 buf.WriteString("\n") 639 } 640 } 641 fmt.Fprintf(buf, "\n") 642 } 643 644 // newBasicBlock adds to f a new basic block and returns it. It does 645 // not automatically become the current block for subsequent calls to emit. 646 // comment is an optional string for more readable debugging output. 647 // 648 func (f *Function) newBasicBlock(comment string) *BasicBlock { 649 b := &BasicBlock{ 650 Index: len(f.Blocks), 651 Comment: comment, 652 parent: f, 653 } 654 b.Succs = b.succs2[:0] 655 f.Blocks = append(f.Blocks, b) 656 return b 657 } 658 659 // NewFunction returns a new synthetic Function instance belonging to 660 // prog, with its name and signature fields set as specified. 661 // 662 // The caller is responsible for initializing the remaining fields of 663 // the function object, e.g. Pkg, Params, Blocks. 664 // 665 // It is practically impossible for clients to construct well-formed 666 // SSA functions/packages/programs directly, so we assume this is the 667 // job of the Builder alone. NewFunction exists to provide clients a 668 // little flexibility. For example, analysis tools may wish to 669 // construct fake Functions for the root of the callgraph, a fake 670 // "reflect" package, etc. 671 // 672 // TODO(adonovan): think harder about the API here. 673 // 674 func (prog *Program) NewFunction(name string, sig *types.Signature, provenance string) *Function { 675 return &Function{Prog: prog, name: name, Signature: sig, Synthetic: provenance} 676 } 677 678 type extentNode [2]token.Pos 679 680 func (n extentNode) Pos() token.Pos { return n[0] } 681 func (n extentNode) End() token.Pos { return n[1] } 682 683 // Syntax returns an ast.Node whose Pos/End methods provide the 684 // lexical extent of the function if it was defined by Go source code 685 // (f.Synthetic==""), or nil otherwise. 686 // 687 // If f was built with debug information (see Package.SetDebugRef), 688 // the result is the *ast.FuncDecl or *ast.FuncLit that declared the 689 // function. Otherwise, it is an opaque Node providing only position 690 // information; this avoids pinning the AST in memory. 691 // 692 func (f *Function) Syntax() ast.Node { return f.syntax }