func (fr *frame) runDefers() {
	for d := fr.defers; d != nil; d = d.tail {
		fr.runDefer(d)
	}
	fr.defers = nil
	if fr.panicking && fr.panic != nil {
		panic(fr.panic)  
	}
}
runDefers executes fr's deferred function calls in LIFO order.

On entry, fr.panicking indicates a state of panic; if
true, fr.panic contains the panic value.

On completion, if a deferred call started a panic, or if no
deferred call recovered from a previous state of panic, then
runDefers itself panics after the last deferred call has run.

If there was no initial state of panic, or it was recovered from,
runDefers returns normally.
package gossa
import (
	"fmt"
	"go/token"
	"go/types"
	"os"
	"reflect"
	"runtime"
	"sync"
	"sync/atomic"
	"unsafe"
	"github.com/goplus/reflectx"
	"github.com/goplus/xtypes"
	"golang.org/x/tools/go/ssa"
)
type continuation int
const (
	kNext continuation = iota
	kReturn
	kJump
)
type Mode uint
const (
	DisableRecover  Mode = 1 << iota  
	EnableTracing                     
	EnableDumpInstr                   
)
type plainError string
func (e plainError) Error() string {
	return string(e)
}
type runtimeError string
func (e runtimeError) RuntimeError() {}
func (e runtimeError) Error() string {
	return "runtime error: " + string(e)
}
type interpreter struct {
	prog        *ssa.Program         
	globals     map[ssa.Value]value  
	mode        Mode                 
	sizes       types.Sizes          
	goroutines  int32                
	ctx         xtypes.Context
	types       map[types.Type]reflect.Type
	caller      *frame
	typesMutex  sync.RWMutex
	callerMutex sync.RWMutex
}
func (i *interpreter) findType(t reflect.Type) (types.Type, bool) {
	i.typesMutex.RLock()
	defer i.typesMutex.RUnlock()
	return i.findTypeHelper(t)
}
func (i *interpreter) findTypeHelper(t reflect.Type) (types.Type, bool) {
	for k, v := range i.types {
		if v == t {
			return k, true
		}
	}
	if t.Kind() == reflect.Ptr {
		if typ, ok := i.findTypeHelper(t.Elem()); ok {
			return types.NewPointer(typ), true
		}
	}
	return nil, false
}
func ptrCount(s string) (string, int) {
	for i, v := range s {
		if v != '*' {
			return s[i:], i
		}
	}
	panic("failed ptrCount " + s)
}
func isUntyped(typ types.Type) bool {
	t, ok := typ.Underlying().(*types.Basic)
	return ok && t.Info()&types.IsUntyped != 0
}
func (i *interpreter) toType(typ types.Type) reflect.Type {
	i.typesMutex.RLock()
	tt, ok := i.types[typ]
	i.typesMutex.RUnlock()
	if ok {
		return tt
	}
	i.typesMutex.Lock()
	defer i.typesMutex.Unlock()
	if isUntyped(typ) {
		typ = types.Default(typ)
	}
	t, err := xtypes.ToType(typ, i.ctx)
	if err != nil {
		panic(fmt.Sprintf("toType %v error: %v", typ, err))
	}
	i.types[typ] = t
	return t
}
func (fr *frame) toFunc(typ reflect.Type, fn value) reflect.Value {
	return reflect.MakeFunc(typ, func(args []reflect.Value) []reflect.Value {
		iargs := make([]value, len(args))
		for i := 0; i < len(args); i++ {
			iargs[i] = args[i].Interface()
		}
		r := call(fr.i, fr, token.NoPos, fn, iargs, nil)
		if v, ok := r.(tuple); ok {
			res := make([]reflect.Value, len(v))
			for i := 0; i < len(v); i++ {
				if v[i] == nil {
					res[i] = reflect.New(typ.Out(i)).Elem()
				} else {
					res[i] = reflect.ValueOf(v[i])
				}
			}
			return res
		} else if typ.NumOut() == 1 {
			if r != nil {
				return []reflect.Value{reflect.ValueOf(r)}
			} else {
				return []reflect.Value{reflect.New(typ.Out(0)).Elem()}
			}
		}
		return nil
	})
}
type deferred struct {
	fn      value
	args    []value
	ssaArgs []ssa.Value
	instr   *ssa.Defer
	tail    *deferred
}
type frame struct {
	i                *interpreter
	caller           *frame
	fn               *ssa.Function
	block, prevBlock *ssa.BasicBlock
	env              map[ssa.Value]value  
	locals           map[ssa.Value]reflect.Value
	mapUnderscoreKey map[types.Type]bool
	defers           *deferred
	result           value
	panicking        bool
	panic            interface{}
}
func (fr *frame) get(key ssa.Value) value {
	if key == nil {
		return nil
	}
	if key.Parent() == nil {
		if ext, ok := externValues[key.String()]; ok {
			if fr.i.mode&EnableTracing != 0 {
				fmt.Fprintln(os.Stderr, "\t(external)")
			}
			return ext.Interface()
		}
	}
	switch key := key.(type) {
	case *ssa.Function:
		return key
	case *ssa.Builtin:
		return key
	case *ssa.Const:
		c := constValue(fr.i, key)
		if c == nil {
			return c
		}
		typ := fr.i.toType(key.Type())
		if typ.PkgPath() == "" {
			return c
		}
		v := reflect.New(typ).Elem()
		SetValue(v, reflect.ValueOf(c))
		return v.Interface()
	case *ssa.Global:
		if r, ok := fr.i.globals[key]; ok {
			return r
		}
	}
	if r, ok := fr.env[key]; ok {
		return r
	}
	panic(fmt.Sprintf("get: no value for %T: %v", key, key.String()))
}
func (fr *frame) runDefer(d *deferred) {
	if fr.i.mode&EnableTracing != 0 {
		fmt.Fprintf(os.Stderr, "%s: invoking deferred function call\n",
			fr.i.prog.Fset.Position(d.instr.Pos()))
	}
	var ok bool
	defer func() {
		if !ok {
			fr.panicking = true
			fr.panic = recover()
		}
	}()
	call(fr.i, fr, d.instr.Pos(), d.fn, d.args, d.ssaArgs)
	ok = true
}