Fix calling function pointers with FP arguments on arm32

This commit is contained in:
Svyatoslav Scherbina
2017-10-25 11:55:04 +03:00
committed by SvyatoslavScherbina
parent 043e6c54ca
commit 73379a6d59
3 changed files with 43 additions and 23 deletions
@@ -67,7 +67,7 @@ import konan.internal.ExportForCompiler
@ExportForCompiler @ExportForCompiler
private fun invokeImplUnitRet(ptr: COpaquePointer, vararg args: Any?): Unit = memScoped { private fun invokeImplUnitRet(ptr: COpaquePointer, vararg args: Any?): Unit = memScoped {
callWithVarargs(ptr.rawValue, nativeNullPtr, FFI_TYPE_KIND_VOID, args, emptyArray(), memScope) callWithVarargs(ptr.rawValue, nativeNullPtr, FFI_TYPE_KIND_VOID, args, null, memScope)
} }
@ExportForCompiler @ExportForCompiler
@@ -77,48 +77,48 @@ private fun invokeImplBooleanRet(ptr: COpaquePointer, vararg args: Any?): Boolea
@ExportForCompiler @ExportForCompiler
private fun invokeImplByteRet(ptr: COpaquePointer, vararg args: Any?): Byte = memScoped { private fun invokeImplByteRet(ptr: COpaquePointer, vararg args: Any?): Byte = memScoped {
val resultBuffer = allocFfiReturnValueBuffer<ByteVar>(ByteVar) val resultBuffer = allocFfiReturnValueBuffer<ByteVar>(ByteVar)
callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_SINT8, args, emptyArray(), memScope) callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_SINT8, args, null, memScope)
resultBuffer.value resultBuffer.value
} }
@ExportForCompiler @ExportForCompiler
private fun invokeImplShortRet(ptr: COpaquePointer, vararg args: Any?): Short = memScoped { private fun invokeImplShortRet(ptr: COpaquePointer, vararg args: Any?): Short = memScoped {
val resultBuffer = allocFfiReturnValueBuffer<ShortVar>(ShortVar) val resultBuffer = allocFfiReturnValueBuffer<ShortVar>(ShortVar)
callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_SINT16, args, emptyArray(), memScope) callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_SINT16, args, null, memScope)
resultBuffer.value resultBuffer.value
} }
@ExportForCompiler @ExportForCompiler
private fun invokeImplIntRet(ptr: COpaquePointer, vararg args: Any?): Int = memScoped { private fun invokeImplIntRet(ptr: COpaquePointer, vararg args: Any?): Int = memScoped {
val resultBuffer = allocFfiReturnValueBuffer<IntVar>(IntVar) val resultBuffer = allocFfiReturnValueBuffer<IntVar>(IntVar)
callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_SINT32, args, emptyArray(), memScope) callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_SINT32, args, null, memScope)
resultBuffer.value resultBuffer.value
} }
@ExportForCompiler @ExportForCompiler
private fun invokeImplLongRet(ptr: COpaquePointer, vararg args: Any?): Long = memScoped { private fun invokeImplLongRet(ptr: COpaquePointer, vararg args: Any?): Long = memScoped {
val resultBuffer = allocFfiReturnValueBuffer<LongVar>(LongVar) val resultBuffer = allocFfiReturnValueBuffer<LongVar>(LongVar)
callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_SINT64, args, emptyArray(), memScope) callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_SINT64, args, null, memScope)
resultBuffer.value resultBuffer.value
} }
@ExportForCompiler @ExportForCompiler
private fun invokeImplFloatRet(ptr: COpaquePointer, vararg args: Any?): Float = memScoped { private fun invokeImplFloatRet(ptr: COpaquePointer, vararg args: Any?): Float = memScoped {
val resultBuffer = allocFfiReturnValueBuffer<FloatVar>(FloatVar) val resultBuffer = allocFfiReturnValueBuffer<FloatVar>(FloatVar)
callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_FLOAT, args, emptyArray(), memScope) callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_FLOAT, args, null, memScope)
resultBuffer.value resultBuffer.value
} }
@ExportForCompiler @ExportForCompiler
private fun invokeImplDoubleRet(ptr: COpaquePointer, vararg args: Any?): Double = memScoped { private fun invokeImplDoubleRet(ptr: COpaquePointer, vararg args: Any?): Double = memScoped {
val resultBuffer = allocFfiReturnValueBuffer<DoubleVar>(DoubleVar) val resultBuffer = allocFfiReturnValueBuffer<DoubleVar>(DoubleVar)
callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_DOUBLE, args, emptyArray(), memScope) callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_DOUBLE, args, null, memScope)
resultBuffer.value resultBuffer.value
} }
@ExportForCompiler @ExportForCompiler
private fun invokeImplPointerRet(ptr: COpaquePointer, vararg args: Any?): COpaquePointer? = memScoped { private fun invokeImplPointerRet(ptr: COpaquePointer, vararg args: Any?): COpaquePointer? = memScoped {
val resultBuffer = allocFfiReturnValueBuffer<COpaquePointerVar>(COpaquePointerVar) val resultBuffer = allocFfiReturnValueBuffer<COpaquePointerVar>(COpaquePointerVar)
callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_POINTER, args, emptyArray(), memScope) callWithVarargs(ptr.rawValue, resultBuffer.rawPtr, FFI_TYPE_KIND_POINTER, args, null, memScope)
resultBuffer.value resultBuffer.value
} }
@@ -95,10 +95,10 @@ inline fun <reified T : CVariable> NativePlacement.allocFfiReturnValueBuffer(ty
} }
fun callWithVarargs(codePtr: NativePtr, returnValuePtr: NativePtr, returnTypeKind: FfiTypeKind, fun callWithVarargs(codePtr: NativePtr, returnValuePtr: NativePtr, returnTypeKind: FfiTypeKind,
fixedArguments: Array<out Any?>, variadicArguments: Array<out Any?>, fixedArguments: Array<out Any?>, variadicArguments: Array<out Any?>?,
argumentsPlacement: AutofreeScope) { argumentsPlacement: AutofreeScope) {
val totalArgumentsNumber = fixedArguments.size + variadicArguments.size val totalArgumentsNumber = fixedArguments.size + if (variadicArguments == null) 0 else variadicArguments.size
// All supported arguments take at most 8 bytes each: // All supported arguments take at most 8 bytes each:
val argumentsStorage = argumentsPlacement.allocArray<LongVar>(totalArgumentsNumber) val argumentsStorage = argumentsPlacement.allocArray<LongVar>(totalArgumentsNumber)
@@ -122,17 +122,30 @@ fun callWithVarargs(codePtr: NativePtr, returnValuePtr: NativePtr, returnTypeKin
addArgument(argument, isVariadic = false) addArgument(argument, isVariadic = false)
} }
for (argument in variadicArguments) { val variadicArgumentsNumber: Int
addArgument(argument, isVariadic = true)
if (variadicArguments != null) {
for (argument in variadicArguments) {
addArgument(argument, isVariadic = true)
}
variadicArgumentsNumber = variadicArguments.size
} else {
variadicArgumentsNumber = -1
} }
assert (index == totalArgumentsNumber) assert (index == totalArgumentsNumber)
callWithVarargs(codePtr, returnValuePtr, returnTypeKind, arguments.rawValue, types.rawValue, callFunctionPointer(codePtr, returnValuePtr, returnTypeKind, arguments.rawValue, types.rawValue,
fixedArguments.size, totalArgumentsNumber) totalArgumentsNumber, variadicArgumentsNumber)
} }
@SymbolName("Kotlin_Interop_callWithVarargs") @SymbolName("Kotlin_Interop_callFunctionPointer")
private external fun callWithVarargs(codePtr: NativePtr, returnValuePtr: NativePtr, returnTypeKind: FfiTypeKind, private external fun callFunctionPointer(
arguments: NativePtr, argumentTypeKinds: NativePtr, codePtr: NativePtr,
fixedArgumentsNumber: Int, totalArgumentsNumber: Int) returnValuePtr: NativePtr,
returnTypeKind: FfiTypeKind,
arguments: NativePtr,
argumentTypeKinds: NativePtr,
totalArgumentsNumber: Int,
variadicArgumentsNumber: Int
)
+12 -5
View File
@@ -61,9 +61,9 @@ ffi_type* convertFfiTypeKindToType(FfiTypeKind typeKind) {
extern "C" { extern "C" {
void Kotlin_Interop_callWithVarargs(void* codePtr, void* returnValuePtr, FfiTypeKind returnTypeKind, void Kotlin_Interop_callFunctionPointer(void* codePtr, void* returnValuePtr, FfiTypeKind returnTypeKind,
void** arguments, intptr_t* argumentTypeKinds, void** arguments, intptr_t* argumentTypeKinds,
int fixedArgumentsNumber, int totalArgumentsNumber) { int totalArgumentsNumber, int variadicArgumentsNumber) {
#ifdef KONAN_NO_FFI #ifdef KONAN_NO_FFI
RuntimeAssert(false, "Vararg calls are not supported on this platform"); RuntimeAssert(false, "Vararg calls are not supported on this platform");
#else #else
@@ -72,11 +72,18 @@ void Kotlin_Interop_callWithVarargs(void* codePtr, void* returnValuePtr, FfiType
for (int i = 0; i < totalArgumentsNumber; ++i) { for (int i = 0; i < totalArgumentsNumber; ++i) {
argumentTypes[i] = convertFfiTypeKindToType((FfiTypeKind) argumentTypeKinds[i]); argumentTypes[i] = convertFfiTypeKindToType((FfiTypeKind) argumentTypeKinds[i]);
} }
ffi_type* returnType = convertFfiTypeKindToType(returnTypeKind);
ffi_cif cif; ffi_cif cif;
ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, if (variadicArgumentsNumber < 0) {
fixedArgumentsNumber, totalArgumentsNumber, // Non-variadic.
convertFfiTypeKindToType(returnTypeKind), argumentTypes); ffi_prep_cif(&cif, FFI_DEFAULT_ABI, totalArgumentsNumber, returnType, argumentTypes);
} else {
int fixedArgumentsNumber = totalArgumentsNumber - variadicArgumentsNumber;
ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI,
fixedArgumentsNumber, totalArgumentsNumber,
returnType, argumentTypes);
}
ffi_call(&cif, (void (*)())codePtr, returnValuePtr, arguments); ffi_call(&cif, (void (*)())codePtr, returnValuePtr, arguments);
#endif #endif