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