* README.Portability: Remove note on an Irix compatibility issue.
[official-gcc.git] / libgo / go / runtime / ffi.go
blob164e1770ea2b55afadd4ac48466e3650ac5a74a1
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Only build this file if libffi is supported.
7 // +build libffi
9 package runtime
11 import "unsafe"
13 // This file contains the code that converts a Go type to an FFI type.
14 // This has to be written in Go because it allocates memory in the Go heap.
16 // C functions to return pointers to libffi variables.
18 func ffi_type_pointer() *__ffi_type
19 func ffi_type_sint8() *__ffi_type
20 func ffi_type_sint16() *__ffi_type
21 func ffi_type_sint32() *__ffi_type
22 func ffi_type_sint64() *__ffi_type
23 func ffi_type_uint8() *__ffi_type
24 func ffi_type_uint16() *__ffi_type
25 func ffi_type_uint32() *__ffi_type
26 func ffi_type_uint64() *__ffi_type
27 func ffi_type_float() *__ffi_type
28 func ffi_type_double() *__ffi_type
29 func ffi_supports_complex() bool
30 func ffi_type_complex_float() *__ffi_type
31 func ffi_type_complex_double() *__ffi_type
32 func ffi_type_void() *__ffi_type
34 // C functions defined in libffi.
36 //extern ffi_prep_cif
37 func ffi_prep_cif(*_ffi_cif, _ffi_abi, uint32, *__ffi_type, **__ffi_type) _ffi_status
39 // ffiFuncToCIF is called from C code.
40 //go:linkname ffiFuncToCIF runtime.ffiFuncToCIF
42 // ffiFuncToCIF builds an _ffi_cif struct for function described by ft.
43 func ffiFuncToCIF(ft *functype, isInterface bool, isMethod bool, cif *_ffi_cif) {
44 nparams := len(ft.in)
45 nargs := nparams
46 if isInterface {
47 nargs++
49 args := make([]*__ffi_type, nargs)
50 i := 0
51 off := 0
52 if isInterface {
53 args[0] = ffi_type_pointer()
54 off = 1
55 } else if isMethod {
56 args[0] = ffi_type_pointer()
57 i = 1
59 for ; i < nparams; i++ {
60 args[i+off] = typeToFFI(ft.in[i])
63 rettype := funcReturnFFI(ft)
65 var pargs **__ffi_type
66 if len(args) > 0 {
67 pargs = &args[0]
69 status := ffi_prep_cif(cif, _FFI_DEFAULT_ABI, uint32(nargs), rettype, pargs)
70 if status != _FFI_OK {
71 throw("ffi_prep_cif failed")
75 // funcReturnFFI returns the FFI definition of the return type of ft.
76 func funcReturnFFI(ft *functype) *__ffi_type {
77 c := len(ft.out)
78 if c == 0 {
79 return ffi_type_void()
82 // Compile a function that returns a zero-sized value as
83 // though it returns void. This works around a problem in
84 // libffi: it can't represent a zero-sized value.
85 var size uintptr
86 for _, v := range ft.out {
87 size += v.size
89 if size == 0 {
90 return ffi_type_void()
93 if c == 1 {
94 return typeToFFI(ft.out[0])
97 elements := make([]*__ffi_type, c+1)
98 for i, v := range ft.out {
99 elements[i] = typeToFFI(v)
101 elements[c] = nil
103 return &__ffi_type{
104 _type: _FFI_TYPE_STRUCT,
105 elements: &elements[0],
109 // typeToFFI returns the __ffi_type for a Go type.
110 func typeToFFI(typ *_type) *__ffi_type {
111 switch typ.kind & kindMask {
112 case kindBool:
113 switch unsafe.Sizeof(false) {
114 case 1:
115 return ffi_type_uint8()
116 case 4:
117 return ffi_type_uint32()
118 default:
119 throw("bad bool size")
120 return nil
122 case kindInt:
123 return intToFFI()
124 case kindInt8:
125 return ffi_type_sint8()
126 case kindInt16:
127 return ffi_type_sint16()
128 case kindInt32:
129 return ffi_type_sint32()
130 case kindInt64:
131 return ffi_type_sint64()
132 case kindUint:
133 switch unsafe.Sizeof(uint(0)) {
134 case 4:
135 return ffi_type_uint32()
136 case 8:
137 return ffi_type_uint64()
138 default:
139 throw("bad uint size")
140 return nil
142 case kindUint8:
143 return ffi_type_uint8()
144 case kindUint16:
145 return ffi_type_uint16()
146 case kindUint32:
147 return ffi_type_uint32()
148 case kindUint64:
149 return ffi_type_uint64()
150 case kindUintptr:
151 switch unsafe.Sizeof(uintptr(0)) {
152 case 4:
153 return ffi_type_uint32()
154 case 8:
155 return ffi_type_uint64()
156 default:
157 throw("bad uinptr size")
158 return nil
160 case kindFloat32:
161 return ffi_type_float()
162 case kindFloat64:
163 return ffi_type_double()
164 case kindComplex64:
165 if ffi_supports_complex() {
166 return ffi_type_complex_float()
167 } else {
168 return complexToFFI(ffi_type_float())
170 case kindComplex128:
171 if ffi_supports_complex() {
172 return ffi_type_complex_double()
173 } else {
174 return complexToFFI(ffi_type_double())
176 case kindArray:
177 return arrayToFFI((*arraytype)(unsafe.Pointer(typ)))
178 case kindChan, kindFunc, kindMap, kindPtr, kindUnsafePointer:
179 // These types are always simple pointers, and for FFI
180 // purposes nothing else matters.
181 return ffi_type_pointer()
182 case kindInterface:
183 return interfaceToFFI()
184 case kindSlice:
185 return sliceToFFI((*slicetype)(unsafe.Pointer(typ)))
186 case kindString:
187 return stringToFFI()
188 case kindStruct:
189 return structToFFI((*structtype)(unsafe.Pointer(typ)))
190 default:
191 throw("unknown type kind")
192 return nil
196 // interfaceToFFI returns an ffi_type for a Go interface type.
197 // This is used for both empty and non-empty interface types.
198 func interfaceToFFI() *__ffi_type {
199 elements := make([]*__ffi_type, 3)
200 elements[0] = ffi_type_pointer()
201 elements[1] = elements[0]
202 elements[2] = nil
203 return &__ffi_type{
204 _type: _FFI_TYPE_STRUCT,
205 elements: &elements[0],
209 // stringToFFI returns an ffi_type for a Go string type.
210 func stringToFFI() *__ffi_type {
211 elements := make([]*__ffi_type, 3)
212 elements[0] = ffi_type_pointer()
213 elements[1] = intToFFI()
214 elements[2] = nil
215 return &__ffi_type{
216 _type: _FFI_TYPE_STRUCT,
217 elements: &elements[0],
221 // structToFFI returns an ffi_type for a Go struct type.
222 func structToFFI(typ *structtype) *__ffi_type {
223 c := len(typ.fields)
224 if c == 0 {
225 return emptyStructToFFI()
228 fields := make([]*__ffi_type, c+1)
229 for i, v := range typ.fields {
230 fields[i] = typeToFFI(v.typ)
232 fields[c] = nil
233 return &__ffi_type{
234 _type: _FFI_TYPE_STRUCT,
235 elements: &fields[0],
239 // sliceToFFI returns an ffi_type for a Go slice type.
240 func sliceToFFI(typ *slicetype) *__ffi_type {
241 elements := make([]*__ffi_type, 4)
242 elements[0] = ffi_type_pointer()
243 elements[1] = intToFFI()
244 elements[2] = elements[1]
245 elements[3] = nil
246 return &__ffi_type{
247 _type: _FFI_TYPE_STRUCT,
248 elements: &elements[0],
252 // complexToFFI returns an ffi_type for a Go complex type.
253 // This is only used if libffi does not support complex types internally
254 // for this target.
255 func complexToFFI(ffiFloatType *__ffi_type) *__ffi_type {
256 elements := make([]*__ffi_type, 3)
257 elements[0] = ffiFloatType
258 elements[1] = ffiFloatType
259 elements[2] = nil
260 return &__ffi_type{
261 _type: _FFI_TYPE_STRUCT,
262 elements: &elements[0],
266 // arrayToFFI returns an ffi_type for a Go array type.
267 func arrayToFFI(typ *arraytype) *__ffi_type {
268 if typ.len == 0 {
269 return emptyStructToFFI()
271 elements := make([]*__ffi_type, typ.len+1)
272 et := typeToFFI(typ.elem)
273 for i := uintptr(0); i < typ.len; i++ {
274 elements[i] = et
276 elements[typ.len] = nil
277 return &__ffi_type{
278 _type: _FFI_TYPE_STRUCT,
279 elements: &elements[0],
283 // intToFFI returns an ffi_type for the Go int type.
284 func intToFFI() *__ffi_type {
285 switch unsafe.Sizeof(0) {
286 case 4:
287 return ffi_type_sint32()
288 case 8:
289 return ffi_type_sint64()
290 default:
291 throw("bad int size")
292 return nil
296 // emptyStructToFFI returns an ffi_type for an empty struct.
297 // The libffi library won't accept a struct with no fields.
298 func emptyStructToFFI() *__ffi_type {
299 elements := make([]*__ffi_type, 2)
300 elements[0] = ffi_type_void()
301 elements[1] = nil
302 return &__ffi_type{
303 _type: _FFI_TYPE_STRUCT,
304 elements: &elements[0],
308 //go:linkname makeCIF reflect.makeCIF
310 // makeCIF is used by the reflect package to allocate a CIF.
311 func makeCIF(ft *functype) *_ffi_cif {
312 cif := new(_ffi_cif)
313 ffiFuncToCIF(ft, false, false, cif)
314 return cif