summaryrefslogtreecommitdiff
path: root/src/cmd/6g/obj.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2008-11-05 11:27:50 -0800
committerRuss Cox <rsc@golang.org>2008-11-05 11:27:50 -0800
commitf93e9122d55a438ef33e00d99f90d157e39c0e8a (patch)
treef3c233209ab5131760a45e54f4314388b4cfe1cc /src/cmd/6g/obj.c
parente5c26e215de8a476f735265abbe36a77e2501479 (diff)
downloadgolang-f93e9122d55a438ef33e00d99f90d157e39c0e8a.tar.gz
6g interface changes:
* allow conversion between nil interface and any type. * mark signatures as DUPOK so that multiple .6 can contain sigt.*[]byte and only one gets used. R=ken OCL=18538 CL=18542
Diffstat (limited to 'src/cmd/6g/obj.c')
-rw-r--r--src/cmd/6g/obj.c403
1 files changed, 182 insertions, 221 deletions
diff --git a/src/cmd/6g/obj.c b/src/cmd/6g/obj.c
index 8b2a47c24..20763cf38 100644
--- a/src/cmd/6g/obj.c
+++ b/src/cmd/6g/obj.c
@@ -516,7 +516,6 @@ gentramp(Type *t, Sig *b)
int c, d, o;
Prog *p;
Type *f;
- Sym *msym;
e = lookup(b->name);
for(d=0; d<nelem(dotlist); d++) {
@@ -596,292 +595,213 @@ out:
}
void
-dumpsigt(void)
+dumpsigt(Type *t0, Sym *s)
{
- Dcl *d, *x;
- Type *t, *f;
- Sym *s1, *s;
- int et, o;
+ Type *f, *t;
+ Sym *s1;
+ int o;
Sig *a, *b;
Prog *p;
- char *sp;
char buf[NSYMB];
- /*
- * put all the names into a linked
- * list so that it may be generated in sorted order.
- * the runtime will be linear rather than quadradic
- */
- for(d=signatlist; d!=D; d=d->forw) {
- if(d->op != OTYPE)
- continue;
- t = d->dtype;
- et = t->etype;
- if(et == TINTER)
- continue;
- at.sym = signame(t, d->block);
- if(at.sym == S)
- continue;
+ at.sym = s;
- // make unique
- if(at.sym->local != 1)
- continue;
- at.sym->local = 2;
+ t = t0;
+ if(isptr[t->etype] && t->type->sym != S) {
+ t = t->type;
+ expandmeth(t->sym, t);
+ }
- s = d->dsym;
- if(s == S)
+ a = nil;
+ o = 0;
+ for(f=t->method; f!=T; f=f->down) {
+ if(f->type->etype != TFUNC)
continue;
- if(s->name[0] == '_')
- continue;
+ if(f->etype != TFIELD)
+ fatal("dumpsignatures: not field");
- if(strcmp(s->opackage, package) != 0)
+ s1 = f->sym;
+ if(s1 == nil)
continue;
- expandmeth(s, t);
-
- a = nil;
- o = 0;
- for(f=t->method; f!=T; f=f->down) {
- if(f->type->etype != TFUNC)
- continue;
-
- if(f->etype != TFIELD)
- fatal("dumpsignatures: not field");
-
- s1 = f->sym;
- if(s1 == nil)
- continue;
-
- b = mal(sizeof(*b));
- b->link = a;
- a = b;
+ b = mal(sizeof(*b));
+ b->link = a;
+ a = b;
- a->name = s1->name;
- a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
- a->perm = o;
- a->sym = methodsym(f->sym, t);
- a->offset = f->embedded; // need trampoline
+ a->name = s1->name;
+ a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
+ a->perm = o;
+ a->sym = methodsym(f->sym, t);
+ a->offset = f->embedded; // need trampoline
- o++;
- }
-
- a = lsort(a, sigcmp);
- ot = 0;
- ot = rnd(ot, maxround); // base structure
-
- // sigi[0].name = ""
- ginsatoa(widthptr, stringo);
-
- // save type name for runtime error message.
- // TODO(rsc): the * is a botch but right more often than not.
- snprint(buf, sizeof buf, "*%#T", t);
- datastring(buf, strlen(buf)+1);
+ o++;
+ }
- // first field of an type signature contains
- // the element parameters and is not a real entry
+ a = lsort(a, sigcmp);
+ ot = 0;
+ ot = rnd(ot, maxround); // base structure
- t = d->dtype;
- if(t->methptr & 2)
- t = types[tptr];
+ // sigi[0].name = ""
+ ginsatoa(widthptr, stringo);
- // sigi[0].hash = elemalg
- gensatac(wi, algtype(t));
+ // save type name for runtime error message.
+ snprint(buf, sizeof buf, "%#T", t0);
+ datastring(buf, strlen(buf)+1);
- // sigi[0].offset = width
- gensatac(wi, t->width);
+ // first field of an type signature contains
+ // the element parameters and is not a real entry
+ if(t->methptr & 2)
+ t = types[tptr];
- // skip the function
- gensatac(widthptr, 0);
+ // sigi[0].hash = elemalg
+ gensatac(wi, algtype(t));
- for(b=a; b!=nil; b=b->link) {
- ot = rnd(ot, maxround); // base structure
+ // sigi[0].offset = width
+ gensatac(wi, t->width);
- // sigx[++].name = "fieldname"
- ginsatoa(widthptr, stringo);
+ // skip the function
+ gensatac(widthptr, 0);
- // sigx[++].hash = hashcode
- gensatac(wi, b->hash);
+ for(b=a; b!=nil; b=b->link) {
+ ot = rnd(ot, maxround); // base structure
- // sigt[++].offset = of embeded struct
- gensatac(wi, 0);
+ // sigx[++].name = "fieldname"
+ ginsatoa(widthptr, stringo);
- // sigt[++].fun = &method
- gensatad(b->sym);
+ // sigx[++].hash = hashcode
+ gensatac(wi, b->hash);
- datastring(b->name, strlen(b->name)+1);
+ // sigt[++].offset = of embeded struct
+ gensatac(wi, 0);
- if(b->offset)
- gentramp(d->dtype, b);
- }
+ // sigt[++].fun = &method
+ gensatad(b->sym);
- // nil field name at end
- ot = rnd(ot, maxround);
- gensatac(widthptr, 0);
+ datastring(b->name, strlen(b->name)+1);
- p = pc;
- gins(AGLOBL, N, N);
- p->from = at;
- p->to = ac;
- p->to.offset = ot;
+ if(b->offset)
+ gentramp(t0, b);
}
- if(stringo > 0) {
- p = pc;
- gins(AGLOBL, N, N);
- p->from = ao;
- p->to = ac;
- p->to.offset = stringo;
- }
+ // nil field name at end
+ ot = rnd(ot, maxround);
+ gensatac(widthptr, 0);
+ // set DUPOK to allow other .6s to contain
+ // the same signature. only one will be chosen.
+ p = pc;
+ gins(AGLOBL, N, N);
+ p->from = at;
+ p->from.scale = DUPOK;
+ p->to = ac;
+ p->to.offset = ot;
}
void
-dumpsigi(void)
+dumpsigi(Type *t, Sym *s)
{
- Dcl *d, *x;
- Type *t, *f;
- Sym *s1, *s;
- int et, o;
+ Type *f;
+ Sym *s1;
+ int o;
Sig *a, *b;
Prog *p;
char *sp;
char buf[NSYMB];
- /*
- * put all the names into a linked
- * list so that it may be generated in sorted order.
- * the runtime will be linear rather than quadradic
- */
-
- for(d=signatlist; d!=D; d=d->forw) {
- if(d->op != OTYPE)
- continue;
+ at.sym = s;
- t = d->dtype;
- et = t->etype;
- if(et != TINTER)
+ a = nil;
+ o = 0;
+ for(f=t->type; f!=T; f=f->down) {
+ if(f->type->etype != TFUNC)
continue;
- at.sym = signame(t, d->block);
- if(at.sym == S)
- continue;
+ if(f->etype != TFIELD)
+ fatal("dumpsignatures: not field");
- // make unique
- if(at.sym->local != 1)
+ s1 = f->sym;
+ if(s1 == nil)
continue;
- at.sym->local = 2;
-
- s = d->dsym;
- if(s == S)
+ if(s1->name[0] == '_')
continue;
- if(s->name[0] == '_')
- continue;
+ b = mal(sizeof(*b));
+ b->link = a;
+ a = b;
- if(strcmp(s->opackage, package) != 0)
- continue;
+ a->name = s1->name;
+ sp = strchr(s1->name, '_');
+ if(sp != nil)
+ a->name = sp+1;
-//print("sigi: %S\n", s);
+ a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
+ a->perm = o;
+ a->sym = methodsym(f->sym, t);
+ a->offset = 0;
- a = nil;
- o = 0;
- for(f=t->type; f!=T; f=f->down) {
- if(f->type->etype != TFUNC)
- continue;
-
- if(f->etype != TFIELD)
- fatal("dumpsignatures: not field");
-
- s1 = f->sym;
- if(s1 == nil)
- continue;
- if(s1->name[0] == '_')
- continue;
-
- b = mal(sizeof(*b));
- b->link = a;
- a = b;
-
- a->name = s1->name;
- sp = strchr(s1->name, '_');
- if(sp != nil)
- a->name = sp+1;
-
- a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
- a->perm = o;
- a->sym = methodsym(f->sym, t);
- a->offset = 0;
-
- o++;
- }
+ o++;
+ }
- a = lsort(a, sigcmp);
- ot = 0;
- ot = rnd(ot, maxround); // base structure
+ a = lsort(a, sigcmp);
+ ot = 0;
+ ot = rnd(ot, maxround); // base structure
- // sigi[0].name = ""
- ginsatoa(widthptr, stringo);
+ // sigi[0].name = ""
+ ginsatoa(widthptr, stringo);
- // save type name for runtime error message.
- // TODO(rsc): the * is a botch but right more often than not.
- snprint(buf, sizeof buf, "%#T", t);
- datastring(buf, strlen(buf)+1);
+ // save type name for runtime error message.
+ snprint(buf, sizeof buf, "%#T", t);
+ datastring(buf, strlen(buf)+1);
- // first field of an interface signature
- // contains the count and is not a real entry
+ // first field of an interface signature
+ // contains the count and is not a real entry
- // sigi[0].hash = 0
- gensatac(wi, 0);
+ // sigi[0].hash = 0
+ gensatac(wi, 0);
- // sigi[0].offset = count
- o = 0;
- for(b=a; b!=nil; b=b->link)
- o++;
- gensatac(wi, o);
+ // sigi[0].offset = count
+ o = 0;
+ for(b=a; b!=nil; b=b->link)
+ o++;
+ gensatac(wi, o);
- for(b=a; b!=nil; b=b->link) {
+ for(b=a; b!=nil; b=b->link) {
//print(" %s\n", b->name);
- ot = rnd(ot, maxround); // base structure
-
- // sigx[++].name = "fieldname"
- ginsatoa(widthptr, stringo);
-
- // sigx[++].hash = hashcode
- gensatac(wi, b->hash);
+ ot = rnd(ot, maxround); // base structure
- // sigi[++].perm = mapped offset of method
- gensatac(wi, b->perm);
+ // sigx[++].name = "fieldname"
+ ginsatoa(widthptr, stringo);
- datastring(b->name, strlen(b->name)+1);
- }
+ // sigx[++].hash = hashcode
+ gensatac(wi, b->hash);
- // nil field name at end
- ot = rnd(ot, maxround);
- gensatac(widthptr, 0);
+ // sigi[++].perm = mapped offset of method
+ gensatac(wi, b->perm);
- p = pc;
- gins(AGLOBL, N, N);
- p->from = at;
- p->to = ac;
- p->to.offset = ot;
+ datastring(b->name, strlen(b->name)+1);
}
- if(stringo > 0) {
- p = pc;
- gins(AGLOBL, N, N);
- p->from = ao;
- p->to = ac;
- p->to.offset = stringo;
- }
+ // nil field name at end
+ ot = rnd(ot, maxround);
+ gensatac(widthptr, 0);
+
+ p = pc;
+ gins(AGLOBL, N, N);
+ p->from = at;
+ p->from.scale = DUPOK;
+ p->to = ac;
+ p->to.offset = ot;
}
void
dumpsignatures(void)
{
+ int et;
Dcl *d, *x;
Type *t;
- Sym *s;
+ Sym *s, *s1;
+ Prog *p;
memset(&at, 0, sizeof(at));
memset(&ao, 0, sizeof(ao));
@@ -923,19 +843,60 @@ dumpsignatures(void)
if(t == T)
continue;
- s = signame(t, 0);
+ s = signame(t);
if(s == S)
continue;
x = mal(sizeof(*d));
x->op = OTYPE;
- x->dsym = d->dsym;
- x->dtype = d->dtype;
+ if(t->etype == TINTER)
+ x->dtype = t;
+ else
+ x->dtype = ptrto(t);
x->forw = signatlist;
x->block = 0;
signatlist = x;
//print("SIG = %lS %lS %lT\n", d->dsym, s, t);
}
- dumpsigi();
- dumpsigt();
+
+ // process signatlist
+ for(d=signatlist; d!=D; d=d->forw) {
+ if(d->op != OTYPE)
+ continue;
+ t = d->dtype;
+ et = t->etype;
+ s = signame(t);
+ if(s == S)
+ continue;
+
+ // only emit one
+ if(s->siggen)
+ continue;
+ s->siggen = 1;
+
+//print("dosig %T\n", t);
+ // don't emit signatures for *NamedStruct or interface if
+ // they were defined by other packages.
+ // (optimization)
+ s1 = S;
+ if(isptr[et] && t->type != T)
+ s1 = t->type->sym;
+ else if(et == TINTER)
+ s1 = t->sym;
+ if(s1 != S && strcmp(s1->opackage, package) != 0)
+ continue;
+
+ if(et == TINTER)
+ dumpsigi(t, s);
+ else
+ dumpsigt(t, s);
+ }
+
+ if(stringo > 0) {
+ p = pc;
+ gins(AGLOBL, N, N);
+ p->from = ao;
+ p->to = ac;
+ p->to.offset = stringo;
+ }
}