mirror of
https://github.com/golang/go
synced 2024-11-26 17:56:55 -07:00
move portable code generation (basic statements) to gc.
R=ken OCL=26929 CL=26929
This commit is contained in:
parent
79b55e226a
commit
bac922c6e1
@ -30,7 +30,5 @@ betypeinit(void)
|
|||||||
zprog.from.scale = 0;
|
zprog.from.scale = 0;
|
||||||
zprog.to = zprog.from;
|
zprog.to = zprog.from;
|
||||||
|
|
||||||
symstringo = lookup(".stringo"); // strings
|
|
||||||
|
|
||||||
listinit();
|
listinit();
|
||||||
}
|
}
|
||||||
|
588
src/cmd/6g/gen.c
588
src/cmd/6g/gen.c
@ -8,17 +8,6 @@
|
|||||||
#include "gg.h"
|
#include "gg.h"
|
||||||
#include "opt.h"
|
#include "opt.h"
|
||||||
|
|
||||||
static Node*
|
|
||||||
sysfunc(char *name)
|
|
||||||
{
|
|
||||||
Node *n;
|
|
||||||
|
|
||||||
n = newname(pkglookup(name, "sys"));
|
|
||||||
n->class = PFUNC;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
compile(Node *fn)
|
compile(Node *fn)
|
||||||
{
|
{
|
||||||
@ -29,16 +18,13 @@ compile(Node *fn)
|
|||||||
Type *t;
|
Type *t;
|
||||||
Iter save;
|
Iter save;
|
||||||
|
|
||||||
if(newproc == N)
|
if(newproc == N) {
|
||||||
newproc = sysfunc("newproc");
|
newproc = sysfunc("newproc");
|
||||||
if(deferproc == N)
|
|
||||||
deferproc = sysfunc("deferproc");
|
deferproc = sysfunc("deferproc");
|
||||||
if(deferreturn == N)
|
|
||||||
deferreturn = sysfunc("deferreturn");
|
deferreturn = sysfunc("deferreturn");
|
||||||
if(throwindex == N)
|
|
||||||
throwindex = sysfunc("throwindex");
|
throwindex = sysfunc("throwindex");
|
||||||
if(throwreturn == N)
|
|
||||||
throwreturn = sysfunc("throwreturn");
|
throwreturn = sysfunc("throwreturn");
|
||||||
|
}
|
||||||
|
|
||||||
if(fn->nbody == N)
|
if(fn->nbody == N)
|
||||||
return;
|
return;
|
||||||
@ -110,297 +96,6 @@ ret:
|
|||||||
lineno = lno;
|
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:
|
* generate:
|
||||||
* call f
|
* call f
|
||||||
@ -494,33 +189,6 @@ cgen_callinter(Node *n, Node *res, int proc)
|
|||||||
setmaxarg(n->left->type);
|
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;
|
* generate function call;
|
||||||
* proc=0 normal 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.
|
* call to n has already been generated.
|
||||||
* generate:
|
* 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
|
int
|
||||||
samereg(Node *a, Node *b)
|
samereg(Node *a, Node *b)
|
||||||
{
|
{
|
||||||
@ -1156,61 +653,40 @@ cgen_bmul(int op, Node *nl, Node *nr, Node *res)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
checklabels(void)
|
clearfat(Node *nl)
|
||||||
{
|
{
|
||||||
Label *l, *m;
|
uint32 w, c, q;
|
||||||
Sym *s;
|
Node n1;
|
||||||
|
|
||||||
// // print the label list
|
/* clear a fat object */
|
||||||
// for(l=labellist; l!=L; l=l->link) {
|
if(debug['g'])
|
||||||
// print("lab %O %S\n", l->op, l->sym);
|
dump("\nclearfat", nl);
|
||||||
// }
|
|
||||||
|
|
||||||
for(l=labellist; l!=L; l=l->link) {
|
w = nl->type->width;
|
||||||
switch(l->op) {
|
c = w % 8; // bytes
|
||||||
case OFOR:
|
q = w / 8; // quads
|
||||||
case OLABEL:
|
|
||||||
// these are definitions -
|
gconreg(AMOVQ, 0, D_AX);
|
||||||
s = l->sym;
|
nodreg(&n1, types[tptr], D_DI);
|
||||||
for(m=labellist; m!=L; m=m->link) {
|
agen(nl, &n1);
|
||||||
if(m->sym != s)
|
|
||||||
continue;
|
if(q >= 4) {
|
||||||
switch(m->op) {
|
gconreg(AMOVQ, q, D_CX);
|
||||||
case OFOR:
|
gins(AREP, N, N); // repeat
|
||||||
case OLABEL:
|
gins(ASTOSQ, N, N); // STOQ AL,*(DI)+
|
||||||
// these are definitions -
|
} else
|
||||||
// look for redefinitions
|
while(q > 0) {
|
||||||
if(l != m)
|
gins(ASTOSQ, N, N); // STOQ AL,*(DI)+
|
||||||
yyerror("label %S redefined", s);
|
q--;
|
||||||
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
|
if(c >= 4) {
|
||||||
for(l=labellist; l!=L; l=l->link)
|
gconreg(AMOVQ, c, D_CX);
|
||||||
if(l->op == OGOTO && l->sym != S)
|
gins(AREP, N, N); // repeat
|
||||||
yyerror("label %S not defined", l->sym);
|
gins(ASTOSB, N, N); // STOB AL,*(DI)+
|
||||||
|
} else
|
||||||
|
while(c > 0) {
|
||||||
|
gins(ASTOSB, N, N); // STOB AL,*(DI)+
|
||||||
|
c--;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#define EXTERN extern
|
#define EXTERN extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct Prog Prog;
|
|
||||||
typedef struct Addr Addr;
|
typedef struct Addr Addr;
|
||||||
|
|
||||||
struct Addr
|
struct Addr
|
||||||
@ -41,7 +40,6 @@ struct Prog
|
|||||||
Prog* link; // next instruction in this func
|
Prog* link; // next instruction in this func
|
||||||
void* reg; // pointer to containing Reg struct
|
void* reg; // pointer to containing Reg struct
|
||||||
};
|
};
|
||||||
#define P ((Prog*)0)
|
|
||||||
|
|
||||||
typedef struct Plist Plist;
|
typedef struct Plist Plist;
|
||||||
struct Plist
|
struct Plist
|
||||||
@ -53,22 +51,6 @@ struct Plist
|
|||||||
Plist* link;
|
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* plist;
|
||||||
EXTERN Plist* plast;
|
EXTERN Plist* plast;
|
||||||
EXTERN Biobuf* bout;
|
EXTERN Biobuf* bout;
|
||||||
@ -79,8 +61,6 @@ EXTERN String emptystring;
|
|||||||
extern char* anames[];
|
extern char* anames[];
|
||||||
EXTERN Hist* hist;
|
EXTERN Hist* hist;
|
||||||
EXTERN Prog zprog;
|
EXTERN Prog zprog;
|
||||||
EXTERN Label* labellist;
|
|
||||||
EXTERN Label* findlab(Sym*);
|
|
||||||
EXTERN Node* curfn;
|
EXTERN Node* curfn;
|
||||||
EXTERN Node* newproc;
|
EXTERN Node* newproc;
|
||||||
EXTERN Node* deferproc;
|
EXTERN Node* deferproc;
|
||||||
@ -96,9 +76,6 @@ void proglist(void);
|
|||||||
void gen(Node*);
|
void gen(Node*);
|
||||||
Node* lookdot(Node*, Node*, int);
|
Node* lookdot(Node*, Node*, int);
|
||||||
void cgen_as(Node*, Node*);
|
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_callmeth(Node*, int);
|
||||||
void cgen_callinter(Node*, Node*, int);
|
void cgen_callinter(Node*, Node*, int);
|
||||||
void cgen_proc(Node*, int);
|
void cgen_proc(Node*, int);
|
||||||
@ -116,7 +93,6 @@ void ginscall(Node*, int);
|
|||||||
/*
|
/*
|
||||||
* cgen
|
* cgen
|
||||||
*/
|
*/
|
||||||
void cgen(Node*, Node*);
|
|
||||||
void agen(Node*, Node*);
|
void agen(Node*, Node*);
|
||||||
void igen(Node*, Node*, Node*);
|
void igen(Node*, Node*, Node*);
|
||||||
vlong fieldoffset(Type*, Node*);
|
vlong fieldoffset(Type*, Node*);
|
||||||
@ -134,7 +110,6 @@ void cgen_aret(Node*, Node*);
|
|||||||
void clearp(Prog*);
|
void clearp(Prog*);
|
||||||
void proglist(void);
|
void proglist(void);
|
||||||
Prog* gbranch(int, Type*);
|
Prog* gbranch(int, Type*);
|
||||||
void patch(Prog*, Prog*);
|
|
||||||
Prog* prog(int);
|
Prog* prog(int);
|
||||||
void gaddoffset(Node*);
|
void gaddoffset(Node*);
|
||||||
void gconv(int, int);
|
void gconv(int, int);
|
||||||
|
@ -1927,3 +1927,21 @@ no:
|
|||||||
sudoclean();
|
sudoclean();
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ OFILES=\
|
|||||||
compat.$O\
|
compat.$O\
|
||||||
bits.$O\
|
bits.$O\
|
||||||
align.$O\
|
align.$O\
|
||||||
|
gen.$O\
|
||||||
|
|
||||||
$(LIB): $(OFILES)
|
$(LIB): $(OFILES)
|
||||||
ar rsc $(LIB) $(OFILES)
|
ar rsc $(LIB) $(OFILES)
|
||||||
|
@ -349,3 +349,35 @@ typeinit(int lex)
|
|||||||
Array_cap = rnd(Array_nel+types[TUINT32]->width, types[TUINT32]->width);
|
Array_cap = rnd(Array_nel+types[TUINT32]->width, types[TUINT32]->width);
|
||||||
sizeof_Array = rnd(Array_cap+types[TUINT32]->width, maxround);
|
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;
|
||||||
|
}
|
||||||
|
505
src/cmd/gc/gen.c
Normal file
505
src/cmd/gc/gen.c
Normal file
@ -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:
|
||||||
|
;
|
||||||
|
}
|
@ -937,26 +937,12 @@ int smallintconst(Node*);
|
|||||||
int consttype(Node*);
|
int consttype(Node*);
|
||||||
int isconst(Node*, int);
|
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
|
* align.c
|
||||||
*/
|
*/
|
||||||
uint32 rnd(uint32, uint32);
|
uint32 rnd(uint32, uint32);
|
||||||
void dowidth(Type*);
|
void dowidth(Type*);
|
||||||
|
int argsize(Type*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bits.c
|
* bits.c
|
||||||
@ -972,3 +958,66 @@ int bset(Bits, uint);
|
|||||||
int Qconv(Fmt *fp);
|
int Qconv(Fmt *fp);
|
||||||
int bitno(int32);
|
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*);
|
||||||
|
@ -66,6 +66,8 @@ main(int argc, char *argv[])
|
|||||||
lexinit();
|
lexinit();
|
||||||
typeinit(LBASETYPE);
|
typeinit(LBASETYPE);
|
||||||
|
|
||||||
|
symstringo = lookup(".stringo"); // strings
|
||||||
|
|
||||||
lineno = 1;
|
lineno = 1;
|
||||||
block = 1;
|
block = 1;
|
||||||
blockgen = 1;
|
blockgen = 1;
|
||||||
@ -336,7 +338,8 @@ cannedimports(char *file, char *cp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
isfrog(int c) {
|
isfrog(int c)
|
||||||
|
{
|
||||||
// complain about possibly invisible control characters
|
// complain about possibly invisible control characters
|
||||||
if(c < 0)
|
if(c < 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user