From 9a9ffb2b0e03c3a53661b1aa56fc70b0cb910708 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 4 Jun 2009 15:24:01 -0700 Subject: [PATCH] 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 --- src/cmd/8g/cgen.c | 83 +++++++++---- src/cmd/8g/gg.h | 6 + src/cmd/8g/ggen.c | 294 +++++++++++++++++++++++++++++++++++++++------ src/cmd/8g/gobj.c | 11 +- src/cmd/8g/gsubr.c | 10 +- src/cmd/gc/obj.c | 2 +- src/cmd/gc/subr.c | 7 +- 7 files changed, 340 insertions(+), 73 deletions(-) diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c index b524f99328e..71a471b6daa 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 03f7aac6f69..ae70490c182 100644 --- a/src/cmd/8g/gg.h +++ b/src/cmd/8g/gg.h @@ -151,6 +151,12 @@ void split64(Node*, Node*, Node*); void splitclean(void); void nswap(Node*, Node*); +/* + * gobj.c + */ +void data(void); +void text(void); + /* * list.c */ diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c index 249c9fe8c77..5ac810b2bfe 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 -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; } + +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 37d7321f11f..c5f67cc4ab3 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 4f30c606b98..314c8aba273 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 525669e9f98..e54010672a2 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 96d6b4deb3c..a29f28cd084 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: