1
0
mirror of https://github.com/golang/go synced 2024-11-26 04:27:58 -07:00

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
This commit is contained in:
Russ Cox 2009-06-04 15:24:01 -07:00
parent 52e5d061c7
commit 9a9ffb2b0e
7 changed files with 340 additions and 73 deletions

View File

@ -7,6 +7,35 @@
#include "gg.h" #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: * generate:
* res = n; * res = n;
@ -18,7 +47,7 @@
void void
cgen(Node *n, Node *res) 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; Prog *p1, *p2, *p3;
int a; int a;
@ -59,10 +88,17 @@ cgen(Node *n, Node *res)
// if both are not addressable, use a temporary. // if both are not addressable, use a temporary.
if(!n->addable && !res->addable) { 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(n, &n1);
cgen(&n1, res); cgen(&n1, res);
tempfree(&n1); regfree(&n1);
return; return;
} }
@ -170,10 +206,9 @@ cgen(Node *n, Node *res)
cgen(nl, res); cgen(nl, res);
break; break;
} }
tempalloc(&n1, nl->type); mgen(nl, &n1, res);
cgen(nl, &n1);
gmove(&n1, res); gmove(&n1, res);
tempfree(&n1); mfree(&n1);
break; break;
case ODOT: case ODOT:
@ -214,13 +249,16 @@ cgen(Node *n, Node *res)
} }
if(istype(nl->type, TSTRING) || isslice(nl->type)) { if(istype(nl->type, TSTRING) || isslice(nl->type)) {
// both slice and string have len one pointer into the struct. // both slice and string have len one pointer into the struct.
// a zero pointer means zero length
igen(nl, &n1, res); igen(nl, &n1, res);
n1.op = OREGISTER; // was OINDREG
regalloc(&n2, types[TUINT32], &n1);
n1.op = OINDREG; n1.op = OINDREG;
n1.type = types[TUINT32]; n1.type = types[TUINT32];
n1.xoffset = Array_nel; n1.xoffset = Array_nel;
gmove(&n1, res); gmove(&n1, &n2);
gmove(&n2, res);
regfree(&n1); regfree(&n1);
regfree(&n2);
break; break;
} }
fatal("cgen: OLEN: unknown type %lT", nl->type); fatal("cgen: OLEN: unknown type %lT", nl->type);
@ -279,23 +317,23 @@ sbop: // symmetric binary
abop: // asymmetric binary abop: // asymmetric binary
if(nl->ullman >= nr->ullman) { if(nl->ullman >= nr->ullman) {
tempalloc(&n1, nl->type); regalloc(&n1, nl->type, res);
cgen(nl, &n1); cgen(nl, &n1);
tempalloc(&n2, nr->type); mgen(nr, &n2, N);
cgen(nr, &n2); gins(a, &n2, &n1);
gmove(&n1, res);
mfree(&n2);
regfree(&n1);
} else { } else {
tempalloc(&n1, nl->type); regalloc(&n2, nr->type, res);
tempalloc(&n2, nr->type);
cgen(nr, &n2); cgen(nr, &n2);
regalloc(&n1, nl->type, N);
cgen(nl, &n1); 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; return;
uop: // unary uop: // unary
@ -585,11 +623,8 @@ igen(Node *n, Node *a, Node *res)
{ {
Node n1; Node n1;
tempalloc(&n1, types[tptr]);
agen(n, &n1);
regalloc(a, types[tptr], res); regalloc(a, types[tptr], res);
gins(optoas(OAS, types[tptr]), &n1, a); agen(n, a);
tempfree(&n1);
a->op = OINDREG; a->op = OINDREG;
a->type = n->type; a->type = n->type;
} }

View File

@ -151,6 +151,12 @@ void split64(Node*, Node*, Node*);
void splitclean(void); void splitclean(void);
void nswap(Node*, Node*); void nswap(Node*, Node*);
/*
* gobj.c
*/
void data(void);
void text(void);
/* /*
* list.c * list.c
*/ */

View File

@ -69,11 +69,11 @@ compile(Node *fn)
gclean(); gclean();
checklabels(); checklabels();
// if(curfn->type->outtuple != 0) if(curfn->type->outtuple != 0)
// ginscall(throwreturn, 0); ginscall(throwreturn, 0);
// if(hasdefer) if(hasdefer)
// ginscall(deferreturn, 0); ginscall(deferreturn, 0);
pc->as = ARET; // overwrite AEND pc->as = ARET; // overwrite AEND
pc->lineno = lineno; pc->lineno = lineno;
@ -195,7 +195,7 @@ cgen_callinter(Node *n, Node *res, int proc)
i = i->left; // interface i = i->left; // interface
if(!i->addable) { if(!i->addable) {
tempname(&tmpi, i->type); tempalloc(&tmpi, i->type);
cgen(i, &tmpi); cgen(i, &tmpi);
i = &tmpi; i = &tmpi;
} }
@ -217,7 +217,7 @@ cgen_callinter(Node *n, Node *res, int proc)
nodo.xoffset -= widthptr; nodo.xoffset -= widthptr;
cgen(&nodo, &nodr); // REG = 0(REG) -- i.m 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] cgen(&nodo, &nodr); // REG = 32+offset(REG) -- i.m->fun[f]
// BOTCH nodr.type = fntype; // BOTCH nodr.type = fntype;
@ -227,6 +227,9 @@ cgen_callinter(Node *n, Node *res, int proc)
regfree(&nodr); regfree(&nodr);
regfree(&nodo); regfree(&nodo);
if(i == &tmpi)
tempfree(i);
setmaxarg(n->left->type); setmaxarg(n->left->type);
} }
@ -379,11 +382,12 @@ cgen_asop(Node *n)
nr = n->right; nr = n->right;
if(nr->ullman >= UINF && nl->ullman >= UINF) { if(nr->ullman >= UINF && nl->ullman >= UINF) {
tempname(&n1, nr->type); tempalloc(&n1, nr->type);
cgen(nr, &n1); cgen(nr, &n1);
n2 = *n; n2 = *n;
n2.right = &n1; n2.right = &n1;
cgen_asop(&n2); cgen_asop(&n2);
tempfree(&n1);
goto ret; goto ret;
} }
@ -505,39 +509,27 @@ ret:
* according to op. * according to op.
*/ */
void 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; int a;
Node n3, n4; Node n3, n4;
Type *t;
t = nl->type; regalloc(&n3, t, res);
if(t->width == 1) {
if(issigned[t->etype])
t = types[TINT32];
else
t = types[TUINT32];
}
a = optoas(op, t); a = optoas(op, t);
regalloc(&n3, nr->type, N); if(nl->ullman >= UINF) {
if(nl->ullman >= nr->ullman) { cgen(nl, &n3);
cgen(nl, ax); gmove(&n3, ax);
if(!issigned[t->etype]) {
nodconst(&n4, t, 0);
gmove(&n4, dx);
} else
gins(optoas(OEXTEND, t), N, N);
cgen(nr, &n3); cgen(nr, &n3);
} else { } else {
cgen(nr, &n3); cgen(nr, &n3);
cgen(nl, ax); 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); gins(a, &n3, N);
regfree(&n3); regfree(&n3);
@ -557,6 +549,7 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
{ {
Node ax, dx; Node ax, dx;
int rax, rdx; int rax, rdx;
Type *t;
rax = reg[D_AX]; rax = reg[D_AX];
rdx = reg[D_DX]; rdx = reg[D_DX];
@ -564,12 +557,16 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
if(is64(nl->type)) if(is64(nl->type))
fatal("cgen_div %T", 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(&ax, types[TINT32], D_AX);
nodreg(&dx, types[TINT32], D_DX); nodreg(&dx, types[TINT32], D_DX);
regalloc(&ax, nl->type, &ax); regalloc(&ax, t, &ax);
regalloc(&dx, nl->type, &dx); regalloc(&dx, t, &dx);
dodiv(op, nl, nr, res, &ax, &dx); dodiv(op, t, nl, nr, res, &ax, &dx);
regfree(&ax); regfree(&ax);
regfree(&dx); regfree(&dx);
@ -583,7 +580,63 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
void void
cgen_shift(int op, Node *nl, Node *nr, Node *res) 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 int
gen_as_init(Node *nr, Node *nl) 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; 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;
}

View File

@ -183,7 +183,8 @@ dumpfuncs(void)
for(pl=plist; pl!=nil; pl=pl->link) { for(pl=plist; pl!=nil; pl=pl->link) {
for(p=pl->firstpc; p!=P; p=p->link) { for(p=pl->firstpc; p!=P; p=p->link) {
p->loc = pcloc; p->loc = pcloc;
pcloc++; if(p->as != ADATA && p->as != AGLOBL)
pcloc++;
} }
} }
@ -265,7 +266,7 @@ static Prog *estrdat;
static int gflag; static int gflag;
static Prog *savepc; static Prog *savepc;
static void void
data(void) data(void)
{ {
gflag = debug['g']; gflag = debug['g'];
@ -282,7 +283,7 @@ data(void)
pc = estrdat; pc = estrdat;
} }
static void void
text(void) text(void)
{ {
if(!savepc) if(!savepc)
@ -589,7 +590,7 @@ out:
p = pc; p = pc;
gins(AMOVL, N, N); gins(AMOVL, N, N);
p->from.type = D_INDIR+D_SP; p->from.type = D_INDIR+D_SP;
p->from.offset = 4; p->from.offset = widthptr;
p->to.type = D_AX; p->to.type = D_AX;
//print("2. %P\n", p); //print("2. %P\n", p);
@ -623,7 +624,7 @@ out:
gins(AMOVL, N, N); gins(AMOVL, N, N);
p->from.type = D_AX; p->from.type = D_AX;
p->to.type = D_INDIR+D_SP; p->to.type = D_INDIR+D_SP;
p->to.offset = 8; p->to.offset = widthptr;
//print("5. %P\n", p); //print("5. %P\n", p);
f = dotlist[0].field; f = dotlist[0].field;

View File

@ -576,10 +576,6 @@ optoas(int op, Type *t)
a = ADIVL; a = ADIVL;
break; break;
case CASE(OEXTEND, TINT8):
a = ACBW;
break;
case CASE(OEXTEND, TINT16): case CASE(OEXTEND, TINT16):
a = ACWD; a = ACWD;
break; break;
@ -716,10 +712,10 @@ gclean(void)
for(i=D_AL; i<=D_DI; i++) for(i=D_AL; i<=D_DI; i++)
if(reg[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++) for(i=D_F0; i<=D_F7; i++)
if(reg[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: try:
if(o != N && o->op == OREGISTER) { if(o != N && o->op == OREGISTER) {
i = o->val.u.reg; i = o->val.u.reg;
if(i >= D_AX && i <= max) if(i >= min && i <= max)
goto out; goto out;
} }
for(i=min; i<=max; i++) for(i=min; i<=max; i++)

View File

@ -461,7 +461,7 @@ dumpsignatures(void)
} }
// if ifacet is too wide, the methods will see a pointer. // if ifacet is too wide, the methods will see a pointer.
if(ifacet->width > 8) { if(ifacet->width > widthptr) {
ifacet = ptrto(progt); ifacet = ptrto(progt);
rcvrt = ptrto(progt); rcvrt = ptrto(progt);
} }

View File

@ -2500,7 +2500,7 @@ saferef(Node *n)
case OIND: case OIND:
l = nod(OXXX, N, N); l = nod(OXXX, N, N);
tempname(l, ptrto(n->type)); 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); r = nod(OIND, l, N);
walktype(r, Elv); walktype(r, Elv);
return r; return r;
@ -2930,7 +2930,7 @@ genwrapper(Type *rcvrtype, Type *method, Sym *newnam)
fn->nbody = nod(ORETURN, call, N); fn->nbody = nod(ORETURN, call, N);
if(debug['r']) if(debug['r'])
dump("genptrtramp body", fn->nbody); dump("genwrapper body", fn->nbody);
funcbody(fn); funcbody(fn);
} }
@ -3117,6 +3117,9 @@ simsimtype(Type *t)
{ {
int et; int et;
if(t == 0)
return 0;
et = simtype[t->etype]; et = simtype[t->etype];
switch(et) { switch(et) {
case TPTR32: case TPTR32: