// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// The inlining facility makes 2 passes: first caninl determines which
// functions are suitable for inlining, and for those that are it
// saves a copy of the body. Then inlcalls walks each function body to
// expand calls to inlinable functions.
//
// The debug['l'] flag controls the agressiveness. Note that main() swaps level 0 and 1,
// making 1 the default and -l disable.  -ll and more is useful to flush out bugs.
// These additional levels (beyond -l) may be buggy and are not supported.
//      0: disabled
//      1: 40-nodes leaf functions, oneliners, lazy typechecking (default)
//      2: early typechecking of all imported bodies 
//      3: allow variadic functions
//      4: allow non-leaf functions , (breaks runtime.Caller)
//      5: transitive inlining
//
//  At some point this may get another default and become switch-offable with -N.
//
//  The debug['m'] flag enables diagnostic output.  a single -m is useful for verifying
//  which calls get inlined or not, more is for debugging, and may go away at any point.
//
// TODO:
//   - inline functions with ... args
//   - handle T.meth(f()) with func f() (t T, arg, arg, )

#include <u.h>
#include <libc.h>
#include "go.h"

// Used by caninl.
static Node*	inlcopy(Node *n);
static NodeList* inlcopylist(NodeList *ll);
static int	ishairy(Node *n, int *budget);
static int	ishairylist(NodeList *ll, int *budget); 

// Used by inlcalls
static void	inlnodelist(NodeList *l);
static void	inlnode(Node **np);
static void	mkinlcall(Node **np, Node *fn, int isddd);
static Node*	inlvar(Node *n);
static Node*	retvar(Type *n, int i);
static Node*	argvar(Type *n, int i);
static Node*	newlabel(void);
static Node*	inlsubst(Node *n);
static NodeList* inlsubstlist(NodeList *l);

static void	setlno(Node*, int);

// Used during inlsubst[list]
static Node *inlfn;		// function currently being inlined
static Node *inlretlabel;	// target of the goto substituted in place of a return
static NodeList *inlretvars;	// temp out variables

// Get the function's package.  For ordinary functions it's on the ->sym, but for imported methods
// the ->sym can be re-used in the local package, so peel it off the receiver's type.
static Pkg*
fnpkg(Node *fn)
{
	Type *rcvr;
	
	if(fn->type->thistuple) {
		// method
		rcvr = getthisx(fn->type)->type->type;
		if(isptr[rcvr->etype])
			rcvr = rcvr->type;
		if(!rcvr->sym)
			fatal("receiver with no sym: [%S] %lN  (%T)", fn->sym, fn, rcvr);
		return rcvr->sym->pkg;
	}
	// non-method
	return fn->sym->pkg;
}

// Lazy typechecking of imported bodies.  For local functions, caninl will set ->typecheck
// because they're a copy of an already checked body. 
void
typecheckinl(Node *fn)
{
	Node *savefn;
	Pkg *pkg;
	int save_safemode, lno;

	lno = setlineno(fn);

	// typecheckinl is only for imported functions;
	// their bodies may refer to unsafe as long as the package
	// was marked safe during import (which was checked then).
	// the ->inl of a local function has been typechecked before caninl copied it.
	pkg = fnpkg(fn);
	if (pkg == localpkg || pkg == nil)
		return; // typecheckinl on local function

	if (debug['m']>2)
		print("typecheck import [%S] %lN { %#H }\n", fn->sym, fn, fn->inl);

	save_safemode = safemode;
	safemode = 0;

	savefn = curfn;
	curfn = fn;
	typechecklist(fn->inl, Etop);
	curfn = savefn;

	safemode = save_safemode;

	lineno = lno;
}

