Skip to content

Commit

Permalink
Merge pull request #279 from visualfc/panicinfo
Browse files Browse the repository at this point in the history
Context.SetPanic
  • Loading branch information
visualfc authored Jan 9, 2025
2 parents 26aeaea + 67fc513 commit 35826fe
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 8 deletions.
26 changes: 19 additions & 7 deletions builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,11 @@ 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".
panic(PanicError{stack: debugStack(caller), Value: args[0]})
var err error = PanicError{stack: debugStack(caller), Value: args[0]}
if inter.ctx.panicFunc != nil {
err = inter.ctx.handlePanic(caller, fn, err)
}
panic(err)

case "recover":
return doRecover(caller)
Expand Down Expand Up @@ -284,7 +288,11 @@ 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".
panic(PanicError{stack: debugStack(caller), Value: args[0]})
var err error = PanicError{stack: debugStack(caller), Value: args[0]}
if inter.ctx.panicFunc != nil {
err = inter.ctx.handlePanic(caller, fn, err)
}
panic(err)

case "recover":
doRecover(caller)
Expand Down Expand Up @@ -328,8 +336,8 @@ func (inter *Interp) callBuiltinDiscardsResult(caller *frame, fn *ssa.Builtin, a

// callBuiltin interprets a call to builtin fn with arguments args,
// returning its result.
func (interp *Interp) callBuiltinByStack(caller *frame, fn string, ssaArgs []ssa.Value, ir register, ia []register) {
switch fn {
func (interp *Interp) callBuiltinByStack(caller *frame, fname string, fn *ssa.Builtin, ssaArgs []ssa.Value, ir register, ia []register) {
switch fname {
case "append":
if len(ia) == 1 {
caller.copyReg(ir, ia[0])
Expand Down Expand Up @@ -365,7 +373,7 @@ func (interp *Interp) callBuiltinByStack(caller *frame, fn string, ssaArgs []ssa
reflect.ValueOf(arg0).SetMapIndex(reflect.ValueOf(arg1), reflect.Value{})

case "print", "println": // print(any, ...)
ln := fn == "println"
ln := fname == "println"
var buf bytes.Buffer
for i := 0; i < len(ia); i++ {
arg := caller.reg(ia[i])
Expand Down Expand Up @@ -436,7 +444,11 @@ func (interp *Interp) callBuiltinByStack(caller *frame, fn string, ssaArgs []ssa
// ssa.Panic handles most cases; this is only for "go
// panic" or "defer panic".
arg0 := caller.reg(ia[0])
panic(PanicError{stack: debugStack(caller), Value: arg0})
var err error = PanicError{stack: debugStack(caller), Value: arg0}
if interp.ctx.panicFunc != nil {
err = interp.ctx.handlePanic(caller, fn, err)
}
panic(err)

case "recover":
caller.setReg(ir, doRecover(caller))
Expand Down Expand Up @@ -608,7 +620,7 @@ func (interp *Interp) callBuiltinByStack(caller *frame, fn string, ssaArgs []ssa
}
caller.setReg(ir, v.Interface())
default:
panic("unknown built-in: " + fn)
panic("unknown built-in: " + fname)
}
}

Expand Down
1 change: 1 addition & 0 deletions cmd/igoptest/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ func init() {
gorootTestSkips["fixedbugs/issue38093.go"] = "skip js"
gorootTestSkips["fixedbugs/issue64565.go"] = "skip command"
gorootTestSkips["fixedbugs/issue9355.go"] = "skip command"
gorootTestSkips["fixedbugs/issue69110.go"] = "skip runtime link"
gorootTestSkips["linkmain_run.go"] = "skip link"
gorootTestSkips["linkobj.go"] = "skip link"
gorootTestSkips["linkx_run.go"] = "skip link"
Expand Down
45 changes: 45 additions & 0 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ type Context struct {
Lookup func(root, path string) (dir string, found bool) // lookup external import
evalCallFn func(interp *Interp, call *ssa.Call, res ...interface{}) // internal eval func for repl
debugFunc func(*DebugInfo) // debug func
panicFunc func(*PanicInfo) // panic func
pkgs map[string]*SourcePackage // imports
override map[string]reflect.Value // override function
evalInit map[string]bool // eval init check
Expand Down Expand Up @@ -212,6 +213,50 @@ func (ctx *Context) SetDebug(fn func(*DebugInfo)) {
ctx.debugFunc = fn
}

func (ctx *Context) SetPanic(fn func(*PanicInfo)) {
ctx.panicFunc = fn
}

type PanicInfo struct {
funcInstr
fset *token.FileSet
fr *frame
Error error // PanicError
}

func (i *PanicInfo) Position() token.Position {
return i.fset.Position(i.Pos())
}

func (i *PanicInfo) CallerFrames() (frames []runtime.Frame) {
rpc := make([]uintptr, 64)
n := runtimeCallers(i.fr, 1, rpc)
fs := runtime.CallersFrames(rpc[:n])
for {
f, more := runtimeFramesNext(i.fr, fs)
frames = append(frames, f)
if !more {
break
}
}
return
}

type funcInstr interface {
Parent() *ssa.Function
Pos() token.Pos
String() string
}

func (ctx *Context) handlePanic(fr *frame, fn funcInstr, err error) error {
info := &PanicInfo{funcInstr: fn, fset: ctx.FileSet, fr: fr, Error: err}
ctx.panicFunc(info)
if info.Error != nil {
return info.Error
}
return err
}

// RegisterExternal register external value must variable address or func.
func (ctx *Context) RegisterExternal(key string, i interface{}) {
if i == nil {
Expand Down
8 changes: 7 additions & 1 deletion opblock.go
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,12 @@ func makeInstr(interp *Interp, pfn *function, instr ssa.Instruction) func(fr *fr
}
case *ssa.Panic:
ix := pfn.regIndex(instr.X)
if interp.ctx.panicFunc != nil {
return func(fr *frame) {
var err error = PanicError{stack: debugStack(fr), Value: fr.reg(ix)}
panic(interp.ctx.handlePanic(fr, instr, err))
}
}
return func(fr *frame) {
panic(PanicError{stack: debugStack(fr), Value: fr.reg(ix)})
}
Expand Down Expand Up @@ -1070,7 +1076,7 @@ func makeCallInstr(pfn *function, interp *Interp, instr ssa.Value, call *ssa.Cal
case *ssa.Builtin:
fname := fn.Name()
return func(fr *frame) {
interp.callBuiltinByStack(fr, fname, call.Args, ir, ia)
interp.callBuiltinByStack(fr, fname, fn, call.Args, ir, ia)
}
case *ssa.MakeClosure:
ifn := interp.loadFunction(fn.Fn.(*ssa.Function))
Expand Down

0 comments on commit 35826fe

Please sign in to comment.