1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
8 "cmd/compile/internal/types"
20 type itabEntry struct {
22 lsym *obj.LSym // symbol of the itab itself
24 // symbols of each method in
25 // the itab, sorted by byte offset;
26 // filled in by peekitabs
30 type ptabEntry struct {
35 // runtime interface and reflection data structures
37 signatmu sync.Mutex // protects signatset and signatslice
38 signatset = make(map[*types.Type]struct{})
39 signatslice []*types.Type
53 // Builds a type representing a Bucket structure for
54 // the given map type. This type is not visible to users -
55 // we include only enough information to generate a correct GC
57 // Make sure this stays in sync with runtime/map.go.
64 func structfieldSize() int { return 3 * Widthptr } // Sizeof(runtime.structfield{})
65 func imethodSize() int { return 4 + 4 } // Sizeof(runtime.imethod{})
66 func commonSize() int { return 4*Widthptr + 8 + 8 } // Sizeof(runtime._type{})
68 func uncommonSize(t *types.Type) int { // Sizeof(runtime.uncommontype{})
69 if t.Sym == nil && len(methods(t)) == 0 {
72 return 4 + 2 + 2 + 4 + 4
75 func makefield(name string, t *types.Type) *types.Field {
78 f.Sym = (*types.Pkg)(nil).Lookup(name)
82 // bmap makes the map bucket type given the type of the map.
83 func bmap(t *types.Type) *types.Type {
84 if t.MapType().Bucket != nil {
85 return t.MapType().Bucket
88 bucket := types.New(TSTRUCT)
93 if keytype.Width > MAXKEYSIZE {
94 keytype = types.NewPtr(keytype)
96 if elemtype.Width > MAXELEMSIZE {
97 elemtype = types.NewPtr(elemtype)
100 field := make([]*types.Field, 0, 5)
102 // The first field is: uint8 topbits[BUCKETSIZE].
103 arr := types.NewArray(types.Types[TUINT8], BUCKETSIZE)
104 field = append(field, makefield("topbits", arr))
106 arr = types.NewArray(keytype, BUCKETSIZE)
108 keys := makefield("keys", arr)
109 field = append(field, keys)
111 arr = types.NewArray(elemtype, BUCKETSIZE)
113 elems := makefield("elems", arr)
114 field = append(field, elems)
116 // If keys and elems have no pointers, the map implementation
117 // can keep a list of overflow pointers on the side so that
118 // buckets can be marked as having no pointers.
119 // Arrange for the bucket to have no pointers by changing
120 // the type of the overflow field to uintptr in this case.
121 // See comment on hmap.overflow in runtime/map.go.
122 otyp := types.NewPtr(bucket)
123 if !elemtype.HasPointers() && !keytype.HasPointers() {
124 otyp = types.Types[TUINTPTR]
126 overflow := makefield("overflow", otyp)
127 field = append(field, overflow)
130 bucket.SetNoalg(true)
131 bucket.SetFields(field[:])
134 // Check invariants that map code depends on.
135 if !IsComparable(t.Key()) {
136 Fatalf("unsupported map key type for %v", t)
139 Fatalf("bucket size too small for proper alignment")
141 if keytype.Align > BUCKETSIZE {
142 Fatalf("key align too big for %v", t)
144 if elemtype.Align > BUCKETSIZE {
145 Fatalf("elem align too big for %v", t)
147 if keytype.Width > MAXKEYSIZE {
148 Fatalf("key size to large for %v", t)
150 if elemtype.Width > MAXELEMSIZE {
151 Fatalf("elem size to large for %v", t)
153 if t.Key().Width > MAXKEYSIZE && !keytype.IsPtr() {
154 Fatalf("key indirect incorrect for %v", t)
156 if t.Elem().Width > MAXELEMSIZE && !elemtype.IsPtr() {
157 Fatalf("elem indirect incorrect for %v", t)
159 if keytype.Width%int64(keytype.Align) != 0 {
160 Fatalf("key size not a multiple of key align for %v", t)
162 if elemtype.Width%int64(elemtype.Align) != 0 {
163 Fatalf("elem size not a multiple of elem align for %v", t)
165 if bucket.Align%keytype.Align != 0 {
166 Fatalf("bucket align not multiple of key align %v", t)
168 if bucket.Align%elemtype.Align != 0 {
169 Fatalf("bucket align not multiple of elem align %v", t)
171 if keys.Offset%int64(keytype.Align) != 0 {
172 Fatalf("bad alignment of keys in bmap for %v", t)
174 if elems.Offset%int64(elemtype.Align) != 0 {
175 Fatalf("bad alignment of elems in bmap for %v", t)
178 // Double-check that overflow field is final memory in struct,
179 // with no padding at end.
180 if overflow.Offset != bucket.Width-int64(Widthptr) {
181 Fatalf("bad offset of overflow in bmap for %v", t)
184 t.MapType().Bucket = bucket
186 bucket.StructType().Map = t
190 // hmap builds a type representing a Hmap structure for the given map type.
191 // Make sure this stays in sync with runtime/map.go.
192 func hmap(t *types.Type) *types.Type {
193 if t.MapType().Hmap != nil {
194 return t.MapType().Hmap
200 // type hmap struct {
209 // extra unsafe.Pointer // *mapextra
211 // must match runtime/map.go:hmap.
212 fields := []*types.Field{
213 makefield("count", types.Types[TINT]),
214 makefield("flags", types.Types[TUINT8]),
215 makefield("B", types.Types[TUINT8]),
216 makefield("noverflow", types.Types[TUINT16]),
217 makefield("hash0", types.Types[TUINT32]), // Used in walk.go for OMAKEMAP.
218 makefield("buckets", types.NewPtr(bmap)), // Used in walk.go for OMAKEMAP.
219 makefield("oldbuckets", types.NewPtr(bmap)),
220 makefield("nevacuate", types.Types[TUINTPTR]),
221 makefield("extra", types.Types[TUNSAFEPTR]),
224 hmap := types.New(TSTRUCT)
226 hmap.SetFields(fields)
229 // The size of hmap should be 48 bytes on 64 bit
230 // and 28 bytes on 32 bit platforms.
231 if size := int64(8 + 5*Widthptr); hmap.Width != size {
232 Fatalf("hmap size not correct: got %d, want %d", hmap.Width, size)
235 t.MapType().Hmap = hmap
236 hmap.StructType().Map = t
240 // hiter builds a type representing an Hiter structure for the given map type.
241 // Make sure this stays in sync with runtime/map.go.
242 func hiter(t *types.Type) *types.Type {
243 if t.MapType().Hiter != nil {
244 return t.MapType().Hiter
251 // type hiter struct {
254 // t unsafe.Pointer // *MapType
258 // overflow unsafe.Pointer // *[]*bmap
259 // oldoverflow unsafe.Pointer // *[]*bmap
260 // startBucket uintptr
266 // checkBucket uintptr
268 // must match runtime/map.go:hiter.
269 fields := []*types.Field{
270 makefield("key", types.NewPtr(t.Key())), // Used in range.go for TMAP.
271 makefield("elem", types.NewPtr(t.Elem())), // Used in range.go for TMAP.
272 makefield("t", types.Types[TUNSAFEPTR]),
273 makefield("h", types.NewPtr(hmap)),
274 makefield("buckets", types.NewPtr(bmap)),
275 makefield("bptr", types.NewPtr(bmap)),
276 makefield("overflow", types.Types[TUNSAFEPTR]),
277 makefield("oldoverflow", types.Types[TUNSAFEPTR]),
278 makefield("startBucket", types.Types[TUINTPTR]),
279 makefield("offset", types.Types[TUINT8]),
280 makefield("wrapped", types.Types[TBOOL]),
281 makefield("B", types.Types[TUINT8]),
282 makefield("i", types.Types[TUINT8]),
283 makefield("bucket", types.Types[TUINTPTR]),
284 makefield("checkBucket", types.Types[TUINTPTR]),
287 // build iterator struct holding the above fields
288 hiter := types.New(TSTRUCT)
290 hiter.SetFields(fields)
292 if hiter.Width != int64(12*Widthptr) {
293 Fatalf("hash_iter size not correct %d %d", hiter.Width, 12*Widthptr)
295 t.MapType().Hiter = hiter
296 hiter.StructType().Map = t
300 // deferstruct makes a runtime._defer structure, with additional space for
301 // stksize bytes of args.
302 func deferstruct(stksize int64) *types.Type {
303 makefield := func(name string, typ *types.Type) *types.Field {
304 f := types.NewField()
306 // Unlike the global makefield function, this one needs to set Pkg
307 // because these types might be compared (in SSA CSE sorting).
308 // TODO: unify this makefield and the global one above.
309 f.Sym = &types.Sym{Name: name, Pkg: localpkg}
312 argtype := types.NewArray(types.Types[TUINT8], stksize)
313 argtype.Width = stksize
315 // These fields must match the ones in runtime/runtime2.go:_defer and
316 // cmd/compile/internal/gc/ssa.go:(*state).call.
317 fields := []*types.Field{
318 makefield("siz", types.Types[TUINT32]),
319 makefield("started", types.Types[TBOOL]),
320 makefield("heap", types.Types[TBOOL]),
321 makefield("openDefer", types.Types[TBOOL]),
322 makefield("sp", types.Types[TUINTPTR]),
323 makefield("pc", types.Types[TUINTPTR]),
324 // Note: the types here don't really matter. Defer structures
325 // are always scanned explicitly during stack copying and GC,
326 // so we make them uintptr type even though they are real pointers.
327 makefield("fn", types.Types[TUINTPTR]),
328 makefield("_panic", types.Types[TUINTPTR]),
329 makefield("link", types.Types[TUINTPTR]),
330 makefield("framepc", types.Types[TUINTPTR]),
331 makefield("varp", types.Types[TUINTPTR]),
332 makefield("fd", types.Types[TUINTPTR]),
333 makefield("args", argtype),
336 // build struct holding the above fields
337 s := types.New(TSTRUCT)
340 s.Width = widstruct(s, s, 0, 1)
341 s.Align = uint8(Widthptr)
345 // f is method type, with receiver.
346 // return function type, receiver as first argument (or not).
347 func methodfunc(f *types.Type, receiver *types.Type) *types.Type {
348 inLen := f.Params().Fields().Len()
352 in := make([]*Node, 0, inLen)
355 d := anonfield(receiver)
359 for _, t := range f.Params().Fields().Slice() {
360 d := anonfield(t.Type)
361 d.SetIsDDD(t.IsDDD())
365 outLen := f.Results().Fields().Len()
366 out := make([]*Node, 0, outLen)
367 for _, t := range f.Results().Fields().Slice() {
368 d := anonfield(t.Type)
372 t := functype(nil, in, out)
373 if f.Nname() != nil {
374 // Link to name of original method function.
375 t.SetNname(f.Nname())
381 // methods returns the methods of the non-interface type t, sorted by name.
382 // Generates stub functions as needed.
383 func methods(t *types.Type) []*Sig {
392 // type stored in interface word
395 if !isdirectiface(it) {
399 // make list of methods for t,
400 // generating code if necessary.
402 for _, f := range mt.AllMethods().Slice() {
404 Fatalf("non-method on %v method %v %v\n", mt, f.Sym, f)
406 if f.Type.Recv() == nil {
407 Fatalf("receiver with no type on %v method %v %v\n", mt, f.Sym, f)
418 // get receiver type for this particular method.
419 // if pointer receiver but non-pointer t and
420 // this is not an embedded pointer inside a struct,
421 // method does not apply.
422 if !isMethodApplicable(t, f) {
428 isym: methodSym(it, method),
429 tsym: methodSym(t, method),
430 type_: methodfunc(f.Type, t),
431 mtype: methodfunc(f.Type, nil),
435 this := f.Type.Recv().Type
437 if !sig.isym.Siggen() {
438 sig.isym.SetSiggen(true)
439 if !types.Identical(this, it) {
440 genwrapper(it, f, sig.isym)
444 if !sig.tsym.Siggen() {
445 sig.tsym.SetSiggen(true)
446 if !types.Identical(this, t) {
447 genwrapper(t, f, sig.tsym)
455 // imethods returns the methods of the interface type t, sorted by name.
456 func imethods(t *types.Type) []*Sig {
458 for _, f := range t.Fields().Slice() {
459 if f.Type.Etype != TFUNC || f.Sym == nil {
463 Fatalf("unexpected blank symbol in interface method set")
465 if n := len(methods); n > 0 {
467 if !last.name.Less(f.Sym) {
468 Fatalf("sigcmp vs sortinter %v %v", last.name, f.Sym)
475 type_: methodfunc(f.Type, nil),
477 methods = append(methods, sig)
479 // NOTE(rsc): Perhaps an oversight that
480 // IfaceType.Method is not in the reflect data.
481 // Generate the method body, so that compiled
482 // code can refer to it.
483 isym := methodSym(t, f.Sym)
486 genwrapper(t, f, isym)
493 func dimportpath(p *types.Pkg) {
494 if p.Pathsym != nil {
498 // If we are compiling the runtime package, there are two runtime packages around
499 // -- localpkg and Runtimepkg. We don't want to produce import path symbols for
500 // both of them, so just produce one for localpkg.
501 if myimportpath == "runtime" && p == Runtimepkg {
507 // Note: myimportpath != "", or else dgopkgpath won't call dimportpath.
511 s := Ctxt.Lookup("type..importpath." + p.Prefix + ".")
512 ot := dnameData(s, 0, str, "", nil, false)
513 ggloblsym(s, int32(ot), obj.DUPOK|obj.RODATA)
514 s.Set(obj.AttrContentAddressable, true)
518 func dgopkgpath(s *obj.LSym, ot int, pkg *types.Pkg) int {
520 return duintptr(s, ot, 0)
523 if pkg == localpkg && myimportpath == "" {
524 // If we don't know the full import path of the package being compiled
525 // (i.e. -p was not passed on the compiler command line), emit a reference to
526 // type..importpath.""., which the linker will rewrite using the correct import path.
527 // Every package that imports this one directly defines the symbol.
528 // See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ.
529 ns := Ctxt.Lookup(`type..importpath."".`)
530 return dsymptr(s, ot, ns, 0)
534 return dsymptr(s, ot, pkg.Pathsym, 0)
537 // dgopkgpathOff writes an offset relocation in s at offset ot to the pkg path symbol.
538 func dgopkgpathOff(s *obj.LSym, ot int, pkg *types.Pkg) int {
540 return duint32(s, ot, 0)
542 if pkg == localpkg && myimportpath == "" {
543 // If we don't know the full import path of the package being compiled
544 // (i.e. -p was not passed on the compiler command line), emit a reference to
545 // type..importpath.""., which the linker will rewrite using the correct import path.
546 // Every package that imports this one directly defines the symbol.
547 // See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ.
548 ns := Ctxt.Lookup(`type..importpath."".`)
549 return dsymptrOff(s, ot, ns)
553 return dsymptrOff(s, ot, pkg.Pathsym)
556 // dnameField dumps a reflect.name for a struct field.
557 func dnameField(lsym *obj.LSym, ot int, spkg *types.Pkg, ft *types.Field) int {
558 if !types.IsExported(ft.Sym.Name) && ft.Sym.Pkg != spkg {
559 Fatalf("package mismatch for %v", ft.Sym)
561 nsym := dname(ft.Sym.Name, ft.Note, nil, types.IsExported(ft.Sym.Name))
562 return dsymptr(lsym, ot, nsym, 0)
565 // dnameData writes the contents of a reflect.name into s at offset ot.
566 func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported bool) int {
567 if len(name) > 1<<16-1 {
568 Fatalf("name too long: %s", name)
570 if len(tag) > 1<<16-1 {
571 Fatalf("tag too long: %s", tag)
574 // Encode name and tag. See reflect/type.go for details.
576 l := 1 + 2 + len(name)
589 b[1] = uint8(len(name) >> 8)
590 b[2] = uint8(len(name))
593 tb := b[3+len(name):]
594 tb[0] = uint8(len(tag) >> 8)
595 tb[1] = uint8(len(tag))
599 ot = int(s.WriteBytes(Ctxt, int64(ot), b))
602 ot = dgopkgpathOff(s, ot, pkg)
610 // dname creates a reflect.name for a struct field or method.
611 func dname(name, tag string, pkg *types.Pkg, exported bool) *obj.LSym {
612 // Write out data as "type.." to signal two things to the
613 // linker, first that when dynamically linking, the symbol
614 // should be moved to a relro section, and second that the
615 // contents should not be decoded as a type.
616 sname := "type..namedata."
618 // In the common case, share data with other packages.
621 sname += "-noname-exported." + tag
623 sname += "-noname-unexported." + tag
627 sname += name + "." + tag
629 sname += name + "-" + tag
633 sname = fmt.Sprintf(`%s"".%d`, sname, dnameCount)
636 s := Ctxt.Lookup(sname)
640 ot := dnameData(s, 0, name, tag, pkg, exported)
641 ggloblsym(s, int32(ot), obj.DUPOK|obj.RODATA)
642 s.Set(obj.AttrContentAddressable, true)
646 // dextratype dumps the fields of a runtime.uncommontype.
647 // dataAdd is the offset in bytes after the header where the
648 // backing array of the []method field is written (by dextratypeData).
649 func dextratype(lsym *obj.LSym, ot int, t *types.Type, dataAdd int) int {
651 if t.Sym == nil && len(m) == 0 {
654 noff := int(Rnd(int64(ot), int64(Widthptr)))
656 Fatalf("unexpected alignment in dextratype for %v", t)
659 for _, a := range m {
663 ot = dgopkgpathOff(lsym, ot, typePkg(t))
665 dataAdd += uncommonSize(t)
667 if mcount != int(uint16(mcount)) {
668 Fatalf("too many methods on %v: %d", t, mcount)
670 xcount := sort.Search(mcount, func(i int) bool { return !types.IsExported(m[i].name.Name) })
671 if dataAdd != int(uint32(dataAdd)) {
672 Fatalf("methods are too far away on %v: %d", t, dataAdd)
675 ot = duint16(lsym, ot, uint16(mcount))
676 ot = duint16(lsym, ot, uint16(xcount))
677 ot = duint32(lsym, ot, uint32(dataAdd))
678 ot = duint32(lsym, ot, 0)
682 func typePkg(t *types.Type) *types.Pkg {
686 case TARRAY, TSLICE, TPTR, TCHAN:
692 if tsym != nil && t != types.Types[t.Etype] && t != types.Errortype {
698 // dextratypeData dumps the backing array for the []method field of
699 // runtime.uncommontype.
700 func dextratypeData(lsym *obj.LSym, ot int, t *types.Type) int {
701 for _, a := range methods(t) {
702 // ../../../../runtime/type.go:/method
703 exported := types.IsExported(a.name.Name)
705 if !exported && a.name.Pkg != typePkg(t) {
708 nsym := dname(a.name.Name, "", pkg, exported)
710 ot = dsymptrOff(lsym, ot, nsym)
711 ot = dmethodptrOff(lsym, ot, dtypesym(a.mtype))
712 ot = dmethodptrOff(lsym, ot, a.isym.Linksym())
713 ot = dmethodptrOff(lsym, ot, a.tsym.Linksym())
718 func dmethodptrOff(s *obj.LSym, ot int, x *obj.LSym) int {
724 r.Type = objabi.R_METHODOFF
729 TINT: objabi.KindInt,
730 TUINT: objabi.KindUint,
731 TINT8: objabi.KindInt8,
732 TUINT8: objabi.KindUint8,
733 TINT16: objabi.KindInt16,
734 TUINT16: objabi.KindUint16,
735 TINT32: objabi.KindInt32,
736 TUINT32: objabi.KindUint32,
737 TINT64: objabi.KindInt64,
738 TUINT64: objabi.KindUint64,
739 TUINTPTR: objabi.KindUintptr,
740 TFLOAT32: objabi.KindFloat32,
741 TFLOAT64: objabi.KindFloat64,
742 TBOOL: objabi.KindBool,
743 TSTRING: objabi.KindString,
744 TPTR: objabi.KindPtr,
745 TSTRUCT: objabi.KindStruct,
746 TINTER: objabi.KindInterface,
747 TCHAN: objabi.KindChan,
748 TMAP: objabi.KindMap,
749 TARRAY: objabi.KindArray,
750 TSLICE: objabi.KindSlice,
751 TFUNC: objabi.KindFunc,
752 TCOMPLEX64: objabi.KindComplex64,
753 TCOMPLEX128: objabi.KindComplex128,
754 TUNSAFEPTR: objabi.KindUnsafePointer,
757 // typeptrdata returns the length in bytes of the prefix of t
758 // containing pointer data. Anything after this offset is scalar data.
759 func typeptrdata(t *types.Type) int64 {
760 if !t.HasPointers() {
770 return int64(Widthptr)
773 // struct { byte *str; intgo len; }
774 return int64(Widthptr)
777 // struct { Itab *tab; void *data; } or
778 // struct { Type *type; void *data; }
779 // Note: see comment in plive.go:onebitwalktype1.
780 return 2 * int64(Widthptr)
783 // struct { byte *array; uintgo len; uintgo cap; }
784 return int64(Widthptr)
787 // haspointers already eliminated t.NumElem() == 0.
788 return (t.NumElem()-1)*t.Elem().Width + typeptrdata(t.Elem())
791 // Find the last field that has pointers.
792 var lastPtrField *types.Field
793 for _, t1 := range t.Fields().Slice() {
794 if t1.Type.HasPointers() {
798 return lastPtrField.Offset + typeptrdata(lastPtrField.Type)
801 Fatalf("typeptrdata: unexpected type, %v", t)
806 // tflag is documented in reflect/type.go.
808 // tflag values must be kept in sync with copies in:
809 // cmd/compile/internal/gc/reflect.go
810 // cmd/link/internal/ld/decodesym.go
814 tflagUncommon = 1 << 0
815 tflagExtraStar = 1 << 1
817 tflagRegularMemory = 1 << 3
821 memhashvarlen *obj.LSym
822 memequalvarlen *obj.LSym
825 // dcommontype dumps the contents of a reflect.rtype (runtime._type).
826 func dcommontype(lsym *obj.LSym, t *types.Type) int {
832 if !t.IsPtr() || t.IsPtrElem() {
833 tptr := types.NewPtr(t)
834 if t.Sym != nil || methods(tptr) != nil {
837 sptr = dtypesym(tptr)
840 gcsym, useGCProg, ptrdata := dgcsym(t)
842 // ../../../../reflect/type.go:/^type.rtype
843 // actual type structure
844 // type rtype struct {
852 // equal func(unsafe.Pointer, unsafe.Pointer) bool
858 ot = duintptr(lsym, ot, uint64(t.Width))
859 ot = duintptr(lsym, ot, uint64(ptrdata))
860 ot = duint32(lsym, ot, typehash(t))
863 if uncommonSize(t) != 0 {
864 tflag |= tflagUncommon
866 if t.Sym != nil && t.Sym.Name != "" {
869 if IsRegularMemory(t) {
870 tflag |= tflagRegularMemory
875 // If we're writing out type T,
876 // we are very likely to write out type *T as well.
877 // Use the string "*T"[1:] for "T", so that the two
878 // share storage. This is a cheap way to reduce the
879 // amount of space taken up by reflect strings.
880 if !strings.HasPrefix(p, "*") {
882 tflag |= tflagExtraStar
884 exported = types.IsExported(t.Sym.Name)
887 if t.Elem() != nil && t.Elem().Sym != nil {
888 exported = types.IsExported(t.Elem().Sym.Name)
892 ot = duint8(lsym, ot, tflag)
894 // runtime (and common sense) expects alignment to be a power of two.
901 Fatalf("invalid alignment %d for %v", t.Align, t)
903 ot = duint8(lsym, ot, t.Align) // align
904 ot = duint8(lsym, ot, t.Align) // fieldAlign
907 if isdirectiface(t) {
908 i |= objabi.KindDirectIface
911 i |= objabi.KindGCProg
913 ot = duint8(lsym, ot, uint8(i)) // kind
915 ot = dsymptr(lsym, ot, eqfunc, 0) // equality function
917 ot = duintptr(lsym, ot, 0) // type we can't do == with
919 ot = dsymptr(lsym, ot, gcsym, 0) // gcdata
921 nsym := dname(p, "", nil, exported)
922 ot = dsymptrOff(lsym, ot, nsym) // str
925 ot = duint32(lsym, ot, 0)
927 ot = dsymptrWeakOff(lsym, ot, sptr)
929 ot = dsymptrOff(lsym, ot, sptr)
935 // typeHasNoAlg reports whether t does not have any associated hash/eq
936 // algorithms because t, or some component of t, is marked Noalg.
937 func typeHasNoAlg(t *types.Type) bool {
938 a, bad := algtype1(t)
939 return a == ANOEQ && bad.Noalg()
942 func typesymname(t *types.Type) string {
943 name := t.ShortString()
944 // Use a separate symbol name for Noalg types for #17752.
946 name = "noalg." + name
951 // Fake package for runtime type info (headers)
952 // Don't access directly, use typeLookup below.
954 typepkgmu sync.Mutex // protects typepkg lookups
955 typepkg = types.NewPkg("type", "type")
958 func typeLookup(name string) *types.Sym {
960 s := typepkg.Lookup(name)
965 func typesym(t *types.Type) *types.Sym {
966 return typeLookup(typesymname(t))
969 // tracksym returns the symbol for tracking use of field/method f, assumed
970 // to be a member of struct/interface type t.
971 func tracksym(t *types.Type, f *types.Field) *types.Sym {
972 return trackpkg.Lookup(t.ShortString() + "." + f.Sym.Name)
975 func typesymprefix(prefix string, t *types.Type) *types.Sym {
976 p := prefix + "." + t.ShortString()
979 // This function is for looking up type-related generated functions
980 // (e.g. eq and hash). Make sure they are indeed generated.
985 //print("algsym: %s -> %+S\n", p, s);
990 func typenamesym(t *types.Type) *types.Sym {
991 if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
992 Fatalf("typenamesym %v", t)
1001 func typename(t *types.Type) *Node {
1004 n := newnamel(src.NoXPos, s)
1005 n.Type = types.Types[TUINT8]
1008 s.Def = asTypesNode(n)
1011 n := nod(OADDR, asNode(s.Def), nil)
1012 n.Type = types.NewPtr(asNode(s.Def).Type)
1017 func itabname(t, itype *types.Type) *Node {
1018 if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() || !itype.IsInterface() || itype.IsEmptyInterface() {
1019 Fatalf("itabname(%v, %v)", t, itype)
1021 s := itabpkg.Lookup(t.ShortString() + "," + itype.ShortString())
1024 n.Type = types.Types[TUINT8]
1027 s.Def = asTypesNode(n)
1028 itabs = append(itabs, itabEntry{t: t, itype: itype, lsym: s.Linksym()})
1031 n := nod(OADDR, asNode(s.Def), nil)
1032 n.Type = types.NewPtr(asNode(s.Def).Type)
1037 // isreflexive reports whether t has a reflexive equality operator.
1038 // That is, if x==x for all x of type t.
1039 func isreflexive(t *types.Type) bool {
1067 return isreflexive(t.Elem())
1070 for _, t1 := range t.Fields().Slice() {
1071 if !isreflexive(t1.Type) {
1078 Fatalf("bad type for map key: %v", t)
1083 // needkeyupdate reports whether map updates with t as a key
1084 // need the key to be updated.
1085 func needkeyupdate(t *types.Type) bool {
1087 case TBOOL, TINT, TUINT, TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32,
1088 TINT64, TUINT64, TUINTPTR, TPTR, TUNSAFEPTR, TCHAN:
1091 case TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, // floats and complex can be +0/-0
1093 TSTRING: // strings might have smaller backing stores
1097 return needkeyupdate(t.Elem())
1100 for _, t1 := range t.Fields().Slice() {
1101 if needkeyupdate(t1.Type) {
1108 Fatalf("bad type for map key: %v", t)
1113 // hashMightPanic reports whether the hash of a map key of type t might panic.
1114 func hashMightPanic(t *types.Type) bool {
1120 return hashMightPanic(t.Elem())
1123 for _, t1 := range t.Fields().Slice() {
1124 if hashMightPanic(t1.Type) {
1135 // formalType replaces byte and rune aliases with real types.
1136 // They've been separate internally to make error messages
1137 // better, but we have to merge them in the reflect tables.
1138 func formalType(t *types.Type) *types.Type {
1139 if t == types.Bytetype || t == types.Runetype {
1140 return types.Types[t.Etype]
1145 func dtypesym(t *types.Type) *obj.LSym {
1148 Fatalf("dtypesym %v", t)
1158 // special case (look for runtime below):
1159 // when compiling package runtime,
1160 // emit the type structures for int, float, etc.
1163 if t.IsPtr() && t.Sym == nil && t.Elem().Sym != nil {
1167 if tbase.Sym == nil {
1171 if myimportpath != "runtime" || (tbase != types.Types[tbase.Etype] && tbase != types.Bytetype && tbase != types.Runetype && tbase != types.Errortype) { // int, float, etc
1172 // named types from other files are defined only by those files
1173 if tbase.Sym != nil && tbase.Sym.Pkg != localpkg {
1174 if i, ok := typeSymIdx[tbase]; ok {
1175 lsym.Pkg = tbase.Sym.Pkg.Prefix
1177 lsym.SymIdx = int32(i[1])
1179 lsym.SymIdx = int32(i[0])
1181 lsym.Set(obj.AttrIndexed, true)
1185 // TODO(mdempsky): Investigate whether this can happen.
1186 if tbase.Etype == TFORW {
1194 ot = dcommontype(lsym, t)
1195 ot = dextratype(lsym, ot, t, 0)
1198 // ../../../../runtime/type.go:/arrayType
1199 s1 := dtypesym(t.Elem())
1200 t2 := types.NewSlice(t.Elem())
1202 ot = dcommontype(lsym, t)
1203 ot = dsymptr(lsym, ot, s1, 0)
1204 ot = dsymptr(lsym, ot, s2, 0)
1205 ot = duintptr(lsym, ot, uint64(t.NumElem()))
1206 ot = dextratype(lsym, ot, t, 0)
1209 // ../../../../runtime/type.go:/sliceType
1210 s1 := dtypesym(t.Elem())
1211 ot = dcommontype(lsym, t)
1212 ot = dsymptr(lsym, ot, s1, 0)
1213 ot = dextratype(lsym, ot, t, 0)
1216 // ../../../../runtime/type.go:/chanType
1217 s1 := dtypesym(t.Elem())
1218 ot = dcommontype(lsym, t)
1219 ot = dsymptr(lsym, ot, s1, 0)
1220 ot = duintptr(lsym, ot, uint64(t.ChanDir()))
1221 ot = dextratype(lsym, ot, t, 0)
1224 for _, t1 := range t.Recvs().Fields().Slice() {
1228 for _, t1 := range t.Params().Fields().Slice() {
1232 for _, t1 := range t.Results().Fields().Slice() {
1236 ot = dcommontype(lsym, t)
1237 inCount := t.NumRecvs() + t.NumParams()
1238 outCount := t.NumResults()
1242 ot = duint16(lsym, ot, uint16(inCount))
1243 ot = duint16(lsym, ot, uint16(outCount))
1245 ot += 4 // align for *rtype
1248 dataAdd := (inCount + t.NumResults()) * Widthptr
1249 ot = dextratype(lsym, ot, t, dataAdd)
1251 // Array of rtype pointers follows funcType.
1252 for _, t1 := range t.Recvs().Fields().Slice() {
1253 ot = dsymptr(lsym, ot, dtypesym(t1.Type), 0)
1255 for _, t1 := range t.Params().Fields().Slice() {
1256 ot = dsymptr(lsym, ot, dtypesym(t1.Type), 0)
1258 for _, t1 := range t.Results().Fields().Slice() {
1259 ot = dsymptr(lsym, ot, dtypesym(t1.Type), 0)
1265 for _, a := range m {
1269 // ../../../../runtime/type.go:/interfaceType
1270 ot = dcommontype(lsym, t)
1273 if t.Sym != nil && t != types.Types[t.Etype] && t != types.Errortype {
1276 ot = dgopkgpath(lsym, ot, tpkg)
1278 xcount := sort.Search(n, func(i int) bool { return !types.IsExported(m[i].name.Name) })
1279 ot = dsymptr(lsym, ot, lsym, ot+3*Widthptr+uncommonSize(t))
1280 ot = duintptr(lsym, ot, uint64(xcount))
1281 ot = duintptr(lsym, ot, uint64(n))
1282 dataAdd := imethodSize() * n
1283 ot = dextratype(lsym, ot, t, dataAdd)
1285 for _, a := range m {
1286 // ../../../../runtime/type.go:/imethod
1287 exported := types.IsExported(a.name.Name)
1289 if !exported && a.name.Pkg != tpkg {
1292 nsym := dname(a.name.Name, "", pkg, exported)
1294 ot = dsymptrOff(lsym, ot, nsym)
1295 ot = dsymptrOff(lsym, ot, dtypesym(a.type_))
1298 // ../../../../runtime/type.go:/mapType
1300 s1 := dtypesym(t.Key())
1301 s2 := dtypesym(t.Elem())
1302 s3 := dtypesym(bmap(t))
1303 hasher := genhash(t.Key())
1305 ot = dcommontype(lsym, t)
1306 ot = dsymptr(lsym, ot, s1, 0)
1307 ot = dsymptr(lsym, ot, s2, 0)
1308 ot = dsymptr(lsym, ot, s3, 0)
1309 ot = dsymptr(lsym, ot, hasher, 0)
1311 // Note: flags must match maptype accessors in ../../../../runtime/type.go
1312 // and maptype builder in ../../../../reflect/type.go:MapOf.
1313 if t.Key().Width > MAXKEYSIZE {
1314 ot = duint8(lsym, ot, uint8(Widthptr))
1315 flags |= 1 // indirect key
1317 ot = duint8(lsym, ot, uint8(t.Key().Width))
1320 if t.Elem().Width > MAXELEMSIZE {
1321 ot = duint8(lsym, ot, uint8(Widthptr))
1322 flags |= 2 // indirect value
1324 ot = duint8(lsym, ot, uint8(t.Elem().Width))
1326 ot = duint16(lsym, ot, uint16(bmap(t).Width))
1327 if isreflexive(t.Key()) {
1328 flags |= 4 // reflexive key
1330 if needkeyupdate(t.Key()) {
1331 flags |= 8 // need key update
1333 if hashMightPanic(t.Key()) {
1334 flags |= 16 // hash might panic
1336 ot = duint32(lsym, ot, flags)
1337 ot = dextratype(lsym, ot, t, 0)
1340 if t.Elem().Etype == TANY {
1341 // ../../../../runtime/type.go:/UnsafePointerType
1342 ot = dcommontype(lsym, t)
1343 ot = dextratype(lsym, ot, t, 0)
1348 // ../../../../runtime/type.go:/ptrType
1349 s1 := dtypesym(t.Elem())
1351 ot = dcommontype(lsym, t)
1352 ot = dsymptr(lsym, ot, s1, 0)
1353 ot = dextratype(lsym, ot, t, 0)
1355 // ../../../../runtime/type.go:/structType
1356 // for security, only the exported fields.
1358 fields := t.Fields().Slice()
1360 // omitFieldForAwfulBoringCryptoKludge reports whether
1361 // the field t should be omitted from the reflect data.
1362 // In the crypto/... packages we omit an unexported field
1363 // named "boring", to keep from breaking client code that
1364 // expects rsa.PublicKey etc to have only public fields.
1365 // As the name suggests, this is an awful kludge, but it is
1366 // limited to the dev.boringcrypto branch and avoids
1367 // much more invasive effects elsewhere.
1368 omitFieldForAwfulBoringCryptoKludge := func(t *types.Field) bool {
1369 if t.Sym == nil || t.Sym.Name != "boring" || t.Sym.Pkg == nil {
1372 path := t.Sym.Pkg.Path
1373 if t.Sym.Pkg == localpkg {
1376 return strings.HasPrefix(path, "crypto/")
1378 newFields := fields[:0:0]
1379 for _, t1 := range fields {
1380 if !omitFieldForAwfulBoringCryptoKludge(t1) {
1381 newFields = append(newFields, t1)
1386 for _, t1 := range fields {
1390 // All non-exported struct field names within a struct
1391 // type must originate from a single package. By
1392 // identifying and recording that package within the
1393 // struct type descriptor, we can omit that
1394 // information from the field descriptors.
1396 for _, f := range fields {
1397 if !types.IsExported(f.Sym.Name) {
1403 ot = dcommontype(lsym, t)
1404 ot = dgopkgpath(lsym, ot, spkg)
1405 ot = dsymptr(lsym, ot, lsym, ot+3*Widthptr+uncommonSize(t))
1406 ot = duintptr(lsym, ot, uint64(len(fields)))
1407 ot = duintptr(lsym, ot, uint64(len(fields)))
1409 dataAdd := len(fields) * structfieldSize()
1410 ot = dextratype(lsym, ot, t, dataAdd)
1412 for _, f := range fields {
1413 // ../../../../runtime/type.go:/structField
1414 ot = dnameField(lsym, ot, spkg, f)
1415 ot = dsymptr(lsym, ot, dtypesym(f.Type), 0)
1416 offsetAnon := uint64(f.Offset) << 1
1417 if offsetAnon>>1 != uint64(f.Offset) {
1418 Fatalf("%v: bad field offset for %s", t, f.Sym.Name)
1420 if f.Embedded != 0 {
1423 ot = duintptr(lsym, ot, offsetAnon)
1427 ot = dextratypeData(lsym, ot, t)
1428 ggloblsym(lsym, int32(ot), int16(dupok|obj.RODATA))
1430 // The linker will leave a table of all the typelinks for
1431 // types in the binary, so the runtime can find them.
1433 // When buildmode=shared, all types are in typelinks so the
1434 // runtime can deduplicate type pointers.
1435 keep := Ctxt.Flag_dynlink
1436 if !keep && t.Sym == nil {
1437 // For an unnamed type, we only need the link if the type can
1438 // be created at run time by reflect.PtrTo and similar
1439 // functions. If the type exists in the program, those
1440 // functions must return the existing type structure rather
1441 // than creating a new one.
1443 case TPTR, TARRAY, TCHAN, TFUNC, TMAP, TSLICE, TSTRUCT:
1447 // Do not put Noalg types in typelinks. See issue #22605.
1448 if typeHasNoAlg(t) {
1451 lsym.Set(obj.AttrMakeTypelink, keep)
1456 // ifaceMethodOffset returns the offset of the i-th method in the interface
1457 // type descriptor, ityp.
1458 func ifaceMethodOffset(ityp *types.Type, i int64) int64 {
1459 // interface type descriptor layout is struct {
1460 // _type // commonSize
1461 // pkgpath // 1 word
1462 // []imethod // 3 words (pointing to [...]imethod below)
1463 // uncommontype // uncommonSize
1466 // The size of imethod is 8.
1467 return int64(commonSize()+4*Widthptr+uncommonSize(ityp)) + i*8
1470 // for each itabEntry, gather the methods on
1471 // the concrete type that implement the interface
1473 for i := range itabs {
1475 methods := genfun(tab.t, tab.itype)
1476 if len(methods) == 0 {
1479 tab.entries = methods
1483 // for the given concrete type and interface
1484 // type, return the (sorted) set of methods
1485 // on the concrete type that implement the interface
1486 func genfun(t, it *types.Type) []*obj.LSym {
1487 if t == nil || it == nil {
1490 sigs := imethods(it)
1491 methods := methods(t)
1492 out := make([]*obj.LSym, 0, len(sigs))
1493 // TODO(mdempsky): Short circuit before calling methods(t)?
1494 // See discussion on CL 105039.
1499 // both sigs and methods are sorted by name,
1500 // so we can find the intersect in a single pass
1501 for _, m := range methods {
1502 if m.name == sigs[0].name {
1503 out = append(out, m.isym.Linksym())
1512 Fatalf("incomplete itab")
1518 // itabsym uses the information gathered in
1519 // peekitabs to de-virtualize interface methods.
1520 // Since this is called by the SSA backend, it shouldn't
1521 // generate additional Nodes, Syms, etc.
1522 func itabsym(it *obj.LSym, offset int64) *obj.LSym {
1523 var syms []*obj.LSym
1528 for i := range itabs {
1539 // keep this arithmetic in sync with *itab layout
1540 methodnum := int((offset - 2*int64(Widthptr) - 8) / int64(Widthptr))
1541 if methodnum >= len(syms) {
1544 return syms[methodnum]
1547 // addsignat ensures that a runtime type descriptor is emitted for t.
1548 func addsignat(t *types.Type) {
1549 if _, ok := signatset[t]; !ok {
1550 signatset[t] = struct{}{}
1551 signatslice = append(signatslice, t)
1555 func addsignats(dcls []*Node) {
1556 // copy types from dcl list to signatset
1557 for _, n := range dcls {
1564 func dumpsignats() {
1565 // Process signatset. Use a loop, as dtypesym adds
1566 // entries to signatset while it is being processed.
1567 signats := make([]typeAndStr, len(signatslice))
1568 for len(signatslice) > 0 {
1569 signats = signats[:0]
1570 // Transfer entries to a slice and sort, for reproducible builds.
1571 for _, t := range signatslice {
1572 signats = append(signats, typeAndStr{t: t, short: typesymname(t), regular: t.String()})
1573 delete(signatset, t)
1575 signatslice = signatslice[:0]
1576 sort.Sort(typesByString(signats))
1577 for _, ts := range signats {
1581 dtypesym(types.NewPtr(t))
1589 for _, i := range itabs {
1590 // dump empty itab symbol into i.sym
1591 // type itab struct {
1592 // inter *interfacetype
1596 // fun [1]uintptr // variable sized
1598 o := dsymptr(i.lsym, 0, dtypesym(i.itype), 0)
1599 o = dsymptr(i.lsym, o, dtypesym(i.t), 0)
1600 o = duint32(i.lsym, o, typehash(i.t)) // copy of type hash
1601 o += 4 // skip unused field
1602 for _, fn := range genfun(i.t, i.itype) {
1603 o = dsymptr(i.lsym, o, fn, 0) // method pointer for each method
1605 // Nothing writes static itabs, so they are read only.
1606 ggloblsym(i.lsym, int32(o), int16(obj.DUPOK|obj.RODATA))
1607 i.lsym.Set(obj.AttrContentAddressable, true)
1611 if localpkg.Name == "main" && len(ptabs) > 0 {
1613 s := Ctxt.Lookup("go.plugin.tabs")
1614 for _, p := range ptabs {
1615 // Dump ptab symbol into go.pluginsym package.
1617 // type ptab struct {
1619 // typ typeOff // pointer to symbol
1621 nsym := dname(p.s.Name, "", nil, true)
1622 ot = dsymptrOff(s, ot, nsym)
1623 ot = dsymptrOff(s, ot, dtypesym(p.t))
1625 ggloblsym(s, int32(ot), int16(obj.RODATA))
1628 s = Ctxt.Lookup("go.plugin.exports")
1629 for _, p := range ptabs {
1630 ot = dsymptr(s, ot, p.s.Linksym(), 0)
1632 ggloblsym(s, int32(ot), int16(obj.RODATA))
1636 func dumpimportstrings() {
1637 // generate import strings for imported packages
1638 for _, p := range types.ImportedPkgList() {
1643 func dumpbasictypes() {
1644 // do basic types if compiling package runtime.
1645 // they have to be in at least one package,
1646 // and runtime is always loaded implicitly,
1647 // so this is as good as any.
1648 // another possible choice would be package main,
1649 // but using runtime means fewer copies in object files.
1650 if myimportpath == "runtime" {
1651 for i := types.EType(1); i <= TBOOL; i++ {
1652 dtypesym(types.NewPtr(types.Types[i]))
1654 dtypesym(types.NewPtr(types.Types[TSTRING]))
1655 dtypesym(types.NewPtr(types.Types[TUNSAFEPTR]))
1657 // emit type structs for error and func(error) string.
1658 // The latter is the type of an auto-generated wrapper.
1659 dtypesym(types.NewPtr(types.Errortype))
1661 dtypesym(functype(nil, []*Node{anonfield(types.Errortype)}, []*Node{anonfield(types.Types[TSTRING])}))
1663 // add paths for runtime and main, which 6l imports implicitly.
1664 dimportpath(Runtimepkg)
1667 dimportpath(racepkg)
1670 dimportpath(msanpkg)
1672 dimportpath(types.NewPkg("main", ""))
1676 type typeAndStr struct {
1682 type typesByString []typeAndStr
1684 func (a typesByString) Len() int { return len(a) }
1685 func (a typesByString) Less(i, j int) bool {
1686 if a[i].short != a[j].short {
1687 return a[i].short < a[j].short
1689 // When the only difference between the types is whether
1690 // they refer to byte or uint8, such as **byte vs **uint8,
1691 // the types' ShortStrings can be identical.
1692 // To preserve deterministic sort ordering, sort these by String().
1693 if a[i].regular != a[j].regular {
1694 return a[i].regular < a[j].regular
1696 // Identical anonymous interfaces defined in different locations
1697 // will be equal for the above checks, but different in DWARF output.
1698 // Sort by source position to ensure deterministic order.
1699 // See issues 27013 and 30202.
1700 if a[i].t.Etype == types.TINTER && a[i].t.Methods().Len() > 0 {
1701 return a[i].t.Methods().Index(0).Pos.Before(a[j].t.Methods().Index(0).Pos)
1705 func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
1707 // maxPtrmaskBytes is the maximum length of a GC ptrmask bitmap,
1708 // which holds 1-bit entries describing where pointers are in a given type.
1709 // Above this length, the GC information is recorded as a GC program,
1710 // which can express repetition compactly. In either form, the
1711 // information is used by the runtime to initialize the heap bitmap,
1712 // and for large types (like 128 or more words), they are roughly the
1713 // same speed. GC programs are never much larger and often more
1714 // compact. (If large arrays are involved, they can be arbitrarily
1717 // The cutoff must be large enough that any allocation large enough to
1718 // use a GC program is large enough that it does not share heap bitmap
1719 // bytes with any other objects, allowing the GC program execution to
1720 // assume an aligned start and not use atomic operations. In the current
1721 // runtime, this means all malloc size classes larger than the cutoff must
1722 // be multiples of four words. On 32-bit systems that's 16 bytes, and
1723 // all size classes >= 16 bytes are 16-byte aligned, so no real constraint.
1724 // On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed
1725 // for size classes >= 256 bytes. On a 64-bit system, 256 bytes allocated
1726 // is 32 pointers, the bits for which fit in 4 bytes. So maxPtrmaskBytes
1729 // We used to use 16 because the GC programs do have some constant overhead
1730 // to get started, and processing 128 pointers seems to be enough to
1731 // amortize that overhead well.
1733 // To make sure that the runtime's chansend can call typeBitsBulkBarrier,
1734 // we raised the limit to 2048, so that even 32-bit systems are guaranteed to
1735 // use bitmaps for objects up to 64 kB in size.
1737 // Also known to reflect/type.go.
1739 const maxPtrmaskBytes = 2048
1741 // dgcsym emits and returns a data symbol containing GC information for type t,
1742 // along with a boolean reporting whether the UseGCProg bit should be set in
1743 // the type kind, and the ptrdata field to record in the reflect type information.
1744 func dgcsym(t *types.Type) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
1745 ptrdata = typeptrdata(t)
1746 if ptrdata/int64(Widthptr) <= maxPtrmaskBytes*8 {
1747 lsym = dgcptrmask(t)
1752 lsym, ptrdata = dgcprog(t)
1756 // dgcptrmask emits and returns the symbol containing a pointer mask for type t.
1757 func dgcptrmask(t *types.Type) *obj.LSym {
1758 ptrmask := make([]byte, (typeptrdata(t)/int64(Widthptr)+7)/8)
1759 fillptrmask(t, ptrmask)
1760 p := fmt.Sprintf("gcbits.%x", ptrmask)
1762 sym := Runtimepkg.Lookup(p)
1763 lsym := sym.Linksym()
1766 for i, x := range ptrmask {
1769 ggloblsym(lsym, int32(len(ptrmask)), obj.DUPOK|obj.RODATA|obj.LOCAL)
1770 lsym.Set(obj.AttrContentAddressable, true)
1775 // fillptrmask fills in ptrmask with 1s corresponding to the
1776 // word offsets in t that hold pointers.
1777 // ptrmask is assumed to fit at least typeptrdata(t)/Widthptr bits.
1778 func fillptrmask(t *types.Type, ptrmask []byte) {
1779 for i := range ptrmask {
1782 if !t.HasPointers() {
1786 vec := bvalloc(8 * int32(len(ptrmask)))
1787 onebitwalktype1(t, 0, vec)
1789 nptr := typeptrdata(t) / int64(Widthptr)
1790 for i := int64(0); i < nptr; i++ {
1791 if vec.Get(int32(i)) {
1792 ptrmask[i/8] |= 1 << (uint(i) % 8)
1797 // dgcprog emits and returns the symbol containing a GC program for type t
1798 // along with the size of the data described by the program (in the range [typeptrdata(t), t.Width]).
1799 // In practice, the size is typeptrdata(t) except for non-trivial arrays.
1800 // For non-trivial arrays, the program describes the full t.Width size.
1801 func dgcprog(t *types.Type) (*obj.LSym, int64) {
1803 if t.Width == BADWIDTH {
1804 Fatalf("dgcprog: %v badwidth", t)
1806 lsym := typesymprefix(".gcprog", t).Linksym()
1810 offset := p.w.BitIndex() * int64(Widthptr)
1812 if ptrdata := typeptrdata(t); offset < ptrdata || offset > t.Width {
1813 Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Width)
1818 type GCProg struct {
1824 var Debug_gcprog int // set by -d gcprog
1826 func (p *GCProg) init(lsym *obj.LSym) {
1828 p.symoff = 4 // first 4 bytes hold program length
1829 p.w.Init(p.writeByte)
1830 if Debug_gcprog > 0 {
1831 fmt.Fprintf(os.Stderr, "compile: start GCProg for %v\n", lsym)
1832 p.w.Debug(os.Stderr)
1836 func (p *GCProg) writeByte(x byte) {
1837 p.symoff = duint8(p.lsym, p.symoff, x)
1840 func (p *GCProg) end() {
1842 duint32(p.lsym, 0, uint32(p.symoff-4))
1843 ggloblsym(p.lsym, int32(p.symoff), obj.DUPOK|obj.RODATA|obj.LOCAL)
1844 if Debug_gcprog > 0 {
1845 fmt.Fprintf(os.Stderr, "compile: end GCProg for %v\n", p.lsym)
1849 func (p *GCProg) emit(t *types.Type, offset int64) {
1851 if !t.HasPointers() {
1854 if t.Width == int64(Widthptr) {
1855 p.w.Ptr(offset / int64(Widthptr))
1860 Fatalf("GCProg.emit: unexpected type %v", t)
1863 p.w.Ptr(offset / int64(Widthptr))
1866 // Note: the first word isn't a pointer. See comment in plive.go:onebitwalktype1.
1867 p.w.Ptr(offset/int64(Widthptr) + 1)
1870 p.w.Ptr(offset / int64(Widthptr))
1873 if t.NumElem() == 0 {
1874 // should have been handled by haspointers check above
1875 Fatalf("GCProg.emit: empty array")
1878 // Flatten array-of-array-of-array to just a big array by multiplying counts.
1879 count := t.NumElem()
1881 for elem.IsArray() {
1882 count *= elem.NumElem()
1886 if !p.w.ShouldRepeat(elem.Width/int64(Widthptr), count) {
1887 // Cheaper to just emit the bits.
1888 for i := int64(0); i < count; i++ {
1889 p.emit(elem, offset+i*elem.Width)
1893 p.emit(elem, offset)
1894 p.w.ZeroUntil((offset + elem.Width) / int64(Widthptr))
1895 p.w.Repeat(elem.Width/int64(Widthptr), count-1)
1898 for _, t1 := range t.Fields().Slice() {
1899 p.emit(t1.Type, offset+t1.Offset)
1904 // zeroaddr returns the address of a symbol with at least
1905 // size bytes of zeros.
1906 func zeroaddr(size int64) *Node {
1908 Fatalf("map elem too big %d", size)
1910 if zerosize < size {
1913 s := mappkg.Lookup("zero")
1916 x.Type = types.Types[TUINT8]
1919 s.Def = asTypesNode(x)
1921 z := nod(OADDR, asNode(s.Def), nil)
1922 z.Type = types.NewPtr(types.Types[TUINT8])