aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/error.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/error.go')
-rw-r--r--src/runtime/error.go38
1 files changed, 37 insertions, 1 deletions
diff --git a/src/runtime/error.go b/src/runtime/error.go
index 0238c5e592..f5b015c091 100644
--- a/src/runtime/error.go
+++ b/src/runtime/error.go
@@ -4,6 +4,8 @@
package runtime
+import _ "unsafe" // for go:linkname
+
// The Error interface identifies a run time error.
type Error interface {
error
@@ -91,7 +93,41 @@ func printany(i interface{}) {
}
}
+// strings.IndexByte is implemented in runtime/asm_$goarch.s
+// but amusingly we need go:linkname to get access to it here in the runtime.
+//go:linkname stringsIndexByte strings.IndexByte
+func stringsIndexByte(s string, c byte) int
+
// called from generated code
-func panicwrap(pkg, typ, meth string) {
+func panicwrap() {
+ pc := make([]uintptr, 1)
+ n := Callers(2, pc)
+ if n == 0 {
+ throw("panicwrap: Callers failed")
+ }
+ frames := CallersFrames(pc)
+ frame, _ := frames.Next()
+ name := frame.Function
+ // name is something like "main.(*T).F".
+ // We want to extract pkg ("main"), typ ("T"), and meth ("F").
+ // Do it by finding the parens.
+ i := stringsIndexByte(name, '(')
+ if i < 0 {
+ throw("panicwrap: no ( in " + frame.Function)
+ }
+ pkg := name[:i-1]
+ if i+2 >= len(name) || name[i-1:i+2] != ".(*" {
+ throw("panicwrap: unexpected string after package name: " + frame.Function)
+ }
+ name = name[i+2:]
+ i = stringsIndexByte(name, ')')
+ if i < 0 {
+ throw("panicwrap: no ) in " + frame.Function)
+ }
+ if i+2 >= len(name) || name[i:i+2] != ")." {
+ throw("panicwrap: unexpected string after type name: " + frame.Function)
+ }
+ typ := name[:i]
+ meth := name[i+2:]
panic(plainError("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer"))
}