1
0
mirror of https://github.com/golang/go synced 2024-11-21 23:14:40 -07:00

gc: typecheck the whole tree before walking. preparation for some escape-analysis related changes.

R=rsc
CC=golang-dev
https://golang.org/cl/4528116
This commit is contained in:
Luuk van Dijk 2011-06-02 18:48:17 +02:00
parent ef2d5f68d0
commit e59aa8ea4a
13 changed files with 177 additions and 345 deletions

View File

@ -15,16 +15,17 @@ HFILES=\
OFILES=\ OFILES=\
../5l/enam.$O\ ../5l/enam.$O\
list.$O\
galign.$O\
gobj.$O\
ggen.$O\
gsubr.$O\
cgen.$O\ cgen.$O\
cgen64.$O\ cgen64.$O\
cplx.$O\ cplx.$O\
reg.$O\ galign.$O\
ggen.$O\
gobj.$O\
gsubr.$O\
list.$O\
peep.$O\ peep.$O\
pgen.$O\
reg.$O\
LIB=\ LIB=\
../gc/gc.a\ ../gc/gc.a\

View File

@ -7,107 +7,9 @@
#include "gg.h" #include "gg.h"
#include "opt.h" #include "opt.h"
static Prog *pret;
void void
compile(Node *fn) defframe(Prog *ptxt)
{ {
Plist *pl;
Node nod1;
Prog *ptxt;
int32 lno;
Type *t;
Iter save;
if(newproc == N) {
newproc = sysfunc("newproc");
deferproc = sysfunc("deferproc");
deferreturn = sysfunc("deferreturn");
panicindex = sysfunc("panicindex");
panicslice = sysfunc("panicslice");
throwreturn = sysfunc("throwreturn");
}
if(fn->nbody == nil)
return;
// set up domain for labels
clearlabels();
lno = setlineno(fn);
curfn = fn;
dowidth(curfn->type);
if(curfn->type->outnamed) {
// add clearing of the output parameters
t = structfirst(&save, getoutarg(curfn->type));
while(t != T) {
if(t->nname != N)
curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
t = structnext(&save);
}
}
hasdefer = 0;
walk(curfn);
if(nerrors != 0 || isblank(curfn->nname))
goto ret;
allocparams();
continpc = P;
breakpc = P;
pl = newplist();
pl->name = curfn->nname;
setlineno(curfn);
nodconst(&nod1, types[TINT32], 0);
ptxt = gins(ATEXT, curfn->nname, &nod1);
afunclit(&ptxt->from);
ginit();
genlist(curfn->enter);
pret = nil;
if(hasdefer || curfn->exit) {
Prog *p1;
p1 = gjmp(nil);
pret = gjmp(nil);
patch(p1, pc);
}
genlist(curfn->nbody);
gclean();
checklabels();
if(nerrors != 0)
goto ret;
if(curfn->type->outtuple != 0)
ginscall(throwreturn, 0);
if(pret)
patch(pret, pc);
ginit();
if(hasdefer)
ginscall(deferreturn, 0);
if(curfn->exit)
genlist(curfn->exit);
gclean();
if(nerrors != 0)
goto ret;
if(curfn->endlineno)
lineno = curfn->endlineno;
pc->as = ARET; // overwrite AEND
pc->lineno = lineno;
if(!debug['N'] || debug['R'] || debug['P']) {
regopt(ptxt);
}
// fill in argument size // fill in argument size
ptxt->to.type = D_CONST2; ptxt->to.type = D_CONST2;
ptxt->reg = 0; // flags ptxt->reg = 0; // flags
@ -118,12 +20,6 @@ compile(Node *fn)
maxstksize = stksize; maxstksize = stksize;
ptxt->to.offset = rnd(maxstksize+maxarg, widthptr); ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
maxstksize = 0; maxstksize = 0;
if(debug['f'])
frame(0);
ret:
lineno = lno;
} }
/* /*
@ -197,7 +93,7 @@ ginscall(Node *f, int proc)
nodconst(&con, types[TINT32], 0); nodconst(&con, types[TINT32], 0);
p = gins(ACMP, &con, N); p = gins(ACMP, &con, N);
p->reg = 0; p->reg = 0;
patch(gbranch(ABNE, T), pret); patch(gbranch(ABNE, T), retpc);
} }
break; break;
} }
@ -401,7 +297,7 @@ cgen_ret(Node *n)
{ {
genlist(n->list); // copy out args genlist(n->list); // copy out args
if(hasdefer || curfn->exit) if(hasdefer || curfn->exit)
gjmp(pret); gjmp(retpc);
else else
gins(ARET, N, N); gins(ARET, N, N);
} }

View File

@ -14,16 +14,17 @@ HFILES=\
opt.h\ opt.h\
OFILES=\ OFILES=\
list.$O\ ../6l/enam.$O\
gobj.$O\
galign.$O\
ggen.$O\
cgen.$O\ cgen.$O\
cplx.$O\ cplx.$O\
galign.$O\
ggen.$O\
gobj.$O\
gsubr.$O\ gsubr.$O\
list.$O\
peep.$O\ peep.$O\
pgen.$O\
reg.$O\ reg.$O\
../6l/enam.$O\
LIB=\ LIB=\
../gc/gc.a\ ../gc/gc.a\

View File

@ -7,121 +7,18 @@
#include "gg.h" #include "gg.h"
#include "opt.h" #include "opt.h"
static Prog *pret;
void void
compile(Node *fn) defframe(Prog *ptxt)
{ {
Plist *pl;
Node nod1;
Prog *ptxt;
int32 lno;
Type *t;
Iter save;
if(newproc == N) {
newproc = sysfunc("newproc");
deferproc = sysfunc("deferproc");
deferreturn = sysfunc("deferreturn");
panicindex = sysfunc("panicindex");
panicslice = sysfunc("panicslice");
throwreturn = sysfunc("throwreturn");
}
if(fn->nbody == nil)
return;
// set up domain for labels
clearlabels();
lno = setlineno(fn);
curfn = fn;
dowidth(curfn->type);
if(curfn->type->outnamed) {
// add clearing of the output parameters
t = structfirst(&save, getoutarg(curfn->type));
while(t != T) {
if(t->nname != N)
curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
t = structnext(&save);
}
}
hasdefer = 0;
walk(curfn);
if(nerrors != 0 || isblank(curfn->nname))
goto ret;
allocparams();
continpc = P;
breakpc = P;
pl = newplist();
pl->name = curfn->nname;
setlineno(curfn);
nodconst(&nod1, types[TINT32], 0);
ptxt = gins(ATEXT, curfn->nname, &nod1);
afunclit(&ptxt->from);
ginit();
genlist(curfn->enter);
pret = nil;
if(hasdefer || curfn->exit) {
Prog *p1;
p1 = gjmp(nil);
pret = gjmp(nil);
patch(p1, pc);
}
genlist(curfn->nbody);
gclean();
checklabels();
if(nerrors != 0)
goto ret;
if(curfn->endlineno)
lineno = curfn->endlineno;
if(curfn->type->outtuple != 0)
ginscall(throwreturn, 0);
if(pret)
patch(pret, pc);
ginit();
if(hasdefer)
ginscall(deferreturn, 0);
if(curfn->exit)
genlist(curfn->exit);
gclean();
if(nerrors != 0)
goto ret;
pc->as = ARET; // overwrite AEND
pc->lineno = lineno;
if(!debug['N'] || debug['R'] || debug['P']) {
regopt(ptxt);
}
// fill in argument size // fill in argument size
ptxt->to.offset = rnd(curfn->type->argwid, widthptr); ptxt->to.offset = rnd(curfn->type->argwid, widthptr);
// fill in final stack size // fill in final stack size
ptxt->to.offset <<= 32; ptxt->to.offset <<= 32;
ptxt->to.offset |= rnd(stksize+maxarg, widthptr); ptxt->to.offset |= rnd(stksize+maxarg, widthptr);
if(debug['f'])
frame(0);
ret:
lineno = lno;
} }
/* /*
* generate: * generate:
* call f * call f
@ -163,7 +60,7 @@ ginscall(Node *f, int proc)
if(proc == 2) { if(proc == 2) {
nodreg(&reg, types[TINT64], D_AX); nodreg(&reg, types[TINT64], D_AX);
gins(ATESTQ, &reg, &reg); gins(ATESTQ, &reg, &reg);
patch(gbranch(AJNE, T), pret); patch(gbranch(AJNE, T), retpc);
} }
break; break;
} }
@ -355,7 +252,7 @@ cgen_ret(Node *n)
{ {
genlist(n->list); // copy out args genlist(n->list); // copy out args
if(hasdefer || curfn->exit) if(hasdefer || curfn->exit)
gjmp(pret); gjmp(retpc);
else else
gins(ARET, N, N); gins(ARET, N, N);
} }

View File

@ -15,15 +15,16 @@ HFILES=\
OFILES=\ OFILES=\
../8l/enam.$O\ ../8l/enam.$O\
list.$O\
galign.$O\
gobj.$O\
ggen.$O\
gsubr.$O\
cgen.$O\ cgen.$O\
cgen64.$O\ cgen64.$O\
cplx.$O\ cplx.$O\
galign.$O\
ggen.$O\
gobj.$O\
gsubr.$O\
list.$O\
peep.$O\ peep.$O\
pgen.$O\
reg.$O\ reg.$O\
LIB=\ LIB=\

View File

@ -7,106 +7,9 @@
#include "gg.h" #include "gg.h"
#include "opt.h" #include "opt.h"
static Prog *pret;
void void
compile(Node *fn) defframe(Prog *ptxt)
{ {
Plist *pl;
Node nod1;
Prog *ptxt;
int32 lno;
Type *t;
Iter save;
if(newproc == N) {
newproc = sysfunc("newproc");
deferproc = sysfunc("deferproc");
deferreturn = sysfunc("deferreturn");
panicindex = sysfunc("panicindex");
panicslice = sysfunc("panicslice");
throwreturn = sysfunc("throwreturn");
}
if(fn->nbody == nil)
return;
// set up domain for labels
clearlabels();
lno = setlineno(fn);
curfn = fn;
dowidth(curfn->type);
if(curfn->type->outnamed) {
// add clearing of the output parameters
t = structfirst(&save, getoutarg(curfn->type));
while(t != T) {
if(t->nname != N)
curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
t = structnext(&save);
}
}
hasdefer = 0;
walk(curfn);
if(nerrors != 0 || isblank(curfn->nname))
goto ret;
allocparams();
continpc = P;
breakpc = P;
pl = newplist();
pl->name = curfn->nname;
setlineno(curfn);
nodconst(&nod1, types[TINT32], 0);
ptxt = gins(ATEXT, curfn->nname, &nod1);
afunclit(&ptxt->from);
ginit();
genlist(curfn->enter);
pret = nil;
if(hasdefer || curfn->exit) {
Prog *p1;
p1 = gjmp(nil);
pret = gjmp(nil);
patch(p1, pc);
}
genlist(curfn->nbody);
gclean();
checklabels();
if(nerrors != 0)
goto ret;
if(curfn->endlineno)
lineno = curfn->endlineno;
if(curfn->type->outtuple != 0)
ginscall(throwreturn, 0);
if(pret)
patch(pret, pc);
ginit();
if(hasdefer)
ginscall(deferreturn, 0);
if(curfn->exit)
genlist(curfn->exit);
gclean();
if(nerrors != 0)
goto ret;
pc->as = ARET; // overwrite AEND
pc->lineno = lineno;
if(!debug['N'] || debug['R'] || debug['P']) {
regopt(ptxt);
}
// fill in argument size // fill in argument size
ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr); ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr);
@ -115,12 +18,6 @@ compile(Node *fn)
maxstksize = stksize; maxstksize = stksize;
ptxt->to.offset = rnd(maxstksize+maxarg, widthptr); ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
maxstksize = 0; maxstksize = 0;
if(debug['f'])
frame(0);
ret:
lineno = lno;
} }
void void
@ -200,7 +97,7 @@ ginscall(Node *f, int proc)
if(proc == 2) { if(proc == 2) {
nodreg(&reg, types[TINT64], D_AX); nodreg(&reg, types[TINT64], D_AX);
gins(ATESTL, &reg, &reg); gins(ATESTL, &reg, &reg);
patch(gbranch(AJNE, T), pret); patch(gbranch(AJNE, T), retpc);
} }
break; break;
} }
@ -391,8 +288,8 @@ void
cgen_ret(Node *n) cgen_ret(Node *n)
{ {
genlist(n->list); // copy out args genlist(n->list); // copy out args
if(pret) if(retpc)
gjmp(pret); gjmp(retpc);
else else
gins(ARET, N, N); gins(ARET, N, N);
} }

View File

@ -1251,9 +1251,6 @@ funccompile(Node *n, int isclosure)
if(curfn) if(curfn)
fatal("funccompile %S inside %S", n->nname->sym, curfn->nname->sym); fatal("funccompile %S inside %S", n->nname->sym, curfn->nname->sym);
curfn = n;
typechecklist(n->nbody, Etop);
curfn = nil;
stksize = 0; stksize = 0;
dclcontext = PAUTO; dclcontext = PAUTO;

View File

@ -1213,6 +1213,7 @@ EXTERN Prog* continpc;
EXTERN Prog* breakpc; EXTERN Prog* breakpc;
EXTERN Prog* pc; EXTERN Prog* pc;
EXTERN Prog* firstpc; EXTERN Prog* firstpc;
EXTERN Prog* retpc;
EXTERN Node* nodfp; EXTERN Node* nodfp;
@ -1226,6 +1227,7 @@ void cgen_callinter(Node *n, Node *res, int proc);
void cgen_ret(Node *n); void cgen_ret(Node *n);
void clearfat(Node *n); void clearfat(Node *n);
void compile(Node*); void compile(Node*);
void defframe(Prog*);
int dgostringptr(Sym*, int off, char *str); int dgostringptr(Sym*, int off, char *str);
int dgostrlitptr(Sym*, int off, Strlit*); int dgostrlitptr(Sym*, int off, Strlit*);
int dstringptr(Sym *s, int off, char *str); int dstringptr(Sym *s, int off, char *str);

View File

@ -182,11 +182,14 @@ fninit(NodeList *n)
// (11) // (11)
a = nod(ORETURN, N, N); a = nod(ORETURN, N, N);
r = list(r, a); r = list(r, a);
exportsym(fn->nname); exportsym(fn->nname);
fn->nbody = r; fn->nbody = r;
funcbody(fn); funcbody(fn);
curfn = fn;
typecheck(&fn, Etop); typecheck(&fn, Etop);
typechecklist(r, Etop);
curfn = nil;
funccompile(fn, 0); funccompile(fn, 0);
} }

View File

@ -235,13 +235,14 @@ main(int argc, char *argv[])
if(debug['f']) if(debug['f'])
frame(1); frame(1);
// Process top-level declarations in three phases. // Process top-level declarations in four phases.
// Phase 1: const, type, and names and types of funcs. // Phase 1: const, type, and names and types of funcs.
// This will gather all the information about types // This will gather all the information about types
// and methods but doesn't depend on any of it. // and methods but doesn't depend on any of it.
// Phase 2: Variable assignments. // Phase 2: Variable assignments.
// To check interface assignments, depends on phase 1. // To check interface assignments, depends on phase 1.
// Phase 3: Function bodies. // Phase 3: Type check function bodies.
// Phase 4: Compile function bodies.
defercheckwidth(); defercheckwidth();
for(l=xtop; l; l=l->next) for(l=xtop; l; l=l->next)
if(l->n->op != ODCL && l->n->op != OAS) if(l->n->op != ODCL && l->n->op != OAS)
@ -251,17 +252,28 @@ main(int argc, char *argv[])
typecheck(&l->n, Etop); typecheck(&l->n, Etop);
resumetypecopy(); resumetypecopy();
resumecheckwidth(); resumecheckwidth();
for(l=xtop; l; l=l->next)
if(l->n->op == ODCLFUNC) {
curfn = l->n;
typechecklist(l->n->nbody, Etop);
}
curfn = nil;
for(l=xtop; l; l=l->next) for(l=xtop; l; l=l->next)
if(l->n->op == ODCLFUNC) if(l->n->op == ODCLFUNC)
funccompile(l->n, 0); funccompile(l->n, 0);
if(nerrors == 0) if(nerrors == 0)
fninit(xtop); fninit(xtop);
while(closures) { while(closures) {
l = closures; l = closures;
closures = nil; closures = nil;
for(; l; l=l->next) for(; l; l=l->next)
funccompile(l->n, 1); funccompile(l->n, 1);
} }
dclchecks(); dclchecks();
if(nerrors) if(nerrors)

119
src/cmd/gc/pgen.c Normal file
View File

@ -0,0 +1,119 @@
// 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.
#undef EXTERN
#define EXTERN
#include "gg.h"
#include "opt.h"
void
compile(Node *fn)
{
Plist *pl;
Node nod1, *n;
Prog *ptxt;
int32 lno;
Type *t;
Iter save;
if(newproc == N) {
newproc = sysfunc("newproc");
deferproc = sysfunc("deferproc");
deferreturn = sysfunc("deferreturn");
panicindex = sysfunc("panicindex");
panicslice = sysfunc("panicslice");
throwreturn = sysfunc("throwreturn");
}
if(fn->nbody == nil)
return;
// set up domain for labels
clearlabels();
lno = setlineno(fn);
curfn = fn;
dowidth(curfn->type);
if(curfn->type->outnamed) {
// add clearing of the output parameters
t = structfirst(&save, getoutarg(curfn->type));
while(t != T) {
if(t->nname != N) {
n = nod(OAS, t->nname, N);
typecheck(&n, Etop);
curfn->nbody = concat(list1(n), curfn->nbody);
}
t = structnext(&save);
}
}
hasdefer = 0;
walk(curfn);
if(nerrors != 0 || isblank(curfn->nname))
goto ret;
allocparams();
continpc = P;
breakpc = P;
pl = newplist();
pl->name = curfn->nname;
setlineno(curfn);
nodconst(&nod1, types[TINT32], 0);
ptxt = gins(ATEXT, curfn->nname, &nod1);
afunclit(&ptxt->from);
ginit();
genlist(curfn->enter);
retpc = nil;
if(hasdefer || curfn->exit) {
Prog *p1;
p1 = gjmp(nil);
retpc = gjmp(nil);
patch(p1, pc);
}
genlist(curfn->nbody);
gclean();
checklabels();
if(nerrors != 0)
goto ret;
if(curfn->endlineno)
lineno = curfn->endlineno;
if(curfn->type->outtuple != 0)
ginscall(throwreturn, 0);
if(retpc)
patch(retpc, pc);
ginit();
if(hasdefer)
ginscall(deferreturn, 0);
if(curfn->exit)
genlist(curfn->exit);
gclean();
if(nerrors != 0)
goto ret;
pc->as = ARET; // overwrite AEND
pc->lineno = lineno;
if(!debug['N'] || debug['R'] || debug['P']) {
regopt(ptxt);
}
defframe(ptxt);
if(debug['f'])
frame(0);
ret:
lineno = lno;
}

View File

@ -3170,7 +3170,10 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
dumplist("genwrapper body", fn->nbody); dumplist("genwrapper body", fn->nbody);
funcbody(fn); funcbody(fn);
curfn = fn;
typecheck(&fn, Etop); typecheck(&fn, Etop);
typechecklist(fn->nbody, Etop);
curfn = nil;
funccompile(fn, 0); funccompile(fn, 0);
} }

View File

@ -66,6 +66,7 @@ walk(Node *fn)
int lno; int lno;
curfn = fn; curfn = fn;
if(debug['W']) { if(debug['W']) {
snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym); snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
dumplist(s, curfn->nbody); dumplist(s, curfn->nbody);
@ -73,7 +74,7 @@ walk(Node *fn)
if(curfn->type->outtuple) if(curfn->type->outtuple)
if(walkret(curfn->nbody)) if(walkret(curfn->nbody))
yyerror("function ends without a return statement"); yyerror("function ends without a return statement");
typechecklist(curfn->nbody, Etop);
lno = lineno; lno = lineno;
for(l=fn->dcl; l; l=l->next) { for(l=fn->dcl; l; l=l->next) {
n = l->n; n = l->n;
@ -468,8 +469,10 @@ walkstmt(Node **np)
case OPANIC: case OPANIC:
case OEMPTY: case OEMPTY:
case ORECOVER: case ORECOVER:
if(n->typecheck == 0) if(n->typecheck == 0) {
dump("missing typecheck:", n);
fatal("missing typecheck"); fatal("missing typecheck");
}
init = n->ninit; init = n->ninit;
n->ninit = nil; n->ninit = nil;
walkexpr(&n, &init); walkexpr(&n, &init);