// Caninl determines whether fn is inlineable.
// If so, caninl saves fn->nbody in fn->inl and substitutes it with a copy.
// fn and ->nbody will already have been typechecked.
void
caninl(Node *fn)
{
	Node *savefn;
	Type *t;
	int budget;

	if(fn->op != ODCLFUNC)
		fatal("caninl %N", fn);
	if(!fn->nname)
		fatal("caninl no nname %+N", fn);

	// If fn has no body (is defined outside of Go), cannot inline it.
	if(fn->nbody == nil)
		return;

	if(fn->typecheck == 0)
		fatal("caninl on non-typechecked function %N", fn);

	// can't handle ... args yet
	if(debug['l'] < 3)
		for(t=fn->type->type->down->down->type; t; t=t->down)
			if(t->isddd)
				return;

	budget = 40;  // allowed hairyness
	if(ishairylist(fn->nbody, &budget))
		return;

	savefn = curfn;
	curfn = fn;

	fn->nname->inl = fn->nbody;
	fn->nbody = inlcopylist(fn->nname->inl);

	// hack, TODO, check for better way to link method nodes back to the thing with the ->inl
	// this is so export can find the body of a method
	fn->type->nname = fn->nname;

	if(debug['m'] > 1)
		print("%L: can inline %#N as: %#T { %#H }\n", fn->lineno, fn->nname, fn->type, fn->nname->inl);
	else if(debug['m'])
		print("%L: can inline %N\n", fn->lineno, fn->nname);

	curfn = savefn;
}

// Look for anything we want to punt on.
static int
ishairylist(NodeList *ll, int* budget)
{
	for(;ll;ll=ll->next)
		if(ishairy(ll->n, budget))
			return 1;
	return 0;
}

static int
ishairy(Node *n, int *budget)
{
	if(!n)
		return 0;

	// Things that are too hairy, irrespective of the budget
	switch(n->op) {
	case OCALL:
	case OCALLFUNC:
	case OCALLINTER:
	case OCALLMETH:
	case OPANIC:
	case ORECOVER:
		if(debug['l'] < 4)
			return 1;
		break;

	case OCLOSURE:
	case OCALLPART:
	case ORANGE:
	case OFOR:
	case OSELECT:
	case OSWITCH:
	case OPROC:
	case ODEFER:
	case ODCLTYPE:  // can't print yet
	case ODCLCONST:  // can't print yet
		return 1;

		break;
	}

	(*budget)--;

	return  *budget < 0 ||
		ishairy(n->left, budget) ||
		ishairy(n->right, budget) ||
		ishairylist(n->list, budget) ||
		ishairylist(n->rlist, budget) ||
		ishairylist(n->ninit, budget) ||
		ishairy(n->ntest, budget) ||
		ishairy(n->nincr, budget) ||
		ishairylist(n->nbody, budget) ||
		ishairylist(n->nelse, budget);
}

// Inlcopy and inlcopylist recursively copy the body of a function.
// Any name-like node of non-local class is marked for re-export by adding it to
// the exportlist.
static NodeList*
inlcopylist(NodeList *ll)
{
	NodeList *l;

	l = nil;
	for(; ll; ll=ll->next)
		l = list(l, inlcopy(ll->n));
	return l;
}

static Node*
inlcopy(Node *n)
{
	Node *m;

	if(n == N)
		return N;

	switch(n->op) {
	case ONAME:
	case OTYPE:
	case OLITERAL:
		return n;
	}

	m = nod(OXXX, N, N);
	*m = *n;
	m->inl = nil;
	m->left	  = inlcopy(n->left);
	m->right  = inlcopy(n->right);
	m->list   = inlcopylist(n->list);
	m->rlist  = inlcopylist(n->rlist);
	m->ninit  = inlcopylist(n->ninit);
	m->ntest  = inlcopy(n->ntest);
	m->nincr  = inlcopy(n->nincr);
	m->nbody  = inlcopylist(n->nbody);
	m->nelse  = inlcopylist(n->nelse);

	return m;
}


// Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any
// calls made to inlineable functions.  This is the external entry point.
void
inlcalls(Node *fn)
{
	Node *savefn;

	savefn = curfn;
	curfn = fn;
	inlnode(&fn);
	if(fn != curfn)
		fatal("inlnode replaced curfn");
	curfn = savefn;
}

// Turn an OINLCALL into a statement.
static void
inlconv2stmt(Node *n)
{
	n->op = OBLOCK;
	// n->ninit stays
	n->list = n->nbody;
	n->nbody = nil;
	n->rlist = nil;
}

