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