]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: emit explicit type information for local variables
authorRuss Cox <rsc@golang.org>
Mon, 25 Feb 2013 17:13:47 +0000 (12:13 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 25 Feb 2013 17:13:47 +0000 (12:13 -0500)
The type information is (and for years has been) included
as an extra field in the address chunk of an instruction.
Unfortunately, suppose there is a string at a+24(FP) and
we have an instruction reading its length. It will say:

        MOVQ x+32(FP), AX

and the type of *that* argument is int (not slice), because
it is the length being read. This confuses the picture seen
by debuggers and now, worse, by the garbage collector.

Instead of attaching the type information to all uses,
emit an explicit list of TYPE instructions with the information.
The TYPE instructions are no-ops whose only role is to
provide an address to attach type information to.

For example, this function:

        func f(x, y, z int) (a, b string) {
                return
        }

now compiles into:

        --- prog list "f" ---
        0000 (/Users/rsc/x.go:3) TEXT    f+0(SB),$0-56
        0001 (/Users/rsc/x.go:3) LOCALS  ,
        0002 (/Users/rsc/x.go:3) TYPE    x+0(FP){int},$8
        0003 (/Users/rsc/x.go:3) TYPE    y+8(FP){int},$8
        0004 (/Users/rsc/x.go:3) TYPE    z+16(FP){int},$8
        0005 (/Users/rsc/x.go:3) TYPE    a+24(FP){string},$16
        0006 (/Users/rsc/x.go:3) TYPE    b+40(FP){string},$16
        0007 (/Users/rsc/x.go:3) MOVQ    $0,b+40(FP)
        0008 (/Users/rsc/x.go:3) MOVQ    $0,b+48(FP)
        0009 (/Users/rsc/x.go:3) MOVQ    $0,a+24(FP)
        0010 (/Users/rsc/x.go:3) MOVQ    $0,a+32(FP)
        0011 (/Users/rsc/x.go:4) RET     ,

The { } show the formerly hidden type information.
The { } syntax is used when printing from within the gc compiler.
It is not accepted by the assemblers.

The same type information is now included on global variables:

0055 (/Users/rsc/x.go:15) GLOBL   slice+0(SB){[]string},$24(AL*0)

This more accurate type information fixes a bug in the
garbage collector's precise heap collection.

The linker only cares about globals right now, but having the
local information should make things a little nicer for Carl
in the future.

Fixes #4907.

R=ken2
CC=golang-dev
https://golang.org/cl/7395056

33 files changed:
src/cmd/5g/ggen.c
src/cmd/5g/gsubr.c
src/cmd/5g/list.c
src/cmd/5g/peep.c
src/cmd/5g/reg.c
src/cmd/5l/5.out.h
src/cmd/5l/obj.c
src/cmd/5l/span.c
src/cmd/6g/ggen.c
src/cmd/6g/gsubr.c
src/cmd/6g/list.c
src/cmd/6g/peep.c
src/cmd/6g/reg.c
src/cmd/6l/6.out.h
src/cmd/6l/obj.c
src/cmd/6l/optab.c
src/cmd/8g/ggen.c
src/cmd/8g/gsubr.c
src/cmd/8g/list.c
src/cmd/8g/peep.c
src/cmd/8g/reg.c
src/cmd/8l/8.out.h
src/cmd/8l/obj.c
src/cmd/8l/optab.c
src/cmd/gc/closure.c
src/cmd/gc/dcl.c
src/cmd/gc/fmt.c
src/cmd/gc/go.h
src/cmd/gc/obj.c
src/cmd/gc/pgen.c
src/cmd/gc/subr.c
src/cmd/gc/typecheck.c
src/cmd/gc/walk.c

index 679354da9afa26bd272c3376336110c1fdec8393..de1671bb6fe293f6f2e3477ae89847277015174e 100644 (file)
@@ -28,6 +28,9 @@ void
 markautoused(Prog* p)
 {
        for (; p; p = p->link) {
+               if (p->as == ATYPE)
+                       continue;
+
                if (p->from.name == D_AUTO && p->from.node)
                        p->from.node->used = 1;
 
@@ -40,12 +43,21 @@ markautoused(Prog* p)
 void
 fixautoused(Prog* p)
 {
-       for (; p; p = p->link) {
+       Prog **lp;
+
+       for (lp=&p; (p=*lp) != P; ) {
+               if (p->as == ATYPE && p->from.node && p->from.name == D_AUTO && !p->from.node->used) {
+                       *lp = p->link;
+                       continue;
+               }
+
                if (p->from.name == D_AUTO && p->from.node)
                        p->from.offset += p->from.node->stkdelta;
 
                if (p->to.name == D_AUTO && p->to.node)
                        p->to.offset += p->to.node->stkdelta;
+
+               lp = &p->link;
        }
 }
 
index ce5ae422e06790dd0258a988bb269deb4321f32a..38c4a920064d8c0bdf0bb24cd11c03eef899da6a 100644 (file)
@@ -192,15 +192,16 @@ gjmp(Prog *to)
 }
 
 void
-ggloblnod(Node *nam, int32 width)
+ggloblnod(Node *nam)
 {
        Prog *p;
 
        p = gins(AGLOBL, nam, N);
        p->lineno = nam->lineno;
+       p->from.gotype = ngotype(nam);
        p->to.sym = S;
        p->to.type = D_CONST;
-       p->to.offset = width;
+       p->to.offset = nam->type->width;
        if(nam->readonly)
                p->reg = RODATA;
        if(nam->type != T && !haspointers(nam->type))
index 9f67f79f432fbbf54256c0b1ee42295f9482e99a..6c3f1d74493679c3a206094be0747db68aee0dc9 100644 (file)
@@ -196,7 +196,10 @@ Dconv(Fmt *fp)
 //             goto conv;
        }
 conv:
-       return fmtstrcpy(fp, str);
+       fmtstrcpy(fp, str);
+       if(a->gotype)
+               fmtprint(fp, "{%s}", a->gotype->name);
+       return 0;
 }
 
 int
index c729a64661a5d8ad32db2b22e2f0f80292d6e69b..b6202a882cf7da2a6253e813399de06d408d505f 100644 (file)
@@ -76,6 +76,8 @@ peep(void)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
+               case ALOCALS:
+               case ATYPE:
                        p = p->link;
                }
        }
