diff --git a/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt b/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt index eed28c06d06..3496cd9252d 100644 --- a/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt +++ b/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt @@ -5,6 +5,8 @@ package kotlinx.cinterop * Subtypes are supposed to represent interpretations of the pointed data or code. * * This interface is likely to be handled by compiler magic and shouldn't be subtyped by arbitrary classes. + * + * TODO: the behavior of [equals], [hashCode] and [toString] differs on Native and JVM backends. */ interface NativePointed { val rawPtr: NativePtr diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt index f60e5b2b707..3a0dc188883 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt @@ -4,6 +4,14 @@ import konan.internal.Intrinsic class NativePtr private constructor() { @Intrinsic external operator fun plus(offset: Long): NativePtr + + @Intrinsic private external fun toLong(): Long + + override fun equals(other: Any?) = (other is NativePtr) && konan.internal.areEqualByValue(this, other) + + override fun hashCode() = this.toLong().hashCode() + + override fun toString() = this.toLong().toString() // TODO: format as hex. } inline val nativeNullPtr: NativePtr diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt index cca7e1f1ba2..887b9d783d5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt @@ -112,6 +112,8 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns) { val nativePtrPlusLong = nativePtr.unsubstitutedMemberScope.getContributedFunctions("plus").single() + val nativePtrToLong = nativePtr.unsubstitutedMemberScope.getContributedFunctions("toLong").single() + val bitsToFloat = packageScope.getContributedFunctions("bitsToFloat").single() val bitsToDouble = packageScope.getContributedFunctions("bitsToDouble").single() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index 01b1b6618d0..2c6415b544f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -24,7 +24,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { private var localAllocs = 0 private var arenaSlot: LLVMValueRef? = null - private val intPtrType = LLVMIntPtrType(llvmTargetData)!! + val intPtrType = LLVMIntPtrType(llvmTargetData)!! private val immOneIntPtrType = LLVMConstInt(intPtrType, 1, 1)!! fun prologue(descriptor: FunctionDescriptor) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 8406be6f275..067bbb0ae8e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -1711,6 +1711,16 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid interop.nativePtrPlusLong -> codegen.gep(args[0], args[1]) interop.getNativeNullPtr -> kNullInt8Ptr interop.getPointerSize -> Int32(LLVMPointerSize(codegen.llvmTargetData)).llvm + interop.nativePtrToLong -> { + val intPtrValue = codegen.ptrToInt(args.single(), codegen.intPtrType) + val resultType = codegen.getLLVMType(descriptor.returnType!!) + + if (resultType == intPtrValue.type) { + intPtrValue + } else { + LLVMBuildSExt(codegen.builder, intPtrValue, resultType, "")!! + } + } else -> TODO(callee.descriptor.original.toString()) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt index bdbc4eb40d8..a528169aa34 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt @@ -324,6 +324,10 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : val llvmFunctionType = getLlvmFunctionType(descriptor) val llvmFunction = if (descriptor.isExternal) { + if (descriptor.isIntrinsic) { + return + } + context.llvm.externalFunction(descriptor.symbolName, llvmFunctionType) } else { val symbolName = if (descriptor.isExported()) { diff --git a/runtime/src/main/kotlin/konan/internal/InteropBoxing.kt b/runtime/src/main/kotlin/konan/internal/InteropBoxing.kt index 8677bd7e280..ef2098ee539 100644 --- a/runtime/src/main/kotlin/konan/internal/InteropBoxing.kt +++ b/runtime/src/main/kotlin/konan/internal/InteropBoxing.kt @@ -27,9 +27,12 @@ class NativePointedBox(val value: NativePointed) { return this.value == other.value } - override fun hashCode() = value.hashCode() + // TODO: can't delegate the following methods to `this.value` + // because `NativePointed` doesn't provide them. - override fun toString() = value.toString() + override fun hashCode() = this.value.rawPtr.hashCode() + + override fun toString() = "NativePointed(raw=${this.value.rawPtr})" } fun boxNativePointed(value: NativePointed?) = if (value != null) NativePointedBox(value) else null