summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-06-04 15:24:01 -0700
committerRuss Cox <rsc@golang.org>2009-06-04 15:24:01 -0700
commit7a35afcd78a2973c28485a3f862b4508bd996fc3 (patch)
tree15e2df8a4cec3383a0c64f41cfaed301dfef86e7 /src/cmd
parent09ba929d1babbf4fe8f375d2c825b22726eb94de (diff)
downloadgo-7a35afcd78a2973c28485a3f862b4508bd996fc3.tar.gz
more 8g progress.
likely to go back to registers for most temporaries. most tests in lib pass. these fail: datafmt fmt go/scanner log reflect strconv template R=ken OCL=29896 CL=29898
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/8g/cgen.c83
-rw-r--r--src/cmd/8g/gg.h6
-rw-r--r--src/cmd/8g/ggen.c292
-rw-r--r--src/cmd/8g/gobj.c11
-rwxr-xr-xsrc/cmd/8g/gsubr.c10
-rw-r--r--src/cmd/gc/obj.c2
-rw-r--r--src/cmd/gc/subr.c7
7 files changed, 339 insertions, 72 deletions
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index b524f9932..71a471b6d 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -7,6 +7,35 @@
#include "gg.h"
+void
+mgen(Node *n, Node *n1, Node *rg)
+{
+ n1->ostk = 0;
+ n1->op = OEMPTY;
+
+ if(n->addable) {
+ *n1 = *n;
+ n1->ostk = 0;
+ if(n1->op == OREGISTER || n1->op == OINDREG)
+ reg[n->val.u.reg]++;
+ return;
+ }
+ if(n->type->width > widthptr)
+ tempalloc(n1, n->type);
+ else
+ regalloc(n1, n->type, rg);
+ cgen(n, n1);
+}
+
+void
+mfree(Node *n)
+{
+ if(n->ostk)
+ tempfree(n);
+ else if(n->op == OREGISTER)
+ regfree(n);
+}
+
/*
* generate:
* res = n;
@@ -18,7 +47,7 @@
void
cgen(Node *n, Node *res)
{
- Node *nl, *nr, *r, n1, n2, rr, f0, f1;
+ Node *nl, *nr, *r, n1, n2, f0, f1;
Prog *p1, *p2, *p3;
int a;
@@ -59,10 +88,17 @@ cgen(Node *n, Node *res)
// if both are not addressable, use a temporary.
if(!n->addable && !res->addable) {
- tempalloc(&n1, n->type);
+ if(is64(n->type)) {
+ tempalloc(&n1, n->type);
+ cgen(n, &n1);
+ cgen(&n1, res);
+ tempfree(&n1);
+ return;
+ }
+ regalloc(&n1, n->type, N);
cgen(n, &n1);
cgen(&n1, res);
- tempfree(&n1);
+ regfree(&n1);
return;
}
@@ -170,10 +206,9 @@ cgen(Node *n, Node *res)
cgen(nl, res);
break;
}
- tempalloc(&n1, nl->type);
- cgen(nl, &n1);
+ mgen(nl, &n1, res);
gmove(&n1, res);
- tempfree(&n1);
+ mfree(&n1);
break;
case ODOT:
@@ -214,13 +249,16 @@ cgen(Node *n, Node *res)
}
if(istype(nl->type, TSTRING) || isslice(nl->type)) {
// both slice and string have len one pointer into the struct.
- // a zero pointer means zero length
igen(nl, &n1, res);
+ n1.op = OREGISTER; // was OINDREG
+ regalloc(&n2, types[TUINT32], &n1);
n1.op = OINDREG;
n1.type = types[TUINT32];
n1.xoffset = Array_nel;
- gmove(&n1, res);
+ gmove(&n1, &n2);
+ gmove(&n2, res);
regfree(&n1);
+ regfree(&n2);
break;
}
fatal("cgen: OLEN: unknown type %lT", nl->type);
@@ -279,23 +317,23 @@ sbop: // symmetric binary
abop: // asymmetric binary
if(nl->ullman >= nr->ullman) {
- tempalloc(&n1, nl->type);
+ regalloc(&n1, nl->type, res);
cgen(nl, &n1);
- tempalloc(&n2, nr->type);
- cgen(nr, &n2);
+ mgen(nr, &n2, N);
+ gins(a, &n2, &n1);
+ gmove(&n1, res);
+ mfree(&n2);
+ regfree(&n1);
} else {
- tempalloc(&n1, nl->type);
- tempalloc(&n2, nr->type);
+ regalloc(&n2, nr->type, res);
cgen(nr, &n2);
+ regalloc(&n1, nl->type, N);
cgen(nl, &n1);
+ gins(a, &n2, &n1);
+ regfree(&n2);
+ gmove(&n1, res);
+ regfree(&n1);
}
- regalloc(&rr, res->type, N);
- gmove(&n1, &rr);
- gins(a, &n2, &rr);
- gmove(&rr, res);
- regfree(&rr);
- tempfree(&n2);
- tempfree(&n1);
return;
uop: // unary
@@ -585,11 +623,8 @@ igen(Node *n, Node *a, Node *res)
{
Node n1;
- tempalloc(&n1, types[tptr]);
- agen(n, &n1);
regalloc(a, types[tptr], res);
- gins(optoas(OAS, types[tptr]), &n1, a);
- tempfree(&n1);
+ agen(n, a);
a->op = OINDREG;
a->type = n->type;
}
diff --git a/src/cmd/8g/gg.h b/src/cmd/8g/gg.h
index 03f7aac6f..ae70490c1 100644
--- a/src/cmd/8g/gg.h
+++ b/src/cmd/8g/gg.h
@@ -152,6 +152,12 @@ void splitclean(void);
void nswap(Node*, Node*);
/*
+ * gobj.c
+ */
+void data(void);
+void text(void);
+
+/*
* list.c
*/
int Aconv(Fmt*);
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 249c9fe8c..5ac810b2b 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -69,11 +69,11 @@ compile(Node *fn)
gclean();
checklabels();
-// if(curfn->type->outtuple != 0)
-// ginscall(throwreturn, 0);
+ if(curfn->type->outtuple != 0)
+ ginscall(throwreturn, 0);
-// if(hasdefer)
-// ginscall(deferreturn, 0);
+ if(hasdefer)
+ ginscall(deferreturn, 0);
pc->as = ARET; // overwrite AEND
pc->lineno = lineno;
@@ -195,7 +195,7 @@ cgen_callinter(Node *n, Node *res, int proc)
i = i->left; // interface
if(!i->addable) {
- tempname(&tmpi, i->type);
+ tempalloc(&tmpi, i->type);
cgen(i, &tmpi);
i = &tmpi;
}
@@ -217,7 +217,7 @@ cgen_callinter(Node *n, Node *res, int proc)
nodo.xoffset -= widthptr;
cgen(&nodo, &nodr); // REG = 0(REG) -- i.m
- nodo.xoffset = n->left->xoffset + 4*widthptr;
+ nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
cgen(&nodo, &nodr); // REG = 32+offset(REG) -- i.m->fun[f]
// BOTCH nodr.type = fntype;
@@ -227,6 +227,9 @@ cgen_callinter(Node *n, Node *res, int proc)
regfree(&nodr);
regfree(&nodo);
+ if(i == &tmpi)
+ tempfree(i);
+
setmaxarg(n->left->type);
}
@@ -379,11 +382,12 @@ cgen_asop(Node *n)
nr = n->right;
if(nr->ullman >= UINF && nl->ullman >= UINF) {
- tempname(&n1, nr->type);
+ tempalloc(&n1, nr->type);
cgen(nr, &n1);
n2 = *n;
n2.right = &n1;
cgen_asop(&n2);
+ tempfree(&n1);
goto ret;
}
@@ -505,39 +509,27 @@ ret:
* according to op.
*/
void
-dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
+dodiv(int op, Type *t, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
{
int a;
Node n3, n4;
- Type *t;
- t = nl->type;
- if(t->width == 1) {
- if(issigned[t->etype])
- t = types[TINT32];
- else
- t = types[TUINT32];
- }
+ regalloc(&n3, t, res);
a = optoas(op, t);
- regalloc(&n3, nr->type, N);
- if(nl->ullman >= nr->ullman) {
- cgen(nl, ax);
- if(!issigned[t->etype]) {
- nodconst(&n4, t, 0);
- gmove(&n4, dx);
- } else
- gins(optoas(OEXTEND, t), N, N);
+ if(nl->ullman >= UINF) {
+ cgen(nl, &n3);
+ gmove(&n3, ax);
cgen(nr, &n3);
} else {
cgen(nr, &n3);
cgen(nl, ax);
- if(!issigned[t->etype]) {
- nodconst(&n4, t, 0);
- gmove(&n4, dx);
- } else
- gins(optoas(OEXTEND, t), N, N);
}
+ if(!issigned[t->etype]) {
+ nodconst(&n4, t, 0);
+ gmove(&n4, dx);
+ } else
+ gins(optoas(OEXTEND, t), N, N);
gins(a, &n3, N);
regfree(&n3);
@@ -557,6 +549,7 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
{
Node ax, dx;
int rax, rdx;
+ Type *t;
rax = reg[D_AX];
rdx = reg[D_DX];
@@ -564,12 +557,16 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
if(is64(nl->type))
fatal("cgen_div %T", nl->type);
+ t = nl->type;
+ if(t->width == 1)
+ t = types[t->etype+2]; // int8 -> int16, uint8 -> uint16
+
nodreg(&ax, types[TINT32], D_AX);
nodreg(&dx, types[TINT32], D_DX);
- regalloc(&ax, nl->type, &ax);
- regalloc(&dx, nl->type, &dx);
+ regalloc(&ax, t, &ax);
+ regalloc(&dx, t, &dx);
- dodiv(op, nl, nr, res, &ax, &dx);
+ dodiv(op, t, nl, nr, res, &ax, &dx);
regfree(&ax);
regfree(&dx);
@@ -583,7 +580,63 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
void
cgen_shift(int op, Node *nl, Node *nr, Node *res)
{
- fatal("cgen_shift");
+ Node n1, n2;
+ int a, w;
+ Prog *p1;
+ uvlong sc;
+
+ if(nl->type->width > 4)
+ fatal("cgen_shift %T", nl->type->width);
+
+ if(nl->type->width == 1 && nl->type->etype != TUINT8)
+ fatal("cgen_shift %T", nl->type);
+
+ w = nl->type->width * 8;
+
+ a = optoas(op, nl->type);
+
+ if(nr->op == OLITERAL) {
+ regalloc(&n1, nl->type, res);
+ cgen(nl, &n1);
+ sc = mpgetfix(nr->val.u.xval);
+ if(sc >= nl->type->width*8) {
+ // large shift gets 2 shifts by width
+ gins(a, ncon(w-1), &n1);
+ gins(a, ncon(w-1), &n1);
+ } else
+ gins(a, nr, &n1);
+ gmove(&n1, res);
+ regfree(&n1);
+ return;
+ }
+
+ nodreg(&n1, types[TUINT32], D_CX);
+ regalloc(&n1, nr->type, &n1); // to hold the shift type in CX
+
+ regalloc(&n2, nl->type, res);
+ if(nl->ullman >= nr->ullman) {
+ cgen(nl, &n2);
+ cgen(nr, &n1);
+ } else {
+ cgen(nr, &n1);
+ cgen(nl, &n2);
+ }
+
+ // test and fix up large shifts
+ gins(optoas(OCMP, types[TUINT32]), &n1, ncon(w));
+ p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+ if(op == ORSH && issigned[nl->type->etype]) {
+ gins(a, ncon(w-1), &n2);
+ } else {
+ gmove(ncon(0), &n2);
+ }
+ patch(p1, pc);
+ gins(a, &n1, &n2);
+
+ gmove(&n2, res);
+
+ regfree(&n1);
+ regfree(&n2);
}
/*
@@ -599,7 +652,180 @@ cgen_bmul(int op, Node *nl, Node *nr, Node *res)
}
int
+getlit(Node *lit)
+{
+ if(smallintconst(lit))
+ return mpgetfix(lit->val.u.xval);
+ return -1;
+}
+
+int
+stataddr(Node *nam, Node *n)
+{
+ int l;
+
+ if(n == N)
+ goto no;
+
+ switch(n->op) {
+ case ONAME:
+ *nam = *n;
+ return n->addable;
+
+ case ODOT:
+ if(!stataddr(nam, n->left))
+ break;
+ nam->xoffset += n->xoffset;
+ nam->type = n->type;
+ return 1;
+
+ case OINDEX:
+ if(n->left->type->bound < 0)
+ break;
+ if(!stataddr(nam, n->left))
+ break;
+ l = getlit(n->right);
+ if(l < 0)
+ break;
+ nam->xoffset += l*n->type->width;
+ nam->type = n->type;
+ return 1;
+ }
+
+no:
+ return 0;
+}
+
+int
gen_as_init(Node *nr, Node *nl)
{
+ Node nam, nod1, nhi, nlo;
+ Prog *p;
+ Addr a;
+
+ if(!initflag)
+ goto no;
+
+ if(nr == N) {
+ if(!stataddr(&nam, nl))
+ goto no;
+ if(nam.class != PEXTERN)
+ goto no;
+ return 1;
+ }
+
+ if(nr->op == OCOMPSLICE) {
+ // create a slice pointing to an array
+ if(!stataddr(&nam, nl)) {
+ dump("stataddr", nl);
+ goto no;
+ }
+
+ data();
+ p = gins(ADATA, &nam, nr->left);
+ p->from.scale = types[tptr]->width;
+ p->to.index = p->to.type;
+ p->to.type = D_ADDR;
+//print("%P\n", p);
+
+ nodconst(&nod1, types[TINT32], nr->left->type->bound);
+ p = gins(ADATA, &nam, &nod1);
+ p->from.scale = types[TINT32]->width;
+ p->from.offset += types[tptr]->width;
+//print("%P\n", p);
+
+ p = gins(ADATA, &nam, &nod1);
+ p->from.scale = types[TINT32]->width;
+ p->from.offset += types[tptr]->width+types[TINT32]->width;
+ text();
+
+ goto yes;
+ }
+
+ if(nr->op == OCOMPMAP) {
+ goto yes;
+ }
+
+ if(nr->type == T ||
+ !eqtype(nl->type, nr->type))
+ goto no;
+
+ if(!stataddr(&nam, nl))
+ goto no;
+ if(nam.class != PEXTERN)
+ goto no;
+
+ switch(nr->op) {
+ default:
+ goto no;
+
+ case OLITERAL:
+ goto lit;
+ }
+
+no:
return 0;
+
+lit:
+ switch(nr->type->etype) {
+ default:
+ goto no;
+
+ case TBOOL:
+ if(memcmp(nam.sym->name, "initdoneĀ·", 9) == 0)
+ goto no;
+ case TINT8:
+ case TUINT8:
+ case TINT16:
+ case TUINT16:
+ case TINT32:
+ case TUINT32:
+ case TINT:
+ case TUINT:
+ case TFLOAT32:
+ case TFLOAT64:
+ case TFLOAT:
+ data();
+ p = gins(ADATA, &nam, nr);
+ p->from.scale = nr->type->width;
+ text();
+ break;
+
+ case TINT64:
+ case TUINT64:
+ data();
+ split64(nr, &nlo, &nhi);
+ p = gins(ADATA, &nam, &nlo);
+ p->from.scale = 4;
+ p = gins(ADATA, &nam, &nhi);
+ p->from.scale = 4;
+ p->from.offset += 4;
+ splitclean();
+ text();
+ break;
+
+ case TSTRING:
+ datastring(nr->val.u.sval->s, nr->val.u.sval->len, &a);
+ data();
+ p = gins(ADATA, &nam, N);
+ p->from.scale = types[tptr]->width;
+ p->to = a;
+ p->to.index = p->to.type;
+ p->to.type = D_ADDR;
+//print("%P\n", p);
+
+ nodconst(&nod1, types[TINT32], nr->val.u.sval->len);
+ p = gins(ADATA, &nam, &nod1);
+ p->from.scale = types[TINT32]->width;
+ p->from.offset += types[tptr]->width;
+//print("%P\n", p);
+ text();
+ break;
+ }
+
+yes:
+//dump("\ngen_as_init", nl);
+//dump("", nr);
+//print("%P\n", p);
+ return 1;
}
diff --git a/src/cmd/8g/gobj.c b/src/cmd/8g/gobj.c
index 37d7321f1..c5f67cc4a 100644
--- a/src/cmd/8g/gobj.c
+++ b/src/cmd/8g/gobj.c
@@ -183,7 +183,8 @@ dumpfuncs(void)
for(pl=plist; pl!=nil; pl=pl->link) {
for(p=pl->firstpc; p!=P; p=p->link) {
p->loc = pcloc;
- pcloc++;
+ if(p->as != ADATA && p->as != AGLOBL)
+ pcloc++;
}
}
@@ -265,7 +266,7 @@ static Prog *estrdat;
static int gflag;
static Prog *savepc;
-static void
+void
data(void)
{
gflag = debug['g'];
@@ -282,7 +283,7 @@ data(void)
pc = estrdat;
}
-static void
+void
text(void)
{
if(!savepc)
@@ -589,7 +590,7 @@ out:
p = pc;
gins(AMOVL, N, N);
p->from.type = D_INDIR+D_SP;
- p->from.offset = 4;
+ p->from.offset = widthptr;
p->to.type = D_AX;
//print("2. %P\n", p);
@@ -623,7 +624,7 @@ out:
gins(AMOVL, N, N);
p->from.type = D_AX;
p->to.type = D_INDIR+D_SP;
- p->to.offset = 8;
+ p->to.offset = widthptr;
//print("5. %P\n", p);
f = dotlist[0].field;
diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c
index 4f30c606b..314c8aba2 100755
--- a/src/cmd/8g/gsubr.c
+++ b/src/cmd/8g/gsubr.c
@@ -576,10 +576,6 @@ optoas(int op, Type *t)
a = ADIVL;
break;
- case CASE(OEXTEND, TINT8):
- a = ACBW;
- break;
-
case CASE(OEXTEND, TINT16):
a = ACWD;
break;
@@ -716,10 +712,10 @@ gclean(void)
for(i=D_AL; i<=D_DI; i++)
if(reg[i])
- yyerror("reg %R left allocated at %lux\n", i, regpc[i]);
+ yyerror("reg %R left allocated at %lux", i, regpc[i]);
for(i=D_F0; i<=D_F7; i++)
if(reg[i])
- yyerror("reg %R left allocated\n", i);
+ yyerror("reg %R left allocated", i);
}
/*
@@ -760,7 +756,7 @@ regalloc(Node *n, Type *t, Node *o)
try:
if(o != N && o->op == OREGISTER) {
i = o->val.u.reg;
- if(i >= D_AX && i <= max)
+ if(i >= min && i <= max)
goto out;
}
for(i=min; i<=max; i++)
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index 525669e9f..e54010672 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -461,7 +461,7 @@ dumpsignatures(void)
}
// if ifacet is too wide, the methods will see a pointer.
- if(ifacet->width > 8) {
+ if(ifacet->width > widthptr) {
ifacet = ptrto(progt);
rcvrt = ptrto(progt);
}
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 96d6b4deb..a29f28cd0 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -2500,7 +2500,7 @@ saferef(Node *n)
case OIND:
l = nod(OXXX, N, N);
tempname(l, ptrto(n->type));
- addtotop(nod(OAS, l, nod(OADDR, n, N)));
+ addtop = list(addtop, nod(OAS, l, nod(OADDR, n, N)));
r = nod(OIND, l, N);
walktype(r, Elv);
return r;
@@ -2930,7 +2930,7 @@ genwrapper(Type *rcvrtype, Type *method, Sym *newnam)
fn->nbody = nod(ORETURN, call, N);
if(debug['r'])
- dump("genptrtramp body", fn->nbody);
+ dump("genwrapper body", fn->nbody);
funcbody(fn);
}
@@ -3117,6 +3117,9 @@ simsimtype(Type *t)
{
int et;
+ if(t == 0)
+ return 0;
+
et = simtype[t->etype];
switch(et) {
case TPTR32: