github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/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  func isExportedField(ft *Field) bool {
   498  	if ft.Sym != nil && ft.Embedded == 0 {
   499  		return exportname(ft.Sym.Name)
   500  	} else {
   501  		if ft.Type.Sym != nil &&
   502  			(ft.Type.Sym.Pkg == builtinpkg || !exportname(ft.Type.Sym.Name)) {
   503  			return false
   504  		} else {
   505  			return true
   506  		}
   507  	}
   508  }
   509  
   510  // dnameField dumps a reflect.name for a struct field.
   511  func dnameField(s *Sym, ot int, ft *Field) int {
   512  	var name string
   513  	if ft.Sym != nil && ft.Embedded == 0 {
   514  		name = ft.Sym.Name
   515  	}
   516  	nsym := dname(name, ft.Note, nil, isExportedField(ft))
   517  	return dsymptrLSym(Linksym(s), ot, nsym, 0)
   518  }
   519  
   520  // dnameData writes the contents of a reflect.name into s at offset ot.
   521  func dnameData(s *obj.LSym, ot int, name, tag string, pkg *Pkg, exported bool) int {
   522  	if len(name) > 1<<16-1 {
   523  		Fatalf("name too long: %s", name)
   524  	}
   525  	if len(tag) > 1<<16-1 {
   526  		Fatalf("tag too long: %s", tag)
   527  	}
   528  
   529  	// Encode name and tag. See reflect/type.go for details.
   530  	var bits byte
   531  	l := 1 + 2 + len(name)
   532  	if exported {
   533  		bits |= 1 << 0
   534  	}
   535  	if len(tag) > 0 {
   536  		l += 2 + len(tag)
   537  		bits |= 1 << 1
   538  	}
   539  	if pkg != nil {
   540  		bits |= 1 << 2
   541  	}
   542  	b := make([]byte, l)
   543  	b[0] = bits
   544  	b[1] = uint8(len(name) >> 8)
   545  	b[2] = uint8(len(name))
   546  	copy(b[3:], name)
   547  	if len(tag) > 0 {
   548  		tb := b[3+len(name):]
   549  		tb[0] = uint8(len(tag) >> 8)
   550  		tb[1] = uint8(len(tag))
   551  		copy(tb[2:], tag)
   552  	}
   553  
   554  	ot = int(s.WriteBytes(Ctxt, int64(ot), b))
   555  
   556  	if pkg != nil {
   557  		ot = dgopkgpathOffLSym(s, ot, pkg)
   558  	}
   559  
   560  	return ot
   561  }
   562  
   563  var dnameCount int
   564  
   565  // dname creates a reflect.name for a struct field or method.
   566  func dname(name, tag string, pkg *Pkg, exported bool) *obj.LSym {
   567  	// Write out data as "type.." to signal two things to the
   568  	// linker, first that when dynamically linking, the symbol
   569  	// should be moved to a relro section, and second that the
   570  	// contents should not be decoded as a type.
   571  	sname := "type..namedata."
   572  	if pkg == nil {
   573  		// In the common case, share data with other packages.
   574  		if name == "" {
   575  			if exported {
   576  				sname += "-noname-exported." + tag
   577  			} else {
   578  				sname += "-noname-unexported." + tag
   579  			}
   580  		} else {
   581  			sname += name + "." + tag
   582  		}
   583  	} else {
   584  		sname = fmt.Sprintf(`%s"".%d`, sname, dnameCount)
   585  		dnameCount++
   586  	}
   587  	s := obj.Linklookup(Ctxt, sname, 0)
   588  	if len(s.P) > 0 {
   589  		return s
   590  	}
   591  	ot := dnameData(s, 0, name, tag, pkg, exported)
   592  	ggloblLSym(s, int32(ot), obj.DUPOK|obj.RODATA)
   593  	return s
   594  }
   595  
   596  // dextratype dumps the fields of a runtime.uncommontype.
   597  // dataAdd is the offset in bytes after the header where the
   598  // backing array of the []method field is written (by dextratypeData).
   599  func dextratype(s *Sym, ot int, t *Type, dataAdd int) int {
   600  	m := methods(t)
   601  	if t.Sym == nil && len(m) == 0 {
   602  		return ot
   603  	}
   604  	noff := int(Rnd(int64(ot), int64(Widthptr)))
   605  	if noff != ot {
   606  		Fatalf("unexpected alignment in dextratype for %v", t)
   607  	}
   608  
   609  	for _, a := range m {
   610  		dtypesym(a.type_)
   611  	}
   612  
   613  	ot = dgopkgpathOffLSym(Linksym(s), ot, typePkg(t))
   614  
   615  	dataAdd += uncommonSize(t)
   616  	mcount := len(m)
   617  	if mcount != int(uint16(mcount)) {
   618  		Fatalf("too many methods on %v: %d", t, mcount)
   619  	}
   620  	if dataAdd != int(uint32(dataAdd)) {
   621  		Fatalf("methods are too far away on %v: %d", t, dataAdd)
   622  	}
   623  
   624  	ot = duint16(s, ot, uint16(mcount))
   625  	ot = duint16(s, ot, 0)
   626  	ot = duint32(s, ot, uint32(dataAdd))
   627  	ot = duint32(s, ot, 0)
   628  	return ot
   629  }
   630  
   631  func typePkg(t *Type) *Pkg {
   632  	tsym := t.Sym
   633  	if tsym == nil {
   634  		switch t.Etype {
   635  		case TARRAY, TSLICE, TPTR32, TPTR64, TCHAN:
   636  			if t.Elem() != nil {
   637  				tsym = t.Elem().Sym
   638  			}
   639  		}
   640  	}
   641  	if tsym != nil && t != Types[t.Etype] && t != errortype {
   642  		return tsym.Pkg
   643  	}
   644  	return nil
   645  }
   646  
   647  // dextratypeData dumps the backing array for the []method field of
   648  // runtime.uncommontype.
   649  func dextratypeData(s *Sym, ot int, t *Type) int {
   650  	lsym := Linksym(s)
   651  	for _, a := range methods(t) {
   652  		// ../../../../runtime/type.go:/method
   653  		exported := exportname(a.name)
   654  		var pkg *Pkg
   655  		if !exported && a.pkg != typePkg(t) {
   656  			pkg = a.pkg
   657  		}
   658  		nsym := dname(a.name, "", pkg, exported)
   659  
   660  		ot = dsymptrOffLSym(lsym, ot, nsym, 0)
   661  		ot = dmethodptrOffLSym(lsym, ot, Linksym(dtypesym(a.mtype)))
   662  		ot = dmethodptrOffLSym(lsym, ot, Linksym(a.isym))
   663  		ot = dmethodptrOffLSym(lsym, ot, Linksym(a.tsym))
   664  	}
   665  	return ot
   666  }
   667  
   668  func dmethodptrOffLSym(s *obj.LSym, ot int, x *obj.LSym) int {
   669  	duintxxLSym(s, ot, 0, 4)
   670  	r := obj.Addrel(s)
   671  	r.Off = int32(ot)
   672  	r.Siz = 4
   673  	r.Sym = x
   674  	r.Type = obj.R_METHODOFF
   675  	return ot + 4
   676  }
   677  
   678  var kinds = []int{
   679  	TINT:        obj.KindInt,
   680  	TUINT:       obj.KindUint,
   681  	TINT8:       obj.KindInt8,
   682  	TUINT8:      obj.KindUint8,
   683  	TINT16:      obj.KindInt16,
   684  	TUINT16:     obj.KindUint16,
   685  	TINT32:      obj.KindInt32,
   686  	TUINT32:     obj.KindUint32,
   687  	TINT64:      obj.KindInt64,
   688  	TUINT64:     obj.KindUint64,
   689  	TUINTPTR:    obj.KindUintptr,
   690  	TFLOAT32:    obj.KindFloat32,
   691  	TFLOAT64:    obj.KindFloat64,
   692  	TBOOL:       obj.KindBool,
   693  	TSTRING:     obj.KindString,
   694  	TPTR32:      obj.KindPtr,
   695  	TPTR64:      obj.KindPtr,
   696  	TSTRUCT:     obj.KindStruct,
   697  	TINTER:      obj.KindInterface,
   698  	TCHAN:       obj.KindChan,
   699  	TMAP:        obj.KindMap,
   700  	TARRAY:      obj.KindArray,
   701  	TSLICE:      obj.KindSlice,
   702  	TFUNC:       obj.KindFunc,
   703  	TCOMPLEX64:  obj.KindComplex64,
   704  	TCOMPLEX128: obj.KindComplex128,
   705  	TUNSAFEPTR:  obj.KindUnsafePointer,
   706  }
   707  
   708  func haspointers(t *Type) bool {
   709  	switch t.Etype {
   710  	case TINT, TUINT, TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64,
   711  		TUINT64, TUINTPTR, TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, TBOOL:
   712  		return false
   713  
   714  	case TSLICE:
   715  		return true
   716  
   717  	case TARRAY:
   718  		at := t.Extra.(*ArrayType)
   719  		if at.Haspointers != 0 {
   720  			return at.Haspointers-1 != 0
   721  		}
   722  
   723  		ret := false
   724  		if t.NumElem() != 0 { // non-empty array
   725  			ret = haspointers(t.Elem())
   726  		}
   727  
   728  		at.Haspointers = 1 + uint8(obj.Bool2int(ret))
   729  		return ret
   730  
   731  	case TSTRUCT:
   732  		st := t.StructType()
   733  		if st.Haspointers != 0 {
   734  			return st.Haspointers-1 != 0
   735  		}
   736  
   737  		ret := false
   738  		for _, t1 := range t.Fields().Slice() {
   739  			if haspointers(t1.Type) {
   740  				ret = true
   741  				break
   742  			}
   743  		}
   744  		st.Haspointers = 1 + uint8(obj.Bool2int(ret))
   745  		return ret
   746  	}
   747  
   748  	return true
   749  }
   750  
   751  // typeptrdata returns the length in bytes of the prefix of t
   752  // containing pointer data. Anything after this offset is scalar data.
   753  func typeptrdata(t *Type) int64 {
   754  	if !haspointers(t) {
   755  		return 0
   756  	}
   757  
   758  	switch t.Etype {
   759  	case TPTR32,
   760  		TPTR64,
   761  		TUNSAFEPTR,
   762  		TFUNC,
   763  		TCHAN,
   764  		TMAP:
   765  		return int64(Widthptr)
   766  
   767  	case TSTRING:
   768  		// struct { byte *str; intgo len; }
   769  		return int64(Widthptr)
   770  
   771  	case TINTER:
   772  		// struct { Itab *tab;	void *data; } or
   773  		// struct { Type *type; void *data; }
   774  		return 2 * int64(Widthptr)
   775  
   776  	case TSLICE:
   777  		// struct { byte *array; uintgo len; uintgo cap; }
   778  		return int64(Widthptr)
   779  
   780  	case TARRAY:
   781  		// haspointers already eliminated t.NumElem() == 0.
   782  		return (t.NumElem()-1)*t.Elem().Width + typeptrdata(t.Elem())
   783  
   784  	case TSTRUCT:
   785  		// Find the last field that has pointers.
   786  		var lastPtrField *Field
   787  		for _, t1 := range t.Fields().Slice() {
   788  			if haspointers(t1.Type) {
   789  				lastPtrField = t1
   790  			}
   791  		}
   792  		return lastPtrField.Offset + typeptrdata(lastPtrField.Type)
   793  
   794  	default:
   795  		Fatalf("typeptrdata: unexpected type, %v", t)
   796  		return 0
   797  	}
   798  }
   799  
   800  // tflag is documented in reflect/type.go.
   801  //
   802  // tflag values must be kept in sync with copies in:
   803  //	cmd/compile/internal/gc/reflect.go
   804  //	cmd/link/internal/ld/decodesym.go
   805  //	reflect/type.go
   806  //	runtime/type.go
   807  const (
   808  	tflagUncommon  = 1 << 0
   809  	tflagExtraStar = 1 << 1
   810  	tflagNamed     = 1 << 2
   811  )
   812  
   813  var dcommontype_algarray *Sym
   814  
   815  // dcommontype dumps the contents of a reflect.rtype (runtime._type).
   816  func dcommontype(s *Sym, ot int, t *Type) int {
   817  	if ot != 0 {
   818  		Fatalf("dcommontype %d", ot)
   819  	}
   820  
   821  	sizeofAlg := 2 * Widthptr
   822  	if dcommontype_algarray == nil {
   823  		dcommontype_algarray = Pkglookup("algarray", Runtimepkg)
   824  	}
   825  	dowidth(t)
   826  	alg := algtype(t)
   827  	var algsym *Sym
   828  	if alg == ASPECIAL || alg == AMEM {
   829  		algsym = dalgsym(t)
   830  	}
   831  
   832  	var sptr *Sym
   833  	tptr := ptrto(t)
   834  	if !t.IsPtr() && (t.Sym != nil || methods(tptr) != nil) {
   835  		sptr = dtypesym(tptr)
   836  	}
   837  
   838  	gcsym, useGCProg, ptrdata := dgcsym(t)
   839  
   840  	// ../../../../reflect/type.go:/^type.rtype
   841  	// actual type structure
   842  	//	type rtype struct {
   843  	//		size          uintptr
   844  	//		ptrdata       uintptr
   845  	//		hash          uint32
   846  	//		tflag         tflag
   847  	//		align         uint8
   848  	//		fieldAlign    uint8
   849  	//		kind          uint8
   850  	//		alg           *typeAlg
   851  	//		gcdata        *byte
   852  	//		str           nameOff
   853  	//		ptrToThis     typeOff
   854  	//	}
   855  	ot = duintptr(s, ot, uint64(t.Width))
   856  	ot = duintptr(s, ot, uint64(ptrdata))
   857  
   858  	ot = duint32(s, ot, typehash(t))
   859  
   860  	var tflag uint8
   861  	if uncommonSize(t) != 0 {
   862  		tflag |= tflagUncommon
   863  	}
   864  	if t.Sym != nil && t.Sym.Name != "" {
   865  		tflag |= tflagNamed
   866  	}
   867  
   868  	exported := false
   869  	p := t.tconv(FmtLeft | FmtUnsigned)
   870  	// If we're writing out type T,
   871  	// we are very likely to write out type *T as well.
   872  	// Use the string "*T"[1:] for "T", so that the two
   873  	// share storage. This is a cheap way to reduce the
   874  	// amount of space taken up by reflect strings.
   875  	if !strings.HasPrefix(p, "*") {
   876  		p = "*" + p
   877  		tflag |= tflagExtraStar
   878  		if t.Sym != nil {
   879  			exported = exportname(t.Sym.Name)
   880  		}
   881  	} else {
   882  		if t.Elem() != nil && t.Elem().Sym != nil {
   883  			exported = exportname(t.Elem().Sym.Name)
   884  		}
   885  	}
   886  
   887  	ot = duint8(s, ot, tflag)
   888  
   889  	// runtime (and common sense) expects alignment to be a power of two.
   890  	i := int(t.Align)
   891  
   892  	if i == 0 {
   893  		i = 1
   894  	}
   895  	if i&(i-1) != 0 {
   896  		Fatalf("invalid alignment %d for %v", t.Align, t)
   897  	}
   898  	ot = duint8(s, ot, t.Align) // align
   899  	ot = duint8(s, ot, t.Align) // fieldAlign
   900  
   901  	i = kinds[t.Etype]
   902  	if !haspointers(t) {
   903  		i |= obj.KindNoPointers
   904  	}
   905  	if isdirectiface(t) {
   906  		i |= obj.KindDirectIface
   907  	}
   908  	if useGCProg {
   909  		i |= obj.KindGCProg
   910  	}
   911  	ot = duint8(s, ot, uint8(i)) // kind
   912  	if algsym == nil {
   913  		ot = dsymptr(s, ot, dcommontype_algarray, int(alg)*sizeofAlg)
   914  	} else {
   915  		ot = dsymptr(s, ot, algsym, 0)
   916  	}
   917  	ot = dsymptr(s, ot, gcsym, 0) // gcdata
   918  
   919  	nsym := dname(p, "", nil, exported)
   920  	ot = dsymptrOffLSym(Linksym(s), ot, nsym, 0) // str
   921  	if sptr == nil {
   922  		ot = duint32(s, ot, 0)
   923  	} else {
   924  		ot = dsymptrOffLSym(Linksym(s), ot, Linksym(sptr), 0) // ptrToThis
   925  	}
   926  
   927  	return ot
   928  }
   929  
   930  func typesym(t *Type) *Sym {
   931  	name := t.tconv(FmtLeft)
   932  
   933  	// Use a separate symbol name for Noalg types for #17752.
   934  	if a, bad := algtype1(t); a == ANOEQ && bad.Noalg {
   935  		name = "noalg." + name
   936  	}
   937  
   938  	return Pkglookup(name, typepkg)
   939  }
   940  
   941  // tracksym returns the symbol for tracking use of field/method f, assumed
   942  // to be a member of struct/interface type t.
   943  func tracksym(t *Type, f *Field) *Sym {
   944  	return Pkglookup(t.tconv(FmtLeft)+"."+f.Sym.Name, trackpkg)
   945  }
   946  
   947  func typesymprefix(prefix string, t *Type) *Sym {
   948  	p := prefix + "." + t.tconv(FmtLeft)
   949  	s := Pkglookup(p, typepkg)
   950  
   951  	//print("algsym: %s -> %+S\n", p, s);
   952  
   953  	return s
   954  }
   955  
   956  func typenamesym(t *Type) *Sym {
   957  	if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
   958  		Fatalf("typename %v", t)
   959  	}
   960  	s := typesym(t)
   961  	if s.Def == nil {
   962  		n := newname(s)
   963  		n.Type = Types[TUINT8]
   964  		n.Class = PEXTERN
   965  		n.Typecheck = 1
   966  		s.Def = n
   967  
   968  		signatlist = append(signatlist, typenod(t))
   969  	}
   970  
   971  	return s.Def.Sym
   972  }
   973  
   974  func typename(t *Type) *Node {
   975  	s := typenamesym(t)
   976  	n := nod(OADDR, s.Def, nil)
   977  	n.Type = ptrto(s.Def.Type)
   978  	n.Addable = true
   979  	n.Ullman = 2
   980  	n.Typecheck = 1
   981  	return n
   982  }
   983  
   984  func itabname(t, itype *Type) *Node {
   985  	if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() || !itype.IsInterface() || itype.IsEmptyInterface() {
   986  		Fatalf("itabname(%v, %v)", t, itype)
   987  	}
   988  	s := Pkglookup(t.tconv(FmtLeft)+","+itype.tconv(FmtLeft), itabpkg)
   989  	Linksym(s).Set(obj.AttrLocal, true)
   990  	if s.Def == nil {
   991  		n := newname(s)
   992  		n.Type = Types[TUINT8]
   993  		n.Class = PEXTERN
   994  		n.Typecheck = 1
   995  		s.Def = n
   996  
   997  		itabs = append(itabs, itabEntry{t: t, itype: itype, sym: s})
   998  	}
   999  
  1000  	n := nod(OADDR, s.Def, nil)
  1001  	n.Type = ptrto(s.Def.Type)
  1002  	n.Addable = true
  1003  	n.Ullman = 2
  1004  	n.Typecheck = 1
  1005  	return n
  1006  }
  1007  
  1008  // isreflexive reports whether t has a reflexive equality operator.
  1009  // That is, if x==x for all x of type t.
  1010  func isreflexive(t *Type) bool {
  1011  	switch t.Etype {
  1012  	case TBOOL,
  1013  		TINT,
  1014  		TUINT,
  1015  		TINT8,
  1016  		TUINT8,
  1017  		TINT16,
  1018  		TUINT16,
  1019  		TINT32,
  1020  		TUINT32,
  1021  		TINT64,
  1022  		TUINT64,
  1023  		TUINTPTR,
  1024  		TPTR32,
  1025  		TPTR64,
  1026  		TUNSAFEPTR,
  1027  		TSTRING,
  1028  		TCHAN:
  1029  		return true
  1030  
  1031  	case TFLOAT32,
  1032  		TFLOAT64,
  1033  		TCOMPLEX64,
  1034  		TCOMPLEX128,
  1035  		TINTER:
  1036  		return false
  1037  
  1038  	case TARRAY:
  1039  		return isreflexive(t.Elem())
  1040  
  1041  	case TSTRUCT:
  1042  		for _, t1 := range t.Fields().Slice() {
  1043  			if !isreflexive(t1.Type) {
  1044  				return false
  1045  			}
  1046  		}
  1047  		return true
  1048  
  1049  	default:
  1050  		Fatalf("bad type for map key: %v", t)
  1051  		return false
  1052  	}
  1053  }
  1054  
  1055  // needkeyupdate reports whether map updates with t as a key
  1056  // need the key to be updated.
  1057  func needkeyupdate(t *Type) bool {
  1058  	switch t.Etype {
  1059  	case TBOOL,
  1060  		TINT,
  1061  		TUINT,
  1062  		TINT8,
  1063  		TUINT8,
  1064  		TINT16,
  1065  		TUINT16,
  1066  		TINT32,
  1067  		TUINT32,
  1068  		TINT64,
  1069  		TUINT64,
  1070  		TUINTPTR,
  1071  		TPTR32,
  1072  		TPTR64,
  1073  		TUNSAFEPTR,
  1074  		TCHAN:
  1075  		return false
  1076  
  1077  	case TFLOAT32, // floats can be +0/-0
  1078  		TFLOAT64,
  1079  		TCOMPLEX64,
  1080  		TCOMPLEX128,
  1081  		TINTER,
  1082  		TSTRING: // strings might have smaller backing stores
  1083  		return true
  1084  
  1085  	case TARRAY:
  1086  		return needkeyupdate(t.Elem())
  1087  
  1088  	case TSTRUCT:
  1089  		for _, t1 := range t.Fields().Slice() {
  1090  			if needkeyupdate(t1.Type) {
  1091  				return true
  1092  			}
  1093  		}
  1094  		return false
  1095  
  1096  	default:
  1097  		Fatalf("bad type for map key: %v", t)
  1098  		return true
  1099  	}
  1100  }
  1101  
  1102  func dtypesym(t *Type) *Sym {
  1103  	// Replace byte, rune aliases with real type.
  1104  	// They've been separate internally to make error messages
  1105  	// better, but we have to merge them in the reflect tables.
  1106  	if t == bytetype || t == runetype {
  1107  		t = Types[t.Etype]
  1108  	}
  1109  
  1110  	if t.IsUntyped() {
  1111  		Fatalf("dtypesym %v", t)
  1112  	}
  1113  
  1114  	s := typesym(t)
  1115  	if s.Flags&SymSiggen != 0 {
  1116  		return s
  1117  	}
  1118  	s.Flags |= SymSiggen
  1119  
  1120  	// special case (look for runtime below):
  1121  	// when compiling package runtime,
  1122  	// emit the type structures for int, float, etc.
  1123  	tbase := t
  1124  
  1125  	if t.IsPtr() && t.Sym == nil && t.Elem().Sym != nil {
  1126  		tbase = t.Elem()
  1127  	}
  1128  	dupok := 0
  1129  	if tbase.Sym == nil {
  1130  		dupok = obj.DUPOK
  1131  	}
  1132  
  1133  	if myimportpath == "runtime" && (tbase == Types[tbase.Etype] || tbase == bytetype || tbase == runetype || tbase == errortype) { // int, float, etc
  1134  		goto ok
  1135  	}
  1136  
  1137  	// named types from other files are defined only by those files
  1138  	if tbase.Sym != nil && !tbase.Local {
  1139  		return s
  1140  	}
  1141  	if isforw[tbase.Etype] {
  1142  		return s
  1143  	}
  1144  
  1145  ok:
  1146  	ot := 0
  1147  	switch t.Etype {
  1148  	default:
  1149  		ot = dcommontype(s, ot, t)
  1150  		ot = dextratype(s, ot, t, 0)
  1151  
  1152  	case TARRAY:
  1153  		// ../../../../runtime/type.go:/arrayType
  1154  		s1 := dtypesym(t.Elem())
  1155  		t2 := typSlice(t.Elem())
  1156  		s2 := dtypesym(t2)
  1157  		ot = dcommontype(s, ot, t)
  1158  		ot = dsymptr(s, ot, s1, 0)
  1159  		ot = dsymptr(s, ot, s2, 0)
  1160  		ot = duintptr(s, ot, uint64(t.NumElem()))
  1161  		ot = dextratype(s, ot, t, 0)
  1162  
  1163  	case TSLICE:
  1164  		// ../../../../runtime/type.go:/sliceType
  1165  		s1 := dtypesym(t.Elem())
  1166  		ot = dcommontype(s, ot, t)
  1167  		ot = dsymptr(s, ot, s1, 0)
  1168  		ot = dextratype(s, ot, t, 0)
  1169  
  1170  	case TCHAN:
  1171  		// ../../../../runtime/type.go:/chanType
  1172  		s1 := dtypesym(t.Elem())
  1173  		ot = dcommontype(s, ot, t)
  1174  		ot = dsymptr(s, ot, s1, 0)
  1175  		ot = duintptr(s, ot, uint64(t.ChanDir()))
  1176  		ot = dextratype(s, ot, t, 0)
  1177  
  1178  	case TFUNC:
  1179  		for _, t1 := range t.Recvs().Fields().Slice() {
  1180  			dtypesym(t1.Type)
  1181  		}
  1182  		isddd := false
  1183  		for _, t1 := range t.Params().Fields().Slice() {
  1184  			isddd = t1.Isddd
  1185  			dtypesym(t1.Type)
  1186  		}
  1187  		for _, t1 := range t.Results().Fields().Slice() {
  1188  			dtypesym(t1.Type)
  1189  		}
  1190  
  1191  		ot = dcommontype(s, ot, t)
  1192  		inCount := t.Recvs().NumFields() + t.Params().NumFields()
  1193  		outCount := t.Results().NumFields()
  1194  		if isddd {
  1195  			outCount |= 1 << 15
  1196  		}
  1197  		ot = duint16(s, ot, uint16(inCount))
  1198  		ot = duint16(s, ot, uint16(outCount))
  1199  		if Widthptr == 8 {
  1200  			ot += 4 // align for *rtype
  1201  		}
  1202  
  1203  		dataAdd := (inCount + t.Results().NumFields()) * Widthptr
  1204  		ot = dextratype(s, ot, t, dataAdd)
  1205  
  1206  		// Array of rtype pointers follows funcType.
  1207  		for _, t1 := range t.Recvs().Fields().Slice() {
  1208  			ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
  1209  		}
  1210  		for _, t1 := range t.Params().Fields().Slice() {
  1211  			ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
  1212  		}
  1213  		for _, t1 := range t.Results().Fields().Slice() {
  1214  			ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
  1215  		}
  1216  
  1217  	case TINTER:
  1218  		m := imethods(t)
  1219  		n := len(m)
  1220  		for _, a := range m {
  1221  			dtypesym(a.type_)
  1222  		}
  1223  
  1224  		// ../../../../runtime/type.go:/interfaceType
  1225  		ot = dcommontype(s, ot, t)
  1226  
  1227  		var tpkg *Pkg
  1228  		if t.Sym != nil && t != Types[t.Etype] && t != errortype {
  1229  			tpkg = t.Sym.Pkg
  1230  		}
  1231  		ot = dgopkgpath(s, ot, tpkg)
  1232  
  1233  		ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint+uncommonSize(t))
  1234  		ot = duintxx(s, ot, uint64(n), Widthint)
  1235  		ot = duintxx(s, ot, uint64(n), Widthint)
  1236  		dataAdd := imethodSize() * n
  1237  		ot = dextratype(s, ot, t, dataAdd)
  1238  
  1239  		lsym := Linksym(s)
  1240  		for _, a := range m {
  1241  			// ../../../../runtime/type.go:/imethod
  1242  			exported := exportname(a.name)
  1243  			var pkg *Pkg
  1244  			if !exported && a.pkg != tpkg {
  1245  				pkg = a.pkg
  1246  			}
  1247  			nsym := dname(a.name, "", pkg, exported)
  1248  
  1249  			ot = dsymptrOffLSym(lsym, ot, nsym, 0)
  1250  			ot = dsymptrOffLSym(lsym, ot, Linksym(dtypesym(a.type_)), 0)
  1251  		}
  1252  
  1253  	// ../../../../runtime/type.go:/mapType
  1254  	case TMAP:
  1255  		s1 := dtypesym(t.Key())
  1256  		s2 := dtypesym(t.Val())
  1257  		s3 := dtypesym(mapbucket(t))
  1258  		s4 := dtypesym(hmap(t))
  1259  		ot = dcommontype(s, ot, t)
  1260  		ot = dsymptr(s, ot, s1, 0)
  1261  		ot = dsymptr(s, ot, s2, 0)
  1262  		ot = dsymptr(s, ot, s3, 0)
  1263  		ot = dsymptr(s, ot, s4, 0)
  1264  		if t.Key().Width > MAXKEYSIZE {
  1265  			ot = duint8(s, ot, uint8(Widthptr))
  1266  			ot = duint8(s, ot, 1) // indirect
  1267  		} else {
  1268  			ot = duint8(s, ot, uint8(t.Key().Width))
  1269  			ot = duint8(s, ot, 0) // not indirect
  1270  		}
  1271  
  1272  		if t.Val().Width > MAXVALSIZE {
  1273  			ot = duint8(s, ot, uint8(Widthptr))
  1274  			ot = duint8(s, ot, 1) // indirect
  1275  		} else {
  1276  			ot = duint8(s, ot, uint8(t.Val().Width))
  1277  			ot = duint8(s, ot, 0) // not indirect
  1278  		}
  1279  
  1280  		ot = duint16(s, ot, uint16(mapbucket(t).Width))
  1281  		ot = duint8(s, ot, uint8(obj.Bool2int(isreflexive(t.Key()))))
  1282  		ot = duint8(s, ot, uint8(obj.Bool2int(needkeyupdate(t.Key()))))
  1283  		ot = dextratype(s, ot, t, 0)
  1284  
  1285  	case TPTR32, TPTR64:
  1286  		if t.Elem().Etype == TANY {
  1287  			// ../../../../runtime/type.go:/UnsafePointerType
  1288  			ot = dcommontype(s, ot, t)
  1289  			ot = dextratype(s, ot, t, 0)
  1290  
  1291  			break
  1292  		}
  1293  
  1294  		// ../../../../runtime/type.go:/ptrType
  1295  		s1 := dtypesym(t.Elem())
  1296  
  1297  		ot = dcommontype(s, ot, t)
  1298  		ot = dsymptr(s, ot, s1, 0)
  1299  		ot = dextratype(s, ot, t, 0)
  1300  
  1301  	// ../../../../runtime/type.go:/structType
  1302  	// for security, only the exported fields.
  1303  	case TSTRUCT:
  1304  		n := 0
  1305  
  1306  		for _, t1 := range t.Fields().Slice() {
  1307  			dtypesym(t1.Type)
  1308  			n++
  1309  		}
  1310  
  1311  		ot = dcommontype(s, ot, t)
  1312  		pkg := localpkg
  1313  		if t.Sym != nil {
  1314  			pkg = t.Sym.Pkg
  1315  		} else {
  1316  			// Unnamed type. Grab the package from the first field, if any.
  1317  			for _, f := range t.Fields().Slice() {
  1318  				if f.Embedded != 0 {
  1319  					continue
  1320  				}
  1321  				pkg = f.Sym.Pkg
  1322  				break
  1323  			}
  1324  		}
  1325  		ot = dgopkgpath(s, ot, pkg)
  1326  		ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint+uncommonSize(t))
  1327  		ot = duintxx(s, ot, uint64(n), Widthint)
  1328  		ot = duintxx(s, ot, uint64(n), Widthint)
  1329  
  1330  		dataAdd := n * structfieldSize()
  1331  		ot = dextratype(s, ot, t, dataAdd)
  1332  
  1333  		for _, f := range t.Fields().Slice() {
  1334  			// ../../../../runtime/type.go:/structField
  1335  			ot = dnameField(s, ot, f)
  1336  			ot = dsymptr(s, ot, dtypesym(f.Type), 0)
  1337  			ot = duintptr(s, ot, uint64(f.Offset))
  1338  		}
  1339  	}
  1340  
  1341  	ot = dextratypeData(s, ot, t)
  1342  	ggloblsym(s, int32(ot), int16(dupok|obj.RODATA))
  1343  
  1344  	// The linker will leave a table of all the typelinks for
  1345  	// types in the binary, so the runtime can find them.
  1346  	//
  1347  	// When buildmode=shared, all types are in typelinks so the
  1348  	// runtime can deduplicate type pointers.
  1349  	keep := Ctxt.Flag_dynlink
  1350  	if !keep && t.Sym == nil {
  1351  		// For an unnamed type, we only need the link if the type can
  1352  		// be created at run time by reflect.PtrTo and similar
  1353  		// functions. If the type exists in the program, those
  1354  		// functions must return the existing type structure rather
  1355  		// than creating a new one.
  1356  		switch t.Etype {
  1357  		case TPTR32, TPTR64, TARRAY, TCHAN, TFUNC, TMAP, TSLICE, TSTRUCT:
  1358  			keep = true
  1359  		}
  1360  	}
  1361  	s.Lsym.Set(obj.AttrMakeTypelink, keep)
  1362  
  1363  	return s
  1364  }
  1365  
  1366  func dumptypestructs() {
  1367  	// copy types from externdcl list to signatlist
  1368  	for _, n := range externdcl {
  1369  		if n.Op != OTYPE {
  1370  			continue
  1371  		}
  1372  		signatlist = append(signatlist, n)
  1373  	}
  1374  
  1375  	// Process signatlist.  This can't use range, as entries are
  1376  	// added to the list while it is being processed.
  1377  	for i := 0; i < len(signatlist); i++ {
  1378  		n := signatlist[i]
  1379  		if n.Op != OTYPE {
  1380  			continue
  1381  		}
  1382  		t := n.Type
  1383  		dtypesym(t)
  1384  		if t.Sym != nil {
  1385  			dtypesym(ptrto(t))
  1386  		}
  1387  	}
  1388  
  1389  	// process itabs
  1390  	for _, i := range itabs {
  1391  		// dump empty itab symbol into i.sym
  1392  		// type itab struct {
  1393  		//   inter  *interfacetype
  1394  		//   _type  *_type
  1395  		//   link   *itab
  1396  		//   bad    int32
  1397  		//   unused int32
  1398  		//   fun    [1]uintptr // variable sized
  1399  		// }
  1400  		o := dsymptr(i.sym, 0, dtypesym(i.itype), 0)
  1401  		o = dsymptr(i.sym, o, dtypesym(i.t), 0)
  1402  		o += Widthptr + 8                      // skip link/bad/unused fields
  1403  		o += len(imethods(i.itype)) * Widthptr // skip fun method pointers
  1404  		// at runtime the itab will contain pointers to types, other itabs and
  1405  		// method functions. None are allocated on heap, so we can use obj.NOPTR.
  1406  		ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR|obj.LOCAL))
  1407  
  1408  		ilink := Pkglookup(i.t.tconv(FmtLeft)+","+i.itype.tconv(FmtLeft), itablinkpkg)
  1409  		dsymptr(ilink, 0, i.sym, 0)
  1410  		ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA|obj.LOCAL))
  1411  	}
  1412  
  1413  	// process ptabs
  1414  	if localpkg.Name == "main" && len(ptabs) > 0 {
  1415  		ot := 0
  1416  		s := obj.Linklookup(Ctxt, "go.plugin.tabs", 0)
  1417  		for _, p := range ptabs {
  1418  			// Dump ptab symbol into go.pluginsym package.
  1419  			//
  1420  			// type ptab struct {
  1421  			//	name nameOff
  1422  			//	typ  typeOff // pointer to symbol
  1423  			// }
  1424  			nsym := dname(p.s.Name, "", nil, true)
  1425  			ot = dsymptrOffLSym(s, ot, nsym, 0)
  1426  			ot = dsymptrOffLSym(s, ot, Linksym(dtypesym(p.t)), 0)
  1427  		}
  1428  		ggloblLSym(s, int32(ot), int16(obj.RODATA))
  1429  
  1430  		ot = 0
  1431  		s = obj.Linklookup(Ctxt, "go.plugin.exports", 0)
  1432  		for _, p := range ptabs {
  1433  			ot = dsymptrLSym(s, ot, Linksym(p.s), 0)
  1434  		}
  1435  		ggloblLSym(s, int32(ot), int16(obj.RODATA))
  1436  	}
  1437  
  1438  	// generate import strings for imported packages
  1439  	if forceObjFileStability {
  1440  		// Sorting the packages is not necessary but to compare binaries created
  1441  		// using textual and binary format we sort by path to reduce differences.
  1442  		sort.Sort(pkgByPath(pkgs))
  1443  	}
  1444  	for _, p := range pkgs {
  1445  		if p.Direct {
  1446  			dimportpath(p)
  1447  		}
  1448  	}
  1449  
  1450  	// do basic types if compiling package runtime.
  1451  	// they have to be in at least one package,
  1452  	// and runtime is always loaded implicitly,
  1453  	// so this is as good as any.
  1454  	// another possible choice would be package main,
  1455  	// but using runtime means fewer copies in .6 files.
  1456  	if myimportpath == "runtime" {
  1457  		for i := EType(1); i <= TBOOL; i++ {
  1458  			dtypesym(ptrto(Types[i]))
  1459  		}
  1460  		dtypesym(ptrto(Types[TSTRING]))
  1461  		dtypesym(ptrto(Types[TUNSAFEPTR]))
  1462  
  1463  		// emit type structs for error and func(error) string.
  1464  		// The latter is the type of an auto-generated wrapper.
  1465  		dtypesym(ptrto(errortype))
  1466  
  1467  		dtypesym(functype(nil, []*Node{nod(ODCLFIELD, nil, typenod(errortype))}, []*Node{nod(ODCLFIELD, nil, typenod(Types[TSTRING]))}))
  1468  
  1469  		// add paths for runtime and main, which 6l imports implicitly.
  1470  		dimportpath(Runtimepkg)
  1471  
  1472  		if flag_race {
  1473  			dimportpath(racepkg)
  1474  		}
  1475  		if flag_msan {
  1476  			dimportpath(msanpkg)
  1477  		}
  1478  		dimportpath(mkpkg("main"))
  1479  	}
  1480  }
  1481  
  1482  type pkgByPath []*Pkg
  1483  
  1484  func (a pkgByPath) Len() int           { return len(a) }
  1485  func (a pkgByPath) Less(i, j int) bool { return a[i].Path < a[j].Path }
  1486  func (a pkgByPath) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
  1487  
  1488  func dalgsym(t *Type) *Sym {
  1489  	var s *Sym
  1490  	var hashfunc *Sym
  1491  	var eqfunc *Sym
  1492  
  1493  	// dalgsym is only called for a type that needs an algorithm table,
  1494  	// which implies that the type is comparable (or else it would use ANOEQ).
  1495  
  1496  	if algtype(t) == AMEM {
  1497  		// we use one algorithm table for all AMEM types of a given size
  1498  		p := fmt.Sprintf(".alg%d", t.Width)
  1499  
  1500  		s = Pkglookup(p, typepkg)
  1501  
  1502  		if s.Flags&SymAlgGen != 0 {
  1503  			return s
  1504  		}
  1505  		s.Flags |= SymAlgGen
  1506  
  1507  		// make hash closure
  1508  		p = fmt.Sprintf(".hashfunc%d", t.Width)
  1509  
  1510  		hashfunc = Pkglookup(p, typepkg)
  1511  
  1512  		ot := 0
  1513  		ot = dsymptr(hashfunc, ot, Pkglookup("memhash_varlen", Runtimepkg), 0)
  1514  		ot = duintxx(hashfunc, ot, uint64(t.Width), Widthptr) // size encoded in closure
  1515  		ggloblsym(hashfunc, int32(ot), obj.DUPOK|obj.RODATA)
  1516  
  1517  		// make equality closure
  1518  		p = fmt.Sprintf(".eqfunc%d", t.Width)
  1519  
  1520  		eqfunc = Pkglookup(p, typepkg)
  1521  
  1522  		ot = 0
  1523  		ot = dsymptr(eqfunc, ot, Pkglookup("memequal_varlen", Runtimepkg), 0)
  1524  		ot = duintxx(eqfunc, ot, uint64(t.Width), Widthptr)
  1525  		ggloblsym(eqfunc, int32(ot), obj.DUPOK|obj.RODATA)
  1526  	} else {
  1527  		// generate an alg table specific to this type
  1528  		s = typesymprefix(".alg", t)
  1529  
  1530  		hash := typesymprefix(".hash", t)
  1531  		eq := typesymprefix(".eq", t)
  1532  		hashfunc = typesymprefix(".hashfunc", t)
  1533  		eqfunc = typesymprefix(".eqfunc", t)
  1534  
  1535  		genhash(hash, t)
  1536  		geneq(eq, t)
  1537  
  1538  		// make Go funcs (closures) for calling hash and equal from Go
  1539  		dsymptr(hashfunc, 0, hash, 0)
  1540  
  1541  		ggloblsym(hashfunc, int32(Widthptr), obj.DUPOK|obj.RODATA)
  1542  		dsymptr(eqfunc, 0, eq, 0)
  1543  		ggloblsym(eqfunc, int32(Widthptr), obj.DUPOK|obj.RODATA)
  1544  	}
  1545  
  1546  	// ../../../../runtime/alg.go:/typeAlg
  1547  	ot := 0
  1548  
  1549  	ot = dsymptr(s, ot, hashfunc, 0)
  1550  	ot = dsymptr(s, ot, eqfunc, 0)
  1551  	ggloblsym(s, int32(ot), obj.DUPOK|obj.RODATA)
  1552  	return s
  1553  }
  1554  
  1555  // maxPtrmaskBytes is the maximum length of a GC ptrmask bitmap,
  1556  // which holds 1-bit entries describing where pointers are in a given type.
  1557  // 16 bytes is enough to describe 128 pointer-sized words, 512 or 1024 bytes
  1558  // depending on the system. Above this length, the GC information is
  1559  // recorded as a GC program, which can express repetition compactly.
  1560  // In either form, the information is used by the runtime to initialize the
  1561  // heap bitmap, and for large types (like 128 or more words), they are
  1562  // roughly the same speed. GC programs are never much larger and often
  1563  // more compact. (If large arrays are involved, they can be arbitrarily more
  1564  // compact.)
  1565  //
  1566  // The cutoff must be large enough that any allocation large enough to
  1567  // use a GC program is large enough that it does not share heap bitmap
  1568  // bytes with any other objects, allowing the GC program execution to
  1569  // assume an aligned start and not use atomic operations. In the current
  1570  // runtime, this means all malloc size classes larger than the cutoff must
  1571  // be multiples of four words. On 32-bit systems that's 16 bytes, and
  1572  // all size classes >= 16 bytes are 16-byte aligned, so no real constraint.
  1573  // On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed
  1574  // for size classes >= 256 bytes. On a 64-bit system, 256 bytes allocated
  1575  // is 32 pointers, the bits for which fit in 4 bytes. So maxPtrmaskBytes
  1576  // must be >= 4.
  1577  //
  1578  // We used to use 16 because the GC programs do have some constant overhead
  1579  // to get started, and processing 128 pointers seems to be enough to
  1580  // amortize that overhead well.
  1581  //
  1582  // To make sure that the runtime's chansend can call typeBitsBulkBarrier,
  1583  // we raised the limit to 2048, so that even 32-bit systems are guaranteed to
  1584  // use bitmaps for objects up to 64 kB in size.
  1585  //
  1586  // Also known to reflect/type.go.
  1587  //
  1588  const maxPtrmaskBytes = 2048
  1589  
  1590  // dgcsym emits and returns a data symbol containing GC information for type t,
  1591  // along with a boolean reporting whether the UseGCProg bit should be set in
  1592  // the type kind, and the ptrdata field to record in the reflect type information.
  1593  func dgcsym(t *Type) (sym *Sym, useGCProg bool, ptrdata int64) {
  1594  	ptrdata = typeptrdata(t)
  1595  	if ptrdata/int64(Widthptr) <= maxPtrmaskBytes*8 {
  1596  		sym = dgcptrmask(t)
  1597  		return
  1598  	}
  1599  
  1600  	useGCProg = true
  1601  	sym, ptrdata = dgcprog(t)
  1602  	return
  1603  }
  1604  
  1605  // dgcptrmask emits and returns the symbol containing a pointer mask for type t.
  1606  func dgcptrmask(t *Type) *Sym {
  1607  	ptrmask := make([]byte, (typeptrdata(t)/int64(Widthptr)+7)/8)
  1608  	fillptrmask(t, ptrmask)
  1609  	p := fmt.Sprintf("gcbits.%x", ptrmask)
  1610  
  1611  	sym := Pkglookup(p, Runtimepkg)
  1612  	if sym.Flags&SymUniq == 0 {
  1613  		sym.Flags |= SymUniq
  1614  		for i, x := range ptrmask {
  1615  			duint8(sym, i, x)
  1616  		}
  1617  		ggloblsym(sym, int32(len(ptrmask)), obj.DUPOK|obj.RODATA|obj.LOCAL)
  1618  	}
  1619  	return sym
  1620  }
  1621  
  1622  // fillptrmask fills in ptrmask with 1s corresponding to the
  1623  // word offsets in t that hold pointers.
  1624  // ptrmask is assumed to fit at least typeptrdata(t)/Widthptr bits.
  1625  func fillptrmask(t *Type, ptrmask []byte) {
  1626  	for i := range ptrmask {
  1627  		ptrmask[i] = 0
  1628  	}
  1629  	if !haspointers(t) {
  1630  		return
  1631  	}
  1632  
  1633  	vec := bvalloc(8 * int32(len(ptrmask)))
  1634  	xoffset := int64(0)
  1635  	onebitwalktype1(t, &xoffset, vec)
  1636  
  1637  	nptr := typeptrdata(t) / int64(Widthptr)
  1638  	for i := int64(0); i < nptr; i++ {
  1639  		if vec.Get(int32(i)) {
  1640  			ptrmask[i/8] |= 1 << (uint(i) % 8)
  1641  		}
  1642  	}
  1643  }
  1644  
  1645  // dgcprog emits and returns the symbol containing a GC program for type t
  1646  // along with the size of the data described by the program (in the range [typeptrdata(t), t.Width]).
  1647  // In practice, the size is typeptrdata(t) except for non-trivial arrays.
  1648  // For non-trivial arrays, the program describes the full t.Width size.
  1649  func dgcprog(t *Type) (*Sym, int64) {
  1650  	dowidth(t)
  1651  	if t.Width == BADWIDTH {
  1652  		Fatalf("dgcprog: %v badwidth", t)
  1653  	}
  1654  	sym := typesymprefix(".gcprog", t)
  1655  	var p GCProg
  1656  	p.init(sym)
  1657  	p.emit(t, 0)
  1658  	offset := p.w.BitIndex() * int64(Widthptr)
  1659  	p.end()
  1660  	if ptrdata := typeptrdata(t); offset < ptrdata || offset > t.Width {
  1661  		Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Width)
  1662  	}
  1663  	return sym, offset
  1664  }
  1665  
  1666  type GCProg struct {
  1667  	sym    *Sym
  1668  	symoff int
  1669  	w      gcprog.Writer
  1670  }
  1671  
  1672  var Debug_gcprog int // set by -d gcprog
  1673  
  1674  func (p *GCProg) init(sym *Sym) {
  1675  	p.sym = sym
  1676  	p.symoff = 4 // first 4 bytes hold program length
  1677  	p.w.Init(p.writeByte)
  1678  	if Debug_gcprog > 0 {
  1679  		fmt.Fprintf(os.Stderr, "compile: start GCProg for %v\n", sym)
  1680  		p.w.Debug(os.Stderr)
  1681  	}
  1682  }
  1683  
  1684  func (p *GCProg) writeByte(x byte) {
  1685  	p.symoff = duint8(p.sym, p.symoff, x)
  1686  }
  1687  
  1688  func (p *GCProg) end() {
  1689  	p.w.End()
  1690  	duint32(p.sym, 0, uint32(p.symoff-4))
  1691  	ggloblsym(p.sym, int32(p.symoff), obj.DUPOK|obj.RODATA|obj.LOCAL)
  1692  	if Debug_gcprog > 0 {
  1693  		fmt.Fprintf(os.Stderr, "compile: end GCProg for %v\n", p.sym)
  1694  	}
  1695  }
  1696  
  1697  func (p *GCProg) emit(t *Type, offset int64) {
  1698  	dowidth(t)
  1699  	if !haspointers(t) {
  1700  		return
  1701  	}
  1702  	if t.Width == int64(Widthptr) {
  1703  		p.w.Ptr(offset / int64(Widthptr))
  1704  		return
  1705  	}
  1706  	switch t.Etype {
  1707  	default:
  1708  		Fatalf("GCProg.emit: unexpected type %v", t)
  1709  
  1710  	case TSTRING:
  1711  		p.w.Ptr(offset / int64(Widthptr))
  1712  
  1713  	case TINTER:
  1714  		p.w.Ptr(offset / int64(Widthptr))
  1715  		p.w.Ptr(offset/int64(Widthptr) + 1)
  1716  
  1717  	case TSLICE:
  1718  		p.w.Ptr(offset / int64(Widthptr))
  1719  
  1720  	case TARRAY:
  1721  		if t.NumElem() == 0 {
  1722  			// should have been handled by haspointers check above
  1723  			Fatalf("GCProg.emit: empty array")
  1724  		}
  1725  
  1726  		// Flatten array-of-array-of-array to just a big array by multiplying counts.
  1727  		count := t.NumElem()
  1728  		elem := t.Elem()
  1729  		for elem.IsArray() {
  1730  			count *= elem.NumElem()
  1731  			elem = elem.Elem()
  1732  		}
  1733  
  1734  		if !p.w.ShouldRepeat(elem.Width/int64(Widthptr), count) {
  1735  			// Cheaper to just emit the bits.
  1736  			for i := int64(0); i < count; i++ {
  1737  				p.emit(elem, offset+i*elem.Width)
  1738  			}
  1739  			return
  1740  		}
  1741  		p.emit(elem, offset)
  1742  		p.w.ZeroUntil((offset + elem.Width) / int64(Widthptr))
  1743  		p.w.Repeat(elem.Width/int64(Widthptr), count-1)
  1744  
  1745  	case TSTRUCT:
  1746  		for _, t1 := range t.Fields().Slice() {
  1747  			p.emit(t1.Type, offset+t1.Offset)
  1748  		}
  1749  	}
  1750  }
  1751  
  1752  // zeroaddr returns the address of a symbol with at least
  1753  // size bytes of zeros.
  1754  func zeroaddr(size int64) *Node {
  1755  	if size >= 1<<31 {
  1756  		Fatalf("map value too big %d", size)
  1757  	}
  1758  	if zerosize < size {
  1759  		zerosize = size
  1760  	}
  1761  	s := Pkglookup("zero", mappkg)
  1762  	if s.Def == nil {
  1763  		x := newname(s)
  1764  		x.Type = Types[TUINT8]
  1765  		x.Class = PEXTERN
  1766  		x.Typecheck = 1
  1767  		s.Def = x
  1768  	}
  1769  	z := nod(OADDR, s.Def, nil)
  1770  	z.Type = ptrto(Types[TUINT8])
  1771  	z.Addable = true
  1772  	z.Typecheck = 1
  1773  	return z
  1774  }