]> Cypherpunks repositories - gostls13.git/commitdiff
gc: typecheck the whole tree before walking. preparation for some escape-analysis...
authorLuuk van Dijk <lvd@golang.org>
Thu, 2 Jun 2011 16:48:17 +0000 (18:48 +0200)
committerLuuk van Dijk <lvd@golang.org>
Thu, 2 Jun 2011 16:48:17 +0000 (18:48 +0200)
R=rsc
CC=golang-dev
https://golang.org/cl/4528116

13 files changed:
src/cmd/5g/Makefile
src/cmd/5g/ggen.c
src/cmd/6g/Makefile
src/cmd/6g/ggen.c
src/cmd/8g/Makefile
src/cmd/8g/ggen.c
src/cmd/gc/dcl.c
src/cmd/gc/go.h
src/cmd/gc/init.c
src/cmd/gc/lex.c
src/cmd/gc/pgen.c [new file with mode: 0644]
src/cmd/gc/subr.c
src/cmd/gc/walk.c

index 6873fbc680d70155f36615793d1eeec8d4f1effa..b47014a4e3f9ef7e8135b2f8cbb0fcbc8b6e3963 100644 (file)
@@ -15,16 +15,17 @@ HFILES=\
 
 OFILES=\
        ../5l/enam.$O\
-       list.$O\
-       galign.$O\
-       gobj.$O\
-       ggen.$O\
-       gsubr.$O\
        cgen.$O\
        cgen64.$O\
        cplx.$O\
-       reg.$O\
+       galign.$O\
+       ggen.$O\
+       gobj.$O\
+       gsubr.$O\
+       list.$O\
        peep.$O\
+       pgen.$O\
+       reg.$O\
 
 LIB=\
        ../gc/gc.a\
index 7197709d4dc7ac78788abb7ab71979324abd1545..0bc1b38fc4c6657f64d0d54860c57e2577d2729d 100644 (file)
@@ -7,107 +7,9 @@
 #include "gg.h"
 #include "opt.h"
 
-static Prog *pret;
-
 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
        ptxt->to.type = D_CONST2;
        ptxt->reg = 0; // flags
@@ -118,12 +20,6 @@ compile(Node *fn)
                maxstksize = stksize;
        ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
        maxstksize = 0;
