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