// A *Func can be either a *_func or a *funcinl, and they are distinguished
// by the first uintptr.
type funcinl struct {
- zero uintptr // set to 0 to distinguish from _func
- entry uintptr // entry of the real (the "outermost") frame.
+ ones uintptr // set to ^0 to distinguish from _func
+ entry uintptr // entry of the real (the "outermost") frame
name string
file string
line int
name := funcnameFromNameoff(f, inltree[ix].func_)
file, line := funcline(f, pc)
fi := &funcinl{
+ ones: ^uintptr(0),
entry: f.entry, // entry of the real (the outermost) function.
name: name,
file: file,
return ""
}
fn := f.raw()
- if fn.entry == 0 { // inlined version
+ if fn.isInlined() { // inlined version
fi := (*funcinl)(unsafe.Pointer(fn))
return fi.name
}
// Entry returns the entry address of the function.
func (f *Func) Entry() uintptr {
fn := f.raw()
- if fn.entry == 0 { // inlined version
+ if fn.isInlined() { // inlined version
fi := (*funcinl)(unsafe.Pointer(fn))
return fi.entry
}
// counter within f.
func (f *Func) FileLine(pc uintptr) (file string, line int) {
fn := f.raw()
- if fn.entry == 0 { // inlined version
+ if fn.isInlined() { // inlined version
fi := (*funcinl)(unsafe.Pointer(fn))
return fi.file, fi.line
}
return (*Func)(unsafe.Pointer(f._func))
}
+// isInlined reports whether f should be re-interpreted as a *funcinl.
+func (f *_func) isInlined() bool {
+ return f.entry == ^uintptr(0) // see comment for funcinl.ones
+}
+
// findfunc looks up function metadata for a PC.
//
// It is nosplit because it's part of the isgoexception