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