]> Cypherpunks repositories - gostls13.git/commitdiff
gc: fix smaller-than-pointer-sized receivers in interfaces
authorRuss Cox <rsc@golang.org>
Mon, 26 Jul 2010 22:25:10 +0000 (15:25 -0700)
committerRuss Cox <rsc@golang.org>
Mon, 26 Jul 2010 22:25:10 +0000 (15:25 -0700)
Fixes #812.

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

src/cmd/5g/gobj.c
src/cmd/6g/gobj.c
src/cmd/8g/gobj.c
src/cmd/gc/dcl.c
src/cmd/gc/go.h
src/cmd/gc/reflect.c
src/cmd/gc/subr.c
src/cmd/gc/typecheck.c
test/fixedbugs/bug296.go [new file with mode: 0644]

index c4564ed6653c0184fa1714b889ce1079038d138c..49c7df1f0280091469658b68cba8fbc16a27b1e9 100644 (file)
@@ -705,7 +705,7 @@ out:
        p->to.type = D_OREG;
        p->to.reg = NREG;
        p->to.name = D_EXTERN;
-       p->to.sym = methodsym(method->sym, ptrto(f->type));
+       p->to.sym = methodsym(method->sym, ptrto(f->type), 0);
 //print("4. %P\n", p);
 
        pc->as = ARET;  // overwrite AEND
index 7c05054b7ae71fbdbf79f7d620cb05c37a783afa..a8e32e9fd50660a99af52c3f62a490ff15bfe939 100644 (file)
@@ -732,7 +732,7 @@ out:
        p = pc;
        gins(AJMP, N, N);
        p->to.type = D_EXTERN;
-       p->to.sym = methodsym(method->sym, ptrto(f->type));
+       p->to.sym = methodsym(method->sym, ptrto(f->type), 0);
 //print("6. %P\n", p);
 
        pc->as = ARET;  // overwrite AEND
index 1f4b106f74a1740a1c7a4dec0dcefed4ea692ea7..6ffdcbcc89f5b54cd21bafa4356277226b8a399c 100644 (file)
@@ -739,7 +739,7 @@ out:
        p = pc;
        gins(AJMP, N, N);
        p->to.type = D_EXTERN;
-       p->to.sym = methodsym(method->sym, ptrto(f->type));
+       p->to.sym = methodsym(method->sym, ptrto(f->type), 0);
 //print("6. %P\n", p);
 
        pc->as = ARET;  // overwrite AEND
index adb1531c3dd619d373fd0226c1b546468f4a44fc..05eff966f7ab1f79db7c462f88e2015b04f75c08 100644 (file)
@@ -1017,11 +1017,12 @@ functype(Node *this, NodeList *in, NodeList *out)
 }
 
 Sym*
-methodsym(Sym *nsym, Type *t0)
+methodsym(Sym *nsym, Type *t0, int iface)
 {
        Sym *s;
        char *p;
        Type *t;
+       char *suffix;
 
        t = t0;
        if(t == T)
@@ -1043,7 +1044,13 @@ methodsym(Sym *nsym, Type *t0)
        if(t != t0 && t0->sym)
                t0 = ptrto(t);
 
-       p = smprint("%#hT·%s", t0, nsym->name);
+       suffix = "";
+       if(iface) {
+               dowidth(t0);
+               if(t0->width < types[tptr]->width)
+                       suffix = "·i";
+       }
+       p = smprint("%#hT·%s%s", t0, nsym->name, suffix);
        s = pkglookup(p, s->pkg);
        free(p);
        return s;
@@ -1058,7 +1065,7 @@ methodname(Node *n, Type *t)
 {
        Sym *s;
 
-       s = methodsym(n->sym, t);
+       s = methodsym(n->sym, t, 0);
        if(s == S)
                return n;
        return newname(s);
index 81eece47850620d0f0692f173e0b8233b37bc967..8417872f408326b858e5ff4ce7523b8f506976e1 100644 (file)
@@ -858,7 +858,7 @@ int isifacemethod(Type *f);
 void   markdcl(void);
 Node*  methodname(Node *n, Type *t);
 Node*  methodname1(Node *n, Node *t);
-Sym*   methodsym(Sym *nsym, Type *t0);
+Sym*   methodsym(Sym *nsym, Type *t0, int iface);
 Node*  newname(Sym *s);
 Type*  newtype(Sym *s);
 Node*  oldname(Sym *s);
@@ -1061,7 +1061,7 @@ void      flusherrors(void);
 void   frame(int context);
 Type*  funcfirst(Iter *s, Type *t);
 Type*  funcnext(Iter *s);
-void   genwrapper(Type *rcvr, Type *method, Sym *newnam);
+void   genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface);
 Type** getinarg(Type *t);
 Type*  getinargx(Type *t);
 Type** getoutarg(Type *t);
index 467f3615bce9697e2392c93239123ed30afedd20..16267ed9d91dcdc552fee00f61e29cfc81777ecc 100644 (file)
@@ -183,14 +183,14 @@ methods(Type *t)
                a = b;
 
                a->name = method->name;
-               a->isym = methodsym(method, it);
-               a->tsym = methodsym(method, t);
+               a->isym = methodsym(method, it, 1);
+               a->tsym = methodsym(method, t, 0);
                a->type = methodfunc(f->type, 1);
                a->mtype = methodfunc(f->type, 0);
 
                if(!(a->isym->flags & SymSiggen)) {
                        a->isym->flags |= SymSiggen;
-                       if(!eqtype(this, it)) {
+                       if(!eqtype(this, it) || this->width < types[tptr]->width) {
                                if(oldlist == nil)
                                        oldlist = pc;
                                // Is okay to call genwrapper here always,
@@ -201,7 +201,7 @@ methods(Type *t)
                                && f->embedded && !isifacemethod(f->type))
                                        genembedtramp(it, f, a->isym);
                                else
-                                       genwrapper(it, f, a->isym);
+                                       genwrapper(it, f, a->isym, 1);
                        }
                }
 
@@ -214,7 +214,7 @@ methods(Type *t)
                                && f->embedded && !isifacemethod(f->type))
                                        genembedtramp(t, f, a->tsym);
                                else
