github.com/karrick/go@v0.0.0-20170817181416-d5b0ec858b37/src/cmd/internal/obj/inl.go (about)

     1  // Copyright 2017 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 obj
     6  
     7  import "cmd/internal/src"
     8  
     9  // InlTree s a collection of inlined calls. The Parent field of an
    10  // InlinedCall is the index of another InlinedCall in InlTree.
    11  //
    12  // The compiler maintains a global inlining tree and adds a node to it
    13  // every time a function is inlined. For example, suppose f() calls g()
    14  // and g has two calls to h(), and that f, g, and h are inlineable:
    15  //
    16  //  1 func main() {
    17  //  2     f()
    18  //  3 }
    19  //  4 func f() {
    20  //  5     g()
    21  //  6 }
    22  //  7 func g() {
    23  //  8     h()
    24  //  9     h()
    25  // 10 }
    26  //
    27  // Assuming the global tree starts empty, inlining will produce the
    28  // following tree:
    29  //
    30  //   []InlinedCall{
    31  //     {Parent: -1, Func: "f", Pos: <line 2>},
    32  //     {Parent:  0, Func: "g", Pos: <line 5>},
    33  //     {Parent:  1, Func: "h", Pos: <line 8>},
    34  //     {Parent:  1, Func: "h", Pos: <line 9>},
    35  //   }
    36  //
    37  // The nodes of h inlined into main will have inlining indexes 2 and 3.
    38  //
    39  // Eventually, the compiler extracts a per-function inlining tree from
    40  // the global inlining tree (see pcln.go).
    41  type InlTree struct {
    42  	nodes []InlinedCall
    43  }
    44  
    45  // InlinedCall is a node in an InlTree.
    46  type InlinedCall struct {
    47  	Parent int      // index of the parent in the InlTree or < 0 if outermost call
    48  	Pos    src.XPos // position of the inlined call
    49  	Func   *LSym    // function that was inlined
    50  }
    51  
    52  // Add adds a new call to the tree, returning its index.
    53  func (tree *InlTree) Add(parent int, pos src.XPos, func_ *LSym) int {
    54  	r := len(tree.nodes)
    55  	call := InlinedCall{
    56  		Parent: parent,
    57  		Pos:    pos,
    58  		Func:   func_,
    59  	}
    60  	tree.nodes = append(tree.nodes, call)
    61  	return r
    62  }
    63  
    64  // OutermostPos returns the outermost position corresponding to xpos,
    65  // which is where xpos was ultimately inlined to. In the example for
    66  // InlTree, main() contains inlined AST nodes from h(), but the
    67  // outermost position for those nodes is line 2.
    68  func (ctxt *Link) OutermostPos(xpos src.XPos) src.Pos {
    69  	pos := ctxt.PosTable.Pos(xpos)
    70  
    71  	outerxpos := xpos
    72  	for ix := pos.Base().InliningIndex(); ix >= 0; {
    73  		call := ctxt.InlTree.nodes[ix]
    74  		ix = call.Parent
    75  		outerxpos = call.Pos
    76  	}
    77  	return ctxt.PosTable.Pos(outerxpos)
    78  }
    79  
    80  func dumpInlTree(ctxt *Link, tree InlTree) {
    81  	for i, call := range tree.nodes {
    82  		pos := ctxt.PosTable.Pos(call.Pos)
    83  		ctxt.Logf("%0d | %0d | %s (%s)\n", i, call.Parent, call.Func, pos)
    84  	}
    85  }