github.com/goplus/gossa@v0.3.25/opblock.go (about)

     1  package gossa
     2  
     3  import (
     4  	"fmt"
     5  	"go/token"
     6  	"go/types"
     7  	"io"
     8  	"reflect"
     9  	"runtime"
    10  	"strings"
    11  	"sync"
    12  	"sync/atomic"
    13  	"unsafe"
    14  
    15  	"github.com/goplus/gossa/internal/xtype"
    16  	"github.com/goplus/reflectx"
    17  	"github.com/visualfc/funcval"
    18  	"golang.org/x/tools/go/ssa"
    19  )
    20  
    21  /*
    22  type Op int
    23  
    24  const (
    25  	OpInvalid Op = iota
    26  	// Value-defining instructions
    27  	OpAlloc
    28  	OpPhi
    29  	OpCall
    30  	OpBinOp
    31  	OpUnOp
    32  	OpChangeType
    33  	OpConvert
    34  	OpChangeInterface
    35  	OpSliceToArrayPointer
    36  	OpMakeInterface
    37  	OpMakeClosure
    38  	OpMakeMap
    39  	OpMakeChan
    40  	OpMakeSlice
    41  	OpSlice
    42  	OpFieldAddr
    43  	OpField
    44  	OpIndexAddr
    45  	OpIndex
    46  	OpLookup
    47  	OpSelect
    48  	OpRange
    49  	OpNext
    50  	OpTypeAssert
    51  	OpExtract
    52  	// Instructions executed for effect
    53  	OpJump
    54  	OpIf
    55  	OpReturn
    56  	OpRunDefers
    57  	OpPanic
    58  	OpGo
    59  	OpDefer
    60  	OpSend
    61  	OpStore
    62  	OpMapUpdate
    63  	OpDebugRef
    64  )
    65  */
    66  
    67  type kind int
    68  
    69  func (k kind) isStatic() bool {
    70  	return k == kindConst || k == kindGlobal || k == kindFunction
    71  }
    72  
    73  const (
    74  	kindInvalid kind = iota
    75  	kindConst
    76  	kindGlobal
    77  	kindFunction
    78  )
    79  
    80  type Value = value
    81  type Tuple = tuple
    82  
    83  type register int
    84  type value = interface{}
    85  type tuple []value
    86  
    87  type closure struct {
    88  	pfn *function
    89  	env []value
    90  }
    91  
    92  type function struct {
    93  	Interp           *Interp
    94  	Fn               *ssa.Function        // ssa function
    95  	Main             *ssa.BasicBlock      // Fn.Blocks[0]
    96  	pool             *sync.Pool           // create frame pool
    97  	Instrs           []func(fr *frame)    // main instrs
    98  	Recover          []func(fr *frame)    // recover instrs
    99  	Blocks           []int                // block offset
   100  	stack            []value              // results args envs datas
   101  	ssaInstrs        []ssa.Instruction    // org ssa instr
   102  	index            map[ssa.Value]uint32 // stack index
   103  	mapUnderscoreKey map[types.Type]bool  // struct has _ key
   104  	nres             int                  // results count
   105  	narg             int                  // arguments count
   106  	nenv             int                  // closure free vars count
   107  	used             int32                // function used count
   108  	cached           int32                // enable cached by pool
   109  }
   110  
   111  func (p *function) initPool() {
   112  	p.pool = &sync.Pool{}
   113  	p.pool.New = func() interface{} {
   114  		fr := &frame{pfn: p, block: p.Main}
   115  		fr.stack = append([]value{}, p.stack...)
   116  		return fr
   117  	}
   118  }
   119  
   120  func (p *function) allocFrame(caller *frame) *frame {
   121  	var fr *frame
   122  	if atomic.LoadInt32(&p.cached) == 1 {
   123  		fr = p.pool.Get().(*frame)
   124  	} else {
   125  		if atomic.AddInt32(&p.used, 1) > int32(p.Interp.ctx.callForPool) {
   126  			atomic.StoreInt32(&p.cached, 1)
   127  		}
   128  		fr = &frame{pfn: p, block: p.Main}
   129  		fr.stack = append([]value{}, p.stack...)
   130  	}
   131  	fr.caller = caller
   132  	if caller != nil {
   133  		fr.deferid = caller.deferid
   134  	}
   135  	if fr.pc == -1 {
   136  		fr.block = p.Main
   137  		fr.defers = nil
   138  		fr.panicking = nil
   139  		fr.pc = 0
   140  		fr.pred = 0
   141  	}
   142  	return fr
   143  }
   144  
   145  func (p *function) deleteFrame(fr *frame) {
   146  	if atomic.LoadInt32(&p.cached) == 1 {
   147  		p.pool.Put(fr)
   148  	}
   149  	fr = nil
   150  }
   151  
   152  func (p *function) InstrForPC(pc int) ssa.Instruction {
   153  	if pc >= 0 && pc < len(p.ssaInstrs) {
   154  		return p.ssaInstrs[pc]
   155  	}
   156  	return nil
   157  }
   158  
   159  func (p *function) PosForPC(pc int) token.Pos {
   160  	if instr := p.InstrForPC(pc); instr != nil {
   161  		return instr.Pos()
   162  	}
   163  	return token.NoPos
   164  }
   165  
   166  func (p *function) regIndex3(v ssa.Value) (register, kind, value) {
   167  	instr := p.regInstr(v)
   168  	index := int(instr & 0xffffff)
   169  	return register(index), kind(instr >> 24), p.stack[index]
   170  }
   171  
   172  func (p *function) regIndex(v ssa.Value) register {
   173  	instr := p.regInstr(v)
   174  	return register(instr & 0xffffff)
   175  }
   176  
   177  func (p *function) regInstr(v ssa.Value) uint32 {
   178  	if i, ok := p.index[v]; ok {
   179  		return i
   180  	}
   181  	var vs interface{}
   182  	var vk kind
   183  	switch v := v.(type) {
   184  	case *ssa.Const:
   185  		vs = constToValue(p.Interp, v)
   186  		vk = kindConst
   187  	case *ssa.Global:
   188  		vs, _ = globalToValue(p.Interp, v)
   189  		vk = kindGlobal
   190  	case *ssa.Function:
   191  		vk = kindFunction
   192  		if v.Blocks != nil {
   193  			typ := p.Interp.preToType(v.Type())
   194  			pfn := p.Interp.loadFunction(v)
   195  			vs = p.Interp.makeFunc(typ, pfn, nil).Interface()
   196  		} else {
   197  			ext, ok := findExternFunc(p.Interp, v)
   198  			if !ok {
   199  				if v.Name() != "init" {
   200  					panic(fmt.Errorf("no code for function: %v", v))
   201  				}
   202  			} else {
   203  				vs = ext.Interface()
   204  			}
   205  		}
   206  	}
   207  	i := uint32(len(p.stack) | int(vk<<24))
   208  	p.stack = append(p.stack, vs)
   209  	p.index[v] = i
   210  	return i
   211  }
   212  
   213  func findExternFunc(interp *Interp, fn *ssa.Function) (ext reflect.Value, ok bool) {
   214  	fnName := fn.String()
   215  	if fnName == "os.Exit" {
   216  		return reflect.ValueOf(func(code int) {
   217  			if atomic.LoadInt32(&interp.goexited) == 1 {
   218  				//os.Exit(code)
   219  				interp.chexit <- code
   220  			} else {
   221  				panic(exitPanic(code))
   222  			}
   223  		}), true
   224  	} else if fnName == "runtime.Goexit" {
   225  		return reflect.ValueOf(func() {
   226  			// main goroutine use panic
   227  			if goroutineId() == interp.mainid {
   228  				atomic.StoreInt32(&interp.goexited, 1)
   229  				panic(goexitPanic(0))
   230  			} else {
   231  				runtime.Goexit()
   232  			}
   233  		}), true
   234  	}
   235  	// check override func
   236  	ext, ok = interp.ctx.override[fnName]
   237  	if ok {
   238  		return
   239  	}
   240  	// check extern func
   241  	ext, ok = externValues[fnName]
   242  	if ok {
   243  		return
   244  	}
   245  	if fn.Pkg != nil {
   246  		if recv := fn.Signature.Recv(); recv == nil {
   247  			if pkg, found := interp.installed(fn.Pkg.Pkg.Path()); found {
   248  				ext, ok = pkg.Funcs[fn.Name()]
   249  			}
   250  		} else if typ, found := interp.loader.LookupReflect(recv.Type()); found {
   251  			if m, found := reflectx.MethodByName(typ, fn.Name()); found {
   252  				ext, ok = m.Func, true
   253  			}
   254  		}
   255  	}
   256  	return
   257  }
   258  
   259  func makeInstr(interp *Interp, pfn *function, instr ssa.Instruction) func(fr *frame) {
   260  	switch instr := instr.(type) {
   261  	case *ssa.Alloc:
   262  		if instr.Heap {
   263  			typ := interp.preToType(instr.Type())
   264  			ir := pfn.regIndex(instr)
   265  			t := xtype.TypeOfType(typ.Elem())
   266  			pt := xtype.TypeOfType(typ)
   267  			return func(fr *frame) {
   268  				fr.setReg(ir, xtype.New(t, pt))
   269  			}
   270  		} else {
   271  			typ := interp.preToType(instr.Type())
   272  			ir := pfn.regIndex(instr)
   273  			t := xtype.TypeOfType(typ.Elem())
   274  			pt := xtype.TypeOfType(typ)
   275  			ptr := xtype.NewPointer(t)
   276  			return func(fr *frame) {
   277  				if v := fr.reg(ir); v != nil {
   278  					xtype.SetPointer(v, ptr)
   279  				} else {
   280  					fr.setReg(ir, xtype.New(t, pt))
   281  				}
   282  			}
   283  		}
   284  	case *ssa.Phi:
   285  		ir := pfn.regIndex(instr)
   286  		ie := make([]register, len(instr.Edges))
   287  		for i, v := range instr.Edges {
   288  			ie[i] = pfn.regIndex(v)
   289  		}
   290  		return func(fr *frame) {
   291  			for i, pred := range instr.Block().Preds {
   292  				if fr.pred == pred.Index {
   293  					fr.setReg(ir, fr.reg(ie[i]))
   294  					break
   295  				}
   296  			}
   297  		}
   298  	case *ssa.Call:
   299  		return makeCallInstr(pfn, interp, instr, &instr.Call)
   300  	case *ssa.BinOp:
   301  		switch instr.Op {
   302  		case token.ADD:
   303  			return makeBinOpADD(pfn, instr)
   304  		case token.SUB:
   305  			return makeBinOpSUB(pfn, instr)
   306  		case token.MUL:
   307  			return makeBinOpMUL(pfn, instr)
   308  		case token.QUO:
   309  			return makeBinOpQUO(pfn, instr)
   310  		case token.REM:
   311  			return makeBinOpREM(pfn, instr)
   312  		case token.AND:
   313  			return makeBinOpAND(pfn, instr)
   314  		case token.OR:
   315  			return makeBinOpOR(pfn, instr)
   316  		case token.XOR:
   317  			return makeBinOpXOR(pfn, instr)
   318  		case token.AND_NOT:
   319  			return makeBinOpANDNOT(pfn, instr)
   320  		case token.LSS:
   321  			return makeBinOpLSS(pfn, instr)
   322  		case token.LEQ:
   323  			return makeBinOpLEQ(pfn, instr)
   324  		case token.GTR:
   325  			return makeBinOpGTR(pfn, instr)
   326  		case token.GEQ:
   327  			return makeBinOpGEQ(pfn, instr)
   328  		case token.EQL:
   329  			return makeBinOpEQL(pfn, instr)
   330  		case token.NEQ:
   331  			return makeBinOpNEQ(pfn, instr)
   332  		case token.SHL:
   333  			return makeBinOpSHL(pfn, instr)
   334  		case token.SHR:
   335  			return makeBinOpSHR(pfn, instr)
   336  		default:
   337  			panic("unreachable")
   338  		}
   339  	case *ssa.UnOp:
   340  		switch instr.Op {
   341  		case token.NOT:
   342  			return makeUnOpNOT(pfn, instr)
   343  		case token.SUB:
   344  			return makeUnOpSUB(pfn, instr)
   345  		case token.XOR:
   346  			return makeUnOpXOR(pfn, instr)
   347  		case token.ARROW:
   348  			return makeUnOpARROW(pfn, instr)
   349  		case token.MUL:
   350  			return makeUnOpMUL(pfn, instr)
   351  		default:
   352  			panic("unreachable")
   353  		}
   354  	case *ssa.ChangeInterface:
   355  		ir := pfn.regIndex(instr)
   356  		ix := pfn.regIndex(instr.X)
   357  		return func(fr *frame) {
   358  			fr.setReg(ir, fr.reg(ix))
   359  		}
   360  	case *ssa.ChangeType:
   361  		return makeTypeChangeInstr(pfn, instr)
   362  	case *ssa.Convert:
   363  		return makeConvertInstr(pfn, interp, instr)
   364  	case *ssa.MakeInterface:
   365  		typ := interp.preToType(instr.Type())
   366  		ir := pfn.regIndex(instr)
   367  		ix, kx, vx := pfn.regIndex3(instr.X)
   368  		if kx.isStatic() {
   369  			if typ == tyEmptyInterface {
   370  				return func(fr *frame) {
   371  					fr.setReg(ir, vx)
   372  				}
   373  			}
   374  			v := reflect.New(typ).Elem()
   375  			if vx != nil {
   376  				SetValue(v, reflect.ValueOf(vx))
   377  			}
   378  			vx = v.Interface()
   379  			return func(fr *frame) {
   380  				fr.setReg(ir, vx)
   381  			}
   382  		}
   383  		if typ == tyEmptyInterface {
   384  			return func(fr *frame) {
   385  				fr.setReg(ir, fr.reg(ix))
   386  			}
   387  		}
   388  		return func(fr *frame) {
   389  			v := reflect.New(typ).Elem()
   390  			if x := fr.reg(ix); x != nil {
   391  				SetValue(v, reflect.ValueOf(x))
   392  			}
   393  			fr.setReg(ir, v.Interface())
   394  		}
   395  	case *ssa.MakeClosure:
   396  		fn := instr.Fn.(*ssa.Function)
   397  		typ := interp.preToType(fn.Type())
   398  		ir := pfn.regIndex(instr)
   399  		ib := make([]register, len(instr.Bindings))
   400  		for i, v := range instr.Bindings {
   401  			ib[i] = pfn.regIndex(v)
   402  		}
   403  		pfn := interp.loadFunction(fn)
   404  		return func(fr *frame) {
   405  			var bindings []value
   406  			for i, _ := range instr.Bindings {
   407  				bindings = append(bindings, fr.reg(ib[i]))
   408  			}
   409  			v := interp.makeFunc(typ, pfn, bindings)
   410  			fr.setReg(ir, v.Interface())
   411  		}
   412  	case *ssa.MakeChan:
   413  		typ := interp.preToType(instr.Type())
   414  		ir := pfn.regIndex(instr)
   415  		is := pfn.regIndex(instr.Size)
   416  		return func(fr *frame) {
   417  			size := fr.reg(is)
   418  			buffer := asInt(size)
   419  			if buffer < 0 {
   420  				panic(runtimeError("makechan: size out of range"))
   421  			}
   422  			fr.setReg(ir, reflect.MakeChan(typ, buffer).Interface())
   423  		}
   424  	case *ssa.MakeMap:
   425  		typ := instr.Type()
   426  		rtyp := interp.preToType(typ)
   427  		key := typ.Underlying().(*types.Map).Key()
   428  		if st, ok := key.Underlying().(*types.Struct); ok && hasUnderscore(st) {
   429  			pfn.mapUnderscoreKey[typ] = true
   430  		}
   431  		ir := pfn.regIndex(instr)
   432  		if instr.Reserve == nil {
   433  			return func(fr *frame) {
   434  				fr.setReg(ir, reflect.MakeMap(rtyp).Interface())
   435  			}
   436  		} else {
   437  			iv := pfn.regIndex(instr.Reserve)
   438  			return func(fr *frame) {
   439  				reserve := asInt(fr.reg(iv))
   440  				fr.setReg(ir, reflect.MakeMapWithSize(rtyp, reserve).Interface())
   441  			}
   442  		}
   443  	case *ssa.MakeSlice:
   444  		typ := interp.preToType(instr.Type())
   445  		ir := pfn.regIndex(instr)
   446  		il := pfn.regIndex(instr.Len)
   447  		ic := pfn.regIndex(instr.Cap)
   448  		return func(fr *frame) {
   449  			Len := asInt(fr.reg(il))
   450  			if Len < 0 || Len >= maxMemLen {
   451  				panic(runtimeError("makeslice: len out of range"))
   452  			}
   453  			Cap := asInt(fr.reg(ic))
   454  			if Cap < 0 || Cap >= maxMemLen {
   455  				panic(runtimeError("makeslice: cap out of range"))
   456  			}
   457  			fr.setReg(ir, reflect.MakeSlice(typ, Len, Cap).Interface())
   458  		}
   459  	case *ssa.Slice:
   460  		typ := interp.preToType(instr.Type())
   461  		isNamed := typ.Kind() == reflect.Slice && typ != reflect.SliceOf(typ.Elem())
   462  		_, makesliceCheck := instr.X.(*ssa.Alloc)
   463  		ir := pfn.regIndex(instr)
   464  		ix := pfn.regIndex(instr.X)
   465  		ih := pfn.regIndex(instr.High)
   466  		il := pfn.regIndex(instr.Low)
   467  		im := pfn.regIndex(instr.Max)
   468  		if isNamed {
   469  			return func(fr *frame) {
   470  				fr.setReg(ir, slice(fr, instr, makesliceCheck, ix, ih, il, im).Convert(typ).Interface())
   471  			}
   472  		} else {
   473  			return func(fr *frame) {
   474  				fr.setReg(ir, slice(fr, instr, makesliceCheck, ix, ih, il, im).Interface())
   475  			}
   476  		}
   477  	case *ssa.FieldAddr:
   478  		ir := pfn.regIndex(instr)
   479  		ix := pfn.regIndex(instr.X)
   480  		return func(fr *frame) {
   481  			v, err := FieldAddr(fr.reg(ix), instr.Field)
   482  			if err != nil {
   483  				panic(runtimeError(err.Error()))
   484  			}
   485  			fr.setReg(ir, v)
   486  		}
   487  	case *ssa.Field:
   488  		ir := pfn.regIndex(instr)
   489  		ix := pfn.regIndex(instr.X)
   490  		return func(fr *frame) {
   491  			v, err := Field(fr.reg(ix), instr.Field)
   492  			if err != nil {
   493  				panic(runtimeError(err.Error()))
   494  			}
   495  			fr.setReg(ir, v)
   496  		}
   497  	case *ssa.IndexAddr:
   498  		ir := pfn.regIndex(instr)
   499  		ix := pfn.regIndex(instr.X)
   500  		ii := pfn.regIndex(instr.Index)
   501  		return func(fr *frame) {
   502  			x := fr.reg(ix)
   503  			idx := fr.reg(ii)
   504  			v := reflect.ValueOf(x)
   505  			if v.Kind() == reflect.Ptr {
   506  				v = v.Elem()
   507  			}
   508  			switch v.Kind() {
   509  			case reflect.Slice:
   510  			case reflect.Array:
   511  			case reflect.Invalid:
   512  				panic(runtimeError("invalid memory address or nil pointer dereference"))
   513  			default:
   514  				panic(fmt.Sprintf("unexpected x type in IndexAddr: %T", x))
   515  			}
   516  			index := asInt(idx)
   517  			if index < 0 {
   518  				panic(runtimeError(fmt.Sprintf("index out of range [%v]", index)))
   519  			} else if length := v.Len(); index >= length {
   520  				panic(runtimeError(fmt.Sprintf("index out of range [%v] with length %v", index, length)))
   521  			}
   522  			fr.setReg(ir, v.Index(index).Addr().Interface())
   523  		}
   524  	case *ssa.Index:
   525  		ir := pfn.regIndex(instr)
   526  		ix := pfn.regIndex(instr.X)
   527  		ii := pfn.regIndex(instr.Index)
   528  		return func(fr *frame) {
   529  			x := fr.reg(ix)
   530  			idx := fr.reg(ii)
   531  			v := reflect.ValueOf(x)
   532  			fr.setReg(ir, v.Index(asInt(idx)).Interface())
   533  		}
   534  	case *ssa.Lookup:
   535  		typ := interp.preToType(instr.X.Type())
   536  		ir := pfn.regIndex(instr)
   537  		ix := pfn.regIndex(instr.X)
   538  		ii := pfn.regIndex(instr.Index)
   539  		switch typ.Kind() {
   540  		case reflect.String:
   541  			return func(fr *frame) {
   542  				v := fr.reg(ix)
   543  				idx := fr.reg(ii)
   544  				fr.setReg(ir, reflect.ValueOf(v).String()[asInt(idx)])
   545  			}
   546  		case reflect.Map:
   547  			if pfn.mapUnderscoreKey[instr.X.Type()] {
   548  				return func(fr *frame) {
   549  					m := fr.reg(ix)
   550  					idx := fr.reg(ii)
   551  					vm := reflect.ValueOf(m)
   552  					vk := reflect.ValueOf(idx)
   553  					for _, vv := range vm.MapKeys() {
   554  						if equalStruct(vk, vv) {
   555  							vk = vv
   556  							break
   557  						}
   558  					}
   559  					v := vm.MapIndex(vk)
   560  					ok := v.IsValid()
   561  					var rv value
   562  					if ok {
   563  						rv = v.Interface()
   564  					} else {
   565  						rv = reflect.New(typ.Elem()).Elem().Interface()
   566  					}
   567  					if instr.CommaOk {
   568  						fr.setReg(ir, tuple{rv, ok})
   569  					} else {
   570  						fr.setReg(ir, rv)
   571  					}
   572  				}
   573  			}
   574  			return func(fr *frame) {
   575  				m := fr.reg(ix)
   576  				idx := fr.reg(ii)
   577  				vm := reflect.ValueOf(m)
   578  				v := vm.MapIndex(reflect.ValueOf(idx))
   579  				ok := v.IsValid()
   580  				var rv value
   581  				if ok {
   582  					rv = v.Interface()
   583  				} else {
   584  					rv = reflect.New(typ.Elem()).Elem().Interface()
   585  				}
   586  				if instr.CommaOk {
   587  					fr.setReg(ir, tuple{rv, ok})
   588  				} else {
   589  					fr.setReg(ir, rv)
   590  				}
   591  			}
   592  		default:
   593  			panic("unreachable")
   594  		}
   595  	case *ssa.Select:
   596  		ir := pfn.regIndex(instr)
   597  		ic := make([]register, len(instr.States))
   598  		is := make([]register, len(instr.States))
   599  		for i, state := range instr.States {
   600  			ic[i] = pfn.regIndex(state.Chan)
   601  			if state.Send != nil {
   602  				is[i] = pfn.regIndex(state.Send)
   603  			}
   604  		}
   605  		return func(fr *frame) {
   606  			var cases []reflect.SelectCase
   607  			if !instr.Blocking {
   608  				cases = append(cases, reflect.SelectCase{
   609  					Dir: reflect.SelectDefault,
   610  				})
   611  			}
   612  			for i, state := range instr.States {
   613  				var dir reflect.SelectDir
   614  				if state.Dir == types.RecvOnly {
   615  					dir = reflect.SelectRecv
   616  				} else {
   617  					dir = reflect.SelectSend
   618  				}
   619  				ch := reflect.ValueOf(fr.reg(ic[i]))
   620  				var send reflect.Value
   621  				if state.Send != nil {
   622  					v := fr.reg(is[i])
   623  					if v == nil {
   624  						send = reflect.New(ch.Type().Elem()).Elem()
   625  					} else {
   626  						send = reflect.ValueOf(v)
   627  					}
   628  				}
   629  				cases = append(cases, reflect.SelectCase{
   630  					Dir:  dir,
   631  					Chan: ch,
   632  					Send: send,
   633  				})
   634  			}
   635  			chosen, recv, recvOk := reflect.Select(cases)
   636  			if !instr.Blocking {
   637  				chosen-- // default case should have index -1.
   638  			}
   639  			r := tuple{chosen, recvOk}
   640  			for n, st := range instr.States {
   641  				if st.Dir == types.RecvOnly {
   642  					var v value
   643  					if n == chosen && recvOk {
   644  						// No need to copy since send makes an unaliased copy.
   645  						v = recv.Interface()
   646  					} else {
   647  						typ := interp.toType(st.Chan.Type())
   648  						v = reflect.New(typ.Elem()).Elem().Interface()
   649  					}
   650  					r = append(r, v)
   651  				}
   652  			}
   653  			fr.setReg(ir, r)
   654  		}
   655  	case *ssa.SliceToArrayPointer:
   656  		typ := interp.preToType(instr.Type())
   657  		ir := pfn.regIndex(instr)
   658  		ix := pfn.regIndex(instr.X)
   659  		return func(fr *frame) {
   660  			x := fr.reg(ix)
   661  			v := reflect.ValueOf(x)
   662  			vLen := v.Len()
   663  			tLen := typ.Elem().Len()
   664  			if tLen > vLen {
   665  				panic(runtimeError(fmt.Sprintf("cannot convert slice with length %v to pointer to array with length %v", vLen, tLen)))
   666  			}
   667  			fr.setReg(ir, v.Convert(typ).Interface())
   668  		}
   669  	case *ssa.Range:
   670  		typ := interp.preToType(instr.X.Type())
   671  		ir := pfn.regIndex(instr)
   672  		ix := pfn.regIndex(instr.X)
   673  		switch typ.Kind() {
   674  		case reflect.String:
   675  			return func(fr *frame) {
   676  				v := fr.string(ix)
   677  				fr.setReg(ir, &stringIter{Reader: strings.NewReader(v)})
   678  			}
   679  		case reflect.Map:
   680  			return func(fr *frame) {
   681  				v := fr.reg(ix)
   682  				fr.setReg(ir, &mapIter{iter: reflect.ValueOf(v).MapRange()})
   683  			}
   684  		default:
   685  			panic("unreachable")
   686  		}
   687  	case *ssa.Next:
   688  		ir := pfn.regIndex(instr)
   689  		ii := pfn.regIndex(instr.Iter)
   690  		if instr.IsString {
   691  			return func(fr *frame) {
   692  				fr.setReg(ir, fr.reg(ii).(*stringIter).next())
   693  			}
   694  		} else {
   695  			return func(fr *frame) {
   696  				fr.setReg(ir, fr.reg(ii).(*mapIter).next())
   697  			}
   698  		}
   699  	case *ssa.TypeAssert:
   700  		typ := interp.preToType(instr.AssertedType)
   701  		ir := pfn.regIndex(instr)
   702  		ix, kx, vx := pfn.regIndex3(instr.X)
   703  		if kx.isStatic() {
   704  			return func(fr *frame) {
   705  				fr.setReg(ir, typeAssert(interp, instr, typ, vx))
   706  			}
   707  		}
   708  		return func(fr *frame) {
   709  			v := fr.reg(ix)
   710  			fr.setReg(ir, typeAssert(interp, instr, typ, v))
   711  		}
   712  	case *ssa.Extract:
   713  		if *instr.Referrers() == nil {
   714  			return nil
   715  		}
   716  		ir := pfn.regIndex(instr)
   717  		it := pfn.regIndex(instr.Tuple)
   718  		return func(fr *frame) {
   719  			fr.setReg(ir, fr.reg(it).(tuple)[instr.Index])
   720  		}
   721  	// Instructions executed for effect
   722  	case *ssa.Jump:
   723  		return func(fr *frame) {
   724  			fr.pred, fr.block = fr.block.Index, fr.block.Succs[0]
   725  			fr.pc = fr.pfn.Blocks[fr.block.Index]
   726  		}
   727  	case *ssa.If:
   728  		ic, kc, vc := pfn.regIndex3(instr.Cond)
   729  		if kc == kindConst {
   730  			if xtype.Bool(vc) {
   731  				return func(fr *frame) {
   732  					fr.pred = fr.block.Index
   733  					fr.block = fr.block.Succs[0]
   734  					fr.pc = fr.pfn.Blocks[fr.block.Index]
   735  				}
   736  			} else {
   737  				return func(fr *frame) {
   738  					fr.pred = fr.block.Index
   739  					fr.block = fr.block.Succs[1]
   740  					fr.pc = fr.pfn.Blocks[fr.block.Index]
   741  				}
   742  			}
   743  		}
   744  		switch instr.Cond.Type().(type) {
   745  		case *types.Basic:
   746  			return func(fr *frame) {
   747  				fr.pred = fr.block.Index
   748  				if fr.reg(ic).(bool) {
   749  					fr.block = fr.block.Succs[0]
   750  				} else {
   751  					fr.block = fr.block.Succs[1]
   752  				}
   753  				fr.pc = fr.pfn.Blocks[fr.block.Index]
   754  			}
   755  		default:
   756  			return func(fr *frame) {
   757  				fr.pred = fr.block.Index
   758  				if fr.bool(ic) {
   759  					fr.block = fr.block.Succs[0]
   760  				} else {
   761  					fr.block = fr.block.Succs[1]
   762  				}
   763  				fr.pc = fr.pfn.Blocks[fr.block.Index]
   764  			}
   765  		}
   766  	case *ssa.Return:
   767  		switch n := pfn.nres; n {
   768  		case 0:
   769  			return func(fr *frame) {
   770  				fr.pc = -1
   771  			}
   772  		case 1:
   773  			ir, ik, iv := pfn.regIndex3(instr.Results[0])
   774  			if ik.isStatic() {
   775  				return func(fr *frame) {
   776  					fr.stack[0] = iv
   777  					fr.pc = -1
   778  				}
   779  			}
   780  			return func(fr *frame) {
   781  				fr.stack[0] = fr.reg(ir)
   782  				fr.pc = -1
   783  			}
   784  		case 2:
   785  			r1, k1, v1 := pfn.regIndex3(instr.Results[0])
   786  			r2, k2, v2 := pfn.regIndex3(instr.Results[1])
   787  			if k1.isStatic() && k2.isStatic() {
   788  				return func(fr *frame) {
   789  					fr.stack[0] = v1
   790  					fr.stack[1] = v2
   791  					fr.pc = -1
   792  				}
   793  			} else if k1.isStatic() {
   794  				return func(fr *frame) {
   795  					fr.stack[0] = v1
   796  					fr.stack[1] = fr.reg(r2)
   797  					fr.pc = -1
   798  				}
   799  			} else if k2.isStatic() {
   800  				return func(fr *frame) {
   801  					fr.stack[0] = fr.reg(r1)
   802  					fr.stack[1] = v2
   803  					fr.pc = -1
   804  				}
   805  			}
   806  			return func(fr *frame) {
   807  				fr.stack[0] = fr.reg(r1)
   808  				fr.stack[1] = fr.reg(r2)
   809  				fr.pc = -1
   810  			}
   811  		default:
   812  			ir := make([]register, n, n)
   813  			for i, v := range instr.Results {
   814  				ir[i] = pfn.regIndex(v)
   815  			}
   816  			return func(fr *frame) {
   817  				for i := 0; i < n; i++ {
   818  					fr.stack[i] = fr.reg(ir[i])
   819  				}
   820  				fr.pc = -1
   821  			}
   822  		}
   823  	case *ssa.RunDefers:
   824  		return func(fr *frame) {
   825  			fr.runDefers()
   826  		}
   827  	case *ssa.Panic:
   828  		ix := pfn.regIndex(instr.X)
   829  		return func(fr *frame) {
   830  			panic(targetPanic{fr.reg(ix)})
   831  		}
   832  	case *ssa.Go:
   833  		iv, ia, ib := getCallIndex(pfn, &instr.Call)
   834  		return func(fr *frame) {
   835  			fn, args := interp.prepareCall(fr, &instr.Call, iv, ia, ib)
   836  			atomic.AddInt32(&interp.goroutines, 1)
   837  			go func() {
   838  				interp.callDiscardsResult(nil, fn, args, instr.Call.Args)
   839  				atomic.AddInt32(&interp.goroutines, -1)
   840  			}()
   841  		}
   842  	case *ssa.Defer:
   843  		iv, ia, ib := getCallIndex(pfn, &instr.Call)
   844  		return func(fr *frame) {
   845  			fn, args := interp.prepareCall(fr, &instr.Call, iv, ia, ib)
   846  			fr.defers = &deferred{
   847  				fn:      fn,
   848  				args:    args,
   849  				ssaArgs: instr.Call.Args,
   850  				instr:   instr,
   851  				tail:    fr.defers,
   852  			}
   853  		}
   854  	case *ssa.Send:
   855  		ic := pfn.regIndex(instr.Chan)
   856  		ix := pfn.regIndex(instr.X)
   857  		return func(fr *frame) {
   858  			c := fr.reg(ic)
   859  			x := fr.reg(ix)
   860  			ch := reflect.ValueOf(c)
   861  			if x == nil {
   862  				ch.Send(reflect.New(ch.Type().Elem()).Elem())
   863  			} else {
   864  				ch.Send(reflect.ValueOf(x))
   865  			}
   866  		}
   867  	case *ssa.Store:
   868  		// skip struct field _
   869  		if addr, ok := instr.Addr.(*ssa.FieldAddr); ok {
   870  			if s, ok := addr.X.Type().(*types.Pointer).Elem().(*types.Struct); ok {
   871  				if s.Field(addr.Field).Name() == "_" {
   872  					return nil
   873  				}
   874  			}
   875  		}
   876  		ia := pfn.regIndex(instr.Addr)
   877  		iv, kv, vv := pfn.regIndex3(instr.Val)
   878  		if kv.isStatic() {
   879  			if vv == nil {
   880  				return func(fr *frame) {
   881  					x := reflect.ValueOf(fr.reg(ia))
   882  					SetValue(x.Elem(), reflect.New(x.Elem().Type()).Elem())
   883  				}
   884  			}
   885  			return func(fr *frame) {
   886  				x := reflect.ValueOf(fr.reg(ia))
   887  				SetValue(x.Elem(), reflect.ValueOf(vv))
   888  			}
   889  		}
   890  		return func(fr *frame) {
   891  			x := reflect.ValueOf(fr.reg(ia))
   892  			val := fr.reg(iv)
   893  			v := reflect.ValueOf(val)
   894  			if v.IsValid() {
   895  				SetValue(x.Elem(), v)
   896  			} else {
   897  				SetValue(x.Elem(), reflect.New(x.Elem().Type()).Elem())
   898  			}
   899  		}
   900  	case *ssa.MapUpdate:
   901  		im := pfn.regIndex(instr.Map)
   902  		ik := pfn.regIndex(instr.Key)
   903  		iv, kv, vv := pfn.regIndex3(instr.Value)
   904  		if pfn.mapUnderscoreKey[instr.Map.Type()] {
   905  			if kv.isStatic() {
   906  				return func(fr *frame) {
   907  					vm := reflect.ValueOf(fr.reg(im))
   908  					vk := reflect.ValueOf(fr.reg(ik))
   909  					for _, v := range vm.MapKeys() {
   910  						if equalStruct(vk, v) {
   911  							vk = v
   912  							break
   913  						}
   914  					}
   915  					vm.SetMapIndex(vk, reflect.ValueOf(vv))
   916  				}
   917  			}
   918  			return func(fr *frame) {
   919  				vm := reflect.ValueOf(fr.reg(im))
   920  				vk := reflect.ValueOf(fr.reg(ik))
   921  				v := fr.reg(iv)
   922  				for _, vv := range vm.MapKeys() {
   923  					if equalStruct(vk, vv) {
   924  						vk = vv
   925  						break
   926  					}
   927  				}
   928  				vm.SetMapIndex(vk, reflect.ValueOf(v))
   929  			}
   930  		}
   931  		if kv.isStatic() {
   932  			return func(fr *frame) {
   933  				vm := reflect.ValueOf(fr.reg(im))
   934  				vk := reflect.ValueOf(fr.reg(ik))
   935  				vm.SetMapIndex(vk, reflect.ValueOf(vv))
   936  			}
   937  		} else {
   938  			return func(fr *frame) {
   939  				vm := reflect.ValueOf(fr.reg(im))
   940  				vk := reflect.ValueOf(fr.reg(ik))
   941  				v := fr.reg(iv)
   942  				vm.SetMapIndex(vk, reflect.ValueOf(v))
   943  			}
   944  		}
   945  	case *ssa.DebugRef:
   946  		if v, ok := instr.Object().(*types.Var); ok {
   947  			ix := pfn.regIndex(instr.X)
   948  			return func(fr *frame) {
   949  				ref := &DebugInfo{DebugRef: instr, fset: interp.fset}
   950  				ref.toValue = func() (*types.Var, interface{}, bool) {
   951  					return v, fr.reg(ix), true
   952  				}
   953  				interp.ctx.debugFunc(ref)
   954  			}
   955  		}
   956  		return func(fr *frame) {
   957  			ref := &DebugInfo{DebugRef: instr, fset: interp.fset}
   958  			ref.toValue = func() (*types.Var, interface{}, bool) {
   959  				return nil, nil, false
   960  			}
   961  			interp.ctx.debugFunc(ref)
   962  		}
   963  	default:
   964  		panic(fmt.Errorf("unreachable %T", instr))
   965  	}
   966  }
   967  
   968  func getCallIndex(pfn *function, call *ssa.CallCommon) (iv register, ia []register, ib []register) {
   969  	iv = pfn.regIndex(call.Value)
   970  	ia = make([]register, len(call.Args), len(call.Args))
   971  	for i, v := range call.Args {
   972  		ia[i] = pfn.regIndex(v)
   973  	}
   974  	if f, ok := call.Value.(*ssa.MakeClosure); ok {
   975  		ib = make([]register, len(f.Bindings), len(f.Bindings))
   976  		for i, binding := range f.Bindings {
   977  			ib[i] = pfn.regIndex(binding)
   978  		}
   979  	}
   980  	return
   981  }
   982  
   983  func makeCallInstr(pfn *function, interp *Interp, instr ssa.Value, call *ssa.CallCommon) func(fr *frame) {
   984  	ir := pfn.regIndex(instr)
   985  	iv, ia, ib := getCallIndex(pfn, call)
   986  	switch fn := call.Value.(type) {
   987  	case *ssa.Builtin:
   988  		fname := fn.Name()
   989  		return func(fr *frame) {
   990  			interp.callBuiltinByStack(fr, fname, call.Args, ir, ia)
   991  		}
   992  	case *ssa.MakeClosure:
   993  		ifn := interp.loadFunction(fn.Fn.(*ssa.Function))
   994  		ia = append(ia, ib...)
   995  		if ifn.Recover == nil {
   996  			switch ifn.nres {
   997  			case 0:
   998  				return func(fr *frame) {
   999  					interp.callFunctionByStackNoRecover0(fr, ifn, ir, ia)
  1000  				}
  1001  			case 1:
  1002  				return func(fr *frame) {
  1003  					interp.callFunctionByStackNoRecover1(fr, ifn, ir, ia)
  1004  				}
  1005  			default:
  1006  				return func(fr *frame) {
  1007  					interp.callFunctionByStackNoRecoverN(fr, ifn, ir, ia)
  1008  				}
  1009  			}
  1010  		}
  1011  		switch ifn.nres {
  1012  		case 0:
  1013  			return func(fr *frame) {
  1014  				interp.callFunctionByStack0(fr, ifn, ir, ia)
  1015  			}
  1016  		case 1:
  1017  			return func(fr *frame) {
  1018  				interp.callFunctionByStack1(fr, ifn, ir, ia)
  1019  			}
  1020  		default:
  1021  			return func(fr *frame) {
  1022  				interp.callFunctionByStackN(fr, ifn, ir, ia)
  1023  			}
  1024  		}
  1025  	case *ssa.Function:
  1026  		// "static func/method call"
  1027  		if fn.Blocks == nil {
  1028  			ext, ok := findExternFunc(interp, fn)
  1029  			if !ok {
  1030  				// skip pkg.init
  1031  				if fn.Pkg != nil && fn.Name() == "init" {
  1032  					return nil
  1033  				}
  1034  				panic(fmt.Errorf("no code for function: %v", fn))
  1035  			}
  1036  			return func(fr *frame) {
  1037  				interp.callExternalByStack(fr, ext, ir, ia)
  1038  			}
  1039  		}
  1040  		ifn := interp.loadFunction(fn)
  1041  		if ifn.Recover == nil {
  1042  			switch ifn.nres {
  1043  			case 0:
  1044  				return func(fr *frame) {
  1045  					interp.callFunctionByStackNoRecover0(fr, ifn, ir, ia)
  1046  				}
  1047  			case 1:
  1048  				return func(fr *frame) {
  1049  					interp.callFunctionByStackNoRecover1(fr, ifn, ir, ia)
  1050  				}
  1051  			default:
  1052  				return func(fr *frame) {
  1053  					interp.callFunctionByStackNoRecoverN(fr, ifn, ir, ia)
  1054  				}
  1055  			}
  1056  		}
  1057  		switch ifn.nres {
  1058  		case 0:
  1059  			return func(fr *frame) {
  1060  				interp.callFunctionByStack0(fr, ifn, ir, ia)
  1061  			}
  1062  		case 1:
  1063  			return func(fr *frame) {
  1064  				interp.callFunctionByStack1(fr, ifn, ir, ia)
  1065  			}
  1066  		default:
  1067  			return func(fr *frame) {
  1068  				interp.callFunctionByStackN(fr, ifn, ir, ia)
  1069  			}
  1070  		}
  1071  	}
  1072  	// "dynamic method call" // ("invoke" mode)
  1073  	if call.IsInvoke() {
  1074  		return makeCallMethodInstr(interp, instr, call, ir, iv, ia)
  1075  	}
  1076  	// dynamic func call
  1077  	typ := interp.preToType(call.Value.Type())
  1078  	if typ.Kind() != reflect.Func {
  1079  		panic("unsupport")
  1080  	}
  1081  	return func(fr *frame) {
  1082  		fn := fr.reg(iv)
  1083  		if fv, n := funcval.Get(fn); n == 1 {
  1084  			c := (*makeFuncVal)(unsafe.Pointer(fv))
  1085  			if c.pfn.Recover == nil {
  1086  				interp.callFunctionByStackNoRecoverWithEnv(fr, c.pfn, ir, ia, c.env)
  1087  			} else {
  1088  				interp.callFunctionByStackWithEnv(fr, c.pfn, ir, ia, c.env)
  1089  			}
  1090  		} else {
  1091  			v := reflect.ValueOf(fn)
  1092  			interp.callExternalByStack(fr, v, ir, ia)
  1093  		}
  1094  	}
  1095  }
  1096  
  1097  // makeFuncVal sync with Interp.makeFunc
  1098  // func (i *Interp) makeFunc(typ reflect.Type, pfn *Function, env []value) reflect.Value {
  1099  // 	return reflect.MakeFunc(typ, func(args []reflect.Value) []reflect.Value {
  1100  // 		return i.callFunctionByReflect(i.tryDeferFrame(), typ, pfn, args, env)
  1101  // 	})
  1102  // }
  1103  type makeFuncVal struct {
  1104  	funcval.FuncVal
  1105  	interp *Interp
  1106  	typ    reflect.Type
  1107  	pfn    *function
  1108  	env    []interface{}
  1109  }
  1110  
  1111  var (
  1112  	typeOfType      = reflect.TypeOf(reflect.TypeOf(0))
  1113  	vfnMethod       = reflect.ValueOf(reflectx.MethodByIndex)
  1114  	vfnMethodByName = reflect.ValueOf(reflectx.MethodByName)
  1115  )
  1116  
  1117  func findUserMethod(typ reflect.Type, name string) (ext reflect.Value, ok bool) {
  1118  	if m, ok := reflectx.MethodByName(typ, name); ok {
  1119  		return m.Func, true
  1120  	}
  1121  	return
  1122  }
  1123  
  1124  func findExternMethod(typ reflect.Type, name string) (ext reflect.Value, ok bool) {
  1125  	if typ == typeOfType {
  1126  		switch name {
  1127  		case "Method":
  1128  			return vfnMethod, true
  1129  		case "MethodByName":
  1130  			return vfnMethodByName, true
  1131  		}
  1132  	}
  1133  	if m, ok := typ.MethodByName(name); ok {
  1134  		return m.Func, true
  1135  	}
  1136  	return
  1137  }
  1138  
  1139  func (i *Interp) findMethod(typ reflect.Type, mname string) (fn *ssa.Function, ok bool) {
  1140  	if mset, mok := i.msets[typ]; mok {
  1141  		fn, ok = mset[mname]
  1142  	}
  1143  	return
  1144  }
  1145  
  1146  func makeCallMethodInstr(interp *Interp, instr ssa.Value, call *ssa.CallCommon, ir register, iv register, ia []register) func(fr *frame) {
  1147  	mname := call.Method.Name()
  1148  	ia = append([]register{iv}, ia...)
  1149  	var found bool
  1150  	var ext reflect.Value
  1151  	return func(fr *frame) {
  1152  		v := fr.reg(iv)
  1153  		rtype := reflect.TypeOf(v)
  1154  		// find user type method *ssa.Function
  1155  		if mset, ok := interp.msets[rtype]; ok {
  1156  			if fn, ok := mset[mname]; ok {
  1157  				interp.callFunctionByStack(fr, interp.funcs[fn], ir, ia)
  1158  				return
  1159  			}
  1160  			ext, found = findUserMethod(rtype, mname)
  1161  		} else {
  1162  			ext, found = findExternMethod(rtype, mname)
  1163  		}
  1164  		if !found {
  1165  			panic(fmt.Errorf("no code for method: %v.%v", rtype, mname))
  1166  		}
  1167  		interp.callExternalByStack(fr, ext, ir, ia)
  1168  	}
  1169  }
  1170  
  1171  type stringIter struct {
  1172  	*strings.Reader
  1173  	i int
  1174  }
  1175  
  1176  func (it *stringIter) next() tuple {
  1177  	okv := make(tuple, 3)
  1178  	ch, n, err := it.ReadRune()
  1179  	ok := err != io.EOF
  1180  	okv[0] = ok
  1181  	if ok {
  1182  		okv[1] = it.i
  1183  		okv[2] = ch
  1184  	}
  1185  	it.i += n
  1186  	return okv
  1187  }
  1188  
  1189  type mapIter struct {
  1190  	iter *reflect.MapIter
  1191  	ok   bool
  1192  }
  1193  
  1194  func (it *mapIter) next() tuple {
  1195  	it.ok = it.iter.Next()
  1196  	if !it.ok {
  1197  		return []value{false, nil, nil}
  1198  	}
  1199  	k, v := it.iter.Key().Interface(), it.iter.Value().Interface()
  1200  	return []value{true, k, v}
  1201  }