-                                       genwrapper(t, f, a->tsym);
+                                       genwrapper(t, f, a->tsym, 0);
                        }
                }
        }
index 6af406be86dda0f03a2dd8b2529f3e8ae08f15dc..1c0bf1a8cc7aabb66c32e06d548017ee324d8aad 100644 (file)
@@ -3043,10 +3043,11 @@ structargs(Type **tl, int mustname)
  *     newnam - the eventual mangled name of this function
  */
 void
-genwrapper(Type *rcvr, Type *method, Sym *newnam)
+genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
 {
-       Node *this, *fn, *call, *n, *t;
+       Node *this, *fn, *call, *n, *t, *pad;
        NodeList *l, *args, *in, *out;
+       Type *tpad;
 
        if(debug['r'])
                print("genwrapper rcvrtype=%T method=%T newnam=%S\n",
@@ -3062,8 +3063,21 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam)
 
        fn = nod(ODCLFUNC, N, N);
        fn->nname = newname(newnam);
-       t = nod(OTFUNC, this, N);
-       t->list = in;
+       t = nod(OTFUNC, N, N);
+       l = list1(this);
+       if(iface && rcvr->width < types[tptr]->width) {
+               // Building method for interface table and receiver
+               // is smaller than the single pointer-sized word
+               // that the interface call will pass in.
+               // Add a dummy padding argument after the
+               // receiver to make up the difference.
+               tpad = typ(TARRAY);
+               tpad->type = types[TUINT8];
+               tpad->bound = types[tptr]->width - rcvr->width;
+               pad = nod(ODCLFIELD, newname(lookup(".pad")), typenod(tpad));
+               l = list(l, pad);
+       }
+       t->list = concat(l, in);
        t->rlist = out;
        fn->nname->ntype = t;
        funchdr(fn);
index 39e577404829aaca2caff78e4971150325c80857..3784c6699e187b3f34211dc0dbd304a1c15fe194 100644 (file)
@@ -494,7 +494,7 @@ reswitch:
                                goto error;
                        }
                        n->op = ONAME;
-                       n->sym = methodsym(sym, l->type);
+                       n->sym = methodsym(sym, l->type, 0);
                        n->type = methodfunc(n->type, 1);
                        n->xoffset = 0;
                        getinargx(n->type)->type->type = l->type;       // fix up receiver
diff --git a/test/fixedbugs/bug296.go b/test/fixedbugs/bug296.go
new file mode 100644 (file)
index 0000000..cfb9c9b
--- /dev/null
@@ -0,0 +1,82 @@
+package main
+
+type I interface {
+       m(a, b, c, d, e, f, g, h byte)
+}
+
+type Int8 int8
+
+func (x Int8) m(a, b, c, d, e, f, g, h byte) {
+       check("Int8", int64(x), 0x01, a, b, c, d, e, f, g, h)
+}
+
+type Uint8 uint8
+
+func (x Uint8) m(a, b, c, d, e, f, g, h byte) {
+       check("Uint8", int64(x), 0x01, a, b, c, d, e, f, g, h)
+}
+
+type Int16 int16
+
+func (x Int16) m(a, b, c, d, e, f, g, h byte) {
+       check("Int16", int64(x), 0x0102, a, b, c, d, e, f, g, h)
+}
+
+type Uint16 uint16
+
+func (x Uint16) m(a, b, c, d, e, f, g, h byte) {
+       check("Uint16", int64(x), 0x0102, a, b, c, d, e, f, g, h)
+}
+
+type Int32 int32
+
+func (x Int32) m(a, b, c, d, e, f, g, h byte) {
+       check("Int32", int64(x), 0x01020304, a, b, c, d, e, f, g, h)
+}
+
+type Uint32 uint32
+
+func (x Uint32) m(a, b, c, d, e, f, g, h byte) {
+       check("Uint32", int64(x), 0x01020304, a, b, c, d, e, f, g, h)
+}
+
+type Int64 int64
+
+func (x Int64) m(a, b, c, d, e, f, g, h byte) {
+       check("Int64", int64(x), 0x0102030405060708, a, b, c, d, e, f, g, h)
+}
+
+type Uint64 uint64
+
+func (x Uint64) m(a, b, c, d, e, f, g, h byte) {
+       check("Uint64", int64(x), 0x0102030405060708, a, b, c, d, e, f, g, h)
+}
+
+var test = []I{
+       Int8(0x01),
+       Uint8(0x01),
+       Int16(0x0102),
+       Uint16(0x0102),
+       Int32(0x01020304),
+       Uint32(0x01020304),
+       Int64(0x0102030405060708),
+       Uint64(0x0102030405060708),
+}
+
+func main() {
+       for _, t := range test {
+               t.m(0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)
+       }
+}
+
+var bug = false
+
+func check(desc string, have, want int64, a, b, c, d, e, f, g, h byte) {
+       if have != want || a != 0x10 || b != 0x11 || c != 0x12 || d != 0x13 || e != 0x14 || f != 0x15 || g != 0x16 || h != 0x17 {
+               if !bug {
+                       bug = true
+                       println("BUG")
+               }
+               println(desc, "check", have, want, a, b, c, d, e, f, g, h)
+       }
+}