mirror of
https://github.com/golang/go
synced 2024-11-13 16:40:22 -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.type = D_OREG;
|
||||||
p->to.reg = NREG;
|
p->to.reg = NREG;
|
||||||
p->to.name = D_EXTERN;
|
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);
|
//print("4. %P\n", p);
|
||||||
|
|
||||||
pc->as = ARET; // overwrite AEND
|
pc->as = ARET; // overwrite AEND
|
||||||
|
@ -732,7 +732,7 @@ out:
|
|||||||
p = pc;
|
p = pc;
|
||||||
gins(AJMP, N, N);
|
gins(AJMP, N, N);
|
||||||
p->to.type = D_EXTERN;
|
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);
|
//print("6. %P\n", p);
|
||||||
|
|
||||||
pc->as = ARET; // overwrite AEND
|
pc->as = ARET; // overwrite AEND
|
||||||
|
@ -739,7 +739,7 @@ out:
|
|||||||
p = pc;
|
p = pc;
|
||||||
gins(AJMP, N, N);
|
gins(AJMP, N, N);
|
||||||
p->to.type = D_EXTERN;
|
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);
|
//print("6. %P\n", p);
|
||||||
|
|
||||||
pc->as = ARET; // overwrite AEND
|
pc->as = ARET; // overwrite AEND
|
||||||
|
@ -1017,11 +1017,12 @@ functype(Node *this, NodeList *in, NodeList *out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Sym*
|
Sym*
|
||||||
methodsym(Sym *nsym, Type *t0)
|
methodsym(Sym *nsym, Type *t0, int iface)
|
||||||
{
|
{
|
||||||
Sym *s;
|
Sym *s;
|
||||||
char *p;
|
char *p;
|
||||||
Type *t;
|
Type *t;
|
||||||
|
char *suffix;
|
||||||
|
|
||||||
t = t0;
|
t = t0;
|
||||||
if(t == T)
|
if(t == T)
|
||||||
@ -1043,7 +1044,13 @@ methodsym(Sym *nsym, Type *t0)
|
|||||||
if(t != t0 && t0->sym)
|
if(t != t0 && t0->sym)
|
||||||
t0 = ptrto(t);
|
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);
|
s = pkglookup(p, s->pkg);
|
||||||
free(p);
|
free(p);
|
||||||
return s;
|
return s;
|
||||||
@ -1058,7 +1065,7 @@ methodname(Node *n, Type *t)
|
|||||||
{
|
{
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
|
||||||
s = methodsym(n->sym, t);
|
s = methodsym(n->sym, t, 0);
|
||||||
if(s == S)
|
if(s == S)
|
||||||
return n;
|
return n;
|
||||||
return newname(s);
|
return newname(s);
|
||||||
|
@ -858,7 +858,7 @@ int isifacemethod(Type *f);
|
|||||||
void markdcl(void);
|
void markdcl(void);
|
||||||
Node* methodname(Node *n, Type *t);
|
Node* methodname(Node *n, Type *t);
|
||||||
Node* methodname1(Node *n, Node *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);
|
Node* newname(Sym *s);
|
||||||
Type* newtype(Sym *s);
|
Type* newtype(Sym *s);
|
||||||
Node* oldname(Sym *s);
|
Node* oldname(Sym *s);
|
||||||
@ -1061,7 +1061,7 @@ void flusherrors(void);
|
|||||||
void frame(int context);
|
void frame(int context);
|
||||||
Type* funcfirst(Iter *s, Type *t);
|
Type* funcfirst(Iter *s, Type *t);
|
||||||
Type* funcnext(Iter *s);
|
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** getinarg(Type *t);
|
||||||
Type* getinargx(Type *t);
|
Type* getinargx(Type *t);
|
||||||
Type** getoutarg(Type *t);
|
Type** getoutarg(Type *t);
|
||||||
|
@ -183,14 +183,14 @@ methods(Type *t)
|
|||||||
a = b;
|
a = b;
|
||||||
|
|
||||||
a->name = method->name;
|
a->name = method->name;
|
||||||
a->isym = methodsym(method, it);
|
a->isym = methodsym(method, it, 1);
|
||||||
a->tsym = methodsym(method, t);
|
a->tsym = methodsym(method, t, 0);
|
||||||
a->type = methodfunc(f->type, 1);
|
a->type = methodfunc(f->type, 1);
|
||||||
a->mtype = methodfunc(f->type, 0);
|
a->mtype = methodfunc(f->type, 0);
|
||||||
|
|
||||||
if(!(a->isym->flags & SymSiggen)) {
|
if(!(a->isym->flags & SymSiggen)) {
|
||||||
a->isym->flags |= SymSiggen;
|
a->isym->flags |= SymSiggen;
|
||||||
if(!eqtype(this, it)) {
|
if(!eqtype(this, it) || this->width < types[tptr]->width) {
|
||||||
if(oldlist == nil)
|
if(oldlist == nil)
|
||||||
oldlist = pc;
|
oldlist = pc;
|
||||||
// Is okay to call genwrapper here always,
|
// Is okay to call genwrapper here always,
|
||||||
@ -201,7 +201,7 @@ methods(Type *t)
|
|||||||
&& f->embedded && !isifacemethod(f->type))
|
&& f->embedded && !isifacemethod(f->type))
|
||||||
genembedtramp(it, f, a->isym);
|
genembedtramp(it, f, a->isym);
|
||||||
else
|
else
|
||||||
genwrapper(it, f, a->isym);
|
genwrapper(it, f, a->isym, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ methods(Type *t)
|
|||||||
&& f->embedded && !isifacemethod(f->type))
|
&& f->embedded && !isifacemethod(f->type))
|
||||||
genembedtramp(t, f, a->tsym);
|
genembedtramp(t, f, a->tsym);
|
||||||
else
|
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
|
* newnam - the eventual mangled name of this function
|
||||||
*/
|
*/
|
||||||
void
|
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;
|
NodeList *l, *args, *in, *out;
|
||||||
|
Type *tpad;
|
||||||
|
|
||||||
if(debug['r'])
|
if(debug['r'])
|
||||||
print("genwrapper rcvrtype=%T method=%T newnam=%S\n",
|
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 = nod(ODCLFUNC, N, N);
|
||||||
fn->nname = newname(newnam);
|
fn->nname = newname(newnam);
|
||||||
t = nod(OTFUNC, this, N);
|
t = nod(OTFUNC, N, N);
|
||||||
t->list = in;
|
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;
|
t->rlist = out;
|
||||||
fn->nname->ntype = t;
|
fn->nname->ntype = t;
|
||||||
funchdr(fn);
|
funchdr(fn);
|
||||||
|
@ -494,7 +494,7 @@ reswitch:
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
n->op = ONAME;
|
n->op = ONAME;
|
||||||
n->sym = methodsym(sym, l->type);
|
n->sym = methodsym(sym, l->type, 0);
|
||||||
n->type = methodfunc(n->type, 1);
|
n->type = methodfunc(n->type, 1);
|
||||||
n->xoffset = 0;
|
n->xoffset = 0;
|
||||||
getinargx(n->type)->type->type = l->type; // fix up receiver
|
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