]> Cypherpunks repositories - gostls13.git/commitdiff
move portable code generation (basic statements) to gc.
authorRuss Cox <rsc@golang.org>
Tue, 31 Mar 2009 02:15:07 +0000 (19:15 -0700)
committerRuss Cox <rsc@golang.org>
Tue, 31 Mar 2009 02:15:07 +0000 (19:15 -0700)
R=ken
OCL=26929
CL=26929

src/cmd/6g/align.c
src/cmd/6g/gen.c
src/cmd/6g/gg.h
src/cmd/6g/gsubr.c
src/cmd/gc/Makefile
src/cmd/gc/align.c
src/cmd/gc/gen.c [new file with mode: 0644]
src/cmd/gc/go.h
src/cmd/gc/lex.c

index 5f8f8d35c928d24a93c114b827cb6625d9af045e..209ac324faeba621a01d3808ce166d0f44196f3a 100644 (file)
@@ -30,7 +30,5 @@ betypeinit(void)
        zprog.from.scale = 0;
        zprog.to = zprog.from;
 
-       symstringo = lookup(".stringo");        // strings
-
        listinit();
 }
index bf7c32d55b43b528cf9f5163e501a3625e4c5120..8e047b8d0399d207bb309f87d5e4f14ade70ce84 100644 (file)
@@ -8,17 +8,6 @@
 #include "gg.h"
 #include "opt.h"
 
-static Node*
-sysfunc(char *name)
-{
-       Node *n;
-
-       n = newname(pkglookup(name, "sys"));
-       n->class = PFUNC;
-       return n;
-}
-
-
 void
 compile(Node *fn)
 {
@@ -29,16 +18,13 @@ compile(Node *fn)
        Type *t;
        Iter save;
 
-       if(newproc == N)
+       if(newproc == N) {
                newproc = sysfunc("newproc");
-       if(deferproc == N)
                deferproc = sysfunc("deferproc");
-       if(deferreturn == N)
                deferreturn = sysfunc("deferreturn");
-       if(throwindex == N)
                throwindex = sysfunc("throwindex");
-       if(throwreturn == N)
                throwreturn = sysfunc("throwreturn");
+       }
 
        if(fn->nbody == N)
                return;
@@ -110,297 +96,6 @@ ret:
        lineno = lno;
 }
 