// Turn an OINLCALL into a single valued expression.
static void
inlconv2expr(Node **np)
{
	Node *n, *r;
	n = *np;
	r = n->rlist->n;
	addinit(&r, concat(n->ninit, n->nbody));
	*np = r;
}

// Turn the rlist (with the return values) of the OINLCALL in
// n into an expression list lumping the ninit and body
// containing the inlined statements on the first list element so
// order will be preserved Used in return, oas2func and call
// statements.
static NodeList*
inlconv2list(Node *n)
{
	NodeList *l;

	if(n->op != OINLCALL || n->rlist == nil)
		fatal("inlconv2list %+N\n", n);
	
	l = n->rlist;
	addinit(&l->n, concat(n->ninit, n->nbody));
	return l;
} 
 
static void
inlnodelist(NodeList *l)
{
	for(; l; l=l->next)
		inlnode(&l->n);
}

// inlnode recurses over the tree to find inlineable calls, which will
// be turned into OINLCALLs by mkinlcall.  When the recursion comes
// back up will examine left, right, list, rlist, ninit, ntest, nincr,
// nbody and nelse and use one of the 4 inlconv/glue functions above
// to turn the OINLCALL into an expression, a statement, or patch it
// in to this nodes list or rlist as appropriate.
// NOTE it makes no sense to pass the glue functions down the
// recursion to the level where the OINLCALL gets created because they
// have to edit /this/ n, so you'd have to push that one down as well,
// but then you may as well do it here.  so this is cleaner and
// shorter and less complicated.
static void
inlnode(Node **np)
{
	Node *n;
	NodeList *l;
	int lno;

	if(*np == nil)
		return;

	n = *np;
	
	switch(n->op) {
	case ODEFER:
	case OPROC:
		// inhibit inlining of their argument
		switch(n->left->op) {
		case OCALLFUNC:
		case OCALLMETH:
			n->left->etype = n->op;
		}

	case OCLOSURE:
		// TODO do them here (or earlier),
		// so escape analysis can avoid more heapmoves.
		return;
	}

	lno = setlineno(n);

	inlnodelist(n->ninit);
	for(l=n->ninit; l; l=l->next)
		if(l->n->op == OINLCALL)
			inlconv2stmt(l->n);

	inlnode(&n->left);
	if(n->left && n->left->op == OINLCALL)
		inlconv2expr(&n->left);

	inlnode(&n->right);
	if(n->right && n->right->op == OINLCALL)
		inlconv2expr(&n->right);

	inlnodelist(n->list);
	switch(n->op) {
	case OBLOCK:
		for(l=n->list; l; l=l->next)
			if(l->n->op == OINLCALL)
				inlconv2stmt(l->n);
		break;

	case ORETURN:
	case OCALLFUNC:
	case OCALLMETH:
	case OCALLINTER:
		// if we just replaced arg in f(arg()) or return arg with an inlined call
		// and arg returns multiple values, glue as list
		if(count(n->list) == 1 && n->list->n->op == OINLCALL && count(n->list->n->rlist) > 1) {
			n->list = inlconv2list(n->list->n);
			break;
		}

		// fallthrough
	default:
		for(l=n->list; l; l=l->next)
			if(l->n->op == OINLCALL)
				inlconv2expr(&l->n);
	}

	inlnodelist(n->rlist);
	switch(n->op) {
	case OAS2FUNC:
		if(n->rlist->n->op == OINLCALL) {
			n->rlist = inlconv2list(n->rlist->n);
			n->op = OAS2;
			n->typecheck = 0;
			typecheck(np, Etop);
			break;
		}

		// fallthrough
	default:
		for(l=n->rlist; l; l=l->next)
			if(l->n->op == OINLCALL)
				inlconv2expr(&l->n);

	}

	inlnode(&n->ntest);
	if(n->ntest && n->ntest->op == OINLCALL)
		inlconv2expr(&n->ntest);

	inlnode(&n->nincr);
	if(n->nincr && n->nincr->op == OINLCALL)
		inlconv2stmt(n->nincr);

	inlnodelist(n->nbody);
	for(l=n->nbody; l; l=l->next)
		if(l->n->op == OINLCALL)
			inlconv2stmt(l->n);

	inlnodelist(n->nelse);
	for(l=n->nelse; l; l=l->next)
		if(l->n->op == OINLCALL)
			inlconv2stmt(l->n);

	// with all the branches out of the way, it is now time to
	// transmogrify this node itself unless inhibited by the
	// switch at the top of this function.
	switch(n->op) {
	case OCALLFUNC:
	case OCALLMETH:
		if (n->etype == OPROC || n->etype == ODEFER)
			return;
	}

	switch(n->op) {
	case OCALLFUNC:
		if(debug['m']>3)
			print("%L:call to func %+N\n", n->lineno, n->left);
		if(n->left->inl)	// normal case
			mkinlcall(np, n->left, n->isddd);
		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
			if(n->left->sym->def)
				mkinlcall(np, n->left->sym->def, n->isddd);
		break;

	case OCALLMETH:
		if(debug['m']>3)
			print("%L:call to meth %lN\n", n->lineno, n->left->right);
		// typecheck should have resolved ODOTMETH->type, whose nname points to the actual function.
		if(n->left->type == T) 
			fatal("no function type for [%p] %+N\n", n->left, n->left);

		if(n->left->type->nname == N) 
			fatal("no function definition for [%p] %+T\n", n->left->type, n->left->type);

		mkinlcall(np, n->left->type->nname, n->isddd);

		break;
	}
	
	lineno = lno;
}

