Commit 541e638f authored by Russ Cox's avatar Russ Cox

6g, 8g: generate data structures for new reflect interface (CL 31107)

R=ken
OCL=31122
CL=31278
parent c7513eac
...@@ -488,6 +488,46 @@ dstringptr(Sym *s, int off, char *str) ...@@ -488,6 +488,46 @@ dstringptr(Sym *s, int off, char *str)
return off; 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 int
duintxx(Sym *s, int off, uint64 v, int wid) duintxx(Sym *s, int off, uint64 v, int wid)
{ {
......
...@@ -486,6 +486,47 @@ dstringptr(Sym *s, int off, char *str) ...@@ -486,6 +486,47 @@ dstringptr(Sym *s, int off, char *str)
return off; 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 int
duintxx(Sym *s, int off, uint64 v, int wid) duintxx(Sym *s, int off, uint64 v, int wid)
{ {
......
...@@ -15,6 +15,7 @@ YFILES=\ ...@@ -15,6 +15,7 @@ YFILES=\
go.y\ go.y\
OFILES=\ OFILES=\
reflect.$O\
y.tab.$O\ y.tab.$O\
lex.$O\ lex.$O\
subr.$O\ subr.$O\
......
...@@ -243,6 +243,10 @@ typeinit(void) ...@@ -243,6 +243,10 @@ typeinit(void)
isptr[TPTR32] = 1; isptr[TPTR32] = 1;
isptr[TPTR64] = 1; isptr[TPTR64] = 1;
isforw[TFORW] = 1;
isforw[TFORWSTRUCT] = 1;
isforw[TFORWINTER] = 1;
issigned[TINT] = 1; issigned[TINT] = 1;
issigned[TINT8] = 1; issigned[TINT8] = 1;
issigned[TINT16] = 1; issigned[TINT16] = 1;
......
...@@ -26,17 +26,17 @@ char *sysimport = ...@@ -26,17 +26,17 @@ char *sysimport =
"func sys.stringiter (? string, ? int) (? int)\n" "func sys.stringiter (? string, ? int) (? int)\n"
"func sys.stringiter2 (? string, ? int) (retk int, retv int)\n" "func sys.stringiter2 (? string, ? int) (retk int, retv int)\n"
"func sys.ifaceI2E (iface any) (ret any)\n" "func sys.ifaceI2E (iface any) (ret any)\n"
"func sys.ifaceE2I (sigi *uint8, iface any) (ret any)\n" "func sys.ifaceE2I (typ *uint8, iface any) (ret any)\n"
"func sys.ifaceT2E (sigt *uint8, elem any) (ret any)\n" "func sys.ifaceT2E (typ *uint8, elem any) (ret any)\n"
"func sys.ifaceE2T (sigt *uint8, elem any) (ret any)\n" "func sys.ifaceE2T (typ *uint8, elem any) (ret any)\n"
"func sys.ifaceE2I2 (sigi *uint8, iface any) (ret any, ok bool)\n" "func sys.ifaceE2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
"func sys.ifaceE2T2 (sigt *uint8, elem any) (ret any, ok bool)\n" "func sys.ifaceE2T2 (typ *uint8, elem any) (ret any, ok bool)\n"
"func sys.ifaceT2I (sigi *uint8, sigt *uint8, elem any) (ret any)\n" "func sys.ifaceT2I (typ1 *uint8, typ2 *uint8, elem any) (ret any)\n"
"func sys.ifaceI2T (sigt *uint8, iface any) (ret any)\n" "func sys.ifaceI2T (typ *uint8, iface any) (ret any)\n"
"func sys.ifaceI2T2 (sigt *uint8, iface any) (ret any, ok bool)\n" "func sys.ifaceI2T2 (typ *uint8, iface any) (ret any, ok bool)\n"
"func sys.ifaceI2I (sigi *uint8, iface any) (ret any)\n" "func sys.ifaceI2I (typ *uint8, iface any) (ret any)\n"
"func sys.ifaceI2Ix (sigi *uint8, iface any) (ret any)\n" "func sys.ifaceI2Ix (typ *uint8, iface any) (ret any)\n"
"func sys.ifaceI2I2 (sigi *uint8, iface any) (ret any, ok bool)\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.ifaceeq (i1 any, i2 any) (ret bool)\n"
"func sys.efaceeq (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" "func sys.ifacethash (i1 any) (ret uint32)\n"
...@@ -80,7 +80,8 @@ char *unsafeimport = ...@@ -80,7 +80,8 @@ char *unsafeimport =
"func unsafe.Offsetof (? any) (? int)\n" "func unsafe.Offsetof (? any) (? int)\n"
"func unsafe.Sizeof (? any) (? int)\n" "func unsafe.Sizeof (? any) (? int)\n"
"func unsafe.Alignof (? any) (? int)\n" "func unsafe.Alignof (? any) (? int)\n"
"func unsafe.Reflect (i interface { }) (? uint64, ? string, ? bool)\n" "func unsafe.Typeof (i interface { }) (typ interface { })\n"
"func unsafe.Unreflect (? uint64, ? string, ? bool) (ret 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"
"$$\n"; "$$\n";
...@@ -391,6 +391,7 @@ enum ...@@ -391,6 +391,7 @@ enum
enum enum
{ {
/* types of channel */ /* types of channel */
/* must match ../../pkg/nreflect/type.go:/Chandir */
Cxxx, Cxxx,
Crecv = 1<<0, Crecv = 1<<0,
Csend = 1<<1, Csend = 1<<1,
...@@ -457,7 +458,10 @@ typedef struct Sig Sig; ...@@ -457,7 +458,10 @@ typedef struct Sig Sig;
struct Sig struct Sig
{ {
char* name; char* name;
Sym* sym; char* package;
Sym* isym;
Sym* tsym;
Type* type;
uint32 hash; uint32 hash;
int32 perm; int32 perm;
int32 offset; int32 offset;
...@@ -736,7 +740,7 @@ int isnilinter(Type*); ...@@ -736,7 +740,7 @@ int isnilinter(Type*);
int isddd(Type*); int isddd(Type*);
Type* maptype(Type*, Type*); Type* maptype(Type*, Type*);
Type* methtype(Type*); Type* methtype(Type*);
Node* signame(Type*); Node* typename(Type*);
int eqtype(Type*, Type*); int eqtype(Type*, Type*);
int cvttype(Type*, Type*); int cvttype(Type*, Type*);
int eqtypenoname(Type*, Type*); int eqtypenoname(Type*, Type*);
...@@ -782,7 +786,6 @@ Type* funcnext(Iter*); ...@@ -782,7 +786,6 @@ Type* funcnext(Iter*);
int brcom(int); int brcom(int);
int brrev(int); int brrev(int);
void setmaxarg(Type*); void setmaxarg(Type*);
Sig* lsort(Sig*, int(*)(Sig*, Sig*));
int dotoffset(Node*, int*, Node**); int dotoffset(Node*, int*, Node**);
void tempname(Node*, Type*); void tempname(Node*, Type*);
...@@ -1073,7 +1076,7 @@ int isfat(Type*); ...@@ -1073,7 +1076,7 @@ int isfat(Type*);
void clearfat(Node *n); void clearfat(Node *n);
void cgen(Node*, Node*); void cgen(Node*, Node*);
void gused(Node*); void gused(Node*);
void dumpsignatures(void); void dumptypestructs(void);
void dumpfuncs(void); void dumpfuncs(void);
void dumpdata(void); void dumpdata(void);
void ggloblnod(Node *nam, int32 width); void ggloblnod(Node *nam, int32 width);
......
...@@ -28,7 +28,7 @@ dumpobj(void) ...@@ -28,7 +28,7 @@ dumpobj(void)
newplist(); newplist();
dumpglobls(); dumpglobls();
dumpsignatures(); dumptypestructs();
dumpdata(); dumpdata();
dumpfuncs(); dumpfuncs();
...@@ -169,414 +169,3 @@ duintptr(Sym *s, int off, uint64 v) ...@@ -169,414 +169,3 @@ duintptr(Sym *s, int off, uint64 v)
{ {
return duintxx(s, off, v, widthptr); 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;
}
// 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));
}
}
...@@ -1613,64 +1613,6 @@ iscomposite(Type *t) ...@@ -1613,64 +1613,6 @@ iscomposite(Type *t)
return 0; 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 int
eqtype1(Type *t1, Type *t2, int d, int names) eqtype1(Type *t1, Type *t2, int d, int names)
{ {
......
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package PACKAGE package PACKAGE
type Pointer *any; type Pointer *any;
func Offsetof(any) int; func Offsetof(any) int;
func Sizeof(any) int; func Sizeof(any) int;
func Alignof(any) int; func Alignof(any) int;
func Reflect(i interface { }) (uint64, string, bool); func Typeof(i interface { }) (typ interface{});
func Unreflect(uint64, string, bool) (ret interface { }); func Reflect(i interface { }) (typ interface{}, addr Pointer);
func Unreflect(typ interface{}, addr Pointer) (ret interface { });
...@@ -1309,7 +1309,7 @@ walkconv(Node *n) ...@@ -1309,7 +1309,7 @@ walkconv(Node *n)
n->op = OCONVNOP; n->op = OCONVNOP;
return; return;
} }
// to/from interface. // to/from interface.
// ifaceas1 will generate a good error // ifaceas1 will generate a good error
// if the conversion is invalid. // if the conversion is invalid.
...@@ -1940,7 +1940,6 @@ loop: ...@@ -1940,7 +1940,6 @@ loop:
Type* Type*
sigtype(Type *st) sigtype(Type *st)
{ {
Dcl *x;
Sym *s; Sym *s;
Type *t; Type *t;
static int sigdddgen; static int sigdddgen;
...@@ -1954,16 +1953,6 @@ sigtype(Type *st) ...@@ -1954,16 +1953,6 @@ sigtype(Type *st)
t = dodcltype(t); t = dodcltype(t);
updatetype(t, st); updatetype(t, st);
t->local = 1; 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; return t;
} }
...@@ -3260,10 +3249,10 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3260,10 +3249,10 @@ ifacecvt(Type *tl, Node *n, int et)
a = n; // elem a = n; // elem
r = a; r = a;
a = nod(OADDR, signame(tr), N); // sigt a = typename(tr); // sigt
r = list(a, r); r = list(a, r);
a = nod(OADDR, signame(tl), N); // sigi a = typename(tl); // sigi
r = list(a, r); r = list(a, r);
on = syslook("ifaceT2I", 1); on = syslook("ifaceT2I", 1);
...@@ -3284,7 +3273,7 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3284,7 +3273,7 @@ ifacecvt(Type *tl, Node *n, int et)
a = n; // interface a = n; // interface
r = a; r = a;
a = nod(OADDR, signame(tl), N); // sigi or sigt a = typename(tl); // sigi or sigt
r = list(a, r); r = list(a, r);
on = syslook(ifacename[et], 1); on = syslook(ifacename[et], 1);
...@@ -3308,7 +3297,7 @@ ifacecvt(Type *tl, Node *n, int et) ...@@ -3308,7 +3297,7 @@ ifacecvt(Type *tl, Node *n, int et)
a = n; // elem a = n; // elem
r = a; r = a;
a = nod(OADDR, signame(tr), N); // sigt a = typename(tr); // sigt
r = list(a, r); r = list(a, r);
on = syslook("ifaceT2E", 1); on = syslook("ifaceT2E", 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment