Source file src/pkg/cmd/compile/internal/gc/dwinl.go
1
2
3
4
5 package gc
6
7 import (
8 "cmd/internal/dwarf"
9 "cmd/internal/obj"
10 "cmd/internal/src"
11 "strings"
12 )
13
14
15 type varPos struct {
16 DeclName string
17 DeclFile string
18 DeclLine uint
19 DeclCol uint
20 }
21
22
23
24
25 func assembleInlines(fnsym *obj.LSym, dwVars []*dwarf.Var) dwarf.InlCalls {
26 var inlcalls dwarf.InlCalls
27
28 if Debug_gendwarfinl != 0 {
29 Ctxt.Logf("assembling DWARF inlined routine info for %v\n", fnsym.Name)
30 }
31
32
33 imap := make(map[int]int)
34
35
36 var prevpos src.XPos
37 for p := fnsym.Func.Text; p != nil; p = p.Link {
38 if p.Pos == prevpos {
39 continue
40 }
41 ii := posInlIndex(p.Pos)
42 if ii >= 0 {
43 insertInlCall(&inlcalls, ii, imap)
44 }
45 prevpos = p.Pos
46 }
47
48
49
50 vmap := make(map[int32][]*dwarf.Var)
51
52
53
54
55 for _, dwv := range dwVars {
56
57 vmap[dwv.InlIndex] = append(vmap[dwv.InlIndex], dwv)
58
59
60 if dwv.InlIndex == 0 {
61 continue
62 }
63
64
65
66 ii := int(dwv.InlIndex) - 1
67 idx, ok := imap[ii]
68 if !ok {
69
70
71
72 idx = insertInlCall(&inlcalls, ii, imap)
73 }
74 inlcalls.Calls[idx].InlVars =
75 append(inlcalls.Calls[idx].InlVars, dwv)
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 for ii, sl := range vmap {
98 var m map[varPos]int
99 if ii == 0 {
100 if !fnsym.WasInlined() {
101 for j, v := range sl {
102 v.ChildIndex = int32(j)
103 }
104 continue
105 }
106 m = makePreinlineDclMap(fnsym)
107 } else {
108 ifnlsym := Ctxt.InlTree.InlinedFunction(int(ii - 1))
109 m = makePreinlineDclMap(ifnlsym)
110 }
111
112
113
114
115
116
117
118
119
120
121 synthCount := len(m)
122 for _, v := range sl {
123 canonName := unversion(v.Name)
124 vp := varPos{
125 DeclName: canonName,
126 DeclFile: v.DeclFile,
127 DeclLine: v.DeclLine,
128 DeclCol: v.DeclCol,
129 }
130 synthesized := strings.HasPrefix(v.Name, "~r") || canonName == "_" || strings.HasPrefix(v.Name, "~b")
131 if idx, found := m[vp]; found {
132 v.ChildIndex = int32(idx)
133 v.IsInAbstract = !synthesized
134 v.Name = canonName
135 } else {
136
137
138
139
140
141
142 v.ChildIndex = int32(synthCount)
143 synthCount++
144 }
145 }
146 }
147
148
149
150 start := int64(-1)
151 curii := -1
152 var prevp *obj.Prog
153 for p := fnsym.Func.Text; p != nil; prevp, p = p, p.Link {
154 if prevp != nil && p.Pos == prevp.Pos {
155 continue
156 }
157 ii := posInlIndex(p.Pos)
158 if ii == curii {
159 continue
160 }
161
162 if start != -1 {
163 addRange(inlcalls.Calls, start, p.Pc, curii, imap)
164 }
165
166 start = p.Pc
167 curii = ii
168 }
169 if start != -1 {
170 addRange(inlcalls.Calls, start, fnsym.Size, curii, imap)
171 }
172
173
174 if Debug_gendwarfinl != 0 {
175 dumpInlCalls(inlcalls)
176 dumpInlVars(dwVars)
177 }
178
179 return inlcalls
180 }
181
182
183
184
185
186 func genAbstractFunc(fn *obj.LSym) {
187 ifn := Ctxt.DwFixups.GetPrecursorFunc(fn)
188 if ifn == nil {
189 Ctxt.Diag("failed to locate precursor fn for %v", fn)
190 return
191 }
192 if Debug_gendwarfinl != 0 {
193 Ctxt.Logf("DwarfAbstractFunc(%v)\n", fn.Name)
194 }
195 Ctxt.DwarfAbstractFunc(ifn, fn, myimportpath)
196 }
197
198
199
200 func unversion(name string) string {
201 if i := strings.Index(name, "ยท"); i > 0 {
202 name = name[:i]
203 }
204 return name
205 }
206
207
208
209
210
211
212
213 func makePreinlineDclMap(fnsym *obj.LSym) map[varPos]int {
214 dcl := preInliningDcls(fnsym)
215 m := make(map[varPos]int)
216 for i, n := range dcl {
217 pos := Ctxt.InnermostPos(n.Pos)
218 vp := varPos{
219 DeclName: unversion(n.Sym.Name),
220 DeclFile: pos.RelFilename(),
221 DeclLine: pos.RelLine(),
222 DeclCol: pos.Col(),
223 }
224 if _, found := m[vp]; found {
225 Fatalf("child dcl collision on symbol %s within %v\n", n.Sym.Name, fnsym.Name)
226 }
227 m[vp] = i
228 }
229 return m
230 }
231
232 func insertInlCall(dwcalls *dwarf.InlCalls, inlIdx int, imap map[int]int) int {
233 callIdx, found := imap[inlIdx]
234 if found {
235 return callIdx
236 }
237
238
239
240
241 parCallIdx := -1
242 parInlIdx := Ctxt.InlTree.Parent(inlIdx)
243 if parInlIdx >= 0 {
244 parCallIdx = insertInlCall(dwcalls, parInlIdx, imap)
245 }
246
247
248 inlinedFn := Ctxt.InlTree.InlinedFunction(inlIdx)
249 callXPos := Ctxt.InlTree.CallPos(inlIdx)
250 absFnSym := Ctxt.DwFixups.AbsFuncDwarfSym(inlinedFn)
251 pb := Ctxt.PosTable.Pos(callXPos).Base()
252 callFileSym := Ctxt.Lookup(pb.SymFilename())
253 ic := dwarf.InlCall{
254 InlIndex: inlIdx,
255 CallFile: callFileSym,
256 CallLine: uint32(callXPos.Line()),
257 AbsFunSym: absFnSym,
258 Root: parCallIdx == -1,
259 }
260 dwcalls.Calls = append(dwcalls.Calls, ic)
261 callIdx = len(dwcalls.Calls) - 1
262 imap[inlIdx] = callIdx
263
264 if parCallIdx != -1 {
265
266 dwcalls.Calls[parCallIdx].Children = append(dwcalls.Calls[parCallIdx].Children, callIdx)
267 }
268
269 return callIdx
270 }
271
272
273
274
275
276
277
278
279 func posInlIndex(xpos src.XPos) int {
280 pos := Ctxt.PosTable.Pos(xpos)
281 if b := pos.Base(); b != nil {
282 ii := b.InliningIndex()
283 if ii >= 0 {
284 return ii
285 }
286 }
287 return -1
288 }
289
290 func addRange(calls []dwarf.InlCall, start, end int64, ii int, imap map[int]int) {
291 if start == -1 {
292 panic("bad range start")
293 }
294 if end == -1 {
295 panic("bad range end")
296 }
297 if ii == -1 {
298 return
299 }
300 if start == end {
301 return
302 }
303
304 callIdx, found := imap[ii]
305 if !found {
306 Fatalf("can't find inlIndex %d in imap for prog at %d\n", ii, start)
307 }
308 call := &calls[callIdx]
309 call.Ranges = append(call.Ranges, dwarf.Range{Start: start, End: end})
310 }
311
312 func dumpInlCall(inlcalls dwarf.InlCalls, idx, ilevel int) {
313 for i := 0; i < ilevel; i++ {
314 Ctxt.Logf(" ")
315 }
316 ic := inlcalls.Calls[idx]
317 callee := Ctxt.InlTree.InlinedFunction(ic.InlIndex)
318 Ctxt.Logf(" %d: II:%d (%s) V: (", idx, ic.InlIndex, callee.Name)
319 for _, f := range ic.InlVars {
320 Ctxt.Logf(" %v", f.Name)
321 }
322 Ctxt.Logf(" ) C: (")
323 for _, k := range ic.Children {
324 Ctxt.Logf(" %v", k)
325 }
326 Ctxt.Logf(" ) R:")
327 for _, r := range ic.Ranges {
328 Ctxt.Logf(" [%d,%d)", r.Start, r.End)
329 }
330 Ctxt.Logf("\n")
331 for _, k := range ic.Children {
332 dumpInlCall(inlcalls, k, ilevel+1)
333 }
334
335 }
336
337 func dumpInlCalls(inlcalls dwarf.InlCalls) {
338 for k, c := range inlcalls.Calls {
339 if c.Root {
340 dumpInlCall(inlcalls, k, 0)
341 }
342 }
343 }
344
345 func dumpInlVars(dwvars []*dwarf.Var) {
346 for i, dwv := range dwvars {
347 typ := "local"
348 if dwv.Abbrev == dwarf.DW_ABRV_PARAM_LOCLIST || dwv.Abbrev == dwarf.DW_ABRV_PARAM {
349 typ = "param"
350 }
351 ia := 0
352 if dwv.IsInAbstract {
353 ia = 1
354 }
355 Ctxt.Logf("V%d: %s CI:%d II:%d IA:%d %s\n", i, dwv.Name, dwv.ChildIndex, dwv.InlIndex-1, ia, typ)
356 }
357 }
358
View as plain text