From bac922c6e15f6c6b7378178087e0772c7aa0745a Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 30 Mar 2009 19:15:07 -0700 Subject: [PATCH] move portable code generation (basic statements) to gc. R=ken OCL=26929 CL=26929 --- src/cmd/6g/align.c | 2 - src/cmd/6g/gen.c | 588 +++----------------------------------------- src/cmd/6g/gg.h | 25 -- src/cmd/6g/gsubr.c | 18 ++ src/cmd/gc/Makefile | 1 + src/cmd/gc/align.c | 32 +++ src/cmd/gc/gen.c | 505 +++++++++++++++++++++++++++++++++++++ src/cmd/gc/go.h | 79 ++++-- src/cmd/gc/lex.c | 5 +- 9 files changed, 656 insertions(+), 599 deletions(-) create mode 100644 src/cmd/gc/gen.c diff --git a/src/cmd/6g/align.c b/src/cmd/6g/align.c index 5f8f8d35c92..209ac324fae 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 bf7c32d55b4..8e047b8d039 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 @@ -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; + uint32 w, c, q; + Node n1; -// // print the label list -// for(l=labellist; l!=L; l=l->link) { -// print("lab %O %S\n", l->op, l->sym); -// } + /* clear a fat object */ + if(debug['g']) + dump("\nclearfat", nl); - 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; - } - } - } + 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--; } - // 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; + 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 8ba4028db89..af1e2c2ccca 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 6ce9ade350b..ab4979a34b0 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 23fe2a6d7ee..2f79f31cbb8 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 7c39c646c00..7c2960277e3 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 00000000000..410c1a51940 --- /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 0a6f1ccbb49..2654d48cc26 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -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*); diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index 3bda54a7a0e..ab7ced37647 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;