Commit 530147e8 authored by Luuk van Dijk's avatar Luuk van Dijk

cmd/gc: inlining functions with local variables

- make sure dclcontext == PAUTO only in function bodies
- introduce PDISCARD to discard declarations in bodies of repeated imports
- skip printing initializing OAS'es in export mode, assuming they only occur after ODCL's
- remove ODCL and the initializing OAS from inl.c:ishairy
- fix confused use of ->typecheck in typecheckinl: it's about the ->inl, not about the fn.
- debuging aids: print ntype on ONAMEs too and -Emm instead of -Ell.

fixes #2812

R=rsc
CC=golang-dev
https://golang.org/cl/6800043
parent 507fcf37
......@@ -172,6 +172,9 @@ declare(Node *n, int ctxt)
Sym *s;
int gen;
static int typegen, vargen;
if(ctxt == PDISCARD)
return;
if(isblank(n))
return;
......@@ -240,7 +243,7 @@ variter(NodeList *vl, Node *t, NodeList *el)
init = nil;
doexpr = el != nil;
if(count(el) == 1 && count(vl) > 1) {
e = el->n;
as2 = nod(OAS2, N, N);
......
......@@ -813,6 +813,12 @@ stmtfmt(Fmt *f, Node *n)
break;
case OAS:
// Don't export "v = <N>" initializing statements, hope they're always
// preceded by the DCL which will be re-parsed and typecheck to reproduce
// the "v = <N>" again.
if(fmtmode == FExp && n->right == N)
break;
if(n->colas && !complexinit)
fmtprint(f, "%N := %N", n->left, n->right);
else
......@@ -1431,6 +1437,10 @@ nodedump(Fmt *fp, Node *n)
fmtprint(fp, "%O-%S%J", n->op, n->sym, n);
else
fmtprint(fp, "%O%J", n->op, n);
if(recur && n->type == T && n->ntype) {
indent(fp);
fmtprint(fp, "%O-ntype%N", n->op, n->ntype);
}
break;
case OASOP:
fmtprint(fp, "%O-%O%J", n->op, n->etype, n);
......
......@@ -649,6 +649,8 @@ enum
PPARAMREF, // param passed by reference
PFUNC,
PDISCARD, // discard during parse of duplicate import
PHEAP = 1<<7,
};
......
......@@ -1293,8 +1293,10 @@ hidden_fndcl:
importsym(s, ONAME);
if(s->def != N && s->def->op == ONAME) {
if(eqtype(t, s->def->type))
if(eqtype(t, s->def->type)) {
dclcontext = PDISCARD; // since we skip funchdr below
break;
}
yyerror("inconsistent definition for func %S during import\n\t%T\n\t%T", s, s->def->type, t);
}
......@@ -1824,8 +1826,10 @@ hidden_import:
}
| LFUNC hidden_fndcl fnbody ';'
{
if($2 == N)
if($2 == N) {
dclcontext = PEXTERN; // since we skip the funcbody below
break;
}
$2->inl = $3;
......@@ -1834,7 +1838,7 @@ hidden_import:
if(debug['E']) {
print("import [%Z] func %lN \n", importpkg->path, $2);
if(debug['l'] > 2 && $2->inl)
if(debug['m'] > 2 && $2->inl)
print("inl body:%+H\n", $2->inl);
}
}
......
......@@ -82,20 +82,18 @@ typecheckinl(Node *fn)
Pkg *pkg;
int save_safemode, lno;
if(fn->typecheck)
return;
lno = setlineno(fn);
if (debug['m']>2)
print("typecheck import [%S] %lN { %#H }\n", fn->sym, fn, fn->inl);
// typecheckinl is only used for imported functions;
// 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)
fatal("typecheckinl on local function %lN", fn);
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;
......@@ -103,7 +101,6 @@ typecheckinl(Node *fn)
savefn = curfn;
curfn = fn;
typechecklist(fn->inl, Etop);
fn->typecheck = 1;
curfn = savefn;
safemode = save_safemode;
......@@ -113,6 +110,7 @@ typecheckinl(Node *fn)
// 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)
{
......@@ -129,6 +127,9 @@ caninl(Node *fn)
if(fn->nbody == nil)
return;
if(fn->typecheck == 0)
fatal("caninl on non-typechecked function %N", fn);
// can't handle ... args yet
for(t=fn->type->type->down->down->type; t; t=t->down)
if(t->isddd)
......@@ -143,8 +144,6 @@ caninl(Node *fn)
fn->nname->inl = fn->nbody;
fn->nbody = inlcopylist(fn->nname->inl);
// nbody will have been typechecked, so we can set this:
fn->typecheck = 1;
// 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
......@@ -193,19 +192,11 @@ ishairy(Node *n, int *budget)
case OSWITCH:
case OPROC:
case ODEFER:
case ODCL: // declares locals as globals b/c of @"". qualification
case ODCLTYPE: // can't print yet
case ODCLCONST: // can't print yet
return 1;
break;
case OAS:
// x = <N> zero initializing assignments aren't representible in export yet.
// alternatively we may just skip them in printing and hope their DCL printed
// as a var will regenerate it
if(n->right == N)
return 1;
break;
}
(*budget)--;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment