github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/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  		//   hash   uint32
  1415  		//   bad    bool
  1416  		//   inhash bool
  1417  		//   unused [2]byte
  1418  		//   fun    [1]uintptr // variable sized
  1419  		// }
  1420  		o := dsymptr(i.sym, 0, dtypesym(i.itype), 0)
  1421  		o = dsymptr(i.sym, o, dtypesym(i.t), 0)
  1422  		o += Widthptr                          // skip link field
  1423  		o = duint32(i.sym, o, typehash(i.t))   // copy of type hash
  1424  		o += 4                                 // skip bad/inhash/unused fields
  1425  		o += len(imethods(i.itype)) * Widthptr // skip fun method pointers
  1426  		// at runtime the itab will contain pointers to types, other itabs and
  1427  		// method functions. None are allocated on heap, so we can use obj.NOPTR.
  1428  		ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR))
  1429  
  1430  		ilink := Pkglookup(i.t.tconv(FmtLeft)+","+i.itype.tconv(FmtLeft), itablinkpkg)
  1431  		dsymptr(ilink, 0, i.sym, 0)
  1432  		ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA))
  1433  	}
  1434  
  1435  	// process ptabs
  1436  	if localpkg.Name == "main" && len(ptabs) > 0 {
  1437  		ot := 0
  1438  		s := obj.Linklookup(Ctxt, "go.plugin.tabs", 0)
  1439  		for _, p := range ptabs {
  1440  			// Dump ptab symbol into go.pluginsym package.
  1441  			//
  1442  			// type ptab struct {
  1443  			//	name nameOff
  1444  			//	typ  typeOff // pointer to symbol
  1445  			// }
  1446  			nsym := dname(p.s.Name, "", nil, true)
  1447  			ot = dsymptrOffLSym(s, ot, nsym, 0)
  1448  			ot = dsymptrOffLSym(s, ot, Linksym(dtypesym(p.t)), 0)
  1449  		}
  1450  		ggloblLSym(s, int32(ot), int16(obj.RODATA))
  1451  
  1452  		ot = 0
  1453  		s = obj.Linklookup(Ctxt, "go.plugin.exports", 0)
  1454  		for _, p := range ptabs {
  1455  			ot = dsymptrLSym(s, ot, Linksym(p.s), 0)
  1456  		}
  1457  		ggloblLSym(s, int32(ot), int16(obj.RODATA))
  1458  	}
  1459  
  1460  	// generate import strings for imported packages
  1461  	if forceObjFileStability {
  1462  		// Sorting the packages is not necessary but to compare binaries created
  1463  		// using textual and binary format we sort by path to reduce differences.
  1464  		sort.Sort(pkgByPath(pkgs))
  1465  	}
  1466  	for _, p := range pkgs {
  1467  		if p.Direct {
  1468  			dimportpath(p)
  1469  		}
  1470  	}
  1471  
  1472  	// do basic types if compiling package runtime.
  1473  	// they have to be in at least one package,
  1474  	// and runtime is always loaded implicitly,
  1475  	// so this is as good as any.
  1476  	// another possible choice would be package main,
  1477  	// but using runtime means fewer copies in .6 files.
  1478  	if myimportpath == "runtime" {
  1479  		for i := EType(1); i <= TBOOL; i++ {
  1480  			dtypesym(ptrto(Types[i]))
  1481  		}
  1482  		dtypesym(ptrto(Types[TSTRING]))
  1483  		dtypesym(ptrto(Types[TUNSAFEPTR]))
  1484  
  1485  		// emit type structs for error and func(error) string.
  1486  		// The latter is the type of an auto-generated wrapper.
  1487  		dtypesym(ptrto(errortype))
  1488  
  1489  		dtypesym(functype(nil, []*Node{nod(ODCLFIELD, nil, typenod(errortype))}, []*Node{nod(ODCLFIELD, nil, typenod(Types[TSTRING]))}))
  1490  
  1491  		// add paths for runtime and main, which 6l imports implicitly.
  1492  		dimportpath(Runtimepkg)
  1493  
  1494  		if flag_race {
  1495  			dimportpath(racepkg)
  1496  		}
  1497  		if flag_msan {
  1498  			dimportpath(msanpkg)
  1499  		}
  1500  		dimportpath(mkpkg("main"))
  1501  	}
  1502  }
  1503  
  1504  type pkgByPath []*Pkg
  1505  
  1506  func (a pkgByPath) Len() int           { return len(a) }
  1507  func (a pkgByPath) Less(i, j int) bool { return a[i].Path < a[j].Path }
  1508  func (a pkgByPath) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
  1509  
  1510  func dalgsym(t *Type) *Sym {
  1511  	var s *Sym
  1512  	var hashfunc *Sym
  1513  	var eqfunc *Sym
  1514  
  1515  	// dalgsym is only called for a type that needs an algorithm table,
  1516  	// which implies that the type is comparable (or else it would use ANOEQ).
  1517  
  1518  	if algtype(t) == AMEM {
  1519  		// we use one algorithm table for all AMEM types of a given size
  1520  		p := fmt.Sprintf(".alg%d", t.Width)
  1521  
  1522  		s = Pkglookup(p, typepkg)
  1523  
  1524  		if s.Flags&SymAlgGen != 0 {
  1525  			return s
  1526  		}
  1527  		s.Flags |= SymAlgGen
  1528  
  1529  		// make hash closure
  1530  		p = fmt.Sprintf(".hashfunc%d", t.Width)
  1531  
  1532  		hashfunc = Pkglookup(p, typepkg)
  1533  
  1534  		ot := 0
  1535  		ot = dsymptr(hashfunc, ot, Pkglookup("memhash_varlen", Runtimepkg), 0)
  1536  		ot = duintxx(hashfunc, ot, uint64(t.Width), Widthptr) // size encoded in closure
  1537  		ggloblsym(hashfunc, int32(ot), obj.DUPOK|obj.RODATA)
  1538  
  1539  		// make equality closure
  1540  		p = fmt.Sprintf(".eqfunc%d", t.Width)
  1541  
  1542  		eqfunc = Pkglookup(p, typepkg)
  1543  
  1544  		ot = 0
  1545  		ot = dsymptr(eqfunc, ot, Pkglookup("memequal_varlen", Runtimepkg), 0)
  1546  		ot = duintxx(eqfunc, ot, uint64(t.Width), Widthptr)
  1547  		ggloblsym(eqfunc, int32(ot), obj.DUPOK|obj.RODATA)
  1548  	} else {
  1549  		// generate an alg table specific to this type
  1550  		s = typesymprefix(".alg", t)
  1551  
  1552  		hash := typesymprefix(".hash", t)
  1553  		eq := typesymprefix(".eq", t)
  1554  		hashfunc = typesymprefix(".hashfunc", t)
  1555  		eqfunc = typesymprefix(".eqfunc", t)
  1556  
  1557  		genhash(hash, t)
  1558  		geneq(eq, t)
  1559  
  1560  		// make Go funcs (closures) for calling hash and equal from Go
  1561  		dsymptr(hashfunc, 0, hash, 0)
  1562  
  1563  		ggloblsym(hashfunc, int32(Widthptr), obj.DUPOK|obj.RODATA)
  1564  		dsymptr(eqfunc, 0, eq, 0)
  1565  		ggloblsym(eqfunc, int32(Widthptr), obj.DUPOK|obj.RODATA)
  1566  	}
  1567  
  1568  	// ../../../../runtime/alg.go:/typeAlg
  1569  	ot := 0
  1570  
  1571  	ot = dsymptr(s, ot, hashfunc, 0)
  1572  	ot = dsymptr(s, ot, eqfunc, 0)
  1573  	ggloblsym(s, int32(ot), obj.DUPOK|obj.RODATA)
  1574  	return s
  1575  }
  1576  
  1577  // maxPtrmaskBytes is the maximum length of a GC ptrmask bitmap,
  1578  // which holds 1-bit entries describing where pointers are in a given type.
  1579  // Above this length, the GC information is recorded as a GC program,
  1580  // which can express repetition compactly. In either form, the
  1581  // information is used by the runtime to initialize the heap bitmap,
  1582  // and for large types (like 128 or more words), they are roughly the
  1583  // same speed. GC programs are never much larger and often more
  1584  // compact. (If large arrays are involved, they can be arbitrarily
  1585  // more compact.)
  1586  //
  1587  // The cutoff must be large enough that any allocation large enough to
  1588  // use a GC program is large enough that it does not share heap bitmap
  1589  // bytes with any other objects, allowing the GC program execution to
  1590  // assume an aligned start and not use atomic operations. In the current
  1591  // runtime, this means all malloc size classes larger than the cutoff must
  1592  // be multiples of four words. On 32-bit systems that's 16 bytes, and
  1593  // all size classes >= 16 bytes are 16-byte aligned, so no real constraint.
  1594  // On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed
  1595  // for size classes >= 256 bytes. On a 64-bit system, 256 bytes allocated
  1596  // is 32 pointers, the bits for which fit in 4 bytes. So maxPtrmaskBytes
  1597  // must be >= 4.
  1598  //
  1599  // We used to use 16 because the GC programs do have some constant overhead
  1600  // to get started, and processing 128 pointers seems to be enough to
  1601  // amortize that overhead well.
  1602  //
  1603  // To make sure that the runtime's chansend can call typeBitsBulkBarrier,
  1604  // we raised the limit to 2048, so that even 32-bit systems are guaranteed to
  1605  // use bitmaps for objects up to 64 kB in size.
  1606  //
  1607  // Also known to reflect/type.go.
  1608  //
  1609  const maxPtrmaskBytes = 2048
  1610  
  1611  // dgcsym emits and returns a data symbol containing GC information for type t,
  1612  // along with a boolean reporting whether the UseGCProg bit should be set in
  1613  // the type kind, and the ptrdata field to record in the reflect type information.
  1614  func dgcsym(t *Type) (sym *Sym, useGCProg bool, ptrdata int64) {
  1615  	ptrdata = typeptrdata(t)
  1616  	if ptrdata/int64(Widthptr) <= maxPtrmaskBytes*8 {
  1617  		sym = dgcptrmask(t)
  1618  		return
  1619  	}
  1620  
  1621  	useGCProg = true
  1622  	sym, ptrdata = dgcprog(t)
  1623  	return
  1624  }
  1625  
  1626  // dgcptrmask emits and returns the symbol containing a pointer mask for type t.
  1627  func dgcptrmask(t *Type) *Sym {
  1628  	ptrmask := make([]byte, (typeptrdata(t)/int64(Widthptr)+7)/8)
  1629  	fillptrmask(t, ptrmask)
  1630  	p := fmt.Sprintf("gcbits.%x", ptrmask)
  1631  
  1632  	sym := Pkglookup(p, Runtimepkg)
  1633  	if sym.Flags&SymUniq == 0 {
  1634  		sym.Flags |= SymUniq
  1635  		for i, x := range ptrmask {
  1636  			duint8(sym, i, x)
  1637  		}
  1638  		ggloblsym(sym, int32(len(ptrmask)), obj.DUPOK|obj.RODATA|obj.LOCAL)
  1639  	}
  1640  	return sym
  1641  }
  1642  
  1643  // fillptrmask fills in ptrmask with 1s corresponding to the
  1644  // word offsets in t that hold pointers.
  1645  // ptrmask is assumed to fit at least typeptrdata(t)/Widthptr bits.
  1646  func fillptrmask(t *Type, ptrmask []byte) {
  1647  	for i := range ptrmask {
  1648  		ptrmask[i] = 0
  1649  	}
  1650  	if !haspointers(t) {
  1651  		return
  1652  	}
  1653  
  1654  	vec := bvalloc(8 * int32(len(ptrmask)))
  1655  	xoffset := int64(0)
  1656  	onebitwalktype1(t, &xoffset, vec)
  1657  
  1658  	nptr := typeptrdata(t) / int64(Widthptr)
  1659  	for i := int64(0); i < nptr; i++ {
  1660  		if vec.Get(int32(i)) {
  1661  			ptrmask[i/8] |= 1 << (uint(i) % 8)
  1662  		}
  1663  	}
  1664  }
  1665  
  1666  // dgcprog emits and returns the symbol containing a GC program for type t
  1667  // along with the size of the data described by the program (in the range [typeptrdata(t), t.Width]).
  1668  // In practice, the size is typeptrdata(t) except for non-trivial arrays.
  1669  // For non-trivial arrays, the program describes the full t.Width size.
  1670  func dgcprog(t *Type) (*Sym, int64) {
  1671  	dowidth(t)
  1672  	if t.Width == BADWIDTH {
  1673  		Fatalf("dgcprog: %v badwidth", t)
  1674  	}
  1675  	sym := typesymprefix(".gcprog", t)
  1676  	var p GCProg
  1677  	p.init(sym)
  1678  	p.emit(t, 0)
  1679  	offset := p.w.BitIndex() * int64(Widthptr)
  1680  	p.end()
  1681  	if ptrdata := typeptrdata(t); offset < ptrdata || offset > t.Width {
  1682  		Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Width)
  1683  	}
  1684  	return sym, offset
  1685  }
  1686  
  1687  type GCProg struct {
  1688  	sym    *Sym
  1689  	symoff int
  1690  	w      gcprog.Writer
  1691  }
  1692  
  1693  var Debug_gcprog int // set by -d gcprog
  1694  
  1695  func (p *GCProg) init(sym *Sym) {
  1696  	p.sym = sym
  1697  	p.symoff = 4 // first 4 bytes hold program length
  1698  	p.w.Init(p.writeByte)
  1699  	if Debug_gcprog > 0 {
  1700  		fmt.Fprintf(os.Stderr, "compile: start GCProg for %v\n", sym)
  1701  		p.w.Debug(os.Stderr)
  1702  	}
  1703  }
  1704  
  1705  func (p *GCProg) writeByte(x byte) {
  1706  	p.symoff = duint8(p.sym, p.symoff, x)
  1707  }
  1708  
  1709  func (p *GCProg) end() {
  1710  	p.w.End()
  1711  	duint32(p.sym, 0, uint32(p.symoff-4))
  1712  	ggloblsym(p.sym, int32(p.symoff), obj.DUPOK|obj.RODATA|obj.LOCAL)
  1713  	if Debug_gcprog > 0 {
  1714  		fmt.Fprintf(os.Stderr, "compile: end GCProg for %v\n", p.sym)
  1715  	}
  1716  }
  1717  
  1718  func (p *GCProg) emit(t *Type, offset int64) {
  1719  	dowidth(t)
  1720  	if !haspointers(t) {
  1721  		return
  1722  	}
  1723  	if t.Width == int64(Widthptr) {
  1724  		p.w.Ptr(offset / int64(Widthptr))
  1725  		return
  1726  	}
  1727  	switch t.Etype {
  1728  	default:
  1729  		Fatalf("GCProg.emit: unexpected type %v", t)
  1730  
  1731  	case TSTRING:
  1732  		p.w.Ptr(offset / int64(Widthptr))
  1733  
  1734  	case TINTER:
  1735  		p.w.Ptr(offset / int64(Widthptr))
  1736  		p.w.Ptr(offset/int64(Widthptr) + 1)
  1737  
  1738  	case TSLICE:
  1739  		p.w.Ptr(offset / int64(Widthptr))
  1740  
  1741  	case TARRAY:
  1742  		if t.NumElem() == 0 {
  1743  			// should have been handled by haspointers check above
  1744  			Fatalf("GCProg.emit: empty array")
  1745  		}
  1746  
  1747  		// Flatten array-of-array-of-array to just a big array by multiplying counts.
  1748  		count := t.NumElem()
  1749  		elem := t.Elem()
  1750  		for elem.IsArray() {
  1751  			count *= elem.NumElem()
  1752  			elem = elem.Elem()
  1753  		}
  1754  
  1755  		if !p.w.ShouldRepeat(elem.Width/int64(Widthptr), count) {
  1756  			// Cheaper to just emit the bits.
  1757  			for i := int64(0); i < count; i++ {
  1758  				p.emit(elem, offset+i*elem.Width)
  1759  			}
  1760  			return
  1761  		}
  1762  		p.emit(elem, offset)
  1763  		p.w.ZeroUntil((offset + elem.Width) / int64(Widthptr))
  1764  		p.w.Repeat(elem.Width/int64(Widthptr), count-1)
  1765  
  1766  	case TSTRUCT:
  1767  		for _, t1 := range t.Fields().Slice() {
  1768  			p.emit(t1.Type, offset+t1.Offset)
  1769  		}
  1770  	}
  1771  }
  1772  
  1773  // zeroaddr returns the address of a symbol with at least
  1774  // size bytes of zeros.
  1775  func zeroaddr(size int64) *Node {
  1776  	if size >= 1<<31 {
  1777  		Fatalf("map value too big %d", size)
  1778  	}
  1779  	if zerosize < size {
  1780  		zerosize = size
  1781  	}
  1782  	s := Pkglookup("zero", mappkg)
  1783  	if s.Def == nil {
  1784  		x := newname(s)
  1785  		x.Type = Types[TUINT8]
  1786  		x.Class = PEXTERN
  1787  		x.Typecheck = 1
  1788  		s.Def = x
  1789  	}
  1790  	z := nod(OADDR, s.Def, nil)
  1791  	z.Type = ptrto(Types[TUINT8])
  1792  	z.Addable = true
  1793  	z.Typecheck = 1
  1794  	return z
  1795  }