github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/gc/esc.c (about)

     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  
     5  // Escape analysis.
     6  
     7  #include <u.h>
     8  #include <libc.h>
     9  #include "go.h"
    10  
    11  // Run analysis on minimal sets of mutually recursive functions
    12  // or single non-recursive functions, bottom up.
    13  //
    14  // Finding these sets is finding strongly connected components
    15  // in the static call graph.  The algorithm for doing that is taken
    16  // from Sedgewick, Algorithms, Second Edition, p. 482, with two
    17  // adaptations.
    18  //
    19  // First, a hidden closure function (n->curfn != N) cannot be the
    20  // root of a connected component. Refusing to use it as a root
    21  // forces it into the component of the function in which it appears.
    22  // The analysis assumes that closures and the functions in which they
    23  // appear are analyzed together, so that the aliasing between their
    24  // variables can be modeled more precisely.
    25  //
    26  // Second, each function becomes two virtual nodes in the graph,
    27  // with numbers n and n+1. We record the function's node number as n
    28  // but search from node n+1. If the search tells us that the component
    29  // number (min) is n+1, we know that this is a trivial component: one function
    30  // plus its closures. If the search tells us that the component number is
    31  // n, then there was a path from node n+1 back to node n, meaning that
    32  // the function set is mutually recursive. The escape analysis can be
    33  // more precise when analyzing a single non-recursive function than
    34  // when analyzing a set of mutually recursive functions.
    35  
    36  static NodeList *stack;
    37  static uint32 visitgen;
    38  static uint32 visit(Node*);
    39  static uint32 visitcode(Node*, uint32);
    40  static uint32 visitcodelist(NodeList*, uint32);
    41  
    42  static void analyze(NodeList*, int);
    43  
    44  enum
    45  {
    46  	EscFuncUnknown = 0,
    47  	EscFuncPlanned,
    48  	EscFuncStarted,
    49  	EscFuncTagged,
    50  };
    51  
    52  void
    53  escapes(NodeList *all)
    54  {
    55  	NodeList *l;
    56  
    57  	for(l=all; l; l=l->next)
    58  		l->n->walkgen = 0;
    59  
    60  	visitgen = 0;
    61  	for(l=all; l; l=l->next)
    62  		if(l->n->op == ODCLFUNC && l->n->curfn == N)
    63  			visit(l->n);
    64  
    65  	for(l=all; l; l=l->next)
    66  		l->n->walkgen = 0;
    67  }
    68  
    69  static uint32
    70  visit(Node *n)
    71  {
    72  	uint32 min, recursive;
    73  	NodeList *l, *block;
    74  
    75  	if(n->walkgen > 0) {
    76  		// already visited
    77  		return n->walkgen;
    78  	}
    79  	
    80  	visitgen++;
    81  	n->walkgen = visitgen;
    82  	visitgen++;
    83  	min = visitgen;
    84  
    85  	l = mal(sizeof *l);
    86  	l->next = stack;
    87  	l->n = n;
    88  	stack = l;
    89  	min = visitcodelist(n->nbody, min);
    90  	if((min == n->walkgen || min == n->walkgen+1) && n->curfn == N) {
    91  		// This node is the root of a strongly connected component.
    92  
    93  		// The original min passed to visitcodelist was n->walkgen+1.
    94  		// If visitcodelist found its way back to n->walkgen, then this
    95  		// block is a set of mutually recursive functions.
    96  		// Otherwise it's just a lone function that does not recurse.
    97  		recursive = min == n->walkgen;
    98  
    99  		// Remove connected component from stack.
   100  		// Mark walkgen so that future visits return a large number
   101  		// so as not to affect the caller's min.
   102  		block = stack;
   103  		for(l=stack; l->n != n; l=l->next)
   104  			l->n->walkgen = (uint32)~0U;
   105  		n->walkgen = (uint32)~0U;
   106  		stack = l->next;
   107  		l->next = nil;
   108  
   109  		// Run escape analysis on this set of functions.
   110  		analyze(block, recursive);
   111  	}
   112  
   113  	return min;
   114  }
   115  
   116  static uint32
   117  visitcodelist(NodeList *l, uint32 min)
   118  {
   119  	for(; l; l=l->next)
   120  		min = visitcode(l->n, min);
   121  	return min;
   122  }
   123  
   124  static uint32
   125  visitcode(Node *n, uint32 min)
   126  {
   127  	Node *fn;
   128  	uint32 m;
   129  
   130  	if(n == N)
   131  		return min;
   132  
   133  	min = visitcodelist(n->ninit, min);
   134  	min = visitcode(n->left, min);
   135  	min = visitcode(n->right, min);
   136  	min = visitcodelist(n->list, min);
   137  	min = visitcode(n->ntest, min);
   138  	min = visitcode(n->nincr, min);
   139  	min = visitcodelist(n->nbody, min);
   140  	min = visitcodelist(n->nelse, min);
   141  	min = visitcodelist(n->rlist, min);
   142  	
   143  	if(n->op == OCALLFUNC || n->op == OCALLMETH) {
   144  		fn = n->left;
   145  		if(n->op == OCALLMETH)
   146  			fn = n->left->right->sym->def;
   147  		if(fn && fn->op == ONAME && fn->class == PFUNC && fn->defn)
   148  			if((m = visit(fn->defn)) < min)
   149  				min = m;
   150  	}
   151  	
   152  	if(n->op == OCLOSURE)
   153  		if((m = visit(n->closure)) < min)
   154  			min = m;
   155  
   156  	return min;
   157  }
   158  
   159  // An escape analysis pass for a set of functions.
   160  //
   161  // First escfunc, esc and escassign recurse over the ast of each
   162  // function to dig out flow(dst,src) edges between any
   163  // pointer-containing nodes and store them in dst->escflowsrc.  For
   164  // variables assigned to a variable in an outer scope or used as a
   165  // return value, they store a flow(theSink, src) edge to a fake node
   166  // 'the Sink'.  For variables referenced in closures, an edge
   167  // flow(closure, &var) is recorded and the flow of a closure itself to
   168  // an outer scope is tracked the same way as other variables.
   169  //
   170  // Then escflood walks the graph starting at theSink and tags all
   171  // variables of it can reach an & node as escaping and all function
   172  // parameters it can reach as leaking.
   173  //
   174  // If a value's address is taken but the address does not escape,
   175  // then the value can stay on the stack.  If the value new(T) does
   176  // not escape, then new(T) can be rewritten into a stack allocation.
   177  // The same is true of slice literals.
   178  //
   179  // If optimizations are disabled (-N), this code is not used.
   180  // Instead, the compiler assumes that any value whose address
   181  // is taken without being immediately dereferenced
   182  // needs to be moved to the heap, and new(T) and slice
   183  // literals are always real allocations.
   184  
   185  typedef struct EscState EscState;
   186  
   187  static void escfunc(EscState*, Node *func);
   188  static void esclist(EscState*, NodeList *l, Node *up);
   189  static void esc(EscState*, Node *n, Node *up);
   190  static void escloopdepthlist(EscState*, NodeList *l);
   191  static void escloopdepth(EscState*, Node *n);
   192  static void escassign(EscState*, Node *dst, Node *src);
   193  static void esccall(EscState*, Node*, Node *up);
   194  static void escflows(EscState*, Node *dst, Node *src);
   195  static void escflood(EscState*, Node *dst);
   196  static void escwalk(EscState*, int level, Node *dst, Node *src);
   197  static void esctag(EscState*, Node *func);
   198  
   199  struct EscState {
   200  	// Fake node that all
   201  	//   - return values and output variables
   202  	//   - parameters on imported functions not marked 'safe'
   203  	//   - assignments to global variables
   204  	// flow to.
   205  	Node	theSink;
   206  	
   207  	// If an analyzed function is recorded to return
   208  	// pieces obtained via indirection from a parameter,
   209  	// and later there is a call f(x) to that function,
   210  	// we create a link funcParam <- x to record that fact.
   211  	// The funcParam node is handled specially in escflood.
   212  	Node	funcParam;	
   213  	
   214  	NodeList*	dsts;		// all dst nodes
   215  	int	loopdepth;	// for detecting nested loop scopes
   216  	int	pdepth;		// for debug printing in recursions.
   217  	int	dstcount, edgecount;	// diagnostic
   218  	NodeList*	noesc;	// list of possible non-escaping nodes, for printing
   219  	int	recursive;	// recursive function or group of mutually recursive functions.
   220  };
   221  
   222  static Strlit *tags[16];
   223  
   224  static Strlit*
   225  mktag(int mask)
   226  {
   227  	Strlit *s;
   228  	char buf[40];
   229  
   230  	switch(mask&EscMask) {
   231  	case EscNone:
   232  	case EscReturn:
   233  		break;
   234  	default:
   235  		fatal("escape mktag");
   236  	}
   237  
   238  	mask >>= EscBits;
   239  
   240  	if(mask < nelem(tags) && tags[mask] != nil)
   241  		return tags[mask];
   242  
   243  	snprint(buf, sizeof buf, "esc:0x%x", mask);
   244  	s = strlit(buf);
   245  	if(mask < nelem(tags))
   246  		tags[mask] = s;
   247  	return s;
   248  }
   249  
   250  static int
   251  parsetag(Strlit *note)
   252  {
   253  	int em;
   254  
   255  	if(note == nil)
   256  		return EscUnknown;
   257  	if(strncmp(note->s, "esc:", 4) != 0)
   258  		return EscUnknown;
   259  	em = atoi(note->s + 4);
   260  	if (em == 0)
   261  		return EscNone;
   262  	return EscReturn | (em << EscBits);
   263  }
   264  
   265  static void
   266  analyze(NodeList *all, int recursive)
   267  {
   268  	NodeList *l;
   269  	EscState es, *e;
   270  	
   271  	memset(&es, 0, sizeof es);
   272  	e = &es;
   273  	e->theSink.op = ONAME;
   274  	e->theSink.orig = &e->theSink;
   275  	e->theSink.class = PEXTERN;
   276  	e->theSink.sym = lookup(".sink");
   277  	e->theSink.escloopdepth = -1;
   278  	e->recursive = recursive;
   279  	
   280  	e->funcParam.op = ONAME;
   281  	e->funcParam.orig = &e->funcParam;
   282  	e->funcParam.class = PAUTO;
   283  	e->funcParam.sym = lookup(".param");
   284  	e->funcParam.escloopdepth = 10000000;
   285  	
   286  	for(l=all; l; l=l->next)
   287  		if(l->n->op == ODCLFUNC)
   288  			l->n->esc = EscFuncPlanned;
   289  
   290  	// flow-analyze functions
   291  	for(l=all; l; l=l->next)
   292  		if(l->n->op == ODCLFUNC)
   293  			escfunc(e, l->n);
   294  
   295  	// print("escapes: %d e->dsts, %d edges\n", e->dstcount, e->edgecount);
   296  
   297  	// visit the upstream of each dst, mark address nodes with
   298  	// addrescapes, mark parameters unsafe
   299  	for(l = e->dsts; l; l=l->next)
   300  		escflood(e, l->n);
   301  
   302  	// for all top level functions, tag the typenodes corresponding to the param nodes
   303  	for(l=all; l; l=l->next)
   304  		if(l->n->op == ODCLFUNC)
   305  			esctag(e, l->n);
   306  
   307  	if(debug['m']) {
   308  		for(l=e->noesc; l; l=l->next)
   309  			if(l->n->esc == EscNone)
   310  				warnl(l->n->lineno, "%S %hN does not escape",
   311  					(l->n->curfn && l->n->curfn->nname) ? l->n->curfn->nname->sym : S,
   312  					l->n);
   313  	}
   314  }
   315  
   316  
   317  static void
   318  escfunc(EscState *e, Node *func)
   319  {
   320  	Node *savefn;
   321  	NodeList *ll;
   322  	int saveld;
   323  
   324  //	print("escfunc %N %s\n", func->nname, e->recursive?"(recursive)":"");
   325  
   326  	if(func->esc != 1)
   327  		fatal("repeat escfunc %N", func->nname);
   328  	func->esc = EscFuncStarted;
   329  
   330  	saveld = e->loopdepth;
   331  	e->loopdepth = 1;
   332  	savefn = curfn;
   333  	curfn = func;
   334  
   335  	for(ll=curfn->dcl; ll; ll=ll->next) {
   336  		if(ll->n->op != ONAME)
   337  			continue;
   338  		switch (ll->n->class) {
   339  		case PPARAMOUT:
   340  			// out params are in a loopdepth between the sink and all local variables
   341  			ll->n->escloopdepth = 0;
   342  			break;
   343  		case PPARAM:
   344  			ll->n->escloopdepth = 1; 
   345  			if(ll->n->type && !haspointers(ll->n->type))
   346  				break;
   347  			if(curfn->nbody == nil && !curfn->noescape)
   348  				ll->n->esc = EscHeap;
   349  			else
   350  				ll->n->esc = EscNone;	// prime for escflood later
   351  			e->noesc = list(e->noesc, ll->n);
   352  			break;
   353  		}
   354  	}
   355  
   356  	// in a mutually recursive group we lose track of the return values
   357  	if(e->recursive)
   358  		for(ll=curfn->dcl; ll; ll=ll->next)
   359  			if(ll->n->op == ONAME && ll->n->class == PPARAMOUT)
   360  				escflows(e, &e->theSink, ll->n);
   361  
   362  	escloopdepthlist(e, curfn->nbody);
   363  	esclist(e, curfn->nbody, curfn);
   364  	curfn = savefn;
   365  	e->loopdepth = saveld;
   366  }
   367  
   368  // Mark labels that have no backjumps to them as not increasing e->loopdepth.
   369  // Walk hasn't generated (goto|label)->left->sym->label yet, so we'll cheat
   370  // and set it to one of the following two.  Then in esc we'll clear it again.
   371  static Label looping;
   372  static Label nonlooping;
   373  
   374  static void
   375  escloopdepthlist(EscState *e, NodeList *l)
   376  {
   377  	for(; l; l=l->next)
   378  		escloopdepth(e, l->n);
   379  }
   380  
   381  static void
   382  escloopdepth(EscState *e, Node *n)
   383  {
   384  	if(n == N)
   385  		return;
   386  
   387  	escloopdepthlist(e, n->ninit);
   388  
   389  	switch(n->op) {
   390  	case OLABEL:
   391  		if(!n->left || !n->left->sym)
   392  			fatal("esc:label without label: %+N", n);
   393  		// Walk will complain about this label being already defined, but that's not until
   394  		// after escape analysis. in the future, maybe pull label & goto analysis out of walk and put before esc
   395  		// if(n->left->sym->label != nil)
   396  		//	fatal("escape analysis messed up analyzing label: %+N", n);
   397  		n->left->sym->label = &nonlooping;
   398  		break;
   399  	case OGOTO:
   400  		if(!n->left || !n->left->sym)
   401  			fatal("esc:goto without label: %+N", n);
   402  		// If we come past one that's uninitialized, this must be a (harmless) forward jump
   403  		// but if it's set to nonlooping the label must have preceded this goto.
   404  		if(n->left->sym->label == &nonlooping)
   405  			n->left->sym->label = &looping;
   406  		break;
   407  	}
   408  
   409  	escloopdepth(e, n->left);
   410  	escloopdepth(e, n->right);
   411  	escloopdepthlist(e, n->list);
   412  	escloopdepth(e, n->ntest);
   413  	escloopdepth(e, n->nincr);
   414  	escloopdepthlist(e, n->nbody);
   415  	escloopdepthlist(e, n->nelse);
   416  	escloopdepthlist(e, n->rlist);
   417  
   418  }
   419  
   420  static void
   421  esclist(EscState *e, NodeList *l, Node *up)
   422  {
   423  	for(; l; l=l->next)
   424  		esc(e, l->n, up);
   425  }
   426  
   427  static void
   428  esc(EscState *e, Node *n, Node *up)
   429  {
   430  	int lno;
   431  	NodeList *ll, *lr;
   432  	Node *a;
   433  
   434  	if(n == N)
   435  		return;
   436  
   437  	lno = setlineno(n);
   438  
   439  	// ninit logically runs at a different loopdepth than the rest of the for loop.
   440  	esclist(e, n->ninit, n);
   441  
   442  	if(n->op == OFOR || n->op == ORANGE)
   443  		e->loopdepth++;
   444  
   445  	// type switch variables have no ODCL.
   446  	// process type switch as declaration.
   447  	// must happen before processing of switch body,
   448  	// so before recursion.
   449  	if(n->op == OSWITCH && n->ntest && n->ntest->op == OTYPESW) {
   450  		for(ll=n->list; ll; ll=ll->next) {  // cases
   451  			// ll->n->nname is the variable per case
   452  			if(ll->n->nname)
   453  				ll->n->nname->escloopdepth = e->loopdepth;
   454  		}
   455  	}
   456  
   457  	esc(e, n->left, n);
   458  	esc(e, n->right, n);
   459  	esc(e, n->ntest, n);
   460  	esc(e, n->nincr, n);
   461  	esclist(e, n->nbody, n);
   462  	esclist(e, n->nelse, n);
   463  	esclist(e, n->list, n);
   464  	esclist(e, n->rlist, n);
   465  
   466  	if(n->op == OFOR || n->op == ORANGE)
   467  		e->loopdepth--;
   468  
   469  	if(debug['m'] > 1)
   470  		print("%L:[%d] %S esc: %N\n", lineno, e->loopdepth,
   471  		      (curfn && curfn->nname) ? curfn->nname->sym : S, n);
   472  
   473  	switch(n->op) {
   474  	case ODCL:
   475  		// Record loop depth at declaration.
   476  		if(n->left)
   477  			n->left->escloopdepth = e->loopdepth;
   478  		break;
   479  
   480  	case OLABEL:
   481  		if(n->left->sym->label == &nonlooping) {
   482  			if(debug['m'] > 1)
   483  				print("%L:%N non-looping label\n", lineno, n);
   484  		} else if(n->left->sym->label == &looping) {
   485  			if(debug['m'] > 1)
   486  				print("%L: %N looping label\n", lineno, n);
   487  			e->loopdepth++;
   488  		}
   489  		// See case OLABEL in escloopdepth above
   490  		// else if(n->left->sym->label == nil)
   491  		//	fatal("escape analysis missed or messed up a label: %+N", n);
   492  
   493  		n->left->sym->label = nil;
   494  		break;
   495  
   496  	case ORANGE:
   497  		// Everything but fixed array is a dereference.
   498  		if(isfixedarray(n->type) && n->list && n->list->next)
   499  			escassign(e, n->list->next->n, n->right);
   500  		break;
   501  
   502  	case OSWITCH:
   503  		if(n->ntest && n->ntest->op == OTYPESW) {
   504  			for(ll=n->list; ll; ll=ll->next) {  // cases
   505  				// ntest->right is the argument of the .(type),
   506  				// ll->n->nname is the variable per case
   507  				escassign(e, ll->n->nname, n->ntest->right);
   508  			}
   509  		}
   510  		break;
   511  
   512  	case OAS:
   513  	case OASOP:
   514  		escassign(e, n->left, n->right);
   515  		break;
   516  
   517  	case OAS2:	// x,y = a,b
   518  		if(count(n->list) == count(n->rlist))
   519  			for(ll=n->list, lr=n->rlist; ll; ll=ll->next, lr=lr->next)
   520  				escassign(e, ll->n, lr->n);
   521  		break;
   522  
   523  	case OAS2RECV:		// v, ok = <-ch
   524  	case OAS2MAPR:		// v, ok = m[k]
   525  	case OAS2DOTTYPE:	// v, ok = x.(type)
   526  		escassign(e, n->list->n, n->rlist->n);
   527  		break;
   528  
   529  	case OSEND:		// ch <- x
   530  		escassign(e, &e->theSink, n->right);
   531  		break;
   532  
   533  	case ODEFER:
   534  		if(e->loopdepth == 1)  // top level
   535  			break;
   536  		// arguments leak out of scope
   537  		// TODO: leak to a dummy node instead
   538  		// fallthrough
   539  	case OPROC:
   540  		// go f(x) - f and x escape
   541  		escassign(e, &e->theSink, n->left->left);
   542  		escassign(e, &e->theSink, n->left->right);  // ODDDARG for call
   543  		for(ll=n->left->list; ll; ll=ll->next)
   544  			escassign(e, &e->theSink, ll->n);
   545  		break;
   546  
   547  	case OCALLMETH:
   548  	case OCALLFUNC:
   549  	case OCALLINTER:
   550  		esccall(e, n, up);
   551  		break;
   552  
   553  	case OAS2FUNC:	// x,y = f()
   554  		// esccall already done on n->rlist->n. tie it's escretval to n->list
   555  		lr=n->rlist->n->escretval;
   556  		for(ll=n->list; lr && ll; lr=lr->next, ll=ll->next)
   557  			escassign(e, ll->n, lr->n);
   558  		if(lr || ll)
   559  			fatal("esc oas2func");
   560  		break;
   561  
   562  	case ORETURN:
   563  		ll=n->list;
   564  		if(count(n->list) == 1 && curfn->type->outtuple > 1) {
   565  			// OAS2FUNC in disguise
   566  			// esccall already done on n->list->n
   567  			// tie n->list->n->escretval to curfn->dcl PPARAMOUT's
   568  			ll = n->list->n->escretval;
   569  		}
   570  
   571  		for(lr = curfn->dcl; lr && ll; lr=lr->next) {
   572  			if (lr->n->op != ONAME || lr->n->class != PPARAMOUT)
   573  				continue;
   574  			escassign(e, lr->n, ll->n);
   575  			ll = ll->next;
   576  		}
   577  		if (ll != nil)
   578  			fatal("esc return list");
   579  		break;
   580  
   581  	case OPANIC:
   582  		// Argument could leak through recover.
   583  		escassign(e, &e->theSink, n->left);
   584  		break;
   585  
   586  	case OAPPEND:
   587  		if(!n->isddd)
   588  			for(ll=n->list->next; ll; ll=ll->next)
   589  				escassign(e, &e->theSink, ll->n);  // lose track of assign to dereference
   590  		break;
   591  
   592  	case OCONV:
   593  	case OCONVNOP:
   594  	case OCONVIFACE:
   595  		escassign(e, n, n->left);
   596  		break;
   597  
   598  	case OARRAYLIT:
   599  		if(isslice(n->type)) {
   600  			n->esc = EscNone;  // until proven otherwise
   601  			e->noesc = list(e->noesc, n);
   602  			n->escloopdepth = e->loopdepth;
   603  			// Values make it to memory, lose track.
   604  			for(ll=n->list; ll; ll=ll->next)
   605  				escassign(e, &e->theSink, ll->n->right);
   606  		} else {
   607  			// Link values to array.
   608  			for(ll=n->list; ll; ll=ll->next)
   609  				escassign(e, n, ll->n->right);
   610  		}
   611  		break;
   612  
   613  	case OSTRUCTLIT:
   614  		// Link values to struct.
   615  		for(ll=n->list; ll; ll=ll->next)
   616  			escassign(e, n, ll->n->right);
   617  		break;
   618  	
   619  	case OPTRLIT:
   620  		n->esc = EscNone;  // until proven otherwise
   621  		e->noesc = list(e->noesc, n);
   622  		n->escloopdepth = e->loopdepth;
   623  		// Contents make it to memory, lose track.
   624  		escassign(e, &e->theSink, n->left);
   625  		break;
   626  	
   627  	case OCALLPART:
   628  		n->esc = EscNone; // until proven otherwise
   629  		e->noesc = list(e->noesc, n);
   630  		n->escloopdepth = e->loopdepth;
   631  		// Contents make it to memory, lose track.
   632  		escassign(e, &e->theSink, n->left);
   633  		break;
   634  
   635  	case OMAPLIT:
   636  		n->esc = EscNone;  // until proven otherwise
   637  		e->noesc = list(e->noesc, n);
   638  		n->escloopdepth = e->loopdepth;
   639  		// Keys and values make it to memory, lose track.
   640  		for(ll=n->list; ll; ll=ll->next) {
   641  			escassign(e, &e->theSink, ll->n->left);
   642  			escassign(e, &e->theSink, ll->n->right);
   643  		}
   644  		break;
   645  	
   646  	case OCLOSURE:
   647  		// Link addresses of captured variables to closure.
   648  		for(ll=n->cvars; ll; ll=ll->next) {
   649  			if(ll->n->op == OXXX)  // unnamed out argument; see dcl.c:/^funcargs
   650  				continue;
   651  			a = nod(OADDR, ll->n->closure, N);
   652  			a->lineno = ll->n->lineno;
   653  			a->escloopdepth = e->loopdepth;
   654  			typecheck(&a, Erv);
   655  			escassign(e, n, a);
   656  		}
   657  		// fallthrough
   658  	case OMAKECHAN:
   659  	case OMAKEMAP:
   660  	case OMAKESLICE:
   661  	case ONEW:
   662  		n->escloopdepth = e->loopdepth;
   663  		n->esc = EscNone;  // until proven otherwise
   664  		e->noesc = list(e->noesc, n);
   665  		break;
   666  
   667  	case OADDR:
   668  		n->esc = EscNone;  // until proven otherwise
   669  		e->noesc = list(e->noesc, n);
   670  		// current loop depth is an upper bound on actual loop depth
   671  		// of addressed value.
   672  		n->escloopdepth = e->loopdepth;
   673  		// for &x, use loop depth of x if known.
   674  		// it should always be known, but if not, be conservative
   675  		// and keep the current loop depth.
   676  		if(n->left->op == ONAME) {
   677  			switch(n->left->class) {
   678  			case PAUTO:
   679  				if(n->left->escloopdepth != 0)
   680  					n->escloopdepth = n->left->escloopdepth;
   681  				break;
   682  			case PPARAM:
   683  			case PPARAMOUT:
   684  				// PPARAM is loop depth 1 always.
   685  				// PPARAMOUT is loop depth 0 for writes
   686  				// but considered loop depth 1 for address-of,
   687  				// so that writing the address of one result
   688  				// to another (or the same) result makes the
   689  				// first result move to the heap.
   690  				n->escloopdepth = 1;
   691  				break;
   692  			}
   693  		}
   694  		break;
   695  	}
   696  
   697  	lineno = lno;
   698  }
   699  
   700  // Assert that expr somehow gets assigned to dst, if non nil.  for
   701  // dst==nil, any name node expr still must be marked as being
   702  // evaluated in curfn.	For expr==nil, dst must still be examined for
   703  // evaluations inside it (e.g *f(x) = y)
   704  static void
   705  escassign(EscState *e, Node *dst, Node *src)
   706  {
   707  	int lno;
   708  	NodeList *ll;
   709  
   710  	if(isblank(dst) || dst == N || src == N || src->op == ONONAME || src->op == OXXX)
   711  		return;
   712  
   713  	if(debug['m'] > 1)
   714  		print("%L:[%d] %S escassign: %hN(%hJ) = %hN(%hJ)\n", lineno, e->loopdepth,
   715  		      (curfn && curfn->nname) ? curfn->nname->sym : S, dst, dst, src, src);
   716  
   717  	setlineno(dst);
   718  	
   719  	// Analyze lhs of assignment.
   720  	// Replace dst with e->theSink if we can't track it.
   721  	switch(dst->op) {
   722  	default:
   723  		dump("dst", dst);
   724  		fatal("escassign: unexpected dst");
   725  
   726  	case OARRAYLIT:
   727  	case OCLOSURE:
   728  	case OCONV:
   729  	case OCONVIFACE:
   730  	case OCONVNOP:
   731  	case OMAPLIT:
   732  	case OSTRUCTLIT:
   733  	case OCALLPART:
   734  		break;
   735  
   736  	case ONAME:
   737  		if(dst->class == PEXTERN)
   738  			dst = &e->theSink;
   739  		break;
   740  	case ODOT:	      // treat "dst.x  = src" as "dst = src"
   741  		escassign(e, dst->left, src);
   742  		return;
   743  	case OINDEX:
   744  		if(isfixedarray(dst->left->type)) {
   745  			escassign(e, dst->left, src);
   746  			return;
   747  		}
   748  		dst = &e->theSink;  // lose track of dereference
   749  		break;
   750  	case OIND:
   751  	case ODOTPTR:
   752  		dst = &e->theSink;  // lose track of dereference
   753  		break;
   754  	case OINDEXMAP:
   755  		// lose track of key and value
   756  		escassign(e, &e->theSink, dst->right);
   757  		dst = &e->theSink;
   758  		break;
   759  	}
   760  
   761  	lno = setlineno(src);
   762  	e->pdepth++;
   763  
   764  	switch(src->op) {
   765  	case OADDR:	// dst = &x
   766  	case OIND:	// dst = *x
   767  	case ODOTPTR:	// dst = (*x).f
   768  	case ONAME:
   769  	case OPARAM:
   770  	case ODDDARG:
   771  	case OPTRLIT:
   772  	case OARRAYLIT:
   773  	case OMAPLIT:
   774  	case OSTRUCTLIT:
   775  	case OMAKECHAN:
   776  	case OMAKEMAP:
   777  	case OMAKESLICE:
   778  	case ONEW:
   779  	case OCLOSURE:
   780  	case OCALLPART:
   781  		escflows(e, dst, src);
   782  		break;
   783  
   784  	case OCALLMETH:
   785  	case OCALLFUNC:
   786  	case OCALLINTER:
   787  		// Flowing multiple returns to a single dst happens when
   788  		// analyzing "go f(g())": here g() flows to sink (issue 4529).
   789  		for(ll=src->escretval; ll; ll=ll->next)
   790  			escflows(e, dst, ll->n);
   791  		break;
   792  
   793  	case ODOT:
   794  		// A non-pointer escaping from a struct does not concern us.
   795  		if(src->type && !haspointers(src->type))
   796  			break;
   797  		// fallthrough
   798  	case OCONV:
   799  	case OCONVIFACE:
   800  	case OCONVNOP:
   801  	case ODOTMETH:	// treat recv.meth as a value with recv in it, only happens in ODEFER and OPROC
   802  			// iface.method already leaks iface in esccall, no need to put in extra ODOTINTER edge here
   803  	case ODOTTYPE:
   804  	case ODOTTYPE2:
   805  	case OSLICE:
   806  	case OSLICE3:
   807  	case OSLICEARR:
   808  	case OSLICE3ARR:
   809  		// Conversions, field access, slice all preserve the input value.
   810  		escassign(e, dst, src->left);
   811  		break;
   812  
   813  	case OAPPEND:
   814  		// Append returns first argument.
   815  		escassign(e, dst, src->list->n);
   816  		break;
   817  	
   818  	case OINDEX:
   819  		// Index of array preserves input value.
   820  		if(isfixedarray(src->left->type))
   821  			escassign(e, dst, src->left);
   822  		break;
   823  
   824  	case OADD:
   825  	case OSUB:
   826  	case OOR:
   827  	case OXOR:
   828  	case OMUL:
   829  	case ODIV:
   830  	case OMOD:
   831  	case OLSH:
   832  	case ORSH:
   833  	case OAND:
   834  	case OANDNOT:
   835  	case OPLUS:
   836  	case OMINUS:
   837  	case OCOM:
   838  		// Might be pointer arithmetic, in which case
   839  		// the operands flow into the result.
   840  		// TODO(rsc): Decide what the story is here.  This is unsettling.
   841  		escassign(e, dst, src->left);
   842  		escassign(e, dst, src->right);
   843  		break;
   844  	}
   845  
   846  	e->pdepth--;
   847  	lineno = lno;
   848  }
   849  
   850  static int
   851  escassignfromtag(EscState *e, Strlit *note, NodeList *dsts, Node *src)
   852  {
   853  	int em, em0;
   854  	
   855  	em = parsetag(note);
   856  
   857  	if(em == EscUnknown) {
   858  		escassign(e, &e->theSink, src);
   859  		return em;
   860  	}
   861  
   862  	if(em == EscNone)
   863  		return em;
   864  	
   865  	// If content inside parameter (reached via indirection)
   866  	// escapes back to results, mark as such.
   867  	if(em & EscContentEscapes)
   868  		escassign(e, &e->funcParam, src);
   869  
   870  	em0 = em;
   871  	for(em >>= EscReturnBits; em && dsts; em >>= 1, dsts=dsts->next)
   872  		if(em & 1)
   873  			escassign(e, dsts->n, src);
   874  
   875  	if (em != 0 && dsts == nil)
   876  		fatal("corrupt esc tag %Z or messed up escretval list\n", note);
   877  	return em0;
   878  }
   879  
   880  // This is a bit messier than fortunate, pulled out of esc's big
   881  // switch for clarity.	We either have the paramnodes, which may be
   882  // connected to other things through flows or we have the parameter type
   883  // nodes, which may be marked "noescape". Navigating the ast is slightly
   884  // different for methods vs plain functions and for imported vs
   885  // this-package
   886  static void
   887  esccall(EscState *e, Node *n, Node *up)
   888  {
   889  	NodeList *ll, *lr;
   890  	Node *a, *fn, *src;
   891  	Type *t, *fntype;
   892  	char buf[40];
   893  	int i;
   894  
   895  	fn = N;
   896  	switch(n->op) {
   897  	default:
   898  		fatal("esccall");
   899  
   900  	case OCALLFUNC:
   901  		fn = n->left;
   902  		fntype = fn->type;
   903  		break;
   904  
   905  	case OCALLMETH:
   906  		fn = n->left->right->sym->def;
   907  		if(fn)
   908  			fntype = fn->type;
   909  		else
   910  			fntype = n->left->type;
   911  		break;
   912  
   913  	case OCALLINTER:
   914  		fntype = n->left->type;
   915  		break;
   916  	}
   917  
   918  	ll = n->list;
   919  	if(n->list != nil && n->list->next == nil) {
   920  		a = n->list->n;
   921  		if(a->type->etype == TSTRUCT && a->type->funarg) // f(g()).
   922  			ll = a->escretval;
   923  	}
   924  
   925  	if(fn && fn->op == ONAME && fn->class == PFUNC && fn->defn && fn->defn->nbody && fn->ntype && fn->defn->esc < EscFuncTagged) {
   926  		// function in same mutually recursive group.  Incorporate into flow graph.
   927  //		print("esc local fn: %N\n", fn->ntype);
   928  		if(fn->defn->esc == EscFuncUnknown || n->escretval != nil)
   929  			fatal("graph inconsistency");
   930  
   931  		// set up out list on this call node
   932  		for(lr=fn->ntype->rlist; lr; lr=lr->next)
   933  			n->escretval = list(n->escretval, lr->n->left);  // type.rlist ->  dclfield -> ONAME (PPARAMOUT)
   934  
   935  		// Receiver.
   936  		if(n->op != OCALLFUNC)
   937  			escassign(e, fn->ntype->left->left, n->left->left);
   938  
   939  		for(lr=fn->ntype->list; ll && lr; ll=ll->next, lr=lr->next) {
   940  			src = ll->n;
   941  			if(lr->n->isddd && !n->isddd) {
   942  				// Introduce ODDDARG node to represent ... allocation.
   943  				src = nod(ODDDARG, N, N);
   944  				src->type = typ(TARRAY);
   945  				src->type->type = lr->n->type->type;
   946  				src->type->bound = count(ll);
   947  				src->type = ptrto(src->type); // make pointer so it will be tracked
   948  				src->escloopdepth = e->loopdepth;
   949  				src->lineno = n->lineno;
   950  				src->esc = EscNone;  // until we find otherwise
   951  				e->noesc = list(e->noesc, src);
   952  				n->right = src;
   953  			}
   954  			if(lr->n->left != N)
   955  				escassign(e, lr->n->left, src);
   956  			if(src != ll->n)
   957  				break;
   958  		}
   959  		// "..." arguments are untracked
   960  		for(; ll; ll=ll->next)
   961  			escassign(e, &e->theSink, ll->n);
   962  
   963  		return;
   964  	}
   965  
   966  	// Imported or completely analyzed function.  Use the escape tags.
   967  	if(n->escretval != nil)
   968  		fatal("esc already decorated call %+N\n", n);
   969  
   970  	// set up out list on this call node with dummy auto ONAMES in the current (calling) function.
   971  	i = 0;
   972  	for(t=getoutargx(fntype)->type; t; t=t->down) {
   973  		src = nod(ONAME, N, N);
   974  		snprint(buf, sizeof buf, ".dum%d", i++);
   975  		src->sym = lookup(buf);
   976  		src->type = t->type;
   977  		src->class = PAUTO;
   978  		src->curfn = curfn;
   979  		src->escloopdepth = e->loopdepth;
   980  		src->used = 1;
   981  		src->lineno = n->lineno;
   982  		n->escretval = list(n->escretval, src); 
   983  	}
   984  
   985  //	print("esc analyzed fn: %#N (%+T) returning (%+H)\n", fn, fntype, n->escretval);
   986  
   987  	// Receiver.
   988  	if(n->op != OCALLFUNC) {
   989  		t = getthisx(fntype)->type;
   990  		src = n->left->left;
   991  		if(haspointers(t->type))
   992  			escassignfromtag(e, t->note, n->escretval, src);
   993  	}
   994  	
   995  	for(t=getinargx(fntype)->type; ll; ll=ll->next) {
   996  		src = ll->n;
   997  		if(t->isddd && !n->isddd) {
   998  			// Introduce ODDDARG node to represent ... allocation.
   999  			src = nod(ODDDARG, N, N);
  1000  			src->escloopdepth = e->loopdepth;
  1001  			src->lineno = n->lineno;
  1002  			src->type = typ(TARRAY);
  1003  			src->type->type = t->type->type;
  1004  			src->type->bound = count(ll);
  1005  			src->type = ptrto(src->type); // make pointer so it will be tracked
  1006  			src->esc = EscNone;  // until we find otherwise
  1007  			e->noesc = list(e->noesc, src);
  1008  			n->right = src;
  1009  		}
  1010  		if(haspointers(t->type)) {
  1011  			if(escassignfromtag(e, t->note, n->escretval, src) == EscNone && up->op != ODEFER && up->op != OPROC) {
  1012  				a = src;
  1013  				while(a->op == OCONVNOP)
  1014  					a = a->left;
  1015  				switch(a->op) {
  1016  				case OCALLPART:
  1017  				case OCLOSURE:
  1018  				case ODDDARG:
  1019  				case OARRAYLIT:
  1020  				case OPTRLIT:
  1021  				case OSTRUCTLIT:
  1022  					// The callee has already been analyzed, so its arguments have esc tags.
  1023  					// The argument is marked as not escaping at all.
  1024  					// Record that fact so that any temporary used for
  1025  					// synthesizing this expression can be reclaimed when
  1026  					// the function returns.
  1027  					// This 'noescape' is even stronger than the usual esc == EscNone.
  1028  					// src->esc == EscNone means that src does not escape the current function.
  1029  					// src->noescape = 1 here means that src does not escape this statement
  1030  					// in the current function.
  1031  					a->noescape = 1;
  1032  					break;
  1033  				}
  1034  			}
  1035  		}
  1036  		if(src != ll->n)
  1037  			break;
  1038  		t = t->down;
  1039  	}
  1040  	// "..." arguments are untracked
  1041  	for(; ll; ll=ll->next)
  1042  		escassign(e, &e->theSink, ll->n);
  1043  }
  1044  
  1045  // Store the link src->dst in dst, throwing out some quick wins.
  1046  static void
  1047  escflows(EscState *e, Node *dst, Node *src)
  1048  {
  1049  	if(dst == nil || src == nil || dst == src)
  1050  		return;
  1051  
  1052  	// Don't bother building a graph for scalars.
  1053  	if(src->type && !haspointers(src->type))
  1054  		return;
  1055  
  1056  	if(debug['m']>2)
  1057  		print("%L::flows:: %hN <- %hN\n", lineno, dst, src);
  1058  
  1059  	if(dst->escflowsrc == nil) {
  1060  		e->dsts = list(e->dsts, dst);
  1061  		e->dstcount++;
  1062  	}
  1063  	e->edgecount++;
  1064  
  1065  	dst->escflowsrc = list(dst->escflowsrc, src);
  1066  }
  1067  
  1068  // Whenever we hit a reference node, the level goes up by one, and whenever
  1069  // we hit an OADDR, the level goes down by one. as long as we're on a level > 0
  1070  // finding an OADDR just means we're following the upstream of a dereference,
  1071  // so this address doesn't leak (yet).
  1072  // If level == 0, it means the /value/ of this node can reach the root of this flood.
  1073  // so if this node is an OADDR, it's argument should be marked as escaping iff
  1074  // it's currfn/e->loopdepth are different from the flood's root.
  1075  // Once an object has been moved to the heap, all of it's upstream should be considered
  1076  // escaping to the global scope.
  1077  static void
  1078  escflood(EscState *e, Node *dst)
  1079  {
  1080  	NodeList *l;
  1081  
  1082  	switch(dst->op) {
  1083  	case ONAME:
  1084  	case OCLOSURE:
  1085  		break;
  1086  	default:
  1087  		return;
  1088  	}
  1089  
  1090  	if(debug['m']>1)
  1091  		print("\nescflood:%d: dst %hN scope:%S[%d]\n", walkgen, dst,
  1092  		      (dst->curfn && dst->curfn->nname) ? dst->curfn->nname->sym : S,
  1093  		      dst->escloopdepth);
  1094  
  1095  	for(l = dst->escflowsrc; l; l=l->next) {
  1096  		walkgen++;
  1097  		escwalk(e, 0, dst, l->n);
  1098  	}
  1099  }
  1100  
  1101  // There appear to be some loops in the escape graph, causing
  1102  // arbitrary recursion into deeper and deeper levels.
  1103  // Cut this off safely by making minLevel sticky: once you
  1104  // get that deep, you cannot go down any further but you also
  1105  // cannot go up any further. This is a conservative fix.
  1106  // Making minLevel smaller (more negative) would handle more
  1107  // complex chains of indirections followed by address-of operations,
  1108  // at the cost of repeating the traversal once for each additional
  1109  // allowed level when a loop is encountered. Using -2 suffices to
  1110  // pass all the tests we have written so far, which we assume matches
  1111  // the level of complexity we want the escape analysis code to handle.
  1112  #define MinLevel (-2)
  1113  /*c2go enum { MinLevel = -2 };*/
  1114  
  1115  static void
  1116  escwalk(EscState *e, int level, Node *dst, Node *src)
  1117  {
  1118  	NodeList *ll;
  1119  	int leaks, newlevel;
  1120  
  1121  	if(src->walkgen == walkgen && src->esclevel <= level)
  1122  		return;
  1123  	src->walkgen = walkgen;
  1124  	src->esclevel = level;
  1125  
  1126  	if(debug['m']>1)
  1127  		print("escwalk: level:%d depth:%d %.*s %hN(%hJ) scope:%S[%d]\n",
  1128  		      level, e->pdepth, e->pdepth, "\t\t\t\t\t\t\t\t\t\t", src, src,
  1129  		      (src->curfn && src->curfn->nname) ? src->curfn->nname->sym : S, src->escloopdepth);
  1130  
  1131  	e->pdepth++;
  1132  
  1133  	// Input parameter flowing to output parameter?
  1134  	if(dst->op == ONAME && dst->class == PPARAMOUT && dst->vargen <= 20) {
  1135  		if(src->op == ONAME && src->class == PPARAM && src->curfn == dst->curfn && src->esc != EscScope && src->esc != EscHeap) {
  1136  			if(level == 0) {
  1137  				if(debug['m'])
  1138  					warnl(src->lineno, "leaking param: %hN to result %S", src, dst->sym);
  1139  				if((src->esc&EscMask) != EscReturn)
  1140  					src->esc = EscReturn;
  1141  				src->esc |= 1<<((dst->vargen-1) + EscReturnBits);
  1142  				goto recurse;
  1143  			} else if(level > 0) {
  1144  				if(debug['m'])
  1145  					warnl(src->lineno, "%N leaking param %hN content to result %S", src->curfn->nname, src, dst->sym);
  1146  				if((src->esc&EscMask) != EscReturn)
  1147  					src->esc = EscReturn;
  1148  				src->esc |= EscContentEscapes;
  1149  				goto recurse;
  1150  			}
  1151  		}
  1152  	}
  1153  
  1154  	// The second clause is for values pointed at by an object passed to a call
  1155  	// that returns something reached via indirect from the object.
  1156  	// We don't know which result it is or how many indirects, so we treat it as leaking.
  1157  	leaks = level <= 0 && dst->escloopdepth < src->escloopdepth ||
  1158  		level < 0 && dst == &e->funcParam && haspointers(src->type);
  1159  
  1160  	switch(src->op) {
  1161  	case ONAME:
  1162  		if(src->class == PPARAM && (leaks || dst->escloopdepth < 0) && src->esc != EscHeap) {
  1163  			src->esc = EscScope;
  1164  			if(debug['m'])
  1165  				warnl(src->lineno, "leaking param: %hN", src);
  1166  		}
  1167  
  1168  		// Treat a PPARAMREF closure variable as equivalent to the
  1169  		// original variable.
  1170  		if(src->class == PPARAMREF) {
  1171  			if(leaks && debug['m'])
  1172  				warnl(src->lineno, "leaking closure reference %hN", src);
  1173  			escwalk(e, level, dst, src->closure);
  1174  		}
  1175  		break;
  1176  
  1177  	case OPTRLIT:
  1178  	case OADDR:
  1179  		if(leaks) {
  1180  			src->esc = EscHeap;
  1181  			addrescapes(src->left);
  1182  			if(debug['m'])
  1183  				warnl(src->lineno, "%hN escapes to heap", src);
  1184  		}
  1185  		newlevel = level;
  1186  		if(level > MinLevel)
  1187  			newlevel--;
  1188  		escwalk(e, newlevel, dst, src->left);
  1189  		break;
  1190  
  1191  	case OARRAYLIT:
  1192  		if(isfixedarray(src->type))
  1193  			break;
  1194  		// fall through
  1195  	case ODDDARG:
  1196  	case OMAKECHAN:
  1197  	case OMAKEMAP:
  1198  	case OMAKESLICE:
  1199  	case OMAPLIT:
  1200  	case ONEW:
  1201  	case OCLOSURE:
  1202  	case OCALLPART:
  1203  		if(leaks) {
  1204  			src->esc = EscHeap;
  1205  			if(debug['m'])
  1206  				warnl(src->lineno, "%hN escapes to heap", src);
  1207  		}
  1208  		break;
  1209  
  1210  	case ODOT:
  1211  	case OSLICE:
  1212  	case OSLICEARR:
  1213  	case OSLICE3:
  1214  	case OSLICE3ARR:
  1215  		escwalk(e, level, dst, src->left);
  1216  		break;
  1217  
  1218  	case OINDEX:
  1219  		if(isfixedarray(src->left->type)) {
  1220  			escwalk(e, level, dst, src->left);
  1221  			break;
  1222  		}
  1223  		// fall through
  1224  	case ODOTPTR:
  1225  	case OINDEXMAP:
  1226  	case OIND:
  1227  		newlevel = level;
  1228  		if(level > MinLevel)
  1229  			newlevel++;
  1230  		escwalk(e, newlevel, dst, src->left);
  1231  	}
  1232  
  1233  recurse:
  1234  	for(ll=src->escflowsrc; ll; ll=ll->next)
  1235  		escwalk(e, level, dst, ll->n);
  1236  
  1237  	e->pdepth--;
  1238  }
  1239  
  1240  static void
  1241  esctag(EscState *e, Node *func)
  1242  {
  1243  	Node *savefn;
  1244  	NodeList *ll;
  1245  	Type *t;
  1246  
  1247  	USED(e);
  1248  	func->esc = EscFuncTagged;
  1249  	
  1250  	// External functions are assumed unsafe,
  1251  	// unless //go:noescape is given before the declaration.
  1252  	if(func->nbody == nil) {
  1253  		if(func->noescape) {
  1254  			for(t=getinargx(func->type)->type; t; t=t->down)
  1255  				if(haspointers(t->type))
  1256  					t->note = mktag(EscNone);
  1257  		}
  1258  		return;
  1259  	}
  1260  
  1261  	savefn = curfn;
  1262  	curfn = func;
  1263  
  1264  	for(ll=curfn->dcl; ll; ll=ll->next) {
  1265  		if(ll->n->op != ONAME || ll->n->class != PPARAM)
  1266  			continue;
  1267  
  1268  		switch (ll->n->esc&EscMask) {
  1269  		case EscNone:	// not touched by escflood
  1270  		case EscReturn:	
  1271  			if(haspointers(ll->n->type)) // don't bother tagging for scalars
  1272  				ll->n->paramfld->note = mktag(ll->n->esc);
  1273  			break;
  1274  		case EscHeap:	// touched by escflood, moved to heap
  1275  		case EscScope:	// touched by escflood, value leaves scope
  1276  			break;
  1277  		}
  1278  	}
  1279  
  1280  	curfn = savefn;
  1281  }