The Go Programming Language

Text file src/cmd/gc/reflect.c

     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 "go.h"
     6	
     7	/*
     8	 * runtime interface and reflection data structures
     9	 */
    10	
    11	static	NodeList*	signatlist;
    12	static	Sym*	dtypesym(Type*);
    13	static	Sym*	weaktypesym(Type*);
    14	
    15	static int
    16	sigcmp(Sig *a, Sig *b)
    17	{
    18		int i;
    19		
    20		i = strcmp(a->name, b->name);
    21		if(i != 0)
    22			return i;
    23		if(a->pkg == b->pkg)
    24			return 0;
    25		if(a->pkg == nil)
    26			return -1;
    27		if(b->pkg == nil)
    28			return +1;
    29		return strcmp(a->pkg->path->s, b->pkg->path->s);
    30	}
    31	
    32	static Sig*
    33	lsort(Sig *l, int(*f)(Sig*, Sig*))
    34	{
    35		Sig *l1, *l2, *le;
    36	
    37		if(l == 0 || l->link == 0)
    38			return l;
    39	
    40		l1 = l;
    41		l2 = l;
    42		for(;;) {
    43			l2 = l2->link;
    44			if(l2 == 0)
    45				break;
    46			l2 = l2->link;
    47			if(l2 == 0)
    48				break;
    49			l1 = l1->link;
    50		}
    51	
    52		l2 = l1->link;
    53		l1->link = 0;
    54		l1 = lsort(l, f);
    55		l2 = lsort(l2, f);
    56	
    57		/* set up lead element */
    58		if((*f)(l1, l2) < 0) {
    59			l = l1;
    60			l1 = l1->link;
    61		} else {
    62			l = l2;
    63			l2 = l2->link;
    64		}
    65		le = l;
    66	
    67		for(;;) {
    68			if(l1 == 0) {
    69				while(l2) {
    70					le->link = l2;
    71					le = l2;
    72					l2 = l2->link;
    73				}
    74				le->link = 0;
    75				break;
    76			}
    77			if(l2 == 0) {
    78				while(l1) {
    79					le->link = l1;
    80					le = l1;
    81					l1 = l1->link;
    82				}
    83				break;
    84			}
    85			if((*f)(l1, l2) < 0) {
    86				le->link = l1;
    87				le = l1;
    88				l1 = l1->link;
    89			} else {
    90				le->link = l2;
    91				le = l2;
    92				l2 = l2->link;
    93			}
    94		}
    95		le->link = 0;
    96		return l;
    97	}
    98	
    99	/*
   100	 * f is method type, with receiver.
   101	 * return function type, receiver as first argument (or not).
   102	 */
   103	Type*
   104	methodfunc(Type *f, Type *receiver)
   105	{
   106		NodeList *in, *out;
   107		Node *d;
   108		Type *t;
   109	
   110		in = nil;
   111		if(receiver) {
   112			d = nod(ODCLFIELD, N, N);
   113			d->type = receiver;
   114			in = list(in, d);
   115		}
   116		for(t=getinargx(f)->type; t; t=t->down) {
   117			d = nod(ODCLFIELD, N, N);
   118			d->type = t->type;
   119			d->isddd = t->isddd;
   120			in = list(in, d);
   121		}
   122	
   123		out = nil;
   124		for(t=getoutargx(f)->type; t; t=t->down) {
   125			d = nod(ODCLFIELD, N, N);
   126			d->type = t->type;
   127			out = list(out, d);
   128		}
   129	
   130		return functype(N, in, out);
   131	}
   132	
   133	/*
   134	 * return methods of non-interface type t, sorted by name.
   135	 * generates stub functions as needed.
   136	 */
   137	static Sig*
   138	methods(Type *t)
   139	{
   140		Type *f, *mt, *it, *this;
   141		Sig *a, *b;
   142		Sym *method;
   143		Prog *oldlist;
   144	
   145		// named method type
   146		mt = methtype(t);
   147		if(mt == T)
   148			return nil;
   149		expandmeth(mt->sym, mt);
   150	
   151		// type stored in interface word
   152		it = t;
   153		if(it->width > widthptr)
   154			it = ptrto(t);
   155	
   156		// make list of methods for t,
   157		// generating code if necessary.
   158		a = nil;
   159		oldlist = nil;
   160		for(f=mt->xmethod; f; f=f->down) {
   161			if(f->type->etype != TFUNC)
   162				continue;
   163			if(f->etype != TFIELD)
   164				fatal("methods: not field");
   165			method = f->sym;
   166			if(method == nil)
   167				continue;
   168	
   169			// get receiver type for this particular method.
   170			// if pointer receiver but non-pointer t and
   171			// this is not an embedded pointer inside a struct,
   172			// method does not apply.
   173			this = getthisx(f->type)->type->type;
   174			if(isptr[this->etype] && this->type == t)
   175				continue;
   176			if(isptr[this->etype] && !isptr[t->etype]
   177			&& f->embedded != 2 && !isifacemethod(f->type))
   178				continue;
   179	
   180			b = mal(sizeof(*b));
   181			b->link = a;
   182			a = b;
   183	
   184			a->name = method->name;
   185			if(!exportname(method->name)) {
   186				if(method->pkg == nil)
   187					fatal("methods: missing package");
   188				a->pkg = method->pkg;
   189			}
   190			a->isym = methodsym(method, it, 1);
   191			a->tsym = methodsym(method, t, 0);
   192			a->type = methodfunc(f->type, t);
   193			a->mtype = methodfunc(f->type, nil);
   194	
   195			if(!(a->isym->flags & SymSiggen)) {
   196				a->isym->flags |= SymSiggen;
   197				if(!eqtype(this, it) || this->width < types[tptr]->width) {
   198					if(oldlist == nil)
   199						oldlist = pc;
   200					// Is okay to call genwrapper here always,
   201					// but we can generate more efficient code
   202					// using genembedtramp if all that is necessary
   203					// is a pointer adjustment and a JMP.
   204					if(isptr[it->etype] && isptr[this->etype]
   205					&& f->embedded && !isifacemethod(f->type))
   206						genembedtramp(it, f, a->isym, 1);
   207					else
   208						genwrapper(it, f, a->isym, 1);
   209				}
   210			}
   211	
   212			if(!(a->tsym->flags & SymSiggen)) {
   213				a->tsym->flags |= SymSiggen;
   214				if(!eqtype(this, t)) {
   215					if(oldlist == nil)
   216						oldlist = pc;
   217					if(isptr[t->etype] && isptr[this->etype]
   218					&& f->embedded && !isifacemethod(f->type))
   219						genembedtramp(t, f, a->tsym, 0);
   220					else
   221						genwrapper(t, f, a->tsym, 0);
   222				}
   223			}
   224		}
   225	
   226		// restore data output
   227		if(oldlist) {
   228			// old list ended with AEND; change to ANOP
   229			// so that the trampolines that follow can be found.
   230			nopout(oldlist);
   231	
   232			// start new data list
   233			newplist();
   234		}
   235	
   236		return lsort(a, sigcmp);
   237	}
   238	
   239	/*
   240	 * return methods of interface type t, sorted by name.
   241	 */
   242	static Sig*
   243	imethods(Type *t)
   244	{
   245		Sig *a, *all, *last;
   246		Type *f;
   247		Sym *method, *isym;
   248		Prog *oldlist;
   249	
   250		all = nil;
   251		last = nil;
   252		oldlist = nil;
   253		for(f=t->type; f; f=f->down) {
   254			if(f->etype != TFIELD)
   255				fatal("imethods: not field");
   256			if(f->type->etype != TFUNC || f->sym == nil)
   257				continue;
   258			method = f->sym;
   259			a = mal(sizeof(*a));
   260			a->name = method->name;
   261			if(!exportname(method->name)) {
   262				if(method->pkg == nil)
   263					fatal("imethods: missing package");
   264				a->pkg = method->pkg;
   265			}
   266			a->mtype = f->type;
   267			a->offset = 0;
   268			a->type = methodfunc(f->type, nil);
   269	
   270			if(last && sigcmp(last, a) >= 0)
   271				fatal("sigcmp vs sortinter %s %s", last->name, a->name);
   272			if(last == nil)
   273				all = a;
   274			else
   275				last->link = a;
   276			last = a;
   277			
   278			// Compiler can only refer to wrappers for
   279			// named interface types.
   280			if(t->sym == S)
   281				continue;
   282			
   283			// NOTE(rsc): Perhaps an oversight that
   284			// IfaceType.Method is not in the reflect data.
   285			// Generate the method body, so that compiled
   286			// code can refer to it.
   287			isym = methodsym(method, t, 0);
   288			if(!(isym->flags & SymSiggen)) {
   289				isym->flags |= SymSiggen;
   290				if(oldlist == nil)
   291					oldlist = pc;
   292				genwrapper(t, f, isym, 0);
   293			}
   294		}
   295	
   296		if(oldlist) {
   297			// old list ended with AEND; change to ANOP
   298			// so that the trampolines that follow can be found.
   299			nopout(oldlist);
   300	
   301			// start new data list
   302			newplist();
   303		}
   304	
   305		return all;
   306	}
   307	
   308	static void
   309	dimportpath(Pkg *p)
   310	{
   311		static Pkg *gopkg;
   312		char *nam;
   313		Node *n;
   314		
   315		if(p->pathsym != S)
   316			return;
   317	
   318		if(gopkg == nil) {
   319			gopkg = mkpkg(strlit("go"));
   320			gopkg->name = "go";
   321		}
   322		nam = smprint("importpath.%s.", p->prefix);
   323	
   324		n = nod(ONAME, N, N);
   325		n->sym = pkglookup(nam, gopkg);
   326		free(nam);
   327		n->class = PEXTERN;
   328		n->xoffset = 0;
   329		p->pathsym = n->sym;
   330		
   331		gdatastring(n, p->path);
   332		ggloblsym(n->sym, types[TSTRING]->width, 1);
   333	}
   334	
   335	static int
   336	dgopkgpath(Sym *s, int ot, Pkg *pkg)
   337	{
   338		if(pkg == nil)
   339			return dgostringptr(s, ot, nil);
   340	
   341		// Emit reference to go.importpath.""., which 6l will
   342		// rewrite using the correct import path.  Every package
   343		// that imports this one directly defines the symbol.
   344		if(pkg == localpkg) {
   345			static Sym *ns;
   346			
   347			if(ns == nil)
   348				ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
   349			return dsymptr(s, ot, ns, 0);
   350		}
   351	
   352		dimportpath(pkg);
   353		return dsymptr(s, ot, pkg->pathsym, 0);
   354	}
   355	
   356	/*
   357	 * uncommonType
   358	 * ../../pkg/runtime/type.go:/uncommonType
   359	 */
   360	static int
   361	dextratype(Sym *sym, int off, Type *t, int ptroff)
   362	{
   363		int ot, n;
   364		Sym *s;
   365		Sig *a, *m;
   366	
   367		m = methods(t);
   368		if(t->sym == nil && m == nil)
   369			return off;
   370		
   371		// fill in *extraType pointer in header
   372		dsymptr(sym, ptroff, sym, off);
   373	
   374		n = 0;
   375		for(a=m; a; a=a->link) {
   376			dtypesym(a->type);
   377			n++;
   378		}
   379	
   380		ot = off;
   381		s = sym;
   382		if(t->sym) {
   383			ot = dgostringptr(s, ot, t->sym->name);
   384			if(t != types[t->etype])
   385				ot = dgopkgpath(s, ot, t->sym->pkg);
   386			else
   387				ot = dgostringptr(s, ot, nil);
   388		} else {
   389			ot = dgostringptr(s, ot, nil);
   390			ot = dgostringptr(s, ot, nil);
   391		}
   392	
   393		// slice header
   394		ot = dsymptr(s, ot, s, ot + widthptr + 2*4);
   395		ot = duint32(s, ot, n);
   396		ot = duint32(s, ot, n);
   397	
   398		// methods
   399		for(a=m; a; a=a->link) {
   400			// method
   401			// ../../pkg/runtime/type.go:/method
   402			ot = dgostringptr(s, ot, a->name);
   403			ot = dgopkgpath(s, ot, a->pkg);
   404			ot = dsymptr(s, ot, dtypesym(a->mtype), 0);
   405			ot = dsymptr(s, ot, dtypesym(a->type), 0);
   406			if(a->isym)
   407				ot = dsymptr(s, ot, a->isym, 0);
   408			else
   409				ot = duintptr(s, ot, 0);
   410			if(a->tsym)
   411				ot = dsymptr(s, ot, a->tsym, 0);
   412			else
   413				ot = duintptr(s, ot, 0);
   414		}
   415	
   416		return ot;
   417	}
   418	
   419	enum {
   420		KindBool = 1,
   421		KindInt,
   422		KindInt8,
   423		KindInt16,
   424		KindInt32,
   425		KindInt64,
   426		KindUint,
   427		KindUint8,
   428		KindUint16,
   429		KindUint32,
   430		KindUint64,
   431		KindUintptr,
   432		KindFloat32,
   433		KindFloat64,
   434		KindComplex64,
   435		KindComplex128,
   436		KindArray,
   437		KindChan,
   438		KindFunc,
   439		KindInterface,
   440		KindMap,
   441		KindPtr,
   442		KindSlice,
   443		KindString,
   444		KindStruct,
   445		KindUnsafePointer,
   446		
   447		KindNoPointers = 1<<7,
   448	};
   449	
   450	static int
   451	kinds[] =
   452	{
   453		[TINT]		= KindInt,
   454		[TUINT]		= KindUint,
   455		[TINT8]		= KindInt8,
   456		[TUINT8]	= KindUint8,
   457		[TINT16]	= KindInt16,
   458		[TUINT16]	= KindUint16,
   459		[TINT32]	= KindInt32,
   460		[TUINT32]	= KindUint32,
   461		[TINT64]	= KindInt64,
   462		[TUINT64]	= KindUint64,
   463		[TUINTPTR]	= KindUintptr,
   464		[TFLOAT32]	= KindFloat32,
   465		[TFLOAT64]	= KindFloat64,
   466		[TBOOL]		= KindBool,
   467		[TSTRING]		= KindString,
   468		[TPTR32]		= KindPtr,
   469		[TPTR64]		= KindPtr,
   470		[TSTRUCT]	= KindStruct,
   471		[TINTER]		= KindInterface,
   472		[TCHAN]		= KindChan,
   473		[TMAP]		= KindMap,
   474		[TARRAY]		= KindArray,
   475		[TFUNC]		= KindFunc,
   476		[TCOMPLEX64]	= KindComplex64,
   477		[TCOMPLEX128]	= KindComplex128,
   478		[TUNSAFEPTR]	= KindUnsafePointer,
   479	};
   480	
   481	static char*
   482	structnames[] =
   483	{
   484		[TINT]		= "*runtime.IntType",
   485		[TUINT]		= "*runtime.UintType",
   486		[TINT8]		= "*runtime.IntType",
   487		[TUINT8]	= "*runtime.UintType",
   488		[TINT16]	= "*runtime.IntType",
   489		[TUINT16]	= "*runtime.UintType",
   490		[TINT32]	= "*runtime.IntType",
   491		[TUINT32]	= "*runtime.UintType",
   492		[TINT64]	= "*runtime.IntType",
   493		[TUINT64]	= "*runtime.UintType",
   494		[TUINTPTR]	= "*runtime.UintType",
   495		[TCOMPLEX64]	= "*runtime.ComplexType",
   496		[TCOMPLEX128]	= "*runtime.ComplexType",
   497		[TFLOAT32]	= "*runtime.FloatType",
   498		[TFLOAT64]	= "*runtime.FloatType",
   499		[TBOOL]		= "*runtime.BoolType",
   500		[TSTRING]	= "*runtime.StringType",
   501		[TUNSAFEPTR] =	"*runtime.UnsafePointerType",
   502	
   503		[TPTR32]	= "*runtime.PtrType",
   504		[TPTR64]	= "*runtime.PtrType",
   505		[TSTRUCT]	= "*runtime.StructType",
   506		[TINTER]	= "*runtime.InterfaceType",
   507		[TCHAN]		= "*runtime.ChanType",
   508		[TMAP]		= "*runtime.MapType",
   509		[TARRAY]	= "*runtime.ArrayType",
   510		[TFUNC]		= "*runtime.FuncType",
   511	};
   512	
   513	static Sym*
   514	typestruct(Type *t)
   515	{
   516		char *name;
   517		int et;
   518	
   519		et = t->etype;
   520		if(et < 0 || et >= nelem(structnames) || (name = structnames[et]) == nil) {
   521			fatal("typestruct %lT", t);
   522			return nil;	// silence gcc
   523		}
   524	
   525		if(isslice(t))
   526			name = "*runtime.SliceType";
   527	
   528		return pkglookup(name, typepkg);
   529	}
   530	
   531	static int
   532	haspointers(Type *t)
   533	{
   534		Type *t1;
   535	
   536		switch(t->etype) {
   537		case TINT:
   538		case TUINT:
   539		case TINT8:
   540		case TUINT8:
   541		case TINT16:
   542		case TUINT16:
   543		case TINT32:
   544		case TUINT32:
   545		case TINT64:
   546		case TUINT64:
   547		case TUINTPTR:
   548		case TFLOAT32:
   549		case TFLOAT64:
   550		case TBOOL:
   551			return 0;
   552		case TARRAY:
   553			if(t->bound < 0)	// slice
   554				return 1;
   555			return haspointers(t->type);
   556		case TSTRUCT:
   557			for(t1=t->type; t1!=T; t1=t1->down)
   558				if(haspointers(t1->type))
   559					return 1;
   560			return 0;
   561		case TSTRING:
   562		case TPTR32:
   563		case TPTR64:
   564		case TUNSAFEPTR:
   565		case TINTER:
   566		case TCHAN:
   567		case TMAP:
   568		case TFUNC:
   569		default:
   570			return 1;
   571		}
   572	}
   573	
   574	/*
   575	 * commonType
   576	 * ../../pkg/runtime/type.go:/commonType
   577	 */
   578	static int
   579	dcommontype(Sym *s, int ot, Type *t)
   580	{
   581		int i;
   582		Sym *sptr;
   583		char *p;
   584	
   585		dowidth(t);
   586		
   587		sptr = nil;
   588		if(t->sym != nil && !isptr[t->etype])
   589			sptr = dtypesym(ptrto(t));
   590		else
   591			sptr = weaktypesym(ptrto(t));
   592	
   593		// empty interface pointing at this type.
   594		// all the references that we emit are *interface{};
   595		// they point here.
   596		ot = rnd(ot, widthptr);
   597		ot = dsymptr(s, ot, typestruct(t), 0);
   598		ot = dsymptr(s, ot, s, 2*widthptr);
   599	
   600		// ../../pkg/runtime/type.go:/commonType
   601		// actual type structure
   602		//	type commonType struct {
   603		//		size uintptr;
   604		//		hash uint32;
   605		//		alg uint8;
   606		//		align uint8;
   607		//		fieldAlign uint8;
   608		//		kind uint8;
   609		//		string *string;
   610		//		*extraType;
   611		//		ptrToThis *Type
   612		//	}
   613		ot = duintptr(s, ot, t->width);
   614		ot = duint32(s, ot, typehash(t));
   615		ot = duint8(s, ot, algtype(t));
   616		ot = duint8(s, ot, t->align);	// align
   617		ot = duint8(s, ot, t->align);	// fieldAlign
   618		i = kinds[t->etype];
   619		if(t->etype == TARRAY && t->bound < 0)
   620			i = KindSlice;
   621		if(!haspointers(t))
   622			i |= KindNoPointers;
   623		ot = duint8(s, ot, i);  // kind
   624		longsymnames = 1;
   625		p = smprint("%-T", t);
   626		longsymnames = 0;
   627		ot = dgostringptr(s, ot, p);	// string
   628		free(p);
   629		
   630		// skip pointer to extraType,
   631		// which follows the rest of this type structure.
   632		// caller will fill in if needed.
   633		// otherwise linker will assume 0.
   634		ot += widthptr;
   635	
   636		ot = dsymptr(s, ot, sptr, 0);  // ptrto type
   637		return ot;
   638	}
   639	
   640	Sym*
   641	typesym(Type *t)
   642	{
   643		char *p;
   644		Sym *s;
   645	
   646		p = smprint("%#-T", t);
   647		s = pkglookup(p, typepkg);
   648		free(p);
   649		return s;
   650	}
   651	
   652	Node*
   653	typename(Type *t)
   654	{
   655		Sym *s;
   656		Node *n;
   657	
   658		if(t == T || (isptr[t->etype] && t->type == T) || isideal(t))
   659			fatal("typename %T", t);
   660		s = typesym(t);
   661		if(s->def == N) {
   662			n = nod(ONAME, N, N);
   663			n->sym = s;
   664			n->type = types[TUINT8];
   665			n->addable = 1;
   666			n->ullman = 1;
   667			n->class = PEXTERN;
   668			n->xoffset = 0;
   669			s->def = n;
   670	
   671			signatlist = list(signatlist, typenod(t));
   672		}
   673	
   674		n = nod(OADDR, s->def, N);
   675		n->type = ptrto(s->def->type);
   676		n->addable = 1;
   677		n->ullman = 2;
   678		return n;
   679	}
   680	
   681	static Sym*
   682	weaktypesym(Type *t)
   683	{
   684		char *p;
   685		Sym *s;
   686		static Pkg *weak;
   687		
   688		if(weak == nil) {
   689			weak = mkpkg(strlit("weak.type"));
   690			weak->name = "weak.type";
   691			weak->prefix = "weak.type";  // not weak%2etype
   692		}
   693		
   694		p = smprint("%#-T", t);
   695		s = pkglookup(p, weak);
   696		free(p);
   697		return s;
   698	}
   699	
   700	static Sym*
   701	dtypesym(Type *t)
   702	{
   703		int ot, xt, n, isddd, dupok;
   704		Sym *s, *s1, *s2;
   705		Sig *a, *m;
   706		Type *t1, *tbase, *t2;
   707	
   708		if(isideal(t))
   709			fatal("dtypesym %T", t);
   710	
   711		s = typesym(t);
   712		if(s->flags & SymSiggen)
   713			return s;
   714		s->flags |= SymSiggen;
   715	
   716		// special case (look for runtime below):
   717		// when compiling package runtime,
   718		// emit the type structures for int, float, etc.
   719		tbase = t;
   720		if(isptr[t->etype] && t->sym == S && t->type->sym != S)
   721			tbase = t->type;
   722		dupok = tbase->sym == S;
   723	
   724		if(compiling_runtime && tbase == types[tbase->etype])	// int, float, etc
   725			goto ok;
   726	
   727		// named types from other files are defined only by those files
   728		if(tbase->sym && !tbase->local)
   729			return s;
   730		if(isforw[tbase->etype])
   731			return s;
   732	
   733	ok:
   734		ot = 0;
   735		xt = 0;
   736		switch(t->etype) {
   737		default:
   738			ot = dcommontype(s, ot, t);
   739			xt = ot - 2*widthptr;
   740			break;
   741	
   742		case TARRAY:
   743			if(t->bound >= 0) {
   744				// ../../pkg/runtime/type.go:/ArrayType
   745				s1 = dtypesym(t->type);
   746				t2 = typ(TARRAY);
   747				t2->type = t->type;
   748				t2->bound = -1;  // slice
   749				s2 = dtypesym(t2);
   750				ot = dcommontype(s, ot, t);
   751				xt = ot - 2*widthptr;
   752				ot = dsymptr(s, ot, s1, 0);
   753				ot = dsymptr(s, ot, s2, 0);
   754				ot = duintptr(s, ot, t->bound);
   755			} else {
   756				// ../../pkg/runtime/type.go:/SliceType
   757				s1 = dtypesym(t->type);
   758				ot = dcommontype(s, ot, t);
   759				xt = ot - 2*widthptr;
   760				ot = dsymptr(s, ot, s1, 0);
   761			}
   762			break;
   763	
   764		case TCHAN:
   765			// ../../pkg/runtime/type.go:/ChanType
   766			s1 = dtypesym(t->type);
   767			ot = dcommontype(s, ot, t);
   768			xt = ot - 2*widthptr;
   769			ot = dsymptr(s, ot, s1, 0);
   770			ot = duintptr(s, ot, t->chan);
   771			break;
   772	
   773		case TFUNC:
   774			for(t1=getthisx(t)->type; t1; t1=t1->down)
   775				dtypesym(t1->type);
   776			isddd = 0;
   777			for(t1=getinargx(t)->type; t1; t1=t1->down) {
   778				isddd = t1->isddd;
   779				dtypesym(t1->type);
   780			}
   781			for(t1=getoutargx(t)->type; t1; t1=t1->down)
   782				dtypesym(t1->type);
   783	
   784			ot = dcommontype(s, ot, t);
   785			xt = ot - 2*widthptr;
   786			ot = duint8(s, ot, isddd);
   787	
   788			// two slice headers: in and out.
   789			ot = rnd(ot, widthptr);
   790			ot = dsymptr(s, ot, s, ot+2*(widthptr+2*4));
   791			n = t->thistuple + t->intuple;
   792			ot = duint32(s, ot, n);
   793			ot = duint32(s, ot, n);
   794			ot = dsymptr(s, ot, s, ot+1*(widthptr+2*4)+n*widthptr);
   795			ot = duint32(s, ot, t->outtuple);
   796			ot = duint32(s, ot, t->outtuple);
   797	
   798			// slice data
   799			for(t1=getthisx(t)->type; t1; t1=t1->down, n++)
   800				ot = dsymptr(s, ot, dtypesym(t1->type), 0);
   801			for(t1=getinargx(t)->type; t1; t1=t1->down, n++)
   802				ot = dsymptr(s, ot, dtypesym(t1->type), 0);
   803			for(t1=getoutargx(t)->type; t1; t1=t1->down, n++)
   804				ot = dsymptr(s, ot, dtypesym(t1->type), 0);
   805			break;
   806	
   807		case TINTER:
   808			m = imethods(t);
   809			n = 0;
   810			for(a=m; a; a=a->link) {
   811				dtypesym(a->type);
   812				n++;
   813			}
   814	
   815			// ../../pkg/runtime/type.go:/InterfaceType
   816			ot = dcommontype(s, ot, t);
   817			xt = ot - 2*widthptr;
   818			ot = dsymptr(s, ot, s, ot+widthptr+2*4);
   819			ot = duint32(s, ot, n);
   820			ot = duint32(s, ot, n);
   821			for(a=m; a; a=a->link) {
   822				// ../../pkg/runtime/type.go:/imethod
   823				ot = dgostringptr(s, ot, a->name);
   824				ot = dgopkgpath(s, ot, a->pkg);
   825				ot = dsymptr(s, ot, dtypesym(a->type), 0);
   826			}
   827			break;
   828	
   829		case TMAP:
   830			// ../../pkg/runtime/type.go:/MapType
   831			s1 = dtypesym(t->down);
   832			s2 = dtypesym(t->type);
   833			ot = dcommontype(s, ot, t);
   834			xt = ot - 2*widthptr;
   835			ot = dsymptr(s, ot, s1, 0);
   836			ot = dsymptr(s, ot, s2, 0);
   837			break;
   838	
   839		case TPTR32:
   840		case TPTR64:
   841			if(t->type->etype == TANY) {
   842				// ../../pkg/runtime/type.go:/UnsafePointerType
   843				ot = dcommontype(s, ot, t);
   844				break;
   845			}
   846			// ../../pkg/runtime/type.go:/PtrType
   847			s1 = dtypesym(t->type);
   848			ot = dcommontype(s, ot, t);
   849			xt = ot - 2*widthptr;
   850			ot = dsymptr(s, ot, s1, 0);
   851			break;
   852	
   853		case TSTRUCT:
   854			// ../../pkg/runtime/type.go:/StructType
   855			// for security, only the exported fields.
   856			n = 0;
   857			for(t1=t->type; t1!=T; t1=t1->down) {
   858				dtypesym(t1->type);
   859				n++;
   860			}
   861			ot = dcommontype(s, ot, t);
   862			xt = ot - 2*widthptr;
   863			ot = dsymptr(s, ot, s, ot+widthptr+2*4);
   864			ot = duint32(s, ot, n);
   865			ot = duint32(s, ot, n);
   866			for(t1=t->type; t1!=T; t1=t1->down) {
   867				// ../../pkg/runtime/type.go:/structField
   868				if(t1->sym && !t1->embedded) {
   869					ot = dgostringptr(s, ot, t1->sym->name);
   870					if(exportname(t1->sym->name))
   871						ot = dgostringptr(s, ot, nil);
   872					else
   873						ot = dgopkgpath(s, ot, t1->sym->pkg);
   874				} else {
   875					ot = dgostringptr(s, ot, nil);
   876					ot = dgostringptr(s, ot, nil);
   877				}
   878				ot = dsymptr(s, ot, dtypesym(t1->type), 0);
   879				ot = dgostrlitptr(s, ot, t1->note);
   880				ot = duintptr(s, ot, t1->width);	// field offset
   881			}
   882			break;
   883		}
   884		ot = dextratype(s, ot, t, xt);
   885		ggloblsym(s, ot, dupok);
   886		return s;
   887	}
   888	
   889	void
   890	dumptypestructs(void)
   891	{
   892		int i;
   893		NodeList *l;
   894		Node *n;
   895		Type *t;
   896		Pkg *p;
   897	
   898		// copy types from externdcl list to signatlist
   899		for(l=externdcl; l; l=l->next) {
   900			n = l->n;
   901			if(n->op != OTYPE)
   902				continue;
   903			signatlist = list(signatlist, n);
   904		}
   905	
   906		// process signatlist
   907		for(l=signatlist; l; l=l->next) {
   908			n = l->n;
   909			if(n->op != OTYPE)
   910				continue;
   911			t = n->type;
   912			dtypesym(t);
   913			if(t->sym)
   914				dtypesym(ptrto(t));
   915		}
   916	
   917		// generate import strings for imported packages
   918		for(i=0; i<nelem(phash); i++)
   919			for(p=phash[i]; p; p=p->link)
   920				if(p->direct)
   921					dimportpath(p);
   922	
   923		// do basic types if compiling package runtime.
   924		// they have to be in at least one package,
   925		// and runtime is always loaded implicitly,
   926		// so this is as good as any.
   927		// another possible choice would be package main,
   928		// but using runtime means fewer copies in .6 files.
   929		if(compiling_runtime) {
   930			for(i=1; i<=TBOOL; i++)
   931				dtypesym(ptrto(types[i]));
   932			dtypesym(ptrto(types[TSTRING]));
   933			dtypesym(ptrto(types[TUNSAFEPTR]));
   934			
   935			// add paths for runtime and main, which 6l imports implicitly.
   936			dimportpath(runtimepkg);
   937			dimportpath(mkpkg(strlit("main")));
   938		}
   939	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.