-void
-allocparams(void)
-{
-       Dcl *d;
-       Node *n;
-       uint32 w;
-
-       /*
-        * allocate (set xoffset) the stack
-        * slots for all automatics.
-        * allocated starting at -w down.
-        */
-       for(d=autodcl; d!=D; d=d->forw) {
-               if(d->op != ONAME)
-                       continue;
-
-               n = d->dnode;
-               if(n->class != PAUTO)
-                       continue;
-
-               dowidth(n->type);
-               w = n->type->width;
-               if(n->class & PHEAP)
-                       w = widthptr;
-               stksize += w;
-               stksize = rnd(stksize, w);
-
-               n->xoffset = -stksize;
-       }
-}
-
-void
-newlab(int op, Sym *s)
-{
-       Label *lab;
-
-       lab = mal(sizeof(*lab));
-       lab->link = labellist;
-       labellist = lab;
-
-       lab->sym = s;
-       lab->op = op;
-       lab->label = pc;
-}
-
-/*
- * compile statements
- */
-void
-gen(Node *n)
-{
-       int32 lno;
-       Prog *scontin, *sbreak;
-       Prog *p1, *p2, *p3;
-       Label *lab;
-
-       lno = setlineno(n);
-
-loop:
-       if(n == N)
-               goto ret;
-
-       p3 = pc;        // save pc for loop labels
-       if(n->ninit)
-               gen(n->ninit);
-
-       setlineno(n);
-
-       switch(n->op) {
-       default:
-               fatal("gen: unknown op %N", n);
-               break;
-
-       case OLIST:
-               gen(n->left);
-               n = n->right;
-               goto loop;
-
-       case OCASE:
-       case OFALL:
-       case OXCASE:
-       case OXFALL:
-       case OEMPTY:
-               break;
-
-       case OLABEL:
-               newlab(OLABEL, n->left->sym);
-               break;
-
-       case OGOTO:
-               newlab(OGOTO, n->left->sym);
-               gbranch(AJMP, T);
-               break;
-
-       case OBREAK:
-               if(n->left != N) {
-                       for(lab=labellist; lab!=L; lab=lab->link) {
-                               if(lab->breakpc != P) {
-                                       patch(gbranch(AJMP, T), lab->breakpc);
-                                       break;
-                               }
-                       }
-                       if(lab == L)
-                               yyerror("break label not defined: %S", n->left->sym);
-                       break;
-               }
-               if(breakpc == P) {
-                       yyerror("break is not in a loop");
-                       break;
-               }
-               patch(gbranch(AJMP, T), breakpc);
-               break;
-
-       case OCONTINUE:
-               if(n->left != N) {
-                       for(lab=labellist; lab!=L; lab=lab->link) {
-                               if(lab->continpc != P) {
-                                       patch(gbranch(AJMP, T), lab->continpc);
-                                       break;
-                               }
-                       }
-                       if(lab == L)
-                               yyerror("break label not defined: %S", n->left->sym);
-                       break;
-               }
-
-               if(continpc == P) {
-                       yyerror("gen: continue is not in a loop");
-                       break;
-               }
-               patch(gbranch(AJMP, T), continpc);
-               break;
-
-       case OFOR:
-               sbreak = breakpc;
-               p1 = gbranch(AJMP, T);                  //              goto test
-               breakpc = gbranch(AJMP, T);             // break:       goto done
-               scontin = continpc;
-               continpc = pc;
-
-               // define break and cotinue labels
-               for(lab=labellist; lab!=L; lab=lab->link) {
-                       if(lab->label != p3)
-                               break;
-                       if(lab->op == OLABEL) {
-                               lab->breakpc = breakpc;
-                               lab->continpc = continpc;
-                       }
-               }
-
-               gen(n->nincr);                          // contin:      incr
-               patch(p1, pc);                          // test:
-               if(n->ntest != N)
-                       if(n->ntest->ninit != N)
-                               gen(n->ntest->ninit);
-               bgen(n->ntest, 0, breakpc);             //              if(!test) goto break
-               gen(n->nbody);                          //              body
-               patch(gbranch(AJMP, T), continpc);      //              goto contin
-               patch(breakpc, pc);                     // done:
-               continpc = scontin;
-               breakpc = sbreak;
-               break;
-
-       case OIF:
-               p1 = gbranch(AJMP, T);                  //              goto test
-               p2 = gbranch(AJMP, T);                  // p2:          goto else
-               patch(p1, pc);                          // test:
-               if(n->ntest != N)
-                       if(n->ntest->ninit != N)
-                               gen(n->ntest->ninit);
-               bgen(n->ntest, 0, p2);                  //              if(!test) goto p2
-               gen(n->nbody);                          //              then
-               p3 = gbranch(AJMP, T);                  //              goto done
-               patch(p2, pc);                          // else:
-               gen(n->nelse);                          //              else
-               patch(p3, pc);                          // done:
-               break;
-
-       case OSWITCH:
-               sbreak = breakpc;
-               p1 = gbranch(AJMP, T);                  //              goto test
-               breakpc = gbranch(AJMP, T);             // break:       goto done
-
-               // define break label
-               for(lab=labellist; lab!=L; lab=lab->link) {
-                       if(lab->label != p3)
-                               break;
-                       if(lab->op == OLABEL) {
-                               lab->breakpc = breakpc;
-                       }
-               }
-
-               patch(p1, pc);                          // test:
-               gen(n->nbody);                          //              switch(test) body
-               patch(breakpc, pc);                     // done:
-               breakpc = sbreak;
-               break;
-
-       case OSELECT:
-               sbreak = breakpc;
-               p1 = gbranch(AJMP, T);                  //              goto test
-               breakpc = gbranch(AJMP, T);             // break:       goto done
-
-               // define break label
-               for(lab=labellist; lab!=L; lab=lab->link) {
-                       if(lab->label != p3)
-                               break;
-                       if(lab->op == OLABEL) {
-                               lab->breakpc = breakpc;
-                       }
-               }
-
-               patch(p1, pc);                          // test:
-               gen(n->nbody);                          //              select() body
-               patch(breakpc, pc);                     // done:
-               breakpc = sbreak;
-               break;
-
-       case OASOP:
-               cgen_asop(n);
-               break;
-
-       case ODCL:
-               cgen_dcl(n->left);
-               break;
-
-       case OAS:
-               cgen_as(n->left, n->right);
-               break;
-
-       case OCALLMETH:
-               cgen_callmeth(n, 0);
-               break;
-
-       case OCALLINTER:
-               cgen_callinter(n, N, 0);
-               break;
-
-       case OCALL:
-               cgen_call(n, 0);
-               break;
-
-       case OPROC:
-               cgen_proc(n, 1);
-               break;
-
-       case ODEFER:
-               cgen_proc(n, 2);
-               break;
-
-       case ORETURN:
-               cgen_ret(n);
-               break;
-       }
-
-ret:
-       lineno = lno;
-}
-
-/*
- * compute total size of f's in/out arguments.
- */
-int
-argsize(Type *t)
-{
-       Iter save;
-       Type *fp;
-       int w, x;
-
-       w = 0;
-
-       fp = structfirst(&save, getoutarg(t));
-       while(fp != T) {
-               x = fp->width + fp->type->width;
-               if(x > w)
-                       w = x;
-               fp = structnext(&save);
-       }
-
-       fp = funcfirst(&save, t);
-       while(fp != T) {
-               x = fp->width + fp->type->width;
-               if(x > w)
-                       w = x;
-               fp = funcnext(&save);
-       }
-
-       w = (w+7) & ~7;
-       return w;
-}
-
 /*
  * generate:
  *     call f
@@ -494,33 +189,6 @@ cgen_callinter(Node *n, Node *res, int proc)
        setmaxarg(n->left->type);
 }
 
-/*
- * generate call to non-interface method
- *     proc=0  normal call
- *     proc=1  goroutine run in new proc
- *     proc=2  defer call save away stack
- */
-void
-cgen_callmeth(Node *n, int proc)
-{
-       Node *l;
-
-       // generate a rewrite for method call
-       // (p.f)(...) goes to (f)(p,...)
-
-       l = n->left;
-       if(l->op != ODOTMETH)
-               fatal("cgen_callmeth: not dotmethod: %N");
-
-       n->op = OCALL;
-       n->left = n->left->right;
-       n->left->type = l->type;
-
-       if(n->left->op == ONAME)
-               n->left->class = PFUNC;
-       cgen_call(n, proc);
-}
-
 /*
  * generate function call;
  *     proc=0  normal call
@@ -577,31 +245,6 @@ ret:
        ;
 }
 
-/*
- * generate code to start new proc running call n.
- */
-void
-cgen_proc(Node *n, int proc)
-{
-       switch(n->left->op) {
-       default:
-               fatal("cgen_proc: unknown call %O", n->left->op);
-
-       case OCALLMETH:
-               cgen_callmeth(n->left, proc);
-               break;
-
-       case OCALLINTER:
-               cgen_callinter(n->left, N, proc);
-               break;
-
-       case OCALL:
-               cgen_call(n->left, proc);
-               break;
-       }
-
-}
-
 /*
  * call to n has already been generated.
  * generate:
@@ -807,152 +450,6 @@ ret:
        ;
 }
 
-/*
- * generate declaration.
- * nothing to do for on-stack automatics,
- * but might have to allocate heap copy
- * for escaped variables.
- */
-void
-cgen_dcl(Node *n)
-{
-       if(debug['g'])
-               dump("\ncgen-dcl", n);
-       if(n->op != ONAME) {
-               dump("cgen_dcl", n);
-               fatal("cgen_dcl");
-       }
-       if(!(n->class & PHEAP))
-               return;
-       cgen_as(n->heapaddr, n->alloc);
-}
-
-/*
- * generate assignment:
- *     nl = nr
- * nr == N means zero nl.
- */
-void
-cgen_as(Node *nl, Node *nr)
-{
-       Node nc, n1;
-       Type *tl;
-       uint32 w, c, q;
-       int iszer;
-
-       if(nl == N)
-               return;
-
-       if(debug['g']) {
-               dump("cgen_as", nl);
-               dump("cgen_as = ", nr);
-       }
-
-       iszer = 0;
-       if(nr == N || isnil(nr)) {
-               if(nl->op == OLIST) {
-                       cgen_as(nl->left, nr);
-                       cgen_as(nl->right, nr);
-                       return;
-               }
-               tl = nl->type;
-               if(tl == T)
-                       return;
-               if(isfat(tl)) {
-                       /* clear a fat object */
-                       if(debug['g'])
-                               dump("\nclearfat", nl);
-
-                       w = nl->type->width;
-                       c = w % 8;      // bytes
-                       q = w / 8;      // quads
-
-                       gconreg(AMOVQ, 0, D_AX);
-                       nodreg(&n1, types[tptr], D_DI);
-                       agen(nl, &n1);
-
-                       if(q >= 4) {
-                               gconreg(AMOVQ, q, D_CX);
-                               gins(AREP, N, N);       // repeat
-                               gins(ASTOSQ, N, N);     // STOQ AL,*(DI)+
-                       } else
-                       while(q > 0) {
-                               gins(ASTOSQ, N, N);     // STOQ AL,*(DI)+
-                               q--;
-                       }
-
-                       if(c >= 4) {
-                               gconreg(AMOVQ, c, D_CX);
-                               gins(AREP, N, N);       // repeat
-                               gins(ASTOSB, N, N);     // STOB AL,*(DI)+
-                       } else
-                       while(c > 0) {
-                               gins(ASTOSB, N, N);     // STOB AL,*(DI)+
-                               c--;
-                       }
-                       goto ret;
-               }
-
-               /* invent a "zero" for the rhs */
-               iszer = 1;
-               nr = &nc;
-               memset(nr, 0, sizeof(*nr));
-               switch(simtype[tl->etype]) {
-               default:
-                       fatal("cgen_as: tl %T", tl);
-                       break;
-
-               case TINT8:
-               case TUINT8:
-               case TINT16:
-               case TUINT16:
-               case TINT32:
-               case TUINT32:
-               case TINT64:
-               case TUINT64:
-                       nr->val.u.xval = mal(sizeof(*nr->val.u.xval));
-                       mpmovecfix(nr->val.u.xval, 0);
-                       nr->val.ctype = CTINT;
-                       break;
-
-               case TFLOAT32:
-               case TFLOAT64:
-               case TFLOAT80:
-                       nr->val.u.fval = mal(sizeof(*nr->val.u.fval));
-                       mpmovecflt(nr->val.u.fval, 0.0);
-                       nr->val.ctype = CTFLT;
-                       break;
-
-               case TBOOL:
-                       nr->val.u.bval = 0;
-                       nr->val.ctype = CTBOOL;
-                       break;
-
-               case TPTR32:
-               case TPTR64:
-                       nr->val.ctype = CTNIL;
-                       break;
-
-               }
-               nr->op = OLITERAL;
-               nr->type = tl;
-               nr->addable = 1;
-               ullmancalc(nr);
-       }
-
-       tl = nl->type;
-       if(tl == T)
-               return;
-
-       cgen(nr, nl);
-       if(iszer && nl->addable)
-               gins(ANOP, nl, N);      // used
-
-
-ret:
-       ;
-}
-
 int
 samereg(Node *a, Node *b)
 {
@@ -1156,61 +653,40 @@ cgen_bmul(int op, Node *nl, Node *nr, Node *res)
 }
 
 void
