Commit 20595ac4 authored by Russ Cox's avatar Russ Cox

many interface bug fixes.

also, after
	func g() (int, int)
	func f(int, int)
allow
	f(g())
and
	func h() (int, int) { return g() }

R=ken
DELTA=356  (252 added, 26 deleted, 78 changed)
OCL=22319
CL=22325
parent 4dc3d74a
...@@ -174,7 +174,7 @@ regalloc(Node *n, Type *t, Node *o) ...@@ -174,7 +174,7 @@ regalloc(Node *n, Type *t, Node *o)
if(t == T) if(t == T)
fatal("regalloc: t nil"); fatal("regalloc: t nil");
et = simtype[t->etype]; et = simtype[t->etype];
switch(et) { switch(et) {
case TINT8: case TINT8:
case TUINT8: case TUINT8:
...@@ -278,6 +278,23 @@ Node* ...@@ -278,6 +278,23 @@ Node*
nodarg(Type *t, int fp) nodarg(Type *t, int fp)
{ {
Node *n; Node *n;
Type *first;
Iter savet;
// entire argument struct, not just one arg
if(t->etype == TSTRUCT && t->funarg) {
n = nod(ONAME, N, N);
n->sym = lookup(".args");
n->type = t;
first = structfirst(&savet, &t);
if(first == nil)
fatal("nodarg: bad struct");
if(first->width == BADWIDTH)
fatal("nodarg: offset not computed for %T", t);
n->xoffset = first->width;
n->addable = 1;
goto fp;
}
if(t->etype != TFIELD) if(t->etype != TFIELD)
fatal("nodarg: not field %T", t); fatal("nodarg: not field %T", t);
...@@ -290,6 +307,7 @@ nodarg(Type *t, int fp) ...@@ -290,6 +307,7 @@ nodarg(Type *t, int fp)
n->xoffset = t->width; n->xoffset = t->width;
n->addable = 1; n->addable = 1;
fp:
switch(fp) { switch(fp) {
case 0: // output arg case 0: // output arg
n->op = OINDREG; n->op = OINDREG;
...@@ -301,7 +319,7 @@ nodarg(Type *t, int fp) ...@@ -301,7 +319,7 @@ nodarg(Type *t, int fp)
break; break;
case 2: // offset output arg case 2: // offset output arg
fatal("shpuldnt be used"); fatal("shouldnt be used");
n->op = OINDREG; n->op = OINDREG;
n->val.u.reg = D_SP; n->val.u.reg = D_SP;
n->xoffset += types[tptr]->width; n->xoffset += types[tptr]->width;
...@@ -1860,7 +1878,7 @@ sudoclean(void) ...@@ -1860,7 +1878,7 @@ sudoclean(void)
/* /*
* generate code to compute address of n, * generate code to compute address of n,
* a reference to a (perhaps nested) field inside * a reference to a (perhaps nested) field inside
* an array or struct. * an array or struct.
* return 0 on failure, 1 on success. * return 0 on failure, 1 on success.
* on success, leaves usable address in a. * on success, leaves usable address in a.
* *
...@@ -1909,7 +1927,7 @@ odot: ...@@ -1909,7 +1927,7 @@ odot:
o = dotoffset(n, oary, &nn); o = dotoffset(n, oary, &nn);
if(nn == N) if(nn == N)
goto no; goto no;
regalloc(reg, types[tptr], N); regalloc(reg, types[tptr], N);
n1 = *reg; n1 = *reg;
n1.op = OINDREG; n1.op = OINDREG;
......
...@@ -524,7 +524,7 @@ gensatad(Sym *s) ...@@ -524,7 +524,7 @@ gensatad(Sym *s)
} }
void void
gentramp(Type *t, Sig *b) genembedtramp(Type *t, Sig *b)
{ {
Sym *e; Sym *e;
int c, d, o; int c, d, o;
...@@ -533,22 +533,24 @@ gentramp(Type *t, Sig *b) ...@@ -533,22 +533,24 @@ gentramp(Type *t, Sig *b)
e = lookup(b->name); e = lookup(b->name);
for(d=0; d<nelem(dotlist); d++) { for(d=0; d<nelem(dotlist); d++) {
c = adddot1(e, t, d); c = adddot1(e, t, d, nil);
if(c == 1) if(c == 1)
goto out; goto out;
} }
fatal("gentramp"); fatal("genembedtramp");
out: out:
if(d == 0) if(d == 0)
return; return;
// print("gentramp %d\n", d); // print("genembedtramp %d\n", d);
// print(" t = %lT\n", t); // print(" t = %lT\n", t);
// print(" name = %s\n", b->name); // print(" name = %s\n", b->name);
// print(" sym = %S\n", b->sym); // print(" sym = %S\n", b->sym);
// print(" hash = 0x%ux\n", b->hash); // print(" hash = 0x%ux\n", b->hash);
newplist()->name = newname(b->sym);
//TEXT main·S_test2(SB),7,$0 //TEXT main·S_test2(SB),7,$0
p = pc; p = pc;
gins(ATEXT, N, N); gins(ATEXT, N, N);
...@@ -601,54 +603,107 @@ out: ...@@ -601,54 +603,107 @@ out:
//print("5. %P\n", p); //print("5. %P\n", p);
f = dotlist[0].field; f = dotlist[0].field;
//JMP main·Sub_test2(SB) //JMP main·*Sub_test2(SB)
if(isptr[f->type->etype]) if(isptr[f->type->etype])
f = f->type; f = f->type;
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(lookup(b->name), f->type); p->to.sym = methodsym(lookup(b->name), ptrto(f->type));
//print("6. %P\n", p); //print("6. %P\n", p);
pc->as = ARET; // overwrite AEND
} }
/*
* Add DATA for signature s.
* progt - type in program
* ifacet - type stored in interface (==progt if small, ==ptrto(progt) if large)
* rcvrt - type used as method interface. eqtype(ifacet, rcvrt) is always true,
* but ifacet might have a name that rcvrt does not.
* methodt - type with methods hanging off it (progt==*methodt sometimes)
*/
void void
dumpsigt(Type *t0, Type *t, Sym *s) dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s)
{ {
Type *f; Type *f;
Sym *s1;
int o; int o;
int indir;
Sig *a, *b; Sig *a, *b;
Prog *p; Prog *p;
char buf[NSYMB]; char buf[NSYMB];
Type *this;
Iter savet;
Prog *oldlist;
Sym *method;
at.sym = s; at.sym = s;
a = nil; a = nil;
o = 0; o = 0;
for(f=t->method; f!=T; f=f->down) { oldlist = nil;
for(f=methodt->method; f!=T; f=f->down) {
if(f->type->etype != TFUNC) if(f->type->etype != TFUNC)
continue; continue;
if(f->etype != TFIELD) if(f->etype != TFIELD)
fatal("dumpsignatures: not field"); fatal("dumpsignatures: not field");
s1 = f->sym; method = f->sym;
if(s1 == nil) if(method == nil)
continue; continue;
b = mal(sizeof(*b)); b = mal(sizeof(*b));
b->link = a; b->link = a;
a = b; a = b;
a->name = s1->name; a->name = method->name;
a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0); a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
a->perm = o; a->perm = o;
a->sym = methodsym(f->sym, t); a->sym = methodsym(method, rcvrt);
a->offset = f->embedded; // need trampoline
if(!a->sym->siggen) {
a->sym->siggen = 1;
// TODO(rsc): This test is still not quite right.
this = structfirst(&savet, getthis(f->type))->type;
if(isptr[this->etype] != isptr[ifacet->etype]) {
if(oldlist == nil)
oldlist = pc;
// indirect vs direct mismatch
Sym *oldname, *newname;
Type *oldthis, *oldtype, *newthis;
newthis = ifacet;
if(isptr[newthis->etype])
oldthis = ifacet->type;
else
oldthis = ptrto(ifacet);
newname = a->sym;
oldname = methodsym(method, oldthis);
genptrtramp(method, oldname, oldthis, f->type, newname, newthis);
}
else if(f->embedded) {
// TODO(rsc): only works for pointer receivers
if(oldlist == nil)
oldlist = pc;
genembedtramp(ifacet, a);
}
}
o++; o++;
} }
// restore data output
if(oldlist) {
// old list ended with AEND; change to ANOP
// so that the trampolines that follow can be found.
oldlist->as = ANOP;
// start new data list
newplist();
}
a = lsort(a, sigcmp); a = lsort(a, sigcmp);
ot = 0; ot = 0;
ot = rnd(ot, maxround); // base structure ot = rnd(ot, maxround); // base structure
...@@ -657,16 +712,16 @@ dumpsigt(Type *t0, Type *t, Sym *s) ...@@ -657,16 +712,16 @@ dumpsigt(Type *t0, Type *t, Sym *s)
ginsatoa(widthptr, stringo); ginsatoa(widthptr, stringo);
// save type name for runtime error message. // save type name for runtime error message.
snprint(buf, sizeof buf, "%#T", t0); snprint(buf, sizeof buf, "%#T", progt);
datastring(buf, strlen(buf)+1); datastring(buf, strlen(buf)+1);
// first field of an type signature contains // first field of an type signature contains
// the element parameters and is not a real entry // the element parameters and is not a real entry
// sigi[0].hash = elemalg // sigi[0].hash = elemalg
gensatac(wi, algtype(t0)); gensatac(wi, algtype(progt));
// sigi[0].offset = width // sigi[0].offset = width
gensatac(wi, t0->width); gensatac(wi, progt->width);
// skip the function // skip the function
gensatac(widthptr, 0); gensatac(widthptr, 0);
...@@ -680,16 +735,13 @@ dumpsigt(Type *t0, Type *t, Sym *s) ...@@ -680,16 +735,13 @@ dumpsigt(Type *t0, Type *t, Sym *s)
// sigx[++].hash = hashcode // sigx[++].hash = hashcode
gensatac(wi, b->hash); gensatac(wi, b->hash);
// sigt[++].offset = of embeded struct // sigt[++].offset = of embedded struct
gensatac(wi, 0); gensatac(wi, 0);
// sigt[++].fun = &method // sigt[++].fun = &method
gensatad(b->sym); gensatad(b->sym);
datastring(b->name, strlen(b->name)+1); datastring(b->name, strlen(b->name)+1);
if(b->offset)
gentramp(t0, b);
} }
// nil field name at end // nil field name at end
...@@ -809,8 +861,8 @@ dumpsignatures(void) ...@@ -809,8 +861,8 @@ dumpsignatures(void)
{ {
int et; int et;
Dcl *d, *x; Dcl *d, *x;
Type *t, *t0; Type *t, *progt, *methodt, *ifacet, *rcvrt;
Sym *s, *s1; Sym *s;
Prog *p; Prog *p;
memset(&at, 0, sizeof(at)); memset(&at, 0, sizeof(at));
...@@ -884,13 +936,6 @@ dumpsignatures(void) ...@@ -884,13 +936,6 @@ dumpsignatures(void)
continue; continue;
s->siggen = 1; s->siggen = 1;
// don't emit non-trivial signatures for types defined outside this file.
// non-trivial signatures might also drag in generated trampolines,
// and ar can't handle duplicates of the trampolines.
// only pay attention to types with symbols, because
// the ... structs and maybe other internal structs
// don't get marked as local.
// interface is easy // interface is easy
if(et == TINTER) { if(et == TINTER) {
if(t->sym && !t->local) if(t->sym && !t->local)
...@@ -899,15 +944,45 @@ dumpsignatures(void) ...@@ -899,15 +944,45 @@ dumpsignatures(void)
continue; continue;
} }
// non-interface is more complex
progt = t;
methodt = t;
ifacet = t;
rcvrt = t;
// if there's a pointer, methods are on base. // if there's a pointer, methods are on base.
t0 = t; if(isptr[methodt->etype] && methodt->type->sym != S) {
if(isptr[et] && t->type->sym != S) { methodt = methodt->type;
t = t->type; expandmeth(methodt->sym, methodt);
expandmeth(t->sym, t);
// if methodt had a name, we don't want to see
// it in the method names that go into the sigt.
// e.g., if
// type item *rat
// then item needs its own sigt distinct from *rat,
// but it needs to have all of *rat's methods, using
// the *rat (not item) in the method names.
if(rcvrt->sym != S)
rcvrt = ptrto(methodt);
}
// and if ifacet is too wide, the methods
// will see a pointer anyway.
if(ifacet->width > 8) {
ifacet = ptrto(progt);
rcvrt = ptrto(progt);
} }
if(t->method && t->sym && !t->local)
// don't emit non-trivial signatures for types defined outside this file.
// non-trivial signatures might also drag in generated trampolines,
// and ar can't handle duplicates of the trampolines.
// only pay attention to types with symbols, because
// the ... structs and maybe other internal structs
// don't get marked as local.
if(methodt->method && methodt->sym && !methodt->local)
continue; continue;
dumpsigt(t0, t, s);
dumpsigt(progt, ifacet, rcvrt, methodt, s);
} }
if(stringo > 0) { if(stringo > 0) {
......
...@@ -203,19 +203,33 @@ methcmp(Type *t1, Type *t2) ...@@ -203,19 +203,33 @@ methcmp(Type *t1, Type *t2)
} }
Sym* Sym*
methodsym(Sym *nsym, Type *t) methodsym(Sym *nsym, Type *t0)
{ {
Sym *s; Sym *s;
char buf[NSYMB]; char buf[NSYMB];
Type *t;
// caller has already called ismethod to obtain t t = t0;
if(t == T) if(t == T)
goto bad; goto bad;
s = t->sym; s = t->sym;
if(s == S) if(s == S) {
goto bad; if(!isptr[t->etype])
goto bad;
t = t->type;
if(t == T)
goto bad;
s = t->sym;
if(s == S)
goto bad;
}
// if t0 == *t and t0 has a sym,
// we want to see *t, not t0, in the method name.
if(t != t0 && t0->sym)
t0 = ptrto(t);
snprint(buf, sizeof(buf), "%#hT·%s", t, nsym->name); snprint(buf, sizeof(buf), "%#hT·%s", t0, nsym->name);
//print("methodname %s\n", buf); //print("methodname %s\n", buf);
return pkglookup(buf, s->opackage); return pkglookup(buf, s->opackage);
......
...@@ -313,7 +313,7 @@ enum ...@@ -313,7 +313,7 @@ enum
OLITERAL, OREGISTER, OINDREG, OLITERAL, OREGISTER, OINDREG,
OCONV, OCOMP, OKEY, OCONV, OCOMP, OKEY,
OBAD, OBAD,
OEXTEND, // 6g internal OEXTEND, // 6g internal
OEND, OEND,
...@@ -681,12 +681,13 @@ int Nconv(Fmt*); ...@@ -681,12 +681,13 @@ int Nconv(Fmt*);
int Wconv(Fmt*); int Wconv(Fmt*);
int Zconv(Fmt*); int Zconv(Fmt*);
int lookdot0(Sym*, Type*); int lookdot0(Sym*, Type*, Type**);
int adddot1(Sym*, Type*, int); int adddot1(Sym*, Type*, int, Type**);
Node* adddot(Node*); Node* adddot(Node*);
void expand0(Type*); void expand0(Type*);
void expand1(Type*, int); void expand1(Type*, int);
void expandmeth(Sym*, Type*); void expandmeth(Sym*, Type*);
void genptrtramp(Sym*, Sym*, Type*, Type*, Sym*, Type*);
/* /*
* dcl.c * dcl.c
......
...@@ -1260,7 +1260,7 @@ fndcl: ...@@ -1260,7 +1260,7 @@ fndcl:
t = ismethod($2->type); t = ismethod($2->type);
$$->nname = $4; $$->nname = $4;
if(t != T) if(t != T)
$$->nname = methodname($4, t); $$->nname = methodname($4, $2->type);
$$->type = functype($2, $6, $8); $$->type = functype($2, $6, $8);
funchdr($$); funchdr($$);
addmethod($4, $$->type, 1); addmethod($4, $$->type, 1);
......
...@@ -947,7 +947,7 @@ Sconv(Fmt *fp) ...@@ -947,7 +947,7 @@ Sconv(Fmt *fp)
nam = s->name; nam = s->name;
if(!(fp->flags & FmtShort)) if(!(fp->flags & FmtShort))
if(strcmp(opk, package) || (fp->flags & FmtLong)) { if(strcmp(opk, package) != 0 || (fp->flags & FmtLong)) {
fmtprint(fp, "%s.%s", opk, nam); fmtprint(fp, "%s.%s", opk, nam);
return 0; return 0;
} }
...@@ -1023,6 +1023,8 @@ Tpretty(Fmt *fp, Type *t) ...@@ -1023,6 +1023,8 @@ Tpretty(Fmt *fp, Type *t)
return fmtprint(fp, "chan %T", t1->type); return fmtprint(fp, "chan %T", t1->type);
} }
} }
if(fp->flags&FmtShort) // pass flag thru for methodsym
return fmtprint(fp, "*%hT", t1);
return fmtprint(fp, "*%T", t1); return fmtprint(fp, "*%T", t1);
// Should not see these: should see ptr instead, handled above. // Should not see these: should see ptr instead, handled above.
...@@ -1156,15 +1158,14 @@ Tconv(Fmt *fp) ...@@ -1156,15 +1158,14 @@ Tconv(Fmt *fp)
} }
et = t->etype; et = t->etype;
snprint(buf, sizeof buf, "%E.", et);
strcpy(buf, ""); if(t->sym != S) {
if(t->sym != S) snprint(buf1, sizeof(buf1), "<%S>", t->sym);
snprint(buf, sizeof(buf), "<%S>", t->sym); strncat(buf, buf1, sizeof(buf));
}
switch(et) { switch(et) {
default: default:
snprint(buf1, sizeof(buf1), "%E", et);
strncat(buf, buf1, sizeof(buf));
if(t->type != T) { if(t->type != T) {
snprint(buf1, sizeof(buf1), " %T", t->type); snprint(buf1, sizeof(buf1), " %T", t->type);
strncat(buf, buf1, sizeof(buf)); strncat(buf, buf1, sizeof(buf));
...@@ -2142,9 +2143,9 @@ loop: ...@@ -2142,9 +2143,9 @@ loop:
yyerror("illegal types for operand: %O", o); yyerror("illegal types for operand: %O", o);
if(tl != T) if(tl != T)
print(" %lT\n", tl); print(" %T\n", tl);
if(tr != T) if(tr != T)
print(" %lT\n", tr); print(" %T\n", tr);
// common mistake: *struct and *interface. // common mistake: *struct and *interface.
if(tl && tr && isptr[tl->etype] && isptr[tr->etype]) { if(tl && tr && isptr[tl->etype] && isptr[tr->etype]) {
...@@ -2393,7 +2394,7 @@ getinargx(Type *t) ...@@ -2393,7 +2394,7 @@ getinargx(Type *t)
// return count of fields+methods // return count of fields+methods
// found with a given name // found with a given name
int int
lookdot0(Sym *s, Type *t) lookdot0(Sym *s, Type *t, Type **save)
{ {
Type *f, *u; Type *f, *u;
int c; int c;
...@@ -2405,14 +2406,20 @@ lookdot0(Sym *s, Type *t) ...@@ -2405,14 +2406,20 @@ lookdot0(Sym *s, Type *t)
c = 0; c = 0;
if(u->etype == TSTRUCT || u->etype == TINTER) { if(u->etype == TSTRUCT || u->etype == TINTER) {
for(f=u->type; f!=T; f=f->down) for(f=u->type; f!=T; f=f->down)
if(f->sym == s) if(f->sym == s) {
if(save)
*save = f;
c++; c++;
}
} }
u = methtype(t); u = methtype(t);
if(u != T) { if(u != T) {
for(f=u->method; f!=T; f=f->down) for(f=u->method; f!=T; f=f->down)
if(f->sym == s && f->embedded == 0) if(f->sym == s && f->embedded == 0) {
if(save)
*save = f;
c++; c++;
}
} }
return c; return c;
} }
...@@ -2423,7 +2430,7 @@ lookdot0(Sym *s, Type *t) ...@@ -2423,7 +2430,7 @@ lookdot0(Sym *s, Type *t)
// answer is in dotlist array and // answer is in dotlist array and
// count of number of ways is returned. // count of number of ways is returned.
int int
adddot1(Sym *s, Type *t, int d) adddot1(Sym *s, Type *t, int d, Type **save)
{ {
Type *f, *u; Type *f, *u;
int c, a; int c, a;
...@@ -2433,7 +2440,7 @@ adddot1(Sym *s, Type *t, int d) ...@@ -2433,7 +2440,7 @@ adddot1(Sym *s, Type *t, int d)
t->trecur = 1; t->trecur = 1;
if(d == 0) { if(d == 0) {
c = lookdot0(s, t); c = lookdot0(s, t, save);
goto out; goto out;
} }
...@@ -2450,7 +2457,7 @@ adddot1(Sym *s, Type *t, int d) ...@@ -2450,7 +2457,7 @@ adddot1(Sym *s, Type *t, int d)
continue; continue;
if(f->sym == S) if(f->sym == S)
continue; continue;
a = adddot1(s, f->type, d); a = adddot1(s, f->type, d, save);
if(a != 0 && c == 0) if(a != 0 && c == 0)
dotlist[d].field = f; dotlist[d].field = f;
c += a; c += a;
...@@ -2484,7 +2491,7 @@ adddot(Node *n) ...@@ -2484,7 +2491,7 @@ adddot(Node *n)
goto ret; goto ret;
for(d=0; d<nelem(dotlist); d++) { for(d=0; d<nelem(dotlist); d++) {
c = adddot1(s, t, d); c = adddot1(s, t, d, nil);
if(c > 0) if(c > 0)
goto out; goto out;
} }
...@@ -2492,7 +2499,7 @@ adddot(Node *n) ...@@ -2492,7 +2499,7 @@ adddot(Node *n)
out: out:
if(c > 1) if(c > 1)
yyerror("ambiguous DOT reference %S", s); yyerror("ambiguous DOT reference %T.%S", t, s);
// rebuild elided dots // rebuild elided dots
for(c=d-1; c>=0; c--) { for(c=d-1; c>=0; c--) {
...@@ -2604,10 +2611,10 @@ expandmeth(Sym *s, Type *t) ...@@ -2604,10 +2611,10 @@ expandmeth(Sym *s, Type *t)
for(sl=slist; sl!=nil; sl=sl->link) { for(sl=slist; sl!=nil; sl=sl->link) {
sl->field->sym->uniq = 0; sl->field->sym->uniq = 0;
for(d=0; d<nelem(dotlist); d++) { for(d=0; d<nelem(dotlist); d++) {
c = adddot1(sl->field->sym, t, d); c = adddot1(sl->field->sym, t, d, &f);
if(c == 0) if(c == 0)
continue; continue;
if(c == 1) if(c == 1 && f == sl->field)
sl->good = 1; sl->good = 1;
break; break;
} }
...@@ -2627,3 +2634,104 @@ expandmeth(Sym *s, Type *t) ...@@ -2627,3 +2634,104 @@ expandmeth(Sym *s, Type *t)
} }
} }
} }
/*
* Given funarg struct list, return list of ODCLFIELD Node fn args.
*/
Node*
structargs(Type **tl, int mustname)
{
Iter savet;
Node *args, *a;
Type *t;
char nam[100];
int n;
args = N;
n = 0;
for(t = structfirst(&savet, tl); t != T; t = structnext(&savet)) {
if(t->sym)
a = nametodcl(newname(t->sym), t->type);
else if(mustname) {
// have to give it a name so we can refer to it in trampoline
snprint(nam, sizeof nam, ".anon%d", n++);
a = nametodcl(newname(lookup(nam)), t->type);
} else
a = anondcl(t->type);
args = list(args, a);
}
args = rev(args);
return args;
}
/*
* Generate a trampoline to convert
* from an indirect receiver to a direct receiver
* or vice versa.
*
* method - short name of method (Len)
* oldname - old mangled method name (x·y·Len)
* oldthis - old this type (y)
* oldtype - type of method being called;
* only in and out params are known okay,
* receiver might be != oldthis.
* newnam [sic] - new mangled method name (x·*y·Len)
* newthis - new this type (*y)
*/
void
genptrtramp(Sym *method, Sym *oldname, Type *oldthis, Type *oldtype, Sym *newnam, Type *newthis)
{
Node *fn, *args, *l, *in, *call, *out, *this, *rcvr, *meth;
Iter savel;
if(debug['r']) {
print("\ngenptrtramp method=%S oldname=%S oldthis=%T\n",
method, oldname, oldthis);
print("\toldtype=%T newnam=%S newthis=%T\n",
oldtype, newnam, newthis);
}
dclcontext = PEXTERN;
markdcl();
this = nametodcl(newname(lookup(".this")), newthis);
in = structargs(getinarg(oldtype), 1);
out = structargs(getoutarg(oldtype), 0);
// fix up oldtype
markdcl();
oldtype = functype(nametodcl(newname(lookup(".this")), oldthis), in, out);
popdcl();
fn = nod(ODCLFUNC, N, N);
fn->nname = newname(newnam);
fn->type = functype(this, in, out);
funchdr(fn);
// arg list
args = N;
for(l = listfirst(&savel, &in); l; l = listnext(&savel))
args = list(args, l->left);
args = rev(args);
// method to call
if(isptr[oldthis->etype])
rcvr = nod(OADDR, this->left, N);
else
rcvr = nod(OIND, this->left, N);
gettype(rcvr, N);
meth = nod(ODOTMETH, rcvr, newname(oldname));
meth->xoffset = BADWIDTH; // TODO(rsc): necessary?
meth->type = oldtype;
call = nod(OCALL, meth, args);
fn->nbody = call;
if(oldtype->outtuple > 0)
fn->nbody = nod(ORETURN, call, N);
if(debug['r'])
dump("genptrtramp body", fn->nbody);
funcbody(fn);
}
...@@ -1540,7 +1540,7 @@ walkselect(Node *sel) ...@@ -1540,7 +1540,7 @@ walkselect(Node *sel)
} }
Type* Type*
lookdot1(Node *n, Type *f) lookdot1(Node *n, Type *t, Type *f)
{ {
Type *r; Type *r;
Sym *s; Sym *s;
...@@ -1554,7 +1554,7 @@ lookdot1(Node *n, Type *f) ...@@ -1554,7 +1554,7 @@ lookdot1(Node *n, Type *f)
if(f->sym != s) if(f->sym != s)
continue; continue;
if(r != T) { if(r != T) {
yyerror("ambiguous DOT reference %S", s); yyerror("ambiguous DOT reference %T.%S", t, s);
break; break;
} }
r = f; r = f;
...@@ -1569,11 +1569,11 @@ lookdot(Node *n, Type *t) ...@@ -1569,11 +1569,11 @@ lookdot(Node *n, Type *t)
f1 = T; f1 = T;
if(t->etype == TSTRUCT || t->etype == TINTER) if(t->etype == TSTRUCT || t->etype == TINTER)
f1 = lookdot1(n->right, t->type); f1 = lookdot1(n->right, t, t->type);
f2 = methtype(n->left->type); f2 = methtype(n->left->type);
if(f2 != T) if(f2 != T)
f2 = lookdot1(n->right, f2->method); f2 = lookdot1(n->right, f2, f2->method);
if(f1 != T) { if(f1 != T) {
if(f2 != T) if(f2 != T)
...@@ -1593,7 +1593,8 @@ lookdot(Node *n, Type *t) ...@@ -1593,7 +1593,8 @@ lookdot(Node *n, Type *t)
n->left = nod(OADDR, n->left, N); n->left = nod(OADDR, n->left, N);
n->left->type = ptrto(n->left->left->type); n->left->type = ptrto(n->left->left->type);
} }
n->right = methodname(n->right, ismethod(n->left->type)); ismethod(n->left->type);
n->right = methodname(n->right, n->left->type);
n->xoffset = f2->width; n->xoffset = f2->width;
n->type = f2->type; n->type = f2->type;
n->op = ODOTMETH; n->op = ODOTMETH;
...@@ -1824,23 +1825,32 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp) ...@@ -1824,23 +1825,32 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp)
return nn; return nn;
} }
/*
* check assign expression list to
* a type list. called in
* return expr-list
* func(expr-list)
*/
Node* Node*
ascompatte(int op, Type **nl, Node **nr, int fp) ascompatte(int op, Type **nl, Node **nr, int fp)
{ {
Type *l, *ll; Type *l, *ll;
Node *r, *rr, *nn, *a; Node *r, *rr, *nn, *a;
Iter savel, saver; Iter savel, saver, peekl, peekr;
/*
* check assign expression list to
* a type list. called in
* return expr-list
* func(expr-list)
*/
l = structfirst(&savel, nl); l = structfirst(&savel, nl);
r = listfirst(&saver, nr); r = listfirst(&saver, nr);
nn = N; nn = N;
// 1 to many
peekl = savel;
peekr = saver;
if(l != T && r != N
&& structnext(&peekl) != T
&& listnext(&peekr) == N)
&& eqtype(r->type, *nl, 0))
return convas(nod(OAS, nodarg(*nl, fp), r));
loop: loop:
if(l != T && isddd(l->type)) { if(l != T && isddd(l->type)) {
// the ddd parameter must be last // the ddd parameter must be last
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include "runtime.h" #include "runtime.h"
static int32 debug = 0; int32 iface_debug = 0;
typedef struct Sigt Sigt; typedef struct Sigt Sigt;
typedef struct Sigi Sigi; typedef struct Sigi Sigi;
...@@ -187,7 +187,7 @@ throw: ...@@ -187,7 +187,7 @@ throw:
} }
m->link = hash[h]; m->link = hash[h];
hash[h] = m; hash[h] = m;
// prints("new itype\n"); // printf("new itype %p\n", m);
return m; return m;
} }
...@@ -204,7 +204,7 @@ sys·ifaceT2I(Sigi *si, Sigt *st, ...) ...@@ -204,7 +204,7 @@ sys·ifaceT2I(Sigi *si, Sigt *st, ...)
ret = (Iface*)(elem + rnd(wid, 8)); ret = (Iface*)(elem + rnd(wid, 8));
ret->type = itype(si, st, 0); ret->type = itype(si, st, 0);
if(debug) { if(iface_debug) {
prints("T2I sigi="); prints("T2I sigi=");
printsigi(si); printsigi(si);
prints(" sigt="); prints(" sigt=");
...@@ -220,12 +220,12 @@ sys·ifaceT2I(Sigi *si, Sigt *st, ...) ...@@ -220,12 +220,12 @@ sys·ifaceT2I(Sigi *si, Sigt *st, ...)
algarray[alg].copy(wid, ret->data, elem); algarray[alg].copy(wid, ret->data, elem);
else{ else{
ret->data[0] = mal(wid); ret->data[0] = mal(wid);
if(debug) if(iface_debug)
printf("T2I mal %d %p\n", wid, ret->data[0]); printf("T2I mal %d %p\n", wid, ret->data[0]);
algarray[alg].copy(wid, ret->data[0], elem); algarray[alg].copy(wid, ret->data[0], elem);
} }
if(debug) { if(iface_debug) {
prints("T2I ret="); prints("T2I ret=");
printiface(*ret); printiface(*ret);
prints("\n"); prints("\n");
...@@ -244,7 +244,7 @@ sys·ifaceI2T(Sigt *st, Iface i, ...) ...@@ -244,7 +244,7 @@ sys·ifaceI2T(Sigt *st, Iface i, ...)
ret = (byte*)(&i+1); ret = (byte*)(&i+1);
if(debug) { if(iface_debug) {
prints("I2T sigt="); prints("I2T sigt=");
printsigt(st); printsigt(st);
prints(" iface="); prints(" iface=");
...@@ -277,7 +277,7 @@ sys·ifaceI2T(Sigt *st, Iface i, ...) ...@@ -277,7 +277,7 @@ sys·ifaceI2T(Sigt *st, Iface i, ...)
else else
algarray[alg].copy(wid, ret, i.data[0]); algarray[alg].copy(wid, ret, i.data[0]);
if(debug) { if(iface_debug) {
prints("I2T ret="); prints("I2T ret=");
sys·printpointer(*(void**)ret); sys·printpointer(*(void**)ret);
prints("\n"); prints("\n");
...@@ -299,7 +299,7 @@ sys·ifaceI2T2(Sigt *st, Iface i, ...) ...@@ -299,7 +299,7 @@ sys·ifaceI2T2(Sigt *st, Iface i, ...)
wid = st->offset; wid = st->offset;
ok = (bool*)(ret+rnd(wid, 8)); ok = (bool*)(ret+rnd(wid, 8));
if(debug) { if(iface_debug) {
prints("I2T2 sigt="); prints("I2T2 sigt=");
printsigt(st); printsigt(st);
prints(" iface="); prints(" iface=");
...@@ -318,7 +318,7 @@ sys·ifaceI2T2(Sigt *st, Iface i, ...) ...@@ -318,7 +318,7 @@ sys·ifaceI2T2(Sigt *st, Iface i, ...)
else else
algarray[alg].copy(wid, ret, i.data[0]); algarray[alg].copy(wid, ret, i.data[0]);
} }
if(debug) { if(iface_debug) {
prints("I2T2 ret="); prints("I2T2 ret=");
sys·printpointer(*(void**)ret); sys·printpointer(*(void**)ret);
sys·printbool(*ok); sys·printbool(*ok);
...@@ -333,7 +333,7 @@ sys·ifaceI2I(Sigi *si, Iface i, Iface ret) ...@@ -333,7 +333,7 @@ sys·ifaceI2I(Sigi *si, Iface i, Iface ret)
Itype *im; Itype *im;
int32 j; int32 j;
if(debug) { if(iface_debug) {
prints("I2I sigi="); prints("I2I sigi=");
printsigi(si); printsigi(si);
prints(" iface="); prints(" iface=");
...@@ -354,7 +354,7 @@ sys·ifaceI2I(Sigi *si, Iface i, Iface ret) ...@@ -354,7 +354,7 @@ sys·ifaceI2I(Sigi *si, Iface i, Iface ret)
ret.type = itype(si, im->sigt, 0); ret.type = itype(si, im->sigt, 0);
} }
if(debug) { if(iface_debug) {
prints("I2I ret="); prints("I2I ret=");
printiface(ret); printiface(ret);
prints("\n"); prints("\n");
...@@ -370,7 +370,7 @@ sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok) ...@@ -370,7 +370,7 @@ sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok)
Itype *im; Itype *im;
int32 j; int32 j;
if(debug) { if(iface_debug) {
prints("I2I2 sigi="); prints("I2I2 sigi=");
printsigi(si); printsigi(si);
prints(" iface="); prints(" iface=");
...@@ -399,7 +399,7 @@ sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok) ...@@ -399,7 +399,7 @@ sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok)
} }
} }
if(debug) { if(iface_debug) {
prints("I2I ret="); prints("I2I ret=");
printiface(ret); printiface(ret);
prints("\n"); prints("\n");
...@@ -415,7 +415,7 @@ sys·ifaceeq(Iface i1, Iface i2, bool ret) ...@@ -415,7 +415,7 @@ sys·ifaceeq(Iface i1, Iface i2, bool ret)
{ {
int32 alg, wid; int32 alg, wid;
if(debug) { if(iface_debug) {
prints("Ieq i1="); prints("Ieq i1=");
printiface(i1); printiface(i1);
prints(" i2="); prints(" i2=");
...@@ -454,7 +454,7 @@ sys·ifaceeq(Iface i1, Iface i2, bool ret) ...@@ -454,7 +454,7 @@ sys·ifaceeq(Iface i1, Iface i2, bool ret)
yes: yes:
ret = true; ret = true;
no: no:
if(debug) { if(iface_debug) {
prints("Ieq ret="); prints("Ieq ret=");
sys·printbool(ret); sys·printbool(ret);
prints("\n"); prints("\n");
......
...@@ -110,7 +110,7 @@ struct String ...@@ -110,7 +110,7 @@ struct String
struct Iface struct Iface
{ {
Itype *type; Itype *type;
void *data[1]; // could make bigger later void *data[1]; // could make bigger later, but must be in sync with compilers
}; };
struct Array struct Array
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment