From 8c6718ab91416a1f60a9dfbacb867dfc03688adb Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 11 May 2017 11:27:14 +0300 Subject: [PATCH] Always use at least register-sized buffer for return value in ffi_call As required by the libffi docs. --- .../native/kotlin/kotlinx/cinterop/Varargs.kt | 18 ++++++++++++++++++ .../native/interop/gen/jvm/StubGenerator.kt | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt index 271e4866c48..3593284bfa9 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt @@ -69,6 +69,24 @@ private tailrec fun convertArgument( else -> throw Error("unsupported argument: $argument") } +inline fun NativePlacement.allocFfiReturnValueBuffer(type: CVariable.Type): T { + var size = type.size + var align = type.align + + // libffi requires return value buffer to be no smaller than system register size; + // TODO: system register size is not exactly the same as pointer size. + + if (size < pointerSize) { + size = pointerSize.toLong() + } + + if (align < pointerSize) { + align = pointerSize + } + + return this.alloc(size, align).reinterpret() +} + fun callWithVarargs(codePtr: NativePtr, returnValuePtr: NativePtr, returnTypeKind: FfiTypeKind, fixedArguments: Array, variadicArguments: Array, argumentsPlacement: NativePlacement) { diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt index bbc656f017d..ff0daa5b428 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt @@ -891,7 +891,8 @@ class StubGenerator( val returnValueMirror = mirror(func.returnType) block(header) { val resultPtr = if (!func.returnsVoid()) { - out("val resultVar = alloc<${returnValueMirror.pointedTypeName}>()") + val returnType = returnValueMirror.pointedTypeName + out("val resultVar = allocFfiReturnValueBuffer<$returnType>($returnType)") "resultVar.rawPtr" } else { "nativeNullPtr"