...

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

View as plain text