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