index da80f32a4b69ba405a8b246349d9a1355a66efd3..0667531ebf309f9358134c81c0417eaa191a50ff 100644 (file)
@@ -248,6 +248,8 @@ regopt(Prog *firstp)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
+               case ALOCALS:
+               case ATYPE:
                        continue;
                }
                r = rega();
index 1ffe9dc85e17a9f4b9caba8b9412088dfb4da29b..4aef8a27f4eef92223e6b266de9594feeba417db 100644 (file)
@@ -198,6 +198,7 @@ enum        as
        
        AUSEFIELD,
        ALOCALS,
+       ATYPE,
 
        ALAST,
 };
index c9e38dc3894bc67f5c3ac621300bb2ba30dd374e..14b1ea7aaebb4f18ff1bcacb8d1bf0df464a36c9 100644 (file)
@@ -578,6 +578,10 @@ loop:
                pc++;
                break;
 
+       case ATYPE:
+               pc++;
+               goto loop;
+
        case ATEXT:
                if(cursym != nil && cursym->text) {
                        histtoauto();
index fd30e91a523c046257e1132895dcbccd1fcef8ad..a5afa02e79a90172cd0161f276d255590223f7e2 100644 (file)
@@ -833,6 +833,7 @@ buildop(void)
                case ALOCALS:
                case ACASE:
                case ABCASE:
+               case ATYPE:
                        break;
                case AADDF:
                        oprange[AADDD] = oprange[r];
index 10c116d623757bda5d1d529d5a04257936037fa2..23bb5093f04988f133c6de44ad39917815b4a5f1 100644 (file)
@@ -25,6 +25,9 @@ void
 markautoused(Prog* p)
 {
        for (; p; p = p->link) {
+               if (p->as == ATYPE)
+                       continue;
+
                if (p->from.type == D_AUTO && p->from.node)
                        p->from.node->used = 1;
 
@@ -35,14 +38,22 @@ markautoused(Prog* p)
 
 // Fixup instructions after compactframe has moved all autos around.
 void
-fixautoused(Progp)
+fixautoused(Prog *p)
 {
-       for (; p; p = p->link) {
+       Prog **lp;
+
+       for (lp=&p; (p=*lp) != P; ) {
+               if (p->as == ATYPE && p->from.node && p->from.type == D_AUTO && !p->from.node->used) {
+                       *lp = p->link;
+                       continue;
+               }
                if (p->from.type == D_AUTO && p->from.node)
                        p->from.offset += p->from.node->stkdelta;
 
                if (p->to.type == D_AUTO && p->to.node)
                        p->to.offset += p->to.node->stkdelta;
+
+               lp = &p->link;
        }
 }
 
index 34965126e8f57e97dee3cf5daf00174d593e690d..fc5407a1f3762c875ccb2f08e733780a2602b28b 100644 (file)
@@ -190,15 +190,16 @@ gjmp(Prog *to)
 }
 
 void
-ggloblnod(Node *nam, int32 width)
+ggloblnod(Node *nam)
 {
        Prog *p;
 
        p = gins(AGLOBL, nam, N);
        p->lineno = nam->lineno;
+       p->from.gotype = ngotype(nam);
        p->to.sym = S;
        p->to.type = D_CONST;
-       p->to.offset = width;
+       p->to.offset = nam->type->width;
        if(nam->readonly)
                p->from.scale = RODATA;
        if(nam->type != T && !haspointers(nam->type))
@@ -1179,10 +1180,8 @@ naddr(Node *n, Addr *a, int canemitcode)
 
        case ONAME:
                a->etype = 0;
-               if(n->type != T) {
+               if(n->type != T)
                        a->etype = simtype[n->type->etype];
-                       a->gotype = ngotype(n);
-               }
                a->offset = n->xoffset;
                a->sym = n->sym;
                a->node = n->orig;
index d84cceffb848d01dad1aa1c20d132228af29b2eb..9d27a6a097b74d693d91a1ef8e874c81cf8cb260 100644 (file)
@@ -161,7 +161,10 @@ brk:
                strcat(str, s);
        }
 conv:
-       return fmtstrcpy(fp, str);
+       fmtstrcpy(fp, str);
+       if(a->gotype)
+               fmtprint(fp, "{%s}", a->gotype->name);
+       return 0;
 }
 
 static char*   regstr[] =
index 070077f1053b124ea9cce8fc1d9db283563ea323..569655786acb4476293ccd59a82c2f8da7421fcb 100644 (file)
@@ -132,6 +132,8 @@ peep(void)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
+               case ALOCALS:
+               case ATYPE:
                        p = p->link;
                }
        }
