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 }