diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt index 1c9d94ec939..2950d1431c1 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt @@ -125,6 +125,10 @@ annotation class InteropStubs() @Retention(AnnotationRetention.SOURCE) internal annotation class ObjCMethodImp(val selector: String, val encoding: String) +@PublishedApi +@TypedIntrinsic(IntrinsicType.OBJC_GET_SELECTOR) +internal external fun objCGetSelector(selector: String): COpaquePointer + @kotlin.native.internal.ExportForCppRuntime("Kotlin_Interop_getObjCClass") private fun getObjCClassByName(name: NativePtr): NativePtr { val result = objc_lookUpClass(name) diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt index 6ac01272d2f..a3abca03ed5 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt @@ -178,6 +178,7 @@ class ObjCMethodStub(private val stubGenerator: StubGenerator, val kniReceiverParameter = "kniR" val kniSuperClassParameter = "kniSC" + val kniSelectorParameter = "kniSEL" val voidPtr = PointerType(VoidType) @@ -199,6 +200,9 @@ class ObjCMethodStub(private val stubGenerator: StubGenerator, TypedKotlinValue(voidPtr, "getReceiverOrSuper($kniReceiverParameter, $kniSuperClassParameter)")) + kotlinObjCBridgeParameters.add(KotlinParameter(kniSelectorParameter, KotlinTypes.cOpaquePointer)) + nativeBridgeArguments.add(TypedKotlinValue(voidPtr, kniSelectorParameter)) + val kotlinParameterNames = method.getKotlinParameterNames() method.parameters.forEachIndexed { index, it -> @@ -224,7 +228,6 @@ class ObjCMethodStub(private val stubGenerator: StubGenerator, returnType, nativeBridgeArguments ) { nativeValues -> - val selector = "@selector(${method.selector})" val messengerParameterTypes = mutableListOf() messengerParameterTypes.add("void*") messengerParameterTypes.add("SEL") @@ -239,7 +242,7 @@ class ObjCMethodStub(private val stubGenerator: StubGenerator, val messenger = "(($messengerType) ${nativeValues.first()})" - val messengerArguments = listOf(nativeValues[1]) + selector + nativeValues.drop(2) + val messengerArguments = nativeValues.drop(1) "$messenger(${messengerArguments.joinToString()})" } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index 1015afa5075..a2dc9668b4b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -233,6 +233,8 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val val interopCreateNSStringFromKString = symbolTable.referenceSimpleFunction(context.interopBuiltIns.CreateNSStringFromKString) + val interopObjCGetSelector = interopFunction("objCGetSelector") + val objCExportTrapOnUndeclaredException = symbolTable.referenceSimpleFunction(context.builtIns.kotlinNativeInternal.getContributedFunctions( Name.identifier("trapOnUndeclaredException"), diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt index b2ea95a8467..6c70a324677 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt @@ -4,6 +4,7 @@ import kotlinx.cinterop.cValuesOf import llvm.* import org.jetbrains.kotlin.backend.konan.descriptors.TypedIntrinsic import org.jetbrains.kotlin.backend.konan.descriptors.isTypedIntrinsic +import org.jetbrains.kotlin.backend.konan.llvm.objc.genObjCSelector import org.jetbrains.kotlin.backend.konan.reportCompilationError import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrConstructor @@ -51,6 +52,7 @@ internal enum class IntrinsicType { OBJC_GET_OBJC_CLASS, OBJC_GET_RECEIVER_OR_SUPER, OBJC_INIT_BY, + OBJC_GET_SELECTOR, // Other GET_CLASS_TYPE_INFO, CREATE_UNINITIALIZED_INSTANCE, @@ -148,6 +150,10 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv environment.evaluateCall(constructorDescriptor, args, Lifetime.IRRELEVANT) receiver } + IntrinsicType.OBJC_GET_SELECTOR -> { + val selector = (callSite.getValueArgument(0) as IrConst<*>).value as String + environment.functionGenerationContext.genObjCSelector(selector) + } IntrinsicType.INIT_INSTANCE -> { val callee = callSite as IrCall val initializer = callee.getValueArgument(1) as IrCall @@ -232,6 +238,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv reportNonLoweredIntrinsic(intrinsicType) IntrinsicType.INIT_INSTANCE, IntrinsicType.OBJC_INIT_BY, + IntrinsicType.OBJC_GET_SELECTOR, IntrinsicType.IMMUTABLE_BLOB -> reportSpecialIntrinsic(intrinsicType) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCCodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCCodeGenerator.kt index ded0d2929b4..9b4ecd0a943 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCCodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCCodeGenerator.kt @@ -14,11 +14,7 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) { val dataGenerator = codegen.objCDataGenerator!! - fun FunctionGenerationContext.genSelector(selector: String): LLVMValueRef { - val selectorRef = dataGenerator.genSelectorRef(selector) - // TODO: clang emits it with `invariant.load` metadata. - return load(selectorRef.llvm) - } + fun FunctionGenerationContext.genSelector(selector: String): LLVMValueRef = genObjCSelector(selector) fun FunctionGenerationContext.genGetLinkedClass(name: String): LLVMValueRef { val classRef = dataGenerator.genClassRef(name) @@ -43,3 +39,9 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) { fun msgSender(functionType: LLVMTypeRef): LLVMValueRef = objcMsgSend.bitcast(pointerType(functionType)).llvm } + +internal fun FunctionGenerationContext.genObjCSelector(selector: String): LLVMValueRef { + val selectorRef = codegen.objCDataGenerator!!.genSelectorRef(selector) + // TODO: clang emits it with `invariant.load` metadata. + return load(selectorRef.llvm) +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt index 0936bafc6a9..e15541edd0a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt @@ -587,10 +587,13 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme return irCall(bridge, symbolTable.translateErased(info.bridge.returnType!!)).apply { putValueArgument(0, superClass) putValueArgument(1, receiver) + putValueArgument(2, irCall(symbols.interopObjCGetSelector.owner).apply { + putValueArgument(0, irString(info.selector)) + }) - assert(arguments.size + 2 == info.bridge.valueParameters.size) + assert(arguments.size + 3 == info.bridge.valueParameters.size) arguments.forEachIndexed { index, argument -> - putValueArgument(index + 2, argument) + putValueArgument(index + 3, argument) } } } diff --git a/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt b/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt index 5f20cd23b95..27ac4342c6d 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt @@ -42,6 +42,7 @@ class IntrinsicType { const val OBJC_GET_OBJC_CLASS = "OBJC_GET_OBJC_CLASS" const val OBJC_GET_RECEIVER_OR_SUPER = "OBJC_GET_RECEIVER_OR_SUPER" const val OBJC_INIT_BY = "OBJC_INIT_BY" + const val OBJC_GET_SELECTOR = "OBJC_GET_SELECTOR" // Other const val GET_CLASS_TYPE_INFO = "GET_CLASS_TYPE_INFO"