index bb8e09c6423c8fb4aa65fadfe35bb5f62d5eedc4..e1188a2353a162a21ae6318407a7dca7f0cd1e43 100644 (file)
@@ -224,6 +224,8 @@ regopt(Prog *firstp)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
+               case ALOCALS:
+               case ATYPE:
                        continue;
                }
                r = rega();
index d348c1304e08c74b9318db0e62e4d37556cdf9c6..805b3fc6f2daf28d6477c582da0e001b67d0ef8f 100644 (file)
@@ -759,6 +759,7 @@ enum        as
        
        AUSEFIELD,
        ALOCALS,
+       ATYPE,
 
        ALAST
 };
index e90a66e5dc9e4cf3ae86ff3dbabb3c6b06db1bd3..10e4a986019eb13849e3e84c31a199d74f7a06f7 100644 (file)
@@ -590,6 +590,10 @@ loop:
                cursym->locals = p->to.offset;
                pc++;
                goto loop;
+       
+       case ATYPE:
+               pc++;
+               goto loop;
 
        case ATEXT:
                s = p->from.sym;
index 21b4784353fe4dd7966ff21ea7e0045dc38d942c..a163e6faab48365ffccad7a0e36026adcb41fc28 100644 (file)
@@ -1318,6 +1318,7 @@ Optab optab[] =
 
        { AUSEFIELD,    ynop,   Px, 0,0 },
        { ALOCALS },
+       { ATYPE },
 
        { AEND },
        0
index e8d6747c4ab37785b9258c1b2b2ad5bc247400ec..70148106c4058f31c5bef7b81a1a28dbb8e2cf9a 100644 (file)
@@ -27,6 +27,9 @@ void
 markautoused(Prog* p)
 {
        for (; p; p = p->link) {
+               if (p->as == ATYPE)
+                       continue;
+
                if (p->from.type == D_AUTO && p->from.node)
                        p->from.node->used = 1;
 
@@ -39,12 +42,21 @@ markautoused(Prog* p)
 void
 fixautoused(Prog* p)
 {
-       for (; p; p = p->link) {
+       Prog **lp;
+
+       for (lp=&p; (p=*lp) != P; ) {
+               if (p->as == ATYPE && p->from.node && p->from.type == D_AUTO && !p->from.node->used) {
+                       *lp = p->link;
+                       continue;
+               }
+
                if (p->from.type == D_AUTO && p->from.node)
                        p->from.offset += p->from.node->stkdelta;
 
                if (p->to.type == D_AUTO && p->to.node)
                        p->to.offset += p->to.node->stkdelta;
+
+               lp = &p->link;
        }
 }
 
index 3650d34a05b2e1ad4dc39384d28fa2f4a5499a05..c4c184bb9a88acd0961723e92b03faf3961af209 100644 (file)
@@ -191,15 +191,16 @@ gjmp(Prog *to)
 }
 
 void
-ggloblnod(Node *nam, int32 width)
+ggloblnod(Node *nam)
 {
        Prog *p;
 
        p = gins(AGLOBL, nam, N);
        p->lineno = nam->lineno;
+       p->from.gotype = ngotype(nam);
        p->to.sym = S;
        p->to.type = D_CONST;
-       p->to.offset = width;
+       p->to.offset = nam->type->width;
        if(nam->readonly)
                p->from.scale = RODATA;
        if(nam->type != T && !haspointers(nam->type))
@@ -2260,7 +2261,6 @@ naddr(Node *n, Addr *a, int canemitcode)
                        a->etype = simtype[n->type->etype];
                        dowidth(n->type);
                        a->width = n->type->width;
-                       a->gotype = ngotype(n);
                }
                a->offset = n->xoffset;
                a->sym = n->sym;
index 7ed1c119d517affff8153dff9b974355b1c3fd90..ec02ba5c5c0bdb4b6ca80b96a18da23d2cd08f36 100644 (file)
@@ -158,7 +158,10 @@ brk:
                strcat(str, s);
        }
 conv:
-       return fmtstrcpy(fp, str);
+       fmtstrcpy(fp, str);
+       if(a->gotype)
+               fmtprint(fp, "{%s}", a->gotype->name);
+       return 0;
 }
 
 static char*   regstr[] =
index ccf7dcd339864c1667411785ebb9008a634b6b93..e5a3149cf1a7dd7d74cd2f5c221a10a34c96b8b0 100644 (file)
@@ -126,6 +126,8 @@ peep(void)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
+               case ALOCALS:
+               case ATYPE:
                        p = p->link;
                }
        }
index e96336b702ebbf96aec5c8c0620a432d78e37150..c1f51c0a4138787f32484090b35d3681084bff86 100644 (file)
@@ -195,6 +195,8 @@ regopt(Prog *firstp)
                case AGLOBL:
                case ANAME:
                case ASIGNAME:
+               case ALOCALS:
+               case ATYPE:
                        continue;
                }
                r = rega();
index ae1397dd8d369c1fb6b3b4f99c0ee5646a41b0da..38688995600f897f856b3c6505caeb620ab637f4 100644 (file)
@@ -569,6 +569,7 @@ enum        as
        
        AUSEFIELD,
        ALOCALS,
+       ATYPE,
 
        ALAST
 };
index bd5684a3508e45fd67badbc8f93195dfa2d9804d..dcb8390b97979d8a4b07f95d2ad385af7d999011 100644 (file)
@@ -600,6 +600,10 @@ loop:
                pc++;
                goto loop;
 
