github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/gc/reflect.c (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include <u.h>
     6  #include <libc.h>
     7  #include "go.h"
     8  #include "../../pkg/runtime/mgc0.h"
     9  
    10  /*
    11   * runtime interface and reflection data structures
    12   */
    13  
    14  static	NodeList*	signatlist;
    15  static	Sym*	dtypesym(Type*);
    16  static	Sym*	weaktypesym(Type*);
    17  static	Sym*	dalgsym(Type*);
    18  static	Sym*	dgcsym(Type*);
    19  
    20  static int
    21  sigcmp(Sig *a, Sig *b)
    22  {
    23  	int i;
    24  
    25  	i = strcmp(a->name, b->name);
    26  	if(i != 0)
    27  		return i;
    28  	if(a->pkg == b->pkg)
    29  		return 0;
    30  	if(a->pkg == nil)
    31  		return -1;
    32  	if(b->pkg == nil)
    33  		return +1;
    34  	return strcmp(a->pkg->path->s, b->pkg->path->s);
    35  }
    36  
    37  static Sig*
    38  lsort(Sig *l, int(*f)(Sig*, Sig*))
    39  {
    40  	Sig *l1, *l2, *le;
    41  
    42  	if(l == 0 || l->link == 0)
    43  		return l;
    44  
    45  	l1 = l;
    46  	l2 = l;
    47  	for(;;) {
    48  		l2 = l2->link;
    49  		if(l2 == 0)
    50  			break;
    51  		l2 = l2->link;
    52  		if(l2 == 0)
    53  			break;
    54  		l1 = l1->link;
    55  	}
    56  
    57  	l2 = l1->link;
    58  	l1->link = 0;
    59  	l1 = lsort(l, f);
    60  	l2 = lsort(l2, f);
    61  
    62  	/* set up lead element */
    63  	if((*f)(l1, l2) < 0) {
    64  		l = l1;
    65  		l1 = l1->link;
    66  	} else {
    67  		l = l2;
    68  		l2 = l2->link;
    69  	}
    70  	le = l;
    71  
    72  	for(;;) {
    73  		if(l1 == 0) {
    74  			while(l2) {
    75  				le->link = l2;
    76  				le = l2;
    77  				l2 = l2->link;
    78  			}
    79  			le->link = 0;
    80  			break;
    81  		}
    82  		if(l2 == 0) {
    83  			while(l1) {
    84  				le->link = l1;
    85  				le = l1;
    86  				l1 = l1->link;
    87  			}
    88  			break;
    89  		}
    90  		if((*f)(l1, l2) < 0) {
    91  			le->link = l1;
    92  			le = l1;
    93  			l1 = l1->link;
    94  		} else {
    95  			le->link = l2;
    96  			le = l2;
    97  			l2 = l2->link;
    98  		}
    99  	}
   100  	le->link = 0;
   101  	return l;
   102  }
   103  
   104  /*
   105   * f is method type, with receiver.
   106   * return function type, receiver as first argument (or not).
   107   */
   108  Type*
   109  methodfunc(Type *f, Type *receiver)
   110  {
   111  	NodeList *in, *out;
   112  	Node *d;
   113  	Type *t;
   114  
   115  	in = nil;
   116  	if(receiver) {
   117  		d = nod(ODCLFIELD, N, N);
   118  		d->type = receiver;
   119  		in = list(in, d);
   120  	}
   121  	for(t=getinargx(f)->type; t; t=t->down) {
   122  		d = nod(ODCLFIELD, N, N);
   123  		d->type = t->type;
   124  		d->isddd = t->isddd;
   125  		in = list(in, d);
   126  	}
   127  
   128  	out = nil;
   129  	for(t=getoutargx(f)->type; t; t=t->down) {
   130  		d = nod(ODCLFIELD, N, N);
   131  		d->type = t->type;
   132  		out = list(out, d);
   133  	}
   134  
   135  	t = functype(N, in, out);
   136  	if(f->nname) {
   137  		// Link to name of original method function.
   138  		t->nname = f->nname;
   139  	}
   140  	return t;
   141  }
   142  
   143  /*
   144   * return methods of non-interface type t, sorted by name.
   145   * generates stub functions as needed.
   146   */
   147  static Sig*
   148  methods(Type *t)
   149  {
   150  	Type *f, *mt, *it, *this;
   151  	Sig *a, *b;
   152  	Sym *method;
   153  
   154  	// method type
   155  	mt = methtype(t, 0);
   156  	if(mt == T)
   157  		return nil;
   158  	expandmeth(mt);
   159  
   160  	// type stored in interface word
   161  	it = t;
   162  	if(it->width > widthptr)
   163  		it = ptrto(t);
   164  
   165  	// make list of methods for t,
   166  	// generating code if necessary.
   167  	a = nil;
   168  	for(f=mt->xmethod; f; f=f->down) {
   169  		if(f->etype != TFIELD)
   170  			fatal("methods: not field %T", f);
   171  		if (f->type->etype != TFUNC || f->type->thistuple == 0)
   172  			fatal("non-method on %T method %S %T\n", mt, f->sym, f);
   173  		if (!getthisx(f->type)->type)
   174  			fatal("receiver with no type on %T method %S %T\n", mt, f->sym, f);
   175  		if(f->nointerface)
   176  			continue;
   177  
   178  		method = f->sym;
   179  		if(method == nil)
   180  			continue;
   181  
   182  		// get receiver type for this particular method.
   183  		// if pointer receiver but non-pointer t and
   184  		// this is not an embedded pointer inside a struct,
   185  		// method does not apply.
   186  		this = getthisx(f->type)->type->type;
   187  		if(isptr[this->etype] && this->type == t)
   188  			continue;
   189  		if(isptr[this->etype] && !isptr[t->etype]
   190  		&& f->embedded != 2 && !isifacemethod(f->type))
   191  			continue;
   192  
   193  		b = mal(sizeof(*b));
   194  		b->link = a;
   195  		a = b;
   196  
   197  		a->name = method->name;
   198  		if(!exportname(method->name)) {
   199  			if(method->pkg == nil)
   200  				fatal("methods: missing package");
   201  			a->pkg = method->pkg;
   202  		}
   203  		a->isym = methodsym(method, it, 1);
   204  		a->tsym = methodsym(method, t, 0);
   205  		a->type = methodfunc(f->type, t);
   206  		a->mtype = methodfunc(f->type, nil);
   207  
   208  		if(!(a->isym->flags & SymSiggen)) {
   209  			a->isym->flags |= SymSiggen;
   210  			if(!eqtype(this, it) || this->width < types[tptr]->width) {
   211  				// Is okay to call genwrapper here always,
   212  				// but we can generate more efficient code
   213  				// using genembedtramp if all that is necessary
   214  				// is a pointer adjustment and a JMP.
   215  				compiling_wrappers = 1;
   216  				if(isptr[it->etype] && isptr[this->etype]
   217  				&& f->embedded && !isifacemethod(f->type))
   218  					genembedtramp(it, f, a->isym, 1);
   219  				else
   220  					genwrapper(it, f, a->isym, 1);
   221  				compiling_wrappers = 0;
   222  			}
   223  		}
   224  
   225  		if(!(a->tsym->flags & SymSiggen)) {
   226  			a->tsym->flags |= SymSiggen;
   227  			if(!eqtype(this, t)) {
   228  				compiling_wrappers = 1;
   229  				if(isptr[t->etype] && isptr[this->etype]
   230  				&& f->embedded && !isifacemethod(f->type))
   231  					genembedtramp(t, f, a->tsym, 0);
   232  				else
   233  					genwrapper(t, f, a->tsym, 0);
   234  				compiling_wrappers = 0;
   235  			}
   236  		}
   237  	}
   238  
   239  	return lsort(a, sigcmp);
   240  }
   241  
   242  /*
   243   * return methods of interface type t, sorted by name.
   244   */
   245  static Sig*
   246  imethods(Type *t)
   247  {
   248  	Sig *a, *all, *last;
   249  	Type *f;
   250  	Sym *method, *isym;
   251  
   252  	all = nil;
   253  	last = nil;
   254  	for(f=t->type; f; f=f->down) {
   255  		if(f->etype != TFIELD)
   256  			fatal("imethods: not field");
   257  		if(f->type->etype != TFUNC || f->sym == nil)
   258  			continue;
   259  		method = f->sym;
   260  		a = mal(sizeof(*a));
   261  		a->name = method->name;
   262  		if(!exportname(method->name)) {
   263  			if(method->pkg == nil)
   264  				fatal("imethods: missing package");
   265  			a->pkg = method->pkg;
   266  		}
   267  		a->mtype = f->type;
   268  		a->offset = 0;
   269  		a->type = methodfunc(f->type, nil);
   270  
   271  		if(last && sigcmp(last, a) >= 0)
   272  			fatal("sigcmp vs sortinter %s %s", last->name, a->name);
   273  		if(last == nil)
   274  			all = a;
   275  		else
   276  			last->link = a;
   277  		last = a;
   278  
   279  		// Compiler can only refer to wrappers for
   280  		// named interface types.
   281  		if(t->sym == S)
   282  			continue;
   283  
   284  		// NOTE(rsc): Perhaps an oversight that
   285  		// IfaceType.Method is not in the reflect data.
   286  		// Generate the method body, so that compiled
   287  		// code can refer to it.
   288  		isym = methodsym(method, t, 0);
   289  		if(!(isym->flags & SymSiggen)) {
   290  			isym->flags |= SymSiggen;
   291  			genwrapper(t, f, isym, 0);
   292  		}
   293  	}
   294  	return all;
   295  }
   296  
   297  static void
   298  dimportpath(Pkg *p)
   299  {
   300  	static Pkg *gopkg;
   301  	char *nam;
   302  	Node *n;
   303  
   304  	if(p->pathsym != S)
   305  		return;
   306  
   307  	if(gopkg == nil) {
   308  		gopkg = mkpkg(strlit("go"));
   309  		gopkg->name = "go";
   310  	}
   311  	nam = smprint("importpath.%s.", p->prefix);
   312  
   313  	n = nod(ONAME, N, N);
   314  	n->sym = pkglookup(nam, gopkg);
   315  	free(nam);
   316  	n->class = PEXTERN;
   317  	n->xoffset = 0;
   318  	p->pathsym = n->sym;
   319  
   320  	gdatastring(n, p->path);
   321  	ggloblsym(n->sym, types[TSTRING]->width, 1, 1);
   322  }
   323  
   324  static int
   325  dgopkgpath(Sym *s, int ot, Pkg *pkg)
   326  {
   327  	if(pkg == nil)
   328  		return dgostringptr(s, ot, nil);
   329  
   330  	// Emit reference to go.importpath.""., which 6l will
   331  	// rewrite using the correct import path.  Every package
   332  	// that imports this one directly defines the symbol.
   333  	if(pkg == localpkg) {
   334  		static Sym *ns;
   335  
   336  		if(ns == nil)
   337  			ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
   338  		return dsymptr(s, ot, ns, 0);
   339  	}
   340  
   341  	dimportpath(pkg);
   342  	return dsymptr(s, ot, pkg->pathsym, 0);
   343  }
   344  
   345  /*
   346   * uncommonType
   347   * ../../pkg/runtime/type.go:/uncommonType
   348   */
   349  static int
   350  dextratype(Sym *sym, int off, Type *t, int ptroff)
   351  {
   352  	int ot, n;
   353  	Sym *s;
   354  	Sig *a, *m;
   355  
   356  	m = methods(t);
   357  	if(t->sym == nil && m == nil)
   358  		return off;
   359  
   360  	// fill in *extraType pointer in header
   361  	dsymptr(sym, ptroff, sym, off);
   362  
   363  	n = 0;
   364  	for(a=m; a; a=a->link) {
   365  		dtypesym(a->type);
   366  		n++;
   367  	}
   368  
   369  	ot = off;
   370  	s = sym;
   371  	if(t->sym) {
   372  		ot = dgostringptr(s, ot, t->sym->name);
   373  		if(t != types[t->etype] && t != errortype)
   374  			ot = dgopkgpath(s, ot, t->sym->pkg);
   375  		else
   376  			ot = dgostringptr(s, ot, nil);
   377  	} else {
   378  		ot = dgostringptr(s, ot, nil);
   379  		ot = dgostringptr(s, ot, nil);
   380  	}
   381  
   382  	// slice header
   383  	ot = dsymptr(s, ot, s, ot + widthptr + 2*widthint);
   384  	ot = duintxx(s, ot, n, widthint);
   385  	ot = duintxx(s, ot, n, widthint);
   386  
   387  	// methods
   388  	for(a=m; a; a=a->link) {
   389  		// method
   390  		// ../../pkg/runtime/type.go:/method
   391  		ot = dgostringptr(s, ot, a->name);
   392  		ot = dgopkgpath(s, ot, a->pkg);
   393  		ot = dsymptr(s, ot, dtypesym(a->mtype), 0);
   394  		ot = dsymptr(s, ot, dtypesym(a->type), 0);
   395  		if(a->isym)
   396  			ot = dsymptr(s, ot, a->isym, 0);
   397  		else
   398  			ot = duintptr(s, ot, 0);
   399  		if(a->tsym)
   400  			ot = dsymptr(s, ot, a->tsym, 0);
   401  		else
   402  			ot = duintptr(s, ot, 0);
   403  	}
   404  
   405  	return ot;
   406  }
   407  
   408  enum {
   409  	KindBool = 1,
   410  	KindInt,
   411  	KindInt8,
   412  	KindInt16,
   413  	KindInt32,
   414  	KindInt64,
   415  	KindUint,
   416  	KindUint8,
   417  	KindUint16,
   418  	KindUint32,
   419  	KindUint64,
   420  	KindUintptr,
   421  	KindFloat32,
   422  	KindFloat64,
   423  	KindComplex64,
   424  	KindComplex128,
   425  	KindArray,
   426  	KindChan,
   427  	KindFunc,
   428  	KindInterface,
   429  	KindMap,
   430  	KindPtr,
   431  	KindSlice,
   432  	KindString,
   433  	KindStruct,
   434  	KindUnsafePointer,
   435  
   436  	KindNoPointers = 1<<7,
   437  };
   438  
   439  static int
   440  kinds[] =
   441  {
   442  	[TINT]		= KindInt,
   443  	[TUINT]		= KindUint,
   444  	[TINT8]		= KindInt8,
   445  	[TUINT8]	= KindUint8,
   446  	[TINT16]	= KindInt16,
   447  	[TUINT16]	= KindUint16,
   448  	[TINT32]	= KindInt32,
   449  	[TUINT32]	= KindUint32,
   450  	[TINT64]	= KindInt64,
   451  	[TUINT64]	= KindUint64,
   452  	[TUINTPTR]	= KindUintptr,
   453  	[TFLOAT32]	= KindFloat32,
   454  	[TFLOAT64]	= KindFloat64,
   455  	[TBOOL]		= KindBool,
   456  	[TSTRING]		= KindString,
   457  	[TPTR32]		= KindPtr,
   458  	[TPTR64]		= KindPtr,
   459  	[TSTRUCT]	= KindStruct,
   460  	[TINTER]		= KindInterface,
   461  	[TCHAN]		= KindChan,
   462  	[TMAP]		= KindMap,
   463  	[TARRAY]		= KindArray,
   464  	[TFUNC]		= KindFunc,
   465  	[TCOMPLEX64]	= KindComplex64,
   466  	[TCOMPLEX128]	= KindComplex128,
   467  	[TUNSAFEPTR]	= KindUnsafePointer,
   468  };
   469  
   470  int
   471  haspointers(Type *t)
   472  {
   473  	Type *t1;
   474  
   475  	switch(t->etype) {
   476  	case TINT:
   477  	case TUINT:
   478  	case TINT8:
   479  	case TUINT8:
   480  	case TINT16:
   481  	case TUINT16:
   482  	case TINT32:
   483  	case TUINT32:
   484  	case TINT64:
   485  	case TUINT64:
   486  	case TUINTPTR:
   487  	case TFLOAT32:
   488  	case TFLOAT64:
   489  	case TBOOL:
   490  		return 0;
   491  	case TARRAY:
   492  		if(t->bound < 0)	// slice
   493  			return 1;
   494  		return haspointers(t->type);
   495  	case TSTRUCT:
   496  		for(t1=t->type; t1!=T; t1=t1->down)
   497  			if(haspointers(t1->type))
   498  				return 1;
   499  		return 0;
   500  	case TSTRING:
   501  	case TPTR32:
   502  	case TPTR64:
   503  	case TUNSAFEPTR:
   504  	case TINTER:
   505  	case TCHAN:
   506  	case TMAP:
   507  	case TFUNC:
   508  	default:
   509  		return 1;
   510  	}
   511  }
   512  
   513  /*
   514   * commonType
   515   * ../../pkg/runtime/type.go:/commonType
   516   */
   517  static int
   518  dcommontype(Sym *s, int ot, Type *t)
   519  {
   520  	int i, alg, sizeofAlg;
   521  	Sym *sptr, *algsym;
   522  	static Sym *algarray;
   523  	char *p;
   524  	
   525  	if(ot != 0)
   526  		fatal("dcommontype %d", ot);
   527  
   528  	sizeofAlg = 4*widthptr;
   529  	if(algarray == nil)
   530  		algarray = pkglookup("algarray", runtimepkg);
   531  	alg = algtype(t);
   532  	algsym = S;
   533  	if(alg < 0)
   534  		algsym = dalgsym(t);
   535  
   536  	dowidth(t);
   537  	if(t->sym != nil && !isptr[t->etype])
   538  		sptr = dtypesym(ptrto(t));
   539  	else
   540  		sptr = weaktypesym(ptrto(t));
   541  
   542  	// ../../pkg/reflect/type.go:/^type.commonType
   543  	// actual type structure
   544  	//	type commonType struct {
   545  	//		size          uintptr
   546  	//		hash          uint32
   547  	//		_             uint8
   548  	//		align         uint8
   549  	//		fieldAlign    uint8
   550  	//		kind          uint8
   551  	//		alg           unsafe.Pointer
   552  	//		gc            unsafe.Pointer
   553  	//		string        *string
   554  	//		*extraType
   555  	//		ptrToThis     *Type
   556  	//	}
   557  	ot = duintptr(s, ot, t->width);
   558  	ot = duint32(s, ot, typehash(t));
   559  	ot = duint8(s, ot, 0);	// unused
   560  
   561  	// runtime (and common sense) expects alignment to be a power of two.
   562  	i = t->align;
   563  	if(i == 0)
   564  		i = 1;
   565  	if((i&(i-1)) != 0)
   566  		fatal("invalid alignment %d for %T", t->align, t);
   567  	ot = duint8(s, ot, t->align);	// align
   568  	ot = duint8(s, ot, t->align);	// fieldAlign
   569  
   570  	i = kinds[t->etype];
   571  	if(t->etype == TARRAY && t->bound < 0)
   572  		i = KindSlice;
   573  	if(!haspointers(t))
   574  		i |= KindNoPointers;
   575  	ot = duint8(s, ot, i);  // kind
   576  	if(alg >= 0)
   577  		ot = dsymptr(s, ot, algarray, alg*sizeofAlg);
   578  	else
   579  		ot = dsymptr(s, ot, algsym, 0);
   580  	ot = dsymptr(s, ot, dgcsym(t), 0);  // gc
   581  	p = smprint("%-uT", t);
   582  	//print("dcommontype: %s\n", p);
   583  	ot = dgostringptr(s, ot, p);	// string
   584  	free(p);
   585  
   586  	// skip pointer to extraType,
   587  	// which follows the rest of this type structure.
   588  	// caller will fill in if needed.
   589  	// otherwise linker will assume 0.
   590  	ot += widthptr;
   591  
   592  	ot = dsymptr(s, ot, sptr, 0);  // ptrto type
   593  	return ot;
   594  }
   595  
   596  Sym*
   597  typesym(Type *t)
   598  {
   599  	char *p;
   600  	Sym *s;
   601  
   602  	p = smprint("%-T", t);
   603  	s = pkglookup(p, typepkg);
   604  	//print("typesym: %s -> %+S\n", p, s);
   605  	free(p);
   606  	return s;
   607  }
   608  
   609  Sym*
   610  tracksym(Type *t)
   611  {
   612  	char *p;
   613  	Sym *s;
   614  
   615  	p = smprint("%-T.%s", t->outer, t->sym->name);
   616  	s = pkglookup(p, trackpkg);
   617  	free(p);
   618  	return s;
   619  }
   620  
   621  Sym*
   622  typelinksym(Type *t)
   623  {
   624  	char *p;
   625  	Sym *s;
   626  
   627  	// %-uT is what the generated Type's string field says.
   628  	// It uses (ambiguous) package names instead of import paths.
   629  	// %-T is the complete, unambiguous type name.
   630  	// We want the types to end up sorted by string field,
   631  	// so use that first in the name, and then add :%-T to
   632  	// disambiguate. The names are a little long but they are
   633  	// discarded by the linker and do not end up in the symbol
   634  	// table of the final binary.
   635  	p = smprint("%-uT/%-T", t, t);
   636  	s = pkglookup(p, typelinkpkg);
   637  	//print("typelinksym: %s -> %+S\n", p, s);
   638  	free(p);
   639  	return s;
   640  }
   641  
   642  Sym*
   643  typesymprefix(char *prefix, Type *t)
   644  {
   645  	char *p;
   646  	Sym *s;
   647  
   648  	p = smprint("%s.%-T", prefix, t);
   649  	s = pkglookup(p, typepkg);
   650  	//print("algsym: %s -> %+S\n", p, s);
   651  	free(p);
   652  	return s;
   653  }
   654  
   655  Sym*
   656  typenamesym(Type *t)
   657  {
   658  	Sym *s;
   659  	Node *n;
   660  
   661  	if(t == T || (isptr[t->etype] && t->type == T) || isideal(t))
   662  		fatal("typename %T", t);
   663  	s = typesym(t);
   664  	if(s->def == N) {
   665  		n = nod(ONAME, N, N);
   666  		n->sym = s;
   667  		n->type = types[TUINT8];
   668  		n->addable = 1;
   669  		n->ullman = 1;
   670  		n->class = PEXTERN;
   671  		n->xoffset = 0;
   672  		n->typecheck = 1;
   673  		s->def = n;
   674  
   675  		signatlist = list(signatlist, typenod(t));
   676  	}
   677  	return s->def->sym;
   678  }
   679  
   680  Node*
   681  typename(Type *t)
   682  {
   683  	Sym *s;
   684  	Node *n;
   685  
   686  	s = typenamesym(t);
   687  	n = nod(OADDR, s->def, N);
   688  	n->type = ptrto(s->def->type);
   689  	n->addable = 1;
   690  	n->ullman = 2;
   691  	n->typecheck = 1;
   692  	return n;
   693  }
   694  
   695  static Sym*
   696  weaktypesym(Type *t)
   697  {
   698  	char *p;
   699  	Sym *s;
   700  
   701  	p = smprint("%-T", t);
   702  	s = pkglookup(p, weaktypepkg);
   703  	//print("weaktypesym: %s -> %+S\n", p, s);
   704  	free(p);
   705  	return s;
   706  }
   707  
   708  static Sym*
   709  dtypesym(Type *t)
   710  {
   711  	int ot, xt, n, isddd, dupok;
   712  	Sym *s, *s1, *s2, *slink;
   713  	Sig *a, *m;
   714  	Type *t1, *tbase, *t2;
   715  
   716  	// Replace byte, rune aliases with real type.
   717  	// They've been separate internally to make error messages
   718  	// better, but we have to merge them in the reflect tables.
   719  	if(t == bytetype || t == runetype)
   720  		t = types[t->etype];
   721  
   722  	if(isideal(t))
   723  		fatal("dtypesym %T", t);
   724  
   725  	s = typesym(t);
   726  	if(s->flags & SymSiggen)
   727  		return s;
   728  	s->flags |= SymSiggen;
   729  
   730  	// special case (look for runtime below):
   731  	// when compiling package runtime,
   732  	// emit the type structures for int, float, etc.
   733  	tbase = t;
   734  	if(isptr[t->etype] && t->sym == S && t->type->sym != S)
   735  		tbase = t->type;
   736  	dupok = tbase->sym == S;
   737  
   738  	if(compiling_runtime &&
   739  			(tbase == types[tbase->etype] ||
   740  			tbase == bytetype ||
   741  			tbase == runetype ||
   742  			tbase == errortype)) { // int, float, etc
   743  		goto ok;
   744  	}
   745  
   746  	// named types from other files are defined only by those files
   747  	if(tbase->sym && !tbase->local)
   748  		return s;
   749  	if(isforw[tbase->etype])
   750  		return s;
   751  
   752  ok:
   753  	ot = 0;
   754  	xt = 0;
   755  	switch(t->etype) {
   756  	default:
   757  		ot = dcommontype(s, ot, t);
   758  		xt = ot - 2*widthptr;
   759  		break;
   760  
   761  	case TARRAY:
   762  		if(t->bound >= 0) {
   763  			// ../../pkg/runtime/type.go:/ArrayType
   764  			s1 = dtypesym(t->type);
   765  			t2 = typ(TARRAY);
   766  			t2->type = t->type;
   767  			t2->bound = -1;  // slice
   768  			s2 = dtypesym(t2);
   769  			ot = dcommontype(s, ot, t);
   770  			xt = ot - 2*widthptr;
   771  			ot = dsymptr(s, ot, s1, 0);
   772  			ot = dsymptr(s, ot, s2, 0);
   773  			ot = duintptr(s, ot, t->bound);
   774  		} else {
   775  			// ../../pkg/runtime/type.go:/SliceType
   776  			s1 = dtypesym(t->type);
   777  			ot = dcommontype(s, ot, t);
   778  			xt = ot - 2*widthptr;
   779  			ot = dsymptr(s, ot, s1, 0);
   780  		}
   781  		break;
   782  
   783  	case TCHAN:
   784  		// ../../pkg/runtime/type.go:/ChanType
   785  		s1 = dtypesym(t->type);
   786  		ot = dcommontype(s, ot, t);
   787  		xt = ot - 2*widthptr;
   788  		ot = dsymptr(s, ot, s1, 0);
   789  		ot = duintptr(s, ot, t->chan);
   790  		break;
   791  
   792  	case TFUNC:
   793  		for(t1=getthisx(t)->type; t1; t1=t1->down)
   794  			dtypesym(t1->type);
   795  		isddd = 0;
   796  		for(t1=getinargx(t)->type; t1; t1=t1->down) {
   797  			isddd = t1->isddd;
   798  			dtypesym(t1->type);
   799  		}
   800  		for(t1=getoutargx(t)->type; t1; t1=t1->down)
   801  			dtypesym(t1->type);
   802  
   803  		ot = dcommontype(s, ot, t);
   804  		xt = ot - 2*widthptr;
   805  		ot = duint8(s, ot, isddd);
   806  
   807  		// two slice headers: in and out.
   808  		ot = rnd(ot, widthptr);
   809  		ot = dsymptr(s, ot, s, ot+2*(widthptr+2*widthint));
   810  		n = t->thistuple + t->intuple;
   811  		ot = duintxx(s, ot, n, widthint);
   812  		ot = duintxx(s, ot, n, widthint);
   813  		ot = dsymptr(s, ot, s, ot+1*(widthptr+2*widthint)+n*widthptr);
   814  		ot = duintxx(s, ot, t->outtuple, widthint);
   815  		ot = duintxx(s, ot, t->outtuple, widthint);
   816  
   817  		// slice data
   818  		for(t1=getthisx(t)->type; t1; t1=t1->down, n++)
   819  			ot = dsymptr(s, ot, dtypesym(t1->type), 0);
   820  		for(t1=getinargx(t)->type; t1; t1=t1->down, n++)
   821  			ot = dsymptr(s, ot, dtypesym(t1->type), 0);
   822  		for(t1=getoutargx(t)->type; t1; t1=t1->down, n++)
   823  			ot = dsymptr(s, ot, dtypesym(t1->type), 0);
   824  		break;
   825  
   826  	case TINTER:
   827  		m = imethods(t);
   828  		n = 0;
   829  		for(a=m; a; a=a->link) {
   830  			dtypesym(a->type);
   831  			n++;
   832  		}
   833  
   834  		// ../../pkg/runtime/type.go:/InterfaceType
   835  		ot = dcommontype(s, ot, t);
   836  		xt = ot - 2*widthptr;
   837  		ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
   838  		ot = duintxx(s, ot, n, widthint);
   839  		ot = duintxx(s, ot, n, widthint);
   840  		for(a=m; a; a=a->link) {
   841  			// ../../pkg/runtime/type.go:/imethod
   842  			ot = dgostringptr(s, ot, a->name);
   843  			ot = dgopkgpath(s, ot, a->pkg);
   844  			ot = dsymptr(s, ot, dtypesym(a->type), 0);
   845  		}
   846  		break;
   847  
   848  	case TMAP:
   849  		// ../../pkg/runtime/type.go:/MapType
   850  		s1 = dtypesym(t->down);
   851  		s2 = dtypesym(t->type);
   852  		ot = dcommontype(s, ot, t);
   853  		xt = ot - 2*widthptr;
   854  		ot = dsymptr(s, ot, s1, 0);
   855  		ot = dsymptr(s, ot, s2, 0);
   856  		break;
   857  
   858  	case TPTR32:
   859  	case TPTR64:
   860  		if(t->type->etype == TANY) {
   861  			// ../../pkg/runtime/type.go:/UnsafePointerType
   862  			ot = dcommontype(s, ot, t);
   863  			break;
   864  		}
   865  		// ../../pkg/runtime/type.go:/PtrType
   866  		s1 = dtypesym(t->type);
   867  		ot = dcommontype(s, ot, t);
   868  		xt = ot - 2*widthptr;
   869  		ot = dsymptr(s, ot, s1, 0);
   870  		break;
   871  
   872  	case TSTRUCT:
   873  		// ../../pkg/runtime/type.go:/StructType
   874  		// for security, only the exported fields.
   875  		n = 0;
   876  		for(t1=t->type; t1!=T; t1=t1->down) {
   877  			dtypesym(t1->type);
   878  			n++;
   879  		}
   880  		ot = dcommontype(s, ot, t);
   881  		xt = ot - 2*widthptr;
   882  		ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
   883  		ot = duintxx(s, ot, n, widthint);
   884  		ot = duintxx(s, ot, n, widthint);
   885  		for(t1=t->type; t1!=T; t1=t1->down) {
   886  			// ../../pkg/runtime/type.go:/structField
   887  			if(t1->sym && !t1->embedded) {
   888  				ot = dgostringptr(s, ot, t1->sym->name);
   889  				if(exportname(t1->sym->name))
   890  					ot = dgostringptr(s, ot, nil);
   891  				else
   892  					ot = dgopkgpath(s, ot, t1->sym->pkg);
   893  			} else {
   894  				ot = dgostringptr(s, ot, nil);
   895  				if(t1->type->sym != S && t1->type->sym->pkg == builtinpkg)
   896  					ot = dgopkgpath(s, ot, localpkg);
   897  				else
   898  					ot = dgostringptr(s, ot, nil);
   899  			}
   900  			ot = dsymptr(s, ot, dtypesym(t1->type), 0);
   901  			ot = dgostrlitptr(s, ot, t1->note);
   902  			ot = duintptr(s, ot, t1->width);	// field offset
   903  		}
   904  		break;
   905  	}
   906  	ot = dextratype(s, ot, t, xt);
   907  	ggloblsym(s, ot, dupok, 1);
   908  
   909  	// generate typelink.foo pointing at s = type.foo.
   910  	// The linker will leave a table of all the typelinks for
   911  	// types in the binary, so reflect can find them.
   912  	// We only need the link for unnamed composites that
   913  	// we want be able to find.
   914  	if(t->sym == S) {
   915  		switch(t->etype) {
   916  		case TARRAY:
   917  		case TCHAN:
   918  		case TMAP:
   919  			slink = typelinksym(t);
   920  			dsymptr(slink, 0, s, 0);
   921  			ggloblsym(slink, widthptr, dupok, 1);
   922  		}
   923  	}
   924  
   925  	return s;
   926  }
   927  
   928  void
   929  dumptypestructs(void)
   930  {
   931  	int i;
   932  	NodeList *l;
   933  	Node *n;
   934  	Type *t;
   935  	Pkg *p;
   936  
   937  	// copy types from externdcl list to signatlist
   938  	for(l=externdcl; l; l=l->next) {
   939  		n = l->n;
   940  		if(n->op != OTYPE)
   941  			continue;
   942  		signatlist = list(signatlist, n);
   943  	}
   944  
   945  	// process signatlist
   946  	for(l=signatlist; l; l=l->next) {
   947  		n = l->n;
   948  		if(n->op != OTYPE)
   949  			continue;
   950  		t = n->type;
   951  		dtypesym(t);
   952  		if(t->sym)
   953  			dtypesym(ptrto(t));
   954  	}
   955  
   956  	// generate import strings for imported packages
   957  	for(i=0; i<nelem(phash); i++)
   958  		for(p=phash[i]; p; p=p->link)
   959  			if(p->direct)
   960  				dimportpath(p);
   961  
   962  	// do basic types if compiling package runtime.
   963  	// they have to be in at least one package,
   964  	// and runtime is always loaded implicitly,
   965  	// so this is as good as any.
   966  	// another possible choice would be package main,
   967  	// but using runtime means fewer copies in .6 files.
   968  	if(compiling_runtime) {
   969  		for(i=1; i<=TBOOL; i++)
   970  			dtypesym(ptrto(types[i]));
   971  		dtypesym(ptrto(types[TSTRING]));
   972  		dtypesym(ptrto(types[TUNSAFEPTR]));
   973  
   974  		// emit type structs for error and func(error) string.
   975  		// The latter is the type of an auto-generated wrapper.
   976  		dtypesym(ptrto(errortype));
   977  		dtypesym(functype(nil,
   978  			list1(nod(ODCLFIELD, N, typenod(errortype))),
   979  			list1(nod(ODCLFIELD, N, typenod(types[TSTRING])))));
   980  
   981  		// add paths for runtime and main, which 6l imports implicitly.
   982  		dimportpath(runtimepkg);
   983  		if(flag_race)
   984  			dimportpath(racepkg);
   985  		dimportpath(mkpkg(strlit("main")));
   986  	}
   987  }
   988  
   989  static Sym*
   990  dalgsym(Type *t)
   991  {
   992  	int ot;
   993  	Sym *s, *hash, *eq;
   994  	char buf[100];
   995  
   996  	// dalgsym is only called for a type that needs an algorithm table,
   997  	// which implies that the type is comparable (or else it would use ANOEQ).
   998  
   999  	s = typesymprefix(".alg", t);
  1000  	hash = typesymprefix(".hash", t);
  1001  	genhash(hash, t);
  1002  	eq = typesymprefix(".eq", t);
  1003  	geneq(eq, t);
  1004  
  1005  	// ../../pkg/runtime/runtime.h:/Alg
  1006  	ot = 0;
  1007  	ot = dsymptr(s, ot, hash, 0);
  1008  	ot = dsymptr(s, ot, eq, 0);
  1009  	ot = dsymptr(s, ot, pkglookup("memprint", runtimepkg), 0);
  1010  	switch(t->width) {
  1011  	default:
  1012  		ot = dsymptr(s, ot, pkglookup("memcopy", runtimepkg), 0);
  1013  		break;
  1014  	case 1:
  1015  	case 2:
  1016  	case 4:
  1017  	case 8:
  1018  	case 16:
  1019  		snprint(buf, sizeof buf, "memcopy%d", (int)t->width*8);
  1020  		ot = dsymptr(s, ot, pkglookup(buf, runtimepkg), 0);
  1021  		break;
  1022  	}
  1023  
  1024  	ggloblsym(s, ot, 1, 1);
  1025  	return s;
  1026  }
  1027  
  1028  static int
  1029  gcinline(Type *t) {
  1030  	switch(t->etype) {
  1031  	case TARRAY:
  1032  		if(t->bound == 1)
  1033  			return 1;
  1034  		if(t->width <= 4*widthptr)
  1035  			return 1;
  1036  		break;
  1037  	}
  1038  	return 0;
  1039  }
  1040  
  1041  static int
  1042  dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
  1043  {
  1044  	Type *t1;
  1045  	vlong o, off2, fieldoffset, i;
  1046  
  1047  	if(t->align > 0 && (*off % t->align) != 0)
  1048  		fatal("dgcsym1: invalid initial alignment, %T", t);
  1049  
  1050  	if(t->width == BADWIDTH)
  1051  		dowidth(t);
  1052  	
  1053  	switch(t->etype) {
  1054  	case TINT8:
  1055  	case TUINT8:
  1056  	case TINT16:
  1057  	case TUINT16:
  1058  	case TINT32:
  1059  	case TUINT32:
  1060  	case TINT64:
  1061  	case TUINT64:
  1062  	case TINT:
  1063  	case TUINT:
  1064  	case TUINTPTR:
  1065  	case TBOOL:
  1066  	case TFLOAT32:
  1067  	case TFLOAT64:
  1068  	case TCOMPLEX64:
  1069  	case TCOMPLEX128:
  1070  		*off += t->width;
  1071  		break;
  1072  
  1073  	case TPTR32:
  1074  	case TPTR64:
  1075  		// NOTE: Any changes here need to be made to reflect.PtrTo as well.
  1076  		if(*off % widthptr != 0)
  1077  			fatal("dgcsym1: invalid alignment, %T", t);
  1078  		if(!haspointers(t->type) || t->type->etype == TUINT8) {
  1079  			ot = duintptr(s, ot, GC_APTR);
  1080  			ot = duintptr(s, ot, *off);
  1081  		} else {
  1082  			ot = duintptr(s, ot, GC_PTR);
  1083  			ot = duintptr(s, ot, *off);
  1084  			ot = dsymptr(s, ot, dgcsym(t->type), 0);
  1085  		}
  1086  		*off += t->width;
  1087  		break;
  1088  
  1089  	case TUNSAFEPTR:
  1090  	case TFUNC:
  1091  		if(*off % widthptr != 0)
  1092  			fatal("dgcsym1: invalid alignment, %T", t);
  1093  		ot = duintptr(s, ot, GC_APTR);
  1094  		ot = duintptr(s, ot, *off);
  1095  		*off += t->width;
  1096  		break;
  1097  
  1098  	// struct Hchan*
  1099  	case TCHAN:
  1100  		// NOTE: Any changes here need to be made to reflect.ChanOf as well.
  1101  		if(*off % widthptr != 0)
  1102  			fatal("dgcsym1: invalid alignment, %T", t);
  1103  		ot = duintptr(s, ot, GC_CHAN_PTR);
  1104  		ot = duintptr(s, ot, *off);
  1105  		ot = dsymptr(s, ot, dtypesym(t), 0);
  1106  		*off += t->width;
  1107  		break;
  1108  
  1109  	// struct Hmap*
  1110  	case TMAP:
  1111  		// NOTE: Any changes here need to be made to reflect.MapOf as well.
  1112  		if(*off % widthptr != 0)
  1113  			fatal("dgcsym1: invalid alignment, %T", t);
  1114  		ot = duintptr(s, ot, GC_MAP_PTR);
  1115  		ot = duintptr(s, ot, *off);
  1116  		ot = dsymptr(s, ot, dtypesym(t), 0);
  1117  		*off += t->width;
  1118  		break;
  1119  
  1120  	// struct { byte *str; int32 len; }
  1121  	case TSTRING:
  1122  		if(*off % widthptr != 0)
  1123  			fatal("dgcsym1: invalid alignment, %T", t);
  1124  		ot = duintptr(s, ot, GC_STRING);
  1125  		ot = duintptr(s, ot, *off);
  1126  		*off += t->width;
  1127  		break;
  1128  
  1129  	// struct { Itab* tab;  void* data; }
  1130  	// struct { Type* type; void* data; }	// When isnilinter(t)==true
  1131  	case TINTER:
  1132  		if(*off % widthptr != 0)
  1133  			fatal("dgcsym1: invalid alignment, %T", t);
  1134  		if(isnilinter(t)) {
  1135  			ot = duintptr(s, ot, GC_EFACE);
  1136  			ot = duintptr(s, ot, *off);
  1137  		} else {
  1138  			ot = duintptr(s, ot, GC_IFACE);
  1139  			ot = duintptr(s, ot, *off);
  1140  		}
  1141  		*off += t->width;
  1142  		break;
  1143  
  1144  	case TARRAY:
  1145  		if(t->bound < -1)
  1146  			fatal("dgcsym1: invalid bound, %T", t);
  1147  		if(t->type->width == BADWIDTH)
  1148  			dowidth(t->type);
  1149  		if(isslice(t)) {
  1150  			// NOTE: Any changes here need to be made to reflect.SliceOf as well.
  1151  			// struct { byte* array; uint32 len; uint32 cap; }
  1152  			if(*off % widthptr != 0)
  1153  				fatal("dgcsym1: invalid alignment, %T", t);
  1154  			if(t->type->width != 0) {
  1155  				ot = duintptr(s, ot, GC_SLICE);
  1156  				ot = duintptr(s, ot, *off);
  1157  				ot = dsymptr(s, ot, dgcsym(t->type), 0);
  1158  			} else {
  1159  				ot = duintptr(s, ot, GC_APTR);
  1160  				ot = duintptr(s, ot, *off);
  1161  			}
  1162  			*off += t->width;
  1163  		} else {
  1164  			// NOTE: Any changes here need to be made to reflect.ArrayOf as well,
  1165  			// at least once ArrayOf's gc info is implemented and ArrayOf is exported.
  1166  			// struct { byte* array; uint32 len; uint32 cap; }
  1167  			if(t->bound < 1 || !haspointers(t->type)) {
  1168  				*off += t->width;
  1169  			} else if(gcinline(t)) {
  1170  				for(i=0; i<t->bound; i++)
  1171  					ot = dgcsym1(s, ot, t->type, off, stack_size);  // recursive call of dgcsym1
  1172  			} else {
  1173  				if(stack_size < GC_STACK_CAPACITY) {
  1174  					ot = duintptr(s, ot, GC_ARRAY_START);  // a stack push during GC
  1175  					ot = duintptr(s, ot, *off);
  1176  					ot = duintptr(s, ot, t->bound);
  1177  					ot = duintptr(s, ot, t->type->width);
  1178  					off2 = 0;
  1179  					ot = dgcsym1(s, ot, t->type, &off2, stack_size+1);  // recursive call of dgcsym1
  1180  					ot = duintptr(s, ot, GC_ARRAY_NEXT);  // a stack pop during GC
  1181  				} else {
  1182  					ot = duintptr(s, ot, GC_REGION);
  1183  					ot = duintptr(s, ot, *off);
  1184  					ot = duintptr(s, ot, t->width);
  1185  					ot = dsymptr(s, ot, dgcsym(t), 0);
  1186  				}
  1187  				*off += t->width;
  1188  			}
  1189  		}
  1190  		break;
  1191  
  1192  	case TSTRUCT:
  1193  		o = 0;
  1194  		for(t1=t->type; t1!=T; t1=t1->down) {
  1195  			fieldoffset = t1->width;
  1196  			*off += fieldoffset - o;
  1197  			ot = dgcsym1(s, ot, t1->type, off, stack_size);  // recursive call of dgcsym1
  1198  			o = fieldoffset + t1->type->width;
  1199  		}
  1200  		*off += t->width - o;
  1201  		break;
  1202  
  1203  	default:
  1204  		fatal("dgcsym1: unexpected type %T", t);
  1205  	}
  1206  
  1207  	return ot;
  1208  }
  1209  
  1210  static Sym*
  1211  dgcsym(Type *t)
  1212  {
  1213  	int ot;
  1214  	vlong off;
  1215  	Sym *s;
  1216  
  1217  	s = typesymprefix(".gc", t);
  1218  	if(s->flags & SymGcgen)
  1219  		return s;
  1220  	s->flags |= SymGcgen;
  1221  
  1222  	if(t->width == BADWIDTH)
  1223  		dowidth(t);
  1224  
  1225  	ot = 0;
  1226  	off = 0;
  1227  	ot = duintptr(s, ot, t->width);
  1228  	ot = dgcsym1(s, ot, t, &off, 0);
  1229  	ot = duintptr(s, ot, GC_END);
  1230  	ggloblsym(s, ot, 1, 1);
  1231  
  1232  	if(t->align > 0)
  1233  		off = rnd(off, t->align);
  1234  	if(off != t->width)
  1235  		fatal("dgcsym: off=%lld, size=%lld, type %T", off, t->width, t);
  1236  
  1237  	return s;
  1238  }