]> Cypherpunks repositories - gostls13.git/commitdiff
6g, 8g: generate data structures for new reflect interface (CL 31107)
authorRuss Cox <rsc@golang.org>
Tue, 7 Jul 2009 18:03:04 +0000 (11:03 -0700)
committerRuss Cox <rsc@golang.org>
Tue, 7 Jul 2009 18:03:04 +0000 (11:03 -0700)
R=ken
OCL=31122
CL=31278

src/cmd/6g/gobj.c
src/cmd/8g/gobj.c
src/cmd/gc/Makefile
src/cmd/gc/align.c
src/cmd/gc/builtin.c.boot
src/cmd/gc/go.h
src/cmd/gc/obj.c
src/cmd/gc/reflect.c [new file with mode: 0644]
src/cmd/gc/subr.c
src/cmd/gc/unsafe.go
src/cmd/gc/walk.c

index 02dffbe4c5ce618aa76b71030cdc55b3c8828e0a..1d7c07eba02257dfd4d38cdb4b4bf8208bef67e2 100644 (file)
@@ -488,6 +488,46 @@ dstringptr(Sym *s, int off, char *str)
        return off;
 }
 
+int
+dgostrlitptr(Sym *s, int off, Strlit *lit)
+{
+       Prog *p;
+
+       if(lit == nil)
+               return duintptr(s, off, 0);
+
+       off = rnd(off, widthptr);
+       p = gins(ADATA, N, N);
+       p->from.type = D_EXTERN;
+       p->from.index = D_NONE;
+       p->from.sym = s;
+       p->from.offset = off;
+       p->from.scale = widthptr;
+       datagostring(lit, &p->to);
+       p->to.index = p->to.type;
+       p->to.type = D_ADDR;
+       p->to.etype = TINT32;
+       off += widthptr;
+
+       return off;
+}
+
+int
+dgostringptr(Sym *s, int off, char *str)
+{
+       int n;
+       Strlit *lit;
+
+       if(str == nil)
+               return duintptr(s, off, 0);
+
+       n = strlen(str);
+       lit = mal(sizeof *lit + n);
+       strcpy(lit->s, str);
+       lit->len = n;
+       return dgostrlitptr(s, off, lit);
+}
+
 int
 duintxx(Sym *s, int off, uint64 v, int wid)
 {
index 1e20add3fe8e91084409d2b57d833af39ddd223b..96762375f2308912d2d36879d8ff67ac4868d57a 100644 (file)
@@ -486,6 +486,47 @@ dstringptr(Sym *s, int off, char *str)
        return off;
 }
 
+int
+dgostrlitptr(Sym *s, int off, Strlit *lit)
+{
+       Prog *p;
+
+       if(lit == nil)
+               return duintptr(s, off, 0);
+
+       off = rnd(off, widthptr);
+       p = gins(ADATA, N, N);
+       p->from.type = D_EXTERN;
+       p->from.index = D_NONE;
+       p->from.sym = s;
+       p->from.offset = off;
+       p->from.scale = widthptr;
+       datagostring(lit, &p->to);
+       p->to.index = p->to.type;
+       p->to.type = D_ADDR;
+       p->to.etype = TINT32;
+       off += widthptr;
+
+       return off;
+}
+
+int
+dgostringptr(Sym *s, int off, char *str)
+{
+       int n;
+       Strlit *lit;
+
+       if(str == nil)
+               return duintptr(s, off, 0);
+
+       n = strlen(str);
+       lit = mal(sizeof *lit + n);
+       strcpy(lit->s, str);
+       lit->len = n;
+       return dgostrlitptr(s, off, lit);
+}
+
+
 int
 duintxx(Sym *s, int off, uint64 v, int wid)
 {
index e5cabbb37ffcdf62fb34b737717412ee303b10e9..516542dbb008bec6ed6a1ec4ac6252f11a36480b 100644 (file)
@@ -15,6 +15,7 @@ YFILES=\
        go.y\
 
 OFILES=\
+       reflect.$O\
        y.tab.$O\
        lex.$O\
        subr.$O\
index ff974f8d9f5c4fd05fbf88ee80853a92db58a4d8..e142ca9716e2665e62121f74311f182c97d38b4d 100644 (file)
@@ -243,6 +243,10 @@ typeinit(void)
        isptr[TPTR32] = 1;
        isptr[TPTR64] = 1;
 
+       isforw[TFORW] = 1;
+       isforw[TFORWSTRUCT] = 1;
+       isforw[TFORWINTER] = 1;
+
        issigned[TINT] = 1;
        issigned[TINT8] = 1;
        issigned[TINT16] = 1;
index 4096e18ed4043d6ee7eb4e429dca22c89b4e92df..e3d9444840f211180b12f8ebcb2c532d34800f92 100644 (file)
@@ -26,17 +26,17 @@ char *sysimport =
        "func sys.stringiter (? string, ? int) (? int)\n"
        "func sys.stringiter2 (? string, ? int) (retk int, retv int)\n"
        "func sys.ifaceI2E (iface any) (ret any)\n"
-       "func sys.ifaceE2I (sigi *uint8, iface any) (ret any)\n"
-       "func sys.ifaceT2E (sigt *uint8, elem any) (ret any)\n"
-       "func sys.ifaceE2T (sigt *uint8, elem any) (ret any)\n"
-       "func sys.ifaceE2I2 (sigi *uint8, iface any) (ret any, ok bool)\n"
-       "func sys.ifaceE2T2 (sigt *uint8, elem any) (ret any, ok bool)\n"
-       "func sys.ifaceT2I (sigi *uint8, sigt *uint8, elem any) (ret any)\n"
-       "func sys.ifaceI2T (sigt *uint8, iface any) (ret any)\n"
-       "func sys.ifaceI2T2 (sigt *uint8, iface any) (ret any, ok bool)\n"
-       "func sys.ifaceI2I (sigi *uint8, iface any) (ret any)\n"
-       "func sys.ifaceI2Ix (sigi *uint8, iface any) (ret any)\n"
-       "func sys.ifaceI2I2 (sigi *uint8, iface any) (ret any, ok bool)\n"
+       "func sys.ifaceE2I (typ *uint8, iface any) (ret any)\n"
+       "func sys.ifaceT2E (typ *uint8, elem any) (ret any)\n"
+       "func sys.ifaceE2T (typ *uint8, elem any) (ret any)\n"
+       "func sys.ifaceE2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
+       "func sys.ifaceE2T2 (typ *uint8, elem any) (ret any, ok bool)\n"
+       "func sys.ifaceT2I (typ1 *uint8, typ2 *uint8, elem any) (ret any)\n"
+       "func sys.ifaceI2T (typ *uint8, iface any) (ret any)\n"
+       "func sys.ifaceI2T2 (typ *uint8, iface any) (ret any, ok bool)\n"
+       "func sys.ifaceI2I (typ *uint8, iface any) (ret any)\n"
+       "func sys.ifaceI2Ix (typ *uint8, iface any) (ret any)\n"
+       "func sys.ifaceI2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
        "func sys.ifaceeq (i1 any, i2 any) (ret bool)\n"
        "func sys.efaceeq (i1 any, i2 any) (ret bool)\n"
        "func sys.ifacethash (i1 any) (ret uint32)\n"
@@ -80,7 +80,8 @@ char *unsafeimport =
        "func unsafe.Offsetof (? any) (? int)\n"
        "func unsafe.Sizeof (? any) (? int)\n"
        "func unsafe.Alignof (? any) (? int)\n"
-       "func unsafe.Reflect (i interface { }) (? uint64, ? string, ? bool)\n"
-       "func unsafe.Unreflect (? uint64, ? string, ? bool) (ret interface { })\n"
+       "func unsafe.Typeof (i interface { }) (typ interface { })\n"
+       "func unsafe.Reflect (i interface { }) (typ interface { }, addr unsafe.Pointer)\n"
+       "func unsafe.Unreflect (typ interface { }, addr unsafe.Pointer) (ret interface { })\n"
        "\n"
        "$$\n";
index eb7e94ca54de84f80090150d3b6fa6edce1124fa..b9af878599859b18bbda7d9f38e8774c99abda3b 100644 (file)
@@ -391,6 +391,7 @@ enum
 enum
 {
        /* types of channel */
+       /* must match ../../pkg/nreflect/type.go:/Chandir */
        Cxxx,
        Crecv = 1<<0,
        Csend = 1<<1,
@@ -457,7 +458,10 @@ typedef    struct  Sig     Sig;
 struct Sig
 {
        char*   name;
-       Sym*    sym;
+       char*   package;
+       Sym*    isym;
+       Sym*    tsym;
+       Type*   type;
        uint32  hash;
        int32   perm;
        int32   offset;
@@ -736,7 +740,7 @@ int isnilinter(Type*);
 int    isddd(Type*);
 Type*  maptype(Type*, Type*);
 Type*  methtype(Type*);
-Node*  signame(Type*);
+Node*  typename(Type*);
 int    eqtype(Type*, Type*);
 int    cvttype(Type*, Type*);
 int    eqtypenoname(Type*, Type*);
@@ -782,7 +786,6 @@ Type*       funcnext(Iter*);
 int    brcom(int);
 int    brrev(int);
 void   setmaxarg(Type*);
-Sig*   lsort(Sig*, int(*)(Sig*, Sig*));
 int    dotoffset(Node*, int*, Node**);
 void   tempname(Node*, Type*);
 
@@ -1073,7 +1076,7 @@ int       isfat(Type*);
 void   clearfat(Node *n);
 void   cgen(Node*, Node*);
 void   gused(Node*);
-void   dumpsignatures(void);
+void   dumptypestructs(void);
 void   dumpfuncs(void);
 void   dumpdata(void);
 void   ggloblnod(Node *nam, int32 width);
index e43a97383d51318a650965969600124646ae8770..6bd66d79dbe15e7f3f7d8791919a0f4b14d4a0de 100644 (file)
@@ -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;
-}
-
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
new file mode 100644 (file)
index 0000000..2e2e68c
--- /dev/null
@@ -0,0 +1,692 @@
+// 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));
+       }
+}
index e397284de092445179a3cb7c52607a96eb32477d..d922c8b01995ed5bff7daf780f7e406db96dd267 100644 (file)
@@ -1613,64 +1613,6 @@ iscomposite(Type *t)
        return 0;
 }
 
-Node*
-signame(Type *t)
-{
-       Sym *ss;
-       char *e;
-       Dcl *x;
-       char buf[NSYMB];
-
-//print("signame %T\n", t);
-       if(t == T)
-               goto bad;
-
-       e = "sigt";
-       if(t->etype == TINTER || t->etype == TDDD)
-               e = "sigi";
-
-       // 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");
-
-       // special case: sigi.... is just too hard to read in assembly.
-       if(strcmp(buf, "...") == 0)
-               strcpy(buf, "dotdotdot");
-
-       ss = pkglookup(buf, e);
-       if(ss->def == N) {
-               ss->def = newname(ss);
-               ss->def->type = types[TUINT8];
-               ss->def->class = PEXTERN;
-       }
-
-//print("siggen %T %d\n", t, t->siggen);
-       if(!t->siggen) {
-               // 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->def;
-
-bad:
-       return N;
-}
-
 int
 eqtype1(Type *t1, Type *t2, int d, int names)
 {
index 9289a9ca8e7dce5f78889cee66694660aded97a2..eff7b0d40565fdea0029d3b7d18672878ae9ccb2 100644 (file)
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-
 package PACKAGE
 
 type   Pointer *any;
 func   Offsetof(any) int;
 func   Sizeof(any) int;
 func   Alignof(any) int;
-func   Reflect(i interface { }) (uint64, string, bool);
-func   Unreflect(uint64, string, bool) (ret interface { });
+func   Typeof(i interface { }) (typ interface{});
+func   Reflect(i interface { }) (typ interface{}, addr Pointer);
+func   Unreflect(typ interface{}, addr Pointer) (ret interface { });
index e0617259f42248699b029cdefe4fcd966724eb2f..08be5bfcb4bc8fbd14faf7134a291a4fe958e8dd 100644 (file)
@@ -1309,7 +1309,7 @@ walkconv(Node *n)
                n->op = OCONVNOP;
                return;
        }
-       
+
        // to/from interface.
        // ifaceas1 will generate a good error
        // if the conversion is invalid.
@@ -1940,7 +1940,6 @@ loop:
 Type*
 sigtype(Type *st)
 {
-       Dcl *x;
        Sym *s;
        Type *t;
        static int sigdddgen;
@@ -1954,16 +1953,6 @@ sigtype(Type *st)
        t = dodcltype(t);
        updatetype(t, st);
        t->local = 1;
-
-       // record internal type for signature generation
-       x = mal(sizeof(*x));
-       x->op = OTYPE;
-       x->dsym = s;
-       x->dtype = t;
-       x->forw = signatlist;
-       x->block = block;
-       signatlist = x;
-
        return t;
 }
 
@@ -3260,10 +3249,10 @@ ifacecvt(Type *tl, Node *n, int et)
                a = n;                          // elem
                r = a;
 
-               a = nod(OADDR, signame(tr), N); // sigt
+               a = typename(tr);       // sigt
                r = list(a, r);
 
-               a = nod(OADDR, signame(tl), N); // sigi
+               a = typename(tl);       // sigi
                r = list(a, r);
 
                on = syslook("ifaceT2I", 1);
@@ -3284,7 +3273,7 @@ ifacecvt(Type *tl, Node *n, int et)
                a = n;                          // interface
                r = a;
 
-               a = nod(OADDR, signame(tl), N); // sigi or sigt
+               a = typename(tl);       // sigi or sigt
                r = list(a, r);
 
                on = syslook(ifacename[et], 1);
@@ -3308,7 +3297,7 @@ ifacecvt(Type *tl, Node *n, int et)
                a = n;                          // elem
                r = a;
 
-               a = nod(OADDR, signame(tr), N); // sigt
+               a = typename(tr);       // sigt
                r = list(a, r);
 
                on = syslook("ifaceT2E", 1);