+       case ATYPE:
+               pc++;
+               goto loop;
+
        case ATEXT:
                s = p->from.sym;
                if(s->text != nil) {
index 3ccdbfd22605949d553a43c752158899aded4f41..79d7b39f0057befbd08b500d554baaabd0ac5240 100644 (file)
@@ -963,6 +963,7 @@ Optab optab[] =
 
        { AUSEFIELD,    ynop,   Px, 0,0 },
        { ALOCALS },
+       { ATYPE },
 
        0
 };
index 3e65e0dd2cc6834a3783a94b70195eface237e03..78b73d847cafb14da8bfeaca3fc9c48a3d633b14 100644 (file)
@@ -13,7 +13,7 @@
 void
 closurehdr(Node *ntype)
 {
-       Node *n, *name, *a, *orig;
+       Node *n, *name, *a;
        NodeList *l;
 
        n = nod(OCLOSURE, N, N);
@@ -43,11 +43,8 @@ closurehdr(Node *ntype)
        }
        for(l=n->rlist; l; l=l->next) {
                name = l->n->left;
-               if(name) {
-                       orig = name->orig;  // preserve the meaning of orig == N (anonymous PPARAMOUT)
+               if(name)
                        name = newname(name->sym);
-                       name->orig = orig;
-               }
                ntype->rlist = list(ntype->rlist, nod(ODCLFIELD, name, l->n->right));
        }
 }
index c4990df072d3714bb3fb11c1809838408097c12a..aa2489d9a104b2ea03848fe9899b1f7c67d72307 100644 (file)
@@ -640,8 +640,7 @@ funcargs(Node *nt)
                        // give it a name so escape analysis has nodes to work with
                        snprint(namebuf, sizeof(namebuf), "~anon%d", gen++);
                        n->left = newname(lookup(namebuf));
-                       n->left->orig = N;  // signal that the original was absent
-
+                       // TODO: n->left->missing = 1;
                } 
 
                n->left->op = ONAME;
@@ -815,7 +814,7 @@ structfield(Node *n)
                break;
        }
 
