.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.1.1 / go / ir / func.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 ir
6
7 // This file implements the Function and BasicBlock types.
8
9 import (
10         "bytes"
11         "fmt"
12         "go/ast"
13         "go/constant"
14         "go/format"
15         "go/token"
16         "go/types"
17         "io"
18         "os"
19         "strings"
20 )
21
22 // addEdge adds a control-flow graph edge from from to to.
23 func addEdge(from, to *BasicBlock) {
24         from.Succs = append(from.Succs, to)
25         to.Preds = append(to.Preds, from)
26 }
27
28 // Control returns the last instruction in the block.
29 func (b *BasicBlock) Control() Instruction {
30         if len(b.Instrs) == 0 {
31                 return nil
32         }
33         return b.Instrs[len(b.Instrs)-1]
34 }
35
36 // SigmaFor returns the sigma node for v coming from pred.
37 func (b *BasicBlock) SigmaFor(v Value, pred *BasicBlock) *Sigma {
38         for _, instr := range b.Instrs {
39                 sigma, ok := instr.(*Sigma)
40                 if !ok {
41                         // no more sigmas
42                         return nil
43                 }
44                 if sigma.From == pred && sigma.X == v {
45                         return sigma
46                 }
47         }
48         return nil
49 }
50
51 // Parent returns the function that contains block b.
52 func (b *BasicBlock) Parent() *Function { return b.parent }
53
54 // String returns a human-readable label of this block.
55 // It is not guaranteed unique within the function.
56 //
57 func (b *BasicBlock) String() string {
58         return fmt.Sprintf("%d", b.Index)
59 }
60
61 // emit appends an instruction to the current basic block.
62 // If the instruction defines a Value, it is returned.
63 //
64 func (b *BasicBlock) emit(i Instruction, source ast.Node) Value {
65         i.setSource(source)
66         i.setBlock(b)
67         b.Instrs = append(b.Instrs, i)
68         v, _ := i.(Value)
69         return v
70 }
71
72 // predIndex returns the i such that b.Preds[i] == c or panics if
73 // there is none.
74 func (b *BasicBlock) predIndex(c *BasicBlock) int {
75         for i, pred := range b.Preds {
76                 if pred == c {
77                         return i
78                 }
79         }
80         panic(fmt.Sprintf("no edge %s -> %s", c, b))
81 }
82
83 // succIndex returns the i such that b.Succs[i] == c or -1 if there is none.
84 func (b *BasicBlock) succIndex(c *BasicBlock) int {
85         for i, succ := range b.Succs {
86                 if succ == c {
87                         return i
88                 }
89         }
90         return -1
91 }
92
93 // hasPhi returns true if b.Instrs contains φ-nodes.
94 func (b *BasicBlock) hasPhi() bool {
95         _, ok := b.Instrs[0].(*Phi)
96         return ok
97 }
98
99 func (b *BasicBlock) Phis() []Instruction {
100         return b.phis()
101 }
102
103 // phis returns the prefix of b.Instrs containing all the block's φ-nodes.
104 func (b *BasicBlock) phis() []Instruction {
105         for i, instr := range b.Instrs {
106                 if _, ok := instr.(*Phi); !ok {
107                         return b.Instrs[:i]
108                 }
109         }
110         return nil // unreachable in well-formed blocks
111 }
112
113 // replacePred replaces all occurrences of p in b's predecessor list with q.
114 // Ordinarily there should be at most one.
115 //
116 func (b *BasicBlock) replacePred(p, q *BasicBlock) {
117         for i, pred := range b.Preds {
118                 if pred == p {
119                         b.Preds[i] = q
120                 }
121         }
122 }
123
124 // replaceSucc replaces all occurrences of p in b's successor list with q.
125 // Ordinarily there should be at most one.
126 //
127 func (b *BasicBlock) replaceSucc(p, q *BasicBlock) {
128         for i, succ := range b.Succs {
129                 if succ == p {
130                         b.Succs[i] = q
131                 }
132         }
133 }
134
135 // removePred removes all occurrences of p in b's
136 // predecessor list and φ-nodes.
137 // Ordinarily there should be at most one.
138 //
139 func (b *BasicBlock) removePred(p *BasicBlock) {
140         phis := b.phis()
141
142         // We must preserve edge order for φ-nodes.
143         j := 0
144         for i, pred := range b.Preds {
145                 if pred != p {
146                         b.Preds[j] = b.Preds[i]
147                         // Strike out φ-edge too.
148                         for _, instr := range phis {
149                                 phi := instr.(*Phi)
150                                 phi.Edges[j] = phi.Edges[i]
151                         }
152                         j++
153                 }
154         }
155         // Nil out b.Preds[j:] and φ-edges[j:] to aid GC.
156         for i := j; i < len(b.Preds); i++ {
157                 b.Preds[i] = nil
158                 for _, instr := range phis {
159                         instr.(*Phi).Edges[i] = nil
160                 }
161         }
162         b.Preds = b.Preds[:j]
163         for _, instr := range phis {
164                 phi := instr.(*Phi)
165                 phi.Edges = phi.Edges[:j]
166         }
167 }
168
169 // Destinations associated with unlabelled for/switch/select stmts.
170 // We push/pop one of these as we enter/leave each construct and for
171 // each BranchStmt we scan for the innermost target of the right type.
172 //
173 type targets struct {
174         tail         *targets // rest of stack
175         _break       *BasicBlock
176         _continue    *BasicBlock
177         _fallthrough *BasicBlock
178 }
179
180 // Destinations associated with a labelled block.
181 // We populate these as labels are encountered in forward gotos or
182 // labelled statements.
183 //
184 type lblock struct {
185         _goto     *BasicBlock
186         _break    *BasicBlock
187         _continue *BasicBlock
188 }
189
190 // labelledBlock returns the branch target associated with the
191 // specified label, creating it if needed.
192 //
193 func (f *Function) labelledBlock(label *ast.Ident) *lblock {
194         lb := f.lblocks[label.Obj]
195         if lb == nil {
196                 lb = &lblock{_goto: f.newBasicBlock(label.Name)}
197                 if f.lblocks == nil {
198                         f.lblocks = make(map[*ast.Object]*lblock)
199                 }
200                 f.lblocks[label.Obj] = lb
201         }
202         return lb
203 }
204
205 // addParam adds a (non-escaping) parameter to f.Params of the
206 // specified name, type and source position.
207 //
208 func (f *Function) addParam(name string, typ types.Type, source ast.Node) *Parameter {
209         var b *BasicBlock
210         if len(f.Blocks) > 0 {
211                 b = f.Blocks[0]
212         }
213         v := &Parameter{
214                 name: name,
215         }
216         v.setBlock(b)
217         v.setType(typ)
218         v.setSource(source)
219         f.Params = append(f.Params, v)
220         if b != nil {
221                 // There may be no blocks if this function has no body. We
222                 // still create params, but aren't interested in the
223                 // instruction.
224                 f.Blocks[0].Instrs = append(f.Blocks[0].Instrs, v)
225         }
226         return v
227 }
228
229 func (f *Function) addParamObj(obj types.Object, source ast.Node) *Parameter {
230         name := obj.Name()
231         if name == "" {
232                 name = fmt.Sprintf("arg%d", len(f.Params))
233         }
234         param := f.addParam(name, obj.Type(), source)
235         param.object = obj
236         return param
237 }
238
239 // addSpilledParam declares a parameter that is pre-spilled to the
240 // stack; the function body will load/store the spilled location.
241 // Subsequent lifting will eliminate spills where possible.
242 //
243 func (f *Function) addSpilledParam(obj types.Object, source ast.Node) {
244         param := f.addParamObj(obj, source)
245         spill := &Alloc{}
246         spill.setType(types.NewPointer(obj.Type()))
247         spill.source = source
248         f.objects[obj] = spill
249         f.Locals = append(f.Locals, spill)
250         f.emit(spill, source)
251         emitStore(f, spill, param, source)
252         // f.emit(&Store{Addr: spill, Val: param})
253 }
254
255 // startBody initializes the function prior to generating IR code for its body.
256 // Precondition: f.Type() already set.
257 //
258 func (f *Function) startBody() {
259         entry := f.newBasicBlock("entry")
260         f.currentBlock = entry
261         f.objects = make(map[types.Object]Value) // needed for some synthetics, e.g. init
262 }
263
264 func (f *Function) blockset(i int) *BlockSet {
265         bs := &f.blocksets[i]
266         if len(bs.values) != len(f.Blocks) {
267                 if cap(bs.values) >= len(f.Blocks) {
268                         bs.values = bs.values[:len(f.Blocks)]
269                         bs.Clear()
270                 } else {
271                         bs.values = make([]bool, len(f.Blocks))
272                 }
273         } else {
274                 bs.Clear()
275         }
276         return bs
277 }
278
279 func (f *Function) exitBlock() {
280         old := f.currentBlock
281
282         f.Exit = f.newBasicBlock("exit")
283         f.currentBlock = f.Exit
284
285         ret := f.results()
286         results := make([]Value, len(ret))
287         // Run function calls deferred in this
288         // function when explicitly returning from it.
289         f.emit(new(RunDefers), nil)
290         for i, r := range ret {
291                 results[i] = emitLoad(f, r, nil)
292         }
293
294         f.emit(&Return{Results: results}, nil)
295         f.currentBlock = old
296 }
297
298 // createSyntacticParams populates f.Params and generates code (spills
299 // and named result locals) for all the parameters declared in the
300 // syntax.  In addition it populates the f.objects mapping.
301 //
302 // Preconditions:
303 // f.startBody() was called.
304 // Postcondition:
305 // len(f.Params) == len(f.Signature.Params) + (f.Signature.Recv() ? 1 : 0)
306 //
307 func (f *Function) createSyntacticParams(recv *ast.FieldList, functype *ast.FuncType) {
308         // Receiver (at most one inner iteration).
309         if recv != nil {
310                 for _, field := range recv.List {
311                         for _, n := range field.Names {
312                                 f.addSpilledParam(f.Pkg.info.Defs[n], n)
313                         }
314                         // Anonymous receiver?  No need to spill.
315                         if field.Names == nil {
316                                 f.addParamObj(f.Signature.Recv(), field)
317                         }
318                 }
319         }
320
321         // Parameters.
322         if functype.Params != nil {
323                 n := len(f.Params) // 1 if has recv, 0 otherwise
324                 for _, field := range functype.Params.List {
325                         for _, n := range field.Names {
326                                 f.addSpilledParam(f.Pkg.info.Defs[n], n)
327                         }
328                         // Anonymous parameter?  No need to spill.
329                         if field.Names == nil {
330                                 f.addParamObj(f.Signature.Params().At(len(f.Params)-n), field)
331                         }
332                 }
333         }
334
335         // Named results.
336         if functype.Results != nil {
337                 for _, field := range functype.Results.List {
338                         // Implicit "var" decl of locals for named results.
339                         for _, n := range field.Names {
340                                 f.namedResults = append(f.namedResults, f.addLocalForIdent(n))
341                         }
342                 }
343
344                 if len(f.namedResults) == 0 {
345                         sig := f.Signature.Results()
346                         for i := 0; i < sig.Len(); i++ {
347                                 // XXX position information
348                                 v := f.addLocal(sig.At(i).Type(), nil)
349                                 f.implicitResults = append(f.implicitResults, v)
350                         }
351                 }
352         }
353 }
354
355 func numberNodes(f *Function) {
356         var base ID
357         for _, b := range f.Blocks {
358                 for _, instr := range b.Instrs {
359                         if instr == nil {
360                                 continue
361                         }
362                         base++
363                         instr.setID(base)
364                 }
365         }
366 }
367
368 // buildReferrers populates the def/use information in all non-nil
369 // Value.Referrers slice.
370 // Precondition: all such slices are initially empty.
371 func buildReferrers(f *Function) {
372         var rands []*Value
373         for _, b := range f.Blocks {
374                 for _, instr := range b.Instrs {
375                         rands = instr.Operands(rands[:0]) // recycle storage
376                         for _, rand := range rands {
377                                 if r := *rand; r != nil {
378                                         if ref := r.Referrers(); ref != nil {
379                                                 *ref = append(*ref, instr)
380                                         }
381                                 }
382                         }
383                 }
384         }
385 }
386
387 func (f *Function) emitConsts() {
388         if len(f.Blocks) == 0 {
389                 f.consts = nil
390                 return
391         }
392
393         // TODO(dh): our deduplication only works on booleans and
394         // integers. other constants are represented as pointers to
395         // things.
396         if len(f.consts) == 0 {
397                 return
398         } else if len(f.consts) <= 32 {
399                 f.emitConstsFew()
400         } else {
401                 f.emitConstsMany()
402         }
403 }
404
405 func (f *Function) emitConstsFew() {
406         dedup := make([]*Const, 0, 32)
407         for _, c := range f.consts {
408                 if len(*c.Referrers()) == 0 {
409                         continue
410                 }
411                 found := false
412                 for _, d := range dedup {
413                         if c.typ == d.typ && c.Value == d.Value {
414                                 replaceAll(c, d)
415                                 found = true
416                                 break
417                         }
418                 }
419                 if !found {
420                         dedup = append(dedup, c)
421                 }
422         }
423
424         instrs := make([]Instruction, len(f.Blocks[0].Instrs)+len(dedup))
425         for i, c := range dedup {
426                 instrs[i] = c
427                 c.setBlock(f.Blocks[0])
428         }
429         copy(instrs[len(dedup):], f.Blocks[0].Instrs)
430         f.Blocks[0].Instrs = instrs
431         f.consts = nil
432 }
433
434 func (f *Function) emitConstsMany() {
435         type constKey struct {
436                 typ   types.Type
437                 value constant.Value
438         }
439
440         m := make(map[constKey]Value, len(f.consts))
441         areNil := 0
442         for i, c := range f.consts {
443                 if len(*c.Referrers()) == 0 {
444                         f.consts[i] = nil
445                         areNil++
446                         continue
447                 }
448
449                 k := constKey{
450                         typ:   c.typ,
451                         value: c.Value,
452                 }
453                 if dup, ok := m[k]; !ok {
454                         m[k] = c
455                 } else {
456                         f.consts[i] = nil
457                         areNil++
458                         replaceAll(c, dup)
459                 }
460         }
461
462         instrs := make([]Instruction, len(f.Blocks[0].Instrs)+len(f.consts)-areNil)
463         i := 0
464         for _, c := range f.consts {
465                 if c != nil {
466                         instrs[i] = c
467                         c.setBlock(f.Blocks[0])
468                         i++
469                 }
470         }
471         copy(instrs[i:], f.Blocks[0].Instrs)
472         f.Blocks[0].Instrs = instrs
473         f.consts = nil
474 }
475
476 // buildFakeExits ensures that every block in the function is
477 // reachable in reverse from the Exit block. This is required to build
478 // a full post-dominator tree, and to ensure the exit block's
479 // inclusion in the dominator tree.
480 func buildFakeExits(fn *Function) {
481         // Find back-edges via forward DFS
482         fn.fakeExits = BlockSet{values: make([]bool, len(fn.Blocks))}
483         seen := fn.blockset(0)
484         backEdges := fn.blockset(1)
485
486         var dfs func(b *BasicBlock)
487         dfs = func(b *BasicBlock) {
488                 if !seen.Add(b) {
489                         backEdges.Add(b)
490                         return
491                 }
492                 for _, pred := range b.Succs {
493                         dfs(pred)
494                 }
495         }
496         dfs(fn.Blocks[0])
497 buildLoop:
498         for {
499                 seen := fn.blockset(2)
500                 var dfs func(b *BasicBlock)
501                 dfs = func(b *BasicBlock) {
502                         if !seen.Add(b) {
503                                 return
504                         }
505                         for _, pred := range b.Preds {
506                                 dfs(pred)
507                         }
508                         if b == fn.Exit {
509                                 for _, b := range fn.Blocks {
510                                         if fn.fakeExits.Has(b) {
511                                                 dfs(b)
512                                         }
513                                 }
514                         }
515                 }
516                 dfs(fn.Exit)
517
518                 for _, b := range fn.Blocks {
519                         if !seen.Has(b) && backEdges.Has(b) {
520                                 // Block b is not reachable from the exit block. Add a
521                                 // fake jump from b to exit, then try again. Note that we
522                                 // only add one fake edge at a time, as it may make
523                                 // multiple blocks reachable.
524                                 //
525                                 // We only consider those blocks that have back edges.
526                                 // Any unreachable block that doesn't have a back edge
527                                 // must flow into a loop, which by definition has a
528                                 // back edge. Thus, by looking for loops, we should
529                                 // need fewer fake edges overall.
530                                 fn.fakeExits.Add(b)
531                                 continue buildLoop
532                         }
533                 }
534
535                 break
536         }
537 }
538
539 // finishBody() finalizes the function after IR code generation of its body.
540 func (f *Function) finishBody() {
541         f.objects = nil
542         f.currentBlock = nil
543         f.lblocks = nil
544
545         // Remove from f.Locals any Allocs that escape to the heap.
546         j := 0
547         for _, l := range f.Locals {
548                 if !l.Heap {
549                         f.Locals[j] = l
550                         j++
551                 }
552         }
553         // Nil out f.Locals[j:] to aid GC.
554         for i := j; i < len(f.Locals); i++ {
555                 f.Locals[i] = nil
556         }
557         f.Locals = f.Locals[:j]
558
559         optimizeBlocks(f)
560         buildFakeExits(f)
561         buildReferrers(f)
562         buildDomTree(f)
563         buildPostDomTree(f)
564
565         if f.Prog.mode&NaiveForm == 0 {
566                 lift(f)
567         }
568
569         // emit constants after lifting, because lifting may produce new constants.
570         f.emitConsts()
571
572         f.namedResults = nil // (used by lifting)
573         f.implicitResults = nil
574
575         numberNodes(f)
576
577         defer f.wr.Close()
578         f.wr.WriteFunc("start", "start", f)
579
580         if f.Prog.mode&PrintFunctions != 0 {
581                 printMu.Lock()
582                 f.WriteTo(os.Stdout)
583                 printMu.Unlock()
584         }
585
586         if f.Prog.mode&SanityCheckFunctions != 0 {
587                 mustSanityCheck(f, nil)
588         }
589 }
590
591 func isUselessPhi(phi *Phi) (Value, bool) {
592         var v0 Value
593         for _, e := range phi.Edges {
594                 if e == phi {
595                         continue
596                 }
597                 if v0 == nil {
598                         v0 = e
599                 }
600                 if v0 != e {
601                         if v0, ok := v0.(*Const); ok {
602                                 if e, ok := e.(*Const); ok {
603                                         if v0.typ == e.typ && v0.Value == e.Value {
604                                                 continue
605                                         }
606                                 }
607                         }
608                         return nil, false
609                 }
610         }
611         return v0, true
612 }
613
614 func (f *Function) RemoveNilBlocks() {
615         f.removeNilBlocks()
616 }
617
618 // removeNilBlocks eliminates nils from f.Blocks and updates each
619 // BasicBlock.Index.  Use this after any pass that may delete blocks.
620 //
621 func (f *Function) removeNilBlocks() {
622         j := 0
623         for _, b := range f.Blocks {
624                 if b != nil {
625                         b.Index = j
626                         f.Blocks[j] = b
627                         j++
628                 }
629         }
630         // Nil out f.Blocks[j:] to aid GC.
631         for i := j; i < len(f.Blocks); i++ {
632                 f.Blocks[i] = nil
633         }
634         f.Blocks = f.Blocks[:j]
635 }
636
637 // SetDebugMode sets the debug mode for package pkg.  If true, all its
638 // functions will include full debug info.  This greatly increases the
639 // size of the instruction stream, and causes Functions to depend upon
640 // the ASTs, potentially keeping them live in memory for longer.
641 //
642 func (pkg *Package) SetDebugMode(debug bool) {
643         // TODO(adonovan): do we want ast.File granularity?
644         pkg.debug = debug
645 }
646
647 // debugInfo reports whether debug info is wanted for this function.
648 func (f *Function) debugInfo() bool {
649         return f.Pkg != nil && f.Pkg.debug
650 }
651
652 // addNamedLocal creates a local variable, adds it to function f and
653 // returns it.  Its name and type are taken from obj.  Subsequent
654 // calls to f.lookup(obj) will return the same local.
655 //
656 func (f *Function) addNamedLocal(obj types.Object, source ast.Node) *Alloc {
657         l := f.addLocal(obj.Type(), source)
658         f.objects[obj] = l
659         return l
660 }
661
662 func (f *Function) addLocalForIdent(id *ast.Ident) *Alloc {
663         return f.addNamedLocal(f.Pkg.info.Defs[id], id)
664 }
665
666 // addLocal creates an anonymous local variable of type typ, adds it
667 // to function f and returns it.  pos is the optional source location.
668 //
669 func (f *Function) addLocal(typ types.Type, source ast.Node) *Alloc {
670         v := &Alloc{}
671         v.setType(types.NewPointer(typ))
672         f.Locals = append(f.Locals, v)
673         f.emit(v, source)
674         return v
675 }
676
677 // lookup returns the address of the named variable identified by obj
678 // that is local to function f or one of its enclosing functions.
679 // If escaping, the reference comes from a potentially escaping pointer
680 // expression and the referent must be heap-allocated.
681 //
682 func (f *Function) lookup(obj types.Object, escaping bool) Value {
683         if v, ok := f.objects[obj]; ok {
684                 if alloc, ok := v.(*Alloc); ok && escaping {
685                         alloc.Heap = true
686                 }
687                 return v // function-local var (address)
688         }
689
690         // Definition must be in an enclosing function;
691         // plumb it through intervening closures.
692         if f.parent == nil {
693                 panic("no ir.Value for " + obj.String())
694         }
695         outer := f.parent.lookup(obj, true) // escaping
696         v := &FreeVar{
697                 name:   obj.Name(),
698                 typ:    outer.Type(),
699                 outer:  outer,
700                 parent: f,
701         }
702         f.objects[obj] = v
703         f.FreeVars = append(f.FreeVars, v)
704         return v
705 }
706
707 // emit emits the specified instruction to function f.
708 func (f *Function) emit(instr Instruction, source ast.Node) Value {
709         return f.currentBlock.emit(instr, source)
710 }
711
712 // RelString returns the full name of this function, qualified by
713 // package name, receiver type, etc.
714 //
715 // The specific formatting rules are not guaranteed and may change.
716 //
717 // Examples:
718 //      "math.IsNaN"                  // a package-level function
719 //      "(*bytes.Buffer).Bytes"       // a declared method or a wrapper
720 //      "(*bytes.Buffer).Bytes$thunk" // thunk (func wrapping method; receiver is param 0)
721 //      "(*bytes.Buffer).Bytes$bound" // bound (func wrapping method; receiver supplied by closure)
722 //      "main.main$1"                 // an anonymous function in main
723 //      "main.init#1"                 // a declared init function
724 //      "main.init"                   // the synthesized package initializer
725 //
726 // When these functions are referred to from within the same package
727 // (i.e. from == f.Pkg.Object), they are rendered without the package path.
728 // For example: "IsNaN", "(*Buffer).Bytes", etc.
729 //
730 // All non-synthetic functions have distinct package-qualified names.
731 // (But two methods may have the same name "(T).f" if one is a synthetic
732 // wrapper promoting a non-exported method "f" from another package; in
733 // that case, the strings are equal but the identifiers "f" are distinct.)
734 //
735 func (f *Function) RelString(from *types.Package) string {
736         // Anonymous?
737         if f.parent != nil {
738                 // An anonymous function's Name() looks like "parentName$1",
739                 // but its String() should include the type/package/etc.
740                 parent := f.parent.RelString(from)
741                 for i, anon := range f.parent.AnonFuncs {
742                         if anon == f {
743                                 return fmt.Sprintf("%s$%d", parent, 1+i)
744                         }
745                 }
746
747                 return f.name // should never happen
748         }
749
750         // Method (declared or wrapper)?
751         if recv := f.Signature.Recv(); recv != nil {
752                 return f.relMethod(from, recv.Type())
753         }
754
755         // Thunk?
756         if f.method != nil {
757                 return f.relMethod(from, f.method.Recv())
758         }
759
760         // Bound?
761         if len(f.FreeVars) == 1 && strings.HasSuffix(f.name, "$bound") {
762                 return f.relMethod(from, f.FreeVars[0].Type())
763         }
764
765         // Package-level function?
766         // Prefix with package name for cross-package references only.
767         if p := f.pkg(); p != nil && p != from {
768                 return fmt.Sprintf("%s.%s", p.Path(), f.name)
769         }
770
771         // Unknown.
772         return f.name
773 }
774
775 func (f *Function) relMethod(from *types.Package, recv types.Type) string {
776         return fmt.Sprintf("(%s).%s", relType(recv, from), f.name)
777 }
778
779 // writeSignature writes to buf the signature sig in declaration syntax.
780 func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *types.Signature, params []*Parameter) {
781         buf.WriteString("func ")
782         if recv := sig.Recv(); recv != nil {
783                 buf.WriteString("(")
784                 if n := params[0].Name(); n != "" {
785                         buf.WriteString(n)
786                         buf.WriteString(" ")
787                 }
788                 types.WriteType(buf, params[0].Type(), types.RelativeTo(from))
789                 buf.WriteString(") ")
790         }
791         buf.WriteString(name)
792         types.WriteSignature(buf, sig, types.RelativeTo(from))
793 }
794
795 func (f *Function) pkg() *types.Package {
796         if f.Pkg != nil {
797                 return f.Pkg.Pkg
798         }
799         return nil
800 }
801
802 var _ io.WriterTo = (*Function)(nil) // *Function implements io.Writer
803
804 func (f *Function) WriteTo(w io.Writer) (int64, error) {
805         var buf bytes.Buffer
806         WriteFunction(&buf, f)
807         n, err := w.Write(buf.Bytes())
808         return int64(n), err
809 }
810
811 // WriteFunction writes to buf a human-readable "disassembly" of f.
812 func WriteFunction(buf *bytes.Buffer, f *Function) {
813         fmt.Fprintf(buf, "# Name: %s\n", f.String())
814         if f.Pkg != nil {
815                 fmt.Fprintf(buf, "# Package: %s\n", f.Pkg.Pkg.Path())
816         }
817         if syn := f.Synthetic; syn != 0 {
818                 fmt.Fprintln(buf, "# Synthetic:", syn)
819         }
820         if pos := f.Pos(); pos.IsValid() {
821                 fmt.Fprintf(buf, "# Location: %s\n", f.Prog.Fset.Position(pos))
822         }
823
824         if f.parent != nil {
825                 fmt.Fprintf(buf, "# Parent: %s\n", f.parent.Name())
826         }
827
828         from := f.pkg()
829
830         if f.FreeVars != nil {
831                 buf.WriteString("# Free variables:\n")
832                 for i, fv := range f.FreeVars {
833                         fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, fv.Name(), relType(fv.Type(), from))
834                 }
835         }
836
837         if len(f.Locals) > 0 {
838                 buf.WriteString("# Locals:\n")
839                 for i, l := range f.Locals {
840                         fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, l.Name(), relType(deref(l.Type()), from))
841                 }
842         }
843         writeSignature(buf, from, f.Name(), f.Signature, f.Params)
844         buf.WriteString(":\n")
845
846         if f.Blocks == nil {
847                 buf.WriteString("\t(external)\n")
848         }
849
850         for _, b := range f.Blocks {
851                 if b == nil {
852                         // Corrupt CFG.
853                         fmt.Fprintf(buf, ".nil:\n")
854                         continue
855                 }
856                 fmt.Fprintf(buf, "b%d:", b.Index)
857                 if len(b.Preds) > 0 {
858                         fmt.Fprint(buf, " ←")
859                         for _, pred := range b.Preds {
860                                 fmt.Fprintf(buf, " b%d", pred.Index)
861                         }
862                 }
863                 if b.Comment != "" {
864                         fmt.Fprintf(buf, " # %s", b.Comment)
865                 }
866                 buf.WriteByte('\n')
867
868                 if false { // CFG debugging
869                         fmt.Fprintf(buf, "\t# CFG: %s --> %s --> %s\n", b.Preds, b, b.Succs)
870                 }
871
872                 buf2 := &bytes.Buffer{}
873                 for _, instr := range b.Instrs {
874                         buf.WriteString("\t")
875                         switch v := instr.(type) {
876                         case Value:
877                                 // Left-align the instruction.
878                                 if name := v.Name(); name != "" {
879                                         fmt.Fprintf(buf, "%s = ", name)
880                                 }
881                                 buf.WriteString(instr.String())
882                         case nil:
883                                 // Be robust against bad transforms.
884                                 buf.WriteString("<deleted>")
885                         default:
886                                 buf.WriteString(instr.String())
887                         }
888                         buf.WriteString("\n")
889
890                         if f.Prog.mode&PrintSource != 0 {
891                                 if s := instr.Source(); s != nil {
892                                         buf2.Reset()
893                                         format.Node(buf2, f.Prog.Fset, s)
894                                         for {
895                                                 line, err := buf2.ReadString('\n')
896                                                 if len(line) == 0 {
897                                                         break
898                                                 }
899                                                 buf.WriteString("\t\t> ")
900                                                 buf.WriteString(line)
901                                                 if line[len(line)-1] != '\n' {
902                                                         buf.WriteString("\n")
903                                                 }
904                                                 if err != nil {
905                                                         break
906                                                 }
907                                         }
908                                 }
909                         }
910                 }
911                 buf.WriteString("\n")
912         }
913 }
914
915 // newBasicBlock adds to f a new basic block and returns it.  It does
916 // not automatically become the current block for subsequent calls to emit.
917 // comment is an optional string for more readable debugging output.
918 //
919 func (f *Function) newBasicBlock(comment string) *BasicBlock {
920         b := &BasicBlock{
921                 Index:   len(f.Blocks),
922                 Comment: comment,
923                 parent:  f,
924         }
925         b.Succs = b.succs2[:0]
926         f.Blocks = append(f.Blocks, b)
927         return b
928 }
929
930 // NewFunction returns a new synthetic Function instance belonging to
931 // prog, with its name and signature fields set as specified.
932 //
933 // The caller is responsible for initializing the remaining fields of
934 // the function object, e.g. Pkg, Params, Blocks.
935 //
936 // It is practically impossible for clients to construct well-formed
937 // IR functions/packages/programs directly, so we assume this is the
938 // job of the Builder alone.  NewFunction exists to provide clients a
939 // little flexibility.  For example, analysis tools may wish to
940 // construct fake Functions for the root of the callgraph, a fake
941 // "reflect" package, etc.
942 //
943 // TODO(adonovan): think harder about the API here.
944 //
945 func (prog *Program) NewFunction(name string, sig *types.Signature, provenance Synthetic) *Function {
946         return &Function{Prog: prog, name: name, Signature: sig, Synthetic: provenance}
947 }
948
949 //lint:ignore U1000 we may make use of this for functions loaded from export data
950 type extentNode [2]token.Pos
951
952 func (n extentNode) Pos() token.Pos { return n[0] }
953 func (n extentNode) End() token.Pos { return n[1] }
954
955 func (f *Function) initHTML(name string) {
956         if name == "" {
957                 return
958         }
959         if rel := f.RelString(nil); rel == name {
960                 f.wr = NewHTMLWriter("ir.html", rel, "")
961         }
962 }