1
2
3
4
5 package reflectdata
6
7 import (
8 "encoding/binary"
9 "fmt"
10 "internal/abi"
11 "os"
12 "sort"
13 "strings"
14 "sync"
15
16 "cmd/compile/internal/base"
17 "cmd/compile/internal/bitvec"
18 "cmd/compile/internal/compare"
19 "cmd/compile/internal/ir"
20 "cmd/compile/internal/objw"
21 "cmd/compile/internal/rttype"
22 "cmd/compile/internal/staticdata"
23 "cmd/compile/internal/typebits"
24 "cmd/compile/internal/typecheck"
25 "cmd/compile/internal/types"
26 "cmd/internal/gcprog"
27 "cmd/internal/obj"
28 "cmd/internal/objabi"
29 "cmd/internal/src"
30 )
31
32 type ptabEntry struct {
33 s *types.Sym
34 t *types.Type
35 }
36
37
38 var (
39
40 signatmu sync.Mutex
41
42 signatset = make(map[*types.Type]struct{})
43
44 signatslice []typeAndStr
45
46 gcsymmu sync.Mutex
47 gcsymset = make(map[*types.Type]struct{})
48 )
49
50 type typeSig struct {
51 name *types.Sym
52 isym *obj.LSym
53 tsym *obj.LSym
54 type_ *types.Type
55 mtype *types.Type
56 }
57
58
59
60
61
62
63
64
65
66
67
68
69
70 const (
71 BUCKETSIZE = abi.MapBucketCount
72 MAXKEYSIZE = abi.MapMaxKeyBytes
73 MAXELEMSIZE = abi.MapMaxElemBytes
74 )
75
76 func commonSize() int { return int(rttype.Type.Size()) }
77
78 func uncommonSize(t *types.Type) int {
79 if t.Sym() == nil && len(methods(t)) == 0 {
80 return 0
81 }
82 return int(rttype.UncommonType.Size())
83 }
84
85 func makefield(name string, t *types.Type) *types.Field {
86 sym := (*types.Pkg)(nil).Lookup(name)
87 return types.NewField(src.NoXPos, sym, t)
88 }
89
90
91 func MapBucketType(t *types.Type) *types.Type {
92 if t.MapType().Bucket != nil {
93 return t.MapType().Bucket
94 }
95
96 keytype := t.Key()
97 elemtype := t.Elem()
98 types.CalcSize(keytype)
99 types.CalcSize(elemtype)
100 if keytype.Size() > MAXKEYSIZE {
101 keytype = types.NewPtr(keytype)
102 }
103 if elemtype.Size() > MAXELEMSIZE {
104 elemtype = types.NewPtr(elemtype)
105 }
106
107 field := make([]*types.Field, 0, 5)
108
109
110 arr := types.NewArray(types.Types[types.TUINT8], BUCKETSIZE)
111 field = append(field, makefield("topbits", arr))
112
113 arr = types.NewArray(keytype, BUCKETSIZE)
114 arr.SetNoalg(true)
115 keys := makefield("keys", arr)
116 field = append(field, keys)
117
118 arr = types.NewArray(elemtype, BUCKETSIZE)
119 arr.SetNoalg(true)
120 elems := makefield("elems", arr)
121 field = append(field, elems)
122
123
124
125
126
127
128
129 otyp := types.Types[types.TUNSAFEPTR]
130 if !elemtype.HasPointers() && !keytype.HasPointers() {
131 otyp = types.Types[types.TUINTPTR]
132 }
133 overflow := makefield("overflow", otyp)
134 field = append(field, overflow)
135
136
137 bucket := types.NewStruct(field[:])
138 bucket.SetNoalg(true)
139 types.CalcSize(bucket)
140
141
142 if !types.IsComparable(t.Key()) {
143 base.Fatalf("unsupported map key type for %v", t)
144 }
145 if BUCKETSIZE < 8 {
146 base.Fatalf("bucket size %d too small for proper alignment %d", BUCKETSIZE, 8)
147 }
148 if uint8(keytype.Alignment()) > BUCKETSIZE {
149 base.Fatalf("key align too big for %v", t)
150 }
151 if uint8(elemtype.Alignment()) > BUCKETSIZE {
152 base.Fatalf("elem align %d too big for %v, BUCKETSIZE=%d", elemtype.Alignment(), t, BUCKETSIZE)
153 }
154 if keytype.Size() > MAXKEYSIZE {
155 base.Fatalf("key size too large for %v", t)
156 }
157 if elemtype.Size() > MAXELEMSIZE {
158 base.Fatalf("elem size too large for %v", t)
159 }
160 if t.Key().Size() > MAXKEYSIZE && !keytype.IsPtr() {
161 base.Fatalf("key indirect incorrect for %v", t)
162 }
163 if t.Elem().Size() > MAXELEMSIZE && !elemtype.IsPtr() {
164 base.Fatalf("elem indirect incorrect for %v", t)
165 }
166 if keytype.Size()%keytype.Alignment() != 0 {
167 base.Fatalf("key size not a multiple of key align for %v", t)
168 }
169 if elemtype.Size()%elemtype.Alignment() != 0 {
170 base.Fatalf("elem size not a multiple of elem align for %v", t)
171 }
172 if uint8(bucket.Alignment())%uint8(keytype.Alignment()) != 0 {
173 base.Fatalf("bucket align not multiple of key align %v", t)
174 }
175 if uint8(bucket.Alignment())%uint8(elemtype.Alignment()) != 0 {
176 base.Fatalf("bucket align not multiple of elem align %v", t)
177 }
178 if keys.Offset%keytype.Alignment() != 0 {
179 base.Fatalf("bad alignment of keys in bmap for %v", t)
180 }
181 if elems.Offset%elemtype.Alignment() != 0 {
182 base.Fatalf("bad alignment of elems in bmap for %v", t)
183 }
184
185
186
187 if overflow.Offset != bucket.Size()-int64(types.PtrSize) {
188 base.Fatalf("bad offset of overflow in bmap for %v, overflow.Offset=%d, bucket.Size()-int64(types.PtrSize)=%d",
189 t, overflow.Offset, bucket.Size()-int64(types.PtrSize))
190 }
191
192 t.MapType().Bucket = bucket
193
194 bucket.StructType().Map = t
195 return bucket
196 }
197
198 var hmapType *types.Type
199
200
201
202 func MapType() *types.Type {
203 if hmapType != nil {
204 return hmapType
205 }
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220 fields := []*types.Field{
221 makefield("count", types.Types[types.TINT]),
222 makefield("flags", types.Types[types.TUINT8]),
223 makefield("B", types.Types[types.TUINT8]),
224 makefield("noverflow", types.Types[types.TUINT16]),
225 makefield("hash0", types.Types[types.TUINT32]),
226 makefield("buckets", types.Types[types.TUNSAFEPTR]),
227 makefield("oldbuckets", types.Types[types.TUNSAFEPTR]),
228 makefield("nevacuate", types.Types[types.TUINTPTR]),
229 makefield("extra", types.Types[types.TUNSAFEPTR]),
230 }
231
232 n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, ir.Pkgs.Runtime.Lookup("hmap"))
233 hmap := types.NewNamed(n)
234 n.SetType(hmap)
235 n.SetTypecheck(1)
236
237 hmap.SetUnderlying(types.NewStruct(fields))
238 types.CalcSize(hmap)
239
240
241
242 if size := int64(8 + 5*types.PtrSize); hmap.Size() != size {
243 base.Fatalf("hmap size not correct: got %d, want %d", hmap.Size(), size)
244 }
245
246 hmapType = hmap
247 return hmap
248 }
249
250 var hiterType *types.Type
251
252
253
254 func MapIterType() *types.Type {
255 if hiterType != nil {
256 return hiterType
257 }
258
259 hmap := MapType()
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280 fields := []*types.Field{
281 makefield("key", types.Types[types.TUNSAFEPTR]),
282 makefield("elem", types.Types[types.TUNSAFEPTR]),
283 makefield("t", types.Types[types.TUNSAFEPTR]),
284 makefield("h", types.NewPtr(hmap)),
285 makefield("buckets", types.Types[types.TUNSAFEPTR]),
286 makefield("bptr", types.Types[types.TUNSAFEPTR]),
287 makefield("overflow", types.Types[types.TUNSAFEPTR]),
288 makefield("oldoverflow", types.Types[types.TUNSAFEPTR]),
289 makefield("startBucket", types.Types[types.TUINTPTR]),
290 makefield("offset", types.Types[types.TUINT8]),
291 makefield("wrapped", types.Types[types.TBOOL]),
292 makefield("B", types.Types[types.TUINT8]),
293 makefield("i", types.Types[types.TUINT8]),
294 makefield("bucket", types.Types[types.TUINTPTR]),
295 makefield("checkBucket", types.Types[types.TUINTPTR]),
296 }
297
298
299 n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, ir.Pkgs.Runtime.Lookup("hiter"))
300 hiter := types.NewNamed(n)
301 n.SetType(hiter)
302 n.SetTypecheck(1)
303
304 hiter.SetUnderlying(types.NewStruct(fields))
305 types.CalcSize(hiter)
306 if hiter.Size() != int64(12*types.PtrSize) {
307 base.Fatalf("hash_iter size not correct %d %d", hiter.Size(), 12*types.PtrSize)
308 }
309
310 hiterType = hiter
311 return hiter
312 }
313
314
315
316 func methods(t *types.Type) []*typeSig {
317 if t.HasShape() {
318
319 return nil
320 }
321
322 mt := types.ReceiverBaseType(t)
323
324 if mt == nil {
325 return nil
326 }
327 typecheck.CalcMethods(mt)
328
329
330
331 var ms []*typeSig
332 for _, f := range mt.AllMethods() {
333 if f.Sym == nil {
334 base.Fatalf("method with no sym on %v", mt)
335 }
336 if !f.IsMethod() {
337 base.Fatalf("non-method on %v method %v %v", mt, f.Sym, f)
338 }
339 if f.Type.Recv() == nil {
340 base.Fatalf("receiver with no type on %v method %v %v", mt, f.Sym, f)
341 }
342 if f.Nointerface() && !t.IsFullyInstantiated() {
343
344
345
346
347 continue
348 }
349
350
351
352
353
354 if !types.IsMethodApplicable(t, f) {
355 continue
356 }
357
358 sig := &typeSig{
359 name: f.Sym,
360 isym: methodWrapper(t, f, true),
361 tsym: methodWrapper(t, f, false),
362 type_: typecheck.NewMethodType(f.Type, t),
363 mtype: typecheck.NewMethodType(f.Type, nil),
364 }
365 if f.Nointerface() {
366
367
368 continue
369 }
370 ms = append(ms, sig)
371 }
372
373 return ms
374 }
375
376
377 func imethods(t *types.Type) []*typeSig {
378 var methods []*typeSig
379 for _, f := range t.AllMethods() {
380 if f.Type.Kind() != types.TFUNC || f.Sym == nil {
381 continue
382 }
383 if f.Sym.IsBlank() {
384 base.Fatalf("unexpected blank symbol in interface method set")
385 }
386 if n := len(methods); n > 0 {
387 last := methods[n-1]
388 if !last.name.Less(f.Sym) {
389 base.Fatalf("sigcmp vs sortinter %v %v", last.name, f.Sym)
390 }
391 }
392
393 sig := &typeSig{
394 name: f.Sym,
395 mtype: f.Type,
396 type_: typecheck.NewMethodType(f.Type, nil),
397 }
398 methods = append(methods, sig)
399
400
401
402
403
404 methodWrapper(t, f, false)
405 }
406
407 return methods
408 }
409
410 func dimportpath(p *types.Pkg) {
411 if p.Pathsym != nil {
412 return
413 }
414
415 if p == types.LocalPkg && base.Ctxt.Pkgpath == "" {
416 panic("missing pkgpath")
417 }
418
419
420
421
422 if base.Ctxt.Pkgpath == "runtime" && p == ir.Pkgs.Runtime {
423 return
424 }
425
426 s := base.Ctxt.Lookup("type:.importpath." + p.Prefix + ".")
427 ot := dnameData(s, 0, p.Path, "", nil, false, false)
428 objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
429 s.Set(obj.AttrContentAddressable, true)
430 p.Pathsym = s
431 }
432
433 func dgopkgpath(c rttype.Cursor, pkg *types.Pkg) {
434 c = c.Field("Bytes")
435 if pkg == nil {
436 c.WritePtr(nil)
437 return
438 }
439
440 dimportpath(pkg)
441 c.WritePtr(pkg.Pathsym)
442 }
443
444
445 func dgopkgpathOff(c rttype.Cursor, pkg *types.Pkg) {
446 if pkg == nil {
447 c.WriteInt32(0)
448 return
449 }
450
451 dimportpath(pkg)
452 c.WriteSymPtrOff(pkg.Pathsym, false)
453 }
454
455
456 func dnameField(c rttype.Cursor, spkg *types.Pkg, ft *types.Field) {
457 if !types.IsExported(ft.Sym.Name) && ft.Sym.Pkg != spkg {
458 base.Fatalf("package mismatch for %v", ft.Sym)
459 }
460 nsym := dname(ft.Sym.Name, ft.Note, nil, types.IsExported(ft.Sym.Name), ft.Embedded != 0)
461 c.Field("Bytes").WritePtr(nsym)
462 }
463
464
465 func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported, embedded bool) int {
466 if len(name) >= 1<<29 {
467 base.Fatalf("name too long: %d %s...", len(name), name[:1024])
468 }
469 if len(tag) >= 1<<29 {
470 base.Fatalf("tag too long: %d %s...", len(tag), tag[:1024])
471 }
472 var nameLen [binary.MaxVarintLen64]byte
473 nameLenLen := binary.PutUvarint(nameLen[:], uint64(len(name)))
474 var tagLen [binary.MaxVarintLen64]byte
475 tagLenLen := binary.PutUvarint(tagLen[:], uint64(len(tag)))
476
477
478 var bits byte
479 l := 1 + nameLenLen + len(name)
480 if exported {
481 bits |= 1 << 0
482 }
483 if len(tag) > 0 {
484 l += tagLenLen + len(tag)
485 bits |= 1 << 1
486 }
487 if pkg != nil {
488 bits |= 1 << 2
489 }
490 if embedded {
491 bits |= 1 << 3
492 }
493 b := make([]byte, l)
494 b[0] = bits
495 copy(b[1:], nameLen[:nameLenLen])
496 copy(b[1+nameLenLen:], name)
497 if len(tag) > 0 {
498 tb := b[1+nameLenLen+len(name):]
499 copy(tb, tagLen[:tagLenLen])
500 copy(tb[tagLenLen:], tag)
501 }
502
503 ot = int(s.WriteBytes(base.Ctxt, int64(ot), b))
504
505 if pkg != nil {
506 c := rttype.NewCursor(s, int64(ot), types.Types[types.TUINT32])
507 dgopkgpathOff(c, pkg)
508 ot += 4
509 }
510
511 return ot
512 }
513
514 var dnameCount int
515
516
517 func dname(name, tag string, pkg *types.Pkg, exported, embedded bool) *obj.LSym {
518
519
520
521
522 sname := "type:.namedata."
523 if pkg == nil {
524
525 if name == "" {
526 if exported {
527 sname += "-noname-exported." + tag
528 } else {
529 sname += "-noname-unexported." + tag
530 }
531 } else {
532 if exported {
533 sname += name + "." + tag
534 } else {
535 sname += name + "-" + tag
536 }
537 }
538 } else {
539
540
541 sname = fmt.Sprintf("%s%s.%d", sname, types.LocalPkg.Prefix, dnameCount)
542 dnameCount++
543 }
544 if embedded {
545 sname += ".embedded"
546 }
547 s := base.Ctxt.Lookup(sname)
548 if len(s.P) > 0 {
549 return s
550 }
551 ot := dnameData(s, 0, name, tag, pkg, exported, embedded)
552 objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
553 s.Set(obj.AttrContentAddressable, true)
554 return s
555 }
556
557
558
559
560 func dextratype(lsym *obj.LSym, off int64, t *types.Type, dataAdd int) {
561 m := methods(t)
562 if t.Sym() == nil && len(m) == 0 {
563 base.Fatalf("extra requested of type with no extra info %v", t)
564 }
565 noff := types.RoundUp(off, int64(types.PtrSize))
566 if noff != off {
567 base.Fatalf("unexpected alignment in dextratype for %v", t)
568 }
569
570 for _, a := range m {
571 writeType(a.type_)
572 }
573
574 c := rttype.NewCursor(lsym, off, rttype.UncommonType)
575 dgopkgpathOff(c.Field("PkgPath"), typePkg(t))
576
577 dataAdd += uncommonSize(t)
578 mcount := len(m)
579 if mcount != int(uint16(mcount)) {
580 base.Fatalf("too many methods on %v: %d", t, mcount)
581 }
582 xcount := sort.Search(mcount, func(i int) bool { return !types.IsExported(m[i].name.Name) })
583 if dataAdd != int(uint32(dataAdd)) {
584 base.Fatalf("methods are too far away on %v: %d", t, dataAdd)
585 }
586
587 c.Field("Mcount").WriteUint16(uint16(mcount))
588 c.Field("Xcount").WriteUint16(uint16(xcount))
589 c.Field("Moff").WriteUint32(uint32(dataAdd))
590
591
592
593 array := rttype.NewArrayCursor(lsym, off+int64(dataAdd), rttype.Method, mcount)
594 for i, a := range m {
595 exported := types.IsExported(a.name.Name)
596 var pkg *types.Pkg
597 if !exported && a.name.Pkg != typePkg(t) {
598 pkg = a.name.Pkg
599 }
600 nsym := dname(a.name.Name, "", pkg, exported, false)
601
602 e := array.Elem(i)
603 e.Field("Name").WriteSymPtrOff(nsym, false)
604 dmethodptrOff(e.Field("Mtyp"), writeType(a.mtype))
605 dmethodptrOff(e.Field("Ifn"), a.isym)
606 dmethodptrOff(e.Field("Tfn"), a.tsym)
607 }
608 }
609
610 func typePkg(t *types.Type) *types.Pkg {
611 tsym := t.Sym()
612 if tsym == nil {
613 switch t.Kind() {
614 case types.TARRAY, types.TSLICE, types.TPTR, types.TCHAN:
615 if t.Elem() != nil {
616 tsym = t.Elem().Sym()
617 }
618 }
619 }
620 if tsym != nil && tsym.Pkg != types.BuiltinPkg {
621 return tsym.Pkg
622 }
623 return nil
624 }
625
626 func dmethodptrOff(c rttype.Cursor, x *obj.LSym) {
627 c.WriteInt32(0)
628 r := c.Reloc()
629 r.Sym = x
630 r.Type = objabi.R_METHODOFF
631 }
632
633 var kinds = []int{
634 types.TINT: objabi.KindInt,
635 types.TUINT: objabi.KindUint,
636 types.TINT8: objabi.KindInt8,
637 types.TUINT8: objabi.KindUint8,
638 types.TINT16: objabi.KindInt16,
639 types.TUINT16: objabi.KindUint16,
640 types.TINT32: objabi.KindInt32,
641 types.TUINT32: objabi.KindUint32,
642 types.TINT64: objabi.KindInt64,
643 types.TUINT64: objabi.KindUint64,
644 types.TUINTPTR: objabi.KindUintptr,
645 types.TFLOAT32: objabi.KindFloat32,
646 types.TFLOAT64: objabi.KindFloat64,
647 types.TBOOL: objabi.KindBool,
648 types.TSTRING: objabi.KindString,
649 types.TPTR: objabi.KindPtr,
650 types.TSTRUCT: objabi.KindStruct,
651 types.TINTER: objabi.KindInterface,
652 types.TCHAN: objabi.KindChan,
653 types.TMAP: objabi.KindMap,
654 types.TARRAY: objabi.KindArray,
655 types.TSLICE: objabi.KindSlice,
656 types.TFUNC: objabi.KindFunc,
657 types.TCOMPLEX64: objabi.KindComplex64,
658 types.TCOMPLEX128: objabi.KindComplex128,
659 types.TUNSAFEPTR: objabi.KindUnsafePointer,
660 }
661
662 var (
663 memhashvarlen *obj.LSym
664 memequalvarlen *obj.LSym
665 )
666
667
668 func dcommontype(c rttype.Cursor, t *types.Type) {
669 types.CalcSize(t)
670 eqfunc := geneq(t)
671
672 sptrWeak := true
673 var sptr *obj.LSym
674 if !t.IsPtr() || t.IsPtrElem() {
675 tptr := types.NewPtr(t)
676 if t.Sym() != nil || methods(tptr) != nil {
677 sptrWeak = false
678 }
679 sptr = writeType(tptr)
680 }
681
682 gcsym, useGCProg, ptrdata := dgcsym(t, true)
683 delete(gcsymset, t)
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700 c.Field("Size_").WriteUintptr(uint64(t.Size()))
701 c.Field("PtrBytes").WriteUintptr(uint64(ptrdata))
702 c.Field("Hash").WriteUint32(types.TypeHash(t))
703
704 var tflag abi.TFlag
705 if uncommonSize(t) != 0 {
706 tflag |= abi.TFlagUncommon
707 }
708 if t.Sym() != nil && t.Sym().Name != "" {
709 tflag |= abi.TFlagNamed
710 }
711 if compare.IsRegularMemory(t) {
712 tflag |= abi.TFlagRegularMemory
713 }
714
715 exported := false
716 p := t.NameString()
717
718
719
720
721
722 if !strings.HasPrefix(p, "*") {
723 p = "*" + p
724 tflag |= abi.TFlagExtraStar
725 if t.Sym() != nil {
726 exported = types.IsExported(t.Sym().Name)
727 }
728 } else {
729 if t.Elem() != nil && t.Elem().Sym() != nil {
730 exported = types.IsExported(t.Elem().Sym().Name)
731 }
732 }
733
734 if tflag != abi.TFlag(uint8(tflag)) {
735
736 panic("Unexpected change in size of abi.TFlag")
737 }
738 c.Field("TFlag").WriteUint8(uint8(tflag))
739
740
741 i := int(uint8(t.Alignment()))
742
743 if i == 0 {
744 i = 1
745 }
746 if i&(i-1) != 0 {
747 base.Fatalf("invalid alignment %d for %v", uint8(t.Alignment()), t)
748 }
749 c.Field("Align_").WriteUint8(uint8(t.Alignment()))
750 c.Field("FieldAlign_").WriteUint8(uint8(t.Alignment()))
751
752 i = kinds[t.Kind()]
753 if types.IsDirectIface(t) {
754 i |= objabi.KindDirectIface
755 }
756 if useGCProg {
757 i |= objabi.KindGCProg
758 }
759 c.Field("Kind_").WriteUint8(uint8(i))
760
761 c.Field("Equal").WritePtr(eqfunc)
762 c.Field("GCData").WritePtr(gcsym)
763
764 nsym := dname(p, "", nil, exported, false)
765 c.Field("Str").WriteSymPtrOff(nsym, false)
766 c.Field("PtrToThis").WriteSymPtrOff(sptr, sptrWeak)
767 }
768
769
770
771 func TrackSym(t *types.Type, f *types.Field) *obj.LSym {
772 return base.PkgLinksym("go:track", t.LinkString()+"."+f.Sym.Name, obj.ABI0)
773 }
774
775 func TypeSymPrefix(prefix string, t *types.Type) *types.Sym {
776 p := prefix + "." + t.LinkString()
777 s := types.TypeSymLookup(p)
778
779
780
781 signatmu.Lock()
782 NeedRuntimeType(t)
783 signatmu.Unlock()
784
785
786
787 return s
788 }
789
790 func TypeSym(t *types.Type) *types.Sym {
791 if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
792 base.Fatalf("TypeSym %v", t)
793 }
794 if t.Kind() == types.TFUNC && t.Recv() != nil {
795 base.Fatalf("misuse of method type: %v", t)
796 }
797 s := types.TypeSym(t)
798 signatmu.Lock()
799 NeedRuntimeType(t)
800 signatmu.Unlock()
801 return s
802 }
803
804 func TypeLinksymPrefix(prefix string, t *types.Type) *obj.LSym {
805 return TypeSymPrefix(prefix, t).Linksym()
806 }
807
808 func TypeLinksymLookup(name string) *obj.LSym {
809 return types.TypeSymLookup(name).Linksym()
810 }
811
812 func TypeLinksym(t *types.Type) *obj.LSym {
813 lsym := TypeSym(t).Linksym()
814 signatmu.Lock()
815 if lsym.Extra == nil {
816 ti := lsym.NewTypeInfo()
817 ti.Type = t
818 }
819 signatmu.Unlock()
820 return lsym
821 }
822
823
824
825 func TypePtrAt(pos src.XPos, t *types.Type) *ir.AddrExpr {
826 return typecheck.LinksymAddr(pos, TypeLinksym(t), types.Types[types.TUINT8])
827 }
828
829
830
831
832
833
834
835
836 func ITabLsym(typ, iface *types.Type) *obj.LSym {
837 s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString())
838 lsym := s.Linksym()
839
840 if !existed {
841 writeITab(lsym, typ, iface, true)
842 }
843 return lsym
844 }
845
846
847
848
849 func ITabAddrAt(pos src.XPos, typ, iface *types.Type) *ir.AddrExpr {
850 s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString())
851 lsym := s.Linksym()
852
853 if !existed {
854 writeITab(lsym, typ, iface, false)
855 }
856
857 return typecheck.LinksymAddr(pos, lsym, types.Types[types.TUINT8])
858 }
859
860
861
862 func needkeyupdate(t *types.Type) bool {
863 switch t.Kind() {
864 case types.TBOOL, types.TINT, types.TUINT, types.TINT8, types.TUINT8, types.TINT16, types.TUINT16, types.TINT32, types.TUINT32,
865 types.TINT64, types.TUINT64, types.TUINTPTR, types.TPTR, types.TUNSAFEPTR, types.TCHAN:
866 return false
867
868 case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128,
869 types.TINTER,
870 types.TSTRING:
871 return true
872
873 case types.TARRAY:
874 return needkeyupdate(t.Elem())
875
876 case types.TSTRUCT:
877 for _, t1 := range t.Fields() {
878 if needkeyupdate(t1.Type) {
879 return true
880 }
881 }
882 return false
883
884 default:
885 base.Fatalf("bad type for map key: %v", t)
886 return true
887 }
888 }
889
890
891 func hashMightPanic(t *types.Type) bool {
892 switch t.Kind() {
893 case types.TINTER:
894 return true
895
896 case types.TARRAY:
897 return hashMightPanic(t.Elem())
898
899 case types.TSTRUCT:
900 for _, t1 := range t.Fields() {
901 if hashMightPanic(t1.Type) {
902 return true
903 }
904 }
905 return false
906
907 default:
908 return false
909 }
910 }
911
912
913
914
915 func formalType(t *types.Type) *types.Type {
916 switch t {
917 case types.AnyType, types.ByteType, types.RuneType:
918 return types.Types[t.Kind()]
919 }
920 return t
921 }
922
923 func writeType(t *types.Type) *obj.LSym {
924 t = formalType(t)
925 if t.IsUntyped() {
926 base.Fatalf("writeType %v", t)
927 }
928
929 s := types.TypeSym(t)
930 lsym := s.Linksym()
931
932
933
934
935 tbase := t
936 if t.IsPtr() && t.Sym() == nil && t.Elem().Sym() != nil {
937 tbase = t.Elem()
938 }
939 if tbase.Kind() == types.TFORW {
940 base.Fatalf("unresolved defined type: %v", tbase)
941 }
942
943
944
945
946
947 if sym := tbase.Sym(); sym != nil && sym.Pkg == ir.Pkgs.Runtime {
948 return lsym
949 }
950
951 if s.Siggen() {
952 return lsym
953 }
954 s.SetSiggen(true)
955
956 if !NeedEmit(tbase) {
957 if i := typecheck.BaseTypeIndex(t); i >= 0 {
958 lsym.Pkg = tbase.Sym().Pkg.Prefix
959 lsym.SymIdx = int32(i)
960 lsym.Set(obj.AttrIndexed, true)
961 }
962
963
964
965
966
967 return lsym
968 }
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992 extra := t.Sym() != nil || len(methods(t)) != 0
993
994
995
996 var rt *types.Type
997 dataAdd := 0
998 switch t.Kind() {
999 default:
1000 rt = rttype.Type
1001 case types.TARRAY:
1002 rt = rttype.ArrayType
1003 case types.TSLICE:
1004 rt = rttype.SliceType
1005 case types.TCHAN:
1006 rt = rttype.ChanType
1007 case types.TFUNC:
1008 rt = rttype.FuncType
1009 dataAdd = (t.NumRecvs() + t.NumParams() + t.NumResults()) * types.PtrSize
1010 case types.TINTER:
1011 rt = rttype.InterfaceType
1012 dataAdd = len(imethods(t)) * int(rttype.IMethod.Size())
1013 case types.TMAP:
1014 rt = rttype.MapType
1015 case types.TPTR:
1016 rt = rttype.PtrType
1017
1018 case types.TSTRUCT:
1019 rt = rttype.StructType
1020 dataAdd = t.NumFields() * int(rttype.StructField.Size())
1021 }
1022
1023
1024 B := rt.Size()
1025 C := B
1026 if extra {
1027 C = B + rttype.UncommonType.Size()
1028 }
1029 D := C + int64(dataAdd)
1030 E := D + int64(len(methods(t)))*rttype.Method.Size()
1031
1032
1033 c := rttype.NewCursor(lsym, 0, rt)
1034 if rt == rttype.Type {
1035 dcommontype(c, t)
1036 } else {
1037 dcommontype(c.Field("Type"), t)
1038 }
1039
1040
1041
1042 switch t.Kind() {
1043 case types.TARRAY:
1044
1045 s1 := writeType(t.Elem())
1046 t2 := types.NewSlice(t.Elem())
1047 s2 := writeType(t2)
1048 c.Field("Elem").WritePtr(s1)
1049 c.Field("Slice").WritePtr(s2)
1050 c.Field("Len").WriteUintptr(uint64(t.NumElem()))
1051
1052 case types.TSLICE:
1053
1054 s1 := writeType(t.Elem())
1055 c.Field("Elem").WritePtr(s1)
1056
1057 case types.TCHAN:
1058
1059 s1 := writeType(t.Elem())
1060 c.Field("Elem").WritePtr(s1)
1061 c.Field("Dir").WriteInt(int64(t.ChanDir()))
1062
1063 case types.TFUNC:
1064
1065 for _, t1 := range t.RecvParamsResults() {
1066 writeType(t1.Type)
1067 }
1068 inCount := t.NumRecvs() + t.NumParams()
1069 outCount := t.NumResults()
1070 if t.IsVariadic() {
1071 outCount |= 1 << 15
1072 }
1073
1074 c.Field("InCount").WriteUint16(uint16(inCount))
1075 c.Field("OutCount").WriteUint16(uint16(outCount))
1076
1077
1078 typs := t.RecvParamsResults()
1079 array := rttype.NewArrayCursor(lsym, C, types.Types[types.TUNSAFEPTR], len(typs))
1080 for i, t1 := range typs {
1081 array.Elem(i).WritePtr(writeType(t1.Type))
1082 }
1083
1084 case types.TINTER:
1085
1086 m := imethods(t)
1087 n := len(m)
1088 for _, a := range m {
1089 writeType(a.type_)
1090 }
1091
1092 var tpkg *types.Pkg
1093 if t.Sym() != nil && t != types.Types[t.Kind()] && t != types.ErrorType {
1094 tpkg = t.Sym().Pkg
1095 }
1096 dgopkgpath(c.Field("PkgPath"), tpkg)
1097 c.Field("Methods").WriteSlice(lsym, C, int64(n), int64(n))
1098
1099 array := rttype.NewArrayCursor(lsym, C, rttype.IMethod, n)
1100 for i, a := range m {
1101 exported := types.IsExported(a.name.Name)
1102 var pkg *types.Pkg
1103 if !exported && a.name.Pkg != tpkg {
1104 pkg = a.name.Pkg
1105 }
1106 nsym := dname(a.name.Name, "", pkg, exported, false)
1107
1108 e := array.Elem(i)
1109 e.Field("Name").WriteSymPtrOff(nsym, false)
1110 e.Field("Typ").WriteSymPtrOff(writeType(a.type_), false)
1111 }
1112
1113 case types.TMAP:
1114
1115 s1 := writeType(t.Key())
1116 s2 := writeType(t.Elem())
1117 s3 := writeType(MapBucketType(t))
1118 hasher := genhash(t.Key())
1119
1120 c.Field("Key").WritePtr(s1)
1121 c.Field("Elem").WritePtr(s2)
1122 c.Field("Bucket").WritePtr(s3)
1123 c.Field("Hasher").WritePtr(hasher)
1124 var flags uint32
1125
1126
1127 if t.Key().Size() > MAXKEYSIZE {
1128 c.Field("KeySize").WriteUint8(uint8(types.PtrSize))
1129 flags |= 1
1130 } else {
1131 c.Field("KeySize").WriteUint8(uint8(t.Key().Size()))
1132 }
1133
1134 if t.Elem().Size() > MAXELEMSIZE {
1135 c.Field("ValueSize").WriteUint8(uint8(types.PtrSize))
1136 flags |= 2
1137 } else {
1138 c.Field("ValueSize").WriteUint8(uint8(t.Elem().Size()))
1139 }
1140 c.Field("BucketSize").WriteUint16(uint16(MapBucketType(t).Size()))
1141 if types.IsReflexive(t.Key()) {
1142 flags |= 4
1143 }
1144 if needkeyupdate(t.Key()) {
1145 flags |= 8
1146 }
1147 if hashMightPanic(t.Key()) {
1148 flags |= 16
1149 }
1150 c.Field("Flags").WriteUint32(flags)
1151
1152 if u := t.Underlying(); u != t {
1153
1154
1155
1156
1157 r := obj.Addrel(lsym)
1158 r.Sym = writeType(u)
1159 r.Type = objabi.R_KEEP
1160 }
1161
1162 case types.TPTR:
1163
1164 if t.Elem().Kind() == types.TANY {
1165 base.Fatalf("bad pointer base type")
1166 }
1167
1168 s1 := writeType(t.Elem())
1169 c.Field("Elem").WritePtr(s1)
1170
1171 case types.TSTRUCT:
1172
1173 fields := t.Fields()
1174 for _, t1 := range fields {
1175 writeType(t1.Type)
1176 }
1177
1178
1179
1180
1181
1182
1183 var spkg *types.Pkg
1184 for _, f := range fields {
1185 if !types.IsExported(f.Sym.Name) {
1186 spkg = f.Sym.Pkg
1187 break
1188 }
1189 }
1190
1191 dgopkgpath(c.Field("PkgPath"), spkg)
1192 c.Field("Fields").WriteSlice(lsym, C, int64(len(fields)), int64(len(fields)))
1193
1194 array := rttype.NewArrayCursor(lsym, C, rttype.StructField, len(fields))
1195 for i, f := range fields {
1196 e := array.Elem(i)
1197 dnameField(e.Field("Name"), spkg, f)
1198 e.Field("Typ").WritePtr(writeType(f.Type))
1199 e.Field("Offset").WriteUintptr(uint64(f.Offset))
1200 }
1201 }
1202
1203
1204 if extra {
1205 dextratype(lsym, B, t, dataAdd)
1206 }
1207
1208
1209
1210
1211
1212 dupok := 0
1213 if tbase.Sym() == nil || tbase.IsFullyInstantiated() || tbase.HasShape() {
1214 dupok = obj.DUPOK
1215 }
1216
1217 objw.Global(lsym, int32(E), int16(dupok|obj.RODATA))
1218
1219
1220
1221
1222
1223
1224 keep := base.Ctxt.Flag_dynlink
1225 if !keep && t.Sym() == nil {
1226
1227
1228
1229
1230
1231 switch t.Kind() {
1232 case types.TPTR, types.TARRAY, types.TCHAN, types.TFUNC, types.TMAP, types.TSLICE, types.TSTRUCT:
1233 keep = true
1234 }
1235 }
1236
1237 if types.TypeHasNoAlg(t) {
1238 keep = false
1239 }
1240 lsym.Set(obj.AttrMakeTypelink, keep)
1241
1242 return lsym
1243 }
1244
1245
1246
1247 func InterfaceMethodOffset(ityp *types.Type, i int64) int64 {
1248
1249
1250
1251
1252
1253
1254
1255
1256 return int64(commonSize()+4*types.PtrSize+uncommonSize(ityp)) + i*8
1257 }
1258
1259
1260 func NeedRuntimeType(t *types.Type) {
1261 if _, ok := signatset[t]; !ok {
1262 signatset[t] = struct{}{}
1263 signatslice = append(signatslice, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()})
1264 }
1265 }
1266
1267 func WriteRuntimeTypes() {
1268
1269
1270 for len(signatslice) > 0 {
1271 signats := signatslice
1272
1273 sort.Sort(typesByString(signats))
1274 for _, ts := range signats {
1275 t := ts.t
1276 writeType(t)
1277 if t.Sym() != nil {
1278 writeType(types.NewPtr(t))
1279 }
1280 }
1281 signatslice = signatslice[len(signats):]
1282 }
1283 }
1284
1285 func WriteGCSymbols() {
1286
1287 gcsyms := make([]typeAndStr, 0, len(gcsymset))
1288 for t := range gcsymset {
1289 gcsyms = append(gcsyms, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()})
1290 }
1291 sort.Sort(typesByString(gcsyms))
1292 for _, ts := range gcsyms {
1293 dgcsym(ts.t, true)
1294 }
1295 }
1296
1297
1298
1299
1300 func writeITab(lsym *obj.LSym, typ, iface *types.Type, allowNonImplement bool) {
1301
1302
1303 oldpos, oldfn := base.Pos, ir.CurFunc
1304 defer func() { base.Pos, ir.CurFunc = oldpos, oldfn }()
1305
1306 if typ == nil || (typ.IsPtr() && typ.Elem() == nil) || typ.IsUntyped() || iface == nil || !iface.IsInterface() || iface.IsEmptyInterface() {
1307 base.Fatalf("writeITab(%v, %v)", typ, iface)
1308 }
1309
1310 sigs := iface.AllMethods()
1311 entries := make([]*obj.LSym, 0, len(sigs))
1312
1313
1314
1315 for _, m := range methods(typ) {
1316 if m.name == sigs[0].Sym {
1317 entries = append(entries, m.isym)
1318 if m.isym == nil {
1319 panic("NO ISYM")
1320 }
1321 sigs = sigs[1:]
1322 if len(sigs) == 0 {
1323 break
1324 }
1325 }
1326 }
1327 completeItab := len(sigs) == 0
1328 if !allowNonImplement && !completeItab {
1329 base.Fatalf("incomplete itab")
1330 }
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340 o := objw.SymPtr(lsym, 0, writeType(iface), 0)
1341 o = objw.SymPtr(lsym, o, writeType(typ), 0)
1342 o = objw.Uint32(lsym, o, types.TypeHash(typ))
1343 o += 4
1344 if !completeItab {
1345
1346 o = objw.Uintptr(lsym, o, 0)
1347 entries = entries[:0]
1348 }
1349 for _, fn := range entries {
1350 o = objw.SymPtrWeak(lsym, o, fn, 0)
1351 }
1352
1353 objw.Global(lsym, int32(o), int16(obj.DUPOK|obj.RODATA))
1354 lsym.Set(obj.AttrContentAddressable, true)
1355 }
1356
1357 func WritePluginTable() {
1358 ptabs := typecheck.Target.PluginExports
1359 if len(ptabs) == 0 {
1360 return
1361 }
1362
1363 lsym := base.Ctxt.Lookup("go:plugin.tabs")
1364 ot := 0
1365 for _, p := range ptabs {
1366
1367
1368
1369
1370
1371
1372 nsym := dname(p.Sym().Name, "", nil, true, false)
1373 t := p.Type()
1374 if p.Class != ir.PFUNC {
1375 t = types.NewPtr(t)
1376 }
1377 tsym := writeType(t)
1378 ot = objw.SymPtrOff(lsym, ot, nsym)
1379 ot = objw.SymPtrOff(lsym, ot, tsym)
1380
1381
1382 tsym.Set(obj.AttrUsedInIface, true)
1383 }
1384 objw.Global(lsym, int32(ot), int16(obj.RODATA))
1385
1386 lsym = base.Ctxt.Lookup("go:plugin.exports")
1387 ot = 0
1388 for _, p := range ptabs {
1389 ot = objw.SymPtr(lsym, ot, p.Linksym(), 0)
1390 }
1391 objw.Global(lsym, int32(ot), int16(obj.RODATA))
1392 }
1393
1394
1395
1396 func writtenByWriteBasicTypes(typ *types.Type) bool {
1397 if typ.Sym() == nil && typ.Kind() == types.TFUNC {
1398
1399 if typ.NumRecvs() == 0 &&
1400 typ.NumParams() == 1 && typ.NumResults() == 1 &&
1401 typ.Param(0).Type == types.ErrorType &&
1402 typ.Result(0).Type == types.Types[types.TSTRING] {
1403 return true
1404 }
1405 }
1406
1407
1408
1409 if typ.Sym() == nil && typ.IsSlice() {
1410 typ = typ.Elem()
1411 }
1412
1413
1414 sym := typ.Sym()
1415 if sym != nil && (sym.Pkg == types.BuiltinPkg || sym.Pkg == types.UnsafePkg) {
1416 return true
1417 }
1418
1419 return (sym == nil && typ.IsEmptyInterface()) || typ == types.ErrorType
1420 }
1421
1422 func WriteBasicTypes() {
1423
1424
1425
1426
1427
1428
1429
1430 if base.Ctxt.Pkgpath != "runtime" {
1431 return
1432 }
1433
1434
1435 var list []*types.Type
1436 for i := types.Kind(1); i <= types.TBOOL; i++ {
1437 list = append(list, types.Types[i])
1438 }
1439 list = append(list,
1440 types.Types[types.TSTRING],
1441 types.Types[types.TUNSAFEPTR],
1442 types.AnyType,
1443 types.ErrorType)
1444 for _, t := range list {
1445 writeType(types.NewPtr(t))
1446 writeType(types.NewPtr(types.NewSlice(t)))
1447 }
1448
1449
1450
1451 writeType(types.NewPtr(types.NewSignature(nil, []*types.Field{
1452 types.NewField(base.Pos, nil, types.ErrorType),
1453 }, []*types.Field{
1454 types.NewField(base.Pos, nil, types.Types[types.TSTRING]),
1455 })))
1456 }
1457
1458 type typeAndStr struct {
1459 t *types.Type
1460 short string
1461 regular string
1462 }
1463
1464 type typesByString []typeAndStr
1465
1466 func (a typesByString) Len() int { return len(a) }
1467 func (a typesByString) Less(i, j int) bool {
1468
1469 if a[i].t.Sym() != nil && a[j].t.Sym() == nil {
1470 return true
1471 }
1472 if a[i].t.Sym() == nil && a[j].t.Sym() != nil {
1473 return false
1474 }
1475
1476 if a[i].short != a[j].short {
1477 return a[i].short < a[j].short
1478 }
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488 if a[i].regular != a[j].regular {
1489 return a[i].regular < a[j].regular
1490 }
1491
1492
1493
1494
1495 if a[i].t.Kind() == types.TINTER && len(a[i].t.AllMethods()) > 0 {
1496 return a[i].t.AllMethods()[0].Pos.Before(a[j].t.AllMethods()[0].Pos)
1497 }
1498 return false
1499 }
1500 func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533 const maxPtrmaskBytes = 2048
1534
1535
1536
1537
1538
1539
1540 func GCSym(t *types.Type) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
1541
1542 gcsymmu.Lock()
1543 if _, ok := gcsymset[t]; !ok {
1544 gcsymset[t] = struct{}{}
1545 }
1546 gcsymmu.Unlock()
1547
1548 return dgcsym(t, false)
1549 }
1550
1551
1552
1553
1554
1555 func dgcsym(t *types.Type, write bool) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
1556 ptrdata = types.PtrDataSize(t)
1557 if ptrdata/int64(types.PtrSize) <= maxPtrmaskBytes*8 {
1558 lsym = dgcptrmask(t, write)
1559 return
1560 }
1561
1562 useGCProg = true
1563 lsym, ptrdata = dgcprog(t, write)
1564 return
1565 }
1566
1567
1568 func dgcptrmask(t *types.Type, write bool) *obj.LSym {
1569
1570 n := (types.PtrDataSize(t)/int64(types.PtrSize) + 7) / 8
1571
1572 n = (n + int64(types.PtrSize) - 1) &^ (int64(types.PtrSize) - 1)
1573 ptrmask := make([]byte, n)
1574 fillptrmask(t, ptrmask)
1575 p := fmt.Sprintf("runtime.gcbits.%x", ptrmask)
1576
1577 lsym := base.Ctxt.Lookup(p)
1578 if write && !lsym.OnList() {
1579 for i, x := range ptrmask {
1580 objw.Uint8(lsym, i, x)
1581 }
1582 objw.Global(lsym, int32(len(ptrmask)), obj.DUPOK|obj.RODATA|obj.LOCAL)
1583 lsym.Set(obj.AttrContentAddressable, true)
1584 }
1585 return lsym
1586 }
1587
1588
1589
1590
1591 func fillptrmask(t *types.Type, ptrmask []byte) {
1592 for i := range ptrmask {
1593 ptrmask[i] = 0
1594 }
1595 if !t.HasPointers() {
1596 return
1597 }
1598
1599 vec := bitvec.New(8 * int32(len(ptrmask)))
1600 typebits.Set(t, 0, vec)
1601
1602 nptr := types.PtrDataSize(t) / int64(types.PtrSize)
1603 for i := int64(0); i < nptr; i++ {
1604 if vec.Get(int32(i)) {
1605 ptrmask[i/8] |= 1 << (uint(i) % 8)
1606 }
1607 }
1608 }
1609
1610
1611
1612
1613
1614
1615 func dgcprog(t *types.Type, write bool) (*obj.LSym, int64) {
1616 types.CalcSize(t)
1617 if t.Size() == types.BADWIDTH {
1618 base.Fatalf("dgcprog: %v badwidth", t)
1619 }
1620 lsym := TypeLinksymPrefix(".gcprog", t)
1621 var p gcProg
1622 p.init(lsym, write)
1623 p.emit(t, 0)
1624 offset := p.w.BitIndex() * int64(types.PtrSize)
1625 p.end()
1626 if ptrdata := types.PtrDataSize(t); offset < ptrdata || offset > t.Size() {
1627 base.Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Size())
1628 }
1629 return lsym, offset
1630 }
1631
1632 type gcProg struct {
1633 lsym *obj.LSym
1634 symoff int
1635 w gcprog.Writer
1636 write bool
1637 }
1638
1639 func (p *gcProg) init(lsym *obj.LSym, write bool) {
1640 p.lsym = lsym
1641 p.write = write && !lsym.OnList()
1642 p.symoff = 4
1643 if !write {
1644 p.w.Init(func(byte) {})
1645 return
1646 }
1647 p.w.Init(p.writeByte)
1648 if base.Debug.GCProg > 0 {
1649 fmt.Fprintf(os.Stderr, "compile: start GCProg for %v\n", lsym)
1650 p.w.Debug(os.Stderr)
1651 }
1652 }
1653
1654 func (p *gcProg) writeByte(x byte) {
1655 p.symoff = objw.Uint8(p.lsym, p.symoff, x)
1656 }
1657
1658 func (p *gcProg) end() {
1659 p.w.End()
1660 if !p.write {
1661 return
1662 }
1663 objw.Uint32(p.lsym, 0, uint32(p.symoff-4))
1664 objw.Global(p.lsym, int32(p.symoff), obj.DUPOK|obj.RODATA|obj.LOCAL)
1665 p.lsym.Set(obj.AttrContentAddressable, true)
1666 if base.Debug.GCProg > 0 {
1667 fmt.Fprintf(os.Stderr, "compile: end GCProg for %v\n", p.lsym)
1668 }
1669 }
1670
1671 func (p *gcProg) emit(t *types.Type, offset int64) {
1672 types.CalcSize(t)
1673 if !t.HasPointers() {
1674 return
1675 }
1676 if t.Size() == int64(types.PtrSize) {
1677 p.w.Ptr(offset / int64(types.PtrSize))
1678 return
1679 }
1680 switch t.Kind() {
1681 default:
1682 base.Fatalf("gcProg.emit: unexpected type %v", t)
1683
1684 case types.TSTRING:
1685 p.w.Ptr(offset / int64(types.PtrSize))
1686
1687 case types.TINTER:
1688
1689 p.w.Ptr(offset/int64(types.PtrSize) + 1)
1690
1691 case types.TSLICE:
1692 p.w.Ptr(offset / int64(types.PtrSize))
1693
1694 case types.TARRAY:
1695 if t.NumElem() == 0 {
1696
1697 base.Fatalf("gcProg.emit: empty array")
1698 }
1699
1700
1701 count := t.NumElem()
1702 elem := t.Elem()
1703 for elem.IsArray() {
1704 count *= elem.NumElem()
1705 elem = elem.Elem()
1706 }
1707
1708 if !p.w.ShouldRepeat(elem.Size()/int64(types.PtrSize), count) {
1709
1710 for i := int64(0); i < count; i++ {
1711 p.emit(elem, offset+i*elem.Size())
1712 }
1713 return
1714 }
1715 p.emit(elem, offset)
1716 p.w.ZeroUntil((offset + elem.Size()) / int64(types.PtrSize))
1717 p.w.Repeat(elem.Size()/int64(types.PtrSize), count-1)
1718
1719 case types.TSTRUCT:
1720 for _, t1 := range t.Fields() {
1721 p.emit(t1.Type, offset+t1.Offset)
1722 }
1723 }
1724 }
1725
1726
1727
1728 func ZeroAddr(size int64) ir.Node {
1729 if size >= 1<<31 {
1730 base.Fatalf("map elem too big %d", size)
1731 }
1732 if ZeroSize < size {
1733 ZeroSize = size
1734 }
1735 lsym := base.PkgLinksym("go:map", "zero", obj.ABI0)
1736 x := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8])
1737 return typecheck.Expr(typecheck.NodAddr(x))
1738 }
1739
1740
1741
1742 func NeedEmit(typ *types.Type) bool {
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752 switch sym := typ.Sym(); {
1753 case writtenByWriteBasicTypes(typ):
1754 return base.Ctxt.Pkgpath == "runtime"
1755
1756 case sym == nil:
1757
1758
1759 return true
1760
1761 case sym.Pkg == types.LocalPkg:
1762
1763 return true
1764
1765 case typ.IsFullyInstantiated():
1766
1767
1768 return true
1769
1770 case typ.HasShape():
1771
1772
1773 return true
1774
1775 default:
1776
1777 return false
1778 }
1779 }
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817 func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSym {
1818 if forItab && !types.IsDirectIface(rcvr) {
1819 rcvr = rcvr.PtrTo()
1820 }
1821
1822 newnam := ir.MethodSym(rcvr, method.Sym)
1823 lsym := newnam.Linksym()
1824
1825
1826 return lsym
1827 }
1828
1829 var ZeroSize int64
1830
1831
1832
1833 func MarkTypeUsedInInterface(t *types.Type, from *obj.LSym) {
1834 if t.HasShape() {
1835
1836 base.Fatalf("shape types have no methods %+v", t)
1837 }
1838 MarkTypeSymUsedInInterface(TypeLinksym(t), from)
1839 }
1840 func MarkTypeSymUsedInInterface(tsym *obj.LSym, from *obj.LSym) {
1841
1842
1843 r := obj.Addrel(from)
1844 r.Sym = tsym
1845 r.Type = objabi.R_USEIFACE
1846 }
1847
1848
1849
1850 func MarkUsedIfaceMethod(n *ir.CallExpr) {
1851
1852 if ir.CurFunc.LSym == nil {
1853 return
1854 }
1855 dot := n.Fun.(*ir.SelectorExpr)
1856 ityp := dot.X.Type()
1857 if ityp.HasShape() {
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877 r := obj.Addrel(ir.CurFunc.LSym)
1878 r.Sym = staticdata.StringSymNoCommon(dot.Sel.Name)
1879 r.Type = objabi.R_USENAMEDMETHOD
1880 return
1881 }
1882
1883 tsym := TypeLinksym(ityp)
1884 r := obj.Addrel(ir.CurFunc.LSym)
1885 r.Sym = tsym
1886
1887
1888 midx := dot.Offset() / int64(types.PtrSize)
1889 r.Add = InterfaceMethodOffset(ityp, midx)
1890 r.Type = objabi.R_USEIFACEMETHOD
1891 }
1892
1893 func deref(t *types.Type) *types.Type {
1894 if t.IsPtr() {
1895 return t.Elem()
1896 }
1897 return t
1898 }
1899
View as plain text