github.com/gotranspile/cxgo@v0.3.8-0.20240118201721-29871598a6a2/types/types.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"sync"
     7  )
     8  
     9  type Node interface {
    10  	Uses() []Usage
    11  }
    12  
    13  type Type interface {
    14  	Sizeof() int
    15  	Kind() Kind
    16  	GoType() GoType
    17  }
    18  
    19  func UnkT(size int) Type {
    20  	if size <= 0 {
    21  		panic("size must be specified; set to ptr size, for example")
    22  	}
    23  	return &unkType{size: size}
    24  }
    25  
    26  type unkType struct {
    27  	isStruct bool
    28  	size     int
    29  }
    30  
    31  func (t *unkType) Kind() Kind {
    32  	return Unknown
    33  }
    34  
    35  func (t *unkType) Sizeof() int {
    36  	return t.size
    37  }
    38  
    39  var (
    40  	uint8Type  = IntType{size: 1, signed: false}
    41  	uint16Type = IntType{size: 2, signed: false}
    42  	uint32Type = IntType{size: 4, signed: false}
    43  	uint64Type = IntType{size: 8, signed: false}
    44  	int8Type   = IntType{size: 1, signed: true}
    45  	int16Type  = IntType{size: 2, signed: true}
    46  	int32Type  = IntType{size: 4, signed: true}
    47  	int64Type  = IntType{size: 8, signed: true}
    48  )
    49  
    50  func UntypedIntT(minSize int) IntType {
    51  	if minSize <= 0 {
    52  		panic("size must be specified")
    53  	}
    54  	return IntType{size: minSize, untyped: true}
    55  }
    56  
    57  func AsUntypedIntT(t IntType) IntType {
    58  	t.untyped = true
    59  	return t
    60  }
    61  
    62  func AsTypedIntT(t IntType) IntType {
    63  	t.untyped = false
    64  	return t
    65  }
    66  
    67  func ToPtrType(exp Type) PtrType {
    68  	if t, ok := Unwrap(exp).(PtrType); ok {
    69  		return t
    70  	}
    71  	return nil
    72  }
    73  
    74  func IntT(size int) IntType {
    75  	if size <= 0 {
    76  		panic("size must be specified")
    77  	}
    78  	switch size {
    79  	case 1:
    80  		return int8Type
    81  	case 2:
    82  		return int16Type
    83  	case 4:
    84  		return int32Type
    85  	case 8:
    86  		return int64Type
    87  	}
    88  	return IntType{size: size, signed: true}
    89  }
    90  
    91  func UintT(size int) IntType {
    92  	if size <= 0 {
    93  		panic("size must be specified")
    94  	}
    95  	switch size {
    96  	case 1:
    97  		return uint8Type
    98  	case 2:
    99  		return uint16Type
   100  	case 4:
   101  		return uint32Type
   102  	case 8:
   103  		return uint64Type
   104  	}
   105  	return IntType{size: size, signed: false}
   106  }
   107  
   108  var (
   109  	float32Type = FloatType{size: 4}
   110  	float64Type = FloatType{size: 8}
   111  )
   112  
   113  func FloatT(size int) FloatType {
   114  	switch size {
   115  	case 4:
   116  		return float32Type
   117  	case 8:
   118  		return float64Type
   119  	}
   120  	return FloatType{size: size}
   121  }
   122  
   123  func AsUntypedFloatT(t FloatType) FloatType {
   124  	t.untyped = true
   125  	return t
   126  }
   127  
   128  func AsTypedFloatT(t FloatType) FloatType {
   129  	t.untyped = false
   130  	return t
   131  }
   132  
   133  func NilT(size int) PtrType {
   134  	return &ptrType{size: size}
   135  }
   136  
   137  type PtrType interface {
   138  	Type
   139  	Elem() Type
   140  	SetElem(e Type)
   141  	ElemKind() Kind
   142  	ElemSizeof() int
   143  }
   144  
   145  func PtrT(size int, elem Type) PtrType {
   146  	if size <= 0 {
   147  		panic("size must be set")
   148  	} else if size < 4 {
   149  		panic("unlikely")
   150  	}
   151  	return &ptrType{elem: elem, size: size}
   152  }
   153  
   154  var _ PtrType = &ptrType{}
   155  
   156  type ptrType struct {
   157  	size int
   158  	zero bool
   159  	elem Type
   160  }
   161  
   162  func (t *ptrType) Sizeof() int {
   163  	return t.size
   164  }
   165  
   166  func (t *ptrType) Kind() Kind {
   167  	if t.zero {
   168  		return Nil
   169  	} else if t.elem == nil {
   170  		return UnsafePtr
   171  	}
   172  	return Ptr
   173  }
   174  
   175  func (t *ptrType) Elem() Type {
   176  	return t.elem
   177  }
   178  
   179  func (t *ptrType) SetElem(e Type) {
   180  	t.elem = e
   181  }
   182  
   183  func (t *ptrType) ElemKind() Kind {
   184  	e := t.elem
   185  	for e != nil {
   186  		p, ok := e.(*ptrType)
   187  		if !ok {
   188  			break
   189  		}
   190  		e = p.elem
   191  	}
   192  	if e == nil {
   193  		return UnsafePtr
   194  	}
   195  	return e.Kind()
   196  }
   197  
   198  func (t *ptrType) ElemSizeof() int {
   199  	if t.elem == nil {
   200  		return 1
   201  	}
   202  	return t.elem.Sizeof()
   203  }
   204  
   205  var (
   206  	_ PtrType = namedPtr{}
   207  	_ Named   = namedPtr{}
   208  )
   209  
   210  type namedPtr struct {
   211  	name *Ident
   212  	*ptrType
   213  }
   214  
   215  func (t namedPtr) Name() *Ident {
   216  	return t.name
   217  }
   218  
   219  func (t namedPtr) Underlying() Type {
   220  	return t.ptrType
   221  }
   222  
   223  func (t namedPtr) SetUnderlying(typ Type) Named {
   224  	panic("trying to change the named type")
   225  }
   226  
   227  func (t namedPtr) Incomplete() bool {
   228  	return false
   229  }
   230  
   231  type Field struct {
   232  	Name *Ident
   233  }
   234  
   235  func (f *Field) Type() Type {
   236  	return f.Name.CType(nil)
   237  }
   238  
   239  func FuncT(ptrSize int, ret Type, args ...*Field) *FuncType {
   240  	return funcT(ptrSize, ret, args, false)
   241  }
   242  
   243  func FuncTT(ptrSize int, ret Type, args ...Type) *FuncType {
   244  	fields := make([]*Field, 0, len(args))
   245  	for _, t := range args {
   246  		fields = append(fields, &Field{Name: NewUnnamed(t)})
   247  	}
   248  	return FuncT(ptrSize, ret, fields...)
   249  }
   250  
   251  func VarFuncT(ptrSize int, ret Type, args ...*Field) *FuncType {
   252  	return funcT(ptrSize, ret, args, true)
   253  }
   254  
   255  func VarFuncTT(ptrSize int, ret Type, args ...Type) *FuncType {
   256  	fields := make([]*Field, 0, len(args))
   257  	for _, t := range args {
   258  		fields = append(fields, &Field{Name: NewUnnamed(t)})
   259  	}
   260  	return VarFuncT(ptrSize, ret, fields...)
   261  }
   262  
   263  func checkFields(fields []*Field) {
   264  	for _, f := range fields {
   265  		if f.Name == nil {
   266  			panic("nil argument name")
   267  		}
   268  	}
   269  }
   270  
   271  func funcT(ptrSize int, ret Type, args []*Field, vari bool) *FuncType {
   272  	if ptrSize <= 0 {
   273  		panic("size must be set")
   274  	} else if ptrSize < 4 {
   275  		panic("unlikely")
   276  	}
   277  	checkFields(args)
   278  	return &FuncType{
   279  		size: ptrSize,
   280  		args: append([]*Field{}, args...),
   281  		ret:  ret,
   282  		vari: vari,
   283  	}
   284  }
   285  
   286  type FuncType struct {
   287  	ptr  bool
   288  	size int
   289  
   290  	args []*Field
   291  	ret  Type
   292  	vari bool
   293  }
   294  
   295  func (t *FuncType) Kind() Kind {
   296  	return Func
   297  }
   298  
   299  func (t *FuncType) Sizeof() int {
   300  	return t.size
   301  }
   302  
   303  func (t *FuncType) Return() Type {
   304  	return t.ret
   305  }
   306  
   307  func (t *FuncType) Variadic() bool {
   308  	return t.vari
   309  }
   310  
   311  func (t *FuncType) ArgN() int {
   312  	return len(t.args)
   313  }
   314  
   315  func (t *FuncType) Args() []*Field {
   316  	return append([]*Field{}, t.args...)
   317  }
   318  
   319  type IntType struct {
   320  	size    int
   321  	signed  bool
   322  	untyped bool
   323  }
   324  
   325  func (t IntType) Kind() Kind {
   326  	s := Unsigned
   327  	if t.signed {
   328  		s = Signed
   329  	}
   330  	if t.untyped {
   331  		return UntypedInt | s
   332  	}
   333  	return Int | s
   334  }
   335  
   336  func (t IntType) Sizeof() int {
   337  	return t.size
   338  }
   339  
   340  func (t IntType) Signed() bool {
   341  	return t.signed
   342  }
   343  
   344  type FloatType struct {
   345  	size    int
   346  	untyped bool
   347  }
   348  
   349  func (t FloatType) Kind() Kind {
   350  	if t.untyped {
   351  		return UntypedFloat
   352  	}
   353  	return Float
   354  }
   355  
   356  func (t FloatType) Sizeof() int {
   357  	return t.size
   358  }
   359  
   360  func BoolT() Type {
   361  	return BoolType{}
   362  }
   363  
   364  type BoolType struct{}
   365  
   366  func (t BoolType) Kind() Kind {
   367  	return Bool
   368  }
   369  
   370  func (t BoolType) Sizeof() int {
   371  	return 1
   372  }
   373  
   374  func ArrayT(elem Type, size int) Type {
   375  	if size < 0 {
   376  		panic("negative size")
   377  	}
   378  	return ArrayType{
   379  		elem:  elem,
   380  		size:  size,
   381  		slice: false,
   382  	}
   383  }
   384  
   385  func SliceT(elem Type) Type {
   386  	return ArrayType{
   387  		elem:  elem,
   388  		size:  0,
   389  		slice: true,
   390  	}
   391  }
   392  
   393  type ArrayType struct {
   394  	elem  Type
   395  	size  int
   396  	slice bool
   397  }
   398  
   399  func (t ArrayType) Kind() Kind {
   400  	return Array
   401  }
   402  
   403  func (t ArrayType) Elem() Type {
   404  	return t.elem
   405  }
   406  
   407  func (t ArrayType) Len() int {
   408  	if t.slice {
   409  		return 0
   410  	}
   411  	return t.size
   412  }
   413  
   414  func (t ArrayType) IsSlice() bool {
   415  	return t.slice
   416  }
   417  
   418  func (t ArrayType) Sizeof() int {
   419  	sz := t.size
   420  	if sz == 0 {
   421  		sz = 1
   422  	}
   423  	return sz * t.elem.Sizeof()
   424  }
   425  
   426  func NamedT(name string, typ Type) Named {
   427  	return NamedTGo(name, "", typ)
   428  }
   429  
   430  func NamedTGo(cname, goname string, typ Type) Named {
   431  	if cname == "" {
   432  		panic("name is not set")
   433  	}
   434  	if typ == nil {
   435  		panic("type is not set")
   436  	}
   437  	switch typ := typ.(type) {
   438  	case *ptrType:
   439  		named := &namedPtr{ptrType: typ}
   440  		named.name = NewIdentGo(cname, goname, named)
   441  		return named
   442  	}
   443  	named := &namedType{typ: typ}
   444  	named.name = NewIdentGo(cname, goname, named)
   445  	return named
   446  }
   447  
   448  type Named interface {
   449  	Type
   450  	Name() *Ident
   451  	Underlying() Type
   452  }
   453  
   454  type namedType struct {
   455  	name *Ident
   456  	typ  Type
   457  }
   458  
   459  func (t *namedType) String() string {
   460  	return t.name.String()
   461  }
   462  
   463  func (t *namedType) Kind() Kind {
   464  	return t.typ.Kind()
   465  }
   466  
   467  func (t *namedType) Name() *Ident {
   468  	return t.name
   469  }
   470  
   471  func (t *namedType) Underlying() Type {
   472  	return t.typ
   473  }
   474  
   475  func (t *namedType) Sizeof() int {
   476  	return t.typ.Sizeof()
   477  }
   478  
   479  var (
   480  	structMu    sync.RWMutex
   481  	structTypes = make(map[string]*StructType)
   482  	unionTypes  = make(map[string]*StructType)
   483  )
   484  
   485  func StructT(fields []*Field) *StructType {
   486  	checkFields(fields)
   487  	s := &StructType{
   488  		fields: append([]*Field{}, fields...),
   489  		union:  false,
   490  	}
   491  	h := s.hash()
   492  
   493  	structMu.RLock()
   494  	t, ok := structTypes[h]
   495  	structMu.RUnlock()
   496  	if ok {
   497  		return t
   498  	}
   499  
   500  	structMu.Lock()
   501  	defer structMu.Unlock()
   502  	if t, ok := structTypes[h]; ok {
   503  		return t
   504  	}
   505  	structTypes[h] = s
   506  	return s
   507  }
   508  
   509  func UnionT(fields []*Field) *StructType {
   510  	checkFields(fields)
   511  	s := &StructType{
   512  		fields: append([]*Field{}, fields...),
   513  		union:  true,
   514  	}
   515  	h := s.hash()
   516  
   517  	structMu.RLock()
   518  	t, ok := unionTypes[h]
   519  	structMu.RUnlock()
   520  	if ok {
   521  		return t
   522  	}
   523  
   524  	structMu.Lock()
   525  	defer structMu.Unlock()
   526  	if t, ok := unionTypes[h]; ok {
   527  		return t
   528  	}
   529  	unionTypes[h] = s
   530  	return s
   531  }
   532  
   533  type StructType struct {
   534  	Where  string
   535  	fields []*Field
   536  	union  bool
   537  }
   538  
   539  func (t *StructType) hash() string {
   540  	buf := bytes.NewBuffer(nil)
   541  	for _, f := range t.fields {
   542  		buf.WriteString(f.Name.Name)
   543  		buf.WriteByte(0)
   544  		fmt.Fprintf(buf, "%p", f.Type())
   545  		buf.WriteByte(0)
   546  	}
   547  	return buf.String()
   548  }
   549  
   550  func (t *StructType) Fields() []*Field {
   551  	return append([]*Field{}, t.fields...)
   552  }
   553  
   554  func (t *StructType) Kind() Kind {
   555  	return Struct
   556  }
   557  
   558  func (t *StructType) Sizeof() int {
   559  	if t.union {
   560  		max := 0
   561  		for _, f := range t.fields {
   562  			if sz := f.Type().Sizeof(); sz > max {
   563  				max = sz
   564  			}
   565  		}
   566  		return max
   567  	}
   568  	n := 0
   569  	for _, f := range t.fields {
   570  		n += f.Type().Sizeof()
   571  	}
   572  	if n == 0 {
   573  		n = 1
   574  	}
   575  	return n
   576  }