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