newplist();
dumpglobls();
- dumpsignatures();
+ dumptypestructs();
dumpdata();
dumpfuncs();
{
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;
-}
-
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "go.h"
+
+/*
+ * runtime interface and reflection data structures
+ */
+
+static Sym* dtypesym(Type*);
+
+static int
+sigcmp(Sig *a, Sig *b)
+{
+ return strcmp(a->name, b->name);
+}
+
+static 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;
+}
+
+/*
+ * f is method type, with receiver.
+ * return function type, receiver as first argument.
+ */
+static Type*
+methodfunc(Type *f)
+{
+ Node *in, *out, *d;
+ Type *t;
+
+ in = N;
+ if(!isifacemethod(f)) {
+ d = nod(ODCLFIELD, N, N);
+ d->type = getthisx(f->type)->type->type;
+ in = list(in, d);
+ }
+ for(t=getinargx(f->type)->type; t; t=t->down) {
+ d = nod(ODCLFIELD, N, N);
+ d->type = t->type;
+ in = list(in, d);
+ }
+
+ out = N;
+ for(t=getoutargx(f->type)->type; t; t=t->down) {
+ d = nod(ODCLFIELD, N, N);
+ d->type = t->type;
+ out = list(out, d);
+ }
+
+ return functype(N, rev(in), rev(out));
+}
+
+/*
+ * return methods of non-interface type t,
+ * sorted by hash.
+ * generates stub functions as needed.
+ */
+static Sig*
+methods(Type *t)
+{
+ int o;
+ Type *f, *mt, *it, *this;
+ Sig *a, *b;
+ Sym *method;
+ Prog *oldlist;
+
+ // named method type
+ mt = methtype(t);
+ if(mt == T)
+ return nil;
+ expandmeth(mt->sym, mt);
+
+ // type stored in interface word
+ it = t;
+ if(it->width > widthptr)
+ it = ptrto(t);
+
+ // make list of methods for t,
+ // generating code if necessary.
+ a = nil;
+ o = 0;
+ oldlist = nil;
+ for(f=mt->method; f; f=f->down) {
+ if(f->type->etype != TFUNC)
+ continue;
+ if(f->etype != TFIELD)
+ fatal("methods: not field");
+ method = f->sym;
+ if(method == nil)
+ continue;
+
+ // get receiver type for this particular method.
+ // if pointer receiver but non-pointer t and
+ // this is not an embedded pointer inside a struct,
+ // method does not apply.
+ this = getthisx(f->type)->type->type;
+ if(isptr[this->etype] && !isptr[t->etype]
+ && f->embedded != 2 && !isifacemethod(f))
+ 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->package = method->package;
+ a->hash += PRIME10*stringhash(a->package);
+ }
+ a->perm = o++;
+ a->isym = methodsym(method, it);
+ a->tsym = methodsym(method, t);
+ a->type = methodfunc(f);
+
+ if(!a->isym->siggen) {
+ a->isym->siggen = 1;
+ if(!eqtype(this, it)) {
+ if(oldlist == nil)
+ oldlist = pc;
+ // Is 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(isptr[it->etype] && isptr[this->etype]
+ && f->embedded && !isifacemethod(f))
+ genembedtramp(it, f, a->isym);
+ else
+ genwrapper(it, f, a->isym);
+ }
+ }
+
+ if(!a->tsym->siggen) {
+ a->tsym->siggen = 1;
+ if(!eqtype(this, t)) {
+ if(oldlist == nil)
+ oldlist = pc;
+ if(isptr[it->etype] && isptr[this->etype]
+ && f->embedded && !isifacemethod(f))
+ genembedtramp(t, f, a->tsym);
+ else
+ genwrapper(t, f, a->tsym);
+ }
+ }
+ }
+
+ // 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();
+ }
+
+ return lsort(a, sigcmp);
+}
+
+/*
+ * return methods of interface type t, sorted by hash.
+ */
+Sig*
+imethods(Type *t)
+{
+ Sig *a, *b;
+ int o;
+ Type *f;
+
+ a = nil;
+ o = 0;
+ for(f=t->type; f; f=f->down) {
+ if(f->etype != TFIELD)
+ fatal("imethods: not field");
+ if(f->type->etype != TFUNC || f->sym == nil)
+ continue;
+ b = mal(sizeof(*b));
+ b->link = a;
+ a = b;
+
+ a->name = f->sym->name;
+ a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0, 0);
+ if(!exportname(a->name)) {
+ a->package = f->sym->package;
+ a->hash += PRIME10*stringhash(a->package);
+ }
+ a->perm = o++;
+ a->offset = 0;
+ a->type = methodfunc(f);
+ }
+
+ return lsort(a, sigcmp);
+}
+
+/*
+ * uncommonType
+ * ../../pkg/runtime/type.go:/uncommonType
+ */
+static Sym*
+dextratype(Type *t)
+{
+ int ot, n;
+ char *p;
+ Sym *s;
+ Sig *a, *m;
+
+ m = methods(t);
+ if(t->sym == nil && m == nil)
+ return nil;
+
+ n = 0;
+ for(a=m; a; a=a->link) {
+ dtypesym(a->type);
+ n++;
+ }
+
+ p = smprint("%#-T", t);
+ s = pkglookup(p, "extratype");
+ ot = 0;
+ if(t->sym) {
+ ot = dgostringptr(s, ot, t->sym->name);
+ if(t != types[t->etype])
+ ot = dgostringptr(s, ot, t->sym->package);
+ else
+ ot = dgostringptr(s, ot, nil);
+ } else {
+ ot = dgostringptr(s, ot, nil);
+ ot = dgostringptr(s, ot, nil);
+ }
+
+ // slice header
+ ot = dsymptr(s, ot, s, ot + widthptr + 2*4);
+ ot = duint32(s, ot, n);
+ ot = duint32(s, ot, n);
+
+ // methods
+ for(a=m; a; a=a->link) {
+ // method
+ // ../../pkg/runtime/type.go:/method
+ ot = duint32(s, ot, a->hash);
+ ot = rnd(ot, widthptr);
+ ot = dgostringptr(s, ot, a->name);
+ ot = dgostringptr(s, ot, a->package);
+ ot = dsymptr(s, ot, dtypesym(a->type), 0);
+ if(a->isym)
+ ot = dsymptr(s, ot, a->isym, 0);
+ else
+ ot = duintptr(s, ot, 0);
+ if(a->tsym)
+ ot = dsymptr(s, ot, a->tsym, 0);
+ else
+ ot = duintptr(s, ot, 0);
+ }
+ ggloblsym(s, ot, 1);
+
+ return s;
+}
+
+static char*
+structnames[] =
+{
+ [TINT] = "*runtime.IntType",
+ [TUINT] = "*runtime.UintType",
+ [TINT8] = "*runtime.Int8Type",
+ [TUINT8] = "*runtime.Uint8Type",
+ [TINT16] = "*runtime.Int16Type",
+ [TUINT16] = "*runtime.Uint16Type",
+ [TINT32] = "*runtime.Int32Type",
+ [TUINT32] = "*runtime.Uint32Type",
+ [TINT64] = "*runtime.Int64Type",
+ [TUINT64] = "*runtime.Uint64Type",
+ [TUINTPTR] = "*runtime.UintptrType",
+ [TFLOAT] = "*runtime.FloatType",
+ [TFLOAT32] = "*runtime.Float32Type",
+ [TFLOAT64] = "*runtime.Float64Type",
+ [TBOOL] = "*runtime.BoolType",
+ [TSTRING] = "*runtime.StringType",
+ [TDDD] = "*runtime.DotDotDotType",
+
+ [TPTR32] = "*runtime.PtrType",
+ [TPTR64] = "*runtime.PtrType",
+ [TSTRUCT] = "*runtime.StructType",
+ [TINTER] = "*runtime.InterfaceType",
+ [TCHAN] = "*runtime.ChanType",
+ [TMAP] = "*runtime.MapType",
+ [TARRAY] = "*runtime.ArrayType",
+ [TFUNC] = "*runtime.FuncType",
+};
+
+static Sym*
+typestruct(Type *t)
+{
+ char *name;
+ int et;
+
+ et = t->etype;
+ if(et < 0 || et >= nelem(structnames) || (name = structnames[et]) == nil) {
+ fatal("typestruct %lT", t);
+ return nil; // silence gcc
+ }
+
+ if(isslice(t))
+ name = "*runtime.SliceType";
+
+ if(isptr[et] && t->type->etype == TANY)
+ name = "*runtime.UnsafePointerType";
+
+ return pkglookup(name, "type");
+}
+
+/*
+ * commonType
+ * ../../pkg/runtime/type.go:/commonType
+ */
+static int
+dcommontype(Sym *s, int ot, Type *t)
+{
+ int i;
+ Sym *s1;
+ Type *elem;
+ char *p;
+
+ s1 = dextratype(t);
+
+ // empty interface pointing at this type.
+ // all the references that we emit are *interface{};
+ // they point here.
+ ot = rnd(ot, widthptr);
+ ot = dsymptr(s, ot, typestruct(t), 0);
+ ot = dsymptr(s, ot, s, 2*widthptr);
+
+ // ../../pkg/runtime/type.go:/commonType
+ // actual type structure
+ // type commonType struct {
+ // size uintptr;
+ // hash uint32;
+ // alg uint8;
+ // align uint8;
+ // fieldAlign uint8;
+ // string *string;
+ // *nameInfo;
+ // }
+ ot = duintptr(s, ot, t->width);
+ ot = duint32(s, ot, typehash(t, 1, 0));
+ ot = duint8(s, ot, algtype(t));
+ elem = t;
+ while(elem->etype == TARRAY && elem->bound >= 0)
+ elem = elem->type;
+ i = elem->width;
+ if(i > maxround)
+ i = maxround;
+ ot = duint8(s, ot, i); // align
+ ot = duint8(s, ot, i); // fieldAlign
+ p = smprint("%#-T", t);
+ ot = dgostringptr(s, ot, p); // string
+ free(p);
+ if(s1)
+ ot = dsymptr(s, ot, s1, 0); // extraType
+ else
+ ot = duintptr(s, ot, 0);
+
+ return ot;
+}
+
+Sym*
+typesym(Type *t)
+{
+ char *p;
+ Sym *s;
+
+ p = smprint("%#-T", t);
+ s = pkglookup(p, "type");
+ free(p);
+ return s;
+}
+
+Node*
+typename(Type *t)
+{
+ Sym *s;
+ Node *n;
+ Dcl *d;
+
+ s = typesym(t);
+ if(s->def == N) {
+ n = nod(ONAME, N, N);
+ n->sym = s;
+ n->type = types[TUINT8];
+ n->addable = 1;
+ n->ullman = 1;
+ n->class = PEXTERN;
+ n->xoffset = 0;
+ s->def = n;
+
+ // copy to signatlist
+ d = dcl();
+ d->dsym = s;
+ d->dtype = t;
+ d->op = OTYPE;
+ d->forw = signatlist;
+ signatlist = d;
+ }
+
+ n = nod(OADDR, s->def, N);
+ n->type = ptrto(s->def->type);
+ n->addable = 1;
+ n->ullman = 2;
+ return n;
+}
+
+Sym*
+dtypesym(Type *t)
+{
+ int ot, n;
+ Sym *s, *s1, *s2;
+ Sig *a, *m;
+ Type *t1;
+
+ s = typesym(t);
+ if(s->siggen)
+ return s;
+ s->siggen = 1;
+
+ // special case (look for runtime below):
+ // when compiling package runtime,
+ // emit the type structures for int, float, etc.
+ t1 = T;
+ if(isptr[t->etype])
+ t1 = t->type;
+
+ if(strcmp(package, "runtime") == 0) {
+ if(t == types[t->etype])
+ goto ok;
+ if(t1 && t1 == types[t1->etype])
+ goto ok;
+ }
+
+ // named types from other files are defined in those files
+ if(t->sym && !t->local)
+ return s;
+ if(!t->sym && t1 && t1->sym && !t1->local)
+ return s;
+ if(isforw[t->etype] || (t1 && isforw[t1->etype]))
+ return s;
+
+ok:
+ ot = 0;
+ switch(t->etype) {
+ default:
+ ot = dcommontype(s, ot, t);
+ break;
+
+ case TARRAY:
+ // ../../pkg/runtime/type.go:/ArrayType
+ s1 = dtypesym(t->type);
+ ot = dcommontype(s, ot, t);
+ ot = dsymptr(s, ot, s1, 0);
+ if(t->bound < 0)
+ ot = duintptr(s, ot, -1);
+ else
+ ot = duintptr(s, ot, t->bound);
+ break;
+
+ case TCHAN:
+ // ../../pkg/runtime/type.go:/ChanType
+ s1 = dtypesym(t->type);
+ ot = dcommontype(s, ot, t);
+ ot = dsymptr(s, ot, s1, 0);
+ ot = duintptr(s, ot, t->chan);
+ break;
+
+ case TFORWSTRUCT:
+ case TFORWINTER:
+ return s;
+
+ case TFUNC:
+ for(t1=getthisx(t)->type; t1; t1=t1->down)
+ dtypesym(t1->type);
+ for(t1=getinargx(t)->type; t1; t1=t1->down)
+ dtypesym(t1->type);
+ for(t1=getoutargx(t)->type; t1; t1=t1->down)
+ dtypesym(t1->type);
+
+ ot = dcommontype(s, ot, t);
+
+ // two slice headers: in and out.
+ ot = dsymptr(s, ot, s, ot+2*(widthptr+2*4));
+ n = t->thistuple + t->intuple;
+ ot = duint32(s, ot, n);
+ ot = duint32(s, ot, n);
+ ot = dsymptr(s, ot, s, ot+1*(widthptr+2*4)+n*widthptr);
+ ot = duint32(s, ot, t->outtuple);
+ ot = duint32(s, ot, t->outtuple);
+
+ // slice data
+ for(t1=getthisx(t)->type; t1; t1=t1->down, n++)
+ ot = dsymptr(s, ot, dtypesym(t1->type), 0);
+ for(t1=getinargx(t)->type; t1; t1=t1->down, n++)
+ ot = dsymptr(s, ot, dtypesym(t1->type), 0);
+ for(t1=getoutargx(t)->type; t1; t1=t1->down, n++)
+ ot = dsymptr(s, ot, dtypesym(t1->type), 0);
+ break;
+
+ case TINTER:
+ m = imethods(t);
+ n = 0;
+ for(a=m; a; a=a->link) {
+ dtypesym(a->type);
+ n++;
+ }
+
+ // ../../pkg/runtime/type.go:/InterfaceType
+ ot = dcommontype(s, ot, t);
+ ot = dsymptr(s, ot, s, ot+widthptr+2*4);
+ ot = duint32(s, ot, n);
+ ot = duint32(s, ot, n);
+ for(a=m; a; a=a->link) {
+ // ../../pkg/runtime/type.go:/imethod
+ ot = duint32(s, ot, a->hash);
+ ot = duint32(s, ot, a->perm);
+ ot = dgostringptr(s, ot, a->name);
+ ot = dgostringptr(s, ot, a->package);
+ ot = dsymptr(s, ot, dtypesym(a->type), 0);
+ }
+ break;
+
+ case TMAP:
+ // ../../pkg/runtime/type.go:/MapType
+ s1 = dtypesym(t->down);
+ s2 = dtypesym(t->type);
+ ot = dcommontype(s, ot, t);
+ ot = dsymptr(s, ot, s1, 0);
+ ot = dsymptr(s, ot, s2, 0);
+ break;
+
+ case TPTR32:
+ case TPTR64:
+ if(t->type->etype == TANY) {
+ ot = dcommontype(s, ot, t);
+ break;
+ }
+ // ../../pkg/runtime/type.go:/PtrType
+ s1 = dtypesym(t->type);
+ ot = dcommontype(s, ot, t);
+ ot = dsymptr(s, ot, s1, 0);
+ break;
+
+ case TSTRUCT:
+ // ../../pkg/runtime/type.go:/StructType
+ // for security, only the exported fields.
+ n = 0;
+ for(t1=t->type; t1!=T; t1=t1->down) {
+ dtypesym(t1->type);
+ n++;
+ }
+ ot = dcommontype(s, ot, t);
+ ot = dsymptr(s, ot, s, ot+widthptr+2*4);
+ ot = duint32(s, ot, n);
+ ot = duint32(s, ot, n);
+ for(t1=t->type; t1!=T; t1=t1->down) {
+ // ../../pkg/runtime/type.go:/structField
+ if(t1->sym) {
+ ot = dgostringptr(s, ot, t1->sym->name);
+ if(exportname(t1->sym->name))
+ ot = dgostringptr(s, ot, nil);
+ else
+ ot = dgostringptr(s, ot, t1->sym->package);
+ } else {
+ ot = dgostringptr(s, ot, nil);
+ ot = dgostringptr(s, ot, nil);
+ }
+ ot = dsymptr(s, ot, dtypesym(t1->type), 0);
+ ot = dgostrlitptr(s, ot, t1->note);
+ ot = duintptr(s, ot, t1->width); // field offset
+ }
+ break;
+ }
+
+ ggloblsym(s, ot, 1);
+ return s;
+}
+
+void
+dumptypestructs(void)
+{
+ int i;
+ Dcl *d, *x;
+ Type *t;
+
+ // copy types from externdcl list to signatlist
+ for(d=externdcl; d!=D; d=d->forw) {
+ if(d->op != OTYPE)
+ continue;
+ t = d->dtype;
+ x = mal(sizeof(*x));
+ x->op = OTYPE;
+ x->dtype = t;
+ x->forw = signatlist;
+ x->block = 0;
+ signatlist = x;
+ }
+
+ // process signatlist
+ for(d=signatlist; d!=D; d=d->forw) {
+ if(d->op != OTYPE)
+ continue;
+ t = d->dtype;
+ dtypesym(t);
+ if(t->sym && !isptr[t->etype])
+ dtypesym(ptrto(t));
+ }
+
+ // do basic types if compiling package runtime, type.go.
+ // they have to be in at least one package,
+ // and reflect is always loaded implicitly,
+ // so this is as good as any.
+ // another possible choice would be package main,
+ // but using runtime means fewer copies in .6 files.
+ if(strcmp(package, "runtime") == 0 && strcmp(filename, "type") == 0) {
+ for(i=1; i<=TBOOL; i++)
+ if(i != TFLOAT80)
+ dtypesym(ptrto(types[i]));
+ dtypesym(ptrto(types[TSTRING]));
+ dtypesym(typ(TDDD));
+ dtypesym(ptrto(pkglookup("Pointer", "unsafe")->def->type));
+ }
+}