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 }