summaryrefslogtreecommitdiff
path: root/src/cmd/gc/obj.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/obj.c')
-rw-r--r--src/cmd/gc/obj.c413
1 files changed, 1 insertions, 412 deletions
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index e43a97383..6bd66d79d 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -28,7 +28,7 @@ dumpobj(void)
newplist();
dumpglobls();
- dumpsignatures();
+ dumptypestructs();
dumpdata();
dumpfuncs();
@@ -169,414 +169,3 @@ duintptr(Sym *s, int off, uint64 v)
{
return duintxx(s, off, v, widthptr);
}
-
-static int
-sigcmp(Sig *a, Sig *b)
-{
- return strcmp(a->name, b->name);
-}
-
-/*
- * 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)
- *
- * memory layout is Sigt struct from iface.c:
- * struct Sigt
- * {
- * byte* name; // name of basic type
- * Sigt* link; // for linking into hash tables
- * uint32 thash; // hash of type
- * uint32 mhash; // hash of methods
- * uint16 width; // width of base type in bytes
- * uint16 alg; // algorithm
- * struct {
- * byte* fname;
- * uint32 fhash; // hash of type
- * uint32 offset; // offset of substruct
- * void (*fun)(void);
- * } meth[1]; // one or more - last name is nil
- * };
- */
-void
-dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s)
-{
- Type *f;
- int o;
- Sig *a, *b;
- char buf[NSYMB];
- Type *this;
- Prog *oldlist;
- Sym *method;
- uint32 sighash;
- int ot;
-
- if(debug['r']) {
- print("dumpsigt progt=%T ifacet=%T rcvrt=%T methodt=%T s=%S\n",
- progt, ifacet, rcvrt, methodt, s);
- }
-
- a = nil;
- o = 0;
- oldlist = nil;
- sighash = typehash(progt, 1, 0);
- for(f=methodt->method; f!=T; f=f->down) {
- if(f->type->etype != TFUNC)
- continue;
-
- if(f->etype != TFIELD)
- fatal("dumpsignatures: not field");
-
- method = f->sym;
- if(method == nil)
- continue;
-
- // get receiver type for this particular method.
- this = getthisx(f->type)->type->type;
- if(f->embedded != 2 && isptr[this->etype] && !isptr[progt->etype] && !isifacemethod(f)) {
- // pointer receiver method but value method set.
- // ignore.
- if(debug['r'])
- print("ignore %T for %T\n", f, progt);
- continue;
- }
-
- b = mal(sizeof(*b));
- b->link = a;
- a = b;
-
- a->name = method->name;
- a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0, 0);
- if(!exportname(a->name))
- a->hash += PRIME10*stringhash(package);
- a->perm = o;
- a->sym = methodsym(method, rcvrt);
-
- sighash = sighash*100003 + a->hash;
-
- if(!a->sym->siggen) {
- a->sym->siggen = 1;
-
- if(!eqtype(this, ifacet)) {
- if(oldlist == nil)
- oldlist = pc;
-
- // It would be okay to call genwrapper here always,
- // but we can generate more efficient code
- // using genembedtramp if all that is necessary
- // is a pointer adjustment and a JMP.
- if(f->embedded && isptr[ifacet->etype] && !isifacemethod(f))
- genembedtramp(ifacet, f, a->sym);
- else
- genwrapper(ifacet, f, a->sym);
- }
- }
- o++;
- }
-
- // restore data output
- if(oldlist) {
- // old list ended with AEND; change to ANOP
- // so that the trampolines that follow can be found.
- nopout(oldlist);
-
- // start new data list
- newplist();
- }
-
- a = lsort(a, sigcmp);
- ot = 0;
- ot = rnd(ot, maxround); // base structure
-
- // base of type signature contains parameters
- snprint(buf, sizeof buf, "%#T", progt);
- ot = dstringptr(s, ot, buf); // name
- ot = duintptr(s, ot, 0); // skip link
- ot = duint32(s, ot, typehash(progt, 1, 0)); // thash
- ot = duint32(s, ot, sighash); // mhash
- ot = duint16(s, ot, progt->width); // width
- ot = duint16(s, ot, algtype(progt)); // algorithm
-
- for(b=a; b!=nil; b=b->link) {
- ot = rnd(ot, maxround); // base of substructure
- ot = dstringptr(s, ot, b->name); // field name
- ot = duint32(s, ot, b->hash); // hash
- ot = duint32(s, ot, 0); // offset
- ot = dsymptr(s, ot, b->sym, 0); // &method
- }
-
- // nil field name at end
- ot = rnd(ot, maxround);
- ot = duintptr(s, ot, 0);
-
- // set DUPOK to allow other .6s to contain
- // the same signature. only one will be chosen.
- // should only happen for empty signatures
- ggloblsym(s, ot, a == nil);
-}
-
-/*
- * memory layout is Sigi struct from iface.c:
- * struct Sigi
- * {
- * byte* name;
- * uint32 hash;
- * uint32 size; // number of methods
- * struct {
- * byte* fname;
- * uint32 fhash;
- * uint32 perm; // location of fun in Sigt
- * } meth[1]; // [size+1] - last name is nil
- * };
- */
-void
-dumpsigi(Type *t, Sym *s)
-{
- Type *f;
- Sym *s1;
- int o;
- Sig *a, *b;
- char buf[NSYMB];
- uint32 sighash;
- int ot;
-
- a = nil;
- o = 0;
- sighash = 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;
-
- b = mal(sizeof(*b));
- b->link = a;
- a = b;
-
- a->name = s1->name;
- a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0, 0);
- if(!exportname(a->name))
- a->hash += PRIME10*stringhash(package);
- a->perm = o;
- a->sym = methodsym(f->sym, t);
- a->offset = 0;
-
- sighash = sighash*100003 + a->hash;
-
- o++;
- }
-
- a = lsort(a, sigcmp);
- ot = 0;
- ot = rnd(ot, maxround); // base structure
-
- // sigi[0].name = type name, for runtime error message
- snprint(buf, sizeof buf, "%#T", t);
- ot = dstringptr(s, ot, buf);
-
- // first field of an interface signature
- // contains the count and is not a real entry
-
- // sigi[0].hash = sighash
- ot = duint32(s, ot, sighash);
-
- // sigi[0].offset = count
- o = 0;
- for(b=a; b!=nil; b=b->link)
- o++;
- ot = duint32(s, ot, o);
-
- for(b=a; b!=nil; b=b->link) {
-//print(" %s\n", b->name);
- ot = rnd(ot, maxround); // base structure
-
- // sigx[++].name = "fieldname"
- // sigx[++].hash = hashcode
- // sigi[++].perm = mapped offset of method
- ot = dstringptr(s, ot, b->name);
- ot = duint32(s, ot, b->hash);
- ot = duint32(s, ot, b->perm);
- }
-
- // nil field name at end
- ot = rnd(ot, maxround);
- ot = duintptr(s, ot, 0);
-
- // TODO(rsc): DUPOK should not be necessary here,
- // and I am a bit worried that it is. If I turn it off,
- // I get multiple definitions for sigi.dotdotdot.
- ggloblsym(s, ot, 1);
-}
-
-void
-dumpsignatures(void)
-{
- int et;
- Dcl *d, *x;
- Type *t, *progt, *methodt, *ifacet, *rcvrt;
- Sym *s;
- Node *n;
-
- // copy externdcl list to signatlist
- for(d=externdcl; d!=D; d=d->forw) {
- if(d->op != OTYPE)
- continue;
-
- t = d->dtype;
- if(t == T)
- continue;
-
- n = signame(t);
- if(n == N || n->sym == S)
- continue;
- s = n->sym;
-
- x = mal(sizeof(*d));
- x->op = OTYPE;
- 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);
- }
-
- // process signatlist
- for(d=signatlist; d!=D; d=d->forw) {
- if(d->op != OTYPE)
- continue;
- t = d->dtype;
- et = t->etype;
- n = signame(t);
-//print("signame %S for %T\n", s, t);
- if(n == N || n->sym == S)
- continue;
- s = n->sym;
-
- // only emit one
- if(s->siggen)
- continue;
- s->siggen = 1;
-
- // interface is easy
- if(et == TINTER || et == TDDD) {
- if(t->sym && !t->local)
- continue;
- dumpsigi(t, s);
- continue;
- }
-
- // non-interface is more complex
- progt = t;
- methodt = t;
- ifacet = t;
- rcvrt = t;
-
- // if there's a pointer, methods are on base.
- methodt = methtype(progt);
- if(methodt == T) {
- // if that failed, go back to progt,
- // assuming we're writing out a signature
- // for a type with no methods
- methodt = progt;
- } else {
- expandmeth(methodt->sym, methodt);
- }
-
- // if ifacet is too wide, the methods will see a pointer.
- if(ifacet->width > widthptr) {
- ifacet = ptrto(progt);
- rcvrt = ptrto(progt);
- }
-
- // 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 duplicate functions.
- // 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;
-
-//print("s=%S\n", s);
- dumpsigt(progt, ifacet, rcvrt, methodt, s);
- }
-}
-
-Sig*
-lsort(Sig *l, int(*f)(Sig*, Sig*))
-{
- Sig *l1, *l2, *le;
-
- if(l == 0 || l->link == 0)
- return l;
-
- l1 = l;
- l2 = l;
- for(;;) {
- l2 = l2->link;
- if(l2 == 0)
- break;
- l2 = l2->link;
- if(l2 == 0)
- break;
- l1 = l1->link;
- }
-
- l2 = l1->link;
- l1->link = 0;
- l1 = lsort(l, f);
- l2 = lsort(l2, f);
-
- /* set up lead element */
- if((*f)(l1, l2) < 0) {
- l = l1;
- l1 = l1->link;
- } else {
- l = l2;
- l2 = l2->link;
- }
- le = l;
-
- for(;;) {
- if(l1 == 0) {
- while(l2) {
- le->link = l2;
- le = l2;
- l2 = l2->link;
- }
- le->link = 0;
- break;
- }
- if(l2 == 0) {
- while(l1) {
- le->link = l1;
- le = l1;
- l1 = l1->link;
- }
- break;
- }
- if((*f)(l1, l2) < 0) {
- le->link = l1;
- le = l1;
- l1 = l1->link;
- } else {
- le->link = l2;
- le = l2;
- l2 = l2->link;
- }
- }
- le->link = 0;
- return l;
-}
-