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  // -----------------------------------------------------------------------------