1// Copyright 2011 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 gc
6
7import (
8	"cmd/compile/internal/types"
9	"fmt"
10	"strconv"
11	"strings"
12)
13
14// Run analysis on minimal sets of mutually recursive functions
15// or single non-recursive functions, bottom up.
16//
17// Finding these sets is finding strongly connected components
18// by reverse topological order in the static call graph.
19// The algorithm (known as Tarjan's algorithm) for doing that is taken from
20// Sedgewick, Algorithms, Second Edition, p. 482, with two adaptations.
21//
22// First, a hidden closure function (n.Func.IsHiddenClosure()) cannot be the
23// root of a connected component. Refusing to use it as a root
24// forces it into the component of the function in which it appears.
25// This is more convenient for escape analysis.
26//
27// Second, each function becomes two virtual nodes in the graph,
28// with numbers n and n+1. We record the function's node number as n
29// but search from node n+1. If the search tells us that the component
30// number (min) is n+1, we know that this is a trivial component: one function
31// plus its closures. If the search tells us that the component number is
32// n, then there was a path from node n+1 back to node n, meaning that
33// the function set is mutually recursive. The escape analysis can be
34// more precise when analyzing a single non-recursive function than
35// when analyzing a set of mutually recursive functions.
36
37type bottomUpVisitor struct {
38	analyze  func([]*Node, bool)
39	visitgen uint32
40	nodeID   map[*Node]uint32
41	stack    []*Node
42}
43
44// visitBottomUp invokes analyze on the ODCLFUNC nodes listed in list.
45// It calls analyze with successive groups of functions, working from
46// the bottom of the call graph upward. Each time analyze is called with
47// a list of functions, every function on that list only calls other functions
48// on the list or functions that have been passed in previous invocations of
49// analyze. Closures appear in the same list as their outer functions.
50// The lists are as short as possible while preserving those requirements.
51// (In a typical program, many invocations of analyze will be passed just
52// a single function.) The boolean argument 'recursive' passed to analyze
53// specifies whether the functions on the list are mutually recursive.
54// If recursive is false, the list consists of only a single function and its closures.
55// If recursive is true, the list may still contain only a single function,
56// if that function is itself recursive.
57func visitBottomUp(list []*Node, analyze func(list []*Node, recursive bool)) {
58	var v bottomUpVisitor
59	v.analyze = analyze
60	v.nodeID = make(map[*Node]uint32)
61	for _, n := range list {
62		if n.Op == ODCLFUNC && !n.Func.IsHiddenClosure() {
63			v.visit(n)
64		}
65	}
66}
67
68func (v *bottomUpVisitor) visit(n *Node) uint32 {
69	if id := v.nodeID[n]; id > 0 {
70		// already visited
71		return id
72	}
73
74	v.visitgen++
75	id := v.visitgen
76	v.nodeID[n] = id
77	v.visitgen++
78	min := v.visitgen
79
80	v.stack = append(v.stack, n)
81	min = v.visitcodelist(n.Nbody, min)
82	if (min == id || min == id+1) && !n.Func.IsHiddenClosure() {
83		// This node is the root of a strongly connected component.
84
85		// The original min passed to visitcodelist was v.nodeID[n]+1.
86		// If visitcodelist found its way back to v.nodeID[n], then this
87		// block is a set of mutually recursive functions.
88		// Otherwise it's just a lone function that does not recurse.
89		recursive := min == id
90
91		// Remove connected component from stack.
92		// Mark walkgen so that future visits return a large number
93		// so as not to affect the caller's min.
94
95		var i int
96		for i = len(v.stack) - 1; i >= 0; i-- {
97			x := v.stack[i]
98			if x == n {
99				break
100			}
101			v.nodeID[x] = ^uint32(0)
102		}
103		v.nodeID[n] = ^uint32(0)
104		block := v.stack[i:]
105		// Run escape analysis on this set of functions.
106		v.stack = v.stack[:i]
107		v.analyze(block, recursive)
108	}
109
110	return min
111}
112
113func (v *bottomUpVisitor) visitcodelist(l Nodes, min uint32) uint32 {
114	for _, n := range l.Slice() {
115		min = v.visitcode(n, min)
116	}
117	return min
118}
119
120func (v *bottomUpVisitor) visitcode(n *Node, min uint32) uint32 {
121	if n == nil {
122		return min
123	}
124
125	min = v.visitcodelist(n.Ninit, min)
126	min = v.visitcode(n.Left, min)
127	min = v.visitcode(n.Right, min)
128	min = v.visitcodelist(n.List, min)
129	min = v.visitcodelist(n.Nbody, min)
130	min = v.visitcodelist(n.Rlist, min)
131
132	if n.Op == OCALLFUNC || n.Op == OCALLMETH {
133		fn := n.Left
134		if n.Op == OCALLMETH {
135			fn = asNode(n.Left.Sym.Def)
136		}
137		if fn != nil && fn.Op == ONAME && fn.Class() == PFUNC && fn.Name.Defn != nil {
138			m := v.visit(fn.Name.Defn)
139			if m < min {
140				min = m
141			}
142		}
143	}
144
145	if n.Op == OCLOSURE {
146		m := v.visit(n.Func.Closure)
147		if m < min {
148			min = m
149		}
150	}
151
152	return min
153}
154
155// Escape analysis.
156
157// An escape analysis pass for a set of functions.
158// The analysis assumes that closures and the functions in which they
159// appear are analyzed together, so that the aliasing between their
160// variables can be modeled more precisely.
161//
162// First escfunc, esc and escassign recurse over the ast of each
163// function to dig out flow(dst,src) edges between any
164// pointer-containing nodes and store them in e.nodeEscState(dst).Flowsrc. For
165// variables assigned to a variable in an outer scope or used as a
166// return value, they store a flow(theSink, src) edge to a fake node
167// 'the Sink'.  For variables referenced in closures, an edge
168// flow(closure, &var) is recorded and the flow of a closure itself to
169// an outer scope is tracked the same way as other variables.
170//
171// Then escflood walks the graph starting at theSink and tags all
172// variables of it can reach an & node as escaping and all function
173// parameters it can reach as leaking.
174//
175// If a value's address is taken but the address does not escape,
176// then the value can stay on the stack. If the value new(T) does
177// not escape, then new(T) can be rewritten into a stack allocation.
178// The same is true of slice literals.
179//
180// If optimizations are disabled (-N), this code is not used.
181// Instead, the compiler assumes that any value whose address
182// is taken without being immediately dereferenced
183// needs to be moved to the heap, and new(T) and slice
184// literals are always real allocations.
185
186func escapes(all []*Node) {
187	visitBottomUp(all, escAnalyze)
188}
189
190const (
191	EscFuncUnknown = 0 + iota
192	EscFuncPlanned
193	EscFuncStarted
194	EscFuncTagged
195)
196
197// There appear to be some loops in the escape graph, causing
198// arbitrary recursion into deeper and deeper levels.
199// Cut this off safely by making minLevel sticky: once you
200// get that deep, you cannot go down any further but you also
201// cannot go up any further. This is a conservative fix.
202// Making minLevel smaller (more negative) would handle more
203// complex chains of indirections followed by address-of operations,
204// at the cost of repeating the traversal once for each additional
205// allowed level when a loop is encountered. Using -2 suffices to
206// pass all the tests we have written so far, which we assume matches
207// the level of complexity we want the escape analysis code to handle.
208const (
209	MinLevel = -2
210)
211
212// A Level encodes the reference state and context applied to
213// (stack, heap) allocated memory.
214//
215// value is the overall sum of *(1) and &(-1) operations encountered
216// along a path from a destination (sink, return value) to a source
217// (allocation, parameter).
218//
219// suffixValue is the maximum-copy-started-suffix-level applied to a sink.
220// For example:
221// sink = x.left.left --> level=2, x is dereferenced twice and does not escape to sink.
222// sink = &Node{x} --> level=-1, x is accessible from sink via one "address of"
223// sink = &Node{&Node{x}} --> level=-2, x is accessible from sink via two "address of"
224// sink = &Node{&Node{x.left}} --> level=-1, but x is NOT accessible from sink because it was indirected and then copied.
225// (The copy operations are sometimes implicit in the source code; in this case,
226// value of x.left was copied into a field of a newly allocated Node)
227//
228// There's one of these for each Node, and the integer values
229// rarely exceed even what can be stored in 4 bits, never mind 8.
230type Level struct {
231	value, suffixValue int8
232}
233
234func (l Level) int() int {
235	return int(l.value)
236}
237
238func levelFrom(i int) Level {
239	if i <= MinLevel {
240		return Level{value: MinLevel}
241	}
242	return Level{value: int8(i)}
243}
244
245func satInc8(x int8) int8 {
246	if x == 127 {
247		return 127
248	}
249	return x + 1
250}
251
252func min8(a, b int8) int8 {
253	if a < b {
254		return a
255	}
256	return b
257}
258
259func max8(a, b int8) int8 {
260	if a > b {
261		return a
262	}
263	return b
264}
265
266// inc returns the level l + 1, representing the effect of an indirect (*) operation.
267func (l Level) inc() Level {
268	if l.value <= MinLevel {
269		return Level{value: MinLevel}
270	}
271	return Level{value: satInc8(l.value), suffixValue: satInc8(l.suffixValue)}
272}
273
274// dec returns the level l - 1, representing the effect of an address-of (&) operation.
275func (l Level) dec() Level {
276	if l.value <= MinLevel {
277		return Level{value: MinLevel}
278	}
279	return Level{value: l.value - 1, suffixValue: l.suffixValue - 1}
280}
281
282// copy returns the level for a copy of a value with level l.
283func (l Level) copy() Level {
284	return Level{value: l.value, suffixValue: max8(l.suffixValue, 0)}
285}
286
287func (l1 Level) min(l2 Level) Level {
288	return Level{
289		value:       min8(l1.value, l2.value),
290		suffixValue: min8(l1.suffixValue, l2.suffixValue)}
291}
292
293// guaranteedDereference returns the number of dereferences
294// applied to a pointer before addresses are taken/generated.
295// This is the maximum level computed from path suffixes starting
296// with copies where paths flow from destination to source.
297func (l Level) guaranteedDereference() int {
298	return int(l.suffixValue)
299}
300
301// An EscStep documents one step in the path from memory
302// that is heap allocated to the (alleged) reason for the
303// heap allocation.
304type EscStep struct {
305	src, dst *Node    // the endpoints of this edge in the escape-to-heap chain.
306	where    *Node    // sometimes the endpoints don't match source locations; set 'where' to make that right
307	parent   *EscStep // used in flood to record path
308	why      string   // explanation for this step in the escape-to-heap chain
309	busy     bool     // used in prevent to snip cycles.
310}
311
312type NodeEscState struct {
313	Curfn             *Node
314	Flowsrc           []EscStep // flow(this, src)
315	Retval            Nodes     // on OCALLxxx, list of dummy return values
316	Loopdepth         int32     // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
317	Level             Level
318	Walkgen           uint32
319	Maxextraloopdepth int32
320}
321
322func (e *EscState) nodeEscState(n *Node) *NodeEscState {
323	if nE, ok := n.Opt().(*NodeEscState); ok {
324		return nE
325	}
326	if n.Opt() != nil {
327		Fatalf("nodeEscState: opt in use (%T)", n.Opt())
328	}
329	nE := &NodeEscState{
330		Curfn: Curfn,
331	}
332	n.SetOpt(nE)
333	e.opts = append(e.opts, n)
334	return nE
335}
336
337func (e *EscState) track(n *Node) {
338	if Curfn == nil {
339		Fatalf("EscState.track: Curfn nil")
340	}
341	n.Esc = EscNone // until proven otherwise
342	nE := e.nodeEscState(n)
343	nE.Loopdepth = e.loopdepth
344	e.noesc = append(e.noesc, n)
345}
346
347// Escape constants are numbered in order of increasing "escapiness"
348// to help make inferences be monotonic. With the exception of
349// EscNever which is sticky, eX < eY means that eY is more exposed
350// than eX, and hence replaces it in a conservative analysis.
351const (
352	EscUnknown        = iota
353	EscNone           // Does not escape to heap, result, or parameters.
354	EscReturn         // Is returned or reachable from returned.
355	EscHeap           // Reachable from the heap
356	EscNever          // By construction will not escape.
357	EscBits           = 3
358	EscMask           = (1 << EscBits) - 1
359	EscContentEscapes = 1 << EscBits // value obtained by indirect of parameter escapes to heap
360	EscReturnBits     = EscBits + 1
361	// Node.esc encoding = | escapeReturnEncoding:(width-4) | contentEscapes:1 | escEnum:3
362)
363
364// escMax returns the maximum of an existing escape value
365// (and its additional parameter flow flags) and a new escape type.
366func escMax(e, etype uint16) uint16 {
367	if e&EscMask >= EscHeap {
368		// normalize
369		if e&^EscMask != 0 {
370			Fatalf("Escape information had unexpected return encoding bits (w/ EscHeap, EscNever), e&EscMask=%v", e&EscMask)
371		}
372	}
373	if e&EscMask > etype {
374		return e
375	}
376	if etype == EscNone || etype == EscReturn {
377		return (e &^ EscMask) | etype
378	}
379	return etype
380}
381
382// For each input parameter to a function, the escapeReturnEncoding describes
383// how the parameter may leak to the function's outputs. This is currently the
384// "level" of the leak where level is 0 or larger (negative level means stored into
385// something whose address is returned -- but that implies stored into the heap,
386// hence EscHeap, which means that the details are not currently relevant. )
387const (
388	bitsPerOutputInTag = 3                                 // For each output, the number of bits for a tag
389	bitsMaskForTag     = uint16(1<<bitsPerOutputInTag) - 1 // The bit mask to extract a single tag.
390	maxEncodedLevel    = int(bitsMaskForTag - 1)           // The largest level that can be stored in a tag.
391)
392
393type EscState struct {
394	// Fake node that all
395	//   - return values and output variables
396	//   - parameters on imported functions not marked 'safe'
397	//   - assignments to global variables
398	// flow to.
399	theSink Node
400
401	dsts      []*Node // all dst nodes
402	loopdepth int32   // for detecting nested loop scopes
403	pdepth    int     // for debug printing in recursions.
404	dstcount  int     // diagnostic
405	edgecount int     // diagnostic
406	noesc     []*Node // list of possible non-escaping nodes, for printing
407	recursive bool    // recursive function or group of mutually recursive functions.
408	opts      []*Node // nodes with .Opt initialized
409	walkgen   uint32
410}
411
412func newEscState(recursive bool) *EscState {
413	e := new(EscState)
414	e.theSink.Op = ONAME
415	e.theSink.Orig = &e.theSink
416	e.theSink.SetClass(PEXTERN)
417	e.theSink.Sym = lookup(".sink")
418	e.nodeEscState(&e.theSink).Loopdepth = -1
419	e.recursive = recursive
420	return e
421}
422
423func (e *EscState) stepWalk(dst, src *Node, why string, parent *EscStep) *EscStep {
424	// TODO: keep a cache of these, mark entry/exit in escwalk to avoid allocation
425	// Or perhaps never mind, since it is disabled unless printing is on.
426	// We may want to revisit this, since the EscStep nodes would make
427	// an excellent replacement for the poorly-separated graph-build/graph-flood
428	// stages.
429	if Debug['m'] == 0 {
430		return nil
431	}
432	return &EscStep{src: src, dst: dst, why: why, parent: parent}
433}
434
435func (e *EscState) stepAssign(step *EscStep, dst, src *Node, why string) *EscStep {
436	if Debug['m'] == 0 {
437		return nil
438	}
439	if step != nil { // Caller may have known better.
440		if step.why == "" {
441			step.why = why
442		}
443		if step.dst == nil {
444			step.dst = dst
445		}
446		if step.src == nil {
447			step.src = src
448		}
449		return step
450	}
451	return &EscStep{src: src, dst: dst, why: why}
452}
453
454func (e *EscState) stepAssignWhere(dst, src *Node, why string, where *Node) *EscStep {
455	if Debug['m'] == 0 {
456		return nil
457	}
458	return &EscStep{src: src, dst: dst, why: why, where: where}
459}
460
461// funcSym returns fn.Func.Nname.Sym if no nils are encountered along the way.
462func funcSym(fn *Node) *types.Sym {
463	if fn == nil || fn.Func.Nname == nil {
464		return nil
465	}
466	return fn.Func.Nname.Sym
467}
468
469// curfnSym returns n.Curfn.Nname.Sym if no nils are encountered along the way.
470func (e *EscState) curfnSym(n *Node) *types.Sym {
471	nE := e.nodeEscState(n)
472	return funcSym(nE.Curfn)
473}
474
475func escAnalyze(all []*Node, recursive bool) {
476	e := newEscState(recursive)
477
478	for _, n := range all {
479		if n.Op == ODCLFUNC {
480			n.Esc = EscFuncPlanned
481			if Debug['m'] > 3 {
482				Dump("escAnalyze", n)
483			}
484
485		}
486	}
487
488	// flow-analyze functions
489	for _, n := range all {
490		if n.Op == ODCLFUNC {
491			e.escfunc(n)
492		}
493	}
494
495	// print("escapes: %d e.dsts, %d edges\n", e.dstcount, e.edgecount);
496
497	// visit the upstream of each dst, mark address nodes with
498	// addrescapes, mark parameters unsafe
499	escapes := make([]uint16, len(e.dsts))
500	for i, n := range e.dsts {
501		escapes[i] = n.Esc
502	}
503	for _, n := range e.dsts {
504		e.escflood(n)
505	}
506	for {
507		done := true
508		for i, n := range e.dsts {
509			if n.Esc != escapes[i] {
510				done = false
511				if Debug['m'] > 2 {
512					Warnl(n.Pos, "Reflooding %v %S", e.curfnSym(n), n)
513				}
514				escapes[i] = n.Esc
515				e.escflood(n)
516			}
517		}
518		if done {
519			break
520		}
521	}
522
523	// for all top level functions, tag the typenodes corresponding to the param nodes
524	for _, n := range all {
525		if n.Op == ODCLFUNC {
526			e.esctag(n)
527		}
528	}
529
530	if Debug['m'] != 0 {
531		for _, n := range e.noesc {
532			if n.Esc == EscNone {
533				Warnl(n.Pos, "%v %S does not escape", e.curfnSym(n), n)
534			}
535		}
536	}
537
538	for _, x := range e.opts {
539		x.SetOpt(nil)
540	}
541}
542
543func (e *EscState) escfunc(fn *Node) {
544	//	print("escfunc %N %s\n", fn.Func.Nname, e.recursive?"(recursive)":"");
545	if fn.Esc != EscFuncPlanned {
546		Fatalf("repeat escfunc %v", fn.Func.Nname)
547	}
548	fn.Esc = EscFuncStarted
549
550	saveld := e.loopdepth
551	e.loopdepth = 1
552	savefn := Curfn
553	Curfn = fn
554
555	for _, ln := range Curfn.Func.Dcl {
556		if ln.Op != ONAME {
557			continue
558		}
559		lnE := e.nodeEscState(ln)
560		switch ln.Class() {
561		// out params are in a loopdepth between the sink and all local variables
562		case PPARAMOUT:
563			lnE.Loopdepth = 0
564
565		case PPARAM:
566			lnE.Loopdepth = 1
567			if ln.Type != nil && !types.Haspointers(ln.Type) {
568				break
569			}
570			if Curfn.Nbody.Len() == 0 && !Curfn.Noescape() {
571				ln.Esc = EscHeap
572			} else {
573				ln.Esc = EscNone // prime for escflood later
574			}
575			e.noesc = append(e.noesc, ln)
576		}
577	}
578
579	// in a mutually recursive group we lose track of the return values
580	if e.recursive {
581		for _, ln := range Curfn.Func.Dcl {
582			if ln.Op == ONAME && ln.Class() == PPARAMOUT {
583				e.escflows(&e.theSink, ln, e.stepAssign(nil, ln, ln, "returned from recursive function"))
584			}
585		}
586	}
587
588	e.escloopdepthlist(Curfn.Nbody)
589	e.esclist(Curfn.Nbody, Curfn)
590	Curfn = savefn
591	e.loopdepth = saveld
592}
593
594// Mark labels that have no backjumps to them as not increasing e.loopdepth.
595// Walk hasn't generated (goto|label).Left.Sym.Label yet, so we'll cheat
596// and set it to one of the following two. Then in esc we'll clear it again.
597var (
598	looping    Node
599	nonlooping Node
600)
601
602func (e *EscState) escloopdepthlist(l Nodes) {
603	for _, n := range l.Slice() {
604		e.escloopdepth(n)
605	}
606}
607
608func (e *EscState) escloopdepth(n *Node) {
609	if n == nil {
610		return
611	}
612
613	e.escloopdepthlist(n.Ninit)
614
615	switch n.Op {
616	case OLABEL:
617		if n.Left == nil || n.Left.Sym == nil {
618			Fatalf("esc:label without label: %+v", n)
619		}
620
621		// Walk will complain about this label being already defined, but that's not until
622		// after escape analysis. in the future, maybe pull label & goto analysis out of walk and put before esc
623		// if(n.Left.Sym.Label != nil)
624		//	fatal("escape analysis messed up analyzing label: %+N", n);
625		n.Left.Sym.Label = asTypesNode(&nonlooping)
626
627	case OGOTO:
628		if n.Left == nil || n.Left.Sym == nil {
629			Fatalf("esc:goto without label: %+v", n)
630		}
631
632		// If we come past one that's uninitialized, this must be a (harmless) forward jump
633		// but if it's set to nonlooping the label must have preceded this goto.
634		if asNode(n.Left.Sym.Label) == &nonlooping {
635			n.Left.Sym.Label = asTypesNode(&looping)
636		}
637	}
638
639	e.escloopdepth(n.Left)
640	e.escloopdepth(n.Right)
641	e.escloopdepthlist(n.List)
642	e.escloopdepthlist(n.Nbody)
643	e.escloopdepthlist(n.Rlist)
644}
645
646func (e *EscState) esclist(l Nodes, parent *Node) {
647	for _, n := range l.Slice() {
648		e.esc(n, parent)
649	}
650}
651
652func (e *EscState) esc(n *Node, parent *Node) {
653	if n == nil {
654		return
655	}
656
657	lno := setlineno(n)
658
659	// ninit logically runs at a different loopdepth than the rest of the for loop.
660	e.esclist(n.Ninit, n)
661
662	if n.Op == OFOR || n.Op == OFORUNTIL || n.Op == ORANGE {
663		e.loopdepth++
664	}
665
666	// type switch variables have no ODCL.
667	// process type switch as declaration.
668	// must happen before processing of switch body,
669	// so before recursion.
670	if n.Op == OSWITCH && n.Left != nil && n.Left.Op == OTYPESW {
671		for _, cas := range n.List.Slice() { // cases
672			// it.N().Rlist is the variable per case
673			if cas.Rlist.Len() != 0 {
674				e.nodeEscState(cas.Rlist.First()).Loopdepth = e.loopdepth
675			}
676		}
677	}
678
679	// Big stuff escapes unconditionally
680	// "Big" conditions that were scattered around in walk have been gathered here
681	if n.Esc != EscHeap && n.Type != nil &&
682		(n.Type.Width > MaxStackVarSize ||
683			(n.Op == ONEW || n.Op == OPTRLIT) && n.Type.Elem().Width >= 1<<16 ||
684			n.Op == OMAKESLICE && !isSmallMakeSlice(n)) {
685		if Debug['m'] > 2 {
686			Warnl(n.Pos, "%v is too large for stack", n)
687		}
688		n.Esc = EscHeap
689		addrescapes(n)
690		e.escassignSinkWhy(n, n, "too large for stack") // TODO category: tooLarge
691	}
692
693	e.esc(n.Left, n)
694	e.esc(n.Right, n)
695	e.esclist(n.Nbody, n)
696	e.esclist(n.List, n)
697	e.esclist(n.Rlist, n)
698
699	if n.Op == OFOR || n.Op == OFORUNTIL || n.Op == ORANGE {
700		e.loopdepth--
701	}
702
703	if Debug['m'] > 2 {
704		fmt.Printf("%v:[%d] %v esc: %v\n", linestr(lineno), e.loopdepth, funcSym(Curfn), n)
705	}
706
707	switch n.Op {
708	// Record loop depth at declaration.
709	case ODCL:
710		if n.Left != nil {
711			e.nodeEscState(n.Left).Loopdepth = e.loopdepth
712		}
713
714	case OLABEL:
715		if asNode(n.Left.Sym.Label) == &nonlooping {
716			if Debug['m'] > 2 {
717				fmt.Printf("%v:%v non-looping label\n", linestr(lineno), n)
718			}
719		} else if asNode(n.Left.Sym.Label) == &looping {
720			if Debug['m'] > 2 {
721				fmt.Printf("%v: %v looping label\n", linestr(lineno), n)
722			}
723			e.loopdepth++
724		}
725
726		// See case OLABEL in escloopdepth above
727		// else if(n.Left.Sym.Label == nil)
728		//	fatal("escape analysis missed or messed up a label: %+N", n);
729
730		n.Left.Sym.Label = nil
731
732	case ORANGE:
733		if n.List.Len() >= 2 {
734			// Everything but fixed array is a dereference.
735
736			// If fixed array is really the address of fixed array,
737			// it is also a dereference, because it is implicitly
738			// dereferenced (see #12588)
739			if n.Type.IsArray() &&
740				!(n.Right.Type.IsPtr() && eqtype(n.Right.Type.Elem(), n.Type)) {
741				e.escassignWhyWhere(n.List.Second(), n.Right, "range", n)
742			} else {
743				e.escassignDereference(n.List.Second(), n.Right, e.stepAssignWhere(n.List.Second(), n.Right, "range-deref", n))
744			}
745		}
746
747	case OSWITCH:
748		if n.Left != nil && n.Left.Op == OTYPESW {
749			for _, cas := range n.List.Slice() {
750				// cases
751				// n.Left.Right is the argument of the .(type),
752				// it.N().Rlist is the variable per case
753				if cas.Rlist.Len() != 0 {
754					e.escassignWhyWhere(cas.Rlist.First(), n.Left.Right, "switch case", n)
755				}
756			}
757		}
758
759	// Filter out the following special case.
760	//
761	//	func (b *Buffer) Foo() {
762	//		n, m := ...
763	//		b.buf = b.buf[n:m]
764	//	}
765	//
766	// This assignment is a no-op for escape analysis,
767	// it does not store any new pointers into b that were not already there.
768	// However, without this special case b will escape, because we assign to OIND/ODOTPTR.
769	case OAS, OASOP:
770		if (n.Left.Op == OIND || n.Left.Op == ODOTPTR) && n.Left.Left.Op == ONAME && // dst is ONAME dereference
771			(n.Right.Op == OSLICE || n.Right.Op == OSLICE3 || n.Right.Op == OSLICESTR) && // src is slice operation
772			(n.Right.Left.Op == OIND || n.Right.Left.Op == ODOTPTR) && n.Right.Left.Left.Op == ONAME && // slice is applied to ONAME dereference
773			n.Left.Left == n.Right.Left.Left { // dst and src reference the same base ONAME
774
775			// Here we also assume that the statement will not contain calls,
776			// that is, that order will move any calls to init.
777			// Otherwise base ONAME value could change between the moments
778			// when we evaluate it for dst and for src.
779			//
780			// Note, this optimization does not apply to OSLICEARR,
781			// because it does introduce a new pointer into b that was not already there
782			// (pointer to b itself). After such assignment, if b contents escape,
783			// b escapes as well. If we ignore such OSLICEARR, we will conclude
784			// that b does not escape when b contents do.
785			if Debug['m'] != 0 {
786				Warnl(n.Pos, "%v ignoring self-assignment to %S", e.curfnSym(n), n.Left)
787			}
788
789			break
790		}
791
792		e.escassign(n.Left, n.Right, e.stepAssignWhere(nil, nil, "", n))
793
794	case OAS2: // x,y = a,b
795		if n.List.Len() == n.Rlist.Len() {
796			rs := n.Rlist.Slice()
797			for i, n := range n.List.Slice() {
798				e.escassignWhyWhere(n, rs[i], "assign-pair", n)
799			}
800		}
801
802	case OAS2RECV: // v, ok = <-ch
803		e.escassignWhyWhere(n.List.First(), n.Rlist.First(), "assign-pair-receive", n)
804	case OAS2MAPR: // v, ok = m[k]
805		e.escassignWhyWhere(n.List.First(), n.Rlist.First(), "assign-pair-mapr", n)
806	case OAS2DOTTYPE: // v, ok = x.(type)
807		e.escassignWhyWhere(n.List.First(), n.Rlist.First(), "assign-pair-dot-type", n)
808
809	case OSEND: // ch <- x
810		e.escassignSinkWhy(n, n.Right, "send")
811
812	case ODEFER:
813		if e.loopdepth == 1 { // top level
814			break
815		}
816		// arguments leak out of scope
817		// TODO: leak to a dummy node instead
818		// defer f(x) - f and x escape
819		e.escassignSinkWhy(n, n.Left.Left, "defer func")
820		e.escassignSinkWhy(n, n.Left.Right, "defer func ...") // ODDDARG for call
821		for _, arg := range n.Left.List.Slice() {
822			e.escassignSinkWhy(n, arg, "defer func arg")
823		}
824
825	case OPROC:
826		// go f(x) - f and x escape
827		e.escassignSinkWhy(n, n.Left.Left, "go func")
828		e.escassignSinkWhy(n, n.Left.Right, "go func ...") // ODDDARG for call
829		for _, arg := range n.Left.List.Slice() {
830			e.escassignSinkWhy(n, arg, "go func arg")
831		}
832
833	case OCALLMETH, OCALLFUNC, OCALLINTER:
834		e.esccall(n, parent)
835
836		// esccall already done on n.Rlist.First(). tie it's Retval to n.List
837	case OAS2FUNC: // x,y = f()
838		rs := e.nodeEscState(n.Rlist.First()).Retval.Slice()
839		for i, n := range n.List.Slice() {
840			if i >= len(rs) {
841				break
842			}
843			e.escassignWhyWhere(n, rs[i], "assign-pair-func-call", n)
844		}
845		if n.List.Len() != len(rs) {
846			Fatalf("esc oas2func")
847		}
848
849	case ORETURN:
850		retList := n.List
851		if retList.Len() == 1 && Curfn.Type.Results().NumFields() > 1 {
852			// OAS2FUNC in disguise
853			// esccall already done on n.List.First()
854			// tie e.nodeEscState(n.List.First()).Retval to Curfn.Func.Dcl PPARAMOUT's
855			retList = e.nodeEscState(n.List.First()).Retval
856		}
857
858		i := 0
859		for _, lrn := range Curfn.Func.Dcl {
860			if i >= retList.Len() {
861				break
862			}
863			if lrn.Op != ONAME || lrn.Class() != PPARAMOUT {
864				continue
865			}
866			e.escassignWhyWhere(lrn, retList.Index(i), "return", n)
867			i++
868		}
869
870		if i < retList.Len() {
871			Fatalf("esc return list")
872		}
873
874		// Argument could leak through recover.
875	case OPANIC:
876		e.escassignSinkWhy(n, n.Left, "panic")
877
878	case OAPPEND:
879		if !n.Isddd() {
880			for _, nn := range n.List.Slice()[1:] {
881				e.escassignSinkWhy(n, nn, "appended to slice") // lose track of assign to dereference
882			}
883		} else {
884			// append(slice1, slice2...) -- slice2 itself does not escape, but contents do.
885			slice2 := n.List.Second()
886			e.escassignDereference(&e.theSink, slice2, e.stepAssignWhere(n, slice2, "appended slice...", n)) // lose track of assign of dereference
887			if Debug['m'] > 3 {
888				Warnl(n.Pos, "%v special treatment of append(slice1, slice2...) %S", e.curfnSym(n), n)
889			}
890		}
891		e.escassignDereference(&e.theSink, n.List.First(), e.stepAssignWhere(n, n.List.First(), "appendee slice", n)) // The original elements are now leaked, too
892
893	case OCOPY:
894		e.escassignDereference(&e.theSink, n.Right, e.stepAssignWhere(n, n.Right, "copied slice", n)) // lose track of assign of dereference
895
896	case OCONV, OCONVNOP:
897		e.escassignWhyWhere(n, n.Left, "converted", n)
898
899	case OCONVIFACE:
900		e.track(n)
901		e.escassignWhyWhere(n, n.Left, "interface-converted", n)
902
903	case OARRAYLIT:
904		// Link values to array
905		for _, elt := range n.List.Slice() {
906			if elt.Op == OKEY {
907				elt = elt.Right
908			}
909			e.escassign(n, elt, e.stepAssignWhere(n, elt, "array literal element", n))
910		}
911
912	case OSLICELIT:
913		// Slice is not leaked until proven otherwise
914		e.track(n)
915		// Link values to slice
916		for _, elt := range n.List.Slice() {
917			if elt.Op == OKEY {
918				elt = elt.Right
919			}
920			e.escassign(n, elt, e.stepAssignWhere(n, elt, "slice literal element", n))
921		}
922
923		// Link values to struct.
924	case OSTRUCTLIT:
925		for _, elt := range n.List.Slice() {
926			e.escassignWhyWhere(n, elt.Left, "struct literal element", n)
927		}
928
929	case OPTRLIT:
930		e.track(n)
931
932		// Link OSTRUCTLIT to OPTRLIT; if OPTRLIT escapes, OSTRUCTLIT elements do too.
933		e.escassignWhyWhere(n, n.Left, "pointer literal [assign]", n)
934
935	case OCALLPART:
936		e.track(n)
937
938		// Contents make it to memory, lose track.
939		e.escassignSinkWhy(n, n.Left, "call part")
940
941	case OMAPLIT:
942		e.track(n)
943		// Keys and values make it to memory, lose track.
944		for _, elt := range n.List.Slice() {
945			e.escassignSinkWhy(n, elt.Left, "map literal key")
946			e.escassignSinkWhy(n, elt.Right, "map literal value")
947		}
948
949	case OCLOSURE:
950		// Link addresses of captured variables to closure.
951		for _, v := range n.Func.Cvars.Slice() {
952			if v.Op == OXXX { // unnamed out argument; see dcl.go:/^funcargs
953				continue
954			}
955			a := v.Name.Defn
956			if !v.Name.Byval() {
957				a = nod(OADDR, a, nil)
958				a.Pos = v.Pos
959				e.nodeEscState(a).Loopdepth = e.loopdepth
960				a = typecheck(a, Erv)
961			}
962
963			e.escassignWhyWhere(n, a, "captured by a closure", n)
964		}
965		fallthrough
966
967	case OMAKECHAN,
968		OMAKEMAP,
969		OMAKESLICE,
970		ONEW,
971		OARRAYRUNESTR,
972		OARRAYBYTESTR,
973		OSTRARRAYRUNE,
974		OSTRARRAYBYTE,
975		ORUNESTR:
976		e.track(n)
977
978	case OADDSTR:
979		e.track(n)
980		// Arguments of OADDSTR do not escape.
981
982	case OADDR:
983		// current loop depth is an upper bound on actual loop depth
984		// of addressed value.
985		e.track(n)
986
987		// for &x, use loop depth of x if known.
988		// it should always be known, but if not, be conservative
989		// and keep the current loop depth.
990		if n.Left.Op == ONAME {
991			switch n.Left.Class() {
992			case PAUTO:
993				nE := e.nodeEscState(n)
994				leftE := e.nodeEscState(n.Left)
995				if leftE.Loopdepth != 0 {
996					nE.Loopdepth = leftE.Loopdepth
997				}
998
999			// PPARAM is loop depth 1 always.
1000			// PPARAMOUT is loop depth 0 for writes
1001			// but considered loop depth 1 for address-of,
1002			// so that writing the address of one result
1003			// to another (or the same) result makes the
1004			// first result move to the heap.
1005			case PPARAM, PPARAMOUT:
1006				nE := e.nodeEscState(n)
1007				nE.Loopdepth = 1
1008			}
1009		}
1010	}
1011
1012	lineno = lno
1013}
1014
1015// escassignWhyWhere bundles a common case of
1016// escassign(e, dst, src, e.stepAssignWhere(dst, src, reason, where))
1017func (e *EscState) escassignWhyWhere(dst, src *Node, reason string, where *Node) {
1018	var step *EscStep
1019	if Debug['m'] != 0 {
1020		step = e.stepAssignWhere(dst, src, reason, where)
1021	}
1022	e.escassign(dst, src, step)
1023}
1024
1025// escassignSinkWhy bundles a common case of
1026// escassign(e, &e.theSink, src, e.stepAssign(nil, dst, src, reason))
1027func (e *EscState) escassignSinkWhy(dst, src *Node, reason string) {
1028	var step *EscStep
1029	if Debug['m'] != 0 {
1030		step = e.stepAssign(nil, dst, src, reason)
1031	}
1032	e.escassign(&e.theSink, src, step)
1033}
1034
1035// escassignSinkWhyWhere is escassignSinkWhy but includes a call site
1036// for accurate location reporting.
1037func (e *EscState) escassignSinkWhyWhere(dst, src *Node, reason string, call *Node) {
1038	var step *EscStep
1039	if Debug['m'] != 0 {
1040		step = e.stepAssignWhere(dst, src, reason, call)
1041	}
1042	e.escassign(&e.theSink, src, step)
1043}
1044
1045// Assert that expr somehow gets assigned to dst, if non nil.  for
1046// dst==nil, any name node expr still must be marked as being
1047// evaluated in curfn.	For expr==nil, dst must still be examined for
1048// evaluations inside it (e.g *f(x) = y)
1049func (e *EscState) escassign(dst, src *Node, step *EscStep) {
1050	if isblank(dst) || dst == nil || src == nil || src.Op == ONONAME || src.Op == OXXX {
1051		return
1052	}
1053
1054	if Debug['m'] > 2 {
1055		fmt.Printf("%v:[%d] %v escassign: %S(%0j)[%v] = %S(%0j)[%v]\n",
1056			linestr(lineno), e.loopdepth, funcSym(Curfn),
1057			dst, dst, dst.Op,
1058			src, src, src.Op)
1059	}
1060
1061	setlineno(dst)
1062
1063	originalDst := dst
1064	dstwhy := "assigned"
1065
1066	// Analyze lhs of assignment.
1067	// Replace dst with &e.theSink if we can't track it.
1068	switch dst.Op {
1069	default:
1070		Dump("dst", dst)
1071		Fatalf("escassign: unexpected dst")
1072
1073	case OARRAYLIT,
1074		OSLICELIT,
1075		OCLOSURE,
1076		OCONV,
1077		OCONVIFACE,
1078		OCONVNOP,
1079		OMAPLIT,
1080		OSTRUCTLIT,
1081		OPTRLIT,
1082		ODDDARG,
1083		OCALLPART:
1084
1085	case ONAME:
1086		if dst.Class() == PEXTERN {
1087			dstwhy = "assigned to top level variable"
1088			dst = &e.theSink
1089		}
1090
1091	case ODOT: // treat "dst.x = src" as "dst = src"
1092		e.escassign(dst.Left, src, e.stepAssign(step, originalDst, src, "dot-equals"))
1093		return
1094
1095	case OINDEX:
1096		if dst.Left.Type.IsArray() {
1097			e.escassign(dst.Left, src, e.stepAssign(step, originalDst, src, "array-element-equals"))
1098			return
1099		}
1100
1101		dstwhy = "slice-element-equals"
1102		dst = &e.theSink // lose track of dereference
1103
1104	case OIND:
1105		dstwhy = "star-equals"
1106		dst = &e.theSink // lose track of dereference
1107
1108	case ODOTPTR:
1109		dstwhy = "star-dot-equals"
1110		dst = &e.theSink // lose track of dereference
1111
1112		// lose track of key and value
1113	case OINDEXMAP:
1114		e.escassign(&e.theSink, dst.Right, e.stepAssign(nil, originalDst, src, "key of map put"))
1115		dstwhy = "value of map put"
1116		dst = &e.theSink
1117	}
1118
1119	lno := setlineno(src)
1120	e.pdepth++
1121
1122	switch src.Op {
1123	case OADDR, // dst = &x
1124		OIND,    // dst = *x
1125		ODOTPTR, // dst = (*x).f
1126		ONAME,
1127		ODDDARG,
1128		OPTRLIT,
1129		OARRAYLIT,
1130		OSLICELIT,
1131		OMAPLIT,
1132		OSTRUCTLIT,
1133		OMAKECHAN,
1134		OMAKEMAP,
1135		OMAKESLICE,
1136		OARRAYRUNESTR,
1137		OARRAYBYTESTR,
1138		OSTRARRAYRUNE,
1139		OSTRARRAYBYTE,
1140		OADDSTR,
1141		ONEW,
1142		OCALLPART,
1143		ORUNESTR,
1144		OCONVIFACE:
1145		e.escflows(dst, src, e.stepAssign(step, originalDst, src, dstwhy))
1146
1147	case OCLOSURE:
1148		// OCLOSURE is lowered to OPTRLIT,
1149		// insert OADDR to account for the additional indirection.
1150		a := nod(OADDR, src, nil)
1151		a.Pos = src.Pos
1152		e.nodeEscState(a).Loopdepth = e.nodeEscState(src).Loopdepth
1153		a.Type = types.NewPtr(src.Type)
1154		e.escflows(dst, a, e.stepAssign(nil, originalDst, src, dstwhy))
1155
1156	// Flowing multiple returns to a single dst happens when
1157	// analyzing "go f(g())": here g() flows to sink (issue 4529).
1158	case OCALLMETH, OCALLFUNC, OCALLINTER:
1159		for _, n := range e.nodeEscState(src).Retval.Slice() {
1160			e.escflows(dst, n, e.stepAssign(nil, originalDst, n, dstwhy))
1161		}
1162
1163		// A non-pointer escaping from a struct does not concern us.
1164	case ODOT:
1165		if src.Type != nil && !types.Haspointers(src.Type) {
1166			break
1167		}
1168		fallthrough
1169
1170		// Conversions, field access, slice all preserve the input value.
1171	case OCONV,
1172		OCONVNOP,
1173		ODOTMETH,
1174		// treat recv.meth as a value with recv in it, only happens in ODEFER and OPROC
1175		// iface.method already leaks iface in esccall, no need to put in extra ODOTINTER edge here
1176		OSLICE,
1177		OSLICE3,
1178		OSLICEARR,
1179		OSLICE3ARR,
1180		OSLICESTR:
1181		// Conversions, field access, slice all preserve the input value.
1182		e.escassign(dst, src.Left, e.stepAssign(step, originalDst, src, dstwhy))
1183
1184	case ODOTTYPE,
1185		ODOTTYPE2:
1186		if src.Type != nil && !types.Haspointers(src.Type) {
1187			break
1188		}
1189		e.escassign(dst, src.Left, e.stepAssign(step, originalDst, src, dstwhy))
1190
1191	case OAPPEND:
1192		// Append returns first argument.
1193		// Subsequent arguments are already leaked because they are operands to append.
1194		e.escassign(dst, src.List.First(), e.stepAssign(step, dst, src.List.First(), dstwhy))
1195
1196	case OINDEX:
1197		// Index of array preserves input value.
1198		if src.Left.Type.IsArray() {
1199			e.escassign(dst, src.Left, e.stepAssign(step, originalDst, src, dstwhy))
1200		} else {
1201			e.escflows(dst, src, e.stepAssign(step, originalDst, src, dstwhy))
1202		}
1203
1204	// Might be pointer arithmetic, in which case
1205	// the operands flow into the result.
1206	// TODO(rsc): Decide what the story is here. This is unsettling.
1207	case OADD,
1208		OSUB,
1209		OOR,
1210		OXOR,
1211		OMUL,
1212		ODIV,
1213		OMOD,
1214		OLSH,
1215		ORSH,
1216		OAND,
1217		OANDNOT,
1218		OPLUS,
1219		OMINUS,
1220		OCOM:
1221		e.escassign(dst, src.Left, e.stepAssign(step, originalDst, src, dstwhy))
1222
1223		e.escassign(dst, src.Right, e.stepAssign(step, originalDst, src, dstwhy))
1224	}
1225
1226	e.pdepth--
1227	lineno = lno
1228}
1229
1230// Common case for escapes is 16 bits 000000000xxxEEEE
1231// where commonest cases for xxx encoding in-to-out pointer
1232//  flow are 000, 001, 010, 011  and EEEE is computed Esc bits.
1233// Note width of xxx depends on value of constant
1234// bitsPerOutputInTag -- expect 2 or 3, so in practice the
1235// tag cache array is 64 or 128 long. Some entries will
1236// never be populated.
1237var tags [1 << (bitsPerOutputInTag + EscReturnBits)]string
1238
1239// mktag returns the string representation for an escape analysis tag.
1240func mktag(mask int) string {
1241	switch mask & EscMask {
1242	case EscNone, EscReturn:
1243	default:
1244		Fatalf("escape mktag")
1245	}
1246
1247	if mask < len(tags) && tags[mask] != "" {
1248		return tags[mask]
1249	}
1250
1251	s := fmt.Sprintf("esc:0x%x", mask)
1252	if mask < len(tags) {
1253		tags[mask] = s
1254	}
1255	return s
1256}
1257
1258// parsetag decodes an escape analysis tag and returns the esc value.
1259func parsetag(note string) uint16 {
1260	if !strings.HasPrefix(note, "esc:") {
1261		return EscUnknown
1262	}
1263	n, _ := strconv.ParseInt(note[4:], 0, 0)
1264	em := uint16(n)
1265	if em == 0 {
1266		return EscNone
1267	}
1268	return em
1269}
1270
1271// describeEscape returns a string describing the escape tag.
1272// The result is either one of {EscUnknown, EscNone, EscHeap} which all have no further annotation
1273// or a description of parameter flow, which takes the form of an optional "contentToHeap"
1274// indicating that the content of this parameter is leaked to the heap, followed by a sequence
1275// of level encodings separated by spaces, one for each parameter, where _ means no flow,
1276// = means direct flow, and N asterisks (*) encodes content (obtained by indirection) flow.
1277// e.g., "contentToHeap _ =" means that a parameter's content (one or more dereferences)
1278// escapes to the heap, the parameter does not leak to the first output, but does leak directly
1279// to the second output (and if there are more than two outputs, there is no flow to those.)
1280func describeEscape(em uint16) string {
1281	var s string
1282	if em&EscMask == EscUnknown {
1283		s = "EscUnknown"
1284	}
1285	if em&EscMask == EscNone {
1286		s = "EscNone"
1287	}
1288	if em&EscMask == EscHeap {
1289		s = "EscHeap"
1290	}
1291	if em&EscMask == EscReturn {
1292		s = "EscReturn"
1293	}
1294	if em&EscContentEscapes != 0 {
1295		if s != "" {
1296			s += " "
1297		}
1298		s += "contentToHeap"
1299	}
1300	for em >>= EscReturnBits; em != 0; em = em >> bitsPerOutputInTag {
1301		// See encoding description above
1302		if s != "" {
1303			s += " "
1304		}
1305		switch embits := em & bitsMaskForTag; embits {
1306		case 0:
1307			s += "_"
1308		case 1:
1309			s += "="
1310		default:
1311			for i := uint16(0); i < embits-1; i++ {
1312				s += "*"
1313			}
1314		}
1315
1316	}
1317	return s
1318}
1319
1320// escassignfromtag models the input-to-output assignment flow of one of a function
1321// calls arguments, where the flow is encoded in "note".
1322func (e *EscState) escassignfromtag(note string, dsts Nodes, src, call *Node) uint16 {
1323	em := parsetag(note)
1324	if src.Op == OLITERAL {
1325		return em
1326	}
1327
1328	if Debug['m'] > 3 {
1329		fmt.Printf("%v::assignfromtag:: src=%S, em=%s\n",
1330			linestr(lineno), src, describeEscape(em))
1331	}
1332
1333	if em == EscUnknown {
1334		e.escassignSinkWhyWhere(src, src, "passed to call[argument escapes]", call)
1335		return em
1336	}
1337
1338	if em == EscNone {
1339		return em
1340	}
1341
1342	// If content inside parameter (reached via indirection)
1343	// escapes to heap, mark as such.
1344	if em&EscContentEscapes != 0 {
1345		e.escassign(&e.theSink, e.addDereference(src), e.stepAssignWhere(src, src, "passed to call[argument content escapes]", call))
1346	}
1347
1348	em0 := em
1349	dstsi := 0
1350	for em >>= EscReturnBits; em != 0 && dstsi < dsts.Len(); em = em >> bitsPerOutputInTag {
1351		// Prefer the lowest-level path to the reference (for escape purposes).
1352		// Two-bit encoding (for example. 1, 3, and 4 bits are other options)
1353		//  01 = 0-level
1354		//  10 = 1-level, (content escapes),
1355		//  11 = 2-level, (content of content escapes),
1356		embits := em & bitsMaskForTag
1357		if embits > 0 {
1358			n := src
1359			for i := uint16(0); i < embits-1; i++ {
1360				n = e.addDereference(n) // encode level>0 as indirections
1361			}
1362			e.escassign(dsts.Index(dstsi), n, e.stepAssignWhere(dsts.Index(dstsi), src, "passed-to-and-returned-from-call", call))
1363		}
1364		dstsi++
1365	}
1366	// If there are too many outputs to fit in the tag,
1367	// that is handled at the encoding end as EscHeap,
1368	// so there is no need to check here.
1369
1370	if em != 0 && dstsi >= dsts.Len() {
1371		Fatalf("corrupt esc tag %q or messed up escretval list\n", note)
1372	}
1373	return em0
1374}
1375
1376func (e *EscState) escassignDereference(dst *Node, src *Node, step *EscStep) {
1377	if src.Op == OLITERAL {
1378		return
1379	}
1380	e.escassign(dst, e.addDereference(src), step)
1381}
1382
1383// addDereference constructs a suitable OIND note applied to src.
1384// Because this is for purposes of escape accounting, not execution,
1385// some semantically dubious node combinations are (currently) possible.
1386func (e *EscState) addDereference(n *Node) *Node {
1387	ind := nod(OIND, n, nil)
1388	e.nodeEscState(ind).Loopdepth = e.nodeEscState(n).Loopdepth
1389	ind.Pos = n.Pos
1390	t := n.Type
1391	if t.IsKind(types.Tptr) {
1392		// This should model our own sloppy use of OIND to encode
1393		// decreasing levels of indirection; i.e., "indirecting" an array
1394		// might yield the type of an element. To be enhanced...
1395		t = t.Elem()
1396	}
1397	ind.Type = t
1398	return ind
1399}
1400
1401// escNoteOutputParamFlow encodes maxEncodedLevel/.../1/0-level flow to the vargen'th parameter.
1402// Levels greater than maxEncodedLevel are replaced with maxEncodedLevel.
1403// If the encoding cannot describe the modified input level and output number, then EscHeap is returned.
1404func escNoteOutputParamFlow(e uint16, vargen int32, level Level) uint16 {
1405	// Flow+level is encoded in two bits.
1406	// 00 = not flow, xx = level+1 for 0 <= level <= maxEncodedLevel
1407	// 16 bits for Esc allows 6x2bits or 4x3bits or 3x4bits if additional information would be useful.
1408	if level.int() <= 0 && level.guaranteedDereference() > 0 {
1409		return escMax(e|EscContentEscapes, EscNone) // At least one deref, thus only content.
1410	}
1411	if level.int() < 0 {
1412		return EscHeap
1413	}
1414	if level.int() > maxEncodedLevel {
1415		// Cannot encode larger values than maxEncodedLevel.
1416		level = levelFrom(maxEncodedLevel)
1417	}
1418	encoded := uint16(level.int() + 1)
1419
1420	shift := uint(bitsPerOutputInTag*(vargen-1) + EscReturnBits)
1421	old := (e >> shift) & bitsMaskForTag
1422	if old == 0 || encoded != 0 && encoded < old {
1423		old = encoded
1424	}
1425
1426	encodedFlow := old << shift
1427	if (encodedFlow>>shift)&bitsMaskForTag != old {
1428		// Encoding failure defaults to heap.
1429		return EscHeap
1430	}
1431
1432	return (e &^ (bitsMaskForTag << shift)) | encodedFlow
1433}
1434
1435func (e *EscState) initEscRetval(call *Node, fntype *types.Type) {
1436	cE := e.nodeEscState(call)
1437	cE.Retval.Set(nil) // Suspect this is not nil for indirect calls.
1438	for i, f := range fntype.Results().Fields().Slice() {
1439		buf := fmt.Sprintf(".out%d", i)
1440		ret := newname(lookup(buf))
1441		ret.SetAddable(false) // TODO(mdempsky): Seems suspicious.
1442		ret.Type = f.Type
1443		ret.SetClass(PAUTO)
1444		ret.Name.Curfn = Curfn
1445		e.nodeEscState(ret).Loopdepth = e.loopdepth
1446		ret.Name.SetUsed(true)
1447		ret.Pos = call.Pos
1448		cE.Retval.Append(ret)
1449	}
1450}
1451
1452// This is a bit messier than fortunate, pulled out of esc's big
1453// switch for clarity. We either have the paramnodes, which may be
1454// connected to other things through flows or we have the parameter type
1455// nodes, which may be marked "noescape". Navigating the ast is slightly
1456// different for methods vs plain functions and for imported vs
1457// this-package
1458func (e *EscState) esccall(call *Node, parent *Node) {
1459	var fntype *types.Type
1460	var indirect bool
1461	var fn *Node
1462	switch call.Op {
1463	default:
1464		Fatalf("esccall")
1465
1466	case OCALLFUNC:
1467		fn = call.Left
1468		fntype = fn.Type
1469		indirect = fn.Op != ONAME || fn.Class() != PFUNC
1470
1471	case OCALLMETH:
1472		fn = asNode(call.Left.Sym.Def)
1473		if fn != nil {
1474			fntype = fn.Type
1475		} else {
1476			fntype = call.Left.Type
1477		}
1478
1479	case OCALLINTER:
1480		fntype = call.Left.Type
1481		indirect = true
1482	}
1483
1484	argList := call.List
1485	if argList.Len() == 1 {
1486		arg := argList.First()
1487		if arg.Type.IsFuncArgStruct() { // f(g())
1488			argList = e.nodeEscState(arg).Retval
1489		}
1490	}
1491
1492	args := argList.Slice()
1493
1494	if indirect {
1495		// We know nothing!
1496		// Leak all the parameters
1497		for _, arg := range args {
1498			e.escassignSinkWhy(call, arg, "parameter to indirect call")
1499			if Debug['m'] > 3 {
1500				fmt.Printf("%v::esccall:: indirect call <- %S, untracked\n", linestr(lineno), arg)
1501			}
1502		}
1503		// Set up bogus outputs
1504		e.initEscRetval(call, fntype)
1505		// If there is a receiver, it also leaks to heap.
1506		if call.Op != OCALLFUNC {
1507			rf := fntype.Recv()
1508			r := call.Left.Left
1509			if types.Haspointers(rf.Type) {
1510				e.escassignSinkWhy(call, r, "receiver in indirect call")
1511			}
1512		} else { // indirect and OCALLFUNC = could be captured variables, too. (#14409)
1513			rets := e.nodeEscState(call).Retval.Slice()
1514			for _, ret := range rets {
1515				e.escassignDereference(ret, fn, e.stepAssignWhere(ret, fn, "captured by called closure", call))
1516			}
1517		}
1518		return
1519	}
1520
1521	cE := e.nodeEscState(call)
1522	if fn != nil && fn.Op == ONAME && fn.Class() == PFUNC &&
1523		fn.Name.Defn != nil && fn.Name.Defn.Nbody.Len() != 0 && fn.Name.Param.Ntype != nil && fn.Name.Defn.Esc < EscFuncTagged {
1524		if Debug['m'] > 3 {
1525			fmt.Printf("%v::esccall:: %S in recursive group\n", linestr(lineno), call)
1526		}
1527
1528		// function in same mutually recursive group. Incorporate into flow graph.
1529		//		print("esc local fn: %N\n", fn.Func.Ntype);
1530		if fn.Name.Defn.Esc == EscFuncUnknown || cE.Retval.Len() != 0 {
1531			Fatalf("graph inconsistency")
1532		}
1533
1534		sawRcvr := false
1535		for _, n := range fn.Name.Defn.Func.Dcl {
1536			switch n.Class() {
1537			case PPARAM:
1538				if call.Op != OCALLFUNC && !sawRcvr {
1539					e.escassignWhyWhere(n, call.Left.Left, "call receiver", call)
1540					sawRcvr = true
1541					continue
1542				}
1543				if len(args) == 0 {
1544					continue
1545				}
1546				arg := args[0]
1547				if n.Isddd() && !call.Isddd() {
1548					// Introduce ODDDARG node to represent ... allocation.
1549					arg = nod(ODDDARG, nil, nil)
1550					arr := types.NewArray(n.Type.Elem(), int64(len(args)))
1551					arg.Type = types.NewPtr(arr) // make pointer so it will be tracked
1552					arg.Pos = call.Pos
1553					e.track(arg)
1554					call.Right = arg
1555				}
1556				e.escassignWhyWhere(n, arg, "arg to recursive call", call) // TODO this message needs help.
1557				if arg != args[0] {
1558					// "..." arguments are untracked
1559					for _, a := range args {
1560						if Debug['m'] > 3 {
1561							fmt.Printf("%v::esccall:: ... <- %S, untracked\n", linestr(lineno), a)
1562						}
1563						e.escassignSinkWhyWhere(arg, a, "... arg to recursive call", call)
1564					}
1565					// No more PPARAM processing, but keep
1566					// going for PPARAMOUT.
1567					args = nil
1568					continue
1569				}
1570				args = args[1:]
1571
1572			case PPARAMOUT:
1573				cE.Retval.Append(n)
1574			}
1575		}
1576
1577		return
1578	}
1579
1580	// Imported or completely analyzed function. Use the escape tags.
1581	if cE.Retval.Len() != 0 {
1582		Fatalf("esc already decorated call %+v\n", call)
1583	}
1584
1585	if Debug['m'] > 3 {
1586		fmt.Printf("%v::esccall:: %S not recursive\n", linestr(lineno), call)
1587	}
1588
1589	// set up out list on this call node with dummy auto ONAMES in the current (calling) function.
1590	e.initEscRetval(call, fntype)
1591
1592	//	print("esc analyzed fn: %#N (%+T) returning (%+H)\n", fn, fntype, e.nodeEscState(call).Retval);
1593
1594	// Receiver.
1595	if call.Op != OCALLFUNC {
1596		rf := fntype.Recv()
1597		r := call.Left.Left
1598		if types.Haspointers(rf.Type) {
1599			e.escassignfromtag(rf.Note, cE.Retval, r, call)
1600		}
1601	}
1602
1603	for i, param := range fntype.Params().FieldSlice() {
1604		note := param.Note
1605		var arg *Node
1606		if param.Isddd() && !call.Isddd() {
1607			rest := args[i:]
1608			if len(rest) == 0 {
1609				break
1610			}
1611
1612			// Introduce ODDDARG node to represent ... allocation.
1613			arg = nod(ODDDARG, nil, nil)
1614			arg.Pos = call.Pos
1615			arr := types.NewArray(param.Type.Elem(), int64(len(rest)))
1616			arg.Type = types.NewPtr(arr) // make pointer so it will be tracked
1617			e.track(arg)
1618			call.Right = arg
1619
1620			// Store arguments into slice for ... arg.
1621			for _, a := range rest {
1622				if Debug['m'] > 3 {
1623					fmt.Printf("%v::esccall:: ... <- %S\n", linestr(lineno), a)
1624				}
1625				if note == uintptrEscapesTag {
1626					e.escassignSinkWhyWhere(arg, a, "arg to uintptrescapes ...", call)
1627				} else {
1628					e.escassignWhyWhere(arg, a, "arg to ...", call)
1629				}
1630			}
1631		} else {
1632			arg = args[i]
1633			if note == uintptrEscapesTag {
1634				e.escassignSinkWhy(arg, arg, "escaping uintptr")
1635			}
1636		}
1637
1638		if types.Haspointers(param.Type) && e.escassignfromtag(note, cE.Retval, arg, call)&EscMask == EscNone && parent.Op != ODEFER && parent.Op != OPROC {
1639			a := arg
1640			for a.Op == OCONVNOP {
1641				a = a.Left
1642			}
1643			switch a.Op {
1644			// The callee has already been analyzed, so its arguments have esc tags.
1645			// The argument is marked as not escaping at all.
1646			// Record that fact so that any temporary used for
1647			// synthesizing this expression can be reclaimed when
1648			// the function returns.
1649			// This 'noescape' is even stronger than the usual esc == EscNone.
1650			// arg.Esc == EscNone means that arg does not escape the current function.
1651			// arg.SetNoescape(true) here means that arg does not escape this statement
1652			// in the current function.
1653			case OCALLPART, OCLOSURE, ODDDARG, OARRAYLIT, OSLICELIT, OPTRLIT, OSTRUCTLIT:
1654				a.SetNoescape(true)
1655			}
1656		}
1657	}
1658}
1659
1660// escflows records the link src->dst in dst, throwing out some quick wins,
1661// and also ensuring that dst is noted as a flow destination.
1662func (e *EscState) escflows(dst, src *Node, why *EscStep) {
1663	if dst == nil || src == nil || dst == src {
1664		return
1665	}
1666
1667	// Don't bother building a graph for scalars.
1668	if src.Type != nil && !types.Haspointers(src.Type) && !isReflectHeaderDataField(src) {
1669		if Debug['m'] > 3 {
1670			fmt.Printf("%v::NOT flows:: %S <- %S\n", linestr(lineno), dst, src)
1671		}
1672		return
1673	}
1674
1675	if Debug['m'] > 3 {
1676		fmt.Printf("%v::flows:: %S <- %S\n", linestr(lineno), dst, src)
1677	}
1678
1679	dstE := e.nodeEscState(dst)
1680	if len(dstE.Flowsrc) == 0 {
1681		e.dsts = append(e.dsts, dst)
1682		e.dstcount++
1683	}
1684
1685	e.edgecount++
1686
1687	if why == nil {
1688		dstE.Flowsrc = append(dstE.Flowsrc, EscStep{src: src})
1689	} else {
1690		starwhy := *why
1691		starwhy.src = src // TODO: need to reconcile this w/ needs of explanations.
1692		dstE.Flowsrc = append(dstE.Flowsrc, starwhy)
1693	}
1694}
1695
1696// Whenever we hit a reference node, the level goes up by one, and whenever
1697// we hit an OADDR, the level goes down by one. as long as we're on a level > 0
1698// finding an OADDR just means we're following the upstream of a dereference,
1699// so this address doesn't leak (yet).
1700// If level == 0, it means the /value/ of this node can reach the root of this flood.
1701// so if this node is an OADDR, its argument should be marked as escaping iff
1702// its currfn/e.loopdepth are different from the flood's root.
1703// Once an object has been moved to the heap, all of its upstream should be considered
1704// escaping to the global scope.
1705func (e *EscState) escflood(dst *Node) {
1706	switch dst.Op {
1707	case ONAME, OCLOSURE:
1708	default:
1709		return
1710	}
1711
1712	dstE := e.nodeEscState(dst)
1713	if Debug['m'] > 2 {
1714		fmt.Printf("\nescflood:%d: dst %S scope:%v[%d]\n", e.walkgen, dst, e.curfnSym(dst), dstE.Loopdepth)
1715	}
1716
1717	for i := range dstE.Flowsrc {
1718		e.walkgen++
1719		s := &dstE.Flowsrc[i]
1720		s.parent = nil
1721		e.escwalk(levelFrom(0), dst, s.src, s)
1722	}
1723}
1724
1725// funcOutputAndInput reports whether dst and src correspond to output and input parameters of the same function.
1726func funcOutputAndInput(dst, src *Node) bool {
1727	// Note if dst is marked as escaping, then "returned" is too weak.
1728	return dst.Op == ONAME && dst.Class() == PPARAMOUT &&
1729		src.Op == ONAME && src.Class() == PPARAM && src.Name.Curfn == dst.Name.Curfn
1730}
1731
1732func (es *EscStep) describe(src *Node) {
1733	if Debug['m'] < 2 {
1734		return
1735	}
1736	step0 := es
1737	for step := step0; step != nil && !step.busy; step = step.parent {
1738		// TODO: We get cycles. Trigger is i = &i (where var i interface{})
1739		step.busy = true
1740		// The trail is a little odd because of how the
1741		// graph is constructed.  The link to the current
1742		// Node is parent.src unless parent is nil in which
1743		// case it is step.dst.
1744		nextDest := step.parent
1745		dst := step.dst
1746		where := step.where
1747		if nextDest != nil {
1748			dst = nextDest.src
1749		}
1750		if where == nil {
1751			where = dst
1752		}
1753		Warnl(src.Pos, "\tfrom %v (%s) at %s", dst, step.why, where.Line())
1754	}
1755	for step := step0; step != nil && step.busy; step = step.parent {
1756		step.busy = false
1757	}
1758}
1759
1760const NOTALOOPDEPTH = -1
1761
1762func (e *EscState) escwalk(level Level, dst *Node, src *Node, step *EscStep) {
1763	e.escwalkBody(level, dst, src, step, NOTALOOPDEPTH)
1764}
1765
1766func (e *EscState) escwalkBody(level Level, dst *Node, src *Node, step *EscStep, extraloopdepth int32) {
1767	if src.Op == OLITERAL {
1768		return
1769	}
1770	srcE := e.nodeEscState(src)
1771	if srcE.Walkgen == e.walkgen {
1772		// Esclevels are vectors, do not compare as integers,
1773		// and must use "min" of old and new to guarantee
1774		// convergence.
1775		level = level.min(srcE.Level)
1776		if level == srcE.Level {
1777			// Have we been here already with an extraloopdepth,
1778			// or is the extraloopdepth provided no improvement on
1779			// what's already been seen?
1780			if srcE.Maxextraloopdepth >= extraloopdepth || srcE.Loopdepth >= extraloopdepth {
1781				return
1782			}
1783			srcE.Maxextraloopdepth = extraloopdepth
1784		}
1785	} else { // srcE.Walkgen < e.walkgen -- first time, reset this.
1786		srcE.Maxextraloopdepth = NOTALOOPDEPTH
1787	}
1788
1789	srcE.Walkgen = e.walkgen
1790	srcE.Level = level
1791	modSrcLoopdepth := srcE.Loopdepth
1792
1793	if extraloopdepth > modSrcLoopdepth {
1794		modSrcLoopdepth = extraloopdepth
1795	}
1796
1797	if Debug['m'] > 2 {
1798		fmt.Printf("escwalk: level:%d depth:%d %.*s op=%v %S(%0j) scope:%v[%d] extraloopdepth=%v\n",
1799			level, e.pdepth, e.pdepth, "\t\t\t\t\t\t\t\t\t\t", src.Op, src, src, e.curfnSym(src), srcE.Loopdepth, extraloopdepth)
1800	}
1801
1802	e.pdepth++
1803
1804	// Input parameter flowing to output parameter?
1805	var leaks bool
1806	var osrcesc uint16 // used to prevent duplicate error messages
1807
1808	dstE := e.nodeEscState(dst)
1809	if funcOutputAndInput(dst, src) && src.Esc&EscMask < EscHeap && dst.Esc != EscHeap {
1810		// This case handles:
1811		// 1. return in
1812		// 2. return &in
1813		// 3. tmp := in; return &tmp
1814		// 4. return *in
1815		if Debug['m'] != 0 {
1816			if Debug['m'] <= 2 {
1817				Warnl(src.Pos, "leaking param: %S to result %v level=%v", src, dst.Sym, level.int())
1818				step.describe(src)
1819			} else {
1820				Warnl(src.Pos, "leaking param: %S to result %v level=%v", src, dst.Sym, level)
1821			}
1822		}
1823		if src.Esc&EscMask != EscReturn {
1824			src.Esc = EscReturn | src.Esc&EscContentEscapes
1825		}
1826		src.Esc = escNoteOutputParamFlow(src.Esc, dst.Name.Vargen, level)
1827		goto recurse
1828	}
1829
1830	// If parameter content escapes to heap, set EscContentEscapes
1831	// Note minor confusion around escape from pointer-to-struct vs escape from struct
1832	if dst.Esc == EscHeap &&
1833		src.Op == ONAME && src.Class() == PPARAM && src.Esc&EscMask < EscHeap &&
1834		level.int() > 0 {
1835		src.Esc = escMax(EscContentEscapes|src.Esc, EscNone)
1836		if Debug['m'] != 0 {
1837			Warnl(src.Pos, "mark escaped content: %S", src)
1838			step.describe(src)
1839		}
1840	}
1841
1842	leaks = level.int() <= 0 && level.guaranteedDereference() <= 0 && dstE.Loopdepth < modSrcLoopdepth
1843	leaks = leaks || level.int() <= 0 && dst.Esc&EscMask == EscHeap
1844
1845	osrcesc = src.Esc
1846	switch src.Op {
1847	case ONAME:
1848		if src.Class() == PPARAM && (leaks || dstE.Loopdepth < 0) && src.Esc&EscMask < EscHeap {
1849			if level.guaranteedDereference() > 0 {
1850				src.Esc = escMax(EscContentEscapes|src.Esc, EscNone)
1851				if Debug['m'] != 0 {
1852					if Debug['m'] <= 2 {
1853						if osrcesc != src.Esc {
1854							Warnl(src.Pos, "leaking param content: %S", src)
1855							step.describe(src)
1856						}
1857					} else {
1858						Warnl(src.Pos, "leaking param content: %S level=%v dst.eld=%v src.eld=%v dst=%S",
1859							src, level, dstE.Loopdepth, modSrcLoopdepth, dst)
1860					}
1861				}
1862			} else {
1863				src.Esc = EscHeap
1864				if Debug['m'] != 0 {
1865					if Debug['m'] <= 2 {
1866						Warnl(src.Pos, "leaking param: %S", src)
1867						step.describe(src)
1868					} else {
1869						Warnl(src.Pos, "leaking param: %S level=%v dst.eld=%v src.eld=%v dst=%S",
1870							src, level, dstE.Loopdepth, modSrcLoopdepth, dst)
1871					}
1872				}
1873			}
1874		}
1875
1876		// Treat a captured closure variable as equivalent to the
1877		// original variable.
1878		if src.IsClosureVar() {
1879			if leaks && Debug['m'] != 0 {
1880				Warnl(src.Pos, "leaking closure reference %S", src)
1881				step.describe(src)
1882			}
1883			e.escwalk(level, dst, src.Name.Defn, e.stepWalk(dst, src.Name.Defn, "closure-var", step))
1884		}
1885
1886	case OPTRLIT, OADDR:
1887		why := "pointer literal"
1888		if src.Op == OADDR {
1889			why = "address-of"
1890		}
1891		if leaks {
1892			src.Esc = EscHeap
1893			if Debug['m'] != 0 && osrcesc != src.Esc {
1894				p := src
1895				if p.Left.Op == OCLOSURE {
1896					p = p.Left // merely to satisfy error messages in tests
1897				}
1898				if Debug['m'] > 2 {
1899					Warnl(src.Pos, "%S escapes to heap, level=%v, dst=%v dst.eld=%v, src.eld=%v",
1900						p, level, dst, dstE.Loopdepth, modSrcLoopdepth)
1901				} else {
1902					Warnl(src.Pos, "%S escapes to heap", p)
1903					step.describe(src)
1904				}
1905			}
1906			addrescapes(src.Left)
1907			e.escwalkBody(level.dec(), dst, src.Left, e.stepWalk(dst, src.Left, why, step), modSrcLoopdepth)
1908			extraloopdepth = modSrcLoopdepth // passes to recursive case, seems likely a no-op
1909		} else {
1910			e.escwalk(level.dec(), dst, src.Left, e.stepWalk(dst, src.Left, why, step))
1911		}
1912
1913	case OAPPEND:
1914		e.escwalk(level, dst, src.List.First(), e.stepWalk(dst, src.List.First(), "append-first-arg", step))
1915
1916	case ODDDARG:
1917		if leaks {
1918			src.Esc = EscHeap
1919			if Debug['m'] != 0 && osrcesc != src.Esc {
1920				Warnl(src.Pos, "%S escapes to heap", src)
1921				step.describe(src)
1922			}
1923			extraloopdepth = modSrcLoopdepth
1924		}
1925		// similar to a slice arraylit and its args.
1926		level = level.dec()
1927
1928	case OSLICELIT:
1929		for _, elt := range src.List.Slice() {
1930			if elt.Op == OKEY {
1931				elt = elt.Right
1932			}
1933			e.escwalk(level.dec(), dst, elt, e.stepWalk(dst, elt, "slice-literal-element", step))
1934		}
1935
1936		fallthrough
1937
1938	case OMAKECHAN,
1939		OMAKEMAP,
1940		OMAKESLICE,
1941		OARRAYRUNESTR,
1942		OARRAYBYTESTR,
1943		OSTRARRAYRUNE,
1944		OSTRARRAYBYTE,
1945		OADDSTR,
1946		OMAPLIT,
1947		ONEW,
1948		OCLOSURE,
1949		OCALLPART,
1950		ORUNESTR,
1951		OCONVIFACE:
1952		if leaks {
1953			src.Esc = EscHeap
1954			if Debug['m'] != 0 && osrcesc != src.Esc {
1955				Warnl(src.Pos, "%S escapes to heap", src)
1956				step.describe(src)
1957			}
1958			extraloopdepth = modSrcLoopdepth
1959		}
1960
1961	case ODOT,
1962		ODOTTYPE:
1963		e.escwalk(level, dst, src.Left, e.stepWalk(dst, src.Left, "dot", step))
1964
1965	case
1966		OSLICE,
1967		OSLICEARR,
1968		OSLICE3,
1969		OSLICE3ARR,
1970		OSLICESTR:
1971		e.escwalk(level, dst, src.Left, e.stepWalk(dst, src.Left, "slice", step))
1972
1973	case OINDEX:
1974		if src.Left.Type.IsArray() {
1975			e.escwalk(level, dst, src.Left, e.stepWalk(dst, src.Left, "fixed-array-index-of", step))
1976			break
1977		}
1978		fallthrough
1979
1980	case ODOTPTR:
1981		e.escwalk(level.inc(), dst, src.Left, e.stepWalk(dst, src.Left, "dot of pointer", step))
1982	case OINDEXMAP:
1983		e.escwalk(level.inc(), dst, src.Left, e.stepWalk(dst, src.Left, "map index", step))
1984	case OIND:
1985		e.escwalk(level.inc(), dst, src.Left, e.stepWalk(dst, src.Left, "indirection", step))
1986
1987	// In this case a link went directly to a call, but should really go
1988	// to the dummy .outN outputs that were created for the call that
1989	// themselves link to the inputs with levels adjusted.
1990	// See e.g. #10466
1991	// This can only happen with functions returning a single result.
1992	case OCALLMETH, OCALLFUNC, OCALLINTER:
1993		if srcE.Retval.Len() != 0 {
1994			if Debug['m'] > 2 {
1995				fmt.Printf("%v:[%d] dst %S escwalk replace src: %S with %S\n",
1996					linestr(lineno), e.loopdepth,
1997					dst, src, srcE.Retval.First())
1998			}
1999			src = srcE.Retval.First()
2000			srcE = e.nodeEscState(src)
2001		}
2002	}
2003
2004recurse:
2005	level = level.copy()
2006
2007	for i := range srcE.Flowsrc {
2008		s := &srcE.Flowsrc[i]
2009		s.parent = step
2010		e.escwalkBody(level, dst, s.src, s, extraloopdepth)
2011		s.parent = nil
2012	}
2013
2014	e.pdepth--
2015}
2016
2017// addrescapes tags node n as having had its address taken
2018// by "increasing" the "value" of n.Esc to EscHeap.
2019// Storage is allocated as necessary to allow the address
2020// to be taken.
2021func addrescapes(n *Node) {
2022	switch n.Op {
2023	default:
2024		// Unexpected Op, probably due to a previous type error. Ignore.
2025
2026	case OIND, ODOTPTR:
2027		// Nothing to do.
2028
2029	case ONAME:
2030		if n == nodfp {
2031			break
2032		}
2033
2034		// if this is a tmpname (PAUTO), it was tagged by tmpname as not escaping.
2035		// on PPARAM it means something different.
2036		if n.Class() == PAUTO && n.Esc == EscNever {
2037			break
2038		}
2039
2040		// If a closure reference escapes, mark the outer variable as escaping.
2041		if n.IsClosureVar() {
2042			addrescapes(n.Name.Defn)
2043			break
2044		}
2045
2046		if n.Class() != PPARAM && n.Class() != PPARAMOUT && n.Class() != PAUTO {
2047			break
2048		}
2049
2050		// This is a plain parameter or local variable that needs to move to the heap,
2051		// but possibly for the function outside the one we're compiling.
2052		// That is, if we have:
2053		//
2054		//	func f(x int) {
2055		//		func() {
2056		//			global = &x
2057		//		}
2058		//	}
2059		//
2060		// then we're analyzing the inner closure but we need to move x to the
2061		// heap in f, not in the inner closure. Flip over to f before calling moveToHeap.
2062		oldfn := Curfn
2063		Curfn = n.Name.Curfn
2064		if Curfn.Func.Closure != nil && Curfn.Op == OCLOSURE {
2065			Curfn = Curfn.Func.Closure
2066		}
2067		ln := lineno
2068		lineno = Curfn.Pos
2069		moveToHeap(n)
2070		Curfn = oldfn
2071		lineno = ln
2072
2073	// ODOTPTR has already been introduced,
2074	// so these are the non-pointer ODOT and OINDEX.
2075	// In &x[0], if x is a slice, then x does not
2076	// escape--the pointer inside x does, but that
2077	// is always a heap pointer anyway.
2078	case ODOT, OINDEX, OPAREN, OCONVNOP:
2079		if !n.Left.Type.IsSlice() {
2080			addrescapes(n.Left)
2081		}
2082	}
2083}
2084
2085// moveToHeap records the parameter or local variable n as moved to the heap.
2086func moveToHeap(n *Node) {
2087	if Debug['r'] != 0 {
2088		Dump("MOVE", n)
2089	}
2090	if compiling_runtime {
2091		yyerror("%v escapes to heap, not allowed in runtime.", n)
2092	}
2093	if n.Class() == PAUTOHEAP {
2094		Dump("n", n)
2095		Fatalf("double move to heap")
2096	}
2097
2098	// Allocate a local stack variable to hold the pointer to the heap copy.
2099	// temp will add it to the function declaration list automatically.
2100	heapaddr := temp(types.NewPtr(n.Type))
2101	heapaddr.Sym = lookup("&" + n.Sym.Name)
2102	heapaddr.Orig.Sym = heapaddr.Sym
2103	heapaddr.Pos = n.Pos
2104
2105	// Unset AutoTemp to persist the &foo variable name through SSA to
2106	// liveness analysis.
2107	// TODO(mdempsky/drchase): Cleaner solution?
2108	heapaddr.Name.SetAutoTemp(false)
2109
2110	// Parameters have a local stack copy used at function start/end
2111	// in addition to the copy in the heap that may live longer than
2112	// the function.
2113	if n.Class() == PPARAM || n.Class() == PPARAMOUT {
2114		if n.Xoffset == BADWIDTH {
2115			Fatalf("addrescapes before param assignment")
2116		}
2117
2118		// We rewrite n below to be a heap variable (indirection of heapaddr).
2119		// Preserve a copy so we can still write code referring to the original,
2120		// and substitute that copy into the function declaration list
2121		// so that analyses of the local (on-stack) variables use it.
2122		stackcopy := newname(n.Sym)
2123		stackcopy.SetAddable(false)
2124		stackcopy.Type = n.Type
2125		stackcopy.Xoffset = n.Xoffset
2126		stackcopy.SetClass(n.Class())
2127		stackcopy.Name.Param.Heapaddr = heapaddr
2128		if n.Class() == PPARAMOUT {
2129			// Make sure the pointer to the heap copy is kept live throughout the function.
2130			// The function could panic at any point, and then a defer could recover.
2131			// Thus, we need the pointer to the heap copy always available so the
2132			// post-deferreturn code can copy the return value back to the stack.
2133			// See issue 16095.
2134			heapaddr.SetIsOutputParamHeapAddr(true)
2135		}
2136		n.Name.Param.Stackcopy = stackcopy
2137
2138		// Substitute the stackcopy into the function variable list so that
2139		// liveness and other analyses use the underlying stack slot
2140		// and not the now-pseudo-variable n.
2141		found := false
2142		for i, d := range Curfn.Func.Dcl {
2143			if d == n {
2144				Curfn.Func.Dcl[i] = stackcopy
2145				found = true
2146				break
2147			}
2148			// Parameters are before locals, so can stop early.
2149			// This limits the search even in functions with many local variables.
2150			if d.Class() == PAUTO {
2151				break
2152			}
2153		}
2154		if !found {
2155			Fatalf("cannot find %v in local variable list", n)
2156		}
2157		Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
2158	}
2159
2160	// Modify n in place so that uses of n now mean indirection of the heapaddr.
2161	n.SetClass(PAUTOHEAP)
2162	n.Xoffset = 0
2163	n.Name.Param.Heapaddr = heapaddr
2164	n.Esc = EscHeap
2165	if Debug['m'] != 0 {
2166		fmt.Printf("%v: moved to heap: %v\n", n.Line(), n)
2167	}
2168}
2169
2170// This special tag is applied to uintptr variables
2171// that we believe may hold unsafe.Pointers for
2172// calls into assembly functions.
2173// It is logically a constant, but using a var
2174// lets us take the address below to get a *string.
2175var unsafeUintptrTag = "unsafe-uintptr"
2176
2177// This special tag is applied to uintptr parameters of functions
2178// marked go:uintptrescapes.
2179const uintptrEscapesTag = "uintptr-escapes"
2180
2181func (e *EscState) esctag(fn *Node) {
2182	fn.Esc = EscFuncTagged
2183
2184	name := func(s *types.Sym, narg int) string {
2185		if s != nil {
2186			return s.Name
2187		}
2188		return fmt.Sprintf("arg#%d", narg)
2189	}
2190
2191	// External functions are assumed unsafe,
2192	// unless //go:noescape is given before the declaration.
2193	if fn.Nbody.Len() == 0 {
2194		if fn.Noescape() {
2195			for _, f := range fn.Type.Params().Fields().Slice() {
2196				if types.Haspointers(f.Type) {
2197					f.Note = mktag(EscNone)
2198				}
2199			}
2200		}
2201
2202		// Assume that uintptr arguments must be held live across the call.
2203		// This is most important for syscall.Syscall.
2204		// See golang.org/issue/13372.
2205		// This really doesn't have much to do with escape analysis per se,
2206		// but we are reusing the ability to annotate an individual function
2207		// argument and pass those annotations along to importing code.
2208		narg := 0
2209		for _, f := range fn.Type.Params().Fields().Slice() {
2210			narg++
2211			if f.Type.Etype == TUINTPTR {
2212				if Debug['m'] != 0 {
2213					Warnl(fn.Pos, "%v assuming %v is unsafe uintptr", funcSym(fn), name(f.Sym, narg))
2214				}
2215				f.Note = unsafeUintptrTag
2216			}
2217		}
2218
2219		return
2220	}
2221
2222	if fn.Func.Pragma&UintptrEscapes != 0 {
2223		narg := 0
2224		for _, f := range fn.Type.Params().Fields().Slice() {
2225			narg++
2226			if f.Type.Etype == TUINTPTR {
2227				if Debug['m'] != 0 {
2228					Warnl(fn.Pos, "%v marking %v as escaping uintptr", funcSym(fn), name(f.Sym, narg))
2229				}
2230				f.Note = uintptrEscapesTag
2231			}
2232
2233			if f.Isddd() && f.Type.Elem().Etype == TUINTPTR {
2234				// final argument is ...uintptr.
2235				if Debug['m'] != 0 {
2236					Warnl(fn.Pos, "%v marking %v as escaping ...uintptr", funcSym(fn), name(f.Sym, narg))
2237				}
2238				f.Note = uintptrEscapesTag
2239			}
2240		}
2241	}
2242
2243	for _, ln := range fn.Func.Dcl {
2244		if ln.Op != ONAME {
2245			continue
2246		}
2247
2248		switch ln.Esc & EscMask {
2249		case EscNone, // not touched by escflood
2250			EscReturn:
2251			if types.Haspointers(ln.Type) { // don't bother tagging for scalars
2252				if ln.Name.Param.Field.Note != uintptrEscapesTag {
2253					ln.Name.Param.Field.Note = mktag(int(ln.Esc))
2254				}
2255			}
2256
2257		case EscHeap: // touched by escflood, moved to heap
2258		}
2259	}
2260
2261	// Unnamed parameters are unused and therefore do not escape.
2262	// (Unnamed parameters are not in the Dcl list in the loop above
2263	// so we need to mark them separately.)
2264	for _, f := range fn.Type.Params().Fields().Slice() {
2265		if f.Sym == nil || f.Sym.IsBlank() {
2266			f.Note = mktag(EscNone)
2267		}
2268	}
2269}
2270