Source file src/cmd/compile/internal/reflectdata/reflect.go

     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 reflectdata
     6  
     7  import (
     8  	"encoding/binary"
     9  	"fmt"
    10  	"internal/abi"
    11  	"os"
    12  	"sort"
    13  	"strings"
    14  	"sync"
    15  
    16  	"cmd/compile/internal/base"
    17  	"cmd/compile/internal/bitvec"
    18  	"cmd/compile/internal/compare"
    19  	"cmd/compile/internal/ir"
    20  	"cmd/compile/internal/objw"
    21  	"cmd/compile/internal/rttype"
    22  	"cmd/compile/internal/staticdata"
    23  	"cmd/compile/internal/typebits"
    24  	"cmd/compile/internal/typecheck"
    25  	"cmd/compile/internal/types"
    26  	"cmd/internal/gcprog"
    27  	"cmd/internal/obj"
    28  	"cmd/internal/objabi"
    29  	"cmd/internal/src"
    30  )
    31  
    32  type ptabEntry struct {
    33  	s *types.Sym
    34  	t *types.Type
    35  }
    36  
    37  // runtime interface and reflection data structures
    38  var (
    39  	// protects signatset and signatslice
    40  	signatmu sync.Mutex
    41  	// Tracking which types need runtime type descriptor
    42  	signatset = make(map[*types.Type]struct{})
    43  	// Queue of types wait to be generated runtime type descriptor
    44  	signatslice []typeAndStr
    45  
    46  	gcsymmu  sync.Mutex // protects gcsymset and gcsymslice
    47  	gcsymset = make(map[*types.Type]struct{})
    48  )
    49  
    50  type typeSig struct {
    51  	name  *types.Sym
    52  	isym  *obj.LSym
    53  	tsym  *obj.LSym
    54  	type_ *types.Type
    55  	mtype *types.Type
    56  }
    57  
    58  func commonSize() int { return int(rttype.Type.Size()) } // Sizeof(runtime._type{})
    59  
    60  func uncommonSize(t *types.Type) int { // Sizeof(runtime.uncommontype{})
    61  	if t.Sym() == nil && len(methods(t)) == 0 {
    62  		return 0
    63  	}
    64  	return int(rttype.UncommonType.Size())
    65  }
    66  
    67  func makefield(name string, t *types.Type) *types.Field {
    68  	sym := (*types.Pkg)(nil).Lookup(name)
    69  	return types.NewField(src.NoXPos, sym, t)
    70  }
    71  
    72  // MapBucketType makes the map bucket type given the type of the map.
    73  func MapBucketType(t *types.Type) *types.Type {
    74  	// Builds a type representing a Bucket structure for
    75  	// the given map type. This type is not visible to users -
    76  	// we include only enough information to generate a correct GC
    77  	// program for it.
    78  	// Make sure this stays in sync with runtime/map.go.
    79  	//
    80  	//	A "bucket" is a "struct" {
    81  	//	      tophash [abi.MapBucketCount]uint8
    82  	//	      keys [abi.MapBucketCount]keyType
    83  	//	      elems [abi.MapBucketCount]elemType
    84  	//	      overflow *bucket
    85  	//	    }
    86  	if t.MapType().Bucket != nil {
    87  		return t.MapType().Bucket
    88  	}
    89  
    90  	keytype := t.Key()
    91  	elemtype := t.Elem()
    92  	types.CalcSize(keytype)
    93  	types.CalcSize(elemtype)
    94  	if keytype.Size() > abi.MapMaxKeyBytes {
    95  		keytype = types.NewPtr(keytype)
    96  	}
    97  	if elemtype.Size() > abi.MapMaxElemBytes {
    98  		elemtype = types.NewPtr(elemtype)
    99  	}
   100  
   101  	field := make([]*types.Field, 0, 5)
   102  
   103  	// The first field is: uint8 topbits[BUCKETSIZE].
   104  	arr := types.NewArray(types.Types[types.TUINT8], abi.MapBucketCount)
   105  	field = append(field, makefield("topbits", arr))
   106  
   107  	arr = types.NewArray(keytype, abi.MapBucketCount)
   108  	arr.SetNoalg(true)
   109  	keys := makefield("keys", arr)
   110  	field = append(field, keys)
   111  
   112  	arr = types.NewArray(elemtype, abi.MapBucketCount)
   113  	arr.SetNoalg(true)
   114  	elems := makefield("elems", arr)
   115  	field = append(field, elems)
   116  
   117  	// If keys and elems have no pointers, the map implementation
   118  	// can keep a list of overflow pointers on the side so that
   119  	// buckets can be marked as having no pointers.
   120  	// Arrange for the bucket to have no pointers by changing
   121  	// the type of the overflow field to uintptr in this case.
   122  	// See comment on hmap.overflow in runtime/map.go.
   123  	otyp := types.Types[types.TUNSAFEPTR]
   124  	if !elemtype.HasPointers() && !keytype.HasPointers() {
   125  		otyp = types.Types[types.TUINTPTR]
   126  	}
   127  	overflow := makefield("overflow", otyp)
   128  	field = append(field, overflow)
   129  
   130  	// link up fields
   131  	bucket := types.NewStruct(field[:])
   132  	bucket.SetNoalg(true)
   133  	types.CalcSize(bucket)
   134  
   135  	// Check invariants that map code depends on.
   136  	if !types.IsComparable(t.Key()) {
   137  		base.Fatalf("unsupported map key type for %v", t)
   138  	}
   139  	if abi.MapBucketCount < 8 {
   140  		base.Fatalf("bucket size %d too small for proper alignment %d", abi.MapBucketCount, 8)
   141  	}
   142  	if uint8(keytype.Alignment()) > abi.MapBucketCount {
   143  		base.Fatalf("key align too big for %v", t)
   144  	}
   145  	if uint8(elemtype.Alignment()) > abi.MapBucketCount {
   146  		base.Fatalf("elem align %d too big for %v, BUCKETSIZE=%d", elemtype.Alignment(), t, abi.MapBucketCount)
   147  	}
   148  	if keytype.Size() > abi.MapMaxKeyBytes {
   149  		base.Fatalf("key size too large for %v", t)
   150  	}
   151  	if elemtype.Size() > abi.MapMaxElemBytes {
   152  		base.Fatalf("elem size too large for %v", t)
   153  	}
   154  	if t.Key().Size() > abi.MapMaxKeyBytes && !keytype.IsPtr() {
   155  		base.Fatalf("key indirect incorrect for %v", t)
   156  	}
   157  	if t.Elem().Size() > abi.MapMaxElemBytes && !elemtype.IsPtr() {
   158  		base.Fatalf("elem indirect incorrect for %v", t)
   159  	}
   160  	if keytype.Size()%keytype.Alignment() != 0 {
   161  		base.Fatalf("key size not a multiple of key align for %v", t)
   162  	}
   163  	if elemtype.Size()%elemtype.Alignment() != 0 {
   164  		base.Fatalf("elem size not a multiple of elem align for %v", t)
   165  	}
   166  	if uint8(bucket.Alignment())%uint8(keytype.Alignment()) != 0 {
   167  		base.Fatalf("bucket align not multiple of key align %v", t)
   168  	}
   169  	if uint8(bucket.Alignment())%uint8(elemtype.Alignment()) != 0 {
   170  		base.Fatalf("bucket align not multiple of elem align %v", t)
   171  	}
   172  	if keys.Offset%keytype.Alignment() != 0 {
   173  		base.Fatalf("bad alignment of keys in bmap for %v", t)
   174  	}
   175  	if elems.Offset%elemtype.Alignment() != 0 {
   176  		base.Fatalf("bad alignment of elems in bmap for %v", t)
   177  	}
   178  
   179  	// Double-check that overflow field is final memory in struct,
   180  	// with no padding at end.
   181  	if overflow.Offset != bucket.Size()-int64(types.PtrSize) {
   182  		base.Fatalf("bad offset of overflow in bmap for %v, overflow.Offset=%d, bucket.Size()-int64(types.PtrSize)=%d",
   183  			t, overflow.Offset, bucket.Size()-int64(types.PtrSize))
   184  	}
   185  
   186  	t.MapType().Bucket = bucket
   187  
   188  	bucket.StructType().Map = t
   189  	return bucket
   190  }
   191  
   192  var hmapType *types.Type
   193  
   194  // MapType returns a type interchangeable with runtime.hmap.
   195  // Make sure this stays in sync with runtime/map.go.
   196  func MapType() *types.Type {
   197  	if hmapType != nil {
   198  		return hmapType
   199  	}
   200  
   201  	// build a struct:
   202  	// type hmap struct {
   203  	//    count      int
   204  	//    flags      uint8
   205  	//    B          uint8
   206  	//    noverflow  uint16
   207  	//    hash0      uint32
   208  	//    buckets    unsafe.Pointer
   209  	//    oldbuckets unsafe.Pointer
   210  	//    nevacuate  uintptr
   211  	//    extra      unsafe.Pointer // *mapextra
   212  	// }
   213  	// must match runtime/map.go:hmap.
   214  	fields := []*types.Field{
   215  		makefield("count", types.Types[types.TINT]),
   216  		makefield("flags", types.Types[types.TUINT8]),
   217  		makefield("B", types.Types[types.TUINT8]),
   218  		makefield("noverflow", types.Types[types.TUINT16]),
   219  		makefield("hash0", types.Types[types.TUINT32]),      // Used in walk.go for OMAKEMAP.
   220  		makefield("buckets", types.Types[types.TUNSAFEPTR]), // Used in walk.go for OMAKEMAP.
   221  		makefield("oldbuckets", types.Types[types.TUNSAFEPTR]),
   222  		makefield("nevacuate", types.Types[types.TUINTPTR]),
   223  		makefield("extra", types.Types[types.TUNSAFEPTR]),
   224  	}
   225  
   226  	n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, ir.Pkgs.Runtime.Lookup("hmap"))
   227  	hmap := types.NewNamed(n)
   228  	n.SetType(hmap)
   229  	n.SetTypecheck(1)
   230  
   231  	hmap.SetUnderlying(types.NewStruct(fields))
   232  	types.CalcSize(hmap)
   233  
   234  	// The size of hmap should be 48 bytes on 64 bit
   235  	// and 28 bytes on 32 bit platforms.
   236  	if size := int64(8 + 5*types.PtrSize); hmap.Size() != size {
   237  		base.Fatalf("hmap size not correct: got %d, want %d", hmap.Size(), size)
   238  	}
   239  
   240  	hmapType = hmap
   241  	return hmap
   242  }
   243  
   244  var hiterType *types.Type
   245  
   246  // MapIterType returns a type interchangeable with runtime.hiter.
   247  // Make sure this stays in sync with runtime/map.go.
   248  func MapIterType() *types.Type {
   249  	if hiterType != nil {
   250  		return hiterType
   251  	}
   252  
   253  	hmap := MapType()
   254  
   255  	// build a struct:
   256  	// type hiter struct {
   257  	//    key         unsafe.Pointer // *Key
   258  	//    elem        unsafe.Pointer // *Elem
   259  	//    t           unsafe.Pointer // *MapType
   260  	//    h           *hmap
   261  	//    buckets     unsafe.Pointer
   262  	//    bptr        unsafe.Pointer // *bmap
   263  	//    overflow    unsafe.Pointer // *[]*bmap
   264  	//    oldoverflow unsafe.Pointer // *[]*bmap
   265  	//    startBucket uintptr
   266  	//    offset      uint8
   267  	//    wrapped     bool
   268  	//    B           uint8
   269  	//    i           uint8
   270  	//    bucket      uintptr
   271  	//    checkBucket uintptr
   272  	// }
   273  	// must match runtime/map.go:hiter.
   274  	fields := []*types.Field{
   275  		makefield("key", types.Types[types.TUNSAFEPTR]),  // Used in range.go for TMAP.
   276  		makefield("elem", types.Types[types.TUNSAFEPTR]), // Used in range.go for TMAP.
   277  		makefield("t", types.Types[types.TUNSAFEPTR]),
   278  		makefield("h", types.NewPtr(hmap)),
   279  		makefield("buckets", types.Types[types.TUNSAFEPTR]),
   280  		makefield("bptr", types.Types[types.TUNSAFEPTR]),
   281  		makefield("overflow", types.Types[types.TUNSAFEPTR]),
   282  		makefield("oldoverflow", types.Types[types.TUNSAFEPTR]),
   283  		makefield("startBucket", types.Types[types.TUINTPTR]),
   284  		makefield("offset", types.Types[types.TUINT8]),
   285  		makefield("wrapped", types.Types[types.TBOOL]),
   286  		makefield("B", types.Types[types.TUINT8]),
   287  		makefield("i", types.Types[types.TUINT8]),
   288  		makefield("bucket", types.Types[types.TUINTPTR]),
   289  		makefield("checkBucket", types.Types[types.TUINTPTR]),
   290  	}
   291  
   292  	// build iterator struct holding the above fields
   293  	n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, ir.Pkgs.Runtime.Lookup("hiter"))
   294  	hiter := types.NewNamed(n)
   295  	n.SetType(hiter)
   296  	n.SetTypecheck(1)
   297  
   298  	hiter.SetUnderlying(types.NewStruct(fields))
   299  	types.CalcSize(hiter)
   300  	if hiter.Size() != int64(12*types.PtrSize) {
   301  		base.Fatalf("hash_iter size not correct %d %d", hiter.Size(), 12*types.PtrSize)
   302  	}
   303  
   304  	hiterType = hiter
   305  	return hiter
   306  }
   307  
   308  // methods returns the methods of the non-interface type t, sorted by name.
   309  // Generates stub functions as needed.
   310  func methods(t *types.Type) []*typeSig {
   311  	if t.HasShape() {
   312  		// Shape types have no methods.
   313  		return nil
   314  	}
   315  	// method type
   316  	mt := types.ReceiverBaseType(t)
   317  
   318  	if mt == nil {
   319  		return nil
   320  	}
   321  	typecheck.CalcMethods(mt)
   322  
   323  	// make list of methods for t,
   324  	// generating code if necessary.
   325  	var ms []*typeSig
   326  	for _, f := range mt.AllMethods() {
   327  		if f.Sym == nil {
   328  			base.Fatalf("method with no sym on %v", mt)
   329  		}
   330  		if !f.IsMethod() {
   331  			base.Fatalf("non-method on %v method %v %v", mt, f.Sym, f)
   332  		}
   333  		if f.Type.Recv() == nil {
   334  			base.Fatalf("receiver with no type on %v method %v %v", mt, f.Sym, f)
   335  		}
   336  		if f.Nointerface() && !t.IsFullyInstantiated() {
   337  			// Skip creating method wrappers if f is nointerface. But, if
   338  			// t is an instantiated type, we still have to call
   339  			// methodWrapper, because methodWrapper generates the actual
   340  			// generic method on the type as well.
   341  			continue
   342  		}
   343  
   344  		// get receiver type for this particular method.
   345  		// if pointer receiver but non-pointer t and
   346  		// this is not an embedded pointer inside a struct,
   347  		// method does not apply.
   348  		if !types.IsMethodApplicable(t, f) {
   349  			continue
   350  		}
   351  
   352  		sig := &typeSig{
   353  			name:  f.Sym,
   354  			isym:  methodWrapper(t, f, true),
   355  			tsym:  methodWrapper(t, f, false),
   356  			type_: typecheck.NewMethodType(f.Type, t),
   357  			mtype: typecheck.NewMethodType(f.Type, nil),
   358  		}
   359  		if f.Nointerface() {
   360  			// In the case of a nointerface method on an instantiated
   361  			// type, don't actually append the typeSig.
   362  			continue
   363  		}
   364  		ms = append(ms, sig)
   365  	}
   366  
   367  	return ms
   368  }
   369  
   370  // imethods returns the methods of the interface type t, sorted by name.
   371  func imethods(t *types.Type) []*typeSig {
   372  	var methods []*typeSig
   373  	for _, f := range t.AllMethods() {
   374  		if f.Type.Kind() != types.TFUNC || f.Sym == nil {
   375  			continue
   376  		}
   377  		if f.Sym.IsBlank() {
   378  			base.Fatalf("unexpected blank symbol in interface method set")
   379  		}
   380  		if n := len(methods); n > 0 {
   381  			last := methods[n-1]
   382  			if !last.name.Less(f.Sym) {
   383  				base.Fatalf("sigcmp vs sortinter %v %v", last.name, f.Sym)
   384  			}
   385  		}
   386  
   387  		sig := &typeSig{
   388  			name:  f.Sym,
   389  			mtype: f.Type,
   390  			type_: typecheck.NewMethodType(f.Type, nil),
   391  		}
   392  		methods = append(methods, sig)
   393  
   394  		// NOTE(rsc): Perhaps an oversight that
   395  		// IfaceType.Method is not in the reflect data.
   396  		// Generate the method body, so that compiled
   397  		// code can refer to it.
   398  		methodWrapper(t, f, false)
   399  	}
   400  
   401  	return methods
   402  }
   403  
   404  func dimportpath(p *types.Pkg) {
   405  	if p.Pathsym != nil {
   406  		return
   407  	}
   408  
   409  	if p == types.LocalPkg && base.Ctxt.Pkgpath == "" {
   410  		panic("missing pkgpath")
   411  	}
   412  
   413  	// If we are compiling the runtime package, there are two runtime packages around
   414  	// -- localpkg and Pkgs.Runtime. We don't want to produce import path symbols for
   415  	// both of them, so just produce one for localpkg.
   416  	if base.Ctxt.Pkgpath == "runtime" && p == ir.Pkgs.Runtime {
   417  		return
   418  	}
   419  
   420  	s := base.Ctxt.Lookup("type:.importpath." + p.Prefix + ".")
   421  	ot := dnameData(s, 0, p.Path, "", nil, false, false)
   422  	objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
   423  	s.Set(obj.AttrContentAddressable, true)
   424  	p.Pathsym = s
   425  }
   426  
   427  func dgopkgpath(c rttype.Cursor, pkg *types.Pkg) {
   428  	c = c.Field("Bytes")
   429  	if pkg == nil {
   430  		c.WritePtr(nil)
   431  		return
   432  	}
   433  
   434  	dimportpath(pkg)
   435  	c.WritePtr(pkg.Pathsym)
   436  }
   437  
   438  // dgopkgpathOff writes an offset relocation to the pkg path symbol to c.
   439  func dgopkgpathOff(c rttype.Cursor, pkg *types.Pkg) {
   440  	if pkg == nil {
   441  		c.WriteInt32(0)
   442  		return
   443  	}
   444  
   445  	dimportpath(pkg)
   446  	c.WriteSymPtrOff(pkg.Pathsym, false)
   447  }
   448  
   449  // dnameField dumps a reflect.name for a struct field.
   450  func dnameField(c rttype.Cursor, spkg *types.Pkg, ft *types.Field) {
   451  	if !types.IsExported(ft.Sym.Name) && ft.Sym.Pkg != spkg {
   452  		base.Fatalf("package mismatch for %v", ft.Sym)
   453  	}
   454  	nsym := dname(ft.Sym.Name, ft.Note, nil, types.IsExported(ft.Sym.Name), ft.Embedded != 0)
   455  	c.Field("Bytes").WritePtr(nsym)
   456  }
   457  
   458  // dnameData writes the contents of a reflect.name into s at offset ot.
   459  func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported, embedded bool) int {
   460  	if len(name) >= 1<<29 {
   461  		base.Fatalf("name too long: %d %s...", len(name), name[:1024])
   462  	}
   463  	if len(tag) >= 1<<29 {
   464  		base.Fatalf("tag too long: %d %s...", len(tag), tag[:1024])
   465  	}
   466  	var nameLen [binary.MaxVarintLen64]byte
   467  	nameLenLen := binary.PutUvarint(nameLen[:], uint64(len(name)))
   468  	var tagLen [binary.MaxVarintLen64]byte
   469  	tagLenLen := binary.PutUvarint(tagLen[:], uint64(len(tag)))
   470  
   471  	// Encode name and tag. See reflect/type.go for details.
   472  	var bits byte
   473  	l := 1 + nameLenLen + len(name)
   474  	if exported {
   475  		bits |= 1 << 0
   476  	}
   477  	if len(tag) > 0 {
   478  		l += tagLenLen + len(tag)
   479  		bits |= 1 << 1
   480  	}
   481  	if pkg != nil {
   482  		bits |= 1 << 2
   483  	}
   484  	if embedded {
   485  		bits |= 1 << 3
   486  	}
   487  	b := make([]byte, l)
   488  	b[0] = bits
   489  	copy(b[1:], nameLen[:nameLenLen])
   490  	copy(b[1+nameLenLen:], name)
   491  	if len(tag) > 0 {
   492  		tb := b[1+nameLenLen+len(name):]
   493  		copy(tb, tagLen[:tagLenLen])
   494  		copy(tb[tagLenLen:], tag)
   495  	}
   496  
   497  	ot = int(s.WriteBytes(base.Ctxt, int64(ot), b))
   498  
   499  	if pkg != nil {
   500  		c := rttype.NewCursor(s, int64(ot), types.Types[types.TUINT32])
   501  		dgopkgpathOff(c, pkg)
   502  		ot += 4
   503  	}
   504  
   505  	return ot
   506  }
   507  
   508  var dnameCount int
   509  
   510  // dname creates a reflect.name for a struct field or method.
   511  func dname(name, tag string, pkg *types.Pkg, exported, embedded bool) *obj.LSym {
   512  	// Write out data as "type:." to signal two things to the
   513  	// linker, first that when dynamically linking, the symbol
   514  	// should be moved to a relro section, and second that the
   515  	// contents should not be decoded as a type.
   516  	sname := "type:.namedata."
   517  	if pkg == nil {
   518  		// In the common case, share data with other packages.
   519  		if name == "" {
   520  			if exported {
   521  				sname += "-noname-exported." + tag
   522  			} else {
   523  				sname += "-noname-unexported." + tag
   524  			}
   525  		} else {
   526  			if exported {
   527  				sname += name + "." + tag
   528  			} else {
   529  				sname += name + "-" + tag
   530  			}
   531  		}
   532  	} else {
   533  		// TODO(mdempsky): We should be able to share these too (except
   534  		// maybe when dynamic linking).
   535  		sname = fmt.Sprintf("%s%s.%d", sname, types.LocalPkg.Prefix, dnameCount)
   536  		dnameCount++
   537  	}
   538  	if embedded {
   539  		sname += ".embedded"
   540  	}
   541  	s := base.Ctxt.Lookup(sname)
   542  	if len(s.P) > 0 {
   543  		return s
   544  	}
   545  	ot := dnameData(s, 0, name, tag, pkg, exported, embedded)
   546  	objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
   547  	s.Set(obj.AttrContentAddressable, true)
   548  	return s
   549  }
   550  
   551  // dextratype dumps the fields of a runtime.uncommontype.
   552  // dataAdd is the offset in bytes after the header where the
   553  // backing array of the []method field should be written.
   554  func dextratype(lsym *obj.LSym, off int64, t *types.Type, dataAdd int) {
   555  	m := methods(t)
   556  	if t.Sym() == nil && len(m) == 0 {
   557  		base.Fatalf("extra requested of type with no extra info %v", t)
   558  	}
   559  	noff := types.RoundUp(off, int64(types.PtrSize))
   560  	if noff != off {
   561  		base.Fatalf("unexpected alignment in dextratype for %v", t)
   562  	}
   563  
   564  	for _, a := range m {
   565  		writeType(a.type_)
   566  	}
   567  
   568  	c := rttype.NewCursor(lsym, off, rttype.UncommonType)
   569  	dgopkgpathOff(c.Field("PkgPath"), typePkg(t))
   570  
   571  	dataAdd += uncommonSize(t)
   572  	mcount := len(m)
   573  	if mcount != int(uint16(mcount)) {
   574  		base.Fatalf("too many methods on %v: %d", t, mcount)
   575  	}
   576  	xcount := sort.Search(mcount, func(i int) bool { return !types.IsExported(m[i].name.Name) })
   577  	if dataAdd != int(uint32(dataAdd)) {
   578  		base.Fatalf("methods are too far away on %v: %d", t, dataAdd)
   579  	}
   580  
   581  	c.Field("Mcount").WriteUint16(uint16(mcount))
   582  	c.Field("Xcount").WriteUint16(uint16(xcount))
   583  	c.Field("Moff").WriteUint32(uint32(dataAdd))
   584  	// Note: there is an unused uint32 field here.
   585  
   586  	// Write the backing array for the []method field.
   587  	array := rttype.NewArrayCursor(lsym, off+int64(dataAdd), rttype.Method, mcount)
   588  	for i, a := range m {
   589  		exported := types.IsExported(a.name.Name)
   590  		var pkg *types.Pkg
   591  		if !exported && a.name.Pkg != typePkg(t) {
   592  			pkg = a.name.Pkg
   593  		}
   594  		nsym := dname(a.name.Name, "", pkg, exported, false)
   595  
   596  		e := array.Elem(i)
   597  		e.Field("Name").WriteSymPtrOff(nsym, false)
   598  		dmethodptrOff(e.Field("Mtyp"), writeType(a.mtype))
   599  		dmethodptrOff(e.Field("Ifn"), a.isym)
   600  		dmethodptrOff(e.Field("Tfn"), a.tsym)
   601  	}
   602  }
   603  
   604  func typePkg(t *types.Type) *types.Pkg {
   605  	tsym := t.Sym()
   606  	if tsym == nil {
   607  		switch t.Kind() {
   608  		case types.TARRAY, types.TSLICE, types.TPTR, types.TCHAN:
   609  			if t.Elem() != nil {
   610  				tsym = t.Elem().Sym()
   611  			}
   612  		}
   613  	}
   614  	if tsym != nil && tsym.Pkg != types.BuiltinPkg {
   615  		return tsym.Pkg
   616  	}
   617  	return nil
   618  }
   619  
   620  func dmethodptrOff(c rttype.Cursor, x *obj.LSym) {
   621  	c.WriteInt32(0)
   622  	r := c.Reloc()
   623  	r.Sym = x
   624  	r.Type = objabi.R_METHODOFF
   625  }
   626  
   627  var kinds = []abi.Kind{
   628  	types.TINT:        abi.Int,
   629  	types.TUINT:       abi.Uint,
   630  	types.TINT8:       abi.Int8,
   631  	types.TUINT8:      abi.Uint8,
   632  	types.TINT16:      abi.Int16,
   633  	types.TUINT16:     abi.Uint16,
   634  	types.TINT32:      abi.Int32,
   635  	types.TUINT32:     abi.Uint32,
   636  	types.TINT64:      abi.Int64,
   637  	types.TUINT64:     abi.Uint64,
   638  	types.TUINTPTR:    abi.Uintptr,
   639  	types.TFLOAT32:    abi.Float32,
   640  	types.TFLOAT64:    abi.Float64,
   641  	types.TBOOL:       abi.Bool,
   642  	types.TSTRING:     abi.String,
   643  	types.TPTR:        abi.Pointer,
   644  	types.TSTRUCT:     abi.Struct,
   645  	types.TINTER:      abi.Interface,
   646  	types.TCHAN:       abi.Chan,
   647  	types.TMAP:        abi.Map,
   648  	types.TARRAY:      abi.Array,
   649  	types.TSLICE:      abi.Slice,
   650  	types.TFUNC:       abi.Func,
   651  	types.TCOMPLEX64:  abi.Complex64,
   652  	types.TCOMPLEX128: abi.Complex128,
   653  	types.TUNSAFEPTR:  abi.UnsafePointer,
   654  }
   655  
   656  var (
   657  	memhashvarlen  *obj.LSym
   658  	memequalvarlen *obj.LSym
   659  )
   660  
   661  // dcommontype dumps the contents of a reflect.rtype (runtime._type) to c.
   662  func dcommontype(c rttype.Cursor, t *types.Type) {
   663  	types.CalcSize(t)
   664  	eqfunc := geneq(t)
   665  
   666  	sptrWeak := true
   667  	var sptr *obj.LSym
   668  	if !t.IsPtr() || t.IsPtrElem() {
   669  		tptr := types.NewPtr(t)
   670  		if t.Sym() != nil || methods(tptr) != nil {
   671  			sptrWeak = false
   672  		}
   673  		sptr = writeType(tptr)
   674  	}
   675  
   676  	gcsym, useGCProg, ptrdata := dgcsym(t, true)
   677  	delete(gcsymset, t)
   678  
   679  	// ../../../../reflect/type.go:/^type.rtype
   680  	// actual type structure
   681  	//	type rtype struct {
   682  	//		size          uintptr
   683  	//		ptrdata       uintptr
   684  	//		hash          uint32
   685  	//		tflag         tflag
   686  	//		align         uint8
   687  	//		fieldAlign    uint8
   688  	//		kind          uint8
   689  	//		equal         func(unsafe.Pointer, unsafe.Pointer) bool
   690  	//		gcdata        *byte
   691  	//		str           nameOff
   692  	//		ptrToThis     typeOff
   693  	//	}
   694  	c.Field("Size_").WriteUintptr(uint64(t.Size()))
   695  	c.Field("PtrBytes").WriteUintptr(uint64(ptrdata))
   696  	c.Field("Hash").WriteUint32(types.TypeHash(t))
   697  
   698  	var tflag abi.TFlag
   699  	if uncommonSize(t) != 0 {
   700  		tflag |= abi.TFlagUncommon
   701  	}
   702  	if t.Sym() != nil && t.Sym().Name != "" {
   703  		tflag |= abi.TFlagNamed
   704  	}
   705  	if compare.IsRegularMemory(t) {
   706  		tflag |= abi.TFlagRegularMemory
   707  	}
   708  
   709  	exported := false
   710  	p := t.NameString()
   711  	// If we're writing out type T,
   712  	// we are very likely to write out type *T as well.
   713  	// Use the string "*T"[1:] for "T", so that the two
   714  	// share storage. This is a cheap way to reduce the
   715  	// amount of space taken up by reflect strings.
   716  	if !strings.HasPrefix(p, "*") {
   717  		p = "*" + p
   718  		tflag |= abi.TFlagExtraStar
   719  		if t.Sym() != nil {
   720  			exported = types.IsExported(t.Sym().Name)
   721  		}
   722  	} else {
   723  		if t.Elem() != nil && t.Elem().Sym() != nil {
   724  			exported = types.IsExported(t.Elem().Sym().Name)
   725  		}
   726  	}
   727  
   728  	if tflag != abi.TFlag(uint8(tflag)) {
   729  		// this should optimize away completely
   730  		panic("Unexpected change in size of abi.TFlag")
   731  	}
   732  	c.Field("TFlag").WriteUint8(uint8(tflag))
   733  
   734  	// runtime (and common sense) expects alignment to be a power of two.
   735  	i := int(uint8(t.Alignment()))
   736  
   737  	if i == 0 {
   738  		i = 1
   739  	}
   740  	if i&(i-1) != 0 {
   741  		base.Fatalf("invalid alignment %d for %v", uint8(t.Alignment()), t)
   742  	}
   743  	c.Field("Align_").WriteUint8(uint8(t.Alignment()))
   744  	c.Field("FieldAlign_").WriteUint8(uint8(t.Alignment()))
   745  
   746  	kind := kinds[t.Kind()]
   747  	if types.IsDirectIface(t) {
   748  		kind |= abi.KindDirectIface
   749  	}
   750  	if useGCProg {
   751  		kind |= abi.KindGCProg
   752  	}
   753  	c.Field("Kind_").WriteUint8(uint8(kind))
   754  
   755  	c.Field("Equal").WritePtr(eqfunc)
   756  	c.Field("GCData").WritePtr(gcsym)
   757  
   758  	nsym := dname(p, "", nil, exported, false)
   759  	c.Field("Str").WriteSymPtrOff(nsym, false)
   760  	c.Field("PtrToThis").WriteSymPtrOff(sptr, sptrWeak)
   761  }
   762  
   763  // TrackSym returns the symbol for tracking use of field/method f, assumed
   764  // to be a member of struct/interface type t.
   765  func TrackSym(t *types.Type, f *types.Field) *obj.LSym {
   766  	return base.PkgLinksym("go:track", t.LinkString()+"."+f.Sym.Name, obj.ABI0)
   767  }
   768  
   769  func TypeSymPrefix(prefix string, t *types.Type) *types.Sym {
   770  	p := prefix + "." + t.LinkString()
   771  	s := types.TypeSymLookup(p)
   772  
   773  	// This function is for looking up type-related generated functions
   774  	// (e.g. eq and hash). Make sure they are indeed generated.
   775  	signatmu.Lock()
   776  	NeedRuntimeType(t)
   777  	signatmu.Unlock()
   778  
   779  	//print("algsym: %s -> %+S\n", p, s);
   780  
   781  	return s
   782  }
   783  
   784  func TypeSym(t *types.Type) *types.Sym {
   785  	if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
   786  		base.Fatalf("TypeSym %v", t)
   787  	}
   788  	if t.Kind() == types.TFUNC && t.Recv() != nil {
   789  		base.Fatalf("misuse of method type: %v", t)
   790  	}
   791  	s := types.TypeSym(t)
   792  	signatmu.Lock()
   793  	NeedRuntimeType(t)
   794  	signatmu.Unlock()
   795  	return s
   796  }
   797  
   798  func TypeLinksymPrefix(prefix string, t *types.Type) *obj.LSym {
   799  	return TypeSymPrefix(prefix, t).Linksym()
   800  }
   801  
   802  func TypeLinksymLookup(name string) *obj.LSym {
   803  	return types.TypeSymLookup(name).Linksym()
   804  }
   805  
   806  func TypeLinksym(t *types.Type) *obj.LSym {
   807  	lsym := TypeSym(t).Linksym()
   808  	signatmu.Lock()
   809  	if lsym.Extra == nil {
   810  		ti := lsym.NewTypeInfo()
   811  		ti.Type = t
   812  	}
   813  	signatmu.Unlock()
   814  	return lsym
   815  }
   816  
   817  // TypePtrAt returns an expression that evaluates to the
   818  // *runtime._type value for t.
   819  func TypePtrAt(pos src.XPos, t *types.Type) *ir.AddrExpr {
   820  	return typecheck.LinksymAddr(pos, TypeLinksym(t), types.Types[types.TUINT8])
   821  }
   822  
   823  // ITabLsym returns the LSym representing the itab for concrete type typ implementing
   824  // interface iface. A dummy tab will be created in the unusual case where typ doesn't
   825  // implement iface. Normally, this wouldn't happen, because the typechecker would
   826  // have reported a compile-time error. This situation can only happen when the
   827  // destination type of a type assert or a type in a type switch is parameterized, so
   828  // it may sometimes, but not always, be a type that can't implement the specified
   829  // interface.
   830  func ITabLsym(typ, iface *types.Type) *obj.LSym {
   831  	s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString())
   832  	lsym := s.Linksym()
   833  
   834  	if !existed {
   835  		writeITab(lsym, typ, iface, true)
   836  	}
   837  	return lsym
   838  }
   839  
   840  // ITabAddrAt returns an expression that evaluates to the
   841  // *runtime.itab value for concrete type typ implementing interface
   842  // iface.
   843  func ITabAddrAt(pos src.XPos, typ, iface *types.Type) *ir.AddrExpr {
   844  	s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString())
   845  	lsym := s.Linksym()
   846  
   847  	if !existed {
   848  		writeITab(lsym, typ, iface, false)
   849  	}
   850  
   851  	return typecheck.LinksymAddr(pos, lsym, types.Types[types.TUINT8])
   852  }
   853  
   854  // needkeyupdate reports whether map updates with t as a key
   855  // need the key to be updated.
   856  func needkeyupdate(t *types.Type) bool {
   857  	switch t.Kind() {
   858  	case types.TBOOL, types.TINT, types.TUINT, types.TINT8, types.TUINT8, types.TINT16, types.TUINT16, types.TINT32, types.TUINT32,
   859  		types.TINT64, types.TUINT64, types.TUINTPTR, types.TPTR, types.TUNSAFEPTR, types.TCHAN:
   860  		return false
   861  
   862  	case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, // floats and complex can be +0/-0
   863  		types.TINTER,
   864  		types.TSTRING: // strings might have smaller backing stores
   865  		return true
   866  
   867  	case types.TARRAY:
   868  		return needkeyupdate(t.Elem())
   869  
   870  	case types.TSTRUCT:
   871  		for _, t1 := range t.Fields() {
   872  			if needkeyupdate(t1.Type) {
   873  				return true
   874  			}
   875  		}
   876  		return false
   877  
   878  	default:
   879  		base.Fatalf("bad type for map key: %v", t)
   880  		return true
   881  	}
   882  }
   883  
   884  // hashMightPanic reports whether the hash of a map key of type t might panic.
   885  func hashMightPanic(t *types.Type) bool {
   886  	switch t.Kind() {
   887  	case types.TINTER:
   888  		return true
   889  
   890  	case types.TARRAY:
   891  		return hashMightPanic(t.Elem())
   892  
   893  	case types.TSTRUCT:
   894  		for _, t1 := range t.Fields() {
   895  			if hashMightPanic(t1.Type) {
   896  				return true
   897  			}
   898  		}
   899  		return false
   900  
   901  	default:
   902  		return false
   903  	}
   904  }
   905  
   906  // formalType replaces predeclared aliases with real types.
   907  // They've been separate internally to make error messages
   908  // better, but we have to merge them in the reflect tables.
   909  func formalType(t *types.Type) *types.Type {
   910  	switch t {
   911  	case types.AnyType, types.ByteType, types.RuneType:
   912  		return types.Types[t.Kind()]
   913  	}
   914  	return t
   915  }
   916  
   917  func writeType(t *types.Type) *obj.LSym {
   918  	t = formalType(t)
   919  	if t.IsUntyped() {
   920  		base.Fatalf("writeType %v", t)
   921  	}
   922  
   923  	s := types.TypeSym(t)
   924  	lsym := s.Linksym()
   925  
   926  	// special case (look for runtime below):
   927  	// when compiling package runtime,
   928  	// emit the type structures for int, float, etc.
   929  	tbase := t
   930  	if t.IsPtr() && t.Sym() == nil && t.Elem().Sym() != nil {
   931  		tbase = t.Elem()
   932  	}
   933  	if tbase.Kind() == types.TFORW {
   934  		base.Fatalf("unresolved defined type: %v", tbase)
   935  	}
   936  
   937  	// This is a fake type we generated for our builtin pseudo-runtime
   938  	// package. We'll emit a description for the real type while
   939  	// compiling package runtime, so we don't need or want to emit one
   940  	// from this fake type.
   941  	if sym := tbase.Sym(); sym != nil && sym.Pkg == ir.Pkgs.Runtime {
   942  		return lsym
   943  	}
   944  
   945  	if s.Siggen() {
   946  		return lsym
   947  	}
   948  	s.SetSiggen(true)
   949  
   950  	if !NeedEmit(tbase) {
   951  		if i := typecheck.BaseTypeIndex(t); i >= 0 {
   952  			lsym.Pkg = tbase.Sym().Pkg.Prefix
   953  			lsym.SymIdx = int32(i)
   954  			lsym.Set(obj.AttrIndexed, true)
   955  		}
   956  
   957  		// TODO(mdempsky): Investigate whether this still happens.
   958  		// If we know we don't need to emit code for a type,
   959  		// we should have a link-symbol index for it.
   960  		// See also TODO in NeedEmit.
   961  		return lsym
   962  	}
   963  
   964  	// Type layout                          Written by               Marker
   965  	// +--------------------------------+                            - 0
   966  	// | abi/internal.Type              |   dcommontype
   967  	// +--------------------------------+                            - A
   968  	// | additional type-dependent      |   code in the switch below
   969  	// | fields, e.g.                   |
   970  	// | abi/internal.ArrayType.Len     |
   971  	// +--------------------------------+                            - B
   972  	// | internal/abi.UncommonType      |   dextratype
   973  	// | This section is optional,      |
   974  	// | if type has a name or methods  |
   975  	// +--------------------------------+                            - C
   976  	// | variable-length data           |   code in the switch below
   977  	// | referenced by                  |
   978  	// | type-dependent fields, e.g.    |
   979  	// | abi/internal.StructType.Fields |
   980  	// | dataAdd = size of this section |
   981  	// +--------------------------------+                            - D
   982  	// | method list, if any            |   dextratype
   983  	// +--------------------------------+                            - E
   984  
   985  	// UncommonType section is included if we have a name or a method.
   986  	extra := t.Sym() != nil || len(methods(t)) != 0
   987  
   988  	// Decide the underlying type of the descriptor, and remember
   989  	// the size we need for variable-length data.
   990  	var rt *types.Type
   991  	dataAdd := 0
   992  	switch t.Kind() {
   993  	default:
   994  		rt = rttype.Type
   995  	case types.TARRAY:
   996  		rt = rttype.ArrayType
   997  	case types.TSLICE:
   998  		rt = rttype.SliceType
   999  	case types.TCHAN:
  1000  		rt = rttype.ChanType
  1001  	case types.TFUNC:
  1002  		rt = rttype.FuncType
  1003  		dataAdd = (t.NumRecvs() + t.NumParams() + t.NumResults()) * types.PtrSize
  1004  	case types.TINTER:
  1005  		rt = rttype.InterfaceType
  1006  		dataAdd = len(imethods(t)) * int(rttype.IMethod.Size())
  1007  	case types.TMAP:
  1008  		rt = rttype.MapType
  1009  	case types.TPTR:
  1010  		rt = rttype.PtrType
  1011  		// TODO: use rttype.Type for Elem() is ANY?
  1012  	case types.TSTRUCT:
  1013  		rt = rttype.StructType
  1014  		dataAdd = t.NumFields() * int(rttype.StructField.Size())
  1015  	}
  1016  
  1017  	// Compute offsets of each section.
  1018  	B := rt.Size()
  1019  	C := B
  1020  	if extra {
  1021  		C = B + rttype.UncommonType.Size()
  1022  	}
  1023  	D := C + int64(dataAdd)
  1024  	E := D + int64(len(methods(t)))*rttype.Method.Size()
  1025  
  1026  	// Write the runtime._type
  1027  	c := rttype.NewCursor(lsym, 0, rt)
  1028  	if rt == rttype.Type {
  1029  		dcommontype(c, t)
  1030  	} else {
  1031  		dcommontype(c.Field("Type"), t)
  1032  	}
  1033  
  1034  	// Write additional type-specific data
  1035  	// (Both the fixed size and variable-sized sections.)
  1036  	switch t.Kind() {
  1037  	case types.TARRAY:
  1038  		// internal/abi.ArrayType
  1039  		s1 := writeType(t.Elem())
  1040  		t2 := types.NewSlice(t.Elem())
  1041  		s2 := writeType(t2)
  1042  		c.Field("Elem").WritePtr(s1)
  1043  		c.Field("Slice").WritePtr(s2)
  1044  		c.Field("Len").WriteUintptr(uint64(t.NumElem()))
  1045  
  1046  	case types.TSLICE:
  1047  		// internal/abi.SliceType
  1048  		s1 := writeType(t.Elem())
  1049  		c.Field("Elem").WritePtr(s1)
  1050  
  1051  	case types.TCHAN:
  1052  		// internal/abi.ChanType
  1053  		s1 := writeType(t.Elem())
  1054  		c.Field("Elem").WritePtr(s1)
  1055  		c.Field("Dir").WriteInt(int64(t.ChanDir()))
  1056  
  1057  	case types.TFUNC:
  1058  		// internal/abi.FuncType
  1059  		for _, t1 := range t.RecvParamsResults() {
  1060  			writeType(t1.Type)
  1061  		}
  1062  		inCount := t.NumRecvs() + t.NumParams()
  1063  		outCount := t.NumResults()
  1064  		if t.IsVariadic() {
  1065  			outCount |= 1 << 15
  1066  		}
  1067  
  1068  		c.Field("InCount").WriteUint16(uint16(inCount))
  1069  		c.Field("OutCount").WriteUint16(uint16(outCount))
  1070  
  1071  		// Array of rtype pointers follows funcType.
  1072  		typs := t.RecvParamsResults()
  1073  		array := rttype.NewArrayCursor(lsym, C, types.Types[types.TUNSAFEPTR], len(typs))
  1074  		for i, t1 := range typs {
  1075  			array.Elem(i).WritePtr(writeType(t1.Type))
  1076  		}
  1077  
  1078  	case types.TINTER:
  1079  		// internal/abi.InterfaceType
  1080  		m := imethods(t)
  1081  		n := len(m)
  1082  		for _, a := range m {
  1083  			writeType(a.type_)
  1084  		}
  1085  
  1086  		var tpkg *types.Pkg
  1087  		if t.Sym() != nil && t != types.Types[t.Kind()] && t != types.ErrorType {
  1088  			tpkg = t.Sym().Pkg
  1089  		}
  1090  		dgopkgpath(c.Field("PkgPath"), tpkg)
  1091  		c.Field("Methods").WriteSlice(lsym, C, int64(n), int64(n))
  1092  
  1093  		array := rttype.NewArrayCursor(lsym, C, rttype.IMethod, n)
  1094  		for i, a := range m {
  1095  			exported := types.IsExported(a.name.Name)
  1096  			var pkg *types.Pkg
  1097  			if !exported && a.name.Pkg != tpkg {
  1098  				pkg = a.name.Pkg
  1099  			}
  1100  			nsym := dname(a.name.Name, "", pkg, exported, false)
  1101  
  1102  			e := array.Elem(i)
  1103  			e.Field("Name").WriteSymPtrOff(nsym, false)
  1104  			e.Field("Typ").WriteSymPtrOff(writeType(a.type_), false)
  1105  		}
  1106  
  1107  	case types.TMAP:
  1108  		// internal/abi.MapType
  1109  		s1 := writeType(t.Key())
  1110  		s2 := writeType(t.Elem())
  1111  		s3 := writeType(MapBucketType(t))
  1112  		hasher := genhash(t.Key())
  1113  
  1114  		c.Field("Key").WritePtr(s1)
  1115  		c.Field("Elem").WritePtr(s2)
  1116  		c.Field("Bucket").WritePtr(s3)
  1117  		c.Field("Hasher").WritePtr(hasher)
  1118  		var flags uint32
  1119  		// Note: flags must match maptype accessors in ../../../../runtime/type.go
  1120  		// and maptype builder in ../../../../reflect/type.go:MapOf.
  1121  		if t.Key().Size() > abi.MapMaxKeyBytes {
  1122  			c.Field("KeySize").WriteUint8(uint8(types.PtrSize))
  1123  			flags |= 1 // indirect key
  1124  		} else {
  1125  			c.Field("KeySize").WriteUint8(uint8(t.Key().Size()))
  1126  		}
  1127  
  1128  		if t.Elem().Size() > abi.MapMaxElemBytes {
  1129  			c.Field("ValueSize").WriteUint8(uint8(types.PtrSize))
  1130  			flags |= 2 // indirect value
  1131  		} else {
  1132  			c.Field("ValueSize").WriteUint8(uint8(t.Elem().Size()))
  1133  		}
  1134  		c.Field("BucketSize").WriteUint16(uint16(MapBucketType(t).Size()))
  1135  		if types.IsReflexive(t.Key()) {
  1136  			flags |= 4 // reflexive key
  1137  		}
  1138  		if needkeyupdate(t.Key()) {
  1139  			flags |= 8 // need key update
  1140  		}
  1141  		if hashMightPanic(t.Key()) {
  1142  			flags |= 16 // hash might panic
  1143  		}
  1144  		c.Field("Flags").WriteUint32(flags)
  1145  
  1146  		if u := t.Underlying(); u != t {
  1147  			// If t is a named map type, also keep the underlying map
  1148  			// type live in the binary. This is important to make sure that
  1149  			// a named map and that same map cast to its underlying type via
  1150  			// reflection, use the same hash function. See issue 37716.
  1151  			r := obj.Addrel(lsym)
  1152  			r.Sym = writeType(u)
  1153  			r.Type = objabi.R_KEEP
  1154  		}
  1155  
  1156  	case types.TPTR:
  1157  		// internal/abi.PtrType
  1158  		if t.Elem().Kind() == types.TANY {
  1159  			base.Fatalf("bad pointer base type")
  1160  		}
  1161  
  1162  		s1 := writeType(t.Elem())
  1163  		c.Field("Elem").WritePtr(s1)
  1164  
  1165  	case types.TSTRUCT:
  1166  		// internal/abi.StructType
  1167  		fields := t.Fields()
  1168  		for _, t1 := range fields {
  1169  			writeType(t1.Type)
  1170  		}
  1171  
  1172  		// All non-exported struct field names within a struct
  1173  		// type must originate from a single package. By
  1174  		// identifying and recording that package within the
  1175  		// struct type descriptor, we can omit that
  1176  		// information from the field descriptors.
  1177  		var spkg *types.Pkg
  1178  		for _, f := range fields {
  1179  			if !types.IsExported(f.Sym.Name) {
  1180  				spkg = f.Sym.Pkg
  1181  				break
  1182  			}
  1183  		}
  1184  
  1185  		dgopkgpath(c.Field("PkgPath"), spkg)
  1186  		c.Field("Fields").WriteSlice(lsym, C, int64(len(fields)), int64(len(fields)))
  1187  
  1188  		array := rttype.NewArrayCursor(lsym, C, rttype.StructField, len(fields))
  1189  		for i, f := range fields {
  1190  			e := array.Elem(i)
  1191  			dnameField(e.Field("Name"), spkg, f)
  1192  			e.Field("Typ").WritePtr(writeType(f.Type))
  1193  			e.Field("Offset").WriteUintptr(uint64(f.Offset))
  1194  		}
  1195  	}
  1196  
  1197  	// Write the extra info, if any.
  1198  	if extra {
  1199  		dextratype(lsym, B, t, dataAdd)
  1200  	}
  1201  
  1202  	// Note: DUPOK is required to ensure that we don't end up with more
  1203  	// than one type descriptor for a given type, if the type descriptor
  1204  	// can be defined in multiple packages, that is, unnamed types,
  1205  	// instantiated types and shape types.
  1206  	dupok := 0
  1207  	if tbase.Sym() == nil || tbase.IsFullyInstantiated() || tbase.HasShape() {
  1208  		dupok = obj.DUPOK
  1209  	}
  1210  
  1211  	objw.Global(lsym, int32(E), int16(dupok|obj.RODATA))
  1212  
  1213  	// The linker will leave a table of all the typelinks for
  1214  	// types in the binary, so the runtime can find them.
  1215  	//
  1216  	// When buildmode=shared, all types are in typelinks so the
  1217  	// runtime can deduplicate type pointers.
  1218  	keep := base.Ctxt.Flag_dynlink
  1219  	if !keep && t.Sym() == nil {
  1220  		// For an unnamed type, we only need the link if the type can
  1221  		// be created at run time by reflect.PointerTo and similar
  1222  		// functions. If the type exists in the program, those
  1223  		// functions must return the existing type structure rather
  1224  		// than creating a new one.
  1225  		switch t.Kind() {
  1226  		case types.TPTR, types.TARRAY, types.TCHAN, types.TFUNC, types.TMAP, types.TSLICE, types.TSTRUCT:
  1227  			keep = true
  1228  		}
  1229  	}
  1230  	// Do not put Noalg types in typelinks.  See issue #22605.
  1231  	if types.TypeHasNoAlg(t) {
  1232  		keep = false
  1233  	}
  1234  	lsym.Set(obj.AttrMakeTypelink, keep)
  1235  
  1236  	return lsym
  1237  }
  1238  
  1239  // InterfaceMethodOffset returns the offset of the i-th method in the interface
  1240  // type descriptor, ityp.
  1241  func InterfaceMethodOffset(ityp *types.Type, i int64) int64 {
  1242  	// interface type descriptor layout is struct {
  1243  	//   _type        // commonSize
  1244  	//   pkgpath      // 1 word
  1245  	//   []imethod    // 3 words (pointing to [...]imethod below)
  1246  	//   uncommontype // uncommonSize
  1247  	//   [...]imethod
  1248  	// }
  1249  	// The size of imethod is 8.
  1250  	return int64(commonSize()+4*types.PtrSize+uncommonSize(ityp)) + i*8
  1251  }
  1252  
  1253  // NeedRuntimeType ensures that a runtime type descriptor is emitted for t.
  1254  func NeedRuntimeType(t *types.Type) {
  1255  	if _, ok := signatset[t]; !ok {
  1256  		signatset[t] = struct{}{}
  1257  		signatslice = append(signatslice, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()})
  1258  	}
  1259  }
  1260  
  1261  func WriteRuntimeTypes() {
  1262  	// Process signatslice. Use a loop, as writeType adds
  1263  	// entries to signatslice while it is being processed.
  1264  	for len(signatslice) > 0 {
  1265  		signats := signatslice
  1266  		// Sort for reproducible builds.
  1267  		sort.Sort(typesByString(signats))
  1268  		for _, ts := range signats {
  1269  			t := ts.t
  1270  			writeType(t)
  1271  			if t.Sym() != nil {
  1272  				writeType(types.NewPtr(t))
  1273  			}
  1274  		}
  1275  		signatslice = signatslice[len(signats):]
  1276  	}
  1277  }
  1278  
  1279  func WriteGCSymbols() {
  1280  	// Emit GC data symbols.
  1281  	gcsyms := make([]typeAndStr, 0, len(gcsymset))
  1282  	for t := range gcsymset {
  1283  		gcsyms = append(gcsyms, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()})
  1284  	}
  1285  	sort.Sort(typesByString(gcsyms))
  1286  	for _, ts := range gcsyms {
  1287  		dgcsym(ts.t, true)
  1288  	}
  1289  }
  1290  
  1291  // writeITab writes the itab for concrete type typ implementing interface iface. If
  1292  // allowNonImplement is true, allow the case where typ does not implement iface, and just
  1293  // create a dummy itab with zeroed-out method entries.
  1294  func writeITab(lsym *obj.LSym, typ, iface *types.Type, allowNonImplement bool) {
  1295  	// TODO(mdempsky): Fix methodWrapper, geneq, and genhash (and maybe
  1296  	// others) to stop clobbering these.
  1297  	oldpos, oldfn := base.Pos, ir.CurFunc
  1298  	defer func() { base.Pos, ir.CurFunc = oldpos, oldfn }()
  1299  
  1300  	if typ == nil || (typ.IsPtr() && typ.Elem() == nil) || typ.IsUntyped() || iface == nil || !iface.IsInterface() || iface.IsEmptyInterface() {
  1301  		base.Fatalf("writeITab(%v, %v)", typ, iface)
  1302  	}
  1303  
  1304  	sigs := iface.AllMethods()
  1305  	entries := make([]*obj.LSym, 0, len(sigs))
  1306  
  1307  	// both sigs and methods are sorted by name,
  1308  	// so we can find the intersection in a single pass
  1309  	for _, m := range methods(typ) {
  1310  		if m.name == sigs[0].Sym {
  1311  			entries = append(entries, m.isym)
  1312  			if m.isym == nil {
  1313  				panic("NO ISYM")
  1314  			}
  1315  			sigs = sigs[1:]
  1316  			if len(sigs) == 0 {
  1317  				break
  1318  			}
  1319  		}
  1320  	}
  1321  	completeItab := len(sigs) == 0
  1322  	if !allowNonImplement && !completeItab {
  1323  		base.Fatalf("incomplete itab")
  1324  	}
  1325  
  1326  	// dump empty itab symbol into i.sym
  1327  	// type itab struct {
  1328  	//   inter  *interfacetype
  1329  	//   _type  *_type
  1330  	//   hash   uint32 // copy of _type.hash. Used for type switches.
  1331  	//   _      [4]byte
  1332  	//   fun    [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
  1333  	// }
  1334  	c := rttype.NewCursor(lsym, 0, rttype.ITab)
  1335  	c.Field("Inter").WritePtr(writeType(iface))
  1336  	c.Field("Type").WritePtr(writeType(typ))
  1337  	c.Field("Hash").WriteUint32(types.TypeHash(typ)) // copy of type hash
  1338  
  1339  	var delta int64
  1340  	c = c.Field("Fun")
  1341  	if !completeItab {
  1342  		// If typ doesn't implement iface, make method entries be zero.
  1343  		c.Elem(0).WriteUintptr(0)
  1344  	} else {
  1345  		var a rttype.ArrayCursor
  1346  		a, delta = c.ModifyArray(len(entries))
  1347  		for i, fn := range entries {
  1348  			a.Elem(i).WritePtrWeak(fn) // method pointer for each method
  1349  		}
  1350  	}
  1351  	// Nothing writes static itabs, so they are read only.
  1352  	objw.Global(lsym, int32(rttype.ITab.Size()+delta), int16(obj.DUPOK|obj.RODATA))
  1353  	lsym.Set(obj.AttrContentAddressable, true)
  1354  }
  1355  
  1356  func WritePluginTable() {
  1357  	ptabs := typecheck.Target.PluginExports
  1358  	if len(ptabs) == 0 {
  1359  		return
  1360  	}
  1361  
  1362  	lsym := base.Ctxt.Lookup("go:plugin.tabs")
  1363  	ot := 0
  1364  	for _, p := range ptabs {
  1365  		// Dump ptab symbol into go.pluginsym package.
  1366  		//
  1367  		// type ptab struct {
  1368  		//	name nameOff
  1369  		//	typ  typeOff // pointer to symbol
  1370  		// }
  1371  		nsym := dname(p.Sym().Name, "", nil, true, false)
  1372  		t := p.Type()
  1373  		if p.Class != ir.PFUNC {
  1374  			t = types.NewPtr(t)
  1375  		}
  1376  		tsym := writeType(t)
  1377  		ot = objw.SymPtrOff(lsym, ot, nsym)
  1378  		ot = objw.SymPtrOff(lsym, ot, tsym)
  1379  		// Plugin exports symbols as interfaces. Mark their types
  1380  		// as UsedInIface.
  1381  		tsym.Set(obj.AttrUsedInIface, true)
  1382  	}
  1383  	objw.Global(lsym, int32(ot), int16(obj.RODATA))
  1384  
  1385  	lsym = base.Ctxt.Lookup("go:plugin.exports")
  1386  	ot = 0
  1387  	for _, p := range ptabs {
  1388  		ot = objw.SymPtr(lsym, ot, p.Linksym(), 0)
  1389  	}
  1390  	objw.Global(lsym, int32(ot), int16(obj.RODATA))
  1391  }
  1392  
  1393  // writtenByWriteBasicTypes reports whether typ is written by WriteBasicTypes.
  1394  // WriteBasicTypes always writes pointer types; any pointer has been stripped off typ already.
  1395  func writtenByWriteBasicTypes(typ *types.Type) bool {
  1396  	if typ.Sym() == nil && typ.Kind() == types.TFUNC {
  1397  		// func(error) string
  1398  		if typ.NumRecvs() == 0 &&
  1399  			typ.NumParams() == 1 && typ.NumResults() == 1 &&
  1400  			typ.Param(0).Type == types.ErrorType &&
  1401  			typ.Result(0).Type == types.Types[types.TSTRING] {
  1402  			return true
  1403  		}
  1404  	}
  1405  
  1406  	// Now we have left the basic types plus any and error, plus slices of them.
  1407  	// Strip the slice.
  1408  	if typ.Sym() == nil && typ.IsSlice() {
  1409  		typ = typ.Elem()
  1410  	}
  1411  
  1412  	// Basic types.
  1413  	sym := typ.Sym()
  1414  	if sym != nil && (sym.Pkg == types.BuiltinPkg || sym.Pkg == types.UnsafePkg) {
  1415  		return true
  1416  	}
  1417  	// any or error
  1418  	return (sym == nil && typ.IsEmptyInterface()) || typ == types.ErrorType
  1419  }
  1420  
  1421  func WriteBasicTypes() {
  1422  	// do basic types if compiling package runtime.
  1423  	// they have to be in at least one package,
  1424  	// and runtime is always loaded implicitly,
  1425  	// so this is as good as any.
  1426  	// another possible choice would be package main,
  1427  	// but using runtime means fewer copies in object files.
  1428  	// The code here needs to be in sync with writtenByWriteBasicTypes above.
  1429  	if base.Ctxt.Pkgpath != "runtime" {
  1430  		return
  1431  	}
  1432  
  1433  	// Note: always write NewPtr(t) because NeedEmit's caller strips the pointer.
  1434  	var list []*types.Type
  1435  	for i := types.Kind(1); i <= types.TBOOL; i++ {
  1436  		list = append(list, types.Types[i])
  1437  	}
  1438  	list = append(list,
  1439  		types.Types[types.TSTRING],
  1440  		types.Types[types.TUNSAFEPTR],
  1441  		types.AnyType,
  1442  		types.ErrorType)
  1443  	for _, t := range list {
  1444  		writeType(types.NewPtr(t))
  1445  		writeType(types.NewPtr(types.NewSlice(t)))
  1446  	}
  1447  
  1448  	// emit type for func(error) string,
  1449  	// which is the type of an auto-generated wrapper.
  1450  	writeType(types.NewPtr(types.NewSignature(nil, []*types.Field{
  1451  		types.NewField(base.Pos, nil, types.ErrorType),
  1452  	}, []*types.Field{
  1453  		types.NewField(base.Pos, nil, types.Types[types.TSTRING]),
  1454  	})))
  1455  }
  1456  
  1457  type typeAndStr struct {
  1458  	t       *types.Type
  1459  	short   string // "short" here means TypeSymName
  1460  	regular string
  1461  }
  1462  
  1463  type typesByString []typeAndStr
  1464  
  1465  func (a typesByString) Len() int { return len(a) }
  1466  func (a typesByString) Less(i, j int) bool {
  1467  	// put named types before unnamed types
  1468  	if a[i].t.Sym() != nil && a[j].t.Sym() == nil {
  1469  		return true
  1470  	}
  1471  	if a[i].t.Sym() == nil && a[j].t.Sym() != nil {
  1472  		return false
  1473  	}
  1474  
  1475  	if a[i].short != a[j].short {
  1476  		return a[i].short < a[j].short
  1477  	}
  1478  	// When the only difference between the types is whether
  1479  	// they refer to byte or uint8, such as **byte vs **uint8,
  1480  	// the types' NameStrings can be identical.
  1481  	// To preserve deterministic sort ordering, sort these by String().
  1482  	//
  1483  	// TODO(mdempsky): This all seems suspect. Using LinkString would
  1484  	// avoid naming collisions, and there shouldn't be a reason to care
  1485  	// about "byte" vs "uint8": they share the same runtime type
  1486  	// descriptor anyway.
  1487  	if a[i].regular != a[j].regular {
  1488  		return a[i].regular < a[j].regular
  1489  	}
  1490  	// Identical anonymous interfaces defined in different locations
  1491  	// will be equal for the above checks, but different in DWARF output.
  1492  	// Sort by source position to ensure deterministic order.
  1493  	// See issues 27013 and 30202.
  1494  	if a[i].t.Kind() == types.TINTER && len(a[i].t.AllMethods()) > 0 {
  1495  		return a[i].t.AllMethods()[0].Pos.Before(a[j].t.AllMethods()[0].Pos)
  1496  	}
  1497  	return false
  1498  }
  1499  func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  1500  
  1501  // GCSym returns a data symbol containing GC information for type t, along
  1502  // with a boolean reporting whether the UseGCProg bit should be set in the
  1503  // type kind, and the ptrdata field to record in the reflect type information.
  1504  // GCSym may be called in concurrent backend, so it does not emit the symbol
  1505  // content.
  1506  func GCSym(t *types.Type) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
  1507  	// Record that we need to emit the GC symbol.
  1508  	gcsymmu.Lock()
  1509  	if _, ok := gcsymset[t]; !ok {
  1510  		gcsymset[t] = struct{}{}
  1511  	}
  1512  	gcsymmu.Unlock()
  1513  
  1514  	return dgcsym(t, false)
  1515  }
  1516  
  1517  // dgcsym returns a data symbol containing GC information for type t, along
  1518  // with a boolean reporting whether the UseGCProg bit should be set in the
  1519  // type kind, and the ptrdata field to record in the reflect type information.
  1520  // When write is true, it writes the symbol data.
  1521  func dgcsym(t *types.Type, write bool) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
  1522  	ptrdata = types.PtrDataSize(t)
  1523  	if ptrdata/int64(types.PtrSize) <= abi.MaxPtrmaskBytes*8 {
  1524  		lsym = dgcptrmask(t, write)
  1525  		return
  1526  	}
  1527  
  1528  	useGCProg = true
  1529  	lsym, ptrdata = dgcprog(t, write)
  1530  	return
  1531  }
  1532  
  1533  // dgcptrmask emits and returns the symbol containing a pointer mask for type t.
  1534  func dgcptrmask(t *types.Type, write bool) *obj.LSym {
  1535  	// Bytes we need for the ptrmask.
  1536  	n := (types.PtrDataSize(t)/int64(types.PtrSize) + 7) / 8
  1537  	// Runtime wants ptrmasks padded to a multiple of uintptr in size.
  1538  	n = (n + int64(types.PtrSize) - 1) &^ (int64(types.PtrSize) - 1)
  1539  	ptrmask := make([]byte, n)
  1540  	fillptrmask(t, ptrmask)
  1541  	p := fmt.Sprintf("runtime.gcbits.%x", ptrmask)
  1542  
  1543  	lsym := base.Ctxt.Lookup(p)
  1544  	if write && !lsym.OnList() {
  1545  		for i, x := range ptrmask {
  1546  			objw.Uint8(lsym, i, x)
  1547  		}
  1548  		objw.Global(lsym, int32(len(ptrmask)), obj.DUPOK|obj.RODATA|obj.LOCAL)
  1549  		lsym.Set(obj.AttrContentAddressable, true)
  1550  	}
  1551  	return lsym
  1552  }
  1553  
  1554  // fillptrmask fills in ptrmask with 1s corresponding to the
  1555  // word offsets in t that hold pointers.
  1556  // ptrmask is assumed to fit at least types.PtrDataSize(t)/PtrSize bits.
  1557  func fillptrmask(t *types.Type, ptrmask []byte) {
  1558  	for i := range ptrmask {
  1559  		ptrmask[i] = 0
  1560  	}
  1561  	if !t.HasPointers() {
  1562  		return
  1563  	}
  1564  
  1565  	vec := bitvec.New(8 * int32(len(ptrmask)))
  1566  	typebits.Set(t, 0, vec)
  1567  
  1568  	nptr := types.PtrDataSize(t) / int64(types.PtrSize)
  1569  	for i := int64(0); i < nptr; i++ {
  1570  		if vec.Get(int32(i)) {
  1571  			ptrmask[i/8] |= 1 << (uint(i) % 8)
  1572  		}
  1573  	}
  1574  }
  1575  
  1576  // dgcprog emits and returns the symbol containing a GC program for type t
  1577  // along with the size of the data described by the program (in the range
  1578  // [types.PtrDataSize(t), t.Width]).
  1579  // In practice, the size is types.PtrDataSize(t) except for non-trivial arrays.
  1580  // For non-trivial arrays, the program describes the full t.Width size.
  1581  func dgcprog(t *types.Type, write bool) (*obj.LSym, int64) {
  1582  	types.CalcSize(t)
  1583  	if t.Size() == types.BADWIDTH {
  1584  		base.Fatalf("dgcprog: %v badwidth", t)
  1585  	}
  1586  	lsym := TypeLinksymPrefix(".gcprog", t)
  1587  	var p gcProg
  1588  	p.init(lsym, write)
  1589  	p.emit(t, 0)
  1590  	offset := p.w.BitIndex() * int64(types.PtrSize)
  1591  	p.end()
  1592  	if ptrdata := types.PtrDataSize(t); offset < ptrdata || offset > t.Size() {
  1593  		base.Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Size())
  1594  	}
  1595  	return lsym, offset
  1596  }
  1597  
  1598  type gcProg struct {
  1599  	lsym   *obj.LSym
  1600  	symoff int
  1601  	w      gcprog.Writer
  1602  	write  bool
  1603  }
  1604  
  1605  func (p *gcProg) init(lsym *obj.LSym, write bool) {
  1606  	p.lsym = lsym
  1607  	p.write = write && !lsym.OnList()
  1608  	p.symoff = 4 // first 4 bytes hold program length
  1609  	if !write {
  1610  		p.w.Init(func(byte) {})
  1611  		return
  1612  	}
  1613  	p.w.Init(p.writeByte)
  1614  	if base.Debug.GCProg > 0 {
  1615  		fmt.Fprintf(os.Stderr, "compile: start GCProg for %v\n", lsym)
  1616  		p.w.Debug(os.Stderr)
  1617  	}
  1618  }
  1619  
  1620  func (p *gcProg) writeByte(x byte) {
  1621  	p.symoff = objw.Uint8(p.lsym, p.symoff, x)
  1622  }
  1623  
  1624  func (p *gcProg) end() {
  1625  	p.w.End()
  1626  	if !p.write {
  1627  		return
  1628  	}
  1629  	objw.Uint32(p.lsym, 0, uint32(p.symoff-4))
  1630  	objw.Global(p.lsym, int32(p.symoff), obj.DUPOK|obj.RODATA|obj.LOCAL)
  1631  	p.lsym.Set(obj.AttrContentAddressable, true)
  1632  	if base.Debug.GCProg > 0 {
  1633  		fmt.Fprintf(os.Stderr, "compile: end GCProg for %v\n", p.lsym)
  1634  	}
  1635  }
  1636  
  1637  func (p *gcProg) emit(t *types.Type, offset int64) {
  1638  	types.CalcSize(t)
  1639  	if !t.HasPointers() {
  1640  		return
  1641  	}
  1642  	if t.Size() == int64(types.PtrSize) {
  1643  		p.w.Ptr(offset / int64(types.PtrSize))
  1644  		return
  1645  	}
  1646  	switch t.Kind() {
  1647  	default:
  1648  		base.Fatalf("gcProg.emit: unexpected type %v", t)
  1649  
  1650  	case types.TSTRING:
  1651  		p.w.Ptr(offset / int64(types.PtrSize))
  1652  
  1653  	case types.TINTER:
  1654  		// Note: the first word isn't a pointer. See comment in typebits.Set
  1655  		p.w.Ptr(offset/int64(types.PtrSize) + 1)
  1656  
  1657  	case types.TSLICE:
  1658  		p.w.Ptr(offset / int64(types.PtrSize))
  1659  
  1660  	case types.TARRAY:
  1661  		if t.NumElem() == 0 {
  1662  			// should have been handled by haspointers check above
  1663  			base.Fatalf("gcProg.emit: empty array")
  1664  		}
  1665  
  1666  		// Flatten array-of-array-of-array to just a big array by multiplying counts.
  1667  		count := t.NumElem()
  1668  		elem := t.Elem()
  1669  		for elem.IsArray() {
  1670  			count *= elem.NumElem()
  1671  			elem = elem.Elem()
  1672  		}
  1673  
  1674  		if !p.w.ShouldRepeat(elem.Size()/int64(types.PtrSize), count) {
  1675  			// Cheaper to just emit the bits.
  1676  			for i := int64(0); i < count; i++ {
  1677  				p.emit(elem, offset+i*elem.Size())
  1678  			}
  1679  			return
  1680  		}
  1681  		p.emit(elem, offset)
  1682  		p.w.ZeroUntil((offset + elem.Size()) / int64(types.PtrSize))
  1683  		p.w.Repeat(elem.Size()/int64(types.PtrSize), count-1)
  1684  
  1685  	case types.TSTRUCT:
  1686  		for _, t1 := range t.Fields() {
  1687  			p.emit(t1.Type, offset+t1.Offset)
  1688  		}
  1689  	}
  1690  }
  1691  
  1692  // ZeroAddr returns the address of a symbol with at least
  1693  // size bytes of zeros.
  1694  func ZeroAddr(size int64) ir.Node {
  1695  	if size >= 1<<31 {
  1696  		base.Fatalf("map elem too big %d", size)
  1697  	}
  1698  	if ZeroSize < size {
  1699  		ZeroSize = size
  1700  	}
  1701  	lsym := base.PkgLinksym("go:map", "zero", obj.ABI0)
  1702  	x := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8])
  1703  	return typecheck.Expr(typecheck.NodAddr(x))
  1704  }
  1705  
  1706  // NeedEmit reports whether typ is a type that we need to emit code
  1707  // for (e.g., runtime type descriptors, method wrappers).
  1708  func NeedEmit(typ *types.Type) bool {
  1709  	// TODO(mdempsky): Export data should keep track of which anonymous
  1710  	// and instantiated types were emitted, so at least downstream
  1711  	// packages can skip re-emitting them.
  1712  	//
  1713  	// Perhaps we can just generalize the linker-symbol indexing to
  1714  	// track the index of arbitrary types, not just defined types, and
  1715  	// use its presence to detect this. The same idea would work for
  1716  	// instantiated generic functions too.
  1717  
  1718  	switch sym := typ.Sym(); {
  1719  	case writtenByWriteBasicTypes(typ):
  1720  		return base.Ctxt.Pkgpath == "runtime"
  1721  
  1722  	case sym == nil:
  1723  		// Anonymous type; possibly never seen before or ever again.
  1724  		// Need to emit to be safe (however, see TODO above).
  1725  		return true
  1726  
  1727  	case sym.Pkg == types.LocalPkg:
  1728  		// Local defined type; our responsibility.
  1729  		return true
  1730  
  1731  	case typ.IsFullyInstantiated():
  1732  		// Instantiated type; possibly instantiated with unique type arguments.
  1733  		// Need to emit to be safe (however, see TODO above).
  1734  		return true
  1735  
  1736  	case typ.HasShape():
  1737  		// Shape type; need to emit even though it lives in the .shape package.
  1738  		// TODO: make sure the linker deduplicates them (see dupok in writeType above).
  1739  		return true
  1740  
  1741  	default:
  1742  		// Should have been emitted by an imported package.
  1743  		return false
  1744  	}
  1745  }
  1746  
  1747  // Generate a wrapper function to convert from
  1748  // a receiver of type T to a receiver of type U.
  1749  // That is,
  1750  //
  1751  //	func (t T) M() {
  1752  //		...
  1753  //	}
  1754  //
  1755  // already exists; this function generates
  1756  //
  1757  //	func (u U) M() {
  1758  //		u.M()
  1759  //	}
  1760  //
  1761  // where the types T and U are such that u.M() is valid
  1762  // and calls the T.M method.
  1763  // The resulting function is for use in method tables.
  1764  //
  1765  //	rcvr - U
  1766  //	method - M func (t T)(), a TFIELD type struct
  1767  //
  1768  // Also wraps methods on instantiated generic types for use in itab entries.
  1769  // For an instantiated generic type G[int], we generate wrappers like:
  1770  // G[int] pointer shaped:
  1771  //
  1772  //	func (x G[int]) f(arg) {
  1773  //		.inst.G[int].f(dictionary, x, arg)
  1774  //	}
  1775  //
  1776  // G[int] not pointer shaped:
  1777  //
  1778  //	func (x *G[int]) f(arg) {
  1779  //		.inst.G[int].f(dictionary, *x, arg)
  1780  //	}
  1781  //
  1782  // These wrappers are always fully stenciled.
  1783  func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSym {
  1784  	if forItab && !types.IsDirectIface(rcvr) {
  1785  		rcvr = rcvr.PtrTo()
  1786  	}
  1787  
  1788  	newnam := ir.MethodSym(rcvr, method.Sym)
  1789  	lsym := newnam.Linksym()
  1790  
  1791  	// Unified IR creates its own wrappers.
  1792  	return lsym
  1793  }
  1794  
  1795  var ZeroSize int64
  1796  
  1797  // MarkTypeUsedInInterface marks that type t is converted to an interface.
  1798  // This information is used in the linker in dead method elimination.
  1799  func MarkTypeUsedInInterface(t *types.Type, from *obj.LSym) {
  1800  	if t.HasShape() {
  1801  		// Shape types shouldn't be put in interfaces, so we shouldn't ever get here.
  1802  		base.Fatalf("shape types have no methods %+v", t)
  1803  	}
  1804  	MarkTypeSymUsedInInterface(TypeLinksym(t), from)
  1805  }
  1806  func MarkTypeSymUsedInInterface(tsym *obj.LSym, from *obj.LSym) {
  1807  	// Emit a marker relocation. The linker will know the type is converted
  1808  	// to an interface if "from" is reachable.
  1809  	r := obj.Addrel(from)
  1810  	r.Sym = tsym
  1811  	r.Type = objabi.R_USEIFACE
  1812  }
  1813  
  1814  // MarkUsedIfaceMethod marks that an interface method is used in the current
  1815  // function. n is OCALLINTER node.
  1816  func MarkUsedIfaceMethod(n *ir.CallExpr) {
  1817  	// skip unnamed functions (func _())
  1818  	if ir.CurFunc.LSym == nil {
  1819  		return
  1820  	}
  1821  	dot := n.Fun.(*ir.SelectorExpr)
  1822  	ityp := dot.X.Type()
  1823  	if ityp.HasShape() {
  1824  		// Here we're calling a method on a generic interface. Something like:
  1825  		//
  1826  		// type I[T any] interface { foo() T }
  1827  		// func f[T any](x I[T]) {
  1828  		//     ... = x.foo()
  1829  		// }
  1830  		// f[int](...)
  1831  		// f[string](...)
  1832  		//
  1833  		// In this case, in f we're calling foo on a generic interface.
  1834  		// Which method could that be? Normally we could match the method
  1835  		// both by name and by type. But in this case we don't really know
  1836  		// the type of the method we're calling. It could be func()int
  1837  		// or func()string. So we match on just the function name, instead
  1838  		// of both the name and the type used for the non-generic case below.
  1839  		// TODO: instantiations at least know the shape of the instantiated
  1840  		// type, and the linker could do more complicated matching using
  1841  		// some sort of fuzzy shape matching. For now, only use the name
  1842  		// of the method for matching.
  1843  		r := obj.Addrel(ir.CurFunc.LSym)
  1844  		r.Sym = staticdata.StringSymNoCommon(dot.Sel.Name)
  1845  		r.Type = objabi.R_USENAMEDMETHOD
  1846  		return
  1847  	}
  1848  
  1849  	tsym := TypeLinksym(ityp)
  1850  	r := obj.Addrel(ir.CurFunc.LSym)
  1851  	r.Sym = tsym
  1852  	// dot.Offset() is the method index * PtrSize (the offset of code pointer
  1853  	// in itab).
  1854  	midx := dot.Offset() / int64(types.PtrSize)
  1855  	r.Add = InterfaceMethodOffset(ityp, midx)
  1856  	r.Type = objabi.R_USEIFACEMETHOD
  1857  }
  1858  
  1859  func deref(t *types.Type) *types.Type {
  1860  	if t.IsPtr() {
  1861  		return t.Elem()
  1862  	}
  1863  	return t
  1864  }
  1865  

View as plain text