]> Cypherpunks repositories - gostls13.git/commitdiff
more 8g progress.
authorRuss Cox <rsc@golang.org>
Thu, 4 Jun 2009 22:24:01 +0000 (15:24 -0700)
committerRuss Cox <rsc@golang.org>
Thu, 4 Jun 2009 22:24:01 +0000 (15:24 -0700)
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
src/cmd/8g/gg.h
src/cmd/8g/ggen.c
src/cmd/8g/gobj.c
src/cmd/8g/gsubr.c
src/cmd/gc/obj.c
src/cmd/gc/subr.c

index b524f99328e747893963afce124968f3ffdf6663..71a471b6daa7f23036086b9f708e86f265746274 100644 (file)
@@ -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;
 }
index 03f7aac6f691f63c79873acb10cdf05a671e3fce..ae70490c182324323aa90796d2016b9b97d33dbf 100644 (file)
@@ -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
  */
index 249c9fe8c773c1e5b201b14896cd52e202b8f040..5ac810b2bfe987a63a7aaa8ed1049fd9a80a2d09 100644 (file)
@@ -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);
 }
 
 /*
@@ -598,8 +651,181 @@ cgen_bmul(int op, Node *nl, Node *nr, Node *res)
        fatal("cgen_bmul");
 }
 
+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;
 }
index 37d7321f11ff720241b3b87e3812abf3296233f8..c5f67cc4ab367ae9898367b120b996d1ecdfd662 100644 (file)
@@ -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;
index 4f30c606b9896da7cb64898b403581ce0efd2d91..314c8aba27366eb155820cf1f1dd5ff76ae29acd 100755 (executable)
@@ -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++)
index 525669e9f9899224d6cd87c74054fda58efd4e13..e54010672a2b40c37162ed752b22b42dfa6464f4 100644 (file)
@@ -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);
                }
index 96d6b4deb3c2074199ff7efbf28a2dd041dc0dcd..a29f28cd084db481cb2a471cc3e414f09124314e 100644 (file)
@@ -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: