github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/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  // Builds a type respresenting a Bucket structure for
   105  // the given map type.  This type is not visible to users -
   106  // we include only enough information to generate a correct GC
   107  // program for it.
   108  // Make sure this stays in sync with ../../pkg/runtime/hashmap.c!
   109  enum {
   110  	BUCKETSIZE = 8,
   111  	MAXKEYSIZE = 128,
   112  	MAXVALSIZE = 128,
   113  };
   114  
   115  static Type*
   116  mapbucket(Type *t)
   117  {
   118  	Type *keytype, *valtype;
   119  	Type *bucket;
   120  	Type *overflowfield, *keysfield, *valuesfield;
   121  	int32 offset;
   122  
   123  	if(t->bucket != T)
   124  		return t->bucket;
   125  
   126  	keytype = t->down;
   127  	valtype = t->type;
   128  	dowidth(keytype);
   129  	dowidth(valtype);
   130  	if(keytype->width > MAXKEYSIZE)
   131  		keytype = ptrto(keytype);
   132  	if(valtype->width > MAXVALSIZE)
   133  		valtype = ptrto(valtype);
   134  
   135  	bucket = typ(TSTRUCT);
   136  	bucket->noalg = 1;
   137  
   138  	// The first field is: uint8 topbits[BUCKETSIZE].
   139  	// We don't need to encode it as GC doesn't care about it.
   140  	offset = BUCKETSIZE * 1;
   141  
   142  	overflowfield = typ(TFIELD);
   143  	overflowfield->type = ptrto(bucket);
   144  	overflowfield->width = offset;         // "width" is offset in structure
   145  	overflowfield->sym = mal(sizeof(Sym)); // not important but needs to be set to give this type a name
   146  	overflowfield->sym->name = "overflow";
   147  	offset += widthptr;
   148  	
   149  	// The keys are padded to the native integer alignment.
   150  	// This is usually the same as widthptr; the exception (as usual) is nacl/amd64.
   151  	if(widthreg > widthptr)
   152  		offset += widthreg - widthptr;
   153  
   154  	keysfield = typ(TFIELD);
   155  	keysfield->type = typ(TARRAY);
   156  	keysfield->type->type = keytype;
   157  	keysfield->type->bound = BUCKETSIZE;
   158  	keysfield->type->width = BUCKETSIZE * keytype->width;
   159  	keysfield->width = offset;
   160  	keysfield->sym = mal(sizeof(Sym));
   161  	keysfield->sym->name = "keys";
   162  	offset += BUCKETSIZE * keytype->width;
   163  
   164  	valuesfield = typ(TFIELD);
   165  	valuesfield->type = typ(TARRAY);
   166  	valuesfield->type->type = valtype;
   167  	valuesfield->type->bound = BUCKETSIZE;
   168  	valuesfield->type->width = BUCKETSIZE * valtype->width;
   169  	valuesfield->width = offset;
   170  	valuesfield->sym = mal(sizeof(Sym));
   171  	valuesfield->sym->name = "values";
   172  	offset += BUCKETSIZE * valtype->width;
   173  
   174  	// link up fields
   175  	bucket->type = overflowfield;
   176  	overflowfield->down = keysfield;
   177  	keysfield->down = valuesfield;
   178  	valuesfield->down = T;
   179  
   180  	bucket->width = offset;
   181  	bucket->local = t->local;
   182  	t->bucket = bucket;
   183  	bucket->map = t;
   184  	return bucket;
   185  }
   186  
   187  // Builds a type respresenting a Hmap structure for
   188  // the given map type.  This type is not visible to users -
   189  // we include only enough information to generate a correct GC
   190  // program for it.
   191  // Make sure this stays in sync with ../../pkg/runtime/hashmap.c!
   192  static Type*
   193  hmap(Type *t)
   194  {
   195  	Type *h, *bucket;
   196  	Type *bucketsfield, *oldbucketsfield;
   197  	int32 offset;
   198  
   199  	if(t->hmap != T)
   200  		return t->hmap;
   201  
   202  	bucket = mapbucket(t);
   203  	h = typ(TSTRUCT);
   204  	h->noalg = 1;
   205  
   206  	offset = widthint; // count
   207  	offset += 4;       // flags
   208  	offset += 4;       // hash0
   209  	offset += 1;       // B
   210  	offset += 1;       // keysize
   211  	offset += 1;       // valuesize
   212  	offset = (offset + 1) / 2 * 2;
   213  	offset += 2;       // bucketsize
   214  	offset = (offset + widthptr - 1) / widthptr * widthptr;
   215  	
   216  	bucketsfield = typ(TFIELD);
   217  	bucketsfield->type = ptrto(bucket);
   218  	bucketsfield->width = offset;
   219  	bucketsfield->sym = mal(sizeof(Sym));
   220  	bucketsfield->sym->name = "buckets";
   221  	offset += widthptr;
   222  
   223  	oldbucketsfield = typ(TFIELD);
   224  	oldbucketsfield->type = ptrto(bucket);
   225  	oldbucketsfield->width = offset;
   226  	oldbucketsfield->sym = mal(sizeof(Sym));
   227  	oldbucketsfield->sym->name = "oldbuckets";
   228  	offset += widthptr;
   229  
   230  	offset += widthptr; // nevacuate (last field in Hmap)
   231  
   232  	// link up fields
   233  	h->type = bucketsfield;
   234  	bucketsfield->down = oldbucketsfield;
   235  	oldbucketsfield->down = T;
   236  
   237  	h->width = offset;
   238  	h->local = t->local;
   239  	t->hmap = h;
   240  	h->map = t;
   241  	return h;
   242  }
   243  
   244  Type*
   245  hiter(Type *t)
   246  {
   247  	int32 n, off;
   248  	Type *field[7];
   249  	Type *i;
   250  
   251  	if(t->hiter != T)
   252  		return t->hiter;
   253  
   254  	// build a struct:
   255  	// hash_iter {
   256  	//    key *Key
   257  	//    val *Value
   258  	//    t *MapType
   259  	//    h *Hmap
   260  	//    buckets *Bucket
   261  	//    bptr *Bucket
   262  	//    other [4]uintptr
   263  	// }
   264  	// must match ../../pkg/runtime/hashmap.c:hash_iter.
   265  	field[0] = typ(TFIELD);
   266  	field[0]->type = ptrto(t->down);
   267  	field[0]->sym = mal(sizeof(Sym));
   268  	field[0]->sym->name = "key";
   269  	
   270  	field[1] = typ(TFIELD);
   271  	field[1]->type = ptrto(t->type);
   272  	field[1]->sym = mal(sizeof(Sym));
   273  	field[1]->sym->name = "val";
   274  	
   275  	field[2] = typ(TFIELD);
   276  	field[2]->type = ptrto(types[TUINT8]); // TODO: is there a Type type?
   277  	field[2]->sym = mal(sizeof(Sym));
   278  	field[2]->sym->name = "t";
   279  	
   280  	field[3] = typ(TFIELD);
   281  	field[3]->type = ptrto(hmap(t));
   282  	field[3]->sym = mal(sizeof(Sym));
   283  	field[3]->sym->name = "h";
   284  	
   285  	field[4] = typ(TFIELD);
   286  	field[4]->type = ptrto(mapbucket(t));
   287  	field[4]->sym = mal(sizeof(Sym));
   288  	field[4]->sym->name = "buckets";
   289  	
   290  	field[5] = typ(TFIELD);
   291  	field[5]->type = ptrto(mapbucket(t));
   292  	field[5]->sym = mal(sizeof(Sym));
   293  	field[5]->sym->name = "bptr";
   294  	
   295  	// all other non-pointer fields
   296  	field[6] = typ(TFIELD);
   297  	field[6]->type = typ(TARRAY);
   298  	field[6]->type->type = types[TUINTPTR];
   299  	field[6]->type->bound = 4;
   300  	field[6]->type->width = 4 * widthptr;
   301  	field[6]->sym = mal(sizeof(Sym));
   302  	field[6]->sym->name = "other";
   303  	
   304  	// build iterator struct holding the above fields
   305  	i = typ(TSTRUCT);
   306  	i->noalg = 1;
   307  	i->type = field[0];
   308  	off = 0;
   309  	for(n = 0; n < 6; n++) {
   310  		field[n]->down = field[n+1];
   311  		field[n]->width = off;
   312  		off += field[n]->type->width;
   313  	}
   314  	field[6]->down = T;
   315  	off += field[6]->type->width;
   316  	if(off != 10 * widthptr)
   317  		yyerror("hash_iter size not correct %d %d", off, 10 * widthptr);
   318  	t->hiter = i;
   319  	i->map = t;
   320  	return i;
   321  }
   322  
   323  /*
   324   * f is method type, with receiver.
   325   * return function type, receiver as first argument (or not).
   326   */
   327  Type*
   328  methodfunc(Type *f, Type *receiver)
   329  {
   330  	NodeList *in, *out;
   331  	Node *d;
   332  	Type *t;
   333  
   334  	in = nil;
   335  	if(receiver) {
   336  		d = nod(ODCLFIELD, N, N);
   337  		d->type = receiver;
   338  		in = list(in, d);
   339  	}
   340  	for(t=getinargx(f)->type; t; t=t->down) {
   341  		d = nod(ODCLFIELD, N, N);
   342  		d->type = t->type;
   343  		d->isddd = t->isddd;
   344  		in = list(in, d);
   345  	}
   346  
   347  	out = nil;
   348  	for(t=getoutargx(f)->type; t; t=t->down) {
   349  		d = nod(ODCLFIELD, N, N);
   350  		d->type = t->type;
   351  		out = list(out, d);
   352  	}
   353  
   354  	t = functype(N, in, out);
   355  	if(f->nname) {
   356  		// Link to name of original method function.
   357  		t->nname = f->nname;
   358  	}
   359  	return t;
   360  }
   361  
   362  /*
   363   * return methods of non-interface type t, sorted by name.
   364   * generates stub functions as needed.
   365   */
   366  static Sig*
   367  methods(Type *t)
   368  {
   369  	Type *f, *mt, *it, *this;
   370  	Sig *a, *b;
   371  	Sym *method;
   372  
   373  	// method type
   374  	mt = methtype(t, 0);
   375  	if(mt == T)
   376  		return nil;
   377  	expandmeth(mt);
   378  
   379  	// type stored in interface word
   380  	it = t;
   381  	if(it->width > widthptr)
   382  		it = ptrto(t);
   383  
   384  	// make list of methods for t,
   385  	// generating code if necessary.
   386  	a = nil;
   387  	for(f=mt->xmethod; f; f=f->down) {
   388  		if(f->etype != TFIELD)
   389  			fatal("methods: not field %T", f);
   390  		if (f->type->etype != TFUNC || f->type->thistuple == 0)
   391  			fatal("non-method on %T method %S %T\n", mt, f->sym, f);
   392  		if (!getthisx(f->type)->type)
   393  			fatal("receiver with no type on %T method %S %T\n", mt, f->sym, f);
   394  		if(f->nointerface)
   395  			continue;
   396  
   397  		method = f->sym;
   398  		if(method == nil)
   399  			continue;
   400  
   401  		// get receiver type for this particular method.
   402  		// if pointer receiver but non-pointer t and
   403  		// this is not an embedded pointer inside a struct,
   404  		// method does not apply.
   405  		this = getthisx(f->type)->type->type;
   406  		if(isptr[this->etype] && this->type == t)
   407  			continue;
   408  		if(isptr[this->etype] && !isptr[t->etype]
   409  		&& f->embedded != 2 && !isifacemethod(f->type))
   410  			continue;
   411  
   412  		b = mal(sizeof(*b));
   413  		b->link = a;
   414  		a = b;
   415  
   416  		a->name = method->name;
   417  		if(!exportname(method->name)) {
   418  			if(method->pkg == nil)
   419  				fatal("methods: missing package");
   420  			a->pkg = method->pkg;
   421  		}
   422  		a->isym = methodsym(method, it, 1);
   423  		a->tsym = methodsym(method, t, 0);
   424  		a->type = methodfunc(f->type, t);
   425  		a->mtype = methodfunc(f->type, nil);
   426  
   427  		if(!(a->isym->flags & SymSiggen)) {
   428  			a->isym->flags |= SymSiggen;
   429  			if(!eqtype(this, it) || this->width < types[tptr]->width) {
   430  				compiling_wrappers = 1;
   431  				genwrapper(it, f, a->isym, 1);
   432  				compiling_wrappers = 0;
   433  			}
   434  		}
   435  
   436  		if(!(a->tsym->flags & SymSiggen)) {
   437  			a->tsym->flags |= SymSiggen;
   438  			if(!eqtype(this, t)) {
   439  				compiling_wrappers = 1;
   440  				genwrapper(t, f, a->tsym, 0);
   441  				compiling_wrappers = 0;
   442  			}
   443  		}
   444  	}
   445  
   446  	return lsort(a, sigcmp);
   447  }
   448  
   449  /*
   450   * return methods of interface type t, sorted by name.
   451   */
   452  static Sig*
   453  imethods(Type *t)
   454  {
   455  	Sig *a, *all, *last;
   456  	Type *f;
   457  	Sym *method, *isym;
   458  
   459  	all = nil;
   460  	last = nil;
   461  	for(f=t->type; f; f=f->down) {
   462  		if(f->etype != TFIELD)
   463  			fatal("imethods: not field");
   464  		if(f->type->etype != TFUNC || f->sym == nil)
   465  			continue;
   466  		method = f->sym;
   467  		a = mal(sizeof(*a));
   468  		a->name = method->name;
   469  		if(!exportname(method->name)) {
   470  			if(method->pkg == nil)
   471  				fatal("imethods: missing package");
   472  			a->pkg = method->pkg;
   473  		}
   474  		a->mtype = f->type;
   475  		a->offset = 0;
   476  		a->type = methodfunc(f->type, nil);
   477  
   478  		if(last && sigcmp(last, a) >= 0)
   479  			fatal("sigcmp vs sortinter %s %s", last->name, a->name);
   480  		if(last == nil)
   481  			all = a;
   482  		else
   483  			last->link = a;
   484  		last = a;
   485  
   486  		// Compiler can only refer to wrappers for non-blank methods.
   487  		if(isblanksym(method))
   488  			continue;
   489  
   490  		// NOTE(rsc): Perhaps an oversight that
   491  		// IfaceType.Method is not in the reflect data.
   492  		// Generate the method body, so that compiled
   493  		// code can refer to it.
   494  		isym = methodsym(method, t, 0);
   495  		if(!(isym->flags & SymSiggen)) {
   496  			isym->flags |= SymSiggen;
   497  			genwrapper(t, f, isym, 0);
   498  		}
   499  	}
   500  	return all;
   501  }
   502  
   503  static void
   504  dimportpath(Pkg *p)
   505  {
   506  	static Pkg *gopkg;
   507  	char *nam;
   508  	Node *n;
   509  
   510  	if(p->pathsym != S)
   511  		return;
   512  
   513  	if(gopkg == nil) {
   514  		gopkg = mkpkg(strlit("go"));
   515  		gopkg->name = "go";
   516  	}
   517  	nam = smprint("importpath.%s.", p->prefix);
   518  
   519  	n = nod(ONAME, N, N);
   520  	n->sym = pkglookup(nam, gopkg);
   521  	free(nam);
   522  	n->class = PEXTERN;
   523  	n->xoffset = 0;
   524  	p->pathsym = n->sym;
   525  
   526  	gdatastring(n, p->path);
   527  	ggloblsym(n->sym, types[TSTRING]->width, 1, 1);
   528  }
   529  
   530  static int
   531  dgopkgpath(Sym *s, int ot, Pkg *pkg)
   532  {
   533  	if(pkg == nil)
   534  		return dgostringptr(s, ot, nil);
   535  
   536  	// Emit reference to go.importpath.""., which 6l will
   537  	// rewrite using the correct import path.  Every package
   538  	// that imports this one directly defines the symbol.
   539  	if(pkg == localpkg) {
   540  		static Sym *ns;
   541  
   542  		if(ns == nil)
   543  			ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
   544  		return dsymptr(s, ot, ns, 0);
   545  	}
   546  
   547  	dimportpath(pkg);
   548  	return dsymptr(s, ot, pkg->pathsym, 0);
   549  }
   550  
   551  /*
   552   * uncommonType
   553   * ../../pkg/runtime/type.go:/uncommonType
   554   */
   555  static int
   556  dextratype(Sym *sym, int off, Type *t, int ptroff)
   557  {
   558  	int ot, n;
   559  	Sym *s;
   560  	Sig *a, *m;
   561  
   562  	m = methods(t);
   563  	if(t->sym == nil && m == nil)
   564  		return off;
   565  
   566  	// fill in *extraType pointer in header
   567  	dsymptr(sym, ptroff, sym, off);
   568  
   569  	n = 0;
   570  	for(a=m; a; a=a->link) {
   571  		dtypesym(a->type);
   572  		n++;
   573  	}
   574  
   575  	ot = off;
   576  	s = sym;
   577  	if(t->sym) {
   578  		ot = dgostringptr(s, ot, t->sym->name);
   579  		if(t != types[t->etype] && t != errortype)
   580  			ot = dgopkgpath(s, ot, t->sym->pkg);
   581  		else
   582  			ot = dgostringptr(s, ot, nil);
   583  	} else {
   584  		ot = dgostringptr(s, ot, nil);
   585  		ot = dgostringptr(s, ot, nil);
   586  	}
   587  
   588  	// slice header
   589  	ot = dsymptr(s, ot, s, ot + widthptr + 2*widthint);
   590  	ot = duintxx(s, ot, n, widthint);
   591  	ot = duintxx(s, ot, n, widthint);
   592  
   593  	// methods
   594  	for(a=m; a; a=a->link) {
   595  		// method
   596  		// ../../pkg/runtime/type.go:/method
   597  		ot = dgostringptr(s, ot, a->name);
   598  		ot = dgopkgpath(s, ot, a->pkg);
   599  		ot = dsymptr(s, ot, dtypesym(a->mtype), 0);
   600  		ot = dsymptr(s, ot, dtypesym(a->type), 0);
   601  		if(a->isym)
   602  			ot = dsymptr(s, ot, a->isym, 0);
   603  		else
   604  			ot = duintptr(s, ot, 0);
   605  		if(a->tsym)
   606  			ot = dsymptr(s, ot, a->tsym, 0);
   607  		else
   608  			ot = duintptr(s, ot, 0);
   609  	}
   610  
   611  	return ot;
   612  }
   613  
   614  enum {
   615  	KindBool = 1,
   616  	KindInt,
   617  	KindInt8,
   618  	KindInt16,
   619  	KindInt32,
   620  	KindInt64,
   621  	KindUint,
   622  	KindUint8,
   623  	KindUint16,
   624  	KindUint32,
   625  	KindUint64,
   626  	KindUintptr,
   627  	KindFloat32,
   628  	KindFloat64,
   629  	KindComplex64,
   630  	KindComplex128,
   631  	KindArray,
   632  	KindChan,
   633  	KindFunc,
   634  	KindInterface,
   635  	KindMap,
   636  	KindPtr,
   637  	KindSlice,
   638  	KindString,
   639  	KindStruct,
   640  	KindUnsafePointer,
   641  
   642  	KindNoPointers = 1<<7,
   643  };
   644  
   645  static int
   646  kinds[] =
   647  {
   648  	[TINT]		= KindInt,
   649  	[TUINT]		= KindUint,
   650  	[TINT8]		= KindInt8,
   651  	[TUINT8]	= KindUint8,
   652  	[TINT16]	= KindInt16,
   653  	[TUINT16]	= KindUint16,
   654  	[TINT32]	= KindInt32,
   655  	[TUINT32]	= KindUint32,
   656  	[TINT64]	= KindInt64,
   657  	[TUINT64]	= KindUint64,
   658  	[TUINTPTR]	= KindUintptr,
   659  	[TFLOAT32]	= KindFloat32,
   660  	[TFLOAT64]	= KindFloat64,
   661  	[TBOOL]		= KindBool,
   662  	[TSTRING]		= KindString,
   663  	[TPTR32]		= KindPtr,
   664  	[TPTR64]		= KindPtr,
   665  	[TSTRUCT]	= KindStruct,
   666  	[TINTER]		= KindInterface,
   667  	[TCHAN]		= KindChan,
   668  	[TMAP]		= KindMap,
   669  	[TARRAY]		= KindArray,
   670  	[TFUNC]		= KindFunc,
   671  	[TCOMPLEX64]	= KindComplex64,
   672  	[TCOMPLEX128]	= KindComplex128,
   673  	[TUNSAFEPTR]	= KindUnsafePointer,
   674  };
   675  
   676  int
   677  haspointers(Type *t)
   678  {
   679  	Type *t1;
   680  	int ret;
   681  
   682  	if(t->haspointers != 0)
   683  		return t->haspointers - 1;
   684  
   685  	switch(t->etype) {
   686  	case TINT:
   687  	case TUINT:
   688  	case TINT8:
   689  	case TUINT8:
   690  	case TINT16:
   691  	case TUINT16:
   692  	case TINT32:
   693  	case TUINT32:
   694  	case TINT64:
   695  	case TUINT64:
   696  	case TUINTPTR:
   697  	case TFLOAT32:
   698  	case TFLOAT64:
   699  	case TCOMPLEX64:
   700  	case TCOMPLEX128:
   701  	case TBOOL:
   702  		ret = 0;
   703  		break;
   704  	case TARRAY:
   705  		if(t->bound < 0) {	// slice
   706  			ret = 1;
   707  			break;
   708  		}
   709  		if(t->bound == 0) {	// empty array
   710  			ret = 0;
   711  			break;
   712  		}
   713  		ret = haspointers(t->type);
   714  		break;
   715  	case TSTRUCT:
   716  		ret = 0;
   717  		for(t1=t->type; t1!=T; t1=t1->down) {
   718  			if(haspointers(t1->type)) {
   719  				ret = 1;
   720  				break;
   721  			}
   722  		}
   723  		break;
   724  	case TSTRING:
   725  	case TPTR32:
   726  	case TPTR64:
   727  	case TUNSAFEPTR:
   728  	case TINTER:
   729  	case TCHAN:
   730  	case TMAP:
   731  	case TFUNC:
   732  	default:
   733  		ret = 1;
   734  		break;
   735  	}
   736  	
   737  	t->haspointers = 1+ret;
   738  	return ret;
   739  }
   740  
   741  /*
   742   * commonType
   743   * ../../pkg/runtime/type.go:/commonType
   744   */
   745  static int
   746  dcommontype(Sym *s, int ot, Type *t)
   747  {
   748  	int i, alg, sizeofAlg;
   749  	Sym *sptr, *algsym, *zero;
   750  	static Sym *algarray;
   751  	char *p;
   752  	
   753  	if(ot != 0)
   754  		fatal("dcommontype %d", ot);
   755  
   756  	sizeofAlg = 4*widthptr;
   757  	if(algarray == nil)
   758  		algarray = pkglookup("algarray", runtimepkg);
   759  	alg = algtype(t);
   760  	algsym = S;
   761  	if(alg < 0)
   762  		algsym = dalgsym(t);
   763  
   764  	dowidth(t);
   765  	if(t->sym != nil && !isptr[t->etype])
   766  		sptr = dtypesym(ptrto(t));
   767  	else
   768  		sptr = weaktypesym(ptrto(t));
   769  
   770  	// All (non-reflect-allocated) Types share the same zero object.
   771  	// Each place in the compiler where a pointer to the zero object
   772  	// might be returned by a runtime call (map access return value,
   773  	// 2-arg type cast) declares the size of the zerovalue it needs.
   774  	// The linker magically takes the max of all the sizes.
   775  	zero = pkglookup("zerovalue", runtimepkg);
   776  
   777  	// We use size 0 here so we get the pointer to the zero value,
   778  	// but don't allocate space for the zero value unless we need it.
   779  	// TODO: how do we get this symbol into bss?  We really want
   780  	// a read-only bss, but I don't think such a thing exists.
   781  
   782  	// ../../pkg/reflect/type.go:/^type.commonType
   783  	// actual type structure
   784  	//	type commonType struct {
   785  	//		size          uintptr
   786  	//		hash          uint32
   787  	//		_             uint8
   788  	//		align         uint8
   789  	//		fieldAlign    uint8
   790  	//		kind          uint8
   791  	//		alg           unsafe.Pointer
   792  	//		gc            unsafe.Pointer
   793  	//		string        *string
   794  	//		*extraType
   795  	//		ptrToThis     *Type
   796  	//		zero          unsafe.Pointer
   797  	//	}
   798  	ot = duintptr(s, ot, t->width);
   799  	ot = duint32(s, ot, typehash(t));
   800  	ot = duint8(s, ot, 0);	// unused
   801  
   802  	// runtime (and common sense) expects alignment to be a power of two.
   803  	i = t->align;
   804  	if(i == 0)
   805  		i = 1;
   806  	if((i&(i-1)) != 0)
   807  		fatal("invalid alignment %d for %T", t->align, t);
   808  	ot = duint8(s, ot, t->align);	// align
   809  	ot = duint8(s, ot, t->align);	// fieldAlign
   810  
   811  	i = kinds[t->etype];
   812  	if(t->etype == TARRAY && t->bound < 0)
   813  		i = KindSlice;
   814  	if(!haspointers(t))
   815  		i |= KindNoPointers;
   816  	ot = duint8(s, ot, i);  // kind
   817  	if(alg >= 0)
   818  		ot = dsymptr(s, ot, algarray, alg*sizeofAlg);
   819  	else
   820  		ot = dsymptr(s, ot, algsym, 0);
   821  	ot = dsymptr(s, ot, dgcsym(t), 0);  // gc
   822  	p = smprint("%-uT", t);
   823  	//print("dcommontype: %s\n", p);
   824  	ot = dgostringptr(s, ot, p);	// string
   825  	free(p);
   826  
   827  	// skip pointer to extraType,
   828  	// which follows the rest of this type structure.
   829  	// caller will fill in if needed.
   830  	// otherwise linker will assume 0.
   831  	ot += widthptr;
   832  
   833  	ot = dsymptr(s, ot, sptr, 0);  // ptrto type
   834  	ot = dsymptr(s, ot, zero, 0);  // ptr to zero value
   835  	return ot;
   836  }
   837  
   838  Sym*
   839  typesym(Type *t)
   840  {
   841  	char *p;
   842  	Sym *s;
   843  
   844  	p = smprint("%-T", t);
   845  	s = pkglookup(p, typepkg);
   846  	//print("typesym: %s -> %+S\n", p, s);
   847  	free(p);
   848  	return s;
   849  }
   850  
   851  Sym*
   852  tracksym(Type *t)
   853  {
   854  	char *p;
   855  	Sym *s;
   856  
   857  	p = smprint("%-T.%s", t->outer, t->sym->name);
   858  	s = pkglookup(p, trackpkg);
   859  	free(p);
   860  	return s;
   861  }
   862  
   863  Sym*
   864  typelinksym(Type *t)
   865  {
   866  	char *p;
   867  	Sym *s;
   868  
   869  	// %-uT is what the generated Type's string field says.
   870  	// It uses (ambiguous) package names instead of import paths.
   871  	// %-T is the complete, unambiguous type name.
   872  	// We want the types to end up sorted by string field,
   873  	// so use that first in the name, and then add :%-T to
   874  	// disambiguate. The names are a little long but they are
   875  	// discarded by the linker and do not end up in the symbol
   876  	// table of the final binary.
   877  	p = smprint("%-uT/%-T", t, t);
   878  	s = pkglookup(p, typelinkpkg);
   879  	//print("typelinksym: %s -> %+S\n", p, s);
   880  	free(p);
   881  	return s;
   882  }
   883  
   884  Sym*
   885  typesymprefix(char *prefix, Type *t)
   886  {
   887  	char *p;
   888  	Sym *s;
   889  
   890  	p = smprint("%s.%-T", prefix, t);
   891  	s = pkglookup(p, typepkg);
   892  	//print("algsym: %s -> %+S\n", p, s);
   893  	free(p);
   894  	return s;
   895  }
   896  
   897  Sym*
   898  typenamesym(Type *t)
   899  {
   900  	Sym *s;
   901  	Node *n;
   902  
   903  	if(t == T || (isptr[t->etype] && t->type == T) || isideal(t))
   904  		fatal("typename %T", t);
   905  	s = typesym(t);
   906  	if(s->def == N) {
   907  		n = nod(ONAME, N, N);
   908  		n->sym = s;
   909  		n->type = types[TUINT8];
   910  		n->addable = 1;
   911  		n->ullman = 1;
   912  		n->class = PEXTERN;
   913  		n->xoffset = 0;
   914  		n->typecheck = 1;
   915  		s->def = n;
   916  
   917  		signatlist = list(signatlist, typenod(t));
   918  	}
   919  	return s->def->sym;
   920  }
   921  
   922  Node*
   923  typename(Type *t)
   924  {
   925  	Sym *s;
   926  	Node *n;
   927  
   928  	s = typenamesym(t);
   929  	n = nod(OADDR, s->def, N);
   930  	n->type = ptrto(s->def->type);
   931  	n->addable = 1;
   932  	n->ullman = 2;
   933  	n->typecheck = 1;
   934  	return n;
   935  }
   936  
   937  static Sym*
   938  weaktypesym(Type *t)
   939  {
   940  	char *p;
   941  	Sym *s;
   942  
   943  	p = smprint("%-T", t);
   944  	s = pkglookup(p, weaktypepkg);
   945  	//print("weaktypesym: %s -> %+S\n", p, s);
   946  	free(p);
   947  	return s;
   948  }
   949  
   950  static Sym*
   951  dtypesym(Type *t)
   952  {
   953  	int ot, xt, n, isddd, dupok;
   954  	Sym *s, *s1, *s2, *s3, *s4, *slink;
   955  	Sig *a, *m;
   956  	Type *t1, *tbase, *t2;
   957  
   958  	// Replace byte, rune aliases with real type.
   959  	// They've been separate internally to make error messages
   960  	// better, but we have to merge them in the reflect tables.
   961  	if(t == bytetype || t == runetype)
   962  		t = types[t->etype];
   963  
   964  	if(isideal(t))
   965  		fatal("dtypesym %T", t);
   966  
   967  	s = typesym(t);
   968  	if(s->flags & SymSiggen)
   969  		return s;
   970  	s->flags |= SymSiggen;
   971  
   972  	// special case (look for runtime below):
   973  	// when compiling package runtime,
   974  	// emit the type structures for int, float, etc.
   975  	tbase = t;
   976  	if(isptr[t->etype] && t->sym == S && t->type->sym != S)
   977  		tbase = t->type;
   978  	dupok = tbase->sym == S;
   979  
   980  	if(compiling_runtime &&
   981  			(tbase == types[tbase->etype] ||
   982  			tbase == bytetype ||
   983  			tbase == runetype ||
   984  			tbase == errortype)) { // int, float, etc
   985  		goto ok;
   986  	}
   987  
   988  	// named types from other files are defined only by those files
   989  	if(tbase->sym && !tbase->local)
   990  		return s;
   991  	if(isforw[tbase->etype])
   992  		return s;
   993  
   994  ok:
   995  	ot = 0;
   996  	xt = 0;
   997  	switch(t->etype) {
   998  	default:
   999  		ot = dcommontype(s, ot, t);
  1000  		xt = ot - 3*widthptr;
  1001  		break;
  1002  
  1003  	case TARRAY:
  1004  		if(t->bound >= 0) {
  1005  			// ../../pkg/runtime/type.go:/ArrayType
  1006  			s1 = dtypesym(t->type);
  1007  			t2 = typ(TARRAY);
  1008  			t2->type = t->type;
  1009  			t2->bound = -1;  // slice
  1010  			s2 = dtypesym(t2);
  1011  			ot = dcommontype(s, ot, t);
  1012  			xt = ot - 3*widthptr;
  1013  			ot = dsymptr(s, ot, s1, 0);
  1014  			ot = dsymptr(s, ot, s2, 0);
  1015  			ot = duintptr(s, ot, t->bound);
  1016  		} else {
  1017  			// ../../pkg/runtime/type.go:/SliceType
  1018  			s1 = dtypesym(t->type);
  1019  			ot = dcommontype(s, ot, t);
  1020  			xt = ot - 3*widthptr;
  1021  			ot = dsymptr(s, ot, s1, 0);
  1022  		}
  1023  		break;
  1024  
  1025  	case TCHAN:
  1026  		// ../../pkg/runtime/type.go:/ChanType
  1027  		s1 = dtypesym(t->type);
  1028  		ot = dcommontype(s, ot, t);
  1029  		xt = ot - 3*widthptr;
  1030  		ot = dsymptr(s, ot, s1, 0);
  1031  		ot = duintptr(s, ot, t->chan);
  1032  		break;
  1033  
  1034  	case TFUNC:
  1035  		for(t1=getthisx(t)->type; t1; t1=t1->down)
  1036  			dtypesym(t1->type);
  1037  		isddd = 0;
  1038  		for(t1=getinargx(t)->type; t1; t1=t1->down) {
  1039  			isddd = t1->isddd;
  1040  			dtypesym(t1->type);
  1041  		}
  1042  		for(t1=getoutargx(t)->type; t1; t1=t1->down)
  1043  			dtypesym(t1->type);
  1044  
  1045  		ot = dcommontype(s, ot, t);
  1046  		xt = ot - 3*widthptr;
  1047  		ot = duint8(s, ot, isddd);
  1048  
  1049  		// two slice headers: in and out.
  1050  		ot = rnd(ot, widthptr);
  1051  		ot = dsymptr(s, ot, s, ot+2*(widthptr+2*widthint));
  1052  		n = t->thistuple + t->intuple;
  1053  		ot = duintxx(s, ot, n, widthint);
  1054  		ot = duintxx(s, ot, n, widthint);
  1055  		ot = dsymptr(s, ot, s, ot+1*(widthptr+2*widthint)+n*widthptr);
  1056  		ot = duintxx(s, ot, t->outtuple, widthint);
  1057  		ot = duintxx(s, ot, t->outtuple, widthint);
  1058  
  1059  		// slice data
  1060  		for(t1=getthisx(t)->type; t1; t1=t1->down, n++)
  1061  			ot = dsymptr(s, ot, dtypesym(t1->type), 0);
  1062  		for(t1=getinargx(t)->type; t1; t1=t1->down, n++)
  1063  			ot = dsymptr(s, ot, dtypesym(t1->type), 0);
  1064  		for(t1=getoutargx(t)->type; t1; t1=t1->down, n++)
  1065  			ot = dsymptr(s, ot, dtypesym(t1->type), 0);
  1066  		break;
  1067  
  1068  	case TINTER:
  1069  		m = imethods(t);
  1070  		n = 0;
  1071  		for(a=m; a; a=a->link) {
  1072  			dtypesym(a->type);
  1073  			n++;
  1074  		}
  1075  
  1076  		// ../../pkg/runtime/type.go:/InterfaceType
  1077  		ot = dcommontype(s, ot, t);
  1078  		xt = ot - 3*widthptr;
  1079  		ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
  1080  		ot = duintxx(s, ot, n, widthint);
  1081  		ot = duintxx(s, ot, n, widthint);
  1082  		for(a=m; a; a=a->link) {
  1083  			// ../../pkg/runtime/type.go:/imethod
  1084  			ot = dgostringptr(s, ot, a->name);
  1085  			ot = dgopkgpath(s, ot, a->pkg);
  1086  			ot = dsymptr(s, ot, dtypesym(a->type), 0);
  1087  		}
  1088  		break;
  1089  
  1090  	case TMAP:
  1091  		// ../../pkg/runtime/type.go:/MapType
  1092  		s1 = dtypesym(t->down);
  1093  		s2 = dtypesym(t->type);
  1094  		s3 = dtypesym(mapbucket(t));
  1095  		s4 = dtypesym(hmap(t));
  1096  		ot = dcommontype(s, ot, t);
  1097  		xt = ot - 3*widthptr;
  1098  		ot = dsymptr(s, ot, s1, 0);
  1099  		ot = dsymptr(s, ot, s2, 0);
  1100  		ot = dsymptr(s, ot, s3, 0);
  1101  		ot = dsymptr(s, ot, s4, 0);
  1102  		break;
  1103  
  1104  	case TPTR32:
  1105  	case TPTR64:
  1106  		if(t->type->etype == TANY) {
  1107  			// ../../pkg/runtime/type.go:/UnsafePointerType
  1108  			ot = dcommontype(s, ot, t);
  1109  			break;
  1110  		}
  1111  		// ../../pkg/runtime/type.go:/PtrType
  1112  		s1 = dtypesym(t->type);
  1113  		ot = dcommontype(s, ot, t);
  1114  		xt = ot - 3*widthptr;
  1115  		ot = dsymptr(s, ot, s1, 0);
  1116  		break;
  1117  
  1118  	case TSTRUCT:
  1119  		// ../../pkg/runtime/type.go:/StructType
  1120  		// for security, only the exported fields.
  1121  		n = 0;
  1122  		for(t1=t->type; t1!=T; t1=t1->down) {
  1123  			dtypesym(t1->type);
  1124  			n++;
  1125  		}
  1126  		ot = dcommontype(s, ot, t);
  1127  		xt = ot - 3*widthptr;
  1128  		ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
  1129  		ot = duintxx(s, ot, n, widthint);
  1130  		ot = duintxx(s, ot, n, widthint);
  1131  		for(t1=t->type; t1!=T; t1=t1->down) {
  1132  			// ../../pkg/runtime/type.go:/structField
  1133  			if(t1->sym && !t1->embedded) {
  1134  				ot = dgostringptr(s, ot, t1->sym->name);
  1135  				if(exportname(t1->sym->name))
  1136  					ot = dgostringptr(s, ot, nil);
  1137  				else
  1138  					ot = dgopkgpath(s, ot, t1->sym->pkg);
  1139  			} else {
  1140  				ot = dgostringptr(s, ot, nil);
  1141  				if(t1->type->sym != S && t1->type->sym->pkg == builtinpkg)
  1142  					ot = dgopkgpath(s, ot, localpkg);
  1143  				else
  1144  					ot = dgostringptr(s, ot, nil);
  1145  			}
  1146  			ot = dsymptr(s, ot, dtypesym(t1->type), 0);
  1147  			ot = dgostrlitptr(s, ot, t1->note);
  1148  			ot = duintptr(s, ot, t1->width);	// field offset
  1149  		}
  1150  		break;
  1151  	}
  1152  	ot = dextratype(s, ot, t, xt);
  1153  	ggloblsym(s, ot, dupok, 1);
  1154  
  1155  	// generate typelink.foo pointing at s = type.foo.
  1156  	// The linker will leave a table of all the typelinks for
  1157  	// types in the binary, so reflect can find them.
  1158  	// We only need the link for unnamed composites that
  1159  	// we want be able to find.
  1160  	if(t->sym == S) {
  1161  		switch(t->etype) {
  1162  		case TARRAY:
  1163  		case TCHAN:
  1164  		case TMAP:
  1165  			slink = typelinksym(t);
  1166  			dsymptr(slink, 0, s, 0);
  1167  			ggloblsym(slink, widthptr, dupok, 1);
  1168  		}
  1169  	}
  1170  
  1171  	return s;
  1172  }
  1173  
  1174  void
  1175  dumptypestructs(void)
  1176  {
  1177  	int i;
  1178  	NodeList *l;
  1179  	Node *n;
  1180  	Type *t;
  1181  	Pkg *p;
  1182  
  1183  	// copy types from externdcl list to signatlist
  1184  	for(l=externdcl; l; l=l->next) {
  1185  		n = l->n;
  1186  		if(n->op != OTYPE)
  1187  			continue;
  1188  		signatlist = list(signatlist, n);
  1189  	}
  1190  
  1191  	// process signatlist
  1192  	for(l=signatlist; l; l=l->next) {
  1193  		n = l->n;
  1194  		if(n->op != OTYPE)
  1195  			continue;
  1196  		t = n->type;
  1197  		dtypesym(t);
  1198  		if(t->sym)
  1199  			dtypesym(ptrto(t));
  1200  	}
  1201  
  1202  	// generate import strings for imported packages
  1203  	for(i=0; i<nelem(phash); i++)
  1204  		for(p=phash[i]; p; p=p->link)
  1205  			if(p->direct)
  1206  				dimportpath(p);
  1207  
  1208  	// do basic types if compiling package runtime.
  1209  	// they have to be in at least one package,
  1210  	// and runtime is always loaded implicitly,
  1211  	// so this is as good as any.
  1212  	// another possible choice would be package main,
  1213  	// but using runtime means fewer copies in .6 files.
  1214  	if(compiling_runtime) {
  1215  		for(i=1; i<=TBOOL; i++)
  1216  			dtypesym(ptrto(types[i]));
  1217  		dtypesym(ptrto(types[TSTRING]));
  1218  		dtypesym(ptrto(types[TUNSAFEPTR]));
  1219  
  1220  		// emit type structs for error and func(error) string.
  1221  		// The latter is the type of an auto-generated wrapper.
  1222  		dtypesym(ptrto(errortype));
  1223  		dtypesym(functype(nil,
  1224  			list1(nod(ODCLFIELD, N, typenod(errortype))),
  1225  			list1(nod(ODCLFIELD, N, typenod(types[TSTRING])))));
  1226  
  1227  		// add paths for runtime and main, which 6l imports implicitly.
  1228  		dimportpath(runtimepkg);
  1229  		if(flag_race)
  1230  			dimportpath(racepkg);
  1231  		dimportpath(mkpkg(strlit("main")));
  1232  	}
  1233  }
  1234  
  1235  static Sym*
  1236  dalgsym(Type *t)
  1237  {
  1238  	int ot;
  1239  	Sym *s, *hash, *eq;
  1240  	char buf[100];
  1241  
  1242  	// dalgsym is only called for a type that needs an algorithm table,
  1243  	// which implies that the type is comparable (or else it would use ANOEQ).
  1244  
  1245  	s = typesymprefix(".alg", t);
  1246  	hash = typesymprefix(".hash", t);
  1247  	genhash(hash, t);
  1248  	eq = typesymprefix(".eq", t);
  1249  	geneq(eq, t);
  1250  
  1251  	// ../../pkg/runtime/runtime.h:/Alg
  1252  	ot = 0;
  1253  	ot = dsymptr(s, ot, hash, 0);
  1254  	ot = dsymptr(s, ot, eq, 0);
  1255  	ot = dsymptr(s, ot, pkglookup("memprint", runtimepkg), 0);
  1256  	switch(t->width) {
  1257  	default:
  1258  		ot = dsymptr(s, ot, pkglookup("memcopy", runtimepkg), 0);
  1259  		break;
  1260  	case 1:
  1261  	case 2:
  1262  	case 4:
  1263  	case 8:
  1264  	case 16:
  1265  		snprint(buf, sizeof buf, "memcopy%d", (int)t->width*8);
  1266  		ot = dsymptr(s, ot, pkglookup(buf, runtimepkg), 0);
  1267  		break;
  1268  	}
  1269  
  1270  	ggloblsym(s, ot, 1, 1);
  1271  	return s;
  1272  }
  1273  
  1274  static int
  1275  gcinline(Type *t)
  1276  {
  1277  	switch(t->etype) {
  1278  	case TARRAY:
  1279  		if(t->bound == 1)
  1280  			return 1;
  1281  		if(t->width <= 4*widthptr)
  1282  			return 1;
  1283  		break;
  1284  	}
  1285  	return 0;
  1286  }
  1287  
  1288  static int
  1289  dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
  1290  {
  1291  	Type *t1;
  1292  	vlong o, off2, fieldoffset, i;
  1293  
  1294  	if(t->align > 0 && (*off % t->align) != 0)
  1295  		fatal("dgcsym1: invalid initial alignment, %T", t);
  1296  
  1297  	if(t->width == BADWIDTH)
  1298  		dowidth(t);
  1299  	
  1300  	switch(t->etype) {
  1301  	case TINT8:
  1302  	case TUINT8:
  1303  	case TINT16:
  1304  	case TUINT16:
  1305  	case TINT32:
  1306  	case TUINT32:
  1307  	case TINT64:
  1308  	case TUINT64:
  1309  	case TINT:
  1310  	case TUINT:
  1311  	case TUINTPTR:
  1312  	case TBOOL:
  1313  	case TFLOAT32:
  1314  	case TFLOAT64:
  1315  	case TCOMPLEX64:
  1316  	case TCOMPLEX128:
  1317  		*off += t->width;
  1318  		break;
  1319  
  1320  	case TPTR32:
  1321  	case TPTR64:
  1322  		// NOTE: Any changes here need to be made to reflect.PtrTo as well.
  1323  		if(*off % widthptr != 0)
  1324  			fatal("dgcsym1: invalid alignment, %T", t);
  1325  
  1326  		// NOTE(rsc): Emitting GC_APTR here for *nonptrtype
  1327  		// (pointer to non-pointer-containing type) means that
  1328  		// we do not record 'nonptrtype' and instead tell the 
  1329  		// garbage collector to look up the type of the memory in
  1330  		// type information stored in the heap. In effect we are telling
  1331  		// the collector "we don't trust our information - use yours".
  1332  		// It's not completely clear why we want to do this.
  1333  		// It does have the effect that if you have a *SliceHeader and a *[]int
  1334  		// pointing at the same actual slice header, *SliceHeader will not be
  1335  		// used as an authoritative type for the memory, which is good:
  1336  		// if the collector scanned the memory as type *SliceHeader, it would
  1337  		// see no pointers inside but mark the block as scanned, preventing
  1338  		// the seeing of pointers when we followed the *[]int pointer.
  1339  		// Perhaps that kind of situation is the rationale.
  1340  		if(!haspointers(t->type)) {
  1341  			ot = duintptr(s, ot, GC_APTR);
  1342  			ot = duintptr(s, ot, *off);
  1343  		} else {
  1344  			ot = duintptr(s, ot, GC_PTR);
  1345  			ot = duintptr(s, ot, *off);
  1346  			ot = dsymptr(s, ot, dgcsym(t->type), 0);
  1347  		}
  1348  		*off += t->width;
  1349  		break;
  1350  
  1351  	case TUNSAFEPTR:
  1352  	case TFUNC:
  1353  		if(*off % widthptr != 0)
  1354  			fatal("dgcsym1: invalid alignment, %T", t);
  1355  		ot = duintptr(s, ot, GC_APTR);
  1356  		ot = duintptr(s, ot, *off);
  1357  		*off += t->width;
  1358  		break;
  1359  
  1360  	// struct Hchan*
  1361  	case TCHAN:
  1362  		// NOTE: Any changes here need to be made to reflect.ChanOf as well.
  1363  		if(*off % widthptr != 0)
  1364  			fatal("dgcsym1: invalid alignment, %T", t);
  1365  		ot = duintptr(s, ot, GC_CHAN_PTR);
  1366  		ot = duintptr(s, ot, *off);
  1367  		ot = dsymptr(s, ot, dtypesym(t), 0);
  1368  		*off += t->width;
  1369  		break;
  1370  
  1371  	// struct Hmap*
  1372  	case TMAP:
  1373  		// NOTE: Any changes here need to be made to reflect.MapOf as well.
  1374  		if(*off % widthptr != 0)
  1375  			fatal("dgcsym1: invalid alignment, %T", t);
  1376  		ot = duintptr(s, ot, GC_PTR);
  1377  		ot = duintptr(s, ot, *off);
  1378  		ot = dsymptr(s, ot, dgcsym(hmap(t)), 0);
  1379  		*off += t->width;
  1380  		break;
  1381  
  1382  	// struct { byte *str; int32 len; }
  1383  	case TSTRING:
  1384  		if(*off % widthptr != 0)
  1385  			fatal("dgcsym1: invalid alignment, %T", t);
  1386  		ot = duintptr(s, ot, GC_STRING);
  1387  		ot = duintptr(s, ot, *off);
  1388  		*off += t->width;
  1389  		break;
  1390  
  1391  	// struct { Itab* tab;  void* data; }
  1392  	// struct { Type* type; void* data; }	// When isnilinter(t)==true
  1393  	case TINTER:
  1394  		if(*off % widthptr != 0)
  1395  			fatal("dgcsym1: invalid alignment, %T", t);
  1396  		if(isnilinter(t)) {
  1397  			ot = duintptr(s, ot, GC_EFACE);
  1398  			ot = duintptr(s, ot, *off);
  1399  		} else {
  1400  			ot = duintptr(s, ot, GC_IFACE);
  1401  			ot = duintptr(s, ot, *off);
  1402  		}
  1403  		*off += t->width;
  1404  		break;
  1405  
  1406  	case TARRAY:
  1407  		if(t->bound < -1)
  1408  			fatal("dgcsym1: invalid bound, %T", t);
  1409  		if(t->type->width == BADWIDTH)
  1410  			dowidth(t->type);
  1411  		if(isslice(t)) {
  1412  			// NOTE: Any changes here need to be made to reflect.SliceOf as well.
  1413  			// struct { byte* array; uint32 len; uint32 cap; }
  1414  			if(*off % widthptr != 0)
  1415  				fatal("dgcsym1: invalid alignment, %T", t);
  1416  			if(t->type->width != 0) {
  1417  				ot = duintptr(s, ot, GC_SLICE);
  1418  				ot = duintptr(s, ot, *off);
  1419  				ot = dsymptr(s, ot, dgcsym(t->type), 0);
  1420  			} else {
  1421  				ot = duintptr(s, ot, GC_APTR);
  1422  				ot = duintptr(s, ot, *off);
  1423  			}
  1424  			*off += t->width;
  1425  		} else {
  1426  			// NOTE: Any changes here need to be made to reflect.ArrayOf as well,
  1427  			// at least once ArrayOf's gc info is implemented and ArrayOf is exported.
  1428  			// struct { byte* array; uint32 len; uint32 cap; }
  1429  			if(t->bound < 1 || !haspointers(t->type)) {
  1430  				*off += t->width;
  1431  			} else if(gcinline(t)) {
  1432  				for(i=0; i<t->bound; i++)
  1433  					ot = dgcsym1(s, ot, t->type, off, stack_size);  // recursive call of dgcsym1
  1434  			} else {
  1435  				if(stack_size < GC_STACK_CAPACITY) {
  1436  					ot = duintptr(s, ot, GC_ARRAY_START);  // a stack push during GC
  1437  					ot = duintptr(s, ot, *off);
  1438  					ot = duintptr(s, ot, t->bound);
  1439  					ot = duintptr(s, ot, t->type->width);
  1440  					off2 = 0;
  1441  					ot = dgcsym1(s, ot, t->type, &off2, stack_size+1);  // recursive call of dgcsym1
  1442  					ot = duintptr(s, ot, GC_ARRAY_NEXT);  // a stack pop during GC
  1443  				} else {
  1444  					ot = duintptr(s, ot, GC_REGION);
  1445  					ot = duintptr(s, ot, *off);
  1446  					ot = duintptr(s, ot, t->width);
  1447  					ot = dsymptr(s, ot, dgcsym(t), 0);
  1448  				}
  1449  				*off += t->width;
  1450  			}
  1451  		}
  1452  		break;
  1453  
  1454  	case TSTRUCT:
  1455  		o = 0;
  1456  		for(t1=t->type; t1!=T; t1=t1->down) {
  1457  			fieldoffset = t1->width;
  1458  			*off += fieldoffset - o;
  1459  			ot = dgcsym1(s, ot, t1->type, off, stack_size);  // recursive call of dgcsym1
  1460  			o = fieldoffset + t1->type->width;
  1461  		}
  1462  		*off += t->width - o;
  1463  		break;
  1464  
  1465  	default:
  1466  		fatal("dgcsym1: unexpected type %T", t);
  1467  	}
  1468  
  1469  	return ot;
  1470  }
  1471  
  1472  static Sym*
  1473  dgcsym(Type *t)
  1474  {
  1475  	int ot;
  1476  	vlong off;
  1477  	Sym *s;
  1478  
  1479  	s = typesymprefix(".gc", t);
  1480  	if(s->flags & SymGcgen)
  1481  		return s;
  1482  	s->flags |= SymGcgen;
  1483  
  1484  	if(t->width == BADWIDTH)
  1485  		dowidth(t);
  1486  
  1487  	ot = 0;
  1488  	off = 0;
  1489  	ot = duintptr(s, ot, t->width);
  1490  	ot = dgcsym1(s, ot, t, &off, 0);
  1491  	ot = duintptr(s, ot, GC_END);
  1492  	ggloblsym(s, ot, 1, 1);
  1493  
  1494  	if(t->align > 0)
  1495  		off = rnd(off, t->align);
  1496  	if(off != t->width)
  1497  		fatal("dgcsym: off=%lld, size=%lld, type %T", off, t->width, t);
  1498  
  1499  	return s;
  1500  }