Rework Objective-C constructors and support 'initBy' intrinsic
This commit is contained in:
committed by
SvyatoslavScherbina
parent
5a7e3e20b4
commit
07f26dc1df
@@ -51,8 +51,17 @@ class ObjCPointerHolder(inline val rawPtr: NativePtr) {
|
||||
@konan.internal.ExportForCompiler
|
||||
private external fun ObjCObject.initFromPtr(ptr: NativePtr)
|
||||
|
||||
@konan.internal.Intrinsic
|
||||
external fun <T : ObjCObjectBase> T.initBy(constructorCall: T): T
|
||||
|
||||
@konan.internal.ExportForCompiler
|
||||
private fun ObjCObject.initFrom(other: ObjCObject?) = this.initFromPtr(other!!.rawPtr)
|
||||
private fun ObjCObjectBase.superInitCheck(superInitCallResult: ObjCObject?) {
|
||||
if (superInitCallResult == null)
|
||||
throw RuntimeException("Super initialization failed")
|
||||
|
||||
if (superInitCallResult.rawPtr != this.rawPtr)
|
||||
throw UnsupportedOperationException("Super initializer has replaced object")
|
||||
}
|
||||
|
||||
fun <T : Any?> Any?.uncheckedCast(): T = @Suppress("UNCHECKED_CAST") (this as T) // TODO: make private
|
||||
|
||||
|
||||
+1
-1
@@ -421,7 +421,7 @@ val ObjCClassOrProtocol.kotlinName: String get() = when (this) {
|
||||
}
|
||||
|
||||
private val ObjCClass.baseClassName: String
|
||||
get() = baseClass?.name ?: "ObjCObject"
|
||||
get() = baseClass?.name ?: "ObjCObjectBase"
|
||||
|
||||
private fun Parameter.getTypeStringRepresentation() =
|
||||
(if (this.nsConsumed) "__attribute__((ns_consumed)) " else "") + type.getStringRepresentation()
|
||||
|
||||
+3
-1
@@ -135,7 +135,6 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns) {
|
||||
.getContributedDescriptors().filterIsInstance<PropertyDescriptor>().single()
|
||||
|
||||
val objCObjectInitFromPtr = packageScope.getContributedFunctions("initFromPtr").single()
|
||||
val objCObjectInitFrom = packageScope.getContributedFunctions("initFrom").single()
|
||||
|
||||
val allocObjCObject = packageScope.getContributedFunctions("allocObjCObject").single()
|
||||
|
||||
@@ -155,6 +154,9 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns) {
|
||||
val interpretObjCPointerOrNull = packageScope.getContributedFunctions("interpretObjCPointerOrNull").single()
|
||||
val interpretObjCPointer = packageScope.getContributedFunctions("interpretObjCPointer").single()
|
||||
|
||||
val objCObjectSuperInitCheck = packageScope.getContributedFunctions("superInitCheck").single()
|
||||
val objCObjectInitBy = packageScope.getContributedFunctions("initBy").single()
|
||||
|
||||
val objCAction = packageScope.getContributedClassifier("ObjCAction") as ClassDescriptor
|
||||
|
||||
val objCOutlet = packageScope.getContributedClassifier("ObjCOutlet") as ClassDescriptor
|
||||
|
||||
+2
-1
@@ -56,7 +56,8 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
|
||||
val interopObjCObjectInitFromPtr =
|
||||
symbolTable.referenceSimpleFunction(context.interopBuiltIns.objCObjectInitFromPtr)
|
||||
|
||||
val interopObjCObjectInitFrom = symbolTable.referenceSimpleFunction(context.interopBuiltIns.objCObjectInitFrom)
|
||||
val interopObjCObjectSuperInitCheck =
|
||||
symbolTable.referenceSimpleFunction(context.interopBuiltIns.objCObjectSuperInitCheck)
|
||||
|
||||
val interopObjCObjectRawValueGetter =
|
||||
symbolTable.referenceSimpleFunction(context.interopBuiltIns.objCObjectRawPtr.getter!!)
|
||||
|
||||
+24
-1
@@ -1607,10 +1607,30 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
return null
|
||||
}
|
||||
|
||||
private fun evaluateSpecialIntrinsicCall(expression: IrFunctionAccessExpression): LLVMValueRef? {
|
||||
if (expression.descriptor.isIntrinsic) {
|
||||
when (expression.descriptor.original) {
|
||||
context.interopBuiltIns.objCObjectInitBy -> {
|
||||
val receiver = evaluateExpression(expression.extensionReceiver!!)
|
||||
val irConstructorCall = expression.getValueArgument(0) as IrCall
|
||||
val constructorDescriptor = irConstructorCall.descriptor as ClassConstructorDescriptor
|
||||
val constructorArgs = evaluateExplicitArgs(irConstructorCall)
|
||||
val args = listOf(receiver) + constructorArgs
|
||||
callDirect(constructorDescriptor, args, Lifetime.IRRELEVANT)
|
||||
return receiver
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
private fun evaluateCall(value: IrMemberAccessExpression): LLVMValueRef {
|
||||
private fun evaluateCall(value: IrFunctionAccessExpression): LLVMValueRef {
|
||||
context.log{"evaluateCall : ${ir2string(value)}"}
|
||||
|
||||
evaluateSpecialIntrinsicCall(value)?.let { return it }
|
||||
|
||||
val args = evaluateExplicitArgs(value)
|
||||
|
||||
compileTimeEvaluate(value, args)?.let { return it }
|
||||
@@ -1925,6 +1945,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
assert(args.isEmpty())
|
||||
functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), count = kImmZero,
|
||||
lifetime = resultLifetime(callee))
|
||||
} else if (constructedClass.isKotlinObjCClass()) {
|
||||
callDirect(context.interopBuiltIns.allocObjCObject, listOf(genGetObjCClass(constructedClass)),
|
||||
resultLifetime(callee))
|
||||
} else {
|
||||
functionGenerationContext.allocInstance(typeInfoForAllocation(constructedClass), resultLifetime(callee))
|
||||
}
|
||||
|
||||
+25
-2
@@ -388,7 +388,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
val initCall = builder.genLoweredObjCMethodCall(
|
||||
initMethodInfo,
|
||||
superQualifier = symbolTable.referenceClass(expression.descriptor.constructedClass),
|
||||
receiver = builder.callAlloc(constructedClass.symbol),
|
||||
receiver = builder.irGet(constructedClass.thisReceiver!!.symbol),
|
||||
arguments = initMethod.valueParameters.map { expression.getValueArgument(it)!! }
|
||||
)
|
||||
|
||||
@@ -400,7 +400,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
// Required for the IR to be valid, will be ignored in codegen:
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset, superConstructor, superConstructor.descriptor)
|
||||
|
||||
+irCall(symbols.interopObjCObjectInitFrom).apply {
|
||||
+irCall(symbols.interopObjCObjectSuperInitCheck).apply {
|
||||
extensionReceiver = irGet(constructedClass.thisReceiver!!.symbol)
|
||||
putValueArgument(0, initCall)
|
||||
}
|
||||
@@ -729,6 +729,29 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
}
|
||||
}
|
||||
|
||||
interop.objCObjectInitBy -> {
|
||||
val intrinsic = interop.objCObjectInitBy.name
|
||||
|
||||
val argument = expression.getValueArgument(0)!!
|
||||
val constructedClass =
|
||||
((argument as? IrCall)?.descriptor as? ClassConstructorDescriptor)?.constructedClass
|
||||
|
||||
if (constructedClass == null) {
|
||||
context.reportCompilationError("Argument of '$intrinsic' must be a constructor call",
|
||||
irFile, argument)
|
||||
}
|
||||
|
||||
val extensionReceiver = expression.extensionReceiver!!
|
||||
if (extensionReceiver !is IrGetValue ||
|
||||
extensionReceiver.descriptor != constructedClass.thisAsReceiverParameter) {
|
||||
|
||||
context.reportCompilationError("Receiver of '$intrinsic' must be a 'this' of the constructed class",
|
||||
irFile, extensionReceiver)
|
||||
}
|
||||
|
||||
expression
|
||||
}
|
||||
|
||||
else -> expression
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user