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