-
-       if(debug['f'])
-               frame(0);
-
-ret:
-       lineno = lno;
 }
 
 /*
@@ -197,7 +93,7 @@ ginscall(Node *f, int proc)
                        nodconst(&con, types[TINT32], 0);
                        p = gins(ACMP, &con, N);
                        p->reg = 0;
-                       patch(gbranch(ABNE, T), pret);
+                       patch(gbranch(ABNE, T), retpc);
                }
                break;
        }
@@ -401,7 +297,7 @@ cgen_ret(Node *n)
 {
        genlist(n->list);               // copy out args
        if(hasdefer || curfn->exit)
-               gjmp(pret);
+               gjmp(retpc);
        else
                gins(ARET, N, N);
 }
index 023f5d111bbfdc0d48f1751c64bbdf4384afb510..64fa1539908ed609be75b2f2bbcb122d7c516417 100644 (file)
@@ -14,16 +14,17 @@ HFILES=\
        opt.h\
 
 OFILES=\
-       list.$O\
-       gobj.$O\
-       galign.$O\
-       ggen.$O\
+       ../6l/enam.$O\
        cgen.$O\
        cplx.$O\
+       galign.$O\
+       ggen.$O\
+       gobj.$O\
        gsubr.$O\
+       list.$O\
        peep.$O\
+       pgen.$O\
        reg.$O\
-       ../6l/enam.$O\
 
 LIB=\
        ../gc/gc.a\
index ce66b43f062f59198e74be51ef389677ee9df761..5260335df75a1a5c229d8eda47721b5f1267f314 100644 (file)
 #include "gg.h"
 #include "opt.h"
 
-static Prog *pret;
-
 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
        ptxt->to.offset = rnd(curfn->type->argwid, widthptr);
 
        // fill in final stack size
        ptxt->to.offset <<= 32;
        ptxt->to.offset |= rnd(stksize+maxarg, widthptr);
-
-       if(debug['f'])
-               frame(0);
-
-ret:
-       lineno = lno;
 }
 
+
 /*
  * generate:
  *     call f
@@ -163,7 +60,7 @@ ginscall(Node *f, int proc)
                if(proc == 2) {
                        nodreg(&reg, types[TINT64], D_AX);
                        gins(ATESTQ, &reg, &reg);
-                       patch(gbranch(AJNE, T), pret);
+                       patch(gbranch(AJNE, T), retpc);
                }
                break;
        }
@@ -355,7 +252,7 @@ cgen_ret(Node *n)
 {
        genlist(n->list);               // copy out args
        if(hasdefer || curfn->exit)
-               gjmp(pret);
+               gjmp(retpc);
        else
                gins(ARET, N, N);
 }
index 09cf8d4e30633360cc285b108834c2092bc97b5a..b459782a386be2e59721c6b5e5cf37c4edc1f954 100644 (file)
@@ -15,15 +15,16 @@ HFILES=\
 
 OFILES=\
        ../8l/enam.$O\
-       list.$O\
-       galign.$O\
-       gobj.$O\
-       ggen.$O\
-       gsubr.$O\
        cgen.$O\
        cgen64.$O\
        cplx.$O\
+       galign.$O\
+       ggen.$O\
+       gobj.$O\
+       gsubr.$O\
+       list.$O\
        peep.$O\
+       pgen.$O\
        reg.$O\
 
 LIB=\
index 22315253640365b5bcb824b32f8737d2af4beade..25adb38c0c14c468642adca0a23f6911919da483 100644 (file)
@@ -7,106 +7,9 @@
 #include "gg.h"
 #include "opt.h"
 
-static Prog *pret;
-
 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
        ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr);
 
@@ -115,12 +18,6 @@ compile(Node *fn)
                maxstksize = stksize;
        ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
        maxstksize = 0;
-
-       if(debug['f'])
-               frame(0);
-
-ret:
-       lineno = lno;
 }
 
 void
@@ -200,7 +97,7 @@ ginscall(Node *f, int proc)
                if(proc == 2) {
                        nodreg(&reg, types[TINT64], D_AX);
                        gins(ATESTL, &reg, &reg);
-                       patch(gbranch(AJNE, T), pret);
+                       patch(gbranch(AJNE, T), retpc);
                }
                break;
        }
@@ -391,8 +288,8 @@ void
 cgen_ret(Node *n)
 {
        genlist(n->list);               // copy out args
-       if(pret)
-               gjmp(pret);
+       if(retpc)
+               gjmp(retpc);
        else
                gins(ARET, N, N);
 }
index 95013586b86ae5aca3bcb2982bfc6d44baa4cb5e..78c676346fa1545fb08822f08dd7adbba3e4c9e9 100644 (file)
@@ -1251,9 +1251,6 @@ funccompile(Node *n, int isclosure)
 
        if(curfn)
                fatal("funccompile %S inside %S", n->nname->sym, curfn->nname->sym);
-       curfn = n;
-       typechecklist(n->nbody, Etop);
-       curfn = nil;
 
        stksize = 0;
        dclcontext = PAUTO;
index f355e53c53f6286e58b95ca4f973a2d0f43acb5c..f5c0443f84b9b20742166d84287c13000771f480 100644 (file)
@@ -1213,6 +1213,7 @@ EXTERN    Prog*   continpc;
 EXTERN Prog*   breakpc;
 EXTERN Prog*   pc;
 EXTERN Prog*   firstpc;
+EXTERN Prog*   retpc;
 
 EXTERN Node*   nodfp;
 
@@ -1226,6 +1227,7 @@ void      cgen_callinter(Node *n, Node *res, int proc);
 void   cgen_ret(Node *n);
 void   clearfat(Node *n);
 void   compile(Node*);
+void   defframe(Prog*);
 int    dgostringptr(Sym*, int off, char *str);
 int    dgostrlitptr(Sym*, int off, Strlit*);
 int    dstringptr(Sym *s, int off, char *str);
index af4eb03360730b1091b31e4933aafffb82f76daa..8818db08c72c37383c0519fea8922fe1259dd403 100644 (file)
@@ -182,11 +182,14 @@ fninit(NodeList *n)
        // (11)
        a = nod(ORETURN, N, N);
        r = list(r, a);
-
        exportsym(fn->nname);
 
        fn->nbody = r;
        funcbody(fn);
+
+       curfn = fn;
        typecheck(&fn, Etop);
+       typechecklist(r, Etop);
+       curfn = nil;
        funccompile(fn, 0);
 }
index 04dd0d5b9507100fedcba7e286a8e13bda32bf57..5e2f73fc5ab22840d7b437e5dd01ef20533d90a2 100644 (file)
@@ -235,13 +235,14 @@ main(int argc, char *argv[])
        if(debug['f'])
                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.
        //   This will gather all the information about types
        //   and methods but doesn't depend on any of it.
        // Phase 2: Variable assignments.
        //   To check interface assignments, depends on phase 1.
-       // Phase 3: Function bodies.
+       // Phase 3: Type check function bodies.
+       // Phase 4: Compile function bodies.
        defercheckwidth();
        for(l=xtop; l; l=l->next)
                if(l->n->op != ODCL && l->n->op != OAS)
@@ -251,17 +252,28 @@ main(int argc, char *argv[])
                        typecheck(&l->n, Etop);
        resumetypecopy();
        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)
                if(l->n->op == ODCLFUNC)
                        funccompile(l->n, 0);
+
        if(nerrors == 0)
                fninit(xtop);
+
        while(closures) {
                l = closures;
                closures = nil;
                for(; l; l=l->next)
                        funccompile(l->n, 1);
        }
+
        dclchecks();
 
        if(nerrors)
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
new file mode 100644 (file)
index 0000000..9bd845d
--- /dev/null
@@ -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;
+}
index 326a5ba74aba4309c7880d0946fc6e14ef15d15a..4c0819cd86750aba3efe84b37833acada06cf2b7 100644 (file)
@@ -3170,7 +3170,10 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
                dumplist("genwrapper body", fn->nbody);
 
        funcbody(fn);
+       curfn = fn;
        typecheck(&fn, Etop);
+       typechecklist(fn->nbody, Etop);
+       curfn = nil;
        funccompile(fn, 0);
 }
 
index 70dc40759395aa7b930f2758eab4028af914bbad..ccc65ff2158e6a52ec38112283f118ae2844c338 100644 (file)
@@ -66,6 +66,7 @@ walk(Node *fn)
        int lno;
 
        curfn = fn;
+
        if(debug['W']) {
                snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
                dumplist(s, curfn->nbody);
@@ -73,7 +74,7 @@ walk(Node *fn)
        if(curfn->type->outtuple)
                if(walkret(curfn->nbody))
                        yyerror("function ends without a return statement");
-       typechecklist(curfn->nbody, Etop);
+
        lno = lineno;
        for(l=fn->dcl; l; l=l->next) {
                n = l->n;
@@ -468,8 +469,10 @@ walkstmt(Node **np)
        case OPANIC:
        case OEMPTY:
        case ORECOVER:
-               if(n->typecheck == 0)
+               if(n->typecheck == 0) {
+                       dump("missing typecheck:", n);
                        fatal("missing typecheck");
+               }
                init = n->ninit;
                n->ninit = nil;
                walkexpr(&n, &init);