summaryrefslogtreecommitdiff
path: root/src/cmd/gc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc')
-rw-r--r--src/cmd/gc/go.h5
-rw-r--r--src/cmd/gc/subr.c135
-rw-r--r--src/cmd/gc/walk.c22
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;