Interop, backend: refactor and reorder interop lowering

* Do not break type compatibility when lowering interop intrinsics.
* Place interop lowering before callable reference lowering.
* Add other improvements to interop implementation.
This commit is contained in:
Svyatoslav Scherbina
2017-02-22 14:09:44 +07:00
committed by SvyatoslavScherbina
parent 6c627a0b55
commit 3411ce2e8c
12 changed files with 118 additions and 115 deletions
@@ -15,7 +15,7 @@ data class StableObjPtr private constructor(val value: COpaquePointer) {
*/
fun create(any: Any) = fromValue(newGlobalRef(any))
private fun fromValue(value: NativePtr) = fromValue(CPointer.create(value))
private fun fromValue(value: NativePtr) = fromValue(interpretCPointer(value)!!)
/**
* Creates [StableObjPtr] from given raw value.
@@ -219,7 +219,7 @@ private fun ffiCreateCif(returnType: ffi_type, paramTypes: List<ffi_type>): ffi_
private fun ffiFunImpl0(ffiCif: Long, ret: Long, args: Long, userData: Any) {
ffiFunImpl(interpretPointed(ffiCif),
CPointer.create(ret),
interpretCPointer(ret)!!,
interpretPointed(args),
userData as UserData)
}
@@ -11,21 +11,30 @@ val nativeNullPtr: NativePtr = 0L
inline fun <reified T : CVariable> typeOf() = T::class.companionObjectInstance as CVariable.Type
/**
* Returns interpretation of entity with given pointer.
* Returns interpretation of entity with given pointer, or `null` if it is null.
*
* @param T must not be abstract
*/
inline fun <reified T : NativePointed> interpretPointed(ptr: NativePtr): T {
return ensuringNotNull(ptr) {
inline fun <reified T : NativePointed> interpretNullablePointed(ptr: NativePtr): T? {
if (ptr == nativeNullPtr) {
return null
} else {
val kClass = T::class
val primaryConstructor = kClass.primaryConstructor
if (primaryConstructor == null) {
throw IllegalArgumentException("${kClass.simpleName} doesn't have a constructor")
}
(primaryConstructor as (NativePtr) -> T)(ptr)
return (primaryConstructor as (NativePtr) -> T)(ptr)
}
}
fun <T : CPointed> interpretCPointer(rawValue: NativePtr) =
if (rawValue == nativeNullPtr) {
null
} else {
CPointer<T>(rawValue)
}
inline fun <reified T : CAdaptedFunctionType<*>> CAdaptedFunctionType.Companion.getInstanceOf(): T =
T::class.objectInstance!!
@@ -12,40 +12,14 @@ interface NativePointed {
// `null` value of `NativePointed?` is mapped to `nativeNullPtr`.
val NativePointed?.rawPtr: NativePtr
get() = this?.rawPtr ?: nativeNullPtr
get() = if (this != null) this.rawPtr else nativeNullPtr
/**
* Returns interpretation of entity with given pointer, or `null` if it is null.
* Returns interpretation of entity with given pointer.
*
* @param T must not be abstract
*/
inline fun <reified T : NativePointed> interpretNullablePointed(ptr: NativePtr): T? {
return ifNotNull(ptr) {
interpretPointed<T>(it)
}
}
/**
* Applies the function to the pointer if it is not null, otherwise returns `null`.
*/
inline fun <T> ifNotNull(ptr: NativePtr, function: (NativePtr)->T): T? {
return if (ptr == nativeNullPtr) {
null
} else {
function(ptr)
}
}
/**
* Applies the function to the pointer ensuring that it is not null.
*/
inline fun <T> ensuringNotNull(ptr: NativePtr, function: (NativePtr)->T): T {
if (ptr == nativeNullPtr) {
throw IllegalArgumentException()
} else {
return function(ptr)
}
}
inline fun <reified T : NativePointed> interpretPointed(ptr: NativePtr): T = interpretNullablePointed<T>(ptr)!!
/**
* Changes the interpretation of the pointed data or code.
@@ -60,16 +34,7 @@ interface CPointed : NativePointed
/**
* C pointer.
*/
class CPointer<T : CPointed> private constructor(val rawValue: NativePtr) {
companion object {
fun <T : CPointed> create(rawValue: NativePtr) = ensuringNotNull(rawValue) {
CPointer<T>(rawValue)
}
fun <T : CPointed> createNullable(rawValue: NativePtr) = ifNotNull(rawValue) {
CPointer<T>(it)
}
}
class CPointer<T : CPointed> internal constructor(val rawValue: NativePtr) {
override fun equals(other: Any?): Boolean {
if (this === other) {
@@ -90,7 +55,7 @@ class CPointer<T : CPointed> private constructor(val rawValue: NativePtr) {
* Returns the pointer to this data or code.
*/
val <T : CPointed> T.ptr: CPointer<T>
get() = CPointer.create(this.rawPtr)
get() = interpretCPointer(this.rawPtr)!!
/**
* Returns the corresponding [CPointed].
@@ -104,7 +69,7 @@ inline val <reified T : CPointed> CPointer<T>.pointed: T
val CPointer<*>?.rawValue: NativePtr
get() = this?.rawValue ?: nativeNullPtr
fun <T : CPointed> CPointer<*>.reinterpret(): CPointer<T> = CPointer.create(this.rawValue)
fun <T : CPointed> CPointer<*>.reinterpret(): CPointer<T> = interpretCPointer(this.rawValue)!!
/**
* The [CPointed] without any specified interpretation.
@@ -251,7 +216,7 @@ typealias CPointerVar<T> = CPointerVarWithValueMappedTo<CPointer<T>>
* The value of this variable.
*/
inline var <reified P : CPointer<*>> CPointerVarWithValueMappedTo<P>.value: P?
get() = CPointer.createNullable<CPointed>(nativeMemUtils.getNativePtr(this)) as P?
get() = interpretCPointer<CPointed>(nativeMemUtils.getNativePtr(this)) as P?
set(value) = nativeMemUtils.putNativePtr(this, value.rawValue)
/**
@@ -151,10 +151,10 @@ fun <T : CPointed> NativePlacement.allocPointerTo() = alloc<CPointerVar<T>>()
/**
* The zero-terminated string.
*/
class CString private constructor(override val rawPtr: NativePtr) : CPointed {
class CString(override val rawPtr: NativePtr) : CPointed {
companion object {
fun fromArray(array: CArray<CInt8Var>) = CString(array.rawPtr)
fun fromArray(array: CArray<CInt8Var>) = array.reinterpret<CString>()
}
fun length(): Int {
@@ -51,7 +51,7 @@ object nativeMemUtils {
if (ptr == nativeNullPtr) {
throw OutOfMemoryError("unable to allocate native memory")
}
return NativeAllocated(ptr)
return interpretPointed<NativeAllocated>(ptr)
}
fun free(mem: NativePointed) {
@@ -14,11 +14,17 @@ inline val nativeNullPtr: NativePtr
fun <T : CVariable> typeOf(): CVariable.Type = throw Error("typeOf() is called with erased argument")
/**
* Returns interpretation of entity with given pointer.
* Returns interpretation of entity with given pointer, or `null` if it is null.
*
* @param T must not be abstract
*/
@Intrinsic external fun <T : NativePointed> interpretPointed(ptr: NativePtr): T
@Intrinsic external fun <T : NativePointed> interpretNullablePointed(ptr: NativePtr): T?
@Intrinsic external fun <T : CPointed> interpretCPointer(rawValue: NativePtr): CPointer<T>?
@Intrinsic external fun NativePointed.getRawPointer(): NativePtr
@Intrinsic external fun CPointer<*>.getRawValue(): NativePtr
inline fun <reified T : CAdaptedFunctionType<*>> CAdaptedFunctionType.Companion.getInstanceOf(): T =
TODO("CAdaptedFunctionType.getInstanceOf")