github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/type.go (about)

     1  package ccall
     2  
     3  /*
     4  #cgo CFLAGS: -I../
     5  #cgo CFLAGS: -Iinclude
     6  
     7  #include <jit/jit.h>
     8  */
     9  import "C"
    10  import (
    11  	"fmt"
    12  	"io"
    13  	"io/ioutil"
    14  	"os"
    15  	"reflect"
    16  	"unsafe"
    17  )
    18  
    19  type Type struct {
    20  	c C.jit_type_t
    21  }
    22  
    23  type Types []*Type
    24  
    25  func (t Types) c() *C.jit_type_t {
    26  	types := make([]C.jit_type_t, len(t))
    27  	for idx, tt := range t {
    28  		types[idx] = tt.c
    29  	}
    30  	return (*C.jit_type_t)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&types)).Data))
    31  }
    32  
    33  // Type kinds that may be returned by Kind().
    34  var (
    35  	JIT_TYPE_INVALID       = C.JIT_TYPE_INVALID
    36  	JIT_TYPE_VOID          = C.JIT_TYPE_VOID
    37  	JIT_TYPE_SBYTE         = C.JIT_TYPE_SBYTE
    38  	JIT_TYPE_UBYTE         = C.JIT_TYPE_UBYTE
    39  	JIT_TYPE_SHORT         = C.JIT_TYPE_SHORT
    40  	JIT_TYPE_USHORT        = C.JIT_TYPE_USHORT
    41  	JIT_TYPE_INT           = C.JIT_TYPE_INT
    42  	JIT_TYPE_UINT          = C.JIT_TYPE_UINT
    43  	JIT_TYPE_NINT          = C.JIT_TYPE_NINT
    44  	JIT_TYPE_NUINT         = C.JIT_TYPE_NUINT
    45  	JIT_TYPE_LONG          = C.JIT_TYPE_LONG
    46  	JIT_TYPE_ULONG         = C.JIT_TYPE_ULONG
    47  	JIT_TYPE_FLOAT32       = C.JIT_TYPE_FLOAT32
    48  	JIT_TYPE_FLOAT64       = C.JIT_TYPE_FLOAT64
    49  	JIT_TYPE_NFLOAT        = C.JIT_TYPE_NFLOAT
    50  	JIT_TYPE_MAX_PRIMITIVE = JIT_TYPE_NFLOAT
    51  	JIT_TYPE_STRUCT        = C.JIT_TYPE_STRUCT
    52  	JIT_TYPE_UNION         = C.JIT_TYPE_UNION
    53  	JIT_TYPE_SIGNATURE     = C.JIT_TYPE_SIGNATURE
    54  	JIT_TYPE_PTR           = C.JIT_TYPE_PTR
    55  	JIT_TYPE_FIRST_TAGGED  = C.JIT_TYPE_FIRST_TAGGED
    56  )
    57  
    58  // Special tag types.
    59  var (
    60  	JIT_TYPETAG_NAME           = C.JIT_TYPETAG_NAME
    61  	JIT_TYPETAG_STRUCT_NAME    = C.JIT_TYPETAG_STRUCT_NAME
    62  	JIT_TYPETAG_UNION_NAME     = C.JIT_TYPETAG_UNION_NAME
    63  	JIT_TYPETAG_ENUM_NAME      = C.JIT_TYPETAG_ENUM_NAME
    64  	JIT_TYPETAG_CONST          = C.JIT_TYPETAG_CONST
    65  	JIT_TYPETAG_VOLATILE       = C.JIT_TYPETAG_VOLATILE
    66  	JIT_TYPETAG_REFERENCE      = C.JIT_TYPETAG_REFERENCE
    67  	JIT_TYPETAG_OUTPUT         = C.JIT_TYPETAG_OUTPUT
    68  	JIT_TYPETAG_RESTRICT       = C.JIT_TYPETAG_RESTRICT
    69  	JIT_TYPETAG_SYS_BOOL       = C.JIT_TYPETAG_SYS_BOOL
    70  	JIT_TYPETAG_SYS_CHAR       = C.JIT_TYPETAG_SYS_CHAR
    71  	JIT_TYPETAG_SYS_SCHAR      = C.JIT_TYPETAG_SYS_SCHAR
    72  	JIT_TYPETAG_SYS_UCHAR      = C.JIT_TYPETAG_SYS_UCHAR
    73  	JIT_TYPETAG_SYS_SHORT      = C.JIT_TYPETAG_SYS_SHORT
    74  	JIT_TYPETAG_SYS_USHORT     = C.JIT_TYPETAG_SYS_USHORT
    75  	JIT_TYPETAG_SYS_INT        = C.JIT_TYPETAG_SYS_INT
    76  	JIT_TYPETAG_SYS_UINT       = C.JIT_TYPETAG_SYS_UINT
    77  	JIT_TYPETAG_SYS_LONG       = C.JIT_TYPETAG_SYS_LONG
    78  	JIT_TYPETAG_SYS_ULONG      = C.JIT_TYPETAG_SYS_ULONG
    79  	JIT_TYPETAG_SYS_LONGLONG   = C.JIT_TYPETAG_SYS_LONGLONG
    80  	JIT_TYPETAG_SYS_ULONGLONG  = C.JIT_TYPETAG_SYS_ULONGLONG
    81  	JIT_TYPETAG_SYS_FLOAT      = C.JIT_TYPETAG_SYS_FLOAT
    82  	JIT_TYPETAG_SYS_DOUBLE     = C.JIT_TYPETAG_SYS_DOUBLE
    83  	JIT_TYPETAG_SYS_LONGDOUBLE = C.JIT_TYPETAG_SYS_LONGDOUBLE
    84  )
    85  
    86  var (
    87  	ptrsize         = uint(unsafe.Sizeof(unsafe.Pointer(nil)))
    88  	TypeInt         = &Type{C.jit_type_int}
    89  	TypeVoidPtr     = &Type{C.jit_type_void_ptr}
    90  	TypeCharPtr     = &Type{C.jit_type_create_pointer(C.jit_type_sys_char, 0)}
    91  	TypeGoInt       = &Type{C.jit_type_sys_longlong}
    92  	TypeGoString    = CreateStruct([]*Type{TypeCharPtr, TypeInt}, 0)
    93  	TypeGoInterface = CreateStruct([]*Type{TypeVoidPtr, TypeVoidPtr}, 0)
    94  	TypeVoid        = &Type{C.jit_type_void}
    95  	TypeFloat32     = &Type{C.jit_type_float32}
    96  	TypeFloat64     = &Type{C.jit_type_float64}
    97  )
    98  
    99  func toType(c C.jit_type_t) *Type {
   100  	return &Type{c}
   101  }
   102  
   103  func ReflectTypeToType(typ reflect.Type) *Type {
   104  	switch typ.Kind() {
   105  	case reflect.Int:
   106  		return TypeGoInt
   107  	case reflect.String:
   108  		return TypeGoString
   109  	case reflect.Interface:
   110  		return TypeGoInterface
   111  	}
   112  	fmt.Println("unknown type = ", typ)
   113  	return TypeVoid
   114  }
   115  
   116  func CreateStruct(fields Types, incref int) *Type {
   117  	return toType(C.jit_type_create_struct(fields.c(), C.uint(len(fields)), C.int(incref)))
   118  }
   119  
   120  func CreateUnion(fields Types, incref int) *Type {
   121  	return toType(C.jit_type_create_union(fields.c(), C.uint(len(fields)), C.int(incref)))
   122  }
   123  
   124  func CreateSignature(args Types, rtype *Type) *Type {
   125  	if rtype == nil {
   126  		rtype = TypeVoid
   127  	}
   128  	return toType(C.jit_type_create_signature(C.jit_abi_cdecl, rtype.c, args.c(), C.uint(len(args)), 0))
   129  }
   130  
   131  func BestAlignment() uint {
   132  	return uint(C.jit_type_best_alignment())
   133  }
   134  
   135  func (t *Type) Copy() *Type {
   136  	return toType(C.jit_type_copy(t.c))
   137  }
   138  
   139  func (t *Type) Free() {
   140  	C.jit_type_free(t.c)
   141  }
   142  
   143  func (t *Type) CreatePointer(incref int) *Type {
   144  	return toType(C.jit_type_create_pointer(t.c, C.int(incref)))
   145  }
   146  
   147  func (t *Type) SetSizeAndAlignment(size, alignment int) {
   148  	C.jit_type_set_size_and_alignment(t.c, C.jit_nint(size), C.jit_nint(alignment))
   149  }
   150  
   151  func (t *Type) SetOffset(fieldIndex, offset uint) {
   152  	C.jit_type_set_offset(t.c, C.uint(fieldIndex), C.jit_nuint(offset))
   153  }
   154  
   155  func (t *Type) Kind() int {
   156  	return int(C.jit_type_get_kind(t.c))
   157  }
   158  
   159  func (t *Type) Size() uint {
   160  	return uint(C.jit_type_get_size(t.c))
   161  }
   162  
   163  func (t *Type) Alignment() uint {
   164  	return uint(C.jit_type_get_alignment(t.c))
   165  }
   166  
   167  func (t *Type) NumFields() uint {
   168  	return uint(C.jit_type_num_fields(t.c))
   169  }
   170  
   171  func (t *Type) Field(index uint) *Type {
   172  	return toType(C.jit_type_get_field(t.c, C.uint(index)))
   173  }
   174  
   175  func (t *Type) Offset(index uint) uint {
   176  	return uint(C.jit_type_get_offset(t.c, C.uint(index)))
   177  }
   178  
   179  func (t *Type) Name(index uint) string {
   180  	return C.GoString(C.jit_type_get_name(t.c, C.uint(index)))
   181  }
   182  
   183  func (t *Type) FindName(name string) uint {
   184  	return uint(C.jit_type_find_name(t.c, C.CString(name)))
   185  }
   186  
   187  func (t *Type) NumParams() uint {
   188  	return uint(C.jit_type_num_params(t.c))
   189  }
   190  
   191  func (t *Type) Return() *Type {
   192  	return toType(C.jit_type_get_return(t.c))
   193  }
   194  
   195  func (t *Type) Param(index uint) *Type {
   196  	return toType(C.jit_type_get_param(t.c, C.uint(index)))
   197  }
   198  
   199  func (t *Type) Ref() *Type {
   200  	return toType(C.jit_type_get_ref(t.c))
   201  }
   202  
   203  func (t *Type) TaggedType() *Type {
   204  	return toType(C.jit_type_get_tagged_type(t.c))
   205  }
   206  
   207  func (t *Type) SetTaggedType(underlying *Type, incref int) {
   208  	C.jit_type_set_tagged_type(t.c, underlying.c, C.int(incref))
   209  }
   210  
   211  func (t *Type) TaggedKind() int {
   212  	return int(C.jit_type_get_tagged_kind(t.c))
   213  }
   214  
   215  func (t *Type) TaggedData() unsafe.Pointer {
   216  	return C.jit_type_get_tagged_data(t.c)
   217  }
   218  
   219  func (t *Type) IsPrimitive() bool {
   220  	return int(C.jit_type_is_primitive(t.c)) == 1
   221  }
   222  
   223  func (t *Type) IsStruct() bool {
   224  	return int(C.jit_type_is_struct(t.c)) == 1
   225  }
   226  
   227  func (t *Type) IsUnion() bool {
   228  	return int(C.jit_type_is_union(t.c)) == 1
   229  }
   230  
   231  func (t *Type) IsSignature() bool {
   232  	return int(C.jit_type_is_signature(t.c)) == 1
   233  }
   234  
   235  func (t *Type) IsPointer() bool {
   236  	return int(C.jit_type_is_pointer(t.c)) == 1
   237  }
   238  
   239  func (t *Type) IsTagged() bool {
   240  	return int(C.jit_type_is_tagged(t.c)) == 1
   241  }
   242  
   243  func (t *Type) RemoveTags() *Type {
   244  	return toType(C.jit_type_remove_tags(t.c))
   245  }
   246  
   247  func (t *Type) Normalize() *Type {
   248  	return toType(C.jit_type_normalize(t.c))
   249  }
   250  
   251  func (t *Type) PromoteInt() *Type {
   252  	return toType(C.jit_type_promote_int(t.c))
   253  }
   254  
   255  func (t *Type) ReturnViaPointer() int {
   256  	return int(C.jit_type_return_via_pointer(t.c))
   257  }
   258  
   259  func (t *Type) HasTag(kind int) bool {
   260  	return int(C.jit_type_has_tag(t.c, C.int(kind))) == 1
   261  }
   262  
   263  func (t *Type) Dump(w io.Writer) error {
   264  	tmpfile, err := ioutil.TempFile("", "")
   265  	if err != nil {
   266  		return err
   267  	}
   268  	defer os.Remove(tmpfile.Name())
   269  	file := C.fdopen(C.int(tmpfile.Fd()), C.CString("w"))
   270  	C.jit_dump_type(file, t.c)
   271  	C.fclose(file)
   272  	contents, err := ioutil.ReadFile(tmpfile.Name())
   273  	if err != nil {
   274  		return err
   275  	}
   276  	if _, err := w.Write(contents); err != nil {
   277  		return err
   278  	}
   279  	return nil
   280  }