github.com/gotranspile/cxgo@v0.3.7/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) Type {
   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 NilT(size int) PtrType {
   124  	return &ptrType{size: size}
   125  }
   126  
   127  type PtrType interface {
   128  	Type
   129  	Elem() Type
   130  	SetElem(e Type)
   131  	ElemKind() Kind
   132  	ElemSizeof() int
   133  }
   134  
   135  func PtrT(size int, elem Type) PtrType {
   136  	if size <= 0 {
   137  		panic("size must be set")
   138  	} else if size < 4 {
   139  		panic("unlikely")
   140  	}
   141  	return &ptrType{elem: elem, size: size}
   142  }
   143  
   144  var _ PtrType = &ptrType{}
   145  
   146  type ptrType struct {
   147  	size int
   148  	zero bool
   149  	elem Type
   150  }
   151  
   152  func (t *ptrType) Sizeof() int {
   153  	return t.size
   154  }
   155  
   156  func (t *ptrType) Kind() Kind {
   157  	if t.zero {
   158  		return Nil
   159  	} else if t.elem == nil {
   160  		return UnsafePtr
   161  	}
   162  	return Ptr
   163  }
   164  
   165  func (t *ptrType) Elem() Type {
   166  	return t.elem
   167  }
   168  
   169  func (t *ptrType) SetElem(e Type) {
   170  	t.elem = e
   171  }
   172  
   173  func (t *ptrType) ElemKind() Kind {
   174  	e := t.elem
   175  	for e != nil {
   176  		p, ok := e.(*ptrType)
   177  		if !ok {
   178  			break
   179  		}
   180  		e = p.elem
   181  	}
   182  	if e == nil {
   183  		return UnsafePtr
   184  	}
   185  	return e.Kind()
   186  }
   187  
   188  func (t *ptrType) ElemSizeof() int {
   189  	if t.elem == nil {
   190  		return 1
   191  	}
   192  	return t.elem.Sizeof()
   193  }
   194  
   195  var (
   196  	_ PtrType = namedPtr{}
   197  	_ Named   = namedPtr{}
   198  )
   199  
   200  type namedPtr struct {
   201  	name *Ident
   202  	*ptrType
   203  }
   204  
   205  func (t namedPtr) Name() *Ident {
   206  	return t.name
   207  }
   208  
   209  func (t namedPtr) Underlying() Type {
   210  	return t.ptrType
   211  }
   212  
   213  func (t namedPtr) SetUnderlying(typ Type) Named {
   214  	panic("trying to change the named type")
   215  }
   216  
   217  func (t namedPtr) Incomplete() bool {
   218  	return false
   219  }
   220  
   221  type Field struct {
   222  	Name *Ident
   223  }
   224  
   225  func (f *Field) Type() Type {
   226  	return f.Name.CType(nil)
   227  }
   228  
   229  func FuncT(ptrSize int, ret Type, args ...*Field) *FuncType {
   230  	return funcT(ptrSize, ret, args, false)
   231  }
   232  
   233  func FuncTT(ptrSize int, ret Type, args ...Type) *FuncType {
   234  	fields := make([]*Field, 0, len(args))
   235  	for _, t := range args {
   236  		fields = append(fields, &Field{Name: NewUnnamed(t)})
   237  	}
   238  	return FuncT(ptrSize, ret, fields...)
   239  }
   240  
   241  func VarFuncT(ptrSize int, ret Type, args ...*Field) *FuncType {
   242  	return funcT(ptrSize, ret, args, true)
   243  }
   244  
   245  func VarFuncTT(ptrSize int, ret Type, args ...Type) *FuncType {
   246  	fields := make([]*Field, 0, len(args))
   247  	for _, t := range args {
   248  		fields = append(fields, &Field{Name: NewUnnamed(t)})
   249  	}
   250  	return VarFuncT(ptrSize, ret, fields...)
   251  }
   252  
   253  func checkFields(fields []*Field) {
   254  	for _, f := range fields {
   255  		if f.Name == nil {
   256  			panic("nil argument name")
   257  		}
   258  	}
   259  }
   260  
   261  func funcT(ptrSize int, ret Type, args []*Field, vari bool) *FuncType {
   262  	if ptrSize <= 0 {
   263  		panic("size must be set")
   264  	} else if ptrSize < 4 {
   265  		panic("unlikely")
   266  	}
   267  	checkFields(args)
   268  	return &FuncType{
   269  		size: ptrSize,
   270  		args: append([]*Field{}, args...),
   271  		ret:  ret,
   272  		vari: vari,
   273  	}
   274  }
   275  
   276  type FuncType struct {
   277  	ptr  bool
   278  	size int
   279  
   280  	args []*Field
   281  	ret  Type
   282  	vari bool
   283  }
   284  
   285  func (t *FuncType) Kind() Kind {
   286  	return Func
   287  }
   288  
   289  func (t *FuncType) Sizeof() int {
   290  	return t.size
   291  }
   292  
   293  func (t *FuncType) Return() Type {
   294  	return t.ret
   295  }
   296  
   297  func (t *FuncType) Variadic() bool {
   298  	return t.vari
   299  }
   300  
   301  func (t *FuncType) ArgN() int {
   302  	return len(t.args)
   303  }
   304  
   305  func (t *FuncType) Args() []*Field {
   306  	return append([]*Field{}, t.args...)
   307  }
   308  
   309  type IntType struct {
   310  	size    int
   311  	signed  bool
   312  	untyped bool
   313  }
   314  
   315  func (t IntType) Kind() Kind {
   316  	s := Unsigned
   317  	if t.signed {
   318  		s = Signed
   319  	}
   320  	if t.untyped {
   321  		return UntypedInt | s
   322  	}
   323  	return Int | s
   324  }
   325  
   326  func (t IntType) Sizeof() int {
   327  	return t.size
   328  }
   329  
   330  func (t IntType) Signed() bool {
   331  	return t.signed
   332  }
   333  
   334  type FloatType struct {
   335  	size int
   336  }
   337  
   338  func (t FloatType) Kind() Kind {
   339  	return Float
   340  }
   341  
   342  func (t FloatType) Sizeof() int {
   343  	return t.size
   344  }
   345  
   346  func BoolT() Type {
   347  	return BoolType{}
   348  }
   349  
   350  type BoolType struct{}
   351  
   352  func (t BoolType) Kind() Kind {
   353  	return Bool
   354  }
   355  
   356  func (t BoolType) Sizeof() int {
   357  	return 1
   358  }
   359  
   360  func ArrayT(elem Type, size int) Type {
   361  	if size < 0 {
   362  		panic("negative size")
   363  	}
   364  	return ArrayType{
   365  		elem:  elem,
   366  		size:  size,
   367  		slice: false,
   368  	}
   369  }
   370  
   371  func SliceT(elem Type) Type {
   372  	return ArrayType{
   373  		elem:  elem,
   374  		size:  0,
   375  		slice: true,
   376  	}
   377  }
   378  
   379  type ArrayType struct {
   380  	elem  Type
   381  	size  int
   382  	slice bool
   383  }
   384  
   385  func (t ArrayType) Kind() Kind {
   386  	return Array
   387  }
   388  
   389  func (t ArrayType) Elem() Type {
   390  	return t.elem
   391  }
   392  
   393  func (t ArrayType) Len() int {
   394  	if t.slice {
   395  		return 0
   396  	}
   397  	return t.size
   398  }
   399  
   400  func (t ArrayType) IsSlice() bool {
   401  	return t.slice
   402  }
   403  
   404  func (t ArrayType) Sizeof() int {
   405  	sz := t.size
   406  	if sz == 0 {
   407  		sz = 1
   408  	}
   409  	return sz * t.elem.Sizeof()
   410  }
   411  
   412  func NamedT(name string, typ Type) Named {
   413  	return NamedTGo(name, "", typ)
   414  }
   415  
   416  func NamedTGo(cname, goname string, typ Type) Named {
   417  	if cname == "" {
   418  		panic("name is not set")
   419  	}
   420  	if typ == nil {
   421  		panic("type is not set")
   422  	}
   423  	switch typ := typ.(type) {
   424  	case *ptrType:
   425  		named := &namedPtr{ptrType: typ}
   426  		named.name = NewIdentGo(cname, goname, named)
   427  		return named
   428  	}
   429  	named := &namedType{typ: typ}
   430  	named.name = NewIdentGo(cname, goname, named)
   431  	return named
   432  }
   433  
   434  type Named interface {
   435  	Type
   436  	Name() *Ident
   437  	Underlying() Type
   438  }
   439  
   440  type namedType struct {
   441  	name *Ident
   442  	typ  Type
   443  }
   444  
   445  func (t *namedType) String() string {
   446  	return t.name.String()
   447  }
   448  
   449  func (t *namedType) Kind() Kind {
   450  	return t.typ.Kind()
   451  }
   452  
   453  func (t *namedType) Name() *Ident {
   454  	return t.name
   455  }
   456  
   457  func (t *namedType) Underlying() Type {
   458  	return t.typ
   459  }
   460  
   461  func (t *namedType) Sizeof() int {
   462  	return t.typ.Sizeof()
   463  }
   464  
   465  var (
   466  	structMu    sync.RWMutex
   467  	structTypes = make(map[string]*StructType)
   468  	unionTypes  = make(map[string]*StructType)
   469  )
   470  
   471  func StructT(fields []*Field) *StructType {
   472  	checkFields(fields)
   473  	s := &StructType{
   474  		fields: append([]*Field{}, fields...),
   475  		union:  false,
   476  	}
   477  	h := s.hash()
   478  
   479  	structMu.RLock()
   480  	t, ok := structTypes[h]
   481  	structMu.RUnlock()
   482  	if ok {
   483  		return t
   484  	}
   485  
   486  	structMu.Lock()
   487  	defer structMu.Unlock()
   488  	if t, ok := structTypes[h]; ok {
   489  		return t
   490  	}
   491  	structTypes[h] = s
   492  	return s
   493  }
   494  
   495  func UnionT(fields []*Field) *StructType {
   496  	checkFields(fields)
   497  	s := &StructType{
   498  		fields: append([]*Field{}, fields...),
   499  		union:  true,
   500  	}
   501  	h := s.hash()
   502  
   503  	structMu.RLock()
   504  	t, ok := unionTypes[h]
   505  	structMu.RUnlock()
   506  	if ok {
   507  		return t
   508  	}
   509  
   510  	structMu.Lock()
   511  	defer structMu.Unlock()
   512  	if t, ok := unionTypes[h]; ok {
   513  		return t
   514  	}
   515  	unionTypes[h] = s
   516  	return s
   517  }
   518  
   519  type StructType struct {
   520  	Where  string
   521  	fields []*Field
   522  	union  bool
   523  }
   524  
   525  func (t *StructType) hash() string {
   526  	buf := bytes.NewBuffer(nil)
   527  	for _, f := range t.fields {
   528  		buf.WriteString(f.Name.Name)
   529  		buf.WriteByte(0)
   530  		fmt.Fprintf(buf, "%p", f.Type())
   531  		buf.WriteByte(0)
   532  	}
   533  	return buf.String()
   534  }
   535  
   536  func (t *StructType) Fields() []*Field {
   537  	return append([]*Field{}, t.fields...)
   538  }
   539  
   540  func (t *StructType) Kind() Kind {
   541  	return Struct
   542  }
   543  
   544  func (t *StructType) Sizeof() int {
   545  	if t.union {
   546  		max := 0
   547  		for _, f := range t.fields {
   548  			if sz := f.Type().Sizeof(); sz > max {
   549  				max = sz
   550  			}
   551  		}
   552  		return max
   553  	}
   554  	n := 0
   555  	for _, f := range t.fields {
   556  		n += f.Type().Sizeof()
   557  	}
   558  	if n == 0 {
   559  		n = 1
   560  	}
   561  	return n
   562  }