static void	mkinlcall1(Node **np, Node *fn, int isddd);

static void
mkinlcall(Node **np, Node *fn, int isddd)
{
	int save_safemode;
	Pkg *pkg;

	save_safemode = safemode;

	// imported functions may refer to unsafe as long as the
	// package was marked safe during import (already checked).
	pkg = fnpkg(fn);
	if(pkg != localpkg && pkg != nil)
		safemode = 0;
	mkinlcall1(np, fn, isddd);
	safemode = save_safemode;
}

static Node*
tinlvar(Type *t)
{
	if(t->nname && !isblank(t->nname)) {
		if(!t->nname->inlvar)
			fatal("missing inlvar for %N\n", t->nname);
		return t->nname->inlvar;
	}
	typecheck(&nblank, Erv | Easgn);
	return nblank;
}

static int inlgen;

// if *np is a call, and fn is a function with an inlinable body, substitute *np with an OINLCALL.
// On return ninit has the parameter assignments, the nbody is the
// inlined function body and list, rlist contain the input, output
// parameters.
static void
mkinlcall1(Node **np, Node *fn, int isddd)
{
	int i;
	int chkargcount;
	Node *n, *call, *saveinlfn, *as, *m;
	NodeList *dcl, *ll, *ninit, *body;
	Type *t;
	// For variadic fn.
	int variadic, varargcount, multiret;
	Node *vararg;
	NodeList *varargs;
	Type *varargtype, *vararrtype;

	if (fn->inl == nil)
		return;

	if (fn == curfn || fn->defn == curfn)
		return;

	if(debug['l']<2)
		typecheckinl(fn);

	n = *np;

	// Bingo, we have a function node, and it has an inlineable body
	if(debug['m']>1)
		print("%L: inlining call to %S %#T { %#H }\n", n->lineno, fn->sym, fn->type, fn->inl);
	else if(debug['m'])
		print("%L: inlining call to %N\n", n->lineno, fn);

	if(debug['m']>2)
		print("%L: Before inlining: %+N\n", n->lineno, n);

	saveinlfn = inlfn;
	inlfn = fn;

	ninit = n->ninit;

//dumplist("ninit pre", ninit);

	if (fn->defn) // local function
		dcl = fn->defn->dcl;
	else // imported function
		dcl = fn->dcl;

	inlretvars = nil;
	i = 0;
	// Make temp names to use instead of the originals
	for(ll = dcl; ll; ll=ll->next) {
		if(ll->n->class == PPARAMOUT)  // return values handled below.
			continue;
		if(ll->n->op == ONAME) {
			ll->n->inlvar = inlvar(ll->n);
			// Typecheck because inlvar is not necessarily a function parameter.
			typecheck(&ll->n->inlvar, Erv);
			if ((ll->n->class&~PHEAP) != PAUTO)
				ninit = list(ninit, nod(ODCL, ll->n->inlvar, N));  // otherwise gen won't emit the allocations for heapallocs
		}
	}

	// temporaries for return values.
	for(t = getoutargx(fn->type)->type; t; t = t->down) {
		if(t != T && t->nname != N && !isblank(t->nname)) {
			m = inlvar(t->nname);
			typecheck(&m, Erv);
			t->nname->inlvar = m;
		} else {
			// anonymous return values, synthesize names for use in assignment that replaces return
			m = retvar(t, i++);
		}
		ninit = list(ninit, nod(ODCL, m, N));
		inlretvars = list(inlretvars, m);
	}

	// assign receiver.
	if(fn->type->thistuple && n->left->op == ODOTMETH) {
		// method call with a receiver.
		t = getthisx(fn->type)->type;
		if(t != T && t->nname != N && !isblank(t->nname) && !t->nname->inlvar)
			fatal("missing inlvar for %N\n", t->nname);
		if(!n->left->left)
			fatal("method call without receiver: %+N", n);
		if(t == T)
			fatal("method call unknown receiver type: %+N", n);
		as = nod(OAS, tinlvar(t), n->left->left);
		if(as != N) {
			typecheck(&as, Etop);
			ninit = list(ninit, as);
		}
	}

	// check if inlined function is variadic.
	variadic = 0;
	varargtype = T;
	varargcount = 0;
	for(t=fn->type->type->down->down->type; t; t=t->down) {
		if(t->isddd) {
			variadic = 1;
			varargtype = t->type;
		}
	}
	// but if argument is dotted too forget about variadicity.
	if(variadic && isddd)
		variadic = 0;

	// check if argument is actually a returned tuple from call.
	multiret = 0;
	if(n->list && !n->list->next) {
		switch(n->list->n->op) {
		case OCALL:
		case OCALLFUNC:
		case OCALLINTER:
		case OCALLMETH:
			if(n->list->n->left->type->outtuple > 1)
				multiret = n->list->n->left->type->outtuple-1;
		}
	}

	if(variadic) {
		varargcount = count(n->list) + multiret;
		if(n->left->op != ODOTMETH)
			varargcount -= fn->type->thistuple;
		varargcount -= fn->type->intuple - 1;
	}

	// assign arguments to the parameters' temp names
	as = nod(OAS2, N, N);
	as->rlist = n->list;
	ll = n->list;

	// TODO: if len(nlist) == 1 but multiple args, check that n->list->n is a call?
	if(fn->type->thistuple && n->left->op != ODOTMETH) {
		// non-method call to method
		if(!n->list)
			fatal("non-method call to method without first arg: %+N", n);
		// append receiver inlvar to LHS.
		t = getthisx(fn->type)->type;
		if(t != T && t->nname != N && !isblank(t->nname) && !t->nname->inlvar)
			fatal("missing inlvar for %N\n", t->nname);
		if(t == T)
			fatal("method call unknown receiver type: %+N", n);
		as->list = list(as->list, tinlvar(t));
		ll = ll->next; // track argument count.
	}

	// append ordinary arguments to LHS.
	chkargcount = n->list && n->list->next;
	vararg = N;    // the slice argument to a variadic call
	varargs = nil; // the list of LHS names to put in vararg.
	if(!chkargcount) {
		// 0 or 1 expression on RHS.
		for(t = getinargx(fn->type)->type; t; t=t->down) {
			if(variadic && t->isddd) {
				vararg = tinlvar(t);
				for(i=0; i<varargcount && ll; i++) {
					m = argvar(varargtype, i);
					varargs = list(varargs, m);
					as->list = list(as->list, m);
				}
				break;
			}
			as->list = list(as->list, tinlvar(t));
		}
	} else {
		// match arguments except final variadic (unless the call is dotted itself)
		for(t = getinargx(fn->type)->type; t;) {
			if(!ll)
				break;
			if(variadic && t->isddd)
				break;
			as->list = list(as->list, tinlvar(t));
			t=t->down;
			ll=ll->next;
		}
		// match varargcount arguments with variadic parameters.
		if(variadic && t && t->isddd) {
			vararg = tinlvar(t);
			for(i=0; i<varargcount && ll; i++) {
				m = argvar(varargtype, i);
				varargs = list(varargs, m);
				as->list = list(as->list, m);
				ll=ll->next;
			}
			if(i==varargcount)
				t=t->down;
		}
		if(ll || t)
			fatal("arg count mismatch: %#T  vs %,H\n",  getinargx(fn->type), n->list);
	}

	if (as->rlist) {
		typecheck(&as, Etop);
		ninit = list(ninit, as);
	}

	// turn the variadic args into a slice.
	if(variadic) {
		as = nod(OAS, vararg, N);
		if(!varargcount) {
			as->right = nodnil();
			as->right->type = varargtype;
		} else {
			vararrtype = typ(TARRAY);
			vararrtype->type = varargtype->type;
			vararrtype->bound = varargcount;

			as->right = nod(OCOMPLIT, N, typenod(varargtype));
			as->right->list = varargs;
			as->right = nod(OSLICE, as->right, nod(OKEY, N, N));
		}
		typecheck(&as, Etop);
		ninit = list(ninit, as);
	}

	// zero the outparams
	for(ll = inlretvars; ll; ll=ll->next) {
		as = nod(OAS, ll->n, N);
		typecheck(&as, Etop);
		ninit = list(ninit, as);
	}

	inlretlabel = newlabel();
	inlgen++;
	body = inlsubstlist(fn->inl);

	body = list(body, nod(OGOTO, inlretlabel, N));	// avoid 'not used' when function doesnt have return
	body = list(body, nod(OLABEL, inlretlabel, N));

	typechecklist(body, Etop);
//dumplist("ninit post", ninit);

	call = nod(OINLCALL, N, N);
	call->ninit = ninit;
	call->nbody = body;
	call->rlist = inlretvars;
	call->type = n->type;
	call->typecheck = 1;

	setlno(call, n->lineno);
//dumplist("call body", body);

	*np = call;

	inlfn =	saveinlfn;

	// transitive inlining
	// TODO do this pre-expansion on fn->inl directly.  requires
	// either supporting exporting statemetns with complex ninits
	// or saving inl and making inlinl
	if(debug['l'] >= 5) {
		body = fn->inl;
		fn->inl = nil;	// prevent infinite recursion
		inlnodelist(call->nbody);
		for(ll=call->nbody; ll; ll=ll->next)
			if(ll->n->op == OINLCALL)
				inlconv2stmt(ll->n);
		fn->inl = body;
	}

	if(debug['m']>2)
		print("%L: After inlining %+N\n\n", n->lineno, *np);

}

