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) ...@@ -172,6 +172,9 @@ declare(Node *n, int ctxt)
Sym *s; Sym *s;
int gen; int gen;
static int typegen, vargen; static int typegen, vargen;
if(ctxt == PDISCARD)
return;
if(isblank(n)) if(isblank(n))
return; return;
...@@ -240,7 +243,7 @@ variter(NodeList *vl, Node *t, NodeList *el) ...@@ -240,7 +243,7 @@ variter(NodeList *vl, Node *t, NodeList *el)
init = nil; init = nil;
doexpr = el != nil; doexpr = el != nil;
if(count(el) == 1 && count(vl) > 1) { if(count(el) == 1 && count(vl) > 1) {
e = el->n; e = el->n;
as2 = nod(OAS2, N, N); as2 = nod(OAS2, N, N);
......
...@@ -813,6 +813,12 @@ stmtfmt(Fmt *f, Node *n) ...@@ -813,6 +813,12 @@ stmtfmt(Fmt *f, Node *n)
break; break;
case OAS: 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) if(n->colas && !complexinit)
fmtprint(f, "%N := %N", n->left, n->right); fmtprint(f, "%N := %N", n->left, n->right);
else else
...@@ -1431,6 +1437,10 @@ nodedump(Fmt *fp, Node *n) ...@@ -1431,6 +1437,10 @@ nodedump(Fmt *fp, Node *n)
fmtprint(fp, "%O-%S%J", n->op, n->sym, n); fmtprint(fp, "%O-%S%J", n->op, n->sym, n);
else else
fmtprint(fp, "%O%J", n->op, n); 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; break;
case OASOP: case OASOP:
fmtprint(fp, "%O-%O%J", n->op, n->etype, n); fmtprint(fp, "%O-%O%J", n->op, n->etype, n);
......
...@@ -649,6 +649,8 @@ enum ...@@ -649,6 +649,8 @@ enum
PPARAMREF, // param passed by reference PPARAMREF, // param passed by reference
PFUNC, PFUNC,
PDISCARD, // discard during parse of duplicate import
PHEAP = 1<<7, PHEAP = 1<<7,
}; };
......
...@@ -1293,8 +1293,10 @@ hidden_fndcl: ...@@ -1293,8 +1293,10 @@ hidden_fndcl:
importsym(s, ONAME); importsym(s, ONAME);
if(s->def != N && s->def->op == 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; break;
}
yyerror("inconsistent definition for func %S during import\n\t%T\n\t%T", s, s->def->type, t); 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: ...@@ -1824,8 +1826,10 @@ hidden_import:
} }
| LFUNC hidden_fndcl fnbody ';' | LFUNC hidden_fndcl fnbody ';'
{ {
if($2 == N) if($2 == N) {
dclcontext = PEXTERN; // since we skip the funcbody below
break; break;
}
$2->inl = $3; $2->inl = $3;
...@@ -1834,7 +1838,7 @@ hidden_import: ...@@ -1834,7 +1838,7 @@ hidden_import:
if(debug['E']) { if(debug['E']) {
print("import [%Z] func %lN \n", importpkg->path, $2); 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); print("inl body:%+H\n", $2->inl);
} }
} }
......
...@@ -82,20 +82,18 @@ typecheckinl(Node *fn) ...@@ -82,20 +82,18 @@ typecheckinl(Node *fn)
Pkg *pkg; Pkg *pkg;
int save_safemode, lno; int save_safemode, lno;
if(fn->typecheck)
return;
lno = setlineno(fn); lno = setlineno(fn);
if (debug['m']>2) // typecheckinl is only for imported functions;
print("typecheck import [%S] %lN { %#H }\n", fn->sym, fn, fn->inl);
// typecheckinl is only used for imported functions;
// their bodies may refer to unsafe as long as the package // their bodies may refer to unsafe as long as the package
// was marked safe during import (which was checked then). // 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); pkg = fnpkg(fn);
if (pkg == localpkg || pkg == nil) 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; save_safemode = safemode;
safemode = 0; safemode = 0;
...@@ -103,7 +101,6 @@ typecheckinl(Node *fn) ...@@ -103,7 +101,6 @@ typecheckinl(Node *fn)
savefn = curfn; savefn = curfn;
curfn = fn; curfn = fn;
typechecklist(fn->inl, Etop); typechecklist(fn->inl, Etop);
fn->typecheck = 1;
curfn = savefn; curfn = savefn;
safemode = save_safemode; safemode = save_safemode;
...@@ -113,6 +110,7 @@ typecheckinl(Node *fn) ...@@ -113,6 +110,7 @@ typecheckinl(Node *fn)
// Caninl determines whether fn is inlineable. // Caninl determines whether fn is inlineable.
// If so, caninl saves fn->nbody in fn->inl and substitutes it with a copy. // If so, caninl saves fn->nbody in fn->inl and substitutes it with a copy.
// fn and ->nbody will already have been typechecked.
void void
caninl(Node *fn) caninl(Node *fn)
{ {
...@@ -129,6 +127,9 @@ caninl(Node *fn) ...@@ -129,6 +127,9 @@ caninl(Node *fn)
if(fn->nbody == nil) if(fn->nbody == nil)
return; return;
if(fn->typecheck == 0)
fatal("caninl on non-typechecked function %N", fn);
// can't handle ... args yet // can't handle ... args yet
for(t=fn->type->type->down->down->type; t; t=t->down) for(t=fn->type->type->down->down->type; t; t=t->down)
if(t->isddd) if(t->isddd)
...@@ -143,8 +144,6 @@ caninl(Node *fn) ...@@ -143,8 +144,6 @@ caninl(Node *fn)
fn->nname->inl = fn->nbody; fn->nname->inl = fn->nbody;
fn->nbody = inlcopylist(fn->nname->inl); 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 // 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 // this is so export can find the body of a method
...@@ -193,19 +192,11 @@ ishairy(Node *n, int *budget) ...@@ -193,19 +192,11 @@ ishairy(Node *n, int *budget)
case OSWITCH: case OSWITCH:
case OPROC: case OPROC:
case ODEFER: case ODEFER:
case ODCL: // declares locals as globals b/c of @"". qualification
case ODCLTYPE: // can't print yet case ODCLTYPE: // can't print yet
case ODCLCONST: // can't print yet case ODCLCONST: // can't print yet
return 1; return 1;
break; 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)--; (*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