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
5package ir
6
7// This file implements the Function and BasicBlock types.
8
9import (
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.
23func 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.
29func (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.
37func (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.
52func (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//
57func (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//
64func (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.
74func (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.
84func (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.
94func (b *BasicBlock) hasPhi() bool {
95	_, ok := b.Instrs[0].(*Phi)
96	return ok
97}
98
99func (b *BasicBlock) Phis() []Instruction {
100	return b.phis()
101}
102
103// phis returns the prefix of b.Instrs containing all the block's φ-nodes.
104func (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//
116func (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//
127func (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//
139func (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//
173type 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//
184type 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//
193func (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//
208func (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
229func (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//
243func (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//
258func (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
264func (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
279func (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//
307func (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
355func 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.
371func 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
387func (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
405func (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
434func (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.
480func 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])
497buildLoop:
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.
540func (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	buildReferrers(f)
561	buildDomTree(f)
562	buildPostDomTree(f)
563
564	if f.Prog.mode&NaiveForm == 0 {
565		lift(f)
566	}
567
568	// emit constants after lifting, because lifting may produce new constants.
569	f.emitConsts()
570
571	f.namedResults = nil // (used by lifting)
572	f.implicitResults = nil
573
574	numberNodes(f)
575
576	defer f.wr.Close()
577	f.wr.WriteFunc("start", "start", f)
578
579	if f.Prog.mode&PrintFunctions != 0 {
580		printMu.Lock()
581		f.WriteTo(os.Stdout)
582		printMu.Unlock()
583	}
584
585	if f.Prog.mode&SanityCheckFunctions != 0 {
586		mustSanityCheck(f, nil)
587	}
588}
589
590func isUselessPhi(phi *Phi) (Value, bool) {
591	var v0 Value
592	for _, e := range phi.Edges {
593		if e == phi {
594			continue
595		}
596		if v0 == nil {
597			v0 = e
598		}
599		if v0 != e {
600			if v0, ok := v0.(*Const); ok {
601				if e, ok := e.(*Const); ok {
602					if v0.typ == e.typ && v0.Value == e.Value {
603						continue
604					}
605				}
606			}
607			return nil, false
608		}
609	}
610	return v0, true
611}
612
613func (f *Function) RemoveNilBlocks() {
614	f.removeNilBlocks()
615}
616
617// removeNilBlocks eliminates nils from f.Blocks and updates each
618// BasicBlock.Index.  Use this after any pass that may delete blocks.
619//
620func (f *Function) removeNilBlocks() {
621	j := 0
622	for _, b := range f.Blocks {
623		if b != nil {
624			b.Index = j
625			f.Blocks[j] = b
626			j++
627		}
628	}
629	// Nil out f.Blocks[j:] to aid GC.
630	for i := j; i < len(f.Blocks); i++ {
631		f.Blocks[i] = nil
632	}
633	f.Blocks = f.Blocks[:j]
634}
635
636// SetDebugMode sets the debug mode for package pkg.  If true, all its
637// functions will include full debug info.  This greatly increases the
638// size of the instruction stream, and causes Functions to depend upon
639// the ASTs, potentially keeping them live in memory for longer.
640//
641func (pkg *Package) SetDebugMode(debug bool) {
642	// TODO(adonovan): do we want ast.File granularity?
643	pkg.debug = debug
644}
645
646// debugInfo reports whether debug info is wanted for this function.
647func (f *Function) debugInfo() bool {
648	return f.Pkg != nil && f.Pkg.debug
649}
650
651// addNamedLocal creates a local variable, adds it to function f and
652// returns it.  Its name and type are taken from obj.  Subsequent
653// calls to f.lookup(obj) will return the same local.
654//
655func (f *Function) addNamedLocal(obj types.Object, source ast.Node) *Alloc {
656	l := f.addLocal(obj.Type(), source)
657	f.objects[obj] = l
658	return l
659}
660
661func (f *Function) addLocalForIdent(id *ast.Ident) *Alloc {
662	return f.addNamedLocal(f.Pkg.info.Defs[id], id)
663}
664
665// addLocal creates an anonymous local variable of type typ, adds it
666// to function f and returns it.  pos is the optional source location.
667//
668func (f *Function) addLocal(typ types.Type, source ast.Node) *Alloc {
669	v := &Alloc{}
670	v.setType(types.NewPointer(typ))
671	f.Locals = append(f.Locals, v)
672	f.emit(v, source)
673	return v
674}
675
676// lookup returns the address of the named variable identified by obj
677// that is local to function f or one of its enclosing functions.
678// If escaping, the reference comes from a potentially escaping pointer
679// expression and the referent must be heap-allocated.
680//
681func (f *Function) lookup(obj types.Object, escaping bool) Value {
682	if v, ok := f.objects[obj]; ok {
683		if alloc, ok := v.(*Alloc); ok && escaping {
684			alloc.Heap = true
685		}
686		return v // function-local var (address)
687	}
688
689	// Definition must be in an enclosing function;
690	// plumb it through intervening closures.
691	if f.parent == nil {
692		panic("no ir.Value for " + obj.String())
693	}
694	outer := f.parent.lookup(obj, true) // escaping
695	v := &FreeVar{
696		name:   obj.Name(),
697		typ:    outer.Type(),
698		outer:  outer,
699		parent: f,
700	}
701	f.objects[obj] = v
702	f.FreeVars = append(f.FreeVars, v)
703	return v
704}
705
706// emit emits the specified instruction to function f.
707func (f *Function) emit(instr Instruction, source ast.Node) Value {
708	return f.currentBlock.emit(instr, source)
709}
710
711// RelString returns the full name of this function, qualified by
712// package name, receiver type, etc.
713//
714// The specific formatting rules are not guaranteed and may change.
715//
716// Examples:
717//      "math.IsNaN"                  // a package-level function
718//      "(*bytes.Buffer).Bytes"       // a declared method or a wrapper
719//      "(*bytes.Buffer).Bytes$thunk" // thunk (func wrapping method; receiver is param 0)
720//      "(*bytes.Buffer).Bytes$bound" // bound (func wrapping method; receiver supplied by closure)
721//      "main.main$1"                 // an anonymous function in main
722//      "main.init#1"                 // a declared init function
723//      "main.init"                   // the synthesized package initializer
724//
725// When these functions are referred to from within the same package
726// (i.e. from == f.Pkg.Object), they are rendered without the package path.
727// For example: "IsNaN", "(*Buffer).Bytes", etc.
728//
729// All non-synthetic functions have distinct package-qualified names.
730// (But two methods may have the same name "(T).f" if one is a synthetic
731// wrapper promoting a non-exported method "f" from another package; in
732// that case, the strings are equal but the identifiers "f" are distinct.)
733//
734func (f *Function) RelString(from *types.Package) string {
735	// Anonymous?
736	if f.parent != nil {
737		// An anonymous function's Name() looks like "parentName$1",
738		// but its String() should include the type/package/etc.
739		parent := f.parent.RelString(from)
740		for i, anon := range f.parent.AnonFuncs {
741			if anon == f {
742				return fmt.Sprintf("%s$%d", parent, 1+i)
743			}
744		}
745
746		return f.name // should never happen
747	}
748
749	// Method (declared or wrapper)?
750	if recv := f.Signature.Recv(); recv != nil {
751		return f.relMethod(from, recv.Type())
752	}
753
754	// Thunk?
755	if f.method != nil {
756		return f.relMethod(from, f.method.Recv())
757	}
758
759	// Bound?
760	if len(f.FreeVars) == 1 && strings.HasSuffix(f.name, "$bound") {
761		return f.relMethod(from, f.FreeVars[0].Type())
762	}
763
764	// Package-level function?
765	// Prefix with package name for cross-package references only.
766	if p := f.pkg(); p != nil && p != from {
767		return fmt.Sprintf("%s.%s", p.Path(), f.name)
768	}
769
770	// Unknown.
771	return f.name
772}
773
774func (f *Function) relMethod(from *types.Package, recv types.Type) string {
775	return fmt.Sprintf("(%s).%s", relType(recv, from), f.name)
776}
777
778// writeSignature writes to buf the signature sig in declaration syntax.
779func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *types.Signature, params []*Parameter) {
780	buf.WriteString("func ")
781	if recv := sig.Recv(); recv != nil {
782		buf.WriteString("(")
783		if n := params[0].Name(); n != "" {
784			buf.WriteString(n)
785			buf.WriteString(" ")
786		}
787		types.WriteType(buf, params[0].Type(), types.RelativeTo(from))
788		buf.WriteString(") ")
789	}
790	buf.WriteString(name)
791	types.WriteSignature(buf, sig, types.RelativeTo(from))
792}
793
794func (f *Function) pkg() *types.Package {
795	if f.Pkg != nil {
796		return f.Pkg.Pkg
797	}
798	return nil
799}
800
801var _ io.WriterTo = (*Function)(nil) // *Function implements io.Writer
802
803func (f *Function) WriteTo(w io.Writer) (int64, error) {
804	var buf bytes.Buffer
805	WriteFunction(&buf, f)
806	n, err := w.Write(buf.Bytes())
807	return int64(n), err
808}
809
810// WriteFunction writes to buf a human-readable "disassembly" of f.
811func WriteFunction(buf *bytes.Buffer, f *Function) {
812	fmt.Fprintf(buf, "# Name: %s\n", f.String())
813	if f.Pkg != nil {
814		fmt.Fprintf(buf, "# Package: %s\n", f.Pkg.Pkg.Path())
815	}
816	if syn := f.Synthetic; syn != "" {
817		fmt.Fprintln(buf, "# Synthetic:", syn)
818	}
819	if pos := f.Pos(); pos.IsValid() {
820		fmt.Fprintf(buf, "# Location: %s\n", f.Prog.Fset.Position(pos))
821	}
822
823	if f.parent != nil {
824		fmt.Fprintf(buf, "# Parent: %s\n", f.parent.Name())
825	}
826
827	from := f.pkg()
828
829	if f.FreeVars != nil {
830		buf.WriteString("# Free variables:\n")
831		for i, fv := range f.FreeVars {
832			fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, fv.Name(), relType(fv.Type(), from))
833		}
834	}
835
836	if len(f.Locals) > 0 {
837		buf.WriteString("# Locals:\n")
838		for i, l := range f.Locals {
839			fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, l.Name(), relType(deref(l.Type()), from))
840		}
841	}
842	writeSignature(buf, from, f.Name(), f.Signature, f.Params)
843	buf.WriteString(":\n")
844
845	if f.Blocks == nil {
846		buf.WriteString("\t(external)\n")
847	}
848
849	for _, b := range f.Blocks {
850		if b == nil {
851			// Corrupt CFG.
852			fmt.Fprintf(buf, ".nil:\n")
853			continue
854		}
855		fmt.Fprintf(buf, "b%d:", b.Index)
856		if len(b.Preds) > 0 {
857			fmt.Fprint(buf, " ←")
858			for _, pred := range b.Preds {
859				fmt.Fprintf(buf, " b%d", pred.Index)
860			}
861		}
862		if b.Comment != "" {
863			fmt.Fprintf(buf, " # %s", b.Comment)
864		}
865		buf.WriteByte('\n')
866
867		if false { // CFG debugging
868			fmt.Fprintf(buf, "\t# CFG: %s --> %s --> %s\n", b.Preds, b, b.Succs)
869		}
870
871		buf2 := &bytes.Buffer{}
872		for _, instr := range b.Instrs {
873			buf.WriteString("\t")
874			switch v := instr.(type) {
875			case Value:
876				// Left-align the instruction.
877				if name := v.Name(); name != "" {
878					fmt.Fprintf(buf, "%s = ", name)
879				}
880				buf.WriteString(instr.String())
881			case nil:
882				// Be robust against bad transforms.
883				buf.WriteString("<deleted>")
884			default:
885				buf.WriteString(instr.String())
886			}
887			buf.WriteString("\n")
888
889			if f.Prog.mode&PrintSource != 0 {
890				if s := instr.Source(); s != nil {
891					buf2.Reset()
892					format.Node(buf2, f.Prog.Fset, s)
893					for {
894						line, err := buf2.ReadString('\n')
895						if len(line) == 0 {
896							break
897						}
898						buf.WriteString("\t\t> ")
899						buf.WriteString(line)
900						if line[len(line)-1] != '\n' {
901							buf.WriteString("\n")
902						}
903						if err != nil {
904							break
905						}
906					}
907				}
908			}
909		}
910		buf.WriteString("\n")
911	}
912}
913
914// newBasicBlock adds to f a new basic block and returns it.  It does
915// not automatically become the current block for subsequent calls to emit.
916// comment is an optional string for more readable debugging output.
917//
918func (f *Function) newBasicBlock(comment string) *BasicBlock {
919	b := &BasicBlock{
920		Index:   len(f.Blocks),
921		Comment: comment,
922		parent:  f,
923	}
924	b.Succs = b.succs2[:0]
925	f.Blocks = append(f.Blocks, b)
926	return b
927}
928
929// NewFunction returns a new synthetic Function instance belonging to
930// prog, with its name and signature fields set as specified.
931//
932// The caller is responsible for initializing the remaining fields of
933// the function object, e.g. Pkg, Params, Blocks.
934//
935// It is practically impossible for clients to construct well-formed
936// IR functions/packages/programs directly, so we assume this is the
937// job of the Builder alone.  NewFunction exists to provide clients a
938// little flexibility.  For example, analysis tools may wish to
939// construct fake Functions for the root of the callgraph, a fake
940// "reflect" package, etc.
941//
942// TODO(adonovan): think harder about the API here.
943//
944func (prog *Program) NewFunction(name string, sig *types.Signature, provenance string) *Function {
945	return &Function{Prog: prog, name: name, Signature: sig, Synthetic: provenance}
946}
947
948//lint:ignore U1000 we may make use of this for functions loaded from export data
949type extentNode [2]token.Pos
950
951func (n extentNode) Pos() token.Pos { return n[0] }
952func (n extentNode) End() token.Pos { return n[1] }
953
954func (f *Function) initHTML(name string) {
955	if name == "" {
956		return
957	}
958	if rel := f.RelString(nil); rel == name {
959		f.wr = NewHTMLWriter("ir.html", rel, "")
960	}
961}
962