// Every time we expand a function we generate a new set of tmpnames,
// PAUTO's in the calling functions, and link them off of the
// PPARAM's, PAUTOS and PPARAMOUTs of the called function. 
static Node*
inlvar(Node *var)
{
	Node *n;

	if(debug['m']>3)
		print("inlvar %+N\n", var);

	n = newname(var->sym);
	n->type = var->type;
	n->class = PAUTO;
	n->used = 1;
	n->curfn = curfn;   // the calling function, not the called one

	// esc pass wont run if we're inlining into a iface wrapper
	// luckily, we can steal the results from the target func
	if(var->esc == EscHeap)
		addrescapes(n);

	curfn->dcl = list(curfn->dcl, n);
	return n;
}

// Synthesize a variable to store the inlined function's results in.
static Node*
retvar(Type *t, int i)
{
	Node *n;

	snprint(namebuf, sizeof(namebuf), "~r%d", i);
	n = newname(lookup(namebuf));
	n->type = t->type;
	n->class = PAUTO;
	n->used = 1;
	n->curfn = curfn;   // the calling function, not the called one
	curfn->dcl = list(curfn->dcl, n);
	return n;
}

// Synthesize a variable to store the inlined function's arguments
// when they come from a multiple return call.
static Node*
argvar(Type *t, int i)
{
	Node *n;

	snprint(namebuf, sizeof(namebuf), "~arg%d", i);
	n = newname(lookup(namebuf));
	n->type = t->type;
	n->class = PAUTO;
	n->used = 1;
	n->curfn = curfn;   // the calling function, not the called one
	curfn->dcl = list(curfn->dcl, n);
	return n;
}

