github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/cmd/compile/internal/gc/reflect.go (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  package gc
     6  
     7  import (
     8  	"cmd/internal/gcprog"
     9  	"cmd/internal/obj"
    10  	"fmt"
    11  	"os"
    12  	"sort"
    13  	"strings"
    14  )
    15  
    16  type itabEntry struct {
    17  	t, itype *Type
    18  	sym      *Sym
    19  }
    20  
    21  // runtime interface and reflection data structures
    22  var signatlist []*Node
    23  var itabs []itabEntry
    24  
    25  // byMethodNameAndPackagePath sorts method signatures by name, then package path.
    26  type byMethodNameAndPackagePath []*Sig
    27  
    28  func (x byMethodNameAndPackagePath) Len() int      { return len(x) }
    29  func (x byMethodNameAndPackagePath) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
    30  func (x byMethodNameAndPackagePath) Less(i, j int) bool {
    31  	return siglt(x[i], x[j])
    32  }
    33  
    34  // siglt reports whether a < b
    35  func siglt(a, b *Sig) bool {
    36  	if a.name != b.name {
    37  		return a.name < b.name
    38  	}
    39  	if a.pkg == b.pkg {
    40  		return false
    41  	}
    42  	if a.pkg == nil {
    43  		return true
    44  	}
    45  	if b.pkg == nil {
    46  		return false
    47  	}
    48  	return a.pkg.Path < b.pkg.Path
    49  }
    50  
    51  // Builds a type representing a Bucket structure for
    52  // the given map type. This type is not visible to users -
    53  // we include only enough information to generate a correct GC
    54  // program for it.
    55  // Make sure this stays in sync with ../../../../runtime/hashmap.go!
    56  const (
    57  	BUCKETSIZE = 8
    58  	MAXKEYSIZE = 128
    59  	MAXVALSIZE = 128
    60  )
    61  
    62  func structfieldSize() int       { return 3 * Widthptr } // Sizeof(runtime.structfield{})
    63  func imethodSize() int           { return 2 * Widthptr } // Sizeof(runtime.imethod{})
    64  func uncommonSize(t *Type) int { // Sizeof(runtime.uncommontype{})
    65  	if t.Sym == nil && len(methods(t)) == 0 {
    66  		return 0
    67  	}
    68  	return 2*Widthptr + 2*Widthint
    69  }
    70  
    71  func makefield(name string, t *Type) *Field {
    72  	f := newField()
    73  	f.Type = t
    74  	f.Sym = nopkg.Lookup(name)
    75  	return f
    76  }
    77  
    78  func mapbucket(t *Type) *Type {
    79  	if t.Bucket != nil {
    80  		return t.Bucket
    81  	}
    82  
    83  	bucket := typ(TSTRUCT)
    84  	keytype := t.Key()
    85  	valtype := t.Val()
    86  	dowidth(keytype)
    87  	dowidth(valtype)
    88  	if keytype.Width > MAXKEYSIZE {
    89  		keytype = Ptrto(keytype)
    90  	}
    91  	if valtype.Width > MAXVALSIZE {
    92  		valtype = Ptrto(valtype)
    93  	}
    94  
    95  	// The first field is: uint8 topbits[BUCKETSIZE].
    96  	arr := typArray(Types[TUINT8], BUCKETSIZE)
    97  	field := make([]*Field, 0, 5)
    98  	field = append(field, makefield("topbits", arr))
    99  	arr = typArray(keytype, BUCKETSIZE)
   100  	field = append(field, makefield("keys", arr))
   101  	arr = typArray(valtype, BUCKETSIZE)
   102  	field = append(field, makefield("values", arr))
   103  
   104  	// Make sure the overflow pointer is the last memory in the struct,
   105  	// because the runtime assumes it can use size-ptrSize as the
   106  	// offset of the overflow pointer. We double-check that property
   107  	// below once the offsets and size are computed.
   108  	//
   109  	// BUCKETSIZE is 8, so the struct is aligned to 64 bits to this point.
   110  	// On 32-bit systems, the max alignment is 32-bit, and the
   111  	// overflow pointer will add another 32-bit field, and the struct
   112  	// will end with no padding.
   113  	// On 64-bit systems, the max alignment is 64-bit, and the
   114  	// overflow pointer will add another 64-bit field, and the struct
   115  	// will end with no padding.
   116  	// On nacl/amd64p32, however, the max alignment is 64-bit,
   117  	// but the overflow pointer will add only a 32-bit field,
   118  	// so if the struct needs 64-bit padding (because a key or value does)
   119  	// then it would end with an extra 32-bit padding field.
   120  	// Preempt that by emitting the padding here.
   121  	if int(t.Val().Align) > Widthptr || int(t.Key().Align) > Widthptr {
   122  		field = append(field, makefield("pad", Types[TUINTPTR]))
   123  	}
   124  
   125  	// If keys and values have no pointers, the map implementation
   126  	// can keep a list of overflow pointers on the side so that
   127  	// buckets can be marked as having no pointers.
   128  	// Arrange for the bucket to have no pointers by changing
   129  	// the type of the overflow field to uintptr in this case.
   130  	// See comment on hmap.overflow in ../../../../runtime/hashmap.go.
   131  	otyp := Ptrto(bucket)
   132  	if !haspointers(t.Val()) && !haspointers(t.Key()) && t.Val().Width <= MAXVALSIZE && t.Key().Width <= MAXKEYSIZE {
   133  		otyp = Types[TUINTPTR]
   134  	}
   135  	ovf := makefield("overflow", otyp)
   136  	field = append(field, ovf)
   137  
   138  	// link up fields
   139  	bucket.Noalg = true
   140  	bucket.Local = t.Local
   141  	bucket.SetFields(field[:])
   142  	dowidth(bucket)
   143  
   144  	// Double-check that overflow field is final memory in struct,
   145  	// with no padding at end. See comment above.
   146  	if ovf.Offset != bucket.Width-int64(Widthptr) {
   147  		Yyerror("bad math in mapbucket for %v", t)
   148  	}
   149  
   150  	t.Bucket = bucket
   151  
   152  	bucket.Map = t
   153  	return bucket
   154  }
   155  
   156  // Builds a type representing a Hmap structure for the given map type.
   157  // Make sure this stays in sync with ../../../../runtime/hashmap.go!
   158  func hmap(t *Type) *Type {
   159  	if t.Hmap != nil {
   160  		return t.Hmap
   161  	}
   162  
   163  	bucket := mapbucket(t)
   164  	var field [8]*Field
   165  	field[0] = makefield("count", Types[TINT])
   166  	field[1] = makefield("flags", Types[TUINT8])
   167  	field[2] = makefield("B", Types[TUINT8])
   168  	field[3] = makefield("hash0", Types[TUINT32])
   169  	field[4] = makefield("buckets", Ptrto(bucket))
   170  	field[5] = makefield("oldbuckets", Ptrto(bucket))
   171  	field[6] = makefield("nevacuate", Types[TUINTPTR])
   172  	field[7] = makefield("overflow", Types[TUNSAFEPTR])
   173  
   174  	h := typ(TSTRUCT)
   175  	h.Noalg = true
   176  	h.Local = t.Local
   177  	h.SetFields(field[:])
   178  	dowidth(h)
   179  	t.Hmap = h
   180  	h.Map = t
   181  	return h
   182  }
   183  
   184  func hiter(t *Type) *Type {
   185  	if t.Hiter != nil {
   186  		return t.Hiter
   187  	}
   188  
   189  	// build a struct:
   190  	// hiter {
   191  	//    key *Key
   192  	//    val *Value
   193  	//    t *MapType
   194  	//    h *Hmap
   195  	//    buckets *Bucket
   196  	//    bptr *Bucket
   197  	//    overflow0 unsafe.Pointer
   198  	//    overflow1 unsafe.Pointer
   199  	//    startBucket uintptr
   200  	//    stuff uintptr
   201  	//    bucket uintptr
   202  	//    checkBucket uintptr
   203  	// }
   204  	// must match ../../../../runtime/hashmap.go:hiter.
   205  	var field [12]*Field
   206  	field[0] = makefield("key", Ptrto(t.Key()))
   207  	field[1] = makefield("val", Ptrto(t.Val()))
   208  	field[2] = makefield("t", Ptrto(Types[TUINT8]))
   209  	field[3] = makefield("h", Ptrto(hmap(t)))
   210  	field[4] = makefield("buckets", Ptrto(mapbucket(t)))
   211  	field[5] = makefield("bptr", Ptrto(mapbucket(t)))
   212  	field[6] = makefield("overflow0", Types[TUNSAFEPTR])
   213  	field[7] = makefield("overflow1", Types[TUNSAFEPTR])
   214  	field[8] = makefield("startBucket", Types[TUINTPTR])
   215  	field[9] = makefield("stuff", Types[TUINTPTR]) // offset+wrapped+B+I
   216  	field[10] = makefield("bucket", Types[TUINTPTR])
   217  	field[11] = makefield("checkBucket", Types[TUINTPTR])
   218  
   219  	// build iterator struct holding the above fields
   220  	i := typ(TSTRUCT)
   221  	i.Noalg = true
   222  	i.SetFields(field[:])
   223  	dowidth(i)
   224  	if i.Width != int64(12*Widthptr) {
   225  		Yyerror("hash_iter size not correct %d %d", i.Width, 12*Widthptr)
   226  	}
   227  	t.Hiter = i
   228  	i.Map = t
   229  	return i
   230  }
   231  
   232  // f is method type, with receiver.
   233  // return function type, receiver as first argument (or not).
   234  func methodfunc(f *Type, receiver *Type) *Type {
   235  	var in []*Node
   236  	if receiver != nil {
   237  		d := Nod(ODCLFIELD, nil, nil)
   238  		d.Type = receiver
   239  		in = append(in, d)
   240  	}
   241  
   242  	var d *Node
   243  	for _, t := range f.Params().Fields().Slice() {
   244  		d = Nod(ODCLFIELD, nil, nil)
   245  		d.Type = t.Type
   246  		d.Isddd = t.Isddd
   247  		in = append(in, d)
   248  	}
   249  
   250  	var out []*Node
   251  	for _, t := range f.Results().Fields().Slice() {
   252  		d = Nod(ODCLFIELD, nil, nil)
   253  		d.Type = t.Type
   254  		out = append(out, d)
   255  	}
   256  
   257  	t := functype(nil, in, out)
   258  	if f.Nname() != nil {
   259  		// Link to name of original method function.
   260  		t.SetNname(f.Nname())
   261  	}
   262  
   263  	return t
   264  }
   265  
   266  // methods returns the methods of the non-interface type t, sorted by name.
   267  // Generates stub functions as needed.
   268  func methods(t *Type) []*Sig {
   269  	// method type
   270  	mt := methtype(t, 0)
   271  
   272  	if mt == nil {
   273  		return nil
   274  	}
   275  	expandmeth(mt)
   276  
   277  	// type stored in interface word
   278  	it := t
   279  
   280  	if !isdirectiface(it) {
   281  		it = Ptrto(t)
   282  	}
   283  
   284  	// make list of methods for t,
   285  	// generating code if necessary.
   286  	var ms []*Sig
   287  	for _, f := range mt.AllMethods().Slice() {
   288  		if f.Type.Etype != TFUNC || f.Type.Recv() == nil {
   289  			Fatalf("non-method on %v method %v %v\n", mt, f.Sym, f)
   290  		}
   291  		if f.Type.Recv() == nil {
   292  			Fatalf("receiver with no type on %v method %v %v\n", mt, f.Sym, f)
   293  		}
   294  		if f.Nointerface {
   295  			continue
   296  		}
   297  
   298  		method := f.Sym
   299  		if method == nil {
   300  			continue
   301  		}
   302  
   303  		// get receiver type for this particular method.
   304  		// if pointer receiver but non-pointer t and
   305  		// this is not an embedded pointer inside a struct,
   306  		// method does not apply.
   307  		this := f.Type.Recv().Type
   308  
   309  		if this.IsPtr() && this.Elem() == t {
   310  			continue
   311  		}
   312  		if this.IsPtr() && !t.IsPtr() && f.Embedded != 2 && !isifacemethod(f.Type) {
   313  			continue
   314  		}
   315  
   316  		var sig Sig
   317  		ms = append(ms, &sig)
   318  
   319  		sig.name = method.Name
   320  		if !exportname(method.Name) {
   321  			if method.Pkg == nil {
   322  				Fatalf("methods: missing package")
   323  			}
   324  			sig.pkg = method.Pkg
   325  		}
   326  
   327  		sig.isym = methodsym(method, it, 1)
   328  		sig.tsym = methodsym(method, t, 0)
   329  		sig.type_ = methodfunc(f.Type, t)
   330  		sig.mtype = methodfunc(f.Type, nil)
   331  
   332  		if sig.isym.Flags&SymSiggen == 0 {
   333  			sig.isym.Flags |= SymSiggen
   334  			if !Eqtype(this, it) || this.Width < Types[Tptr].Width {
   335  				compiling_wrappers = 1
   336  				genwrapper(it, f, sig.isym, 1)
   337  				compiling_wrappers = 0
   338  			}
   339  		}
   340  
   341  		if sig.tsym.Flags&SymSiggen == 0 {
   342  			sig.tsym.Flags |= SymSiggen
   343  			if !Eqtype(this, t) {
   344  				compiling_wrappers = 1
   345  				genwrapper(t, f, sig.tsym, 0)
   346  				compiling_wrappers = 0
   347  			}
   348  		}
   349  	}
   350  
   351  	sort.Sort(byMethodNameAndPackagePath(ms))
   352  	return ms
   353  }
   354  
   355  // imethods returns the methods of the interface type t, sorted by name.
   356  func imethods(t *Type) []*Sig {
   357  	var methods []*Sig
   358  	for _, f := range t.Fields().Slice() {
   359  		if f.Type.Etype != TFUNC || f.Sym == nil {
   360  			continue
   361  		}
   362  		method := f.Sym
   363  		var sig = Sig{
   364  			name: method.Name,
   365  		}
   366  		if !exportname(method.Name) {
   367  			if method.Pkg == nil {
   368  				Fatalf("imethods: missing package")
   369  			}
   370  			sig.pkg = method.Pkg
   371  		}
   372  
   373  		sig.mtype = f.Type
   374  		sig.offset = 0
   375  		sig.type_ = methodfunc(f.Type, nil)
   376  
   377  		if n := len(methods); n > 0 {
   378  			last := methods[n-1]
   379  			if !(siglt(last, &sig)) {
   380  				Fatalf("sigcmp vs sortinter %s %s", last.name, sig.name)
   381  			}
   382  		}
   383  		methods = append(methods, &sig)
   384  
   385  		// Compiler can only refer to wrappers for non-blank methods.
   386  		if isblanksym(method) {
   387  			continue
   388  		}
   389  
   390  		// NOTE(rsc): Perhaps an oversight that
   391  		// IfaceType.Method is not in the reflect data.
   392  		// Generate the method body, so that compiled
   393  		// code can refer to it.
   394  		isym := methodsym(method, t, 0)
   395  
   396  		if isym.Flags&SymSiggen == 0 {
   397  			isym.Flags |= SymSiggen
   398  			genwrapper(t, f, isym, 0)
   399  		}
   400  	}
   401  
   402  	return methods
   403  }
   404  
   405  var dimportpath_gopkg *Pkg
   406  
   407  func dimportpath(p *Pkg) {
   408  	if p.Pathsym != nil {
   409  		return
   410  	}
   411  
   412  	// If we are compiling the runtime package, there are two runtime packages around
   413  	// -- localpkg and Runtimepkg. We don't want to produce import path symbols for
   414  	// both of them, so just produce one for localpkg.
   415  	if myimportpath == "runtime" && p == Runtimepkg {
   416  		return
   417  	}
   418  
   419  	if dimportpath_gopkg == nil {
   420  		dimportpath_gopkg = mkpkg("go")
   421  		dimportpath_gopkg.Name = "go"
   422  	}
   423  
   424  	nam := "importpath." + p.Prefix + "."
   425  
   426  	n := Nod(ONAME, nil, nil)
   427  	n.Sym = Pkglookup(nam, dimportpath_gopkg)
   428  
   429  	n.Class = PEXTERN
   430  	n.Xoffset = 0
   431  	p.Pathsym = n.Sym
   432  
   433  	if p == localpkg {
   434  		// Note: myimportpath != "", or else dgopkgpath won't call dimportpath.
   435  		gdatastring(n, myimportpath)
   436  	} else {
   437  		gdatastring(n, p.Path)
   438  	}
   439  	ggloblsym(n.Sym, int32(Types[TSTRING].Width), obj.DUPOK|obj.RODATA)
   440  }
   441  
   442  func dgopkgpath(s *Sym, ot int, pkg *Pkg) int {
   443  	return dgopkgpathLSym(Linksym(s), ot, pkg)
   444  }
   445  
   446  func dgopkgpathLSym(s *obj.LSym, ot int, pkg *Pkg) int {
   447  	if pkg == nil {
   448  		return duintxxLSym(s, ot, 0, Widthptr)
   449  	}
   450  
   451  	if pkg == localpkg && myimportpath == "" {
   452  		// If we don't know the full import path of the package being compiled
   453  		// (i.e. -p was not passed on the compiler command line), emit a reference to
   454  		// go.importpath.""., which the linker will rewrite using the correct import path.
   455  		// Every package that imports this one directly defines the symbol.
   456  		// See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ.
   457  		ns := obj.Linklookup(Ctxt, `go.importpath."".`, 0)
   458  		return dsymptrLSym(s, ot, ns, 0)
   459  	}
   460  
   461  	dimportpath(pkg)
   462  	return dsymptrLSym(s, ot, Linksym(pkg.Pathsym), 0)
   463  }
   464  
   465  // isExportedField reports whether a struct field is exported.
   466  func isExportedField(ft *Field) bool {
   467  	if ft.Sym != nil && ft.Embedded == 0 {
   468  		return exportname(ft.Sym.Name)
   469  	} else {
   470  		if ft.Type.Sym != nil &&
   471  			(ft.Type.Sym.Pkg == builtinpkg || !exportname(ft.Type.Sym.Name)) {
   472  			return false
   473  		} else {
   474  			return true
   475  		}
   476  	}
   477  }
   478  
   479  // dnameField dumps a reflect.name for a struct field.
   480  func dnameField(s *Sym, ot int, ft *Field) int {
   481  	var name, tag string
   482  	if ft.Sym != nil && ft.Embedded == 0 {
   483  		name = ft.Sym.Name
   484  	}
   485  	if ft.Note != nil {
   486  		tag = *ft.Note
   487  	}
   488  	return dname(s, ot, name, tag, nil, isExportedField(ft))
   489  }
   490  
   491  var dnameCount int
   492  
   493  // dname dumps a reflect.name for a struct field or method.
   494  func dname(s *Sym, ot int, name, tag string, pkg *Pkg, exported bool) int {
   495  	if len(name) > 1<<16-1 {
   496  		Fatalf("name too long: %s", name)
   497  	}
   498  	if len(tag) > 1<<16-1 {
   499  		Fatalf("tag too long: %s", tag)
   500  	}
   501  
   502  	// Encode name and tag. See reflect/type.go for details.
   503  	var bits byte
   504  	l := 1 + 2 + len(name)
   505  	if exported {
   506  		bits |= 1 << 0
   507  	}
   508  	if len(tag) > 0 {
   509  		l += 2 + len(tag)
   510  		bits |= 1 << 1
   511  	}
   512  	if pkg != nil {
   513  		bits |= 1 << 2
   514  	}
   515  	b := make([]byte, l)
   516  	b[0] = bits
   517  	b[1] = uint8(len(name) >> 8)
   518  	b[2] = uint8(len(name))
   519  	copy(b[3:], name)
   520  	if len(tag) > 0 {
   521  		tb := b[3+len(name):]
   522  		tb[0] = uint8(len(tag) >> 8)
   523  		tb[1] = uint8(len(tag))
   524  		copy(tb[2:], tag)
   525  	}
   526  
   527  	// Very few names require a pkgPath *string (only those
   528  	// defined in a different package than their type). So if
   529  	// there is no pkgPath, we treat the name contents as string
   530  	// data that duplicates across packages.
   531  	var bsym *obj.LSym
   532  	if pkg == nil {
   533  		_, bsym = stringsym(string(b))
   534  	} else {
   535  		// Write out data as "type.." to signal two things to the
   536  		// linker, first that when dynamically linking, the symbol
   537  		// should be moved to a relro section, and second that the
   538  		// contents should not be decoded as a type.
   539  		bsymname := fmt.Sprintf(`type..methodname."".%d`, dnameCount)
   540  		dnameCount++
   541  		bsym = obj.Linklookup(Ctxt, bsymname, 0)
   542  		bsym.P = b
   543  		boff := len(b)
   544  		boff = int(Rnd(int64(boff), int64(Widthptr)))
   545  		boff = dgopkgpathLSym(bsym, boff, pkg)
   546  		ggloblLSym(bsym, int32(boff), obj.RODATA|obj.LOCAL)
   547  	}
   548  
   549  	ot = dsymptrLSym(Linksym(s), ot, bsym, 0)
   550  
   551  	return ot
   552  }
   553  
   554  // dextratype dumps the fields of a runtime.uncommontype.
   555  // dataAdd is the offset in bytes after the header where the
   556  // backing array of the []method field is written (by dextratypeData).
   557  func dextratype(s *Sym, ot int, t *Type, dataAdd int) int {
   558  	m := methods(t)
   559  	if t.Sym == nil && len(m) == 0 {
   560  		return ot
   561  	}
   562  	noff := int(Rnd(int64(ot), int64(Widthptr)))
   563  	if noff != ot {
   564  		Fatalf("unexpected alignment in dextratype for %s", t)
   565  	}
   566  
   567  	for _, a := range m {
   568  		dtypesym(a.type_)
   569  	}
   570  
   571  	ot = dgopkgpath(s, ot, typePkg(t))
   572  
   573  	// slice header
   574  	ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint+dataAdd)
   575  
   576  	n := len(m)
   577  	ot = duintxx(s, ot, uint64(n), Widthint)
   578  	ot = duintxx(s, ot, uint64(n), Widthint)
   579  
   580  	return ot
   581  }
   582  
   583  func typePkg(t *Type) *Pkg {
   584  	tsym := t.Sym
   585  	if tsym == nil {
   586  		switch t.Etype {
   587  		case TARRAY, TPTR32, TPTR64, TCHAN:
   588  			if t.Elem() != nil {
   589  				tsym = t.Elem().Sym
   590  			}
   591  		}
   592  	}
   593  	if tsym != nil && t != Types[t.Etype] && t != errortype {
   594  		return tsym.Pkg
   595  	}
   596  	return nil
   597  }
   598  
   599  // dextratypeData dumps the backing array for the []method field of
   600  // runtime.uncommontype.
   601  func dextratypeData(s *Sym, ot int, t *Type) int {
   602  	for _, a := range methods(t) {
   603  		// ../../../../runtime/type.go:/method
   604  		exported := exportname(a.name)
   605  		var pkg *Pkg
   606  		if !exported && a.pkg != typePkg(t) {
   607  			pkg = a.pkg
   608  		}
   609  		ot = dname(s, ot, a.name, "", pkg, exported)
   610  		ot = dmethodptr(s, ot, dtypesym(a.mtype))
   611  		ot = dmethodptr(s, ot, a.isym)
   612  		ot = dmethodptr(s, ot, a.tsym)
   613  	}
   614  	return ot
   615  }
   616  
   617  func dmethodptr(s *Sym, off int, x *Sym) int {
   618  	duintptr(s, off, 0)
   619  	r := obj.Addrel(Linksym(s))
   620  	r.Off = int32(off)
   621  	r.Siz = uint8(Widthptr)
   622  	r.Sym = Linksym(x)
   623  	r.Type = obj.R_METHOD
   624  	return off + Widthptr
   625  }
   626  
   627  var kinds = []int{
   628  	TINT:        obj.KindInt,
   629  	TUINT:       obj.KindUint,
   630  	TINT8:       obj.KindInt8,
   631  	TUINT8:      obj.KindUint8,
   632  	TINT16:      obj.KindInt16,
   633  	TUINT16:     obj.KindUint16,
   634  	TINT32:      obj.KindInt32,
   635  	TUINT32:     obj.KindUint32,
   636  	TINT64:      obj.KindInt64,
   637  	TUINT64:     obj.KindUint64,
   638  	TUINTPTR:    obj.KindUintptr,
   639  	TFLOAT32:    obj.KindFloat32,
   640  	TFLOAT64:    obj.KindFloat64,
   641  	TBOOL:       obj.KindBool,
   642  	TSTRING:     obj.KindString,
   643  	TPTR32:      obj.KindPtr,
   644  	TPTR64:      obj.KindPtr,
   645  	TSTRUCT:     obj.KindStruct,
   646  	TINTER:      obj.KindInterface,
   647  	TCHAN:       obj.KindChan,
   648  	TMAP:        obj.KindMap,
   649  	TARRAY:      obj.KindArray,
   650  	TFUNC:       obj.KindFunc,
   651  	TCOMPLEX64:  obj.KindComplex64,
   652  	TCOMPLEX128: obj.KindComplex128,
   653  	TUNSAFEPTR:  obj.KindUnsafePointer,
   654  }
   655  
   656  func haspointers(t *Type) bool {
   657  	if t.Haspointers != 0 {
   658  		return t.Haspointers-1 != 0
   659  	}
   660  
   661  	var ret bool
   662  	switch t.Etype {
   663  	case TINT,
   664  		TUINT,
   665  		TINT8,
   666  		TUINT8,
   667  		TINT16,
   668  		TUINT16,
   669  		TINT32,
   670  		TUINT32,
   671  		TINT64,
   672  		TUINT64,
   673  		TUINTPTR,
   674  		TFLOAT32,
   675  		TFLOAT64,
   676  		TCOMPLEX64,
   677  		TCOMPLEX128,
   678  		TBOOL:
   679  		ret = false
   680  
   681  	case TARRAY:
   682  		if t.IsSlice() {
   683  			ret = true
   684  			break
   685  		}
   686  
   687  		if t.NumElem() == 0 { // empty array
   688  			ret = false
   689  			break
   690  		}
   691  
   692  		ret = haspointers(t.Elem())
   693  
   694  	case TSTRUCT:
   695  		ret = false
   696  		for _, t1 := range t.Fields().Slice() {
   697  			if haspointers(t1.Type) {
   698  				ret = true
   699  				break
   700  			}
   701  		}
   702  
   703  	case TSTRING,
   704  		TPTR32,
   705  		TPTR64,
   706  		TUNSAFEPTR,
   707  		TINTER,
   708  		TCHAN,
   709  		TMAP,
   710  		TFUNC:
   711  		fallthrough
   712  	default:
   713  		ret = true
   714  	}
   715  
   716  	t.Haspointers = 1 + uint8(obj.Bool2int(ret))
   717  	return ret
   718  }
   719  
   720  // typeptrdata returns the length in bytes of the prefix of t
   721  // containing pointer data. Anything after this offset is scalar data.
   722  func typeptrdata(t *Type) int64 {
   723  	if !haspointers(t) {
   724  		return 0
   725  	}
   726  
   727  	switch t.Etype {
   728  	case TPTR32,
   729  		TPTR64,
   730  		TUNSAFEPTR,
   731  		TFUNC,
   732  		TCHAN,
   733  		TMAP:
   734  		return int64(Widthptr)
   735  
   736  	case TSTRING:
   737  		// struct { byte *str; intgo len; }
   738  		return int64(Widthptr)
   739  
   740  	case TINTER:
   741  		// struct { Itab *tab;	void *data; } or
   742  		// struct { Type *type; void *data; }
   743  		return 2 * int64(Widthptr)
   744  
   745  	case TARRAY:
   746  		if t.IsSlice() {
   747  			// struct { byte *array; uintgo len; uintgo cap; }
   748  			return int64(Widthptr)
   749  		}
   750  		// haspointers already eliminated t.NumElem() == 0.
   751  		return (t.NumElem()-1)*t.Elem().Width + typeptrdata(t.Elem())
   752  
   753  	case TSTRUCT:
   754  		// Find the last field that has pointers.
   755  		var lastPtrField *Field
   756  		for _, t1 := range t.Fields().Slice() {
   757  			if haspointers(t1.Type) {
   758  				lastPtrField = t1
   759  			}
   760  		}
   761  		return lastPtrField.Offset + typeptrdata(lastPtrField.Type)
   762  
   763  	default:
   764  		Fatalf("typeptrdata: unexpected type, %v", t)
   765  		return 0
   766  	}
   767  }
   768  
   769  // tflag is documented in ../../../../reflect/type.go.
   770  const tflagUncommon = 1
   771  
   772  // commonType
   773  // ../../../../runtime/type.go:/commonType
   774  
   775  var dcommontype_algarray *Sym
   776  
   777  func dcommontype(s *Sym, ot int, t *Type) int {
   778  	if ot != 0 {
   779  		Fatalf("dcommontype %d", ot)
   780  	}
   781  
   782  	sizeofAlg := 2 * Widthptr
   783  	if dcommontype_algarray == nil {
   784  		dcommontype_algarray = Pkglookup("algarray", Runtimepkg)
   785  	}
   786  	dowidth(t)
   787  	alg := algtype(t)
   788  	var algsym *Sym
   789  	if alg == ASPECIAL || alg == AMEM {
   790  		algsym = dalgsym(t)
   791  	}
   792  
   793  	tptr := Ptrto(t)
   794  	if !t.IsPtr() && (t.Sym != nil || methods(tptr) != nil) {
   795  		sptr := dtypesym(tptr)
   796  		r := obj.Addrel(Linksym(s))
   797  		r.Off = 0
   798  		r.Siz = 0
   799  		r.Sym = sptr.Lsym
   800  		r.Type = obj.R_USETYPE
   801  	}
   802  
   803  	gcsym, useGCProg, ptrdata := dgcsym(t)
   804  
   805  	// ../../../../reflect/type.go:/^type.rtype
   806  	// actual type structure
   807  	//	type rtype struct {
   808  	//		size          uintptr
   809  	//		ptrdata       uintptr
   810  	//		hash          uint32
   811  	//		tflag         tflag
   812  	//		align         uint8
   813  	//		fieldAlign    uint8
   814  	//		kind          uint8
   815  	//		alg           *typeAlg
   816  	//		gcdata        *byte
   817  	//		string        *string
   818  	//	}
   819  	ot = duintptr(s, ot, uint64(t.Width))
   820  	ot = duintptr(s, ot, uint64(ptrdata))
   821  
   822  	ot = duint32(s, ot, typehash(t))
   823  
   824  	var tflag uint8
   825  	if uncommonSize(t) != 0 {
   826  		tflag |= tflagUncommon
   827  	}
   828  	ot = duint8(s, ot, tflag)
   829  
   830  	// runtime (and common sense) expects alignment to be a power of two.
   831  	i := int(t.Align)
   832  
   833  	if i == 0 {
   834  		i = 1
   835  	}
   836  	if i&(i-1) != 0 {
   837  		Fatalf("invalid alignment %d for %v", t.Align, t)
   838  	}
   839  	ot = duint8(s, ot, t.Align) // align
   840  	ot = duint8(s, ot, t.Align) // fieldAlign
   841  
   842  	i = kinds[t.Etype]
   843  	if t.IsSlice() {
   844  		i = obj.KindSlice
   845  	}
   846  	if !haspointers(t) {
   847  		i |= obj.KindNoPointers
   848  	}
   849  	if isdirectiface(t) {
   850  		i |= obj.KindDirectIface
   851  	}
   852  	if useGCProg {
   853  		i |= obj.KindGCProg
   854  	}
   855  	ot = duint8(s, ot, uint8(i)) // kind
   856  	if algsym == nil {
   857  		ot = dsymptr(s, ot, dcommontype_algarray, int(alg)*sizeofAlg)
   858  	} else {
   859  		ot = dsymptr(s, ot, algsym, 0)
   860  	}
   861  	ot = dsymptr(s, ot, gcsym, 0) // gcdata
   862  
   863  	p := Tconv(t, FmtLeft|FmtUnsigned)
   864  
   865  	// If we're writing out type T,
   866  	// we are very likely to write out type *T as well.
   867  	// Use the string "*T"[1:] for "T", so that the two
   868  	// share storage. This is a cheap way to reduce the
   869  	// amount of space taken up by reflect strings.
   870  	prefix := 0
   871  	if !strings.HasPrefix(p, "*") {
   872  		p = "*" + p
   873  		prefix = 1
   874  	}
   875  	_, symdata := stringsym(p) // string
   876  	ot = dsymptrLSym(Linksym(s), ot, symdata, prefix)
   877  	ot = duintxx(s, ot, uint64(len(p)-prefix), Widthint)
   878  
   879  	return ot
   880  }
   881  
   882  func typesym(t *Type) *Sym {
   883  	return Pkglookup(Tconv(t, FmtLeft), typepkg)
   884  }
   885  
   886  // tracksym returns the symbol for tracking use of field/method f, assumed
   887  // to be a member of struct/interface type t.
   888  func tracksym(t *Type, f *Field) *Sym {
   889  	return Pkglookup(Tconv(t, FmtLeft)+"."+f.Sym.Name, trackpkg)
   890  }
   891  
   892  func typelinksym(t *Type) *Sym {
   893  	// %-uT is what the generated Type's string field says.
   894  	// It uses (ambiguous) package names instead of import paths.
   895  	// %-T is the complete, unambiguous type name.
   896  	// We want the types to end up sorted by string field,
   897  	// so use that first in the name, and then add :%-T to
   898  	// disambiguate. We use a tab character as the separator to
   899  	// ensure the types appear sorted by their string field. The
   900  	// names are a little long but they are discarded by the linker
   901  	// and do not end up in the symbol table of the final binary.
   902  	p := Tconv(t, FmtLeft|FmtUnsigned) + "\t" + Tconv(t, FmtLeft)
   903  
   904  	s := Pkglookup(p, typelinkpkg)
   905  
   906  	//print("typelinksym: %s -> %+S\n", p, s);
   907  
   908  	return s
   909  }
   910  
   911  func typesymprefix(prefix string, t *Type) *Sym {
   912  	p := prefix + "." + Tconv(t, FmtLeft)
   913  	s := Pkglookup(p, typepkg)
   914  
   915  	//print("algsym: %s -> %+S\n", p, s);
   916  
   917  	return s
   918  }
   919  
   920  func typenamesym(t *Type) *Sym {
   921  	if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
   922  		Fatalf("typename %v", t)
   923  	}
   924  	s := typesym(t)
   925  	if s.Def == nil {
   926  		n := newname(s)
   927  		n.Type = Types[TUINT8]
   928  		n.Class = PEXTERN
   929  		n.Typecheck = 1
   930  		s.Def = n
   931  
   932  		signatlist = append(signatlist, typenod(t))
   933  	}
   934  
   935  	return s.Def.Sym
   936  }
   937  
   938  func typename(t *Type) *Node {
   939  	s := typenamesym(t)
   940  	n := Nod(OADDR, s.Def, nil)
   941  	n.Type = Ptrto(s.Def.Type)
   942  	n.Addable = true
   943  	n.Ullman = 2
   944  	n.Typecheck = 1
   945  	return n
   946  }
   947  
   948  func itabname(t, itype *Type) *Node {
   949  	if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
   950  		Fatalf("itabname %v", t)
   951  	}
   952  	s := Pkglookup(Tconv(t, FmtLeft)+","+Tconv(itype, FmtLeft), itabpkg)
   953  	if s.Def == nil {
   954  		n := newname(s)
   955  		n.Type = Types[TUINT8]
   956  		n.Class = PEXTERN
   957  		n.Typecheck = 1
   958  		s.Def = n
   959  
   960  		itabs = append(itabs, itabEntry{t: t, itype: itype, sym: s})
   961  	}
   962  
   963  	n := Nod(OADDR, s.Def, nil)
   964  	n.Type = Ptrto(s.Def.Type)
   965  	n.Addable = true
   966  	n.Ullman = 2
   967  	n.Typecheck = 1
   968  	return n
   969  }
   970  
   971  // isreflexive reports whether t has a reflexive equality operator.
   972  // That is, if x==x for all x of type t.
   973  func isreflexive(t *Type) bool {
   974  	switch t.Etype {
   975  	case TBOOL,
   976  		TINT,
   977  		TUINT,
   978  		TINT8,
   979  		TUINT8,
   980  		TINT16,
   981  		TUINT16,
   982  		TINT32,
   983  		TUINT32,
   984  		TINT64,
   985  		TUINT64,
   986  		TUINTPTR,
   987  		TPTR32,
   988  		TPTR64,
   989  		TUNSAFEPTR,
   990  		TSTRING,
   991  		TCHAN:
   992  		return true
   993  
   994  	case TFLOAT32,
   995  		TFLOAT64,
   996  		TCOMPLEX64,
   997  		TCOMPLEX128,
   998  		TINTER:
   999  		return false
  1000  
  1001  	case TARRAY:
  1002  		if t.IsSlice() {
  1003  			Fatalf("slice can't be a map key: %v", t)
  1004  		}
  1005  		return isreflexive(t.Elem())
  1006  
  1007  	case TSTRUCT:
  1008  		for _, t1 := range t.Fields().Slice() {
  1009  			if !isreflexive(t1.Type) {
  1010  				return false
  1011  			}
  1012  		}
  1013  		return true
  1014  
  1015  	default:
  1016  		Fatalf("bad type for map key: %v", t)
  1017  		return false
  1018  	}
  1019  }
  1020  
  1021  // needkeyupdate reports whether map updates with t as a key
  1022  // need the key to be updated.
  1023  func needkeyupdate(t *Type) bool {
  1024  	switch t.Etype {
  1025  	case TBOOL,
  1026  		TINT,
  1027  		TUINT,
  1028  		TINT8,
  1029  		TUINT8,
  1030  		TINT16,
  1031  		TUINT16,
  1032  		TINT32,
  1033  		TUINT32,
  1034  		TINT64,
  1035  		TUINT64,
  1036  		TUINTPTR,
  1037  		TPTR32,
  1038  		TPTR64,
  1039  		TUNSAFEPTR,
  1040  		TCHAN:
  1041  		return false
  1042  
  1043  	case TFLOAT32, // floats can be +0/-0
  1044  		TFLOAT64,
  1045  		TCOMPLEX64,
  1046  		TCOMPLEX128,
  1047  		TINTER,
  1048  		TSTRING: // strings might have smaller backing stores
  1049  		return true
  1050  
  1051  	case TARRAY:
  1052  		if t.IsSlice() {
  1053  			Fatalf("slice can't be a map key: %v", t)
  1054  		}
  1055  		return needkeyupdate(t.Elem())
  1056  
  1057  	case TSTRUCT:
  1058  		for _, t1 := range t.Fields().Slice() {
  1059  			if needkeyupdate(t1.Type) {
  1060  				return true
  1061  			}
  1062  		}
  1063  		return false
  1064  
  1065  	default:
  1066  		Fatalf("bad type for map key: %v", t)
  1067  		return true
  1068  	}
  1069  }
  1070  
  1071  func dtypesym(t *Type) *Sym {
  1072  	// Replace byte, rune aliases with real type.
  1073  	// They've been separate internally to make error messages
  1074  	// better, but we have to merge them in the reflect tables.
  1075  	if t == bytetype || t == runetype {
  1076  		t = Types[t.Etype]
  1077  	}
  1078  
  1079  	if t.IsUntyped() {
  1080  		Fatalf("dtypesym %v", t)
  1081  	}
  1082  
  1083  	s := typesym(t)
  1084  	if s.Flags&SymSiggen != 0 {
  1085  		return s
  1086  	}
  1087  	s.Flags |= SymSiggen
  1088  
  1089  	// special case (look for runtime below):
  1090  	// when compiling package runtime,
  1091  	// emit the type structures for int, float, etc.
  1092  	tbase := t
  1093  
  1094  	if t.IsPtr() && t.Sym == nil && t.Elem().Sym != nil {
  1095  		tbase = t.Elem()
  1096  	}
  1097  	dupok := 0
  1098  	if tbase.Sym == nil {
  1099  		dupok = obj.DUPOK
  1100  	}
  1101  
  1102  	if myimportpath == "runtime" && (tbase == Types[tbase.Etype] || tbase == bytetype || tbase == runetype || tbase == errortype) { // int, float, etc
  1103  		goto ok
  1104  	}
  1105  
  1106  	// named types from other files are defined only by those files
  1107  	if tbase.Sym != nil && !tbase.Local {
  1108  		return s
  1109  	}
  1110  	if isforw[tbase.Etype] {
  1111  		return s
  1112  	}
  1113  
  1114  ok:
  1115  	ot := 0
  1116  	switch t.Etype {
  1117  	default:
  1118  		ot = dcommontype(s, ot, t)
  1119  		ot = dextratype(s, ot, t, 0)
  1120  
  1121  	case TARRAY:
  1122  		if t.IsArray() {
  1123  			// ../../../../runtime/type.go:/arrayType
  1124  			s1 := dtypesym(t.Elem())
  1125  			t2 := typSlice(t.Elem())
  1126  			s2 := dtypesym(t2)
  1127  			ot = dcommontype(s, ot, t)
  1128  			ot = dsymptr(s, ot, s1, 0)
  1129  			ot = dsymptr(s, ot, s2, 0)
  1130  			ot = duintptr(s, ot, uint64(t.NumElem()))
  1131  		} else {
  1132  			// ../../../../runtime/type.go:/sliceType
  1133  			s1 := dtypesym(t.Elem())
  1134  
  1135  			ot = dcommontype(s, ot, t)
  1136  			ot = dsymptr(s, ot, s1, 0)
  1137  		}
  1138  		ot = dextratype(s, ot, t, 0)
  1139  
  1140  	// ../../../../runtime/type.go:/chanType
  1141  	case TCHAN:
  1142  		s1 := dtypesym(t.Elem())
  1143  
  1144  		ot = dcommontype(s, ot, t)
  1145  		ot = dsymptr(s, ot, s1, 0)
  1146  		ot = duintptr(s, ot, uint64(t.ChanDir()))
  1147  		ot = dextratype(s, ot, t, 0)
  1148  
  1149  	case TFUNC:
  1150  		for _, t1 := range t.Recvs().Fields().Slice() {
  1151  			dtypesym(t1.Type)
  1152  		}
  1153  		isddd := false
  1154  		for _, t1 := range t.Params().Fields().Slice() {
  1155  			isddd = t1.Isddd
  1156  			dtypesym(t1.Type)
  1157  		}
  1158  		for _, t1 := range t.Results().Fields().Slice() {
  1159  			dtypesym(t1.Type)
  1160  		}
  1161  
  1162  		ot = dcommontype(s, ot, t)
  1163  		inCount := t.Recvs().NumFields() + t.Params().NumFields()
  1164  		outCount := t.Results().NumFields()
  1165  		if isddd {
  1166  			outCount |= 1 << 15
  1167  		}
  1168  		ot = duint16(s, ot, uint16(inCount))
  1169  		ot = duint16(s, ot, uint16(outCount))
  1170  		if Widthptr == 8 {
  1171  			ot += 4 // align for *rtype
  1172  		}
  1173  
  1174  		dataAdd := (inCount + t.Results().NumFields()) * Widthptr
  1175  		ot = dextratype(s, ot, t, dataAdd)
  1176  
  1177  		// Array of rtype pointers follows funcType.
  1178  		for _, t1 := range t.Recvs().Fields().Slice() {
  1179  			ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
  1180  		}
  1181  		for _, t1 := range t.Params().Fields().Slice() {
  1182  			ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
  1183  		}
  1184  		for _, t1 := range t.Results().Fields().Slice() {
  1185  			ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
  1186  		}
  1187  
  1188  	case TINTER:
  1189  		m := imethods(t)
  1190  		n := len(m)
  1191  		for _, a := range m {
  1192  			dtypesym(a.type_)
  1193  		}
  1194  
  1195  		// ../../../../runtime/type.go:/interfaceType
  1196  		ot = dcommontype(s, ot, t)
  1197  
  1198  		var tpkg *Pkg
  1199  		if t.Sym != nil && t != Types[t.Etype] && t != errortype {
  1200  			tpkg = t.Sym.Pkg
  1201  		}
  1202  		ot = dgopkgpath(s, ot, tpkg)
  1203  
  1204  		ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint+uncommonSize(t))
  1205  		ot = duintxx(s, ot, uint64(n), Widthint)
  1206  		ot = duintxx(s, ot, uint64(n), Widthint)
  1207  		dataAdd := imethodSize() * n
  1208  		ot = dextratype(s, ot, t, dataAdd)
  1209  
  1210  		for _, a := range m {
  1211  			// ../../../../runtime/type.go:/imethod
  1212  			exported := exportname(a.name)
  1213  			var pkg *Pkg
  1214  			if !exported && a.pkg != tpkg {
  1215  				pkg = a.pkg
  1216  			}
  1217  			ot = dname(s, ot, a.name, "", pkg, exported)
  1218  			ot = dsymptr(s, ot, dtypesym(a.type_), 0)
  1219  		}
  1220  
  1221  	// ../../../../runtime/type.go:/mapType
  1222  	case TMAP:
  1223  		s1 := dtypesym(t.Key())
  1224  		s2 := dtypesym(t.Val())
  1225  		s3 := dtypesym(mapbucket(t))
  1226  		s4 := dtypesym(hmap(t))
  1227  		ot = dcommontype(s, ot, t)
  1228  		ot = dsymptr(s, ot, s1, 0)
  1229  		ot = dsymptr(s, ot, s2, 0)
  1230  		ot = dsymptr(s, ot, s3, 0)
  1231  		ot = dsymptr(s, ot, s4, 0)
  1232  		if t.Key().Width > MAXKEYSIZE {
  1233  			ot = duint8(s, ot, uint8(Widthptr))
  1234  			ot = duint8(s, ot, 1) // indirect
  1235  		} else {
  1236  			ot = duint8(s, ot, uint8(t.Key().Width))
  1237  			ot = duint8(s, ot, 0) // not indirect
  1238  		}
  1239  
  1240  		if t.Val().Width > MAXVALSIZE {
  1241  			ot = duint8(s, ot, uint8(Widthptr))
  1242  			ot = duint8(s, ot, 1) // indirect
  1243  		} else {
  1244  			ot = duint8(s, ot, uint8(t.Val().Width))
  1245  			ot = duint8(s, ot, 0) // not indirect
  1246  		}
  1247  
  1248  		ot = duint16(s, ot, uint16(mapbucket(t).Width))
  1249  		ot = duint8(s, ot, uint8(obj.Bool2int(isreflexive(t.Key()))))
  1250  		ot = duint8(s, ot, uint8(obj.Bool2int(needkeyupdate(t.Key()))))
  1251  		ot = dextratype(s, ot, t, 0)
  1252  
  1253  	case TPTR32, TPTR64:
  1254  		if t.Elem().Etype == TANY {
  1255  			// ../../../../runtime/type.go:/UnsafePointerType
  1256  			ot = dcommontype(s, ot, t)
  1257  			ot = dextratype(s, ot, t, 0)
  1258  
  1259  			break
  1260  		}
  1261  
  1262  		// ../../../../runtime/type.go:/ptrType
  1263  		s1 := dtypesym(t.Elem())
  1264  
  1265  		ot = dcommontype(s, ot, t)
  1266  		ot = dsymptr(s, ot, s1, 0)
  1267  		ot = dextratype(s, ot, t, 0)
  1268  
  1269  	// ../../../../runtime/type.go:/structType
  1270  	// for security, only the exported fields.
  1271  	case TSTRUCT:
  1272  		n := 0
  1273  
  1274  		for _, t1 := range t.Fields().Slice() {
  1275  			dtypesym(t1.Type)
  1276  			n++
  1277  		}
  1278  
  1279  		ot = dcommontype(s, ot, t)
  1280  		pkg := localpkg
  1281  		if t.Sym != nil {
  1282  			pkg = t.Sym.Pkg
  1283  		}
  1284  		ot = dgopkgpath(s, ot, pkg)
  1285  		ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint+uncommonSize(t))
  1286  		ot = duintxx(s, ot, uint64(n), Widthint)
  1287  		ot = duintxx(s, ot, uint64(n), Widthint)
  1288  
  1289  		dataAdd := n * structfieldSize()
  1290  		ot = dextratype(s, ot, t, dataAdd)
  1291  
  1292  		for _, f := range t.Fields().Slice() {
  1293  			// ../../../../runtime/type.go:/structField
  1294  			ot = dnameField(s, ot, f)
  1295  			ot = dsymptr(s, ot, dtypesym(f.Type), 0)
  1296  			ot = duintptr(s, ot, uint64(f.Offset))
  1297  		}
  1298  	}
  1299  
  1300  	ot = dextratypeData(s, ot, t)
  1301  	ggloblsym(s, int32(ot), int16(dupok|obj.RODATA))
  1302  
  1303  	// generate typelink.foo pointing at s = type.foo.
  1304  	// The linker will leave a table of all the typelinks for
  1305  	// types in the binary, so reflect can find them.
  1306  	// We only need the link for unnamed composites that
  1307  	// we want be able to find.
  1308  	if t.Sym == nil {
  1309  		switch t.Etype {
  1310  		case TPTR32, TPTR64, TARRAY, TCHAN, TFUNC, TMAP, TSTRUCT:
  1311  			slink := typelinksym(t)
  1312  			dsymptr(slink, 0, s, 0)
  1313  			ggloblsym(slink, int32(Widthptr), int16(dupok|obj.RODATA))
  1314  		}
  1315  	}
  1316  
  1317  	return s
  1318  }
  1319  
  1320  func dumptypestructs() {
  1321  	// copy types from externdcl list to signatlist
  1322  	for _, n := range externdcl {
  1323  		if n.Op != OTYPE {
  1324  			continue
  1325  		}
  1326  		signatlist = append(signatlist, n)
  1327  	}
  1328  
  1329  	// Process signatlist.  This can't use range, as entries are
  1330  	// added to the list while it is being processed.
  1331  	for i := 0; i < len(signatlist); i++ {
  1332  		n := signatlist[i]
  1333  		if n.Op != OTYPE {
  1334  			continue
  1335  		}
  1336  		t := n.Type
  1337  		dtypesym(t)
  1338  		if t.Sym != nil {
  1339  			dtypesym(Ptrto(t))
  1340  		}
  1341  	}
  1342  
  1343  	// process itabs
  1344  	for _, i := range itabs {
  1345  		// dump empty itab symbol into i.sym
  1346  		// type itab struct {
  1347  		//   inter  *interfacetype
  1348  		//   _type  *_type
  1349  		//   link   *itab
  1350  		//   bad    int32
  1351  		//   unused int32
  1352  		//   fun    [1]uintptr // variable sized
  1353  		// }
  1354  		o := dsymptr(i.sym, 0, dtypesym(i.itype), 0)
  1355  		o = dsymptr(i.sym, o, dtypesym(i.t), 0)
  1356  		o += Widthptr + 8                      // skip link/bad/unused fields
  1357  		o += len(imethods(i.itype)) * Widthptr // skip fun method pointers
  1358  		// at runtime the itab will contain pointers to types, other itabs and
  1359  		// method functions. None are allocated on heap, so we can use obj.NOPTR.
  1360  		ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR))
  1361  
  1362  		ilink := Pkglookup(Tconv(i.t, FmtLeft)+","+Tconv(i.itype, FmtLeft), itablinkpkg)
  1363  		dsymptr(ilink, 0, i.sym, 0)
  1364  		ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA))
  1365  	}
  1366  
  1367  	// generate import strings for imported packages
  1368  	for _, p := range pkgs {
  1369  		if p.Direct {
  1370  			dimportpath(p)
  1371  		}
  1372  	}
  1373  
  1374  	// do basic types if compiling package runtime.
  1375  	// they have to be in at least one package,
  1376  	// and runtime is always loaded implicitly,
  1377  	// so this is as good as any.
  1378  	// another possible choice would be package main,
  1379  	// but using runtime means fewer copies in .6 files.
  1380  	if myimportpath == "runtime" {
  1381  		for i := EType(1); i <= TBOOL; i++ {
  1382  			dtypesym(Ptrto(Types[i]))
  1383  		}
  1384  		dtypesym(Ptrto(Types[TSTRING]))
  1385  		dtypesym(Ptrto(Types[TUNSAFEPTR]))
  1386  
  1387  		// emit type structs for error and func(error) string.
  1388  		// The latter is the type of an auto-generated wrapper.
  1389  		dtypesym(Ptrto(errortype))
  1390  
  1391  		dtypesym(functype(nil, []*Node{Nod(ODCLFIELD, nil, typenod(errortype))}, []*Node{Nod(ODCLFIELD, nil, typenod(Types[TSTRING]))}))
  1392  
  1393  		// add paths for runtime and main, which 6l imports implicitly.
  1394  		dimportpath(Runtimepkg)
  1395  
  1396  		if flag_race != 0 {
  1397  			dimportpath(racepkg)
  1398  		}
  1399  		if flag_msan != 0 {
  1400  			dimportpath(msanpkg)
  1401  		}
  1402  		dimportpath(mkpkg("main"))
  1403  	}
  1404  }
  1405  
  1406  func dalgsym(t *Type) *Sym {
  1407  	var s *Sym
  1408  	var hashfunc *Sym
  1409  	var eqfunc *Sym
  1410  
  1411  	// dalgsym is only called for a type that needs an algorithm table,
  1412  	// which implies that the type is comparable (or else it would use ANOEQ).
  1413  
  1414  	if algtype(t) == AMEM {
  1415  		// we use one algorithm table for all AMEM types of a given size
  1416  		p := fmt.Sprintf(".alg%d", t.Width)
  1417  
  1418  		s = Pkglookup(p, typepkg)
  1419  
  1420  		if s.Flags&SymAlgGen != 0 {
  1421  			return s
  1422  		}
  1423  		s.Flags |= SymAlgGen
  1424  
  1425  		// make hash closure
  1426  		p = fmt.Sprintf(".hashfunc%d", t.Width)
  1427  
  1428  		hashfunc = Pkglookup(p, typepkg)
  1429  
  1430  		ot := 0
  1431  		ot = dsymptr(hashfunc, ot, Pkglookup("memhash_varlen", Runtimepkg), 0)
  1432  		ot = duintxx(hashfunc, ot, uint64(t.Width), Widthptr) // size encoded in closure
  1433  		ggloblsym(hashfunc, int32(ot), obj.DUPOK|obj.RODATA)
  1434  
  1435  		// make equality closure
  1436  		p = fmt.Sprintf(".eqfunc%d", t.Width)
  1437  
  1438  		eqfunc = Pkglookup(p, typepkg)
  1439  
  1440  		ot = 0
  1441  		ot = dsymptr(eqfunc, ot, Pkglookup("memequal_varlen", Runtimepkg), 0)
  1442  		ot = duintxx(eqfunc, ot, uint64(t.Width), Widthptr)
  1443  		ggloblsym(eqfunc, int32(ot), obj.DUPOK|obj.RODATA)
  1444  	} else {
  1445  		// generate an alg table specific to this type
  1446  		s = typesymprefix(".alg", t)
  1447  
  1448  		hash := typesymprefix(".hash", t)
  1449  		eq := typesymprefix(".eq", t)
  1450  		hashfunc = typesymprefix(".hashfunc", t)
  1451  		eqfunc = typesymprefix(".eqfunc", t)
  1452  
  1453  		genhash(hash, t)
  1454  		geneq(eq, t)
  1455  
  1456  		// make Go funcs (closures) for calling hash and equal from Go
  1457  		dsymptr(hashfunc, 0, hash, 0)
  1458  
  1459  		ggloblsym(hashfunc, int32(Widthptr), obj.DUPOK|obj.RODATA)
  1460  		dsymptr(eqfunc, 0, eq, 0)
  1461  		ggloblsym(eqfunc, int32(Widthptr), obj.DUPOK|obj.RODATA)
  1462  	}
  1463  
  1464  	// ../../../../runtime/alg.go:/typeAlg
  1465  	ot := 0
  1466  
  1467  	ot = dsymptr(s, ot, hashfunc, 0)
  1468  	ot = dsymptr(s, ot, eqfunc, 0)
  1469  	ggloblsym(s, int32(ot), obj.DUPOK|obj.RODATA)
  1470  	return s
  1471  }
  1472  
  1473  // maxPtrmaskBytes is the maximum length of a GC ptrmask bitmap,
  1474  // which holds 1-bit entries describing where pointers are in a given type.
  1475  // 16 bytes is enough to describe 128 pointer-sized words, 512 or 1024 bytes
  1476  // depending on the system. Above this length, the GC information is
  1477  // recorded as a GC program, which can express repetition compactly.
  1478  // In either form, the information is used by the runtime to initialize the
  1479  // heap bitmap, and for large types (like 128 or more words), they are
  1480  // roughly the same speed. GC programs are never much larger and often
  1481  // more compact. (If large arrays are involved, they can be arbitrarily more
  1482  // compact.)
  1483  //
  1484  // The cutoff must be large enough that any allocation large enough to
  1485  // use a GC program is large enough that it does not share heap bitmap
  1486  // bytes with any other objects, allowing the GC program execution to
  1487  // assume an aligned start and not use atomic operations. In the current
  1488  // runtime, this means all malloc size classes larger than the cutoff must
  1489  // be multiples of four words. On 32-bit systems that's 16 bytes, and
  1490  // all size classes >= 16 bytes are 16-byte aligned, so no real constraint.
  1491  // On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed
  1492  // for size classes >= 256 bytes. On a 64-bit system, 256 bytes allocated
  1493  // is 32 pointers, the bits for which fit in 4 bytes. So maxPtrmaskBytes
  1494  // must be >= 4.
  1495  //
  1496  // We used to use 16 because the GC programs do have some constant overhead
  1497  // to get started, and processing 128 pointers seems to be enough to
  1498  // amortize that overhead well.
  1499  //
  1500  // To make sure that the runtime's chansend can call typeBitsBulkBarrier,
  1501  // we raised the limit to 2048, so that even 32-bit systems are guaranteed to
  1502  // use bitmaps for objects up to 64 kB in size.
  1503  //
  1504  // Also known to reflect/type.go.
  1505  //
  1506  const maxPtrmaskBytes = 2048
  1507  
  1508  // dgcsym emits and returns a data symbol containing GC information for type t,
  1509  // along with a boolean reporting whether the UseGCProg bit should be set in
  1510  // the type kind, and the ptrdata field to record in the reflect type information.
  1511  func dgcsym(t *Type) (sym *Sym, useGCProg bool, ptrdata int64) {
  1512  	ptrdata = typeptrdata(t)
  1513  	if ptrdata/int64(Widthptr) <= maxPtrmaskBytes*8 {
  1514  		sym = dgcptrmask(t)
  1515  		return
  1516  	}
  1517  
  1518  	useGCProg = true
  1519  	sym, ptrdata = dgcprog(t)
  1520  	return
  1521  }
  1522  
  1523  // dgcptrmask emits and returns the symbol containing a pointer mask for type t.
  1524  func dgcptrmask(t *Type) *Sym {
  1525  	ptrmask := make([]byte, (typeptrdata(t)/int64(Widthptr)+7)/8)
  1526  	fillptrmask(t, ptrmask)
  1527  	p := fmt.Sprintf("gcbits.%x", ptrmask)
  1528  
  1529  	sym := Pkglookup(p, Runtimepkg)
  1530  	if sym.Flags&SymUniq == 0 {
  1531  		sym.Flags |= SymUniq
  1532  		for i, x := range ptrmask {
  1533  			duint8(sym, i, x)
  1534  		}
  1535  		ggloblsym(sym, int32(len(ptrmask)), obj.DUPOK|obj.RODATA|obj.LOCAL)
  1536  	}
  1537  	return sym
  1538  }
  1539  
  1540  // fillptrmask fills in ptrmask with 1s corresponding to the
  1541  // word offsets in t that hold pointers.
  1542  // ptrmask is assumed to fit at least typeptrdata(t)/Widthptr bits.
  1543  func fillptrmask(t *Type, ptrmask []byte) {
  1544  	for i := range ptrmask {
  1545  		ptrmask[i] = 0
  1546  	}
  1547  	if !haspointers(t) {
  1548  		return
  1549  	}
  1550  
  1551  	vec := bvalloc(8 * int32(len(ptrmask)))
  1552  	xoffset := int64(0)
  1553  	onebitwalktype1(t, &xoffset, vec)
  1554  
  1555  	nptr := typeptrdata(t) / int64(Widthptr)
  1556  	for i := int64(0); i < nptr; i++ {
  1557  		if bvget(vec, int32(i)) == 1 {
  1558  			ptrmask[i/8] |= 1 << (uint(i) % 8)
  1559  		}
  1560  	}
  1561  }
  1562  
  1563  // dgcprog emits and returns the symbol containing a GC program for type t
  1564  // along with the size of the data described by the program (in the range [typeptrdata(t), t.Width]).
  1565  // In practice, the size is typeptrdata(t) except for non-trivial arrays.
  1566  // For non-trivial arrays, the program describes the full t.Width size.
  1567  func dgcprog(t *Type) (*Sym, int64) {
  1568  	dowidth(t)
  1569  	if t.Width == BADWIDTH {
  1570  		Fatalf("dgcprog: %v badwidth", t)
  1571  	}
  1572  	sym := typesymprefix(".gcprog", t)
  1573  	var p GCProg
  1574  	p.init(sym)
  1575  	p.emit(t, 0)
  1576  	offset := p.w.BitIndex() * int64(Widthptr)
  1577  	p.end()
  1578  	if ptrdata := typeptrdata(t); offset < ptrdata || offset > t.Width {
  1579  		Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Width)
  1580  	}
  1581  	return sym, offset
  1582  }
  1583  
  1584  type GCProg struct {
  1585  	sym    *Sym
  1586  	symoff int
  1587  	w      gcprog.Writer
  1588  }
  1589  
  1590  var Debug_gcprog int // set by -d gcprog
  1591  
  1592  func (p *GCProg) init(sym *Sym) {
  1593  	p.sym = sym
  1594  	p.symoff = 4 // first 4 bytes hold program length
  1595  	p.w.Init(p.writeByte)
  1596  	if Debug_gcprog > 0 {
  1597  		fmt.Fprintf(os.Stderr, "compile: start GCProg for %v\n", sym)
  1598  		p.w.Debug(os.Stderr)
  1599  	}
  1600  }
  1601  
  1602  func (p *GCProg) writeByte(x byte) {
  1603  	p.symoff = duint8(p.sym, p.symoff, x)
  1604  }
  1605  
  1606  func (p *GCProg) end() {
  1607  	p.w.End()
  1608  	duint32(p.sym, 0, uint32(p.symoff-4))
  1609  	ggloblsym(p.sym, int32(p.symoff), obj.DUPOK|obj.RODATA|obj.LOCAL)
  1610  	if Debug_gcprog > 0 {
  1611  		fmt.Fprintf(os.Stderr, "compile: end GCProg for %v\n", p.sym)
  1612  	}
  1613  }
  1614  
  1615  func (p *GCProg) emit(t *Type, offset int64) {
  1616  	dowidth(t)
  1617  	if !haspointers(t) {
  1618  		return
  1619  	}
  1620  	if t.Width == int64(Widthptr) {
  1621  		p.w.Ptr(offset / int64(Widthptr))
  1622  		return
  1623  	}
  1624  	switch t.Etype {
  1625  	default:
  1626  		Fatalf("GCProg.emit: unexpected type %v", t)
  1627  
  1628  	case TSTRING:
  1629  		p.w.Ptr(offset / int64(Widthptr))
  1630  
  1631  	case TINTER:
  1632  		p.w.Ptr(offset / int64(Widthptr))
  1633  		p.w.Ptr(offset/int64(Widthptr) + 1)
  1634  
  1635  	case TARRAY:
  1636  		if t.IsSlice() {
  1637  			p.w.Ptr(offset / int64(Widthptr))
  1638  			return
  1639  		}
  1640  		if t.NumElem() == 0 {
  1641  			// should have been handled by haspointers check above
  1642  			Fatalf("GCProg.emit: empty array")
  1643  		}
  1644  
  1645  		// Flatten array-of-array-of-array to just a big array by multiplying counts.
  1646  		count := t.NumElem()
  1647  		elem := t.Elem()
  1648  		for elem.IsArray() {
  1649  			count *= elem.NumElem()
  1650  			elem = elem.Elem()
  1651  		}
  1652  
  1653  		if !p.w.ShouldRepeat(elem.Width/int64(Widthptr), count) {
  1654  			// Cheaper to just emit the bits.
  1655  			for i := int64(0); i < count; i++ {
  1656  				p.emit(elem, offset+i*elem.Width)
  1657  			}
  1658  			return
  1659  		}
  1660  		p.emit(elem, offset)
  1661  		p.w.ZeroUntil((offset + elem.Width) / int64(Widthptr))
  1662  		p.w.Repeat(elem.Width/int64(Widthptr), count-1)
  1663  
  1664  	case TSTRUCT:
  1665  		for _, t1 := range t.Fields().Slice() {
  1666  			p.emit(t1.Type, offset+t1.Offset)
  1667  		}
  1668  	}
  1669  }