mirror of
https://github.com/golang/go
synced 2024-11-24 23:07:56 -07:00
gc: fix smaller-than-pointer-sized receivers in interfaces
Fixes #812. R=ken2 CC=golang-dev https://golang.org/cl/1904041
This commit is contained in:
parent
7b240e8135
commit
607eaea456
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
82
test/fixedbugs/bug296.go
Normal file
82
test/fixedbugs/bug296.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user