static Node*
newlabel(void)
{
	Node *n;
	static int label;
	
	label++;
	snprint(namebuf, sizeof(namebuf), ".inlret%.6d", label);
	n = newname(lookup(namebuf));
	n->etype = 1;  // flag 'safe' for escape analysis (no backjumps)
	return n;
}

// inlsubst and inlsubstlist recursively copy the body of the saved
// pristine ->inl body of the function while substituting references
// to input/output parameters with ones to the tmpnames, and
// substituting returns with assignments to the output.
static NodeList*
inlsubstlist(NodeList *ll)
{
	NodeList *l;

	l = nil;
	for(; ll; ll=ll->next)
		l = list(l, inlsubst(ll->n));
	return l;
}

static Node*
inlsubst(Node *n)
{
	char *p;
	Node *m, *as;
	NodeList *ll;

	if(n == N)
		return N;

	switch(n->op) {
	case ONAME:
		if(n->inlvar) { // These will be set during inlnode
			if (debug['m']>2)
				print ("substituting name %+N  ->  %+N\n", n, n->inlvar);
			return n->inlvar;
		}
		if (debug['m']>2)
			print ("not substituting name %+N\n", n);
		return n;

	case OLITERAL:
	case OTYPE:
		return n;

	case ORETURN:
		// Since we don't handle bodies with closures, this return is guaranteed to belong to the current inlined function.

//		dump("Return before substitution", n);
		m = nod(OGOTO, inlretlabel, N);
		m->ninit  = inlsubstlist(n->ninit);

		if(inlretvars && n->list) {
			as = nod(OAS2, N, N);
			// shallow copy or OINLCALL->rlist will be the same list, and later walk and typecheck may clobber that.
			for(ll=inlretvars; ll; ll=ll->next)
				as->list = list(as->list, ll->n);
			as->rlist = inlsubstlist(n->list);
			typecheck(&as, Etop);
			m->ninit = list(m->ninit, as);
		}

		typechecklist(m->ninit, Etop);
		typecheck(&m, Etop);
//		dump("Return after substitution", m);
		return m;
	
	case OGOTO:
	case OLABEL:
		m = nod(OXXX, N, N);
		*m = *n;
		m->ninit = nil;
		p = smprint("%s·%d", n->left->sym->name, inlgen);	
		m->left = newname(lookup(p));
		free(p);
		return m;	
	}


	m = nod(OXXX, N, N);
	*m = *n;
	m->ninit = nil;
	
	if(n->op == OCLOSURE)
		fatal("cannot inline function containing closure: %+N", n);

	m->left	  = inlsubst(n->left);
	m->right  = inlsubst(n->right);
	m->list	  = inlsubstlist(n->list);
	m->rlist  = inlsubstlist(n->rlist);
	m->ninit  = concat(m->ninit, inlsubstlist(n->ninit));
	m->ntest  = inlsubst(n->ntest);
	m->nincr  = inlsubst(n->nincr);
	m->nbody  = inlsubstlist(n->nbody);
	m->nelse  = inlsubstlist(n->nelse);

	return m;
}

// Plaster over linenumbers
static void
setlnolist(NodeList *ll, int lno)
{
	for(;ll;ll=ll->next)
		setlno(ll->n, lno);
}

static void
setlno(Node *n, int lno)
{
	if(!n)
		return;

	// don't clobber names, unless they're freshly synthesized
	if(n->op != ONAME || n->lineno == 0)
		n->lineno = lno;
	
	setlno(n->left, lno);
	setlno(n->right, lno);
	setlnolist(n->list, lno);
	setlnolist(n->rlist, lno);
	setlnolist(n->ninit, lno);
	setlno(n->ntest, lno);
	setlno(n->nincr, lno);
	setlnolist(n->nbody, lno);
	setlnolist(n->nelse, lno);
}
