summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-03-30 19:15:07 -0700
committerRuss Cox <rsc@golang.org>2009-03-30 19:15:07 -0700
commitcf83eceb759122f8d76775a4e25723ff7c4c7f7e (patch)
tree14b7d5647a1062a7a6b5a2f9b8d0251b1fe4c1ee
parent15e351916302cdfbfd726d798501aebb6bed0f9f (diff)
downloadgolang-cf83eceb759122f8d76775a4e25723ff7c4c7f7e.tar.gz
move portable code generation (basic statements) to gc.
R=ken OCL=26929 CL=26929
-rw-r--r--src/cmd/6g/align.c2
-rw-r--r--src/cmd/6g/gen.c592
-rw-r--r--src/cmd/6g/gg.h25
-rw-r--r--src/cmd/6g/gsubr.c18
-rw-r--r--src/cmd/gc/Makefile1
-rw-r--r--src/cmd/gc/align.c32
-rw-r--r--src/cmd/gc/gen.c505
-rw-r--r--src/cmd/gc/go.h79
-rw-r--r--src/cmd/gc/lex.c5
9 files changed, 658 insertions, 601 deletions
diff --git a/src/cmd/6g/align.c b/src/cmd/6g/align.c
index 5f8f8d35c..209ac324f 100644
--- a/src/cmd/6g/align.c
+++ b/src/cmd/6g/align.c
@@ -30,7 +30,5 @@ betypeinit(void)
zprog.from.scale = 0;
zprog.to = zprog.from;
- symstringo = lookup(".stringo"); // strings
-
listinit();
}
diff --git a/src/cmd/6g/gen.c b/src/cmd/6g/gen.c
index bf7c32d55..8e047b8d0 100644
--- a/src/cmd/6g/gen.c
+++ b/src/cmd/6g/gen.c
@@ -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
@@ -495,33 +190,6 @@ cgen_callinter(Node *n, Node *res, int proc)
}
/*
- * 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
* proc=1 goroutine run in new proc
@@ -578,31 +246,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:
* res = return value from call.
@@ -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;
}
diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h
index 8ba4028db..af1e2c2cc 100644
--- a/src/cmd/6g/gg.h
+++ b/src/cmd/6g/gg.h
@@ -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);
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index 6ce9ade35..ab4979a34 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -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;
+}
+
diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile
index 23fe2a6d7..2f79f31cb 100644
--- a/src/cmd/gc/Makefile
+++ b/src/cmd/gc/Makefile
@@ -30,6 +30,7 @@ OFILES=\
compat.$O\
bits.$O\
align.$O\
+ gen.$O\
$(LIB): $(OFILES)
ar rsc $(LIB) $(OFILES)
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index 7c39c646c..7c2960277 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -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
index 000000000..410c1a519
--- /dev/null
+++ b/src/cmd/gc/gen.c
@@ -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:
+ ;
+}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 0a6f1ccbb..2654d48cc 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -938,25 +938,11 @@ 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*);
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 3bda54a7a..ab7ced376 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -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;