-       if(n->left && n->left->op == ONAME && n->left->orig != N) {
+       if(n->left && n->left->op == ONAME) {
                f->nname = n->left;
                f->embedded = n->embedded;
                f->sym = f->nname->sym;
@@ -1177,6 +1176,7 @@ functype(Node *this, NodeList *in, NodeList *out)
 {
        Type *t;
        NodeList *rcvr;
+       Sym *s;
 
        t = typ(TFUNC);
 
@@ -1194,7 +1194,12 @@ functype(Node *this, NodeList *in, NodeList *out)
                t->thistuple = 1;
        t->outtuple = count(out);
        t->intuple = count(in);
-       t->outnamed = t->outtuple > 0 && out->n->left != N && out->n->left->orig != N;
+       t->outnamed = 0;
+       if(t->outtuple > 0 && out->n->left != N && out->n->left->orig != N) {
+               s = out->n->left->orig->sym;
+               if(s != S && s->name[0] != '~')
+                       t->outnamed = 1;
+       }
 
        return t;
 }
index bae66e07728e541678c5bb7cf873a4cf9b99f225..5d37ac0fd5232ea54ba24763ecfda408f838993b 100644 (file)
@@ -723,12 +723,15 @@ typefmt(Fmt *fp, Type *t)
                if(!(fp->flags&FmtShort)) {
                        s = t->sym;
 
-                       // Take the name from the original, lest we substituted it with .anon%d
-                       if ((fmtmode == FErr || fmtmode == FExp) && t->nname != N)
-                               if(t->nname->orig != N)
+                       // Take the name from the original, lest we substituted it with ~anon%d
+                       if ((fmtmode == FErr || fmtmode == FExp) && t->nname != N) {
+                               if(t->nname->orig != N) {
                                        s = t->nname->orig->sym;
-                               else 
+                                       if(s != S && s->name[0] == '~')
+                                               s = S;
+                               } else 
                                        s = S;
+                       }
                        
                        if(s != S && !t->embedded) {
                                if(t->funarg)
index 68a0563aac39b1727acd986b81100f574dff0fbe..05d942b41925e4d8f4969ee0921d523aa612c804 100644 (file)
@@ -271,7 +271,6 @@ struct      Node
 
        // most nodes
        Type*   type;
-       Type*   realtype;       // as determined by typecheck
        Node*   orig;           // original form, for printing, and tracking copies of ONAMEs
 
        // func
@@ -1438,7 +1437,7 @@ void      gdata(Node*, Node*, int);
 void   gdatacomplex(Node*, Mpcplx*);
 void   gdatastring(Node*, Strlit*);
 void   genembedtramp(Type*, Type*, Sym*, int iface);
-void   ggloblnod(Node *nam, int32 width);
+void   ggloblnod(Node *nam);
 void   ggloblsym(Sym *s, int32 width, int dupok, int rodata);
 Prog*  gjmp(Prog*);
 void   gused(Node*);
index 94f1c65c969f27728c7562576ef867da3d39ff6f..b87d35b7bdcd6c2c6c2b02c070e3c215b7e1b7cd 100644 (file)
@@ -59,7 +59,7 @@ dumpglobls(void)
                        continue;
                dowidth(n->type);
 
-               ggloblnod(n, n->type->width);
+               ggloblnod(n);
        }
 
        for(l=funcsyms; l; l=l->next) {
index f4894e468e6682aad4c91a2c91c8e2657877c5a0..6f732b991ebcc4eb087211849323372ea5536ab5 100644 (file)
@@ -14,11 +14,12 @@ compile(Node *fn)
 {
        Plist *pl;
        Node nod1, *n;
-       Prog *plocals, *ptxt;
+       Prog *plocals, *ptxt, *p, *p1;
        int32 lno;
        Type *t;
        Iter save;
        vlong oldstksize;
+       NodeList *l;
 
        if(newproc == N) {
                newproc = sysfunc("newproc");
@@ -92,12 +93,25 @@ compile(Node *fn)
        for(t=curfn->paramfld; t; t=t->down)
                gtrack(tracksym(t->type));
 
+       for(l=fn->dcl; l; l=l->next) {
+               n = l->n;
+               if(n->op != ONAME) // might be OTYPE or OLITERAL
+                       continue;
+               switch(n->class) {
+               case PAUTO:
+               case PPARAM:
+               case PPARAMOUT:
+                       nodconst(&nod1, types[TUINTPTR], l->n->type->width);
+                       p = gins(ATYPE, l->n, &nod1);
+                       p->from.gotype = ngotype(l->n);
+                       break;
+               }
+       }
+
        genlist(curfn->enter);
 
        retpc = nil;
        if(hasdefer || curfn->exit) {
-               Prog *p1;
-
                p1 = gjmp(nil);
                retpc = gjmp(nil);
                patch(p1, pc);
index 323d4f392282b37766b97f668fee0eb9814c399a..db8b17014568b6d1daa5cdb695d5dd83cced275f 100644 (file)
@@ -3555,10 +3555,8 @@ umagic(Magic *m)
 Sym*
 ngotype(Node *n)
 {
-       if(n->sym != S && n->realtype != T)
-       if(strncmp(n->sym->name, "autotmp_", 8) != 0)
-               return typenamesym(n->realtype);
-
+       if(n->type != T)
+               return typenamesym(n->type);
        return S;
 }
 
index 6b750384c097a29f59965bf4d2fa051f2ef5a9da..ac90baafd2979080a65874a1f4e1787fe9d7d968 100644 (file)
@@ -296,7 +296,6 @@ typecheck1(Node **np, int top)
                }
 
                typecheckdef(n);
-               n->realtype = n->type;
                if(n->op == ONONAME)
                        goto error;
        }
index c79339ca77132f31fea378446cc6622f1f8f70a4..de2105ed39e7edc2b7dbaa90490687b613e65fa6 100644 (file)
@@ -2217,6 +2217,8 @@ paramstoheap(Type **argin, int out)
        nn = nil;
        for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
                v = t->nname;
+               if(v && v->sym && v->sym->name[0] == '~')
+                       v = N;
                if(v == N && out && hasdefer) {
                        // Defer might stop a panic and show the
                        // return values as they exist at the time of panic.