-checklabels(void)
+clearfat(Node *nl)
 {
-       Label *l, *m;
-       Sym *s;
-
-//     // print the label list
-//     for(l=labellist; l!=L; l=l->link) {
-//             print("lab %O %S\n", l->op, l->sym);
-//     }
-
-       for(l=labellist; l!=L; l=l->link) {
-       switch(l->op) {
-               case OFOR:
-               case OLABEL:
-                       // these are definitions -
-                       s = l->sym;
-                       for(m=labellist; m!=L; m=m->link) {
-                               if(m->sym != s)
-                                       continue;
-                               switch(m->op) {
-                               case OFOR:
-                               case OLABEL:
-                                       // these are definitions -
-                                       // look for redefinitions
-                                       if(l != m)
-                                               yyerror("label %S redefined", s);
-                                       break;
-                               case OGOTO:
-                                       // these are references -
-                                       // patch to definition
-                                       patch(m->label, l->label);
-                                       m->sym = S;     // mark done
-                                       break;
-                               }
-                       }
-               }
-       }
+       uint32 w, c, q;
+       Node n1;
 
-       // diagnostic for all undefined references
-       for(l=labellist; l!=L; l=l->link)
-               if(l->op == OGOTO && l->sym != S)
-                       yyerror("label %S not defined", l->sym);
-}
+       /* clear a fat object */
+       if(debug['g'])
+               dump("\nclearfat", nl);
 
