github.com/goplus/llgo@v0.8.3/internal/abi/type.go (about) 1 /* 2 * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package abi 18 19 import ( 20 "unsafe" 21 ) 22 23 // ----------------------------------------------------------------------------- 24 25 // Type is the runtime representation of a Go type. 26 // 27 // Type is also referenced implicitly 28 // (in the form of expressions involving constants and arch.PtrSize) 29 // in cmd/compile/internal/reflectdata/reflect.go 30 // and cmd/link/internal/ld/decodesym.go 31 // (e.g. data[2*arch.PtrSize+4] references the TFlag field) 32 // unsafe.OffsetOf(Type{}.TFlag) cannot be used directly in those 33 // places because it varies with cross compilation and experiments. 34 type Type struct { 35 Size_ uintptr 36 PtrBytes uintptr // number of (prefix) bytes in the type that can contain pointers 37 Hash uint32 // hash of type; avoids computation in hash tables 38 TFlag TFlag // extra type information flags 39 Align_ uint8 // alignment of variable with this type 40 FieldAlign_ uint8 // alignment of struct field with this type 41 Kind_ uint8 // enumeration for C 42 // function for comparing objects of this type 43 // (ptr to object A, ptr to object B) -> ==? 44 Equal func(unsafe.Pointer, unsafe.Pointer) bool 45 // GCData stores the GC type data for the garbage collector. 46 // If the KindGCProg bit is set in kind, GCData is a GC program. 47 // Otherwise it is a ptrmask bitmap. See mbitmap.go for details. 48 GCData *byte 49 Str NameOff // string form 50 PtrToThis TypeOff // type for pointer to this type, may be zero 51 } 52 53 func (t *Type) Kind() Kind { return Kind(t.Kind_ & KindMask) } 54 55 // A Kind represents the specific kind of type that a Type represents. 56 // The zero Kind is not a valid kind. 57 type Kind uint 58 59 const ( 60 Invalid Kind = iota 61 Bool 62 Int 63 Int8 64 Int16 65 Int32 66 Int64 67 Uint 68 Uint8 69 Uint16 70 Uint32 71 Uint64 72 Uintptr 73 Float32 74 Float64 75 Complex64 76 Complex128 77 Array 78 Chan 79 Func 80 Interface 81 Map 82 Pointer 83 Slice 84 String 85 Struct 86 UnsafePointer 87 ) 88 89 const ( 90 // TODO (khr, drchase) why aren't these in TFlag? Investigate, fix if possible. 91 KindDirectIface = 1 << 5 92 KindGCProg = 1 << 6 // Type.gc points to GC program 93 KindMask = (1 << 5) - 1 94 ) 95 96 // TFlag is used by a Type to signal what extra type information is 97 // available in the memory directly following the Type value. 98 type TFlag uint8 99 100 const ( 101 // TFlagUncommon means that there is a data with a type, UncommonType, 102 // just beyond the shared-per-type common data. That is, the data 103 // for struct types will store their UncommonType at one offset, the 104 // data for interface types will store their UncommonType at a different 105 // offset. UncommonType is always accessed via a pointer that is computed 106 // using trust-us-we-are-the-implementors pointer arithmetic. 107 // 108 // For example, if t.Kind() == Struct and t.tflag&TFlagUncommon != 0, 109 // then t has UncommonType data and it can be accessed as: 110 // 111 // type structTypeUncommon struct { 112 // structType 113 // u UncommonType 114 // } 115 // u := &(*structTypeUncommon)(unsafe.Pointer(t)).u 116 TFlagUncommon TFlag = 1 << 0 117 118 // TFlagExtraStar means the name in the str field has an 119 // extraneous '*' prefix. This is because for most types T in 120 // a program, the type *T also exists and reusing the str data 121 // saves binary size. 122 TFlagExtraStar TFlag = 1 << 1 123 124 // TFlagNamed means the type has a name. 125 TFlagNamed TFlag = 1 << 2 126 127 // TFlagRegularMemory means that equal and hash functions can treat 128 // this type as a single region of t.size bytes. 129 TFlagRegularMemory TFlag = 1 << 3 130 ) 131 132 // NameOff is the offset to a name from moduledata.types. See resolveNameOff in runtime. 133 type NameOff int32 134 135 // TypeOff is the offset to a type from moduledata.types. See resolveTypeOff in runtime. 136 type TypeOff int32 137 138 // ----------------------------------------------------------------------------- 139 140 // ArrayType represents a fixed array type. 141 type ArrayType struct { 142 Type 143 Elem *Type // array element type 144 Slice *Type // slice type 145 Len uintptr 146 } 147 148 type SliceType struct { 149 Type 150 Elem *Type // slice element type 151 } 152 153 type MapType struct { 154 Type 155 Key *Type 156 Elem *Type 157 Bucket *Type // internal type representing a hash bucket 158 // function for hashing keys (ptr to key, seed) -> hash 159 Hasher func(unsafe.Pointer, uintptr) uintptr 160 KeySize uint8 // size of key slot 161 ValueSize uint8 // size of elem slot 162 BucketSize uint16 // size of bucket 163 Flags uint32 164 } 165 166 type PtrType struct { 167 Type 168 Elem *Type // pointer element (pointed at) type 169 } 170 171 type ChanDir int 172 173 const ( 174 RecvDir ChanDir = 1 << iota // <-chan 175 SendDir // chan<- 176 BothDir = RecvDir | SendDir // chan 177 InvalidDir ChanDir = 0 178 ) 179 180 // ChanType represents a channel type 181 type ChanType struct { 182 Type 183 Elem *Type 184 Dir ChanDir 185 } 186 187 // funcType represents a function type. 188 // 189 // A *Type for each in and out parameter is stored in an array that 190 // directly follows the funcType (and possibly its uncommonType). So 191 // a function type with one method, one input, and one output is: 192 // 193 // struct { 194 // funcType 195 // uncommonType 196 // [2]*rtype // [0] is in, [1] is out 197 // } 198 type FuncType struct { 199 Type 200 InCount uint16 201 OutCount uint16 // top bit is set if last input parameter is ... 202 } 203 204 type StructField struct { 205 Name Name // name is always non-empty 206 Typ *Type // type of field 207 Offset uintptr // byte offset of field 208 } 209 210 type StructType struct { 211 Type 212 PkgPath Name 213 Fields []StructField 214 } 215 216 // Name is an encoded type Name with optional extra data. 217 // 218 // The first byte is a bit field containing: 219 // 220 // 1<<0 the name is exported 221 // 1<<1 tag data follows the name 222 // 1<<2 pkgPath nameOff follows the name and tag 223 // 1<<3 the name is of an embedded (a.k.a. anonymous) field 224 // 225 // Following that, there is a varint-encoded length of the name, 226 // followed by the name itself. 227 // 228 // If tag data is present, it also has a varint-encoded length 229 // followed by the tag itself. 230 // 231 // If the import path follows, then 4 bytes at the end of 232 // the data form a nameOff. The import path is only set for concrete 233 // methods that are defined in a different package than their type. 234 // 235 // If a name starts with "*", then the exported bit represents 236 // whether the pointed to type is exported. 237 // 238 // Note: this encoding must match here and in: 239 // cmd/compile/internal/reflectdata/reflect.go 240 // cmd/link/internal/ld/decodesym.go 241 242 type Name struct { 243 Bytes *byte 244 } 245 246 type InterfaceType struct { 247 Type 248 PkgPath Name // import path 249 Methods []Imethod // sorted by hash 250 } 251 252 // Imethod represents a method on an interface type 253 type Imethod struct { 254 Name NameOff // name of method 255 Typ TypeOff // .(*FuncType) underneath 256 } 257 258 func (t *Type) Common() *Type { 259 return t 260 } 261 262 // Len returns the length of t if t is an array type, otherwise 0 263 func (t *Type) Len() int { 264 if t.Kind() == Array { 265 return int((*ArrayType)(unsafe.Pointer(t)).Len) 266 } 267 return 0 268 } 269 270 // Elem returns the element type for t if t is an array, channel, map, pointer, or slice, otherwise nil. 271 func (t *Type) Elem() *Type { 272 switch t.Kind() { 273 case Array: 274 tt := (*ArrayType)(unsafe.Pointer(t)) 275 return tt.Elem 276 case Chan: 277 tt := (*ChanType)(unsafe.Pointer(t)) 278 return tt.Elem 279 case Map: 280 tt := (*MapType)(unsafe.Pointer(t)) 281 return tt.Elem 282 case Pointer: 283 tt := (*PtrType)(unsafe.Pointer(t)) 284 return tt.Elem 285 case Slice: 286 tt := (*SliceType)(unsafe.Pointer(t)) 287 return tt.Elem 288 } 289 return nil 290 } 291 292 // StructType returns t cast to a *StructType, or nil if its tag does not match. 293 func (t *Type) StructType() *StructType { 294 if t.Kind() != Struct { 295 return nil 296 } 297 return (*StructType)(unsafe.Pointer(t)) 298 } 299 300 // MapType returns t cast to a *MapType, or nil if its tag does not match. 301 func (t *Type) MapType() *MapType { 302 if t.Kind() != Map { 303 return nil 304 } 305 return (*MapType)(unsafe.Pointer(t)) 306 } 307 308 // ArrayType returns t cast to a *ArrayType, or nil if its tag does not match. 309 func (t *Type) ArrayType() *ArrayType { 310 if t.Kind() != Array { 311 return nil 312 } 313 return (*ArrayType)(unsafe.Pointer(t)) 314 } 315 316 // FuncType returns t cast to a *FuncType, or nil if its tag does not match. 317 func (t *Type) FuncType() *FuncType { 318 if t.Kind() != Func { 319 return nil 320 } 321 return (*FuncType)(unsafe.Pointer(t)) 322 } 323 324 // InterfaceType returns t cast to a *InterfaceType, or nil if its tag does not match. 325 func (t *Type) InterfaceType() *InterfaceType { 326 if t.Kind() != Interface { 327 return nil 328 } 329 return (*InterfaceType)(unsafe.Pointer(t)) 330 } 331 332 // -----------------------------------------------------------------------------