podman
131 строка · 4.0 Кб
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
5package obj6
7import "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).
44type InlTree struct {45nodes []InlinedCall46}
47
48// InlinedCall is a node in an InlTree.
49type InlinedCall struct {50Parent int // index of the parent in the InlTree or < 0 if outermost call51Pos src.XPos // position of the inlined call52Func *LSym // function that was inlined53ParentPC 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.
57func (tree *InlTree) Add(parent int, pos src.XPos, func_ *LSym) int {58r := len(tree.nodes)59call := InlinedCall{60Parent: parent,61Pos: pos,62Func: func_,63}64tree.nodes = append(tree.nodes, call)65return r66}
67
68func (tree *InlTree) Parent(inlIndex int) int {69return tree.nodes[inlIndex].Parent70}
71
72func (tree *InlTree) InlinedFunction(inlIndex int) *LSym {73return tree.nodes[inlIndex].Func74}
75
76func (tree *InlTree) CallPos(inlIndex int) src.XPos {77return tree.nodes[inlIndex].Pos78}
79
80func (tree *InlTree) setParentPC(inlIndex int, pc int32) {81tree.nodes[inlIndex].ParentPC = pc82}
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.
88func (ctxt *Link) OutermostPos(xpos src.XPos) src.Pos {89pos := ctxt.InnermostPos(xpos)90
91outerxpos := xpos92for ix := pos.Base().InliningIndex(); ix >= 0; {93call := ctxt.InlTree.nodes[ix]94ix = call.Parent95outerxpos = call.Pos96}97return 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.
107func (ctxt *Link) InnermostPos(xpos src.XPos) src.Pos {108return 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.
114func (ctxt *Link) AllPos(xpos src.XPos, result []src.Pos) []src.Pos {115pos := ctxt.InnermostPos(xpos)116result = result[:0]117result = append(result, ctxt.PosTable.Pos(xpos))118for ix := pos.Base().InliningIndex(); ix >= 0; {119call := ctxt.InlTree.nodes[ix]120ix = call.Parent121result = append(result, ctxt.PosTable.Pos(call.Pos))122}123return result124}
125
126func dumpInlTree(ctxt *Link, tree InlTree) {127for i, call := range tree.nodes {128pos := ctxt.PosTable.Pos(call.Pos)129ctxt.Logf("%0d | %0d | %s (%s) pc=%d\n", i, call.Parent, call.Func, pos, call.ParentPC)130}131}
132