forwprop: Also dce from added statements from gimple_simplify
[official-gcc.git] / libgo / go / runtime / symtab.go
blob89a27c43fb0b59781ed3c164505909adcf7c9e7f
1 // Copyright 2014 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.
5 package runtime
7 import (
8 "internal/bytealg"
9 _ "unsafe" // for go:linkname
12 // Frames may be used to get function/file/line information for a
13 // slice of PC values returned by Callers.
14 type Frames struct {
15 // callers is a slice of PCs that have not yet been expanded to frames.
16 callers []uintptr
18 // The last PC we saw.
19 last uintptr
21 // The number of times we've seen last.
22 lastCount int
25 // Frame is the information returned by Frames for each call frame.
26 type Frame struct {
27 // PC is the program counter for the location in this frame.
28 // For a frame that calls another frame, this will be the
29 // program counter of a call instruction. Because of inlining,
30 // multiple frames may have the same PC value, but different
31 // symbolic information.
32 PC uintptr
34 // Func is the Func value of this call frame. This may be nil
35 // for non-Go code or fully inlined functions.
36 Func *Func
38 // Function is the package path-qualified function name of
39 // this call frame. If non-empty, this string uniquely
40 // identifies a single function in the program.
41 // This may be the empty string if not known.
42 // If Func is not nil then Function == Func.Name().
43 Function string
45 // File and Line are the file name and line number of the
46 // location in this frame. For non-leaf frames, this will be
47 // the location of a call. These may be the empty string and
48 // zero, respectively, if not known.
49 File string
50 Line int
52 // Entry point program counter for the function; may be zero
53 // if not known. If Func is not nil then Entry ==
54 // Func.Entry().
55 Entry uintptr
58 // CallersFrames takes a slice of PC values returned by Callers and
59 // prepares to return function/file/line information.
60 // Do not change the slice until you are done with the Frames.
61 func CallersFrames(callers []uintptr) *Frames {
62 return &Frames{callers: callers}
65 // Next returns a Frame representing the next call frame in the slice
66 // of PC values. If it has already returned all call frames, Next
67 // returns a zero Frame.
69 // The more result indicates whether the next call to Next will return
70 // a valid Frame. It does not necessarily indicate whether this call
71 // returned one.
73 // See the Frames example for idiomatic usage.
74 func (ci *Frames) Next() (frame Frame, more bool) {
75 if len(ci.callers) == 0 {
76 return Frame{}, false
79 pc := ci.callers[0]
80 ci.callers = ci.callers[1:]
82 i := 0
83 if pc == ci.last {
84 ci.lastCount++
85 i = ci.lastCount
86 } else {
87 ci.last = pc
88 ci.lastCount = 0
90 more = len(ci.callers) > 0
92 // Subtract 1 from PC to undo the 1 we added in callback in
93 // go-callers.c.
94 function, file, line, _ := funcfileline(pc-1, int32(i), more)
95 if function == "" && file == "" {
96 return Frame{}, more
99 // Demangle function name if needed.
100 function = demangleSymbol(function)
102 // Create entry.
103 entry := funcentry(pc - 1)
104 f := &Func{name: function, entry: entry}
106 xpc := pc
107 if xpc > entry {
108 xpc--
111 frame = Frame{
112 PC: xpc,
113 Func: f,
114 Function: function,
115 File: file,
116 Line: line,
117 Entry: entry,
120 return frame, more
123 //go:noescape
124 // pcInlineCallers is written in C.
125 func pcInlineCallers(pc uintptr, locbuf *location, max int32) int32
127 // runtime_expandFinalInlineFrame expands the final pc in stk to include all
128 // "callers" if pc is inline.
130 //go:linkname runtime_expandFinalInlineFrame runtime_1pprof.runtime__expandFinalInlineFrame
131 func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr {
132 if len(stk) == 0 {
133 return stk
135 pc := stk[len(stk)-1]
136 tracepc := pc - 1
138 var locbuf [_TracebackMaxFrames]location
139 n := pcInlineCallers(tracepc, &locbuf[0], int32(len(locbuf)))
141 // Returning the same PC several times causes Frame.Next to do
142 // the right thing.
143 for i := int32(1); i < n; i++ {
144 stk = append(stk, pc)
147 return stk
150 // NOTE: Func does not expose the actual unexported fields, because we return *Func
151 // values to users, and we want to keep them from being able to overwrite the data
152 // with (say) *f = Func{}.
153 // All code operating on a *Func must call raw() to get the *_func
154 // or funcInfo() to get the funcInfo instead.
156 // A Func represents a Go function in the running binary.
157 type Func struct {
158 name string
159 entry uintptr
162 // FuncForPC returns a *Func describing the function that contains the
163 // given program counter address, or else nil.
165 // If pc represents multiple functions because of inlining, it returns
166 // the *Func describing the innermost function, but with an entry of
167 // the outermost function.
168 func FuncForPC(pc uintptr) *Func {
169 name, _, _, _ := funcfileline(pc, -1, false)
170 if name == "" {
171 return nil
173 entry := funcentry(pc)
174 return &Func{name: name, entry: entry}
177 // Name returns the name of the function.
178 func (f *Func) Name() string {
179 if f == nil {
180 return ""
182 return f.name
185 // Entry returns the entry address of the function.
186 func (f *Func) Entry() uintptr {
187 if f == nil {
188 return 0
190 return f.entry
193 // FileLine returns the file name and line number of the
194 // source code corresponding to the program counter pc.
195 // The result will not be accurate if pc is not a program
196 // counter within f.
197 func (f *Func) FileLine(pc uintptr) (file string, line int) {
198 _, file, line, _ = funcfileline(pc, -1, false)
199 return file, line
202 func hexval(b byte) uint {
203 if b >= '0' && b <= '9' {
204 return uint(b - '0')
206 if b >= 'a' && b <= 'f' {
207 return uint(b-'a') + 10
209 return 0
212 func hexDigitsToRune(digits []byte, ndig int) rune {
213 result := uint(0)
214 for i := 0; i < ndig; i++ {
215 result <<= uint(4)
216 result |= hexval(digits[i])
218 return rune(result)
221 // decodeIdentifier performs an in-place decoding on the input byte slice.
222 // This undoes the compiler underscore mangling.
223 // Returns the number of bytes used by the result.
224 func decodeIdentifier(bsl []byte) int {
225 underscoreCodes := map[byte]byte{
226 '_': '_',
227 '0': '.',
228 '1': '/',
229 '2': '*',
230 '3': ',',
231 '4': '{',
232 '5': '}',
233 '6': '[',
234 '7': ']',
235 '8': '(',
236 '9': ')',
237 'a': '"',
238 'b': ' ',
239 'c': ';',
242 j := 0
243 for i := 0; i < len(bsl); i++ {
244 b := bsl[i]
245 if b != '_' || i+1 >= len(bsl) {
246 bsl[j] = b
248 continue
251 if d, ok := underscoreCodes[bsl[i+1]]; ok {
253 bsl[j] = d
255 continue
258 rlen := 0
259 switch bsl[i+1] {
260 case 'x':
261 rlen = 2
262 case 'u':
263 rlen = 4
264 case 'U':
265 rlen = 8
268 if rlen > 0 && i+1+rlen < len(bsl) {
269 r := hexDigitsToRune(bsl[i+2:], rlen)
270 nc := encoderune(bsl[j:], r)
271 j += nc
272 i += rlen + 1
273 } else {
274 bsl[j] = b
278 return j
281 // Demangle a function symbol. Applies the reverse of go_encode_id()
282 // as used in the compiler.
284 func demangleSymbol(s string) string {
285 if bytealg.IndexByteString(s, '.') < 0 {
286 // A symbol with no '.' is not a Go symbol.
287 return s
290 bsl := []byte(s)
291 nchars := decodeIdentifier(bsl)
292 bsl = bsl[:nchars]
293 return string(bsl)
296 // implemented in go-caller.c
297 func funcfileline(uintptr, int32, bool) (string, string, int, int)
298 func funcentry(uintptr) uintptr