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