diff --git a/builtin.go b/builtin.go index 0f206562..8ff73dd7 100644 --- a/builtin.go +++ b/builtin.go @@ -32,7 +32,7 @@ import ( // callBuiltin interprets a call to builtin fn with arguments args, // returning its result. -func (inter *Interp) callBuiltin(caller *frame, fn *ssa.Builtin, args []value, ssaArgs []ssa.Value) value { +func (inter *Interp) callBuiltin(fr *frame, fn *ssa.Builtin, args []value, ssaArgs []ssa.Value) value { switch fnName := fn.Name(); fnName { case "append": if len(args) == 1 { @@ -47,7 +47,7 @@ func (inter *Interp) callBuiltin(caller *frame, fn *ssa.Builtin, args []value, s i0 := v0.Len() i1 := v1.Len() if i0+i1 < i0 { - panic(runtimeError(errAppendOutOfRange)) + panic(fr.runtimeError(fn, errAppendOutOfRange)) } return reflect.AppendSlice(v0, v1).Interface() @@ -127,14 +127,14 @@ func (inter *Interp) callBuiltin(caller *frame, fn *ssa.Builtin, args []value, s case "panic": // ssa.Panic handles most cases; this is only for "go // panic" or "defer panic". - var err error = PanicError{stack: debugStack(caller), Value: args[0]} + var err error = PanicError{stack: debugStack(fr), Value: args[0]} if inter.ctx.panicFunc != nil { - err = inter.ctx.handlePanic(caller, fn, err) + err = inter.ctx.handlePanic(fr, fn, err) } panic(err) case "recover": - return doRecover(caller) + return doRecover(fr) case "ssa:wrapnilchk": recv := args[0] @@ -147,7 +147,7 @@ func (inter *Interp) callBuiltin(caller *frame, fn *ssa.Builtin, args []value, s } else { info = recvType } - panic(plainError(fmt.Sprintf("value method %s.%s called using nil *%s pointer", + panic(fr.plainError(fn, fmt.Sprintf("value method %s.%s called using nil *%s pointer", recvType, methodName, info))) } return recv @@ -166,11 +166,11 @@ func (inter *Interp) callBuiltin(caller *frame, fn *ssa.Builtin, args []value, s if length == 0 { return reflect.New(reflect.SliceOf(etyp)).Elem().Interface() } - panic(runtimeError("unsafe.Slice: ptr is nil and len is not zero")) + panic(fr.runtimeError(fn, "unsafe.Slice: ptr is nil and len is not zero")) } mem, overflow := mulUintptr(etyp.Size(), uintptr(length)) if overflow || mem > -uintptr(ptr.Pointer()) { - panic(runtimeError("unsafe.Slice: len out of range")) + panic(fr.runtimeError(fn, "unsafe.Slice: len out of range")) } typ := reflect.ArrayOf(length, etyp) v := reflect.NewAt(typ, unsafe.Pointer(ptr.Pointer())) @@ -210,11 +210,11 @@ func (inter *Interp) callBuiltin(caller *frame, fn *ssa.Builtin, args []value, s if length == 0 { return "" } - panic(runtimeError("unsafe.String: ptr is nil and len is not zero")) + panic(fr.runtimeError(fn, "unsafe.String: ptr is nil and len is not zero")) } mem, overflow := mulUintptr(1, uintptr(length)) if overflow || mem > -uintptr(unsafe.Pointer(ptr)) { - panic(runtimeError("unsafe.String: len out of range")) + panic(fr.runtimeError(fn, "unsafe.String: len out of range")) } sh := reflect.StringHeader{Data: uintptr(unsafe.Pointer(ptr)), Len: length} return *(*string)(unsafe.Pointer(&sh)) @@ -235,7 +235,7 @@ func (inter *Interp) callBuiltin(caller *frame, fn *ssa.Builtin, args []value, s // callBuiltinDiscardsResult interprets a call to builtin fn with arguments args, // discards its result. -func (inter *Interp) callBuiltinDiscardsResult(caller *frame, fn *ssa.Builtin, args []value, ssaArgs []ssa.Value) { +func (inter *Interp) callBuiltinDiscardsResult(fr *frame, fn *ssa.Builtin, args []value, ssaArgs []ssa.Value) { switch fnName := fn.Name(); fnName { case "append": panic("discards result of " + fnName) @@ -288,14 +288,14 @@ func (inter *Interp) callBuiltinDiscardsResult(caller *frame, fn *ssa.Builtin, a case "panic": // ssa.Panic handles most cases; this is only for "go // panic" or "defer panic". - var err error = PanicError{stack: debugStack(caller), Value: args[0]} + var err error = PanicError{stack: debugStack(fr), Value: args[0]} if inter.ctx.panicFunc != nil { - err = inter.ctx.handlePanic(caller, fn, err) + err = inter.ctx.handlePanic(fr, fn, err) } panic(err) case "recover": - doRecover(caller) + doRecover(fr) case "ssa:wrapnilchk": recv := args[0] @@ -308,7 +308,7 @@ func (inter *Interp) callBuiltinDiscardsResult(caller *frame, fn *ssa.Builtin, a } else { info = recvType } - panic(plainError(fmt.Sprintf("value method %s.%s called using nil *%s pointer", + panic(fr.plainError(fn, fmt.Sprintf("value method %s.%s called using nil *%s pointer", recvType, methodName, info))) } @@ -356,7 +356,7 @@ func (interp *Interp) makeBuiltinByStack(fn *ssa.Builtin, ssaArgs []ssa.Value, i i0 := v0.Len() i1 := v1.Len() if i0+i1 < i0 { - panic(runtimeError(errAppendOutOfRange)) + panic(fr.runtimeError(fn, errAppendOutOfRange)) } fr.setReg(ir, reflect.AppendSlice(v0, v1).Interface()) } @@ -492,7 +492,7 @@ func (interp *Interp) makeBuiltinByStack(fn *ssa.Builtin, ssaArgs []ssa.Value, i } else { info = recvType } - panic(plainError(fmt.Sprintf("value method %s.%s called using nil *%s pointer", + panic(fr.plainError(fn, fmt.Sprintf("value method %s.%s called using nil *%s pointer", recvType, methodName, info))) } fr.setReg(ir, recv) @@ -520,11 +520,11 @@ func (interp *Interp) makeBuiltinByStack(fn *ssa.Builtin, ssaArgs []ssa.Value, i fr.setReg(ir, reflect.New(reflect.SliceOf(etyp)).Elem().Interface()) return } - panic(runtimeError("unsafe.Slice: ptr is nil and len is not zero")) + panic(fr.runtimeError(fn, "unsafe.Slice: ptr is nil and len is not zero")) } mem, overflow := mulUintptr(etyp.Size(), uintptr(length)) if overflow || mem > -uintptr(ptr.Pointer()) { - panic(runtimeError("unsafe.Slice: len out of range")) + panic(fr.runtimeError(fn, "unsafe.Slice: len out of range")) } typ := reflect.ArrayOf(length, etyp) v := reflect.NewAt(typ, unsafe.Pointer(ptr.Pointer())) @@ -570,11 +570,11 @@ func (interp *Interp) makeBuiltinByStack(fn *ssa.Builtin, ssaArgs []ssa.Value, i fr.setReg(ir, "") return } - panic(runtimeError("unsafe.String: ptr is nil and len is not zero")) + panic(fr.runtimeError(fn, "unsafe.String: ptr is nil and len is not zero")) } mem, overflow := mulUintptr(1, uintptr(length)) if overflow || mem > -uintptr(unsafe.Pointer(ptr)) { - panic(runtimeError("unsafe.String: len out of range")) + panic(fr.runtimeError(fn, "unsafe.String: len out of range")) } sh := reflect.StringHeader{Data: uintptr(unsafe.Pointer(ptr)), Len: length} fr.setReg(ir, *(*string)(unsafe.Pointer(&sh))) @@ -603,7 +603,7 @@ func (interp *Interp) makeBuiltinByStack(fn *ssa.Builtin, ssaArgs []ssa.Value, i } case "Offsetof": // instance of generic function return func(fr *frame) { - offset, err := builtinOffsetof(fr.pfn, fr.ipc-1) + offset, err := builtinOffsetof(fr, fn, fr.ipc-1) if err != nil { panic(err) } @@ -693,27 +693,28 @@ func mulUintptr(a, b uintptr) (uintptr, bool) { return a * b, overflow } -func builtinOffsetof(pfn *function, pc int) (int64, error) { +func builtinOffsetof(fr *frame, fn *ssa.Builtin, pc int) (int64, error) { + pfn := fr.pfn pos := pfn.ssaInstrs[pc].Pos() paths, info, ok := pathEnclosingInterval(pfn.Interp.ctx, pos) if !ok { - return -1, plainError("unsafe.Offsetof not found code") + return -1, fr.plainError(fn, "unsafe.Offsetof not found code") } call, ok := paths[0].(*ast.CallExpr) if !ok { - return -1, plainError("unsafe.Offsetof not found call") + return -1, fr.plainError(fn, "unsafe.Offsetof not found call") } selx, ok := call.Args[0].(*ast.SelectorExpr) if !ok { - return -1, plainError("unsafe.Offsetof not found selector expr") + return -1, fr.plainError(fn, "unsafe.Offsetof not found selector expr") } sel, _ := info.Selections[selx] if sel == nil { - return -1, plainError("unsafe.Offsetof not found selector type") + return -1, fr.plainError(fn, "unsafe.Offsetof not found selector type") } instrs, found := foundFieldAddr(pfn, pc) if !found || len(sel.Index()) > len(instrs) { - return -1, plainError("unsafe.Offsetof not found FieldAddr instr") + return -1, fr.plainError(fn, "unsafe.Offsetof not found FieldAddr instr") } instr := instrs[len(sel.Index())-1] return selOffsetof(pfn.Interp.ctx.sizes, instr.X.Type().Underlying().(*types.Pointer).Elem().Underlying().(*types.Struct), sel.Index(), selx.Sel.Name) diff --git a/context.go b/context.go index c0db8eb0..e0d18d27 100644 --- a/context.go +++ b/context.go @@ -237,7 +237,7 @@ type PanicInfo struct { funcInstr *Frame fset *token.FileSet - Error error // PanicError + Error error // PanicError / FatalError / PlainError / RuntimeError } func (i *PanicInfo) Position() token.Position { diff --git a/errors.go b/errors.go index 194cc5b2..72e97428 100644 --- a/errors.go +++ b/errors.go @@ -17,6 +17,7 @@ package igop import ( + "bytes" "errors" "fmt" ) @@ -36,18 +37,55 @@ func (r ExitError) Error() string { return fmt.Sprintf("exit %v", int(r)) } -type plainError string +type PlainError string -func (e plainError) RuntimeError() {} +func (e PlainError) RuntimeError() {} -func (e plainError) Error() string { +func (e PlainError) Error() string { return string(e) } -type runtimeError string +type RuntimeError string -func (e runtimeError) RuntimeError() {} +func (e RuntimeError) RuntimeError() {} -func (e runtimeError) Error() string { +func (e RuntimeError) Error() string { return "runtime error: " + string(e) } + +// If the target program panics, the interpreter panics with this type. +type PanicError struct { + stack []byte + Value value +} + +func (p PanicError) Error() string { + var buf bytes.Buffer + writeany(&buf, p.Value) + return buf.String() +} + +func (p PanicError) Stack() []byte { + return p.stack +} + +// run func fatal error +type FatalError struct { + stack []byte + Value value +} + +func (p FatalError) Error() string { + var buf bytes.Buffer + writeany(&buf, p.Value) + return buf.String() +} + +func (p FatalError) Stack() []byte { + return p.stack +} + +// If the target program calls exit, the interpreter panics with this type. +type exitPanic int + +type goexitPanic int diff --git a/interp.go b/interp.go index a651529c..c0e6a525 100644 --- a/interp.go +++ b/interp.go @@ -52,7 +52,6 @@ import ( "go/token" "go/types" "reflect" - "runtime" "strings" "sync" "sync/atomic" @@ -480,6 +479,20 @@ func (fr *frame) copyReg(dst register, src register) { fr.stack[dst] = fr.stack[src] } +func (fr *frame) runtimeError(instr funcInstr, text string) error { + if fr.interp.ctx.panicFunc != nil { + return fr.interp.ctx.handlePanic(fr, instr, RuntimeError(text)) + } + return RuntimeError(text) +} + +func (fr *frame) plainError(instr funcInstr, text string) error { + if fr.interp.ctx.panicFunc != nil { + return fr.interp.ctx.handlePanic(fr, instr, PlainError(text)) + } + return PlainError(text) +} + type _panic struct { arg interface{} link *_panic @@ -1277,16 +1290,18 @@ func (i *Interp) RunFunc(name string, args ...Value) (r Value, err error) { i.exitCode = <-i.chexit atomic.StoreInt32(&i.exited, 1) } - case runtime.Error: - err = p case PanicError: err = p default: + // runtimeError / plainError ... pfr := fr for pfr.callee != nil { pfr = pfr.callee } - err = PanicError{stack: debugStack(pfr), Value: p} + err = FatalError{stack: debugStack(pfr), Value: p} + if i.ctx.panicFunc != nil { + i.ctx.handlePanic(fr, i.mainpkg.Func(name), err) + } } }() if fn := i.mainpkg.Func(name); fn != nil { diff --git a/opblock.go b/opblock.go index dede336f..9e38cac1 100644 --- a/opblock.go +++ b/opblock.go @@ -520,7 +520,7 @@ func makeInstr(interp *Interp, pfn *function, instr ssa.Instruction) func(fr *fr size := fr.reg(is) buffer := asInt(size) if buffer < 0 { - panic(runtimeError("makechan: size out of range")) + panic(fr.runtimeError(instr, "makechan: size out of range")) } fr.setReg(ir, reflect.MakeChan(typ, buffer).Interface()) } @@ -530,7 +530,7 @@ func makeInstr(interp *Interp, pfn *function, instr ssa.Instruction) func(fr *fr size := fr.reg(is) buffer := asInt(size) if buffer < 0 { - panic(runtimeError("makechan: size out of range")) + panic(fr.runtimeError(instr, "makechan: size out of range")) } fr.setReg(ir, reflect.MakeChan(ctyp, buffer).Convert(typ).Interface()) } @@ -556,11 +556,11 @@ func makeInstr(interp *Interp, pfn *function, instr ssa.Instruction) func(fr *fr return func(fr *frame) { Len := asInt(fr.reg(il)) if Len < 0 || Len >= maxMemLen { - panic(runtimeError("makeslice: len out of range")) + panic(fr.runtimeError(instr, "makeslice: len out of range")) } Cap := asInt(fr.reg(ic)) if Cap < 0 || Cap >= maxMemLen { - panic(runtimeError("makeslice: cap out of range")) + panic(fr.runtimeError(instr, "makeslice: cap out of range")) } fr.setReg(ir, reflect.MakeSlice(typ, Len, Cap).Interface()) } @@ -587,7 +587,7 @@ func makeInstr(interp *Interp, pfn *function, instr ssa.Instruction) func(fr *fr return func(fr *frame) { v, err := fieldAddrX(fr.reg(ix), instr.Field) if err != nil { - panic(runtimeError(err.Error())) + panic(fr.runtimeError(instr, err.Error())) } fr.setReg(ir, v) } @@ -597,7 +597,7 @@ func makeInstr(interp *Interp, pfn *function, instr ssa.Instruction) func(fr *fr return func(fr *frame) { v, err := fieldX(fr.reg(ix), instr.Field) if err != nil { - panic(runtimeError(err.Error())) + panic(fr.runtimeError(instr, err.Error())) } fr.setReg(ir, v) } @@ -616,15 +616,15 @@ func makeInstr(interp *Interp, pfn *function, instr ssa.Instruction) func(fr *fr case reflect.Slice: case reflect.Array: case reflect.Invalid: - panic(runtimeError("invalid memory address or nil pointer dereference")) + panic(fr.runtimeError(instr, "invalid memory address or nil pointer dereference")) default: panic(fmt.Sprintf("unexpected x type in IndexAddr: %T", x)) } index := asInt(idx) if index < 0 { - panic(runtimeError(fmt.Sprintf("index out of range [%v]", index))) + panic(fr.runtimeError(instr, fmt.Sprintf("index out of range [%v]", index))) } else if length := v.Len(); index >= length { - panic(runtimeError(fmt.Sprintf("index out of range [%v] with length %v", index, length))) + panic(fr.runtimeError(instr, fmt.Sprintf("index out of range [%v] with length %v", index, length))) } fr.setReg(ir, v.Index(index).Addr().Interface()) } @@ -638,9 +638,9 @@ func makeInstr(interp *Interp, pfn *function, instr ssa.Instruction) func(fr *fr index := asInt(idx) v := reflect.ValueOf(x) if index < 0 { - panic(runtimeError(fmt.Sprintf("index out of range [%v]", index))) + panic(fr.runtimeError(instr, fmt.Sprintf("index out of range [%v]", index))) } else if length := v.Len(); index >= length { - panic(runtimeError(fmt.Sprintf("index out of range [%v] with length %v", index, length))) + panic(fr.runtimeError(instr, fmt.Sprintf("index out of range [%v] with length %v", index, length))) } fr.setReg(ir, v.Index(index).Interface()) } @@ -748,7 +748,7 @@ func makeInstr(interp *Interp, pfn *function, instr ssa.Instruction) func(fr *fr vLen := v.Len() tLen := typ.Elem().Len() if tLen > vLen { - panic(runtimeError(fmt.Sprintf(errSliceToArrayPointer, vLen, tLen))) + panic(fr.runtimeError(instr, fmt.Sprintf(errSliceToArrayPointer, vLen, tLen))) } fr.setReg(ir, v.Convert(typ).Interface()) } @@ -788,12 +788,12 @@ func makeInstr(interp *Interp, pfn *function, instr ssa.Instruction) func(fr *fr ix, kx, vx := pfn.regIndex3(instr.X) if kx.isStatic() { return func(fr *frame) { - fr.setReg(ir, typeAssert(interp, instr, typ, xtyp, vx)) + fr.setReg(ir, typeAssert(fr, instr, typ, xtyp, vx)) } } return func(fr *frame) { v := fr.reg(ix) - fr.setReg(ir, typeAssert(interp, instr, typ, xtyp, v)) + fr.setReg(ir, typeAssert(fr, instr, typ, xtyp, v)) } case *ssa.Extract: if *instr.Referrers() == nil { diff --git a/ops.go b/ops.go index 28df30bd..18d6f898 100644 --- a/ops.go +++ b/ops.go @@ -5,7 +5,6 @@ package igop import ( - "bytes" "fmt" "go/constant" "go/token" @@ -16,27 +15,6 @@ import ( "golang.org/x/tools/go/ssa" ) -// If the target program panics, the interpreter panics with this type. -type PanicError struct { - stack []byte - Value value -} - -func (p PanicError) Error() string { - var buf bytes.Buffer - writeany(&buf, p.Value) - return buf.String() -} - -func (p PanicError) Stack() []byte { - return p.stack -} - -// If the target program calls exit, the interpreter panics with this type. -type exitPanic int - -type goexitPanic int - func xtypeValue(c *ssa.Const, kind types.BasicKind) value { switch kind { case types.Bool, types.UntypedBool: @@ -219,7 +197,7 @@ func asUint64(x value) uint64 { panic(fmt.Sprintf("cannot convert %T to uint64", x)) } } - panic(runtimeError("negative shift amount")) + panic(RuntimeError("negative shift amount")) } // slice returns x[lo:hi:max]. Any of lo, hi and max may be nil. @@ -262,42 +240,42 @@ func slice(fr *frame, instr *ssa.Slice, makesliceCheck bool, ix, ih, il, im regi if makesliceCheck { if hi < 0 { - panic(runtimeError("makeslice: len out of range")) + panic(fr.runtimeError(instr, "makeslice: len out of range")) } else if hi > max { - panic(runtimeError("makeslice: cap out of range")) + panic(fr.runtimeError(instr, "makeslice: cap out of range")) } } else { if slice3 { if max < 0 { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [::%v]", max))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [::%v]", max))) } else if max > Cap { if kind == reflect.Slice { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [::%v] with capacity %v", max, Cap))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [::%v] with capacity %v", max, Cap))) } else { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [::%v] with length %v", max, Cap))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [::%v] with length %v", max, Cap))) } } else if hi < 0 { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [:%v:]", hi))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [:%v:]", hi))) } else if hi > max { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [:%v:%v]", hi, max))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [:%v:%v]", hi, max))) } else if lo < 0 { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [%v::]", lo))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [%v::]", lo))) } else if lo > hi { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [%v:%v:]", lo, hi))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [%v:%v:]", lo, hi))) } } else { if hi < 0 { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [:%v]", hi))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [:%v]", hi))) } else if hi > Cap { if kind == reflect.Slice { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [:%v] with capacity %v", hi, Cap))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [:%v] with capacity %v", hi, Cap))) } else { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [:%v] with length %v", hi, Cap))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [:%v] with length %v", hi, Cap))) } } else if lo < 0 { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [%v:]", lo))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [%v:]", lo))) } else if lo > hi { - panic(runtimeError(fmt.Sprintf("slice bounds out of range [%v:%v]", lo, hi))) + panic(fr.runtimeError(instr, fmt.Sprintf("slice bounds out of range [%v:%v]", lo, hi))) } } } @@ -1266,7 +1244,7 @@ func unop(instr *ssa.UnOp, x value) value { case token.MUL: v := reflect.ValueOf(x).Elem() if !v.IsValid() { - panic(runtimeError("invalid memory address or nil pointer dereference")) + panic(RuntimeError("invalid memory address or nil pointer dereference")) } return v.Interface() //return load(deref(instr.X.Type()), x.(*value)) @@ -1331,16 +1309,16 @@ failed: // typeAssert checks whether dynamic type of itf is instr.AssertedType. // It returns the extracted value on success, and panics on failure, // unless instr.CommaOk, in which case it always returns a "value,ok" tuple. -func typeAssert(i *Interp, instr *ssa.TypeAssert, typ reflect.Type, xtyp reflect.Type, iv interface{}) value { +func typeAssert(fr *frame, instr *ssa.TypeAssert, typ reflect.Type, xtyp reflect.Type, iv interface{}) value { var v value var err error if iv == nil { if xtyp == tyErrorInterface { - err = runtimeError("invalid memory address or nil pointer dereference") + err = fr.runtimeError(instr, "invalid memory address or nil pointer dereference") } else if xtyp == typ { - err = plainError(fmt.Sprintf("interface conversion: interface is nil, not %v", typ)) + err = fr.plainError(instr, fmt.Sprintf("interface conversion: interface is nil, not %v", typ)) } else { - err = plainError(fmt.Sprintf("interface conversion: %v is nil, not %v", xtyp, typ)) + err = fr.plainError(instr, fmt.Sprintf("interface conversion: %v is nil, not %v", xtyp, typ)) } // } } else { @@ -1350,22 +1328,22 @@ func typeAssert(i *Interp, instr *ssa.TypeAssert, typ reflect.Type, xtyp reflect v = iv } else { if !rt.AssignableTo(typ) { - err = runtimeError(fmt.Sprintf("interface conversion: %v is %v, not %v", xtyp, rt, typ)) + err = fr.runtimeError(instr, fmt.Sprintf("interface conversion: %v is %v, not %v", xtyp, rt, typ)) if itype, ok := instr.AssertedType.Underlying().(*types.Interface); ok { - if it, ok := i.findType(rt, false); ok { + if it, ok := fr.interp.findType(rt, false); ok { if meth, _ := types.MissingMethod(it, itype, true); meth != nil { - err = runtimeError(fmt.Sprintf("interface conversion: %v is not %v: missing method %s", + err = fr.runtimeError(instr, fmt.Sprintf("interface conversion: %v is not %v: missing method %s", rt, instr.AssertedType, meth.Name())) } } } else if typ.PkgPath() == rt.PkgPath() && typ.Name() == rt.Name() { - t1, ok1 := i.findType(typ, false) - t2, ok2 := i.findType(rt, false) + t1, ok1 := fr.interp.findType(typ, false) + t2, ok2 := fr.interp.findType(rt, false) if ok1 && ok2 { n1, ok1 := t1.(*types.Named) n2, ok2 := t2.(*types.Named) if ok1 && ok2 && n1.Obj().Parent() != n2.Obj().Parent() { - err = runtimeError(fmt.Sprintf("interface conversion: %v is %v, not %v (types from different scopes)", xtyp, rt, typ)) + err = fr.runtimeError(instr, fmt.Sprintf("interface conversion: %v is %v, not %v (types from different scopes)", xtyp, rt, typ)) } } } diff --git a/unop_x.go b/unop_x.go index 1214a296..ab2eed35 100644 --- a/unop_x.go +++ b/unop_x.go @@ -60,7 +60,7 @@ func makeUnOpMUL(pfn *function, instr *ssa.UnOp) func(fr *frame) { return func(fr *frame) { elem := v.Elem() if !elem.IsValid() { - panic(runtimeError("invalid memory address or nil pointer dereference")) + panic(fr.runtimeError(instr, "invalid memory address or nil pointer dereference")) } fr.setReg(ir, elem.Interface()) } @@ -68,7 +68,7 @@ func makeUnOpMUL(pfn *function, instr *ssa.UnOp) func(fr *frame) { return func(fr *frame) { elem := reflect.ValueOf(fr.reg(ix)).Elem() if !elem.IsValid() { - panic(runtimeError("invalid memory address or nil pointer dereference")) + panic(fr.runtimeError(instr, "invalid memory address or nil pointer dereference")) } fr.setReg(ir, elem.Interface()) }