-Label*
-findlab(Sym *s)
-{
-       Label *l;
-
-       for(l=labellist; l!=L; l=l->link) {
-               if(l->sym != s)
-                       continue;
-               if(l->op != OFOR)
-                       continue;
-               return l;
+       w = nl->type->width;
+       c = w % 8;      // bytes
+       q = w / 8;      // quads
+
+       gconreg(AMOVQ, 0, D_AX);
+       nodreg(&n1, types[tptr], D_DI);
+       agen(nl, &n1);
+
+       if(q >= 4) {
+               gconreg(AMOVQ, q, D_CX);
+               gins(AREP, N, N);       // repeat
+               gins(ASTOSQ, N, N);     // STOQ AL,*(DI)+
+       } else
+       while(q > 0) {
+               gins(ASTOSQ, N, N);     // STOQ AL,*(DI)+
+               q--;
+       }
+
+       if(c >= 4) {
+               gconreg(AMOVQ, c, D_CX);
+               gins(AREP, N, N);       // repeat
+               gins(ASTOSB, N, N);     // STOB AL,*(DI)+
+       } else
+       while(c > 0) {
+               gins(ASTOSB, N, N);     // STOB AL,*(DI)+
+               c--;
        }
-       return L;
 }
index 8ba4028db8913d810367e695de7bd867b49668af..af1e2c2ccca8eaea105163066afcb38458cfca2d 100644 (file)
@@ -13,7 +13,6 @@
 #define EXTERN extern
 #endif
 
-typedef        struct  Prog    Prog;
 typedef        struct  Addr    Addr;
 
 struct Addr
@@ -41,7 +40,6 @@ struct        Prog
        Prog*   link;           // next instruction in this func
        void*   reg;            // pointer to containing Reg struct
 };
-#define        P       ((Prog*)0)
 
 typedef        struct  Plist   Plist;
 struct Plist
@@ -53,22 +51,6 @@ struct       Plist
        Plist*  link;
 };
 
-typedef        struct  Label Label;
-struct Label
-{
-       uchar   op;             // OGOTO/OLABEL
-       Sym*    sym;
-       Prog*   label;          // pointer to code
-       Prog*   breakpc;        // pointer to code
-       Prog*   continpc;       // pointer to code
-       Label*  link;
-};
-#define        L       ((Label*)0)
-
-EXTERN Prog*   continpc;
-EXTERN Prog*   breakpc;
-EXTERN Prog*   pc;
-EXTERN Prog*   firstpc;
 EXTERN Plist*  plist;
 EXTERN Plist*  plast;
 EXTERN Biobuf* bout;
@@ -79,8 +61,6 @@ EXTERN        String  emptystring;
 extern char*   anames[];
 EXTERN Hist*   hist;
 EXTERN Prog    zprog;
-EXTERN Label*  labellist;
-EXTERN Label*  findlab(Sym*);
 EXTERN Node*   curfn;
 EXTERN Node*   newproc;
 EXTERN Node*   deferproc;
@@ -96,9 +76,6 @@ void  proglist(void);
 void   gen(Node*);
 Node*  lookdot(Node*, Node*, int);
 void   cgen_as(Node*, Node*);
-void   cgen_asop(Node*);
-void   cgen_ret(Node*);
-void   cgen_call(Node*, int);
 void   cgen_callmeth(Node*, int);
 void   cgen_callinter(Node*, Node*, int);
 void   cgen_proc(Node*, int);
@@ -116,7 +93,6 @@ void ginscall(Node*, int);
 /*
  * cgen
  */
-void   cgen(Node*, Node*);
 void   agen(Node*, Node*);
 void   igen(Node*, Node*, Node*);
 vlong  fieldoffset(Type*, Node*);
@@ -134,7 +110,6 @@ void        cgen_aret(Node*, Node*);
 void   clearp(Prog*);
 void   proglist(void);
 Prog*  gbranch(int, Type*);
-void   patch(Prog*, Prog*);
 Prog*  prog(int);
 void   gaddoffset(Node*);
 void   gconv(int, int);
index 6ce9ade350b319596fd9ae5d9d2ad94c05b54918..ab4979a34b0e78172c37eea771a80a0a4b1a3e51 100644 (file)
@@ -1927,3 +1927,21 @@ no:
        sudoclean();
        return 0;
 }
+
+void
+gused(Node *n)
+{
+       gins(ANOP, n, N);       // used
+}
+
+Prog*
+gjmp(Prog *to)
+{
+       Prog *p;
+       
+       p = gbranch(AJMP, T);
+       if(to != P)
+               patch(p, to);
+       return p;
+}
+
index 23fe2a6d7eeda146a1b526a64bc3cbf7b2cab9b0..2f79f31cbb855dabca106a69e004f1bd1fe97d3f 100644 (file)
@@ -30,6 +30,7 @@ OFILES=\
        compat.$O\
        bits.$O\
        align.$O\
+       gen.$O\
 
 $(LIB): $(OFILES)
        ar rsc $(LIB) $(OFILES)
index 7c39c646c0097fa7a4ba67a04f82a4b53369f1e0..7c2960277e32f39da842bcbefb4e9a0e43aa9524 100644 (file)
@@ -349,3 +349,35 @@ typeinit(int lex)
        Array_cap = rnd(Array_nel+types[TUINT32]->width, types[TUINT32]->width);
        sizeof_Array = rnd(Array_cap+types[TUINT32]->width, maxround);
 }
+
+/*
+ * compute total size of f's in/out arguments.
+ */
+int
+argsize(Type *t)
+{
+       Iter save;
+       Type *fp;
+       int w, x;
+
+       w = 0;
+
+       fp = structfirst(&save, getoutarg(t));
+       while(fp != T) {
+               x = fp->width + fp->type->width;
+               if(x > w)
+                       w = x;
+               fp = structnext(&save);
+       }
+
+       fp = funcfirst(&save, t);
+       while(fp != T) {
+               x = fp->width + fp->type->width;
+               if(x > w)
+                       w = x;
+               fp = funcnext(&save);
+       }
+
+       w = (w+7) & ~7;
+       return w;
+}
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
new file mode 100644 (file)
index 0000000..410c1a5
--- /dev/null
@@ -0,0 +1,505 @@
+// Copyright 2009 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.
+
+/*
+ * portable half of code generator.
+ * mainly statements and control flow.
+ */
+
+#include "go.h"
+
+Node*
+sysfunc(char *name)
+{
+       Node *n;
+
+       n = newname(pkglookup(name, "sys"));
+       n->class = PFUNC;
+       return n;
+}
+
+void
+allocparams(void)
+{
+       Dcl *d;
+       Node *n;
+       uint32 w;
+
+       /*
+        * allocate (set xoffset) the stack
+        * slots for all automatics.
+        * allocated starting at -w down.
+        */
+       for(d=autodcl; d!=D; d=d->forw) {
+               if(d->op != ONAME)
+                       continue;
+
+               n = d->dnode;
+               if(n->class != PAUTO)
+                       continue;
+
+               dowidth(n->type);
+               w = n->type->width;
+               if(n->class & PHEAP)
+                       w = widthptr;
+               stksize += w;
+               stksize = rnd(stksize, w);
+
+               n->xoffset = -stksize;
+       }
+}
+
+void
+newlab(int op, Sym *s)
+{
+       Label *lab;
+
+       lab = mal(sizeof(*lab));
+       lab->link = labellist;
+       labellist = lab;
+
+       lab->sym = s;
+       lab->op = op;
+       lab->label = pc;
+}
+
+void
+checklabels(void)
+{
+       Label *l, *m;
+       Sym *s;
+
+//     // print the label list
+//     for(l=labellist; l!=L; l=l->link) {
+//             print("lab %O %S\n", l->op, l->sym);
+//     }
+
+       for(l=labellist; l!=L; l=l->link) {
+       switch(l->op) {
+               case OFOR:
+               case OLABEL:
+                       // these are definitions -
+                       s = l->sym;
+                       for(m=labellist; m!=L; m=m->link) {
+                               if(m->sym != s)
+                                       continue;
+                               switch(m->op) {
+                               case OFOR:
+                               case OLABEL:
+                                       // these are definitions -
+                                       // look for redefinitions
+                                       if(l != m)
+                                               yyerror("label %S redefined", s);
+                                       break;
+                               case OGOTO:
+                                       // these are references -
+                                       // patch to definition
+                                       patch(m->label, l->label);
+                                       m->sym = S;     // mark done
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       // diagnostic for all undefined references
+       for(l=labellist; l!=L; l=l->link)
+               if(l->op == OGOTO && l->sym != S)
+                       yyerror("label %S not defined", l->sym);
+}
+
+Label*
+findlab(Sym *s)
+{
+       Label *l;
+
+       for(l=labellist; l!=L; l=l->link) {
+               if(l->sym != s)
+                       continue;
+               if(l->op != OFOR)
+                       continue;
+               return l;
+       }
+       return L;
+}
+
+/*
+ * compile statements
+ */
+void
+gen(Node *n)
+{
+       int32 lno;
+       Prog *scontin, *sbreak;
+       Prog *p1, *p2, *p3;
+       Label *lab;
+
+       lno = setlineno(n);
+
+loop:
+       if(n == N)
+               goto ret;
+
+       p3 = pc;        // save pc for loop labels
+       if(n->ninit)
+               gen(n->ninit);
+
+       setlineno(n);
+
+       switch(n->op) {
+       default:
+               fatal("gen: unknown op %N", n);
+               break;
+
+       case OLIST:
+               gen(n->left);
+               n = n->right;
+               goto loop;
+
+       case OCASE:
+       case OFALL:
+       case OXCASE:
+       case OXFALL:
+       case OEMPTY:
+               break;
+
+       case OLABEL:
+               newlab(OLABEL, n->left->sym);
+               break;
+
+       case OGOTO:
+               newlab(OGOTO, n->left->sym);
+               gjmp(P);
+               break;
+
+       case OBREAK:
+               if(n->left != N) {
+                       for(lab=labellist; lab!=L; lab=lab->link) {
+                               if(lab->breakpc != P) {
+                                       gjmp(lab->breakpc);
+                                       break;
+                               }
+                       }
+                       if(lab == L)
+                               yyerror("break label not defined: %S", n->left->sym);
+                       break;
+               }
+               if(breakpc == P) {
+                       yyerror("break is not in a loop");
+                       break;
+               }
+               gjmp(breakpc);
+               break;
+
+       case OCONTINUE:
+               if(n->left != N) {
+                       for(lab=labellist; lab!=L; lab=lab->link) {
+                               if(lab->continpc != P) {
+                                       gjmp(lab->continpc);
+                                       break;
+                               }
+                       }
+                       if(lab == L)
+                               yyerror("break label not defined: %S", n->left->sym);
+                       break;
+               }
+
+               if(continpc == P) {
+                       yyerror("gen: continue is not in a loop");
+                       break;
+               }
+               gjmp(continpc);
+               break;
+
+       case OFOR:
+               sbreak = breakpc;
+               p1 = gjmp(P);                   //              goto test
+               breakpc = gjmp(P);              // break:       goto done
+               scontin = continpc;
+               continpc = pc;
+
+               // define break and cotinue labels
+               for(lab=labellist; lab!=L; lab=lab->link) {
+                       if(lab->label != p3)
+                               break;
+                       if(lab->op == OLABEL) {
+                               lab->breakpc = breakpc;
+                               lab->continpc = continpc;
+                       }
+               }
+
+               gen(n->nincr);                          // contin:      incr
+               patch(p1, pc);                          // test:
+               if(n->ntest != N)
+                       if(n->ntest->ninit != N)
+                               gen(n->ntest->ninit);
+               bgen(n->ntest, 0, breakpc);             //              if(!test) goto break
+               gen(n->nbody);                          //              body
+               gjmp(continpc);
+               patch(breakpc, pc);                     // done:
+               continpc = scontin;
+               breakpc = sbreak;
+               break;
+
+       case OIF:
+               p1 = gjmp(P);                   //              goto test
+               p2 = gjmp(P);                   // p2:          goto else
+               patch(p1, pc);                          // test:
+               if(n->ntest != N)
+                       if(n->ntest->ninit != N)
+                               gen(n->ntest->ninit);
+               bgen(n->ntest, 0, p2);                  //              if(!test) goto p2
+               gen(n->nbody);                          //              then
+               p3 = gjmp(P);                   //              goto done
+               patch(p2, pc);                          // else:
+               gen(n->nelse);                          //              else
+               patch(p3, pc);                          // done:
+               break;
+
+       case OSWITCH:
+               sbreak = breakpc;
+               p1 = gjmp(P);                   //              goto test
+               breakpc = gjmp(P);              // break:       goto done
+
+               // define break label
+               for(lab=labellist; lab!=L; lab=lab->link) {
+                       if(lab->label != p3)
+                               break;
+                       if(lab->op == OLABEL) {
+                               lab->breakpc = breakpc;
+                       }
+               }
+
+               patch(p1, pc);                          // test:
+               gen(n->nbody);                          //              switch(test) body
+               patch(breakpc, pc);                     // done:
+               breakpc = sbreak;
+               break;
+
+       case OSELECT:
+               sbreak = breakpc;
+               p1 = gjmp(P);                   //              goto test
+               breakpc = gjmp(P);              // break:       goto done
+
+               // define break label
+               for(lab=labellist; lab!=L; lab=lab->link) {
+                       if(lab->label != p3)
+                               break;
+                       if(lab->op == OLABEL) {
+                               lab->breakpc = breakpc;
+                       }
+               }
+
+               patch(p1, pc);                          // test:
+               gen(n->nbody);                          //              select() body
+               patch(breakpc, pc);                     // done:
+               breakpc = sbreak;
+               break;
+
+       case OASOP:
+               cgen_asop(n);
+               break;
+
+       case ODCL:
+               cgen_dcl(n->left);
+               break;
+
+       case OAS:
+               cgen_as(n->left, n->right);
+               break;
+
+       case OCALLMETH:
+               cgen_callmeth(n, 0);
+               break;
+
+       case OCALLINTER:
+               cgen_callinter(n, N, 0);
+               break;
+
+       case OCALL:
+               cgen_call(n, 0);
+               break;
+
+       case OPROC:
+               cgen_proc(n, 1);
+               break;
+
+       case ODEFER:
+               cgen_proc(n, 2);
+               break;
+
+       case ORETURN:
+               cgen_ret(n);
+               break;
+       }
+
+ret:
+       lineno = lno;
+}
+
+/*
+ * generate call to non-interface method
+ *     proc=0  normal call
+ *     proc=1  goroutine run in new proc
+ *     proc=2  defer call save away stack
+ */
+void
+cgen_callmeth(Node *n, int proc)
+{
+       Node *l;
+
+       // generate a rewrite for method call
+       // (p.f)(...) goes to (f)(p,...)
+
+       l = n->left;
+       if(l->op != ODOTMETH)
+               fatal("cgen_callmeth: not dotmethod: %N");
+
+       n->op = OCALL;
+       n->left = n->left->right;
+       n->left->type = l->type;
+
+       if(n->left->op == ONAME)
+               n->left->class = PFUNC;
+       cgen_call(n, proc);
+}
+
+/*
+ * generate code to start new proc running call n.
+ */
+void
+cgen_proc(Node *n, int proc)
+{
+       switch(n->left->op) {
+       default:
+               fatal("cgen_proc: unknown call %O", n->left->op);
+
+       case OCALLMETH:
+               cgen_callmeth(n->left, proc);
+               break;
+
+       case OCALLINTER:
+               cgen_callinter(n->left, N, proc);
+               break;
+
+       case OCALL:
+               cgen_call(n->left, proc);
+               break;
+       }
+
+}
+
+/*
+ * generate declaration.
+ * nothing to do for on-stack automatics,
+ * but might have to allocate heap copy
+ * for escaped variables.
+ */
+void
+cgen_dcl(Node *n)
+{
+       if(debug['g'])
+               dump("\ncgen-dcl", n);
+       if(n->op != ONAME) {
+               dump("cgen_dcl", n);
+               fatal("cgen_dcl");
+       }
+       if(!(n->class & PHEAP))
+               return;
+       cgen_as(n->heapaddr, n->alloc);
+}
+
+/*
+ * generate assignment:
+ *     nl = nr
+ * nr == N means zero nl.
+ */
+void
+cgen_as(Node *nl, Node *nr)
+{
+       Node nc;
+       Type *tl;
+       int iszer;
+
+       if(nl == N)
+               return;
+
+       if(debug['g']) {
+               dump("cgen_as", nl);
+               dump("cgen_as = ", nr);
+       }
+
+       iszer = 0;
+       if(nr == N || isnil(nr)) {
+               if(nl->op == OLIST) {
+                       cgen_as(nl->left, nr);
+                       cgen_as(nl->right, nr);
+                       return;
+               }
+               tl = nl->type;
+               if(tl == T)
+                       return;
+               if(isfat(tl)) {
+                       clearfat(nl);
+                       goto ret;
+               }
+
+               /* invent a "zero" for the rhs */
+               iszer = 1;
+               nr = &nc;
+               memset(nr, 0, sizeof(*nr));
+               switch(simtype[tl->etype]) {
+               default:
+                       fatal("cgen_as: tl %T", tl);
+                       break;
+
+               case TINT8:
+               case TUINT8:
+               case TINT16:
+               case TUINT16:
+               case TINT32:
+               case TUINT32:
+               case TINT64:
+               case TUINT64:
+                       nr->val.u.xval = mal(sizeof(*nr->val.u.xval));
+                       mpmovecfix(nr->val.u.xval, 0);
+                       nr->val.ctype = CTINT;
+                       break;
+
+               case TFLOAT32:
+               case TFLOAT64:
+               case TFLOAT80:
+                       nr->val.u.fval = mal(sizeof(*nr->val.u.fval));
+                       mpmovecflt(nr->val.u.fval, 0.0);
+                       nr->val.ctype = CTFLT;
+                       break;
+
+               case TBOOL:
+                       nr->val.u.bval = 0;
+                       nr->val.ctype = CTBOOL;
+                       break;
+
+               case TPTR32:
+               case TPTR64:
+                       nr->val.ctype = CTNIL;
+                       break;
+
+               }
+               nr->op = OLITERAL;
+               nr->type = tl;
+               nr->addable = 1;
+               ullmancalc(nr);
+       }
+
+       tl = nl->type;
+       if(tl == T)
+               return;
+
+       cgen(nr, nl);
+       if(iszer && nl->addable)
+               gused(nl);
+
+ret:
+       ;
+}
index 0a6f1ccbb493c1e10c63aeb41b935e23059f55b4..2654d48cc26f61db7158cd52d759b42d5aa0f271 100644 (file)
@@ -937,26 +937,12 @@ int       smallintconst(Node*);
 int    consttype(Node*);
 int    isconst(Node*, int);
 
-/*
- *     gen.c/gsubr.c/obj.c
- */
-void   betypeinit(void);
-vlong  convvtox(vlong, int);
-void   compile(Node*);
-void   proglist(void);
-int    optopop(int);
-void   dumpobj(void);
-void   dowidth(Type*);
-void   argspace(int32);
-Node*  nodarg(Type*, int);
-Type*  deep(Type*);
-Type*  shallow(Type*);
-
 /*
  *     align.c
  */
 uint32 rnd(uint32, uint32);
 void   dowidth(Type*);
+int    argsize(Type*);
 
 /*
  *     bits.c
@@ -972,3 +958,66 @@ int        bset(Bits, uint);
 int    Qconv(Fmt *fp);
 int    bitno(int32);
 
+/*
+ *     gen.c
+ */
+typedef        struct  Prog    Prog;
+#define        P       ((Prog*)0)
+
+typedef        struct  Label Label;
+struct Label
+{
+       uchar   op;             // OGOTO/OLABEL
+       Sym*    sym;
+       Prog*   label;          // pointer to code
+       Prog*   breakpc;        // pointer to code
+       Prog*   continpc;       // pointer to code
+       Label*  link;
+};
+#define        L       ((Label*)0)
+
+EXTERN Label*  labellist;
+EXTERN Label*  findlab(Sym*);
+
+EXTERN Prog*   continpc;
+EXTERN Prog*   breakpc;
+EXTERN Prog*   pc;
+EXTERN Prog*   firstpc;
+
+void   allocparams(void);
+void   cgen_as(Node *nl, Node *nr);
+void   cgen_callmeth(Node *n, int proc);
+void   cgen_dcl(Node *n);
+void   cgen_proc(Node *n, int proc);
+void   checklabels(void);
+Label* findlab(Sym *s);
+void   gen(Node *n);
+void   newlab(int op, Sym *s);
+Node*  sysfunc(char *name);
+
+
+/*
+ *     gen.c/gsubr.c/obj.c
+ */
+void   betypeinit(void);
+vlong  convvtox(vlong, int);
+void   compile(Node*);
+void   proglist(void);
+int    optopop(int);
+void   dumpobj(void);
+void   dowidth(Type*);
+void   argspace(int32);
+Node*  nodarg(Type*, int);
+Type*  deep(Type*);
+Type*  shallow(Type*);
+Prog*  gjmp(Prog*);
+void   patch(Prog*, Prog*);
+void   bgen(Node *n, int true, Prog *to);
+void   cgen_asop(Node *n);
+void   cgen_call(Node *n, int proc);
+void   cgen_callinter(Node *n, Node *res, int proc);
+void   cgen_ret(Node *n);
+int    isfat(Type*);
+void   clearfat(Node *n);
+void   cgen(Node*, Node*);
+void   gused(Node*);
index 3bda54a7a0e1a70d3ceb9bdcebf6cfa8aef4f2a9..ab7ced37647fc13936ca40c5449ff9d9aadec576 100644 (file)
@@ -66,6 +66,8 @@ main(int argc, char *argv[])
        lexinit();
        typeinit(LBASETYPE);
 
+       symstringo = lookup(".stringo");        // strings
+
        lineno = 1;
        block = 1;
        blockgen = 1;
@@ -336,7 +338,8 @@ cannedimports(char *file, char *cp)
 }
 
 int
-isfrog(int c) {
+isfrog(int c)
+{
        // complain about possibly invisible control characters
        if(c < 0)
                return 1;