github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/typebits/typebits.go (about) 1 // Copyright 2013 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. 4 5 package typebits 6 7 import ( 8 "github.com/go-asm/go/cmd/compile/base" 9 "github.com/go-asm/go/cmd/compile/bitvec" 10 "github.com/go-asm/go/cmd/compile/types" 11 ) 12 13 // NOTE: The bitmap for a specific type t could be cached in t after 14 // the first run and then simply copied into bv at the correct offset 15 // on future calls with the same type t. 16 func Set(t *types.Type, off int64, bv bitvec.BitVec) { 17 set(t, off, bv, false) 18 } 19 20 // SetNoCheck is like Set, but do not check for alignment. 21 func SetNoCheck(t *types.Type, off int64, bv bitvec.BitVec) { 22 set(t, off, bv, true) 23 } 24 25 func set(t *types.Type, off int64, bv bitvec.BitVec, skip bool) { 26 if !skip && uint8(t.Alignment()) > 0 && off&int64(uint8(t.Alignment())-1) != 0 { 27 base.Fatalf("typebits.Set: invalid initial alignment: type %v has alignment %d, but offset is %v", t, uint8(t.Alignment()), off) 28 } 29 if !t.HasPointers() { 30 // Note: this case ensures that pointers to not-in-heap types 31 // are not considered pointers by garbage collection and stack copying. 32 return 33 } 34 35 switch t.Kind() { 36 case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP: 37 if off&int64(types.PtrSize-1) != 0 { 38 base.Fatalf("typebits.Set: invalid alignment, %v", t) 39 } 40 bv.Set(int32(off / int64(types.PtrSize))) // pointer 41 42 case types.TSTRING: 43 // struct { byte *str; intgo len; } 44 if off&int64(types.PtrSize-1) != 0 { 45 base.Fatalf("typebits.Set: invalid alignment, %v", t) 46 } 47 bv.Set(int32(off / int64(types.PtrSize))) //pointer in first slot 48 49 case types.TINTER: 50 // struct { Itab *tab; void *data; } 51 // or, when isnilinter(t)==true: 52 // struct { Type *type; void *data; } 53 if off&int64(types.PtrSize-1) != 0 { 54 base.Fatalf("typebits.Set: invalid alignment, %v", t) 55 } 56 // The first word of an interface is a pointer, but we don't 57 // treat it as such. 58 // 1. If it is a non-empty interface, the pointer points to an itab 59 // which is always in persistentalloc space. 60 // 2. If it is an empty interface, the pointer points to a _type. 61 // a. If it is a compile-time-allocated type, it points into 62 // the read-only data section. 63 // b. If it is a reflect-allocated type, it points into the Go heap. 64 // Reflect is responsible for keeping a reference to 65 // the underlying type so it won't be GCd. 66 // If we ever have a moving GC, we need to change this for 2b (as 67 // well as scan itabs to update their itab._type fields). 68 bv.Set(int32(off/int64(types.PtrSize) + 1)) // pointer in second slot 69 70 case types.TSLICE: 71 // struct { byte *array; uintgo len; uintgo cap; } 72 if off&int64(types.PtrSize-1) != 0 { 73 base.Fatalf("typebits.Set: invalid TARRAY alignment, %v", t) 74 } 75 bv.Set(int32(off / int64(types.PtrSize))) // pointer in first slot (BitsPointer) 76 77 case types.TARRAY: 78 elt := t.Elem() 79 if elt.Size() == 0 { 80 // Short-circuit for #20739. 81 break 82 } 83 for i := int64(0); i < t.NumElem(); i++ { 84 set(elt, off, bv, skip) 85 off += elt.Size() 86 } 87 88 case types.TSTRUCT: 89 for _, f := range t.Fields() { 90 set(f.Type, off+f.Offset, bv, skip) 91 } 92 93 default: 94 base.Fatalf("typebits.Set: unexpected type, %v", t) 95 } 96 }