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