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