GoPLS Viewer

Home|gopls/go/ssa/interp/interp.go
1// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package ssa/interp defines an interpreter for the SSA
6// representation of Go programs.
7//
8// This interpreter is provided as an adjunct for testing the SSA
9// construction algorithm.  Its purpose is to provide a minimal
10// metacircular implementation of the dynamic semantics of each SSA
11// instruction.  It is not, and will never be, a production-quality Go
12// interpreter.
13//
14// The following is a partial list of Go features that are currently
15// unsupported or incomplete in the interpreter.
16//
17// * Unsafe operations, including all uses of unsafe.Pointer, are
18// impossible to support given the "boxed" value representation we
19// have chosen.
20//
21// * The reflect package is only partially implemented.
22//
23// * The "testing" package is no longer supported because it
24// depends on low-level details that change too often.
25//
26// * "sync/atomic" operations are not atomic due to the "boxed" value
27// representation: it is not possible to read, modify and write an
28// interface value atomically. As a consequence, Mutexes are currently
29// broken.
30//
31// * recover is only partially implemented.  Also, the interpreter
32// makes no attempt to distinguish target panics from interpreter
33// crashes.
34//
35// * the sizes of the int, uint and uintptr types in the target
36// program are assumed to be the same as those of the interpreter
37// itself.
38//
39// * all values occupy space, even those of types defined by the spec
40// to have zero size, e.g. struct{}.  This can cause asymptotic
41// performance degradation.
42//
43// * os.Exit is implemented using panic, causing deferred functions to
44// run.
45package interp // import "golang.org/x/tools/go/ssa/interp"
46
47import (
48    "fmt"
49    "go/token"
50    "go/types"
51    "os"
52    "reflect"
53    "runtime"
54    "sync/atomic"
55
56    "golang.org/x/tools/go/ssa"
57)
58
59type continuation int
60
61const (
62    kNext continuation = iota
63    kReturn
64    kJump
65)
66
67// Mode is a bitmask of options affecting the interpreter.
68type Mode uint
69
70const (
71    DisableRecover Mode = 1 << iota // Disable recover() in target programs; show interpreter crash instead.
72    EnableTracing                   // Print a trace of all instructions as they are interpreted.
73)
74
75type methodSet map[string]*ssa.Function
76
77// State shared between all interpreted goroutines.
78type interpreter struct {
79    osArgs             []value                // the value of os.Args
80    prog               *ssa.Program           // the SSA program
81    globals            map[*ssa.Global]*value // addresses of global variables (immutable)
82    mode               Mode                   // interpreter options
83    reflectPackage     *ssa.Package           // the fake reflect package
84    errorMethods       methodSet              // the method set of reflect.error, which implements the error interface.
85    rtypeMethods       methodSet              // the method set of rtype, which implements the reflect.Type interface.
86    runtimeErrorString types.Type             // the runtime.errorString type
87    sizes              types.Sizes            // the effective type-sizing function
88    goroutines         int32                  // atomically updated
89}
90
91type deferred struct {
92    fn    value
93    args  []value
94    instr *ssa.Defer
95    tail  *deferred
96}
97
98type frame struct {
99    i                *interpreter
100    caller           *frame
101    fn               *ssa.Function
102    blockprevBlock *ssa.BasicBlock
103    env              map[ssa.Value]value // dynamic values of SSA variables
104    locals           []value
105    defers           *deferred
106    result           value
107    panicking        bool
108    panic            interface{}
109}
110
111func (fr *frameget(key ssa.Valuevalue {
112    switch key := key.(type) {
113    case nil:
114        // Hack; simplifies handling of optional attributes
115        // such as ssa.Slice.{Low,High}.
116        return nil
117    case *ssa.Function, *ssa.Builtin:
118        return key
119    case *ssa.Const:
120        return constValue(key)
121    case *ssa.Global:
122        if rok := fr.i.globals[key]; ok {
123            return r
124        }
125    }
126    if rok := fr.env[key]; ok {
127        return r
128    }
129    panic(fmt.Sprintf("get: no value for %T: %v"keykey.Name()))
130}
131
132// runDefer runs a deferred call d.
133// It always returns normally, but may set or clear fr.panic.
134func (fr *framerunDefer(d *deferred) {
135    if fr.i.mode&EnableTracing != 0 {
136        fmt.Fprintf(os.Stderr"%s: invoking deferred function call\n",
137            fr.i.prog.Fset.Position(d.instr.Pos()))
138    }
139    var ok bool
140    defer func() {
141        if !ok {
142            // Deferred call created a new state of panic.
143            fr.panicking = true
144            fr.panic = recover()
145        }
146    }()
147    call(fr.ifrd.instr.Pos(), d.fnd.args)
148    ok = true
149}
150
151// runDefers executes fr's deferred function calls in LIFO order.
152//
153// On entry, fr.panicking indicates a state of panic; if
154// true, fr.panic contains the panic value.
155//
156// On completion, if a deferred call started a panic, or if no
157// deferred call recovered from a previous state of panic, then
158// runDefers itself panics after the last deferred call has run.
159//
160// If there was no initial state of panic, or it was recovered from,
161// runDefers returns normally.
162func (fr *framerunDefers() {
163    for d := fr.defersd != nild = d.tail {
164        fr.runDefer(d)
165    }
166    fr.defers = nil
167    if fr.panicking {
168        panic(fr.panic// new panic, or still panicking
169    }
170}
171
172// lookupMethod returns the method set for type typ, which may be one
173// of the interpreter's fake types.
174func lookupMethod(i *interpretertyp types.Typemeth *types.Func) *ssa.Function {
175    switch typ {
176    case rtypeType:
177        return i.rtypeMethods[meth.Id()]
178    case errorType:
179        return i.errorMethods[meth.Id()]
180    }
181    return i.prog.LookupMethod(typmeth.Pkg(), meth.Name())
182}
183
184// visitInstr interprets a single ssa.Instruction within the activation
185// record frame.  It returns a continuation value indicating where to
186// read the next instruction from.
187func visitInstr(fr *frameinstr ssa.Instructioncontinuation {
188    switch instr := instr.(type) {
189    case *ssa.DebugRef:
190        // no-op
191
192    case *ssa.UnOp:
193        fr.env[instr] = unop(instrfr.get(instr.X))
194
195    case *ssa.BinOp:
196        fr.env[instr] = binop(instr.Opinstr.X.Type(), fr.get(instr.X), fr.get(instr.Y))
197
198    case *ssa.Call:
199        fnargs := prepareCall(fr, &instr.Call)
200        fr.env[instr] = call(fr.ifrinstr.Pos(), fnargs)
201
202    case *ssa.ChangeInterface:
203        fr.env[instr] = fr.get(instr.X)
204
205    case *ssa.ChangeType:
206        fr.env[instr] = fr.get(instr.X// (can't fail)
207
208    case *ssa.Convert:
209        fr.env[instr] = conv(instr.Type(), instr.X.Type(), fr.get(instr.X))
210
211    case *ssa.SliceToArrayPointer:
212        fr.env[instr] = sliceToArrayPointer(instr.Type(), instr.X.Type(), fr.get(instr.X))
213
214    case *ssa.MakeInterface:
215        fr.env[instr] = iface{tinstr.X.Type(), vfr.get(instr.X)}
216
217    case *ssa.Extract:
218        fr.env[instr] = fr.get(instr.Tuple).(tuple)[instr.Index]
219
220    case *ssa.Slice:
221        fr.env[instr] = slice(fr.get(instr.X), fr.get(instr.Low), fr.get(instr.High), fr.get(instr.Max))
222
223    case *ssa.Return:
224        switch len(instr.Results) {
225        case 0:
226        case 1:
227            fr.result = fr.get(instr.Results[0])
228        default:
229            var res []value
230            for _r := range instr.Results {
231                res = append(resfr.get(r))
232            }
233            fr.result = tuple(res)
234        }
235        fr.block = nil
236        return kReturn
237
238    case *ssa.RunDefers:
239        fr.runDefers()
240
241    case *ssa.Panic:
242        panic(targetPanic{fr.get(instr.X)})
243
244    case *ssa.Send:
245        fr.get(instr.Chan).(chan value) <- fr.get(instr.X)
246
247    case *ssa.Store:
248        store(deref(instr.Addr.Type()), fr.get(instr.Addr).(*value), fr.get(instr.Val))
249
250    case *ssa.If:
251        succ := 1
252        if fr.get(instr.Cond).(bool) {
253            succ = 0
254        }
255        fr.prevBlockfr.block = fr.blockfr.block.Succs[succ]
256        return kJump
257
258    case *ssa.Jump:
259        fr.prevBlockfr.block = fr.blockfr.block.Succs[0]
260        return kJump
261
262    case *ssa.Defer:
263        fnargs := prepareCall(fr, &instr.Call)
264        fr.defers = &deferred{
265            fn:    fn,
266            args:  args,
267            instrinstr,
268            tail:  fr.defers,
269        }
270
271    case *ssa.Go:
272        fnargs := prepareCall(fr, &instr.Call)
273        atomic.AddInt32(&fr.i.goroutines1)
274        go func() {
275            call(fr.inilinstr.Pos(), fnargs)
276            atomic.AddInt32(&fr.i.goroutines, -1)
277        }()
278
279    case *ssa.MakeChan:
280        fr.env[instr] = make(chan valueasInt64(fr.get(instr.Size)))
281
282    case *ssa.Alloc:
283        var addr *value
284        if instr.Heap {
285            // new
286            addr = new(value)
287            fr.env[instr] = addr
288        } else {
289            // local
290            addr = fr.env[instr].(*value)
291        }
292        *addr = zero(deref(instr.Type()))
293
294    case *ssa.MakeSlice:
295        slice := make([]valueasInt64(fr.get(instr.Cap)))
296        tElt := instr.Type().Underlying().(*types.Slice).Elem()
297        for i := range slice {
298            slice[i] = zero(tElt)
299        }
300        fr.env[instr] = slice[:asInt64(fr.get(instr.Len))]
301
302    case *ssa.MakeMap:
303        var reserve int64
304        if instr.Reserve != nil {
305            reserve = asInt64(fr.get(instr.Reserve))
306        }
307        if !fitsInt(reservefr.i.sizes) {
308            panic(fmt.Sprintf("ssa.MakeMap.Reserve value %d does not fit in int"reserve))
309        }
310        fr.env[instr] = makeMap(instr.Type().Underlying().(*types.Map).Key(), reserve)
311
312    case *ssa.Range:
313        fr.env[instr] = rangeIter(fr.get(instr.X), instr.X.Type())
314
315    case *ssa.Next:
316        fr.env[instr] = fr.get(instr.Iter).(iter).next()
317
318    case *ssa.FieldAddr:
319        fr.env[instr] = &(*fr.get(instr.X).(*value)).(structure)[instr.Field]
320
321    case *ssa.Field:
322        fr.env[instr] = fr.get(instr.X).(structure)[instr.Field]
323
324    case *ssa.IndexAddr:
325        x := fr.get(instr.X)
326        idx := fr.get(instr.Index)
327        switch x := x.(type) {
328        case []value:
329            fr.env[instr] = &x[asInt64(idx)]
330        case *value// *array
331            fr.env[instr] = &(*x).(array)[asInt64(idx)]
332        default:
333            panic(fmt.Sprintf("unexpected x type in IndexAddr: %T"x))
334        }
335
336    case *ssa.Index:
337        x := fr.get(instr.X)
338        idx := fr.get(instr.Index)
339
340        switch x := x.(type) {
341        case array:
342            fr.env[instr] = x[asInt64(idx)]
343        case string:
344            fr.env[instr] = x[asInt64(idx)]
345        default:
346            panic(fmt.Sprintf("unexpected x type in Index: %T"x))
347        }
348
349    case *ssa.Lookup:
350        fr.env[instr] = lookup(instrfr.get(instr.X), fr.get(instr.Index))
351
352    case *ssa.MapUpdate:
353        m := fr.get(instr.Map)
354        key := fr.get(instr.Key)
355        v := fr.get(instr.Value)
356        switch m := m.(type) {
357        case map[value]value:
358            m[key] = v
359        case *hashmap:
360            m.insert(key.(hashable), v)
361        default:
362            panic(fmt.Sprintf("illegal map type: %T"m))
363        }
364
365    case *ssa.TypeAssert:
366        fr.env[instr] = typeAssert(fr.iinstrfr.get(instr.X).(iface))
367
368    case *ssa.MakeClosure:
369        var bindings []value
370        for _binding := range instr.Bindings {
371            bindings = append(bindingsfr.get(binding))
372        }
373        fr.env[instr] = &closure{instr.Fn.(*ssa.Function), bindings}
374
375    case *ssa.Phi:
376        for ipred := range instr.Block().Preds {
377            if fr.prevBlock == pred {
378                fr.env[instr] = fr.get(instr.Edges[i])
379                break
380            }
381        }
382
383    case *ssa.Select:
384        var cases []reflect.SelectCase
385        if !instr.Blocking {
386            cases = append(casesreflect.SelectCase{
387                Dirreflect.SelectDefault,
388            })
389        }
390        for _state := range instr.States {
391            var dir reflect.SelectDir
392            if state.Dir == types.RecvOnly {
393                dir = reflect.SelectRecv
394            } else {
395                dir = reflect.SelectSend
396            }
397            var send reflect.Value
398            if state.Send != nil {
399                send = reflect.ValueOf(fr.get(state.Send))
400            }
401            cases = append(casesreflect.SelectCase{
402                Dir:  dir,
403                Chanreflect.ValueOf(fr.get(state.Chan)),
404                Sendsend,
405            })
406        }
407        chosenrecvrecvOk := reflect.Select(cases)
408        if !instr.Blocking {
409            chosen-- // default case should have index -1.
410        }
411        r := tuple{chosenrecvOk}
412        for ist := range instr.States {
413            if st.Dir == types.RecvOnly {
414                var v value
415                if i == chosen && recvOk {
416                    // No need to copy since send makes an unaliased copy.
417                    v = recv.Interface().(value)
418                } else {
419                    v = zero(st.Chan.Type().Underlying().(*types.Chan).Elem())
420                }
421                r = append(rv)
422            }
423        }
424        fr.env[instr] = r
425
426    default:
427        panic(fmt.Sprintf("unexpected instruction: %T"instr))
428    }
429
430    // if val, ok := instr.(ssa.Value); ok {
431    //     fmt.Println(toString(fr.env[val])) // debugging
432    // }
433
434    return kNext
435}
436
437// prepareCall determines the function value and argument values for a
438// function call in a Call, Go or Defer instruction, performing
439// interface method lookup if needed.
440func prepareCall(fr *framecall *ssa.CallCommon) (fn valueargs []value) {
441    v := fr.get(call.Value)
442    if call.Method == nil {
443        // Function call.
444        fn = v
445    } else {
446        // Interface method invocation.
447        recv := v.(iface)
448        if recv.t == nil {
449            panic("method invoked on nil interface")
450        }
451        if f := lookupMethod(fr.irecv.tcall.Method); f == nil {
452            // Unreachable in well-typed programs.
453            panic(fmt.Sprintf("method set for dynamic type %v does not contain %s"recv.tcall.Method))
454        } else {
455            fn = f
456        }
457        args = append(argsrecv.v)
458    }
459    for _arg := range call.Args {
460        args = append(argsfr.get(arg))
461    }
462    return
463}
464
465// call interprets a call to a function (function, builtin or closure)
466// fn with arguments args, returning its result.
467// callpos is the position of the callsite.
468func call(i *interpretercaller *framecallpos token.Posfn valueargs []valuevalue {
469    switch fn := fn.(type) {
470    case *ssa.Function:
471        if fn == nil {
472            panic("call of nil function"// nil of func type
473        }
474        return callSSA(icallercallposfnargsnil)
475    case *closure:
476        return callSSA(icallercallposfn.Fnargsfn.Env)
477    case *ssa.Builtin:
478        return callBuiltin(callercallposfnargs)
479    }
480    panic(fmt.Sprintf("cannot call %T"fn))
481}
482
483func loc(fset *token.FileSetpos token.Posstring {
484    if pos == token.NoPos {
485        return ""
486    }
487    return " at " + fset.Position(pos).String()
488}
489
490// callSSA interprets a call to function fn with arguments args,
491// and lexical environment env, returning its result.
492// callpos is the position of the callsite.
493func callSSA(i *interpretercaller *framecallpos token.Posfn *ssa.Functionargs []valueenv []valuevalue {
494    if i.mode&EnableTracing != 0 {
495        fset := fn.Prog.Fset
496        // TODO(adonovan): fix: loc() lies for external functions.
497        fmt.Fprintf(os.Stderr"Entering %s%s.\n"fnloc(fsetfn.Pos()))
498        suffix := ""
499        if caller != nil {
500            suffix = ", resuming " + caller.fn.String() + loc(fsetcallpos)
501        }
502        defer fmt.Fprintf(os.Stderr"Leaving %s%s.\n"fnsuffix)
503    }
504    fr := &frame{
505        i:      i,
506        callercaller// for panic/recover
507        fn:     fn,
508    }
509    if fn.Parent() == nil {
510        name := fn.String()
511        if ext := externals[name]; ext != nil {
512            if i.mode&EnableTracing != 0 {
513                fmt.Fprintln(os.Stderr"\t(external)")
514            }
515            return ext(frargs)
516        }
517        if fn.Blocks == nil {
518            panic("no code for function: " + name)
519        }
520    }
521
522    // generic function body?
523    if fn.TypeParams().Len() > 0 && len(fn.TypeArgs()) == 0 {
524        panic("interp requires ssa.BuilderMode to include InstantiateGenerics to execute generics")
525    }
526
527    fr.env = make(map[ssa.Value]value)
528    fr.block = fn.Blocks[0]
529    fr.locals = make([]valuelen(fn.Locals))
530    for il := range fn.Locals {
531        fr.locals[i] = zero(deref(l.Type()))
532        fr.env[l] = &fr.locals[i]
533    }
534    for ip := range fn.Params {
535        fr.env[p] = args[i]
536    }
537    for ifv := range fn.FreeVars {
538        fr.env[fv] = env[i]
539    }
540    for fr.block != nil {
541        runFrame(fr)
542    }
543    // Destroy the locals to avoid accidental use after return.
544    for i := range fn.Locals {
545        fr.locals[i] = bad{}
546    }
547    return fr.result
548}
549
550// runFrame executes SSA instructions starting at fr.block and
551// continuing until a return, a panic, or a recovered panic.
552//
553// After a panic, runFrame panics.
554//
555// After a normal return, fr.result contains the result of the call
556// and fr.block is nil.
557//
558// A recovered panic in a function without named return parameters
559// (NRPs) becomes a normal return of the zero value of the function's
560// result type.
561//
562// After a recovered panic in a function with NRPs, fr.result is
563// undefined and fr.block contains the block at which to resume
564// control.
565func runFrame(fr *frame) {
566    defer func() {
567        if fr.block == nil {
568            return // normal return
569        }
570        if fr.i.mode&DisableRecover != 0 {
571            return // let interpreter crash
572        }
573        fr.panicking = true
574        fr.panic = recover()
575        if fr.i.mode&EnableTracing != 0 {
576            fmt.Fprintf(os.Stderr"Panicking: %T %v.\n"fr.panicfr.panic)
577        }
578        fr.runDefers()
579        fr.block = fr.fn.Recover
580    }()
581
582    for {
583        if fr.i.mode&EnableTracing != 0 {
584            fmt.Fprintf(os.Stderr".%s:\n"fr.block)
585        }
586    block:
587        for _instr := range fr.block.Instrs {
588            if fr.i.mode&EnableTracing != 0 {
589                if vok := instr.(ssa.Value); ok {
590                    fmt.Fprintln(os.Stderr"\t"v.Name(), "="instr)
591                } else {
592                    fmt.Fprintln(os.Stderr"\t"instr)
593                }
594            }
595            switch visitInstr(frinstr) {
596            case kReturn:
597                return
598            case kNext:
599                // no-op
600            case kJump:
601                break block
602            }
603        }
604    }
605}
606
607// doRecover implements the recover() built-in.
608func doRecover(caller *framevalue {
609    // recover() must be exactly one level beneath the deferred
610    // function (two levels beneath the panicking function) to
611    // have any effect.  Thus we ignore both "defer recover()" and
612    // "defer f() -> g() -> recover()".
613    if caller.i.mode&DisableRecover == 0 &&
614        caller != nil && !caller.panicking &&
615        caller.caller != nil && caller.caller.panicking {
616        caller.caller.panicking = false
617        p := caller.caller.panic
618        caller.caller.panic = nil
619
620        // TODO(adonovan): support runtime.Goexit.
621        switch p := p.(type) {
622        case targetPanic:
623            // The target program explicitly called panic().
624            return p.v
625        case runtime.Error:
626            // The interpreter encountered a runtime error.
627            return iface{caller.i.runtimeErrorStringp.Error()}
628        case string:
629            // The interpreter explicitly called panic().
630            return iface{caller.i.runtimeErrorStringp}
631        default:
632            panic(fmt.Sprintf("unexpected panic type %T in target call to recover()"p))
633        }
634    }
635    return iface{}
636}
637
638// setGlobal sets the value of a system-initialized global variable.
639func setGlobal(i *interpreterpkg *ssa.Packagename stringv value) {
640    if gok := i.globals[pkg.Var(name)]; ok {
641        *g = v
642        return
643    }
644    panic("no global variable: " + pkg.Pkg.Path() + "." + name)
645}
646
647// Interpret interprets the Go program whose main package is mainpkg.
648// mode specifies various interpreter options.  filename and args are
649// the initial values of os.Args for the target program.  sizes is the
650// effective type-sizing function for this program.
651//
652// Interpret returns the exit code of the program: 2 for panic (like
653// gc does), or the argument to os.Exit for normal termination.
654//
655// The SSA program must include the "runtime" package.
656//
657// Type parameterized functions must have been built with
658// InstantiateGenerics in the ssa.BuilderMode to be interpreted.
659func Interpret(mainpkg *ssa.Packagemode Modesizes types.Sizesfilename stringargs []string) (exitCode int) {
660    i := &interpreter{
661        prog:       mainpkg.Prog,
662        globals:    make(map[*ssa.Global]*value),
663        mode:       mode,
664        sizes:      sizes,
665        goroutines1,
666    }
667    runtimePkg := i.prog.ImportedPackage("runtime")
668    if runtimePkg == nil {
669        panic("ssa.Program doesn't include runtime package")
670    }
671    i.runtimeErrorString = runtimePkg.Type("errorString").Object().Type()
672
673    initReflect(i)
674
675    i.osArgs = append(i.osArgsfilename)
676    for _arg := range args {
677        i.osArgs = append(i.osArgsarg)
678    }
679
680    for _pkg := range i.prog.AllPackages() {
681        // Initialize global storage.
682        for _m := range pkg.Members {
683            switch v := m.(type) {
684            case *ssa.Global:
685                cell := zero(deref(v.Type()))
686                i.globals[v] = &cell
687            }
688        }
689    }
690
691    // Top-level error handler.
692    exitCode = 2
693    defer func() {
694        if exitCode != 2 || i.mode&DisableRecover != 0 {
695            return
696        }
697        switch p := recover().(type) {
698        case exitPanic:
699            exitCode = int(p)
700            return
701        case targetPanic:
702            fmt.Fprintln(os.Stderr"panic:"toString(p.v))
703        case runtime.Error:
704            fmt.Fprintln(os.Stderr"panic:"p.Error())
705        case string:
706            fmt.Fprintln(os.Stderr"panic:"p)
707        default:
708            fmt.Fprintf(os.Stderr"panic: unexpected type: %T: %v\n"pp)
709        }
710
711        // TODO(adonovan): dump panicking interpreter goroutine?
712        // buf := make([]byte, 0x10000)
713        // runtime.Stack(buf, false)
714        // fmt.Fprintln(os.Stderr, string(buf))
715        // (Or dump panicking target goroutine?)
716    }()
717
718    // Run!
719    call(iniltoken.NoPosmainpkg.Func("init"), nil)
720    if mainFn := mainpkg.Func("main"); mainFn != nil {
721        call(iniltoken.NoPosmainFnnil)
722        exitCode = 0
723    } else {
724        fmt.Fprintln(os.Stderr"No main function.")
725        exitCode = 1
726    }
727    return
728}
729
730// deref returns a pointer's element type; otherwise it returns typ.
731// TODO(adonovan): Import from ssa?
732func deref(typ types.Typetypes.Type {
733    if pok := typ.Underlying().(*types.Pointer); ok {
734        return p.Elem()
735    }
736    return typ
737}
738
MembersX
frame.runDefers.d
lookupMethod.meth
visitInstr.BlockStmt.x
prepareCall.RangeStmt_12572.arg
callSSA.fn
setGlobal
fmt
kNext
call.args
Interpret.RangeStmt_18933.arg
runFrame.BlockStmt.RangeStmt_16128.instr
interpreter.osArgs
visitInstr.BlockStmt.slice
prepareCall.args
callSSA.BlockStmt.fset
frame.locals
visitInstr.BlockStmt.RangeStmt_10747.BlockStmt.dir
frame.runDefer.ok
frame.runDefers.fr
lookupMethod
lookupMethod.typ
visitInstr.BlockStmt.addr
visitInstr.BlockStmt.r
interpreter.rtypeMethods
deferred.fn
callSSA.args
runFrame
runFrame.fr
Interpret.sizes
Interpret.RangeStmt_19000.BlockStmt.RangeStmt_19077.BlockStmt.BlockStmt.cell
prepareCall.BlockStmt.f
loc.pos
frame.result
visitInstr.BlockStmt.RangeStmt_10448.i
setGlobal.v
Interpret.mainpkg
deref.typ
Mode
deferred.instr
Interpret.i
prepareCall
call.caller
DisableRecover
lookupMethod.i
visitInstr.BlockStmt.reserve
prepareCall.call
loc
doRecover
ssa
continuation
Interpret.args
callSSA
callSSA.RangeStmt_14699.l
visitInstr.BlockStmt.recvOk
call.callpos
callSSA.RangeStmt_14699.i
callSSA.RangeStmt_14800.i
callSSA.RangeStmt_14800.p
frame.panic
visitInstr.BlockStmt.idx
visitInstr.BlockStmt.fn
prepareCall.fn
frame
frame.caller
frame.runDefers
call.i
call.fn
callSSA.RangeStmt_14856.i
callSSA.RangeStmt_14856.fv
callSSA.RangeStmt_15017.i
atomic
frame.runDefer.fr
callSSA.env
setGlobal.i
frame.prevBlock
frame.panicking
visitInstr.fr
visitInstr.BlockStmt.cases
prepareCall.fr
callSSA.caller
doRecover.BlockStmt.p
token
interpreter.globals
interpreter.runtimeErrorString
frame.defers
frame.get
frame.runDefer
Interpret.filename
interpreter.prog
deferred.tail
callSSA.fr
Interpret.RangeStmt_19000.BlockStmt.RangeStmt_19077.m
visitInstr.BlockStmt.BlockStmt.res
callSSA.BlockStmt.suffix
deref
frame.fn
frame.env
frame.get.key
visitInstr.BlockStmt.args
Interpret.runtimePkg
interpreter.mode
deferred.args
visitInstr.instr
visitInstr.BlockStmt.v
reflect
frame.i
loc.fset
Interpret.exitCode
frame.block
visitInstr.BlockStmt.recv
visitInstr.BlockStmt.succ
visitInstr.BlockStmt.m
visitInstr.BlockStmt.RangeStmt_11317.BlockStmt.BlockStmt.v
callSSA.BlockStmt.name
interpreter.errorMethods
frame.runDefer.d
visitInstr.BlockStmt.tElt
Interpret.mainFn
interpreter
frame.get.fr
prepareCall.v
interpreter.reflectPackage
visitInstr.BlockStmt.RangeStmt_10273.binding
visitInstr.BlockStmt.RangeStmt_10747.BlockStmt.send
visitInstr.BlockStmt.RangeStmt_11317.st
callSSA.callpos
Interpret.RangeStmt_19000.pkg
visitInstr
visitInstr.BlockStmt.RangeStmt_10747.state
Interpret
methodSet
setGlobal.name
visitInstr.BlockStmt.key
visitInstr.BlockStmt.bindings
deferred
visitInstr.BlockStmt.BlockStmt.RangeStmt_7013.r
call
visitInstr.BlockStmt.RangeStmt_10448.pred
visitInstr.BlockStmt.chosen
setGlobal.pkg
types
visitInstr.BlockStmt.RangeStmt_8444.i
interpreter.goroutines
visitInstr.BlockStmt.RangeStmt_11317.i
doRecover.caller
Interpret.mode
interpreter.sizes
callSSA.i
Members
X