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
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
@@ -77,48 +77,48 @@ private fun invokeImplBooleanRet(ptr: COpaquePointer, vararg args: Any?): Boolea
@ExportForCompiler
private fun invokeImplByteRet(ptr: COpaquePointer, vararg args: Any?): Byte = memScoped {
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
}
@ExportForCompiler
private fun invokeImplShortRet(ptr: COpaquePointer, vararg args: Any?): Short = memScoped {
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
}
@ExportForCompiler
private fun invokeImplIntRet(ptr: COpaquePointer, vararg args: Any?): Int = memScoped {
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
}
@ExportForCompiler
private fun invokeImplLongRet(ptr: COpaquePointer, vararg args: Any?): Long = memScoped {
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
}
@ExportForCompiler
private fun invokeImplFloatRet(ptr: COpaquePointer, vararg args: Any?): Float = memScoped {
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
}
@ExportForCompiler
private fun invokeImplDoubleRet(ptr: COpaquePointer, vararg args: Any?): Double = memScoped {
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
}
@ExportForCompiler
private fun invokeImplPointerRet(ptr: COpaquePointer, vararg args: Any?): COpaquePointer? = memScoped {
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
}
@@ -95,10 +95,10 @@ inline fun <reified T : CVariable> NativePlacement.allocFfiReturnValueBuffer(ty
}
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) {
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:
val argumentsStorage = argumentsPlacement.allocArray<LongVar>(totalArgumentsNumber)
@@ -122,17 +122,30 @@ fun callWithVarargs(codePtr: NativePtr, returnValuePtr: NativePtr, returnTypeKin
addArgument(argument, isVariadic = false)
}
for (argument in variadicArguments) {
addArgument(argument, isVariadic = true)
val variadicArgumentsNumber: Int
if (variadicArguments != null) {
for (argument in variadicArguments) {
addArgument(argument, isVariadic = true)
}
variadicArgumentsNumber = variadicArguments.size
} else {
variadicArgumentsNumber = -1
}
assert (index == totalArgumentsNumber)
callWithVarargs(codePtr, returnValuePtr, returnTypeKind, arguments.rawValue, types.rawValue,
fixedArguments.size, totalArgumentsNumber)
callFunctionPointer(codePtr, returnValuePtr, returnTypeKind, arguments.rawValue, types.rawValue,
totalArgumentsNumber, variadicArgumentsNumber)
}
@SymbolName("Kotlin_Interop_callWithVarargs")
private external fun callWithVarargs(codePtr: NativePtr, returnValuePtr: NativePtr, returnTypeKind: FfiTypeKind,
arguments: NativePtr, argumentTypeKinds: NativePtr,
fixedArgumentsNumber: Int, totalArgumentsNumber: Int)
@SymbolName("Kotlin_Interop_callFunctionPointer")
private external fun callFunctionPointer(
codePtr: NativePtr,
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" {
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,
int fixedArgumentsNumber, int totalArgumentsNumber) {
int totalArgumentsNumber, int variadicArgumentsNumber) {
#ifdef KONAN_NO_FFI
RuntimeAssert(false, "Vararg calls are not supported on this platform");
#else
@@ -72,11 +72,18 @@ void Kotlin_Interop_callWithVarargs(void* codePtr, void* returnValuePtr, FfiType
for (int i = 0; i < totalArgumentsNumber; ++i) {
argumentTypes[i] = convertFfiTypeKindToType((FfiTypeKind) argumentTypeKinds[i]);
}
ffi_type* returnType = convertFfiTypeKindToType(returnTypeKind);
ffi_cif cif;
ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI,
fixedArgumentsNumber, totalArgumentsNumber,
convertFfiTypeKindToType(returnTypeKind), argumentTypes);
if (variadicArgumentsNumber < 0) {
// Non-variadic.
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);
#endif