Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / 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.
45 package interp // import "golang.org/x/tools/go/ssa/interp"
46
47 import (
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
59 type continuation int
60
61 const (
62         kNext continuation = iota
63         kReturn
64         kJump
65 )
66
67 // Mode is a bitmask of options affecting the interpreter.
68 type Mode uint
69
70 const (
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
75 type methodSet map[string]*ssa.Function
76
77 // State shared between all interpreted goroutines.
78 type interpreter struct {
79         osArgs             []value              // the value of os.Args
80         prog               *ssa.Program         // the SSA program
81         globals            map[ssa.Value]*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
91 type deferred struct {
92         fn    value
93         args  []value
94         instr *ssa.Defer
95         tail  *deferred
96 }
97
98 type frame struct {
99         i                *interpreter
100         caller           *frame
101         fn               *ssa.Function
102         block, prevBlock *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
111 func (fr *frame) get(key ssa.Value) value {
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 r, ok := fr.i.globals[key]; ok {
123                         return r
124                 }
125         }
126         if r, ok := fr.env[key]; ok {
127                 return r
128         }
129         panic(fmt.Sprintf("get: no value for %T: %v", key, key.Name()))
130 }
131
132 // runDefer runs a deferred call d.
133 // It always returns normally, but may set or clear fr.panic.
134 //
135 func (fr *frame) runDefer(d *deferred) {
136         if fr.i.mode&EnableTracing != 0 {
137                 fmt.Fprintf(os.Stderr, "%s: invoking deferred function call\n",
138                         fr.i.prog.Fset.Position(d.instr.Pos()))
139         }
140         var ok bool
141         defer func() {
142                 if !ok {
143                         // Deferred call created a new state of panic.
144                         fr.panicking = true
145                         fr.panic = recover()
146                 }
147         }()
148         call(fr.i, fr, d.instr.Pos(), d.fn, d.args)
149         ok = true
150 }
151
152 // runDefers executes fr's deferred function calls in LIFO order.
153 //
154 // On entry, fr.panicking indicates a state of panic; if
155 // true, fr.panic contains the panic value.
156 //
157 // On completion, if a deferred call started a panic, or if no
158 // deferred call recovered from a previous state of panic, then
159 // runDefers itself panics after the last deferred call has run.
160 //
161 // If there was no initial state of panic, or it was recovered from,
162 // runDefers returns normally.
163 //
164 func (fr *frame) runDefers() {
165         for d := fr.defers; d != nil; d = d.tail {
166                 fr.runDefer(d)
167         }
168         fr.defers = nil
169         if fr.panicking {
170                 panic(fr.panic) // new panic, or still panicking
171         }
172 }
173
174 // lookupMethod returns the method set for type typ, which may be one
175 // of the interpreter's fake types.
176 func lookupMethod(i *interpreter, typ types.Type, meth *types.Func) *ssa.Function {
177         switch typ {
178         case rtypeType:
179                 return i.rtypeMethods[meth.Id()]
180         case errorType:
181                 return i.errorMethods[meth.Id()]
182         }
183         return i.prog.LookupMethod(typ, meth.Pkg(), meth.Name())
184 }
185
186 // visitInstr interprets a single ssa.Instruction within the activation
187 // record frame.  It returns a continuation value indicating where to
188 // read the next instruction from.
189 func visitInstr(fr *frame, instr ssa.Instruction) continuation {
190         switch instr := instr.(type) {
191         case *ssa.DebugRef:
192                 // no-op
193
194         case *ssa.UnOp:
195                 fr.env[instr] = unop(instr, fr.get(instr.X))
196
197         case *ssa.BinOp:
198                 fr.env[instr] = binop(instr.Op, instr.X.Type(), fr.get(instr.X), fr.get(instr.Y))
199
200         case *ssa.Call:
201                 fn, args := prepareCall(fr, &instr.Call)
202                 fr.env[instr] = call(fr.i, fr, instr.Pos(), fn, args)
203
204         case *ssa.ChangeInterface:
205                 fr.env[instr] = fr.get(instr.X)
206
207         case *ssa.ChangeType:
208                 fr.env[instr] = fr.get(instr.X) // (can't fail)
209
210         case *ssa.Convert:
211                 fr.env[instr] = conv(instr.Type(), instr.X.Type(), fr.get(instr.X))
212
213         case *ssa.MakeInterface:
214                 fr.env[instr] = iface{t: instr.X.Type(), v: fr.get(instr.X)}
215
216         case *ssa.Extract:
217                 fr.env[instr] = fr.get(instr.Tuple).(tuple)[instr.Index]
218
219         case *ssa.Slice:
220                 fr.env[instr] = slice(fr.get(instr.X), fr.get(instr.Low), fr.get(instr.High), fr.get(instr.Max))
221
222         case *ssa.Return:
223                 switch len(instr.Results) {
224                 case 0:
225                 case 1:
226                         fr.result = fr.get(instr.Results[0])
227                 default:
228                         var res []value
229                         for _, r := range instr.Results {
230                                 res = append(res, fr.get(r))
231                         }
232                         fr.result = tuple(res)
233                 }
234                 fr.block = nil
235                 return kReturn
236
237         case *ssa.RunDefers:
238                 fr.runDefers()
239
240         case *ssa.Panic:
241                 panic(targetPanic{fr.get(instr.X)})
242
243         case *ssa.Send:
244                 fr.get(instr.Chan).(chan value) <- fr.get(instr.X)
245
246         case *ssa.Store:
247                 store(deref(instr.Addr.Type()), fr.get(instr.Addr).(*value), fr.get(instr.Val))
248
249         case *ssa.If:
250                 succ := 1
251                 if fr.get(instr.Cond).(bool) {
252                         succ = 0
253                 }
254                 fr.prevBlock, fr.block = fr.block, fr.block.Succs[succ]
255                 return kJump
256
257         case *ssa.Jump:
258                 fr.prevBlock, fr.block = fr.block, fr.block.Succs[0]
259                 return kJump
260
261         case *ssa.Defer:
262                 fn, args := prepareCall(fr, &instr.Call)
263                 fr.defers = &deferred{
264                         fn:    fn,
265                         args:  args,
266                         instr: instr,
267                         tail:  fr.defers,
268                 }
269
270         case *ssa.Go:
271                 fn, args := prepareCall(fr, &instr.Call)
272                 atomic.AddInt32(&fr.i.goroutines, 1)
273                 go func() {
274                         call(fr.i, nil, instr.Pos(), fn, args)
275                         atomic.AddInt32(&fr.i.goroutines, -1)
276                 }()
277
278         case *ssa.MakeChan:
279                 fr.env[instr] = make(chan value, asInt(fr.get(instr.Size)))
280
281         case *ssa.Alloc:
282                 var addr *value
283                 if instr.Heap {
284                         // new
285                         addr = new(value)
286                         fr.env[instr] = addr
287                 } else {
288                         // local
289                         addr = fr.env[instr].(*value)
290                 }
291                 *addr = zero(deref(instr.Type()))
292
293         case *ssa.MakeSlice:
294                 slice := make([]value, asInt(fr.get(instr.Cap)))
295                 tElt := instr.Type().Underlying().(*types.Slice).Elem()
296                 for i := range slice {
297                         slice[i] = zero(tElt)
298                 }
299                 fr.env[instr] = slice[:asInt(fr.get(instr.Len))]
300
301         case *ssa.MakeMap:
302                 reserve := 0
303                 if instr.Reserve != nil {
304                         reserve = asInt(fr.get(instr.Reserve))
305                 }
306                 fr.env[instr] = makeMap(instr.Type().Underlying().(*types.Map).Key(), reserve)
307
308         case *ssa.Range:
309                 fr.env[instr] = rangeIter(fr.get(instr.X), instr.X.Type())
310
311         case *ssa.Next:
312                 fr.env[instr] = fr.get(instr.Iter).(iter).next()
313
314         case *ssa.FieldAddr:
315                 fr.env[instr] = &(*fr.get(instr.X).(*value)).(structure)[instr.Field]
316
317         case *ssa.Field:
318                 fr.env[instr] = fr.get(instr.X).(structure)[instr.Field]
319
320         case *ssa.IndexAddr:
321                 x := fr.get(instr.X)
322                 idx := fr.get(instr.Index)
323                 switch x := x.(type) {
324                 case []value:
325                         fr.env[instr] = &x[asInt(idx)]
326                 case *value: // *array
327                         fr.env[instr] = &(*x).(array)[asInt(idx)]
328                 default:
329                         panic(fmt.Sprintf("unexpected x type in IndexAddr: %T", x))
330                 }
331
332         case *ssa.Index:
333                 fr.env[instr] = fr.get(instr.X).(array)[asInt(fr.get(instr.Index))]
334
335         case *ssa.Lookup:
336                 fr.env[instr] = lookup(instr, fr.get(instr.X), fr.get(instr.Index))
337
338         case *ssa.MapUpdate:
339                 m := fr.get(instr.Map)
340                 key := fr.get(instr.Key)
341                 v := fr.get(instr.Value)
342                 switch m := m.(type) {
343                 case map[value]value:
344                         m[key] = v
345                 case *hashmap:
346                         m.insert(key.(hashable), v)
347                 default:
348                         panic(fmt.Sprintf("illegal map type: %T", m))
349                 }
350
351         case *ssa.TypeAssert:
352                 fr.env[instr] = typeAssert(fr.i, instr, fr.get(instr.X).(iface))
353
354         case *ssa.MakeClosure:
355                 var bindings []value
356                 for _, binding := range instr.Bindings {
357                         bindings = append(bindings, fr.get(binding))
358                 }
359                 fr.env[instr] = &closure{instr.Fn.(*ssa.Function), bindings}
360
361         case *ssa.Phi:
362                 for i, pred := range instr.Block().Preds {
363                         if fr.prevBlock == pred {
364                                 fr.env[instr] = fr.get(instr.Edges[i])
365                                 break
366                         }
367                 }
368
369         case *ssa.Select:
370                 var cases []reflect.SelectCase
371                 if !instr.Blocking {
372                         cases = append(cases, reflect.SelectCase{
373                                 Dir: reflect.SelectDefault,
374                         })
375                 }
376                 for _, state := range instr.States {
377                         var dir reflect.SelectDir
378                         if state.Dir == types.RecvOnly {
379                                 dir = reflect.SelectRecv
380                         } else {
381                                 dir = reflect.SelectSend
382                         }
383                         var send reflect.Value
384                         if state.Send != nil {
385                                 send = reflect.ValueOf(fr.get(state.Send))
386                         }
387                         cases = append(cases, reflect.SelectCase{
388                                 Dir:  dir,
389                                 Chan: reflect.ValueOf(fr.get(state.Chan)),
390                                 Send: send,
391                         })
392                 }
393                 chosen, recv, recvOk := reflect.Select(cases)
394                 if !instr.Blocking {
395                         chosen-- // default case should have index -1.
396                 }
397                 r := tuple{chosen, recvOk}
398                 for i, st := range instr.States {
399                         if st.Dir == types.RecvOnly {
400                                 var v value
401                                 if i == chosen && recvOk {
402                                         // No need to copy since send makes an unaliased copy.
403                                         v = recv.Interface().(value)
404                                 } else {
405                                         v = zero(st.Chan.Type().Underlying().(*types.Chan).Elem())
406                                 }
407                                 r = append(r, v)
408                         }
409                 }
410                 fr.env[instr] = r
411
412         default:
413                 panic(fmt.Sprintf("unexpected instruction: %T", instr))
414         }
415
416         // if val, ok := instr.(ssa.Value); ok {
417         //      fmt.Println(toString(fr.env[val])) // debugging
418         // }
419
420         return kNext
421 }
422
423 // prepareCall determines the function value and argument values for a
424 // function call in a Call, Go or Defer instruction, performing
425 // interface method lookup if needed.
426 //
427 func prepareCall(fr *frame, call *ssa.CallCommon) (fn value, args []value) {
428         v := fr.get(call.Value)
429         if call.Method == nil {
430                 // Function call.
431                 fn = v
432         } else {
433                 // Interface method invocation.
434                 recv := v.(iface)
435                 if recv.t == nil {
436                         panic("method invoked on nil interface")
437                 }
438                 if f := lookupMethod(fr.i, recv.t, call.Method); f == nil {
439                         // Unreachable in well-typed programs.
440                         panic(fmt.Sprintf("method set for dynamic type %v does not contain %s", recv.t, call.Method))
441                 } else {
442                         fn = f
443                 }
444                 args = append(args, recv.v)
445         }
446         for _, arg := range call.Args {
447                 args = append(args, fr.get(arg))
448         }
449         return
450 }
451
452 // call interprets a call to a function (function, builtin or closure)
453 // fn with arguments args, returning its result.
454 // callpos is the position of the callsite.
455 //
456 func call(i *interpreter, caller *frame, callpos token.Pos, fn value, args []value) value {
457         switch fn := fn.(type) {
458         case *ssa.Function:
459                 if fn == nil {
460                         panic("call of nil function") // nil of func type
461                 }
462                 return callSSA(i, caller, callpos, fn, args, nil)
463         case *closure:
464                 return callSSA(i, caller, callpos, fn.Fn, args, fn.Env)
465         case *ssa.Builtin:
466                 return callBuiltin(caller, callpos, fn, args)
467         }
468         panic(fmt.Sprintf("cannot call %T", fn))
469 }
470
471 func loc(fset *token.FileSet, pos token.Pos) string {
472         if pos == token.NoPos {
473                 return ""
474         }
475         return " at " + fset.Position(pos).String()
476 }
477
478 // callSSA interprets a call to function fn with arguments args,
479 // and lexical environment env, returning its result.
480 // callpos is the position of the callsite.
481 //
482 func callSSA(i *interpreter, caller *frame, callpos token.Pos, fn *ssa.Function, args []value, env []value) value {
483         if i.mode&EnableTracing != 0 {
484                 fset := fn.Prog.Fset
485                 // TODO(adonovan): fix: loc() lies for external functions.
486                 fmt.Fprintf(os.Stderr, "Entering %s%s.\n", fn, loc(fset, fn.Pos()))
487                 suffix := ""
488                 if caller != nil {
489                         suffix = ", resuming " + caller.fn.String() + loc(fset, callpos)
490                 }
491                 defer fmt.Fprintf(os.Stderr, "Leaving %s%s.\n", fn, suffix)
492         }
493         fr := &frame{
494                 i:      i,
495                 caller: caller, // for panic/recover
496                 fn:     fn,
497         }
498         if fn.Parent() == nil {
499                 name := fn.String()
500                 if ext := externals[name]; ext != nil {
501                         if i.mode&EnableTracing != 0 {
502                                 fmt.Fprintln(os.Stderr, "\t(external)")
503                         }
504                         return ext(fr, args)
505                 }
506                 if fn.Blocks == nil {
507                         panic("no code for function: " + name)
508                 }
509         }
510         fr.env = make(map[ssa.Value]value)
511         fr.block = fn.Blocks[0]
512         fr.locals = make([]value, len(fn.Locals))
513         for i, l := range fn.Locals {
514                 fr.locals[i] = zero(deref(l.Type()))
515                 fr.env[l] = &fr.locals[i]
516         }
517         for i, p := range fn.Params {
518                 fr.env[p] = args[i]
519         }
520         for i, fv := range fn.FreeVars {
521                 fr.env[fv] = env[i]
522         }
523         for fr.block != nil {
524                 runFrame(fr)
525         }
526         // Destroy the locals to avoid accidental use after return.
527         for i := range fn.Locals {
528                 fr.locals[i] = bad{}
529         }
530         return fr.result
531 }
532
533 // runFrame executes SSA instructions starting at fr.block and
534 // continuing until a return, a panic, or a recovered panic.
535 //
536 // After a panic, runFrame panics.
537 //
538 // After a normal return, fr.result contains the result of the call
539 // and fr.block is nil.
540 //
541 // A recovered panic in a function without named return parameters
542 // (NRPs) becomes a normal return of the zero value of the function's
543 // result type.
544 //
545 // After a recovered panic in a function with NRPs, fr.result is
546 // undefined and fr.block contains the block at which to resume
547 // control.
548 //
549 func runFrame(fr *frame) {
550         defer func() {
551                 if fr.block == nil {
552                         return // normal return
553                 }
554                 if fr.i.mode&DisableRecover != 0 {
555                         return // let interpreter crash
556                 }
557                 fr.panicking = true
558                 fr.panic = recover()
559                 if fr.i.mode&EnableTracing != 0 {
560                         fmt.Fprintf(os.Stderr, "Panicking: %T %v.\n", fr.panic, fr.panic)
561                 }
562                 fr.runDefers()
563                 fr.block = fr.fn.Recover
564         }()
565
566         for {
567                 if fr.i.mode&EnableTracing != 0 {
568                         fmt.Fprintf(os.Stderr, ".%s:\n", fr.block)
569                 }
570         block:
571                 for _, instr := range fr.block.Instrs {
572                         if fr.i.mode&EnableTracing != 0 {
573                                 if v, ok := instr.(ssa.Value); ok {
574                                         fmt.Fprintln(os.Stderr, "\t", v.Name(), "=", instr)
575                                 } else {
576                                         fmt.Fprintln(os.Stderr, "\t", instr)
577                                 }
578                         }
579                         switch visitInstr(fr, instr) {
580                         case kReturn:
581                                 return
582                         case kNext:
583                                 // no-op
584                         case kJump:
585                                 break block
586                         }
587                 }
588         }
589 }
590
591 // doRecover implements the recover() built-in.
592 func doRecover(caller *frame) value {
593         // recover() must be exactly one level beneath the deferred
594         // function (two levels beneath the panicking function) to
595         // have any effect.  Thus we ignore both "defer recover()" and
596         // "defer f() -> g() -> recover()".
597         if caller.i.mode&DisableRecover == 0 &&
598                 caller != nil && !caller.panicking &&
599                 caller.caller != nil && caller.caller.panicking {
600                 caller.caller.panicking = false
601                 p := caller.caller.panic
602                 caller.caller.panic = nil
603
604                 // TODO(adonovan): support runtime.Goexit.
605                 switch p := p.(type) {
606                 case targetPanic:
607                         // The target program explicitly called panic().
608                         return p.v
609                 case runtime.Error:
610                         // The interpreter encountered a runtime error.
611                         return iface{caller.i.runtimeErrorString, p.Error()}
612                 case string:
613                         // The interpreter explicitly called panic().
614                         return iface{caller.i.runtimeErrorString, p}
615                 default:
616                         panic(fmt.Sprintf("unexpected panic type %T in target call to recover()", p))
617                 }
618         }
619         return iface{}
620 }
621
622 // setGlobal sets the value of a system-initialized global variable.
623 func setGlobal(i *interpreter, pkg *ssa.Package, name string, v value) {
624         if g, ok := i.globals[pkg.Var(name)]; ok {
625                 *g = v
626                 return
627         }
628         panic("no global variable: " + pkg.Pkg.Path() + "." + name)
629 }
630
631 // Interpret interprets the Go program whose main package is mainpkg.
632 // mode specifies various interpreter options.  filename and args are
633 // the initial values of os.Args for the target program.  sizes is the
634 // effective type-sizing function for this program.
635 //
636 // Interpret returns the exit code of the program: 2 for panic (like
637 // gc does), or the argument to os.Exit for normal termination.
638 //
639 // The SSA program must include the "runtime" package.
640 //
641 func Interpret(mainpkg *ssa.Package, mode Mode, sizes types.Sizes, filename string, args []string) (exitCode int) {
642         i := &interpreter{
643                 prog:       mainpkg.Prog,
644                 globals:    make(map[ssa.Value]*value),
645                 mode:       mode,
646                 sizes:      sizes,
647                 goroutines: 1,
648         }
649         runtimePkg := i.prog.ImportedPackage("runtime")
650         if runtimePkg == nil {
651                 panic("ssa.Program doesn't include runtime package")
652         }
653         i.runtimeErrorString = runtimePkg.Type("errorString").Object().Type()
654
655         initReflect(i)
656
657         i.osArgs = append(i.osArgs, filename)
658         for _, arg := range args {
659                 i.osArgs = append(i.osArgs, arg)
660         }
661
662         for _, pkg := range i.prog.AllPackages() {
663                 // Initialize global storage.
664                 for _, m := range pkg.Members {
665                         switch v := m.(type) {
666                         case *ssa.Global:
667                                 cell := zero(deref(v.Type()))
668                                 i.globals[v] = &cell
669                         }
670                 }
671         }
672
673         // Top-level error handler.
674         exitCode = 2
675         defer func() {
676                 if exitCode != 2 || i.mode&DisableRecover != 0 {
677                         return
678                 }
679                 switch p := recover().(type) {
680                 case exitPanic:
681                         exitCode = int(p)
682                         return
683                 case targetPanic:
684                         fmt.Fprintln(os.Stderr, "panic:", toString(p.v))
685                 case runtime.Error:
686                         fmt.Fprintln(os.Stderr, "panic:", p.Error())
687                 case string:
688                         fmt.Fprintln(os.Stderr, "panic:", p)
689                 default:
690                         fmt.Fprintf(os.Stderr, "panic: unexpected type: %T: %v\n", p, p)
691                 }
692
693                 // TODO(adonovan): dump panicking interpreter goroutine?
694                 // buf := make([]byte, 0x10000)
695                 // runtime.Stack(buf, false)
696                 // fmt.Fprintln(os.Stderr, string(buf))
697                 // (Or dump panicking target goroutine?)
698         }()
699
700         // Run!
701         call(i, nil, token.NoPos, mainpkg.Func("init"), nil)
702         if mainFn := mainpkg.Func("main"); mainFn != nil {
703                 call(i, nil, token.NoPos, mainFn, nil)
704                 exitCode = 0
705         } else {
706                 fmt.Fprintln(os.Stderr, "No main function.")
707                 exitCode = 1
708         }
709         return
710 }
711
712 // deref returns a pointer's element type; otherwise it returns typ.
713 // TODO(adonovan): Import from ssa?
714 func deref(typ types.Type) types.Type {
715         if p, ok := typ.Underlying().(*types.Pointer); ok {
716                 return p.Elem()
717         }
718         return typ
719 }