Avoid requesting selectors in Objective-C interop stubs
Selector references aren't DCEed and thus can cause false positive API usage report from AppStore online validation. Generate selectors by compiler instead.
This commit is contained in:
committed by
SvyatoslavScherbina
parent
0ff1209d0a
commit
f8393819fc
@@ -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)
|
||||
|
||||
+5
-2
@@ -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<String>()
|
||||
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()})"
|
||||
}
|
||||
|
||||
+2
@@ -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"),
|
||||
|
||||
+7
@@ -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)
|
||||
}
|
||||
|
||||
+7
-5
@@ -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)
|
||||
}
|
||||
+5
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user