diff options
Diffstat (limited to 'src/cmd/gc')
-rw-r--r-- | src/cmd/gc/go.h | 5 | ||||
-rw-r--r-- | src/cmd/gc/subr.c | 135 | ||||
-rw-r--r-- | src/cmd/gc/walk.c | 22 |
3 files changed, 43 insertions, 119 deletions
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 025edaad7..7e4e22c87 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -125,6 +125,7 @@ struct Type uchar methptr; // 1=direct 2=pointer uchar printed; uchar embedded; // TFIELD embedded type + uchar siggen; // TFUNCT uchar thistuple; @@ -208,6 +209,7 @@ struct Sym uchar sym; // huffman encoding in object file uchar local; // created in this file uchar uniq; // imbedded field name first found + uchar siggen; // signature generated char* opackage; // original package name char* package; // package name @@ -596,11 +598,10 @@ int isptrdarray(Type*); int isinter(Type*); int isnilinter(Type*); int isddd(Type*); -Sym* globalsig(Type*); Type* ismethod(Type*); Type* methtype(Type*); int needaddr(Type*); -Sym* signame(Type*, int); +Sym* signame(Type*); int bytearraysz(Type*); int eqtype(Type*, Type*, int); void argtype(Node*, Type*); diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 15650c8be..b6e225f81 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -1606,134 +1606,53 @@ iscomposite(Type *t) } Sym* -globalsig(Type *t) +signame(Type *t) { - int et; - Sym *s; - char buf[NSYMB]; - char *sigx; - - if(t == T) - return S; - - et = t->etype; - switch(et) { - default: - return S; - - case TINTER: - case TDDD: - if(isnilinter(t)) { - sigx = "sigi"; - strcpy(buf, "inter"); - goto out; - } - return S; - - case TPTR32: - case TPTR64: - if(isptrto(t, TSTRING)) { - et = TSTRING; - break; - } - return S; - - case TINT: - case TINT8: - case TINT16: - case TINT32: - case TINT64: - - case TUINT: - case TUINT8: - case TUINT16: - case TUINT32: - case TUINT64: - case TUINTPTR: - - case TFLOAT: - case TFLOAT32: - case TFLOAT64: - case TFLOAT80: - - case TBOOL: - break; - } - if(t->sym == S) - return S; - if(t->method != T) - return S; - if(strcmp(t->sym->name, types[et]->sym->name) != 0) - return S; - sigx = "sigt"; - snprint(buf, sizeof(buf), "%#T", t); - -out: - s = pkglookup(buf, sigx); - if(s->oname == N) { - s->oname = newname(s); - s->oname->type = types[TUINT8]; - s->oname->class = PEXTERN; - s->local = s->local; - } -//print("*** %lT %lS\n", t, s); - return s; -} - -Sym* -signame(Type *t, int block) -{ - Sym *s, *ss; + Sym *ss; char *e; Dcl *x; char buf[NSYMB]; +//print("signame %T\n", t); if(t == T) goto bad; - ss = globalsig(t); - if(ss != S) - return ss; - - s = t->sym; - if(s == S) { - if(isptr[t->etype]) { - t = t->type; - if(t == T) - goto bad; - } - s = t->sym; - if(s == S) - goto bad; - } - e = "sigt"; if(t->etype == TINTER) e = "sigi"; - if(block == 0) - block = s->tblock; - - if(block > 1) { - // record internal type for signature generation - x = mal(sizeof(*x)); - x->op = OTYPE; - x->dsym = s; - x->dtype = s->otype; - x->forw = signatlist; - x->block = block; - signatlist = x; - } + // name is exported name, like *[]byte or *Struct or Interface + // (special symbols don't bother the linker). snprint(buf, sizeof(buf), "%#T", t); + + // special case: empty interface is named sigi.empty + // so that it can be referred to by the runtime. + if(strcmp(buf, "interface { }") == 0) + strcpy(buf, "empty"); + ss = pkglookup(buf, e); if(ss->oname == N) { ss->oname = newname(ss); ss->oname->type = types[TUINT8]; ss->oname->class = PEXTERN; - ss->local = s->local; -//print("signame: %d %lS\n", ss->local, ss); } + if(!t->siggen) { +//print("siggen %T\n", t); + // special case: don't generate the empty interface + if(strcmp(buf, "empty") == 0) + goto out; + + // record internal type for signature generation + x = mal(sizeof(*x)); + x->op = OTYPE; + x->dtype = t; + x->forw = signatlist; + t->siggen = 1; + signatlist = x; + } + +out: return ss; bad: diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index f0627d4f5..ceae4480a 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -919,10 +919,10 @@ loop: nnew = nod(ONEW, N, N); nnew->type = nvar->type; nnew = newcompat(nnew); - + nas = nod(OAS, nvar, nnew); addtop = list(addtop, nas); - + nas = nod(OAS, nod(OIND, nvar, N), n->left); addtop = list(addtop, nas); @@ -1761,7 +1761,7 @@ loop: return N; } -more: + a = nod(OAS, nodarg(l, fp), r); a = convas(a); nn = list(a, nn); @@ -1786,6 +1786,8 @@ ascompat(Type *t1, Type *t2) // if(eqtype(t2, nilptr, 0)) // return 1; + if(isnilinter(t1)) + return 1; if(isinter(t1)) { if(isinter(t2)) return 1; @@ -1793,6 +1795,8 @@ ascompat(Type *t1, Type *t2) return 1; } + if(isnilinter(t2)) + return 1; if(isinter(t2)) if(ismethod(t1)) return 1; @@ -2649,13 +2653,13 @@ isandss(Type *lt, Node *r) return I2I; return Inone; } - if(ismethod(rt) != T) + if(isnilinter(lt) || ismethod(rt) != T) return T2I; return Inone; } if(isinter(rt)) { - if(ismethod(lt) != T) + if(isnilinter(rt) || ismethod(lt) != T) return I2T; return Inone; } @@ -2682,7 +2686,7 @@ ifaceop(Type *tl, Node *n, int op) a = n; // interface r = a; - s = signame(tl, 0); // sigi + s = signame(tl); // sigi if(s == S) fatal("ifaceop: signame I2T"); a = s->oname; @@ -2701,14 +2705,14 @@ ifaceop(Type *tl, Node *n, int op) a = n; // elem r = a; - s = signame(tr, 0); // sigt + s = signame(tr); // sigt if(s == S) fatal("ifaceop: signame-1 T2I: %lT", tr); a = s->oname; a = nod(OADDR, a, N); r = list(a, r); - s = signame(tl, 0); // sigi + s = signame(tl); // sigi if(s == S) { fatal("ifaceop: signame-2 T2I: %lT", tl); } @@ -2728,7 +2732,7 @@ ifaceop(Type *tl, Node *n, int op) a = n; // interface r = a; - s = signame(tl, 0); // sigi + s = signame(tl); // sigi if(s == S) fatal("ifaceop: signame I2I"); a = s->oname; |