github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/cmd/gc/inl.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  // The inlining facility makes 2 passes: first caninl determines which
     6  // functions are suitable for inlining, and for those that are it
     7  // saves a copy of the body. Then inlcalls walks each function body to
     8  // expand calls to inlinable functions.
     9  //
    10  // The debug['l'] flag controls the agressiveness. Note that main() swaps level 0 and 1,
    11  // making 1 the default and -l disable.  -ll and more is useful to flush out bugs.
    12  // These additional levels (beyond -l) may be buggy and are not supported.
    13  //      0: disabled
    14  //      1: 40-nodes leaf functions, oneliners, lazy typechecking (default)
    15  //      2: early typechecking of all imported bodies 
    16  //      3: allow variadic functions
    17  //      4: allow non-leaf functions , (breaks runtime.Caller)
    18  //      5: transitive inlining
    19  //
    20  //  At some point this may get another default and become switch-offable with -N.
    21  //
    22  //  The debug['m'] flag enables diagnostic output.  a single -m is useful for verifying
    23  //  which calls get inlined or not, more is for debugging, and may go away at any point.
    24  //
    25  // TODO:
    26  //   - inline functions with ... args
    27  //   - handle T.meth(f()) with func f() (t T, arg, arg, )
    28  
    29  #include <u.h>
    30  #include <libc.h>
    31  #include "go.h"
    32  
    33  // Used by caninl.
    34  static Node*	inlcopy(Node *n);
    35  static NodeList* inlcopylist(NodeList *ll);
    36  static int	ishairy(Node *n, int *budget);
    37  static int	ishairylist(NodeList *ll, int *budget); 
    38  
    39  // Used by inlcalls
    40  static void	inlnodelist(NodeList *l);
    41  static void	inlnode(Node **np);
    42  static void	mkinlcall(Node **np, Node *fn, int isddd);
    43  static Node*	inlvar(Node *n);
    44  static Node*	retvar(Type *n, int i);
    45  static Node*	argvar(Type *n, int i);
    46  static Node*	newlabel(void);
    47  static Node*	inlsubst(Node *n);
    48  static NodeList* inlsubstlist(NodeList *l);
    49  
    50  static void	setlno(Node*, int);
    51  
    52  // Used during inlsubst[list]
    53  static Node *inlfn;		// function currently being inlined
    54  static Node *inlretlabel;	// target of the goto substituted in place of a return
    55  static NodeList *inlretvars;	// temp out variables
    56  
    57  // Get the function's package.  For ordinary functions it's on the ->sym, but for imported methods
    58  // the ->sym can be re-used in the local package, so peel it off the receiver's type.
    59  static Pkg*
    60  fnpkg(Node *fn)
    61  {
    62  	Type *rcvr;
    63  	
    64  	if(fn->type->thistuple) {
    65  		// method
    66  		rcvr = getthisx(fn->type)->type->type;
    67  		if(isptr[rcvr->etype])
    68  			rcvr = rcvr->type;
    69  		if(!rcvr->sym)
    70  			fatal("receiver with no sym: [%S] %lN  (%T)", fn->sym, fn, rcvr);
    71  		return rcvr->sym->pkg;
    72  	}
    73  	// non-method
    74  	return fn->sym->pkg;
    75  }
    76  
    77  // Lazy typechecking of imported bodies.  For local functions, caninl will set ->typecheck
    78  // because they're a copy of an already checked body. 
    79  void
    80  typecheckinl(Node *fn)
    81  {
    82  	Node *savefn;
    83  	Pkg *pkg;
    84  	int save_safemode, lno;
    85  
    86  	lno = setlineno(fn);
    87  
    88  	// typecheckinl is only for imported functions;
    89  	// their bodies may refer to unsafe as long as the package
    90  	// was marked safe during import (which was checked then).
    91  	// the ->inl of a local function has been typechecked before caninl copied it.
    92  	pkg = fnpkg(fn);
    93  	if (pkg == localpkg || pkg == nil)
    94  		return; // typecheckinl on local function
    95  
    96  	if (debug['m']>2)
    97  		print("typecheck import [%S] %lN { %#H }\n", fn->sym, fn, fn->inl);
    98  
    99  	save_safemode = safemode;
   100  	safemode = 0;
   101  
   102  	savefn = curfn;
   103  	curfn = fn;
   104  	typechecklist(fn->inl, Etop);
   105  	curfn = savefn;
   106  
   107  	safemode = save_safemode;
   108  
   109  	lineno = lno;
   110  }
   111  
   112  // Caninl determines whether fn is inlineable.
   113  // If so, caninl saves fn->nbody in fn->inl and substitutes it with a copy.
   114  // fn and ->nbody will already have been typechecked.
   115  void
   116  caninl(Node *fn)
   117  {
   118  	Node *savefn;
   119  	Type *t;
   120  	int budget;
   121  
   122  	if(fn->op != ODCLFUNC)
   123  		fatal("caninl %N", fn);
   124  	if(!fn->nname)
   125  		fatal("caninl no nname %+N", fn);
   126  
   127  	// If fn has no body (is defined outside of Go), cannot inline it.
   128  	if(fn->nbody == nil)
   129  		return;
   130  
   131  	if(fn->typecheck == 0)
   132  		fatal("caninl on non-typechecked function %N", fn);
   133  
   134  	// can't handle ... args yet
   135  	if(debug['l'] < 3)
   136  		for(t=fn->type->type->down->down->type; t; t=t->down)
   137  			if(t->isddd)
   138  				return;
   139  
   140  	budget = 40;  // allowed hairyness
   141  	if(ishairylist(fn->nbody, &budget))
   142  		return;
   143  
   144  	savefn = curfn;
   145  	curfn = fn;
   146  
   147  	fn->nname->inl = fn->nbody;
   148  	fn->nbody = inlcopylist(fn->nname->inl);
   149  	fn->nname->inldcl = inlcopylist(fn->nname->defn->dcl);
   150  
   151  	// hack, TODO, check for better way to link method nodes back to the thing with the ->inl
   152  	// this is so export can find the body of a method
   153  	fn->type->nname = fn->nname;
   154  
   155  	if(debug['m'] > 1)
   156  		print("%L: can inline %#N as: %#T { %#H }\n", fn->lineno, fn->nname, fn->type, fn->nname->inl);
   157  	else if(debug['m'])
   158  		print("%L: can inline %N\n", fn->lineno, fn->nname);
   159  
   160  	curfn = savefn;
   161  }
   162  
   163  // Look for anything we want to punt on.
   164  static int
   165  ishairylist(NodeList *ll, int* budget)
   166  {
   167  	for(;ll;ll=ll->next)
   168  		if(ishairy(ll->n, budget))
   169  			return 1;
   170  	return 0;
   171  }
   172  
   173  static int
   174  ishairy(Node *n, int *budget)
   175  {
   176  	if(!n)
   177  		return 0;
   178  
   179  	// Things that are too hairy, irrespective of the budget
   180  	switch(n->op) {
   181  	case OCALL:
   182  	case OCALLFUNC:
   183  	case OCALLINTER:
   184  	case OCALLMETH:
   185  	case OPANIC:
   186  	case ORECOVER:
   187  		if(debug['l'] < 4)
   188  			return 1;
   189  		break;
   190  
   191  	case OCLOSURE:
   192  	case OCALLPART:
   193  	case ORANGE:
   194  	case OFOR:
   195  	case OSELECT:
   196  	case OSWITCH:
   197  	case OPROC:
   198  	case ODEFER:
   199  	case ODCLTYPE:  // can't print yet
   200  	case ODCLCONST:  // can't print yet
   201  	case ORETJMP:
   202  		return 1;
   203  
   204  		break;
   205  	}
   206  
   207  	(*budget)--;
   208  
   209  	return  *budget < 0 ||
   210  		ishairy(n->left, budget) ||
   211  		ishairy(n->right, budget) ||
   212  		ishairylist(n->list, budget) ||
   213  		ishairylist(n->rlist, budget) ||
   214  		ishairylist(n->ninit, budget) ||
   215  		ishairy(n->ntest, budget) ||
   216  		ishairy(n->nincr, budget) ||
   217  		ishairylist(n->nbody, budget) ||
   218  		ishairylist(n->nelse, budget);
   219  }
   220  
   221  // Inlcopy and inlcopylist recursively copy the body of a function.
   222  // Any name-like node of non-local class is marked for re-export by adding it to
   223  // the exportlist.
   224  static NodeList*
   225  inlcopylist(NodeList *ll)
   226  {
   227  	NodeList *l;
   228  
   229  	l = nil;
   230  	for(; ll; ll=ll->next)
   231  		l = list(l, inlcopy(ll->n));
   232  	return l;
   233  }
   234  
   235  static Node*
   236  inlcopy(Node *n)
   237  {
   238  	Node *m;
   239  
   240  	if(n == N)
   241  		return N;
   242  
   243  	switch(n->op) {
   244  	case ONAME:
   245  	case OTYPE:
   246  	case OLITERAL:
   247  		return n;
   248  	}
   249  
   250  	m = nod(OXXX, N, N);
   251  	*m = *n;
   252  	m->inl = nil;
   253  	m->left	  = inlcopy(n->left);
   254  	m->right  = inlcopy(n->right);
   255  	m->list   = inlcopylist(n->list);
   256  	m->rlist  = inlcopylist(n->rlist);
   257  	m->ninit  = inlcopylist(n->ninit);
   258  	m->ntest  = inlcopy(n->ntest);
   259  	m->nincr  = inlcopy(n->nincr);
   260  	m->nbody  = inlcopylist(n->nbody);
   261  	m->nelse  = inlcopylist(n->nelse);
   262  
   263  	return m;
   264  }
   265  
   266  
   267  // Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any
   268  // calls made to inlineable functions.  This is the external entry point.
   269  void
   270  inlcalls(Node *fn)
   271  {
   272  	Node *savefn;
   273  
   274  	savefn = curfn;
   275  	curfn = fn;
   276  	inlnode(&fn);
   277  	if(fn != curfn)
   278  		fatal("inlnode replaced curfn");
   279  	curfn = savefn;
   280  }
   281  
   282  // Turn an OINLCALL into a statement.
   283  static void
   284  inlconv2stmt(Node *n)
   285  {
   286  	n->op = OBLOCK;
   287  	// n->ninit stays
   288  	n->list = n->nbody;
   289  	n->nbody = nil;
   290  	n->rlist = nil;
   291  }
   292  
   293  // Turn an OINLCALL into a single valued expression.
   294  static void
   295  inlconv2expr(Node **np)
   296  {
   297  	Node *n, *r;
   298  	n = *np;
   299  	r = n->rlist->n;
   300  	addinit(&r, concat(n->ninit, n->nbody));
   301  	*np = r;
   302  }
   303  
   304  // Turn the rlist (with the return values) of the OINLCALL in
   305  // n into an expression list lumping the ninit and body
   306  // containing the inlined statements on the first list element so
   307  // order will be preserved Used in return, oas2func and call
   308  // statements.
   309  static NodeList*
   310  inlconv2list(Node *n)
   311  {
   312  	NodeList *l;
   313  
   314  	if(n->op != OINLCALL || n->rlist == nil)
   315  		fatal("inlconv2list %+N\n", n);
   316  	
   317  	l = n->rlist;
   318  	addinit(&l->n, concat(n->ninit, n->nbody));
   319  	return l;
   320  } 
   321   
   322  static void
   323  inlnodelist(NodeList *l)
   324  {
   325  	for(; l; l=l->next)
   326  		inlnode(&l->n);
   327  }
   328  
   329  // inlnode recurses over the tree to find inlineable calls, which will
   330  // be turned into OINLCALLs by mkinlcall.  When the recursion comes
   331  // back up will examine left, right, list, rlist, ninit, ntest, nincr,
   332  // nbody and nelse and use one of the 4 inlconv/glue functions above
   333  // to turn the OINLCALL into an expression, a statement, or patch it
   334  // in to this nodes list or rlist as appropriate.
   335  // NOTE it makes no sense to pass the glue functions down the
   336  // recursion to the level where the OINLCALL gets created because they
   337  // have to edit /this/ n, so you'd have to push that one down as well,
   338  // but then you may as well do it here.  so this is cleaner and
   339  // shorter and less complicated.
   340  static void
   341  inlnode(Node **np)
   342  {
   343  	Node *n;
   344  	NodeList *l;
   345  	int lno;
   346  
   347  	if(*np == nil)
   348  		return;
   349  
   350  	n = *np;
   351  	
   352  	switch(n->op) {
   353  	case ODEFER:
   354  	case OPROC:
   355  		// inhibit inlining of their argument
   356  		switch(n->left->op) {
   357  		case OCALLFUNC:
   358  		case OCALLMETH:
   359  			n->left->etype = n->op;
   360  		}
   361  
   362  	case OCLOSURE:
   363  		// TODO do them here (or earlier),
   364  		// so escape analysis can avoid more heapmoves.
   365  		return;
   366  	}
   367  
   368  	lno = setlineno(n);
   369  
   370  	inlnodelist(n->ninit);
   371  	for(l=n->ninit; l; l=l->next)
   372  		if(l->n->op == OINLCALL)
   373  			inlconv2stmt(l->n);
   374  
   375  	inlnode(&n->left);
   376  	if(n->left && n->left->op == OINLCALL)
   377  		inlconv2expr(&n->left);
   378  
   379  	inlnode(&n->right);
   380  	if(n->right && n->right->op == OINLCALL)
   381  		inlconv2expr(&n->right);
   382  
   383  	inlnodelist(n->list);
   384  	switch(n->op) {
   385  	case OBLOCK:
   386  		for(l=n->list; l; l=l->next)
   387  			if(l->n->op == OINLCALL)
   388  				inlconv2stmt(l->n);
   389  		break;
   390  
   391  	case ORETURN:
   392  	case OCALLFUNC:
   393  	case OCALLMETH:
   394  	case OCALLINTER:
   395  	case OAPPEND:
   396  	case OCOMPLEX:
   397  		// if we just replaced arg in f(arg()) or return arg with an inlined call
   398  		// and arg returns multiple values, glue as list
   399  		if(count(n->list) == 1 && n->list->n->op == OINLCALL && count(n->list->n->rlist) > 1) {
   400  			n->list = inlconv2list(n->list->n);
   401  			break;
   402  		}
   403  
   404  		// fallthrough
   405  	default:
   406  		for(l=n->list; l; l=l->next)
   407  			if(l->n->op == OINLCALL)
   408  				inlconv2expr(&l->n);
   409  	}
   410  
   411  	inlnodelist(n->rlist);
   412  	switch(n->op) {
   413  	case OAS2FUNC:
   414  		if(n->rlist->n->op == OINLCALL) {
   415  			n->rlist = inlconv2list(n->rlist->n);
   416  			n->op = OAS2;
   417  			n->typecheck = 0;
   418  			typecheck(np, Etop);
   419  			break;
   420  		}
   421  
   422  		// fallthrough
   423  	default:
   424  		for(l=n->rlist; l; l=l->next)
   425  			if(l->n->op == OINLCALL)
   426  				inlconv2expr(&l->n);
   427  
   428  	}
   429  
   430  	inlnode(&n->ntest);
   431  	if(n->ntest && n->ntest->op == OINLCALL)
   432  		inlconv2expr(&n->ntest);
   433  
   434  	inlnode(&n->nincr);
   435  	if(n->nincr && n->nincr->op == OINLCALL)
   436  		inlconv2stmt(n->nincr);
   437  
   438  	inlnodelist(n->nbody);
   439  	for(l=n->nbody; l; l=l->next)
   440  		if(l->n->op == OINLCALL)
   441  			inlconv2stmt(l->n);
   442  
   443  	inlnodelist(n->nelse);
   444  	for(l=n->nelse; l; l=l->next)
   445  		if(l->n->op == OINLCALL)
   446  			inlconv2stmt(l->n);
   447  
   448  	// with all the branches out of the way, it is now time to
   449  	// transmogrify this node itself unless inhibited by the
   450  	// switch at the top of this function.
   451  	switch(n->op) {
   452  	case OCALLFUNC:
   453  	case OCALLMETH:
   454  		if (n->etype == OPROC || n->etype == ODEFER)
   455  			return;
   456  	}
   457  
   458  	switch(n->op) {
   459  	case OCALLFUNC:
   460  		if(debug['m']>3)
   461  			print("%L:call to func %+N\n", n->lineno, n->left);
   462  		if(n->left->inl)	// normal case
   463  			mkinlcall(np, n->left, n->isddd);
   464  		else if(n->left->op == ONAME && n->left->left && n->left->left->op == OTYPE && n->left->right &&  n->left->right->op == ONAME)  // methods called as functions
   465  			if(n->left->sym->def)
   466  				mkinlcall(np, n->left->sym->def, n->isddd);
   467  		break;
   468  
   469  	case OCALLMETH:
   470  		if(debug['m']>3)
   471  			print("%L:call to meth %lN\n", n->lineno, n->left->right);
   472  		// typecheck should have resolved ODOTMETH->type, whose nname points to the actual function.
   473  		if(n->left->type == T) 
   474  			fatal("no function type for [%p] %+N\n", n->left, n->left);
   475  
   476  		if(n->left->type->nname == N) 
   477  			fatal("no function definition for [%p] %+T\n", n->left->type, n->left->type);
   478  
   479  		mkinlcall(np, n->left->type->nname, n->isddd);
   480  
   481  		break;
   482  	}
   483  	
   484  	lineno = lno;
   485  }
   486  
   487  static void	mkinlcall1(Node **np, Node *fn, int isddd);
   488  
   489  static void
   490  mkinlcall(Node **np, Node *fn, int isddd)
   491  {
   492  	int save_safemode;
   493  	Pkg *pkg;
   494  
   495  	save_safemode = safemode;
   496  
   497  	// imported functions may refer to unsafe as long as the
   498  	// package was marked safe during import (already checked).
   499  	pkg = fnpkg(fn);
   500  	if(pkg != localpkg && pkg != nil)
   501  		safemode = 0;
   502  	mkinlcall1(np, fn, isddd);
   503  	safemode = save_safemode;
   504  }
   505  
   506  static Node*
   507  tinlvar(Type *t)
   508  {
   509  	if(t->nname && !isblank(t->nname)) {
   510  		if(!t->nname->inlvar)
   511  			fatal("missing inlvar for %N\n", t->nname);
   512  		return t->nname->inlvar;
   513  	}
   514  	typecheck(&nblank, Erv | Easgn);
   515  	return nblank;
   516  }
   517  
   518  static int inlgen;
   519  
   520  // if *np is a call, and fn is a function with an inlinable body, substitute *np with an OINLCALL.
   521  // On return ninit has the parameter assignments, the nbody is the
   522  // inlined function body and list, rlist contain the input, output
   523  // parameters.
   524  static void
   525  mkinlcall1(Node **np, Node *fn, int isddd)
   526  {
   527  	int i;
   528  	int chkargcount;
   529  	Node *n, *call, *saveinlfn, *as, *m;
   530  	NodeList *dcl, *ll, *ninit, *body;
   531  	Type *t;
   532  	// For variadic fn.
   533  	int variadic, varargcount, multiret;
   534  	Node *vararg;
   535  	NodeList *varargs;
   536  	Type *varargtype, *vararrtype;
   537  
   538  	if (fn->inl == nil)
   539  		return;
   540  
   541  	if (fn == curfn || fn->defn == curfn)
   542  		return;
   543  
   544  	if(debug['l']<2)
   545  		typecheckinl(fn);
   546  
   547  	n = *np;
   548  
   549  	// Bingo, we have a function node, and it has an inlineable body
   550  	if(debug['m']>1)
   551  		print("%L: inlining call to %S %#T { %#H }\n", n->lineno, fn->sym, fn->type, fn->inl);
   552  	else if(debug['m'])
   553  		print("%L: inlining call to %N\n", n->lineno, fn);
   554  
   555  	if(debug['m']>2)
   556  		print("%L: Before inlining: %+N\n", n->lineno, n);
   557  
   558  	saveinlfn = inlfn;
   559  	inlfn = fn;
   560  
   561  	ninit = n->ninit;
   562  
   563  //dumplist("ninit pre", ninit);
   564  
   565  	if(fn->defn) // local function
   566  		dcl = fn->inldcl;
   567  	else // imported function
   568  		dcl = fn->dcl;
   569  
   570  	inlretvars = nil;
   571  	i = 0;
   572  	// Make temp names to use instead of the originals
   573  	for(ll = dcl; ll; ll=ll->next) {
   574  		if(ll->n->class == PPARAMOUT)  // return values handled below.
   575  			continue;
   576  		if(ll->n->op == ONAME) {
   577  			ll->n->inlvar = inlvar(ll->n);
   578  			// Typecheck because inlvar is not necessarily a function parameter.
   579  			typecheck(&ll->n->inlvar, Erv);
   580  			if ((ll->n->class&~PHEAP) != PAUTO)
   581  				ninit = list(ninit, nod(ODCL, ll->n->inlvar, N));  // otherwise gen won't emit the allocations for heapallocs
   582  		}
   583  	}
   584  
   585  	// temporaries for return values.
   586  	for(t = getoutargx(fn->type)->type; t; t = t->down) {
   587  		if(t != T && t->nname != N && !isblank(t->nname)) {
   588  			m = inlvar(t->nname);
   589  			typecheck(&m, Erv);
   590  			t->nname->inlvar = m;
   591  		} else {
   592  			// anonymous return values, synthesize names for use in assignment that replaces return
   593  			m = retvar(t, i++);
   594  		}
   595  		ninit = list(ninit, nod(ODCL, m, N));
   596  		inlretvars = list(inlretvars, m);
   597  	}
   598  
   599  	// assign receiver.
   600  	if(fn->type->thistuple && n->left->op == ODOTMETH) {
   601  		// method call with a receiver.
   602  		t = getthisx(fn->type)->type;
   603  		if(t != T && t->nname != N && !isblank(t->nname) && !t->nname->inlvar)
   604  			fatal("missing inlvar for %N\n", t->nname);
   605  		if(!n->left->left)
   606  			fatal("method call without receiver: %+N", n);
   607  		if(t == T)
   608  			fatal("method call unknown receiver type: %+N", n);
   609  		as = nod(OAS, tinlvar(t), n->left->left);
   610  		if(as != N) {
   611  			typecheck(&as, Etop);
   612  			ninit = list(ninit, as);
   613  		}
   614  	}
   615  
   616  	// check if inlined function is variadic.
   617  	variadic = 0;
   618  	varargtype = T;
   619  	varargcount = 0;
   620  	for(t=fn->type->type->down->down->type; t; t=t->down) {
   621  		if(t->isddd) {
   622  			variadic = 1;
   623  			varargtype = t->type;
   624  		}
   625  	}
   626  	// but if argument is dotted too forget about variadicity.
   627  	if(variadic && isddd)
   628  		variadic = 0;
   629  
   630  	// check if argument is actually a returned tuple from call.
   631  	multiret = 0;
   632  	if(n->list && !n->list->next) {
   633  		switch(n->list->n->op) {
   634  		case OCALL:
   635  		case OCALLFUNC:
   636  		case OCALLINTER:
   637  		case OCALLMETH:
   638  			if(n->list->n->left->type->outtuple > 1)
   639  				multiret = n->list->n->left->type->outtuple-1;
   640  		}
   641  	}
   642  
   643  	if(variadic) {
   644  		varargcount = count(n->list) + multiret;
   645  		if(n->left->op != ODOTMETH)
   646  			varargcount -= fn->type->thistuple;
   647  		varargcount -= fn->type->intuple - 1;
   648  	}
   649  
   650  	// assign arguments to the parameters' temp names
   651  	as = nod(OAS2, N, N);
   652  	as->rlist = n->list;
   653  	ll = n->list;
   654  
   655  	// TODO: if len(nlist) == 1 but multiple args, check that n->list->n is a call?
   656  	if(fn->type->thistuple && n->left->op != ODOTMETH) {
   657  		// non-method call to method
   658  		if(!n->list)
   659  			fatal("non-method call to method without first arg: %+N", n);
   660  		// append receiver inlvar to LHS.
   661  		t = getthisx(fn->type)->type;
   662  		if(t != T && t->nname != N && !isblank(t->nname) && !t->nname->inlvar)
   663  			fatal("missing inlvar for %N\n", t->nname);
   664  		if(t == T)
   665  			fatal("method call unknown receiver type: %+N", n);
   666  		as->list = list(as->list, tinlvar(t));
   667  		ll = ll->next; // track argument count.
   668  	}
   669  
   670  	// append ordinary arguments to LHS.
   671  	chkargcount = n->list && n->list->next;
   672  	vararg = N;    // the slice argument to a variadic call
   673  	varargs = nil; // the list of LHS names to put in vararg.
   674  	if(!chkargcount) {
   675  		// 0 or 1 expression on RHS.
   676  		for(t = getinargx(fn->type)->type; t; t=t->down) {
   677  			if(variadic && t->isddd) {
   678  				vararg = tinlvar(t);
   679  				for(i=0; i<varargcount && ll; i++) {
   680  					m = argvar(varargtype, i);
   681  					varargs = list(varargs, m);
   682  					as->list = list(as->list, m);
   683  				}
   684  				break;
   685  			}
   686  			as->list = list(as->list, tinlvar(t));
   687  		}
   688  	} else {
   689  		// match arguments except final variadic (unless the call is dotted itself)
   690  		for(t = getinargx(fn->type)->type; t;) {
   691  			if(!ll)
   692  				break;
   693  			if(variadic && t->isddd)
   694  				break;
   695  			as->list = list(as->list, tinlvar(t));
   696  			t=t->down;
   697  			ll=ll->next;
   698  		}
   699  		// match varargcount arguments with variadic parameters.
   700  		if(variadic && t && t->isddd) {
   701  			vararg = tinlvar(t);
   702  			for(i=0; i<varargcount && ll; i++) {
   703  				m = argvar(varargtype, i);
   704  				varargs = list(varargs, m);
   705  				as->list = list(as->list, m);
   706  				ll=ll->next;
   707  			}
   708  			if(i==varargcount)
   709  				t=t->down;
   710  		}
   711  		if(ll || t)
   712  			fatal("arg count mismatch: %#T  vs %,H\n",  getinargx(fn->type), n->list);
   713  	}
   714  
   715  	if (as->rlist) {
   716  		typecheck(&as, Etop);
   717  		ninit = list(ninit, as);
   718  	}
   719  
   720  	// turn the variadic args into a slice.
   721  	if(variadic) {
   722  		as = nod(OAS, vararg, N);
   723  		if(!varargcount) {
   724  			as->right = nodnil();
   725  			as->right->type = varargtype;
   726  		} else {
   727  			vararrtype = typ(TARRAY);
   728  			vararrtype->type = varargtype->type;
   729  			vararrtype->bound = varargcount;
   730  
   731  			as->right = nod(OCOMPLIT, N, typenod(varargtype));
   732  			as->right->list = varargs;
   733  			as->right = nod(OSLICE, as->right, nod(OKEY, N, N));
   734  		}
   735  		typecheck(&as, Etop);
   736  		ninit = list(ninit, as);
   737  	}
   738  
   739  	// zero the outparams
   740  	for(ll = inlretvars; ll; ll=ll->next) {
   741  		as = nod(OAS, ll->n, N);
   742  		typecheck(&as, Etop);
   743  		ninit = list(ninit, as);
   744  	}
   745  
   746  	inlretlabel = newlabel();
   747  	inlgen++;
   748  	body = inlsubstlist(fn->inl);
   749  
   750  	body = list(body, nod(OGOTO, inlretlabel, N));	// avoid 'not used' when function doesnt have return
   751  	body = list(body, nod(OLABEL, inlretlabel, N));
   752  
   753  	typechecklist(body, Etop);
   754  //dumplist("ninit post", ninit);
   755  
   756  	call = nod(OINLCALL, N, N);
   757  	call->ninit = ninit;
   758  	call->nbody = body;
   759  	call->rlist = inlretvars;
   760  	call->type = n->type;
   761  	call->typecheck = 1;
   762  
   763  	setlno(call, n->lineno);
   764  //dumplist("call body", body);
   765  
   766  	*np = call;
   767  
   768  	inlfn =	saveinlfn;
   769  
   770  	// transitive inlining
   771  	// TODO do this pre-expansion on fn->inl directly.  requires
   772  	// either supporting exporting statemetns with complex ninits
   773  	// or saving inl and making inlinl
   774  	if(debug['l'] >= 5) {
   775  		body = fn->inl;
   776  		fn->inl = nil;	// prevent infinite recursion
   777  		inlnodelist(call->nbody);
   778  		for(ll=call->nbody; ll; ll=ll->next)
   779  			if(ll->n->op == OINLCALL)
   780  				inlconv2stmt(ll->n);
   781  		fn->inl = body;
   782  	}
   783  
   784  	if(debug['m']>2)
   785  		print("%L: After inlining %+N\n\n", n->lineno, *np);
   786  
   787  }
   788  
   789  // Every time we expand a function we generate a new set of tmpnames,
   790  // PAUTO's in the calling functions, and link them off of the
   791  // PPARAM's, PAUTOS and PPARAMOUTs of the called function. 
   792  static Node*
   793  inlvar(Node *var)
   794  {
   795  	Node *n;
   796  
   797  	if(debug['m']>3)
   798  		print("inlvar %+N\n", var);
   799  
   800  	n = newname(var->sym);
   801  	n->type = var->type;
   802  	n->class = PAUTO;
   803  	n->used = 1;
   804  	n->curfn = curfn;   // the calling function, not the called one
   805  	n->addrtaken = var->addrtaken;
   806  
   807  	// esc pass wont run if we're inlining into a iface wrapper
   808  	// luckily, we can steal the results from the target func
   809  	if(var->esc == EscHeap)
   810  		addrescapes(n);
   811  
   812  	curfn->dcl = list(curfn->dcl, n);
   813  	return n;
   814  }
   815  
   816  // Synthesize a variable to store the inlined function's results in.
   817  static Node*
   818  retvar(Type *t, int i)
   819  {
   820  	Node *n;
   821  
   822  	snprint(namebuf, sizeof(namebuf), "~r%d", i);
   823  	n = newname(lookup(namebuf));
   824  	n->type = t->type;
   825  	n->class = PAUTO;
   826  	n->used = 1;
   827  	n->curfn = curfn;   // the calling function, not the called one
   828  	curfn->dcl = list(curfn->dcl, n);
   829  	return n;
   830  }
   831  
   832  // Synthesize a variable to store the inlined function's arguments
   833  // when they come from a multiple return call.
   834  static Node*
   835  argvar(Type *t, int i)
   836  {
   837  	Node *n;
   838  
   839  	snprint(namebuf, sizeof(namebuf), "~arg%d", i);
   840  	n = newname(lookup(namebuf));
   841  	n->type = t->type;
   842  	n->class = PAUTO;
   843  	n->used = 1;
   844  	n->curfn = curfn;   // the calling function, not the called one
   845  	curfn->dcl = list(curfn->dcl, n);
   846  	return n;
   847  }
   848  
   849  static Node*
   850  newlabel(void)
   851  {
   852  	Node *n;
   853  	static int label;
   854  	
   855  	label++;
   856  	snprint(namebuf, sizeof(namebuf), ".inlret%.6d", label);
   857  	n = newname(lookup(namebuf));
   858  	n->etype = 1;  // flag 'safe' for escape analysis (no backjumps)
   859  	return n;
   860  }
   861  
   862  // inlsubst and inlsubstlist recursively copy the body of the saved
   863  // pristine ->inl body of the function while substituting references
   864  // to input/output parameters with ones to the tmpnames, and
   865  // substituting returns with assignments to the output.
   866  static NodeList*
   867  inlsubstlist(NodeList *ll)
   868  {
   869  	NodeList *l;
   870  
   871  	l = nil;
   872  	for(; ll; ll=ll->next)
   873  		l = list(l, inlsubst(ll->n));
   874  	return l;
   875  }
   876  
   877  static Node*
   878  inlsubst(Node *n)
   879  {
   880  	char *p;
   881  	Node *m, *as;
   882  	NodeList *ll;
   883  
   884  	if(n == N)
   885  		return N;
   886  
   887  	switch(n->op) {
   888  	case ONAME:
   889  		if(n->inlvar) { // These will be set during inlnode
   890  			if (debug['m']>2)
   891  				print ("substituting name %+N  ->  %+N\n", n, n->inlvar);
   892  			return n->inlvar;
   893  		}
   894  		if (debug['m']>2)
   895  			print ("not substituting name %+N\n", n);
   896  		return n;
   897  
   898  	case OLITERAL:
   899  	case OTYPE:
   900  		return n;
   901  
   902  	case ORETURN:
   903  		// Since we don't handle bodies with closures, this return is guaranteed to belong to the current inlined function.
   904  
   905  //		dump("Return before substitution", n);
   906  		m = nod(OGOTO, inlretlabel, N);
   907  		m->ninit  = inlsubstlist(n->ninit);
   908  
   909  		if(inlretvars && n->list) {
   910  			as = nod(OAS2, N, N);
   911  			// shallow copy or OINLCALL->rlist will be the same list, and later walk and typecheck may clobber that.
   912  			for(ll=inlretvars; ll; ll=ll->next)
   913  				as->list = list(as->list, ll->n);
   914  			as->rlist = inlsubstlist(n->list);
   915  			typecheck(&as, Etop);
   916  			m->ninit = list(m->ninit, as);
   917  		}
   918  
   919  		typechecklist(m->ninit, Etop);
   920  		typecheck(&m, Etop);
   921  //		dump("Return after substitution", m);
   922  		return m;
   923  	
   924  	case OGOTO:
   925  	case OLABEL:
   926  		m = nod(OXXX, N, N);
   927  		*m = *n;
   928  		m->ninit = nil;
   929  		p = smprint("%s·%d", n->left->sym->name, inlgen);	
   930  		m->left = newname(lookup(p));
   931  		free(p);
   932  		return m;	
   933  	}
   934  
   935  
   936  	m = nod(OXXX, N, N);
   937  	*m = *n;
   938  	m->ninit = nil;
   939  	
   940  	if(n->op == OCLOSURE)
   941  		fatal("cannot inline function containing closure: %+N", n);
   942  
   943  	m->left	  = inlsubst(n->left);
   944  	m->right  = inlsubst(n->right);
   945  	m->list	  = inlsubstlist(n->list);
   946  	m->rlist  = inlsubstlist(n->rlist);
   947  	m->ninit  = concat(m->ninit, inlsubstlist(n->ninit));
   948  	m->ntest  = inlsubst(n->ntest);
   949  	m->nincr  = inlsubst(n->nincr);
   950  	m->nbody  = inlsubstlist(n->nbody);
   951  	m->nelse  = inlsubstlist(n->nelse);
   952  
   953  	return m;
   954  }
   955  
   956  // Plaster over linenumbers
   957  static void
   958  setlnolist(NodeList *ll, int lno)
   959  {
   960  	for(;ll;ll=ll->next)
   961  		setlno(ll->n, lno);
   962  }
   963  
   964  static void
   965  setlno(Node *n, int lno)
   966  {
   967  	if(!n)
   968  		return;
   969  
   970  	// don't clobber names, unless they're freshly synthesized
   971  	if(n->op != ONAME || n->lineno == 0)
   972  		n->lineno = lno;
   973  	
   974  	setlno(n->left, lno);
   975  	setlno(n->right, lno);
   976  	setlnolist(n->list, lno);
   977  	setlnolist(n->rlist, lno);
   978  	setlnolist(n->ninit, lno);
   979  	setlno(n->ntest, lno);
   980  	setlno(n->nincr, lno);
   981  	setlnolist(n->nbody, lno);
   982  	setlnolist(n->nelse, lno);
   983  }