gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

inl.go (4114B)


      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 "github.com/twitchyliquid64/golang-asm/src"
      8 
      9 // InlTree is 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 // 11 func h() {
     27 // 12     println("H")
     28 // 13 }
     29 //
     30 // Assuming the global tree starts empty, inlining will produce the
     31 // following tree:
     32 //
     33 //   []InlinedCall{
     34 //     {Parent: -1, Func: "f", Pos: <line 2>},
     35 //     {Parent:  0, Func: "g", Pos: <line 5>},
     36 //     {Parent:  1, Func: "h", Pos: <line 8>},
     37 //     {Parent:  1, Func: "h", Pos: <line 9>},
     38 //   }
     39 //
     40 // The nodes of h inlined into main will have inlining indexes 2 and 3.
     41 //
     42 // Eventually, the compiler extracts a per-function inlining tree from
     43 // the global inlining tree (see pcln.go).
     44 type InlTree struct {
     45 	nodes []InlinedCall
     46 }
     47 
     48 // InlinedCall is a node in an InlTree.
     49 type InlinedCall struct {
     50 	Parent   int      // index of the parent in the InlTree or < 0 if outermost call
     51 	Pos      src.XPos // position of the inlined call
     52 	Func     *LSym    // function that was inlined
     53 	ParentPC int32    // PC of instruction just before inlined body. Only valid in local trees.
     54 }
     55 
     56 // Add adds a new call to the tree, returning its index.
     57 func (tree *InlTree) Add(parent int, pos src.XPos, func_ *LSym) int {
     58 	r := len(tree.nodes)
     59 	call := InlinedCall{
     60 		Parent: parent,
     61 		Pos:    pos,
     62 		Func:   func_,
     63 	}
     64 	tree.nodes = append(tree.nodes, call)
     65 	return r
     66 }
     67 
     68 func (tree *InlTree) Parent(inlIndex int) int {
     69 	return tree.nodes[inlIndex].Parent
     70 }
     71 
     72 func (tree *InlTree) InlinedFunction(inlIndex int) *LSym {
     73 	return tree.nodes[inlIndex].Func
     74 }
     75 
     76 func (tree *InlTree) CallPos(inlIndex int) src.XPos {
     77 	return tree.nodes[inlIndex].Pos
     78 }
     79 
     80 func (tree *InlTree) setParentPC(inlIndex int, pc int32) {
     81 	tree.nodes[inlIndex].ParentPC = pc
     82 }
     83 
     84 // OutermostPos returns the outermost position corresponding to xpos,
     85 // which is where xpos was ultimately inlined to. In the example for
     86 // InlTree, main() contains inlined AST nodes from h(), but the
     87 // outermost position for those nodes is line 2.
     88 func (ctxt *Link) OutermostPos(xpos src.XPos) src.Pos {
     89 	pos := ctxt.InnermostPos(xpos)
     90 
     91 	outerxpos := xpos
     92 	for ix := pos.Base().InliningIndex(); ix >= 0; {
     93 		call := ctxt.InlTree.nodes[ix]
     94 		ix = call.Parent
     95 		outerxpos = call.Pos
     96 	}
     97 	return ctxt.PosTable.Pos(outerxpos)
     98 }
     99 
    100 // InnermostPos returns the innermost position corresponding to xpos,
    101 // that is, the code that is inlined and that inlines nothing else.
    102 // In the example for InlTree above, the code for println within h
    103 // would have an innermost position with line number 12, whether
    104 // h was not inlined, inlined into g, g-then-f, or g-then-f-then-main.
    105 // This corresponds to what someone debugging main, f, g, or h might
    106 // expect to see while single-stepping.
    107 func (ctxt *Link) InnermostPos(xpos src.XPos) src.Pos {
    108 	return ctxt.PosTable.Pos(xpos)
    109 }
    110 
    111 // AllPos returns a slice of the positions inlined at xpos, from
    112 // innermost (index zero) to outermost.  To avoid gratuitous allocation
    113 // the result is passed in and extended if necessary.
    114 func (ctxt *Link) AllPos(xpos src.XPos, result []src.Pos) []src.Pos {
    115 	pos := ctxt.InnermostPos(xpos)
    116 	result = result[:0]
    117 	result = append(result, ctxt.PosTable.Pos(xpos))
    118 	for ix := pos.Base().InliningIndex(); ix >= 0; {
    119 		call := ctxt.InlTree.nodes[ix]
    120 		ix = call.Parent
    121 		result = append(result, ctxt.PosTable.Pos(call.Pos))
    122 	}
    123 	return result
    124 }
    125 
    126 func dumpInlTree(ctxt *Link, tree InlTree) {
    127 	for i, call := range tree.nodes {
    128 		pos := ctxt.PosTable.Pos(call.Pos)
    129 		ctxt.Logf("%0d | %0d | %s (%s) pc=%d\n", i, call.Parent, call.Func, pos, call.ParentPC)
    130 	}
    131 }