diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt index 7145b6e5ec1..3dbc018ebcf 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt @@ -99,7 +99,7 @@ private fun KotlinToCCallBuilder.addArgument( if (!variadic) cFunctionBuilder.addParameter(cArgument.type) } -private fun KotlinToCCallBuilder.buildKotlinBridgeCall(transformCall: (IrCall) -> IrExpression = { it }): IrExpression = +private fun KotlinToCCallBuilder.buildKotlinBridgeCall(transformCall: (IrMemberAccessExpression) -> IrExpression = { it }): IrExpression = bridgeCallBuilder.build( bridgeBuilder.buildKotlinBridge().also { this.stubs.addKotlin(it) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGenUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGenUtils.kt index cda8152bcee..9a4f9114d97 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGenUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGenUtils.kt @@ -16,6 +16,8 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl @@ -128,8 +130,9 @@ private fun createKotlinBridge( ) bridgeDescriptor.bind(bridge) if (isExternal) { + val constructor = symbols.filterExceptions.owner.constructors.single() bridge.annotations += - irCall(startOffset, endOffset, symbols.filterExceptions.owner.constructors.single(), emptyList()) + IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, constructor.returnType, constructor.symbol) } return bridge } @@ -185,7 +188,7 @@ internal class KotlinCallBuilder(private val irBuilder: IrBuilderWithScope, priv fun build( function: IrFunction, - transformCall: (IrCall) -> IrExpression = { it } + transformCall: (IrMemberAccessExpression) -> IrExpression = { it } ): IrExpression { val arguments = this.arguments.toMutableList() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt index 810e252ca45..675169334d2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.backend.konan.descriptors import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager import org.jetbrains.kotlin.backend.konan.KonanBackendContext -import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor @@ -21,9 +20,9 @@ import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.IrSetVariable import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol -import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.types.* @@ -36,14 +35,6 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S private val elementProperty = refClass.owner.declarations.filterIsInstance().single() - private fun refConstructor(elementType: KotlinType): ClassConstructorDescriptor { - val typeParameter = refClassConstructor.descriptor.typeParameters[0] - - return refClassConstructor.descriptor.substitute(TypeSubstitutor.create( - mapOf(typeParameter.typeConstructor to TypeProjectionImpl(Variance.INVARIANT, elementType)) - ))!! - } - private fun refType(elementType: KotlinType): KotlinType { return refClass.descriptor.defaultType.replace(listOf(TypeProjectionImpl(elementType))) } @@ -66,10 +57,10 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S val valueType = originalDeclaration.type - val refConstructorCall = IrCallImpl( + val refConstructorCall = IrConstructorCallImpl.fromSymbolOwner( originalDeclaration.startOffset, originalDeclaration.endOffset, refClass.typeWith(valueType), - refClassConstructor, refConstructor(valueType.toKotlinType()), 1 + refClassConstructor ).apply { putTypeArgument(0, valueType) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt index 49d560b14db..c830804439d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt @@ -97,7 +97,7 @@ class IrFileImpl(entry: SourceManager.FileEntry) : IrFile { override val metadata: MetadataSource.File? get() = TODO("not implemented") - override val annotations: MutableList + override val annotations: MutableList get() = TODO("not implemented") override val fqName: FqName get() = TODO("not implemented") diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/NewIrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/NewIrUtils.kt index d844ac8836d..e8f3de1da17 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/NewIrUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/NewIrUtils.kt @@ -92,13 +92,6 @@ val IrClass.isFinalClass: Boolean fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing() -private val IrCall.annotationClass - get() = (this.symbol.owner as IrConstructor).constructedClass - -fun List.findAnnotation(fqName: FqName): IrCall? = this.firstOrNull { - it.annotationClass.fqNameSafe == fqName -} - fun IrDeclaration.getAnnotationArgumentValue(fqName: FqName, argumentName: String): T? { val annotation = this.annotations.findAnnotation(fqName) if (annotation == null) { 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 67f1d94d230..f63a0b7bba4 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 @@ -8,7 +8,6 @@ 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.IrClass -import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.types.getClass @@ -147,8 +146,8 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv } IntrinsicType.OBJC_INIT_BY -> { val receiver = environment.evaluateExpression(callSite.extensionReceiver!!) - val irConstructorCall = callSite.getValueArgument(0) as IrCall - val constructorDescriptor = irConstructorCall.symbol.owner as IrConstructor + val irConstructorCall = callSite.getValueArgument(0) as IrConstructorCall + val constructorDescriptor = irConstructorCall.symbol.owner val constructorArgs = environment.evaluateExplicitArgs(irConstructorCall) val args = listOf(receiver) + constructorArgs environment.evaluateCall(constructorDescriptor, args, Lifetime.IRRELEVANT) @@ -159,7 +158,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv environment.functionGenerationContext.genObjCSelector(selector) } IntrinsicType.INIT_INSTANCE -> { - val initializer = callSite.getValueArgument(1) as IrCall + val initializer = callSite.getValueArgument(1) as IrConstructorCall val thiz = environment.evaluateExpression(callSite.getValueArgument(0)!!) environment.evaluateCall( initializer.symbol.owner, 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 b02a1b69dc5..375f37a5fbd 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 @@ -760,6 +760,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map return evaluateCall (value) is IrDelegatingConstructorCall -> return evaluateCall (value) + is IrConstructorCall -> return evaluateCall (value) is IrInstanceInitializerCall -> return evaluateInstanceInitializerCall(value) is IrGetValue -> return evaluateGetValue (value) @@ -1751,6 +1752,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map delegatingConstructorCall(value.symbol.owner, args) + is IrConstructorCall -> evaluateConstructorCall(value, args) else -> evaluateFunctionCall(value as IrCall, args, resultLifetime(value)) } } @@ -2016,7 +2018,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map intrinsicGenerator.evaluateCall(callee, args) function.symbol in context.irBuiltIns.irBuiltInsSymbols -> evaluateOperatorCall(callee, argsWithContinuationIfNeeded) - function is IrConstructor -> evaluateConstructorCall(callee, argsWithContinuationIfNeeded) else -> evaluateSimpleFunctionCall(function, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifierSymbol?.owner) } } @@ -2045,34 +2046,40 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map): LLVMValueRef { + private fun evaluateConstructorCall(callee: IrConstructorCall, args: List): LLVMValueRef { context.log{"evaluateConstructorCall : ${ir2string(callee)}"} return memScoped { - val constructedClass = (callee.symbol as IrConstructorSymbol).owner.constructedClass - val thisValue = if (constructedClass.isArray) { - assert(args.isNotEmpty() && args[0].type == int32Type) - functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), args[0], - resultLifetime(callee), currentCodeContext.exceptionHandler) - } else if (constructedClass == context.ir.symbols.string.owner) { - // TODO: consider returning the empty string literal instead. - assert(args.isEmpty()) - functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), count = kImmZero, - lifetime = resultLifetime(callee), exceptionHandler = currentCodeContext.exceptionHandler) - } else if (constructedClass.isObjCClass()) { - assert(constructedClass.isKotlinObjCClass()) // Calls to other ObjC class constructors must be lowered. - val symbols = context.ir.symbols - val rawPtr = callDirect( - symbols.interopAllocObjCObject.owner, - listOf(genGetObjCClass(constructedClass)), - Lifetime.IRRELEVANT - ) - - callDirect(symbols.interopInterpretObjCPointer.owner, listOf(rawPtr), resultLifetime(callee)).also { - // Balance pointer retained by alloc: - callDirect(symbols.interopObjCRelease.owner, listOf(rawPtr), Lifetime.IRRELEVANT) + val constructedClass = callee.symbol.owner.constructedClass + val thisValue = when { + constructedClass.isArray -> { + assert(args.isNotEmpty() && args[0].type == int32Type) + functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), args[0], + resultLifetime(callee), currentCodeContext.exceptionHandler) } - } else { - functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee)) + + constructedClass == context.ir.symbols.string.owner -> { + // TODO: consider returning the empty string literal instead. + assert(args.isEmpty()) + functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), count = kImmZero, + lifetime = resultLifetime(callee), exceptionHandler = currentCodeContext.exceptionHandler) + } + + constructedClass.isObjCClass() -> { + assert(constructedClass.isKotlinObjCClass()) // Calls to other ObjC class constructors must be lowered. + val symbols = context.ir.symbols + val rawPtr = callDirect( + symbols.interopAllocObjCObject.owner, + listOf(genGetObjCClass(constructedClass)), + Lifetime.IRRELEVANT + ) + + callDirect(symbols.interopInterpretObjCPointer.owner, listOf(rawPtr), resultLifetime(callee)).also { + // Balance pointer retained by alloc: + callDirect(symbols.interopObjCRelease.owner, listOf(rawPtr), Lifetime.IRRELEVANT) + } + } + + else -> functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee)) } evaluateSimpleFunctionCall(callee.symbol.owner, listOf(thisValue) + args, Lifetime.IRRELEVANT /* constructor doesn't return anything */) @@ -2223,8 +2230,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map): LLVMValueRef { + private fun delegatingConstructorCall(constructor: IrConstructor, args: List): LLVMValueRef { val constructedClass = functionGenerationContext.constructedClass!! val thisPtr = currentCodeContext.genGetValue(constructedClass.thisReceiver!!) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt index 51ecebb206c..8f0e2d40ede 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.target import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* @@ -32,8 +33,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.addIfNotNull @@ -131,6 +131,7 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr private val IrFunctionAccessExpression.target: IrFunction get() = when (this) { is IrCall -> this.callTarget is IrDelegatingConstructorCall -> this.symbol.owner + is IrConstructorCall -> this.symbol.owner else -> TODO(this.render()) } @@ -266,12 +267,12 @@ private class InlineClassTransformer(private val context: Context) : IrBuildingT } } - override fun visitCall(expression: IrCall): IrExpression { - super.visitCall(expression) + override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { + super.visitConstructorCall(expression) - val function = expression.symbol.owner - return if (function is IrConstructor && function.constructedClass.isInlined()) { - builder.lowerConstructorCallToValue(expression, function) + val constructor = expression.symbol.owner + return if (constructor.constructedClass.isInlined()) { + builder.lowerConstructorCallToValue(expression, constructor) } else { expression } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt index 2a1f33a6291..a97c95b5839 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl @@ -171,7 +172,7 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context, classifier = symbolRemapper.getReferencedClassifier(type.classifier), hasQuestionMark = type.hasQuestionMark, arguments = remapTypeArguments(type.arguments), - annotations = type.annotations.map { it.transform(copier, null) as IrCall } + annotations = type.annotations.map { it.transform(copier, null) as IrConstructorCall } ) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt index 46bd8897862..ccd9e886a79 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt @@ -220,14 +220,14 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { .map { val initializer = it.initializerExpression val entryConstructorCall = when { - initializer is IrCall -> initializer + initializer is IrConstructorCall -> initializer initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> - initializer.statements.last() as IrCall + initializer.statements.last() as IrConstructorCall else -> error("Unexpected initializer: $initializer") } - val entryClass = (entryConstructorCall.symbol.owner as IrConstructor).constructedClass + val entryClass = entryConstructorCall.symbol.owner.constructedClass irCall(startOffset, endOffset, createUninitializedInstance, @@ -265,7 +265,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val startOffset = irClass.startOffset val endOffset = irClass.endOffset - fun IrBlockBuilder.initInstanceCall(instance: IrCall, constructor: IrCall): IrCall = + fun IrBlockBuilder.initInstanceCall(instance: IrCall, constructor: IrConstructorCall): IrCall = irCall(initInstanceSymbol).apply { putValueArgument(0, instance) putValueArgument(1, constructor) @@ -288,11 +288,11 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val initializer = it.value.initializerExpression!! initializer.patchDeclarationParents(constructor) when { - initializer is IrCall -> +initInstanceCall(instance, initializer) + initializer is IrConstructorCall -> +initInstanceCall(instance, initializer) initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> { val statements = initializer.statements - val constructorCall = statements.last() as IrCall + val constructorCall = statements.last() as IrConstructorCall statements[statements.lastIndex] = initInstanceCall(instance, constructorCall) +initializer } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumConstructorsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumConstructorsLowering.kt index da585ceb317..fdf3a3b19f2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumConstructorsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumConstructorsLowering.kt @@ -270,21 +270,13 @@ internal class EnumConstructorsLowering(val context: Context) : ClassLoweringPas } private inner class InEnumEntryClassConstructor(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) { - override fun createConstructorCall( - startOffset: Int, - endOffset: Int, - loweredConstructor: IrConstructorSymbol - ) = IrDelegatingConstructorCallImpl( - startOffset, - endOffset, - context.irBuiltIns.unitType, - loweredConstructor - ) + override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol) = + IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType, loweredConstructor) } private inner class InEnumEntryInitializer(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) { override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol) = - IrCallImpl(startOffset, endOffset, loweredConstructor.owner.returnType, loweredConstructor) + IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, loweredConstructor.owner.returnType, loweredConstructor) } private inner class EnumClassBodyTransformer : IrElementTransformerVoid() { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt index 2362f15e835..2e8b68a410a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt @@ -32,13 +32,7 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPass { override fun lower(irFile: IrFile) { // All declarations with `isExpect == true` are nested into a top-level declaration with `isExpect == true`. - irFile.declarations.removeAll { - if (it.descriptor.isExpectMember) { - true - } else { - false - } - } + irFile.declarations.removeAll { it.descriptor.isExpectMember } } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt index d9a151d3ea6..600b2bed90a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt @@ -36,19 +36,24 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid fun inline(irModule: IrModuleFragment) = irModule.accept(this, data = null) - override fun visitCall(expression: IrCall): IrExpression { - val callSite = super.visitCall(expression) as IrCall - if (!callSite.symbol.owner.needsInlining) - return callSite - if (Symbols.isLateinitIsInitializedPropertyGetter(callSite.symbol)) - return callSite + override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression { + expression.transformChildrenVoid(this) + val callee = when (expression) { + is IrCall -> expression.symbol.owner + is IrConstructorCall -> expression.symbol.owner + else -> return expression + } + if (!callee.needsInlining) + return expression + if (Symbols.isLateinitIsInitializedPropertyGetter(callee.symbol)) + return expression - val callee = getFunctionDeclaration(callSite.symbol) + val actualCallee = getFunctionDeclaration(callee.symbol) - callee.transformChildrenVoid(this) // Process recursive inline. + actualCallee.transformChildrenVoid(this) // Process recursive inline. val parent = allScopes.map { it.irElement }.filterIsInstance().lastOrNull() - val inliner = Inliner(callSite, callee, currentScope!!, parent, context) + val inliner = Inliner(expression, actualCallee, currentScope!!, parent, context) return inliner.inline() } @@ -76,7 +81,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid private val IrFunction.needsInlining get() = isInlineConstructor || (this.isInline && !this.isExternal) - private inner class Inliner(val callSite: IrCall, + private inner class Inliner(val callSite: IrFunctionAccessExpression, val callee: IrFunction, val currentScope: ScopeWithIr, val parent: IrDeclarationParent?, @@ -109,7 +114,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid } } - private fun inlineFunction(callSite: IrCall, callee: IrFunction): IrReturnableBlock { + private fun inlineFunction(callSite: IrFunctionAccessExpression, callee: IrFunction): IrReturnableBlock { val copiedCallee = copyIrElement.copy(callee) as IrFunction val evaluationStatements = evaluateArguments(callSite, copiedCallee) @@ -126,12 +131,13 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid val constructedClass = callee.parentAsClass copiedCallee.parent = constructedClass val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall + // TODO: Try use type parameters from callee. irBuilder.run { - val constructorCall = IrCallImpl( + val constructorCall = IrConstructorCallImpl( startOffset, endOffset, callSite.type, delegatingConstructorCall.symbol, delegatingConstructorCall.descriptor, - constructedClass.typeParameters.size, + constructedClass.typeParameters.size, 0, delegatingConstructorCall.symbol.owner.valueParameters.size ).apply { delegatingConstructorCall.symbol.owner.valueParameters.forEach { @@ -216,11 +222,12 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid val unboundArgsSet = unboundFunctionParameters.toSet() val valueParameters = expression.getArguments().drop(1) // Skip dispatch receiver. - val immediateCall = IrCallImpl( - expression.startOffset, expression.endOffset, - expression.type, - functionArgument.symbol, functionArgument.descriptor - ).apply { + val immediateCall = with(expression) { + if (function is IrConstructor) + IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, type, function.symbol) + else + IrCallImpl(startOffset, endOffset, type, functionArgument.symbol) + }.apply { functionParameters.forEach { val argument = if (!unboundArgsSet.contains(it)) @@ -237,7 +244,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid for (index in 0 until functionArgument.typeArgumentsCount) putTypeArgument(index, functionArgument.getTypeArgument(index)) } - return this@FunctionInlining.visitCall(super.visitCall(immediateCall) as IrCall) + return this@FunctionInlining.visitExpression(super.visitExpression(immediateCall)) } if (functionArgument !is IrBlock) return super.visitCall(expression) @@ -292,7 +299,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid //-------------------------------------------------------------------------// - private fun buildParameterToArgument(callSite: IrCall, callee: IrFunction): List { + private fun buildParameterToArgument(callSite: IrFunctionAccessExpression, callee: IrFunction): List { val parameterToArgument = mutableListOf() @@ -367,7 +374,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid //-------------------------------------------------------------------------// - private fun evaluateArguments(callSite: IrCall, callee: IrFunction): List { + private fun evaluateArguments(callSite: IrFunctionAccessExpression, callee: IrFunction): List { val parameterToArgumentOld = buildParameterToArgument(callSite, callee) val evaluationStatements = mutableListOf() 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 74b606afa41..b28b3a9a551 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 @@ -649,28 +649,31 @@ internal class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfo ) } + override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { + expression.transformChildrenVoid() + + val descriptor = expression.descriptor.original + val callee = expression.symbol.owner + val initMethod = callee.getObjCInitMethod() ?: return expression + + val arguments = descriptor.valueParameters.map { expression.getValueArgument(it) } + assert(expression.extensionReceiver == null) + assert(expression.dispatchReceiver == null) + + val constructedClass = callee.constructedClass + val initMethodInfo = initMethod.getExternalObjCMethodInfo()!! + return builder.at(expression).run { + val classPtr = getObjCClass(constructedClass.symbol) + irForceNotNull(callAllocAndInit(classPtr, initMethodInfo, arguments, expression, initMethod)) + } + } + override fun visitCall(expression: IrCall): IrExpression { expression.transformChildrenVoid() val descriptor = expression.descriptor.original val callee = expression.symbol.owner - if (callee is IrConstructor) { - val initMethod = callee.getObjCInitMethod() - - if (initMethod != null) { - val arguments = descriptor.valueParameters.map { expression.getValueArgument(it) } - assert(expression.extensionReceiver == null) - assert(expression.dispatchReceiver == null) - - val constructedClass = callee.constructedClass - val initMethodInfo = initMethod.getExternalObjCMethodInfo()!! - return builder.at(expression).run { - val classPtr = getObjCClass(constructedClass.symbol) - irForceNotNull(callAllocAndInit(classPtr, initMethodInfo, arguments, expression, initMethod)) - } - } - } descriptor.getObjCFactoryInitMethodInfo()?.let { initMethodInfo -> val arguments = (0 until expression.valueArgumentsCount) @@ -858,6 +861,17 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi private fun generateCFunctionPointer(function: IrSimpleFunction, expression: IrExpression): IrExpression = generateWithStubs { generateCFunctionPointer(function, function, expression) } + override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { + expression.transformChildrenVoid(this) + + val function = expression.symbol.owner + val inlinedClass = function.returnType.getInlinedClassNative() + if (inlinedClass?.descriptor == interop.cPointer || inlinedClass?.descriptor == interop.nativePointed) { + throw Error("Native interop types constructors must not be called directly") + } + return expression + } + override fun visitCall(expression: IrCall): IrExpression { expression.transformChildrenVoid(this) @@ -865,13 +879,6 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi val descriptor = expression.descriptor.original val function = expression.symbol.owner - if (function is IrConstructor) { - val inlinedClass = function.returnType.getInlinedClassNative() - if (inlinedClass?.descriptor == interop.cPointer || inlinedClass?.descriptor == interop.nativePointed) { - throw Error("Native interop types constructors must not be called directly") - } - } - if (descriptor == interop.nativePointedRawPtrGetter || OverridingUtil.overrides(descriptor, interop.nativePointedRawPtrGetter)) { @@ -1029,8 +1036,7 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi val intrinsic = interop.objCObjectInitBy.name val argument = expression.getValueArgument(0)!! - val constructedClass = - ((argument as? IrCall)?.descriptor as? ClassConstructorDescriptor)?.constructedClass + val constructedClass = (argument as? IrConstructorCall)?.symbol?.owner?.constructedClass?.descriptor if (constructedClass == null) { context.reportCompilationError("Argument of '$intrinsic' must be a constructor call", diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt index 473a2b3c185..a464a641f54 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt @@ -1068,7 +1068,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass } } - fun IrBlockBodyBuilder.irSuccess(value: IrExpression): IrCall { + fun IrBlockBodyBuilder.irSuccess(value: IrExpression): IrMemberAccessExpression { val createResult = symbols.kotlinResult.owner.constructors.single { it.isPrimary } return irCall(createResult).apply { putValueArgument(0, value) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt index 0fb5fdef5db..38c54b6ef3a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt @@ -87,12 +87,7 @@ internal class VarargInjectionLowering constructor(val context: KonanBackendCont expression.transformChildrenVoid(this) } - override fun visitCall(expression: IrCall): IrExpression { - replaceEmptyParameterWithEmptyArray(expression) - return expression - } - - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { + override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression { replaceEmptyParameterWithEmptyArray(expression) return expression } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt index e677e567670..ecf9d5805c9 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt @@ -557,6 +557,17 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag else symbolTable.mapFunction(value.symbol.owner.constructors.single()) ) + is IrConstructorCall -> { + val callee = value.symbol.owner + val arguments = value.getArguments().map { expressionToEdge(it.second) } + DataFlowIR.Node.NewObject( + symbolTable.mapFunction(callee), + arguments, + symbolTable.mapClassReferenceType(callee.constructedClass, false), + value + ) + } + is IrCall -> when (value.symbol) { getContinuationSymbol -> getContinuation() @@ -573,9 +584,9 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag initInstanceSymbol -> { val thiz = expressionToEdge(value.getValueArgument(0)!!) - val initializer = value.getValueArgument(1) as IrCall + val initializer = value.getValueArgument(1) as IrConstructorCall val arguments = listOf(thiz) + initializer.getArguments().map { expressionToEdge(it.second) } - val callee = initializer.symbol.owner as IrConstructor + val callee = initializer.symbol.owner DataFlowIR.Node.StaticCall( symbolTable.mapFunction(callee), arguments, @@ -595,12 +606,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag it } if (callee is IrConstructor) { - DataFlowIR.Node.NewObject( - symbolTable.mapFunction(callee), - arguments, - symbolTable.mapClassReferenceType(callee.constructedClass, false), - value - ) + error("Constructor call should be done with IrConstructorCall") } else { callee as IrSimpleFunction if (callee.isOverridable && value.superQualifier == null) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt index f93715fe7b2..3ad46827374 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrGetField import org.jetbrains.kotlin.ir.types.IrType @@ -233,7 +234,8 @@ internal object DataFlowIR { : Call(callee, arguments, irCallSite) // TODO: It can be replaced with a pair(AllocInstance, constructor Call), remove. - class NewObject(constructor: FunctionSymbol, arguments: List, val constructedType: Type, override val irCallSite: IrCall?) + class NewObject(constructor: FunctionSymbol, arguments: List, val constructedType: Type, + override val irCallSite: IrConstructorCall?) : Call(constructor, arguments, irCallSite) open class VirtualCall(callee: FunctionSymbol, arguments: List, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt index c332a5d3880..912ed3e985b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt @@ -491,12 +491,10 @@ private fun IrFunction.substitutedReturnType(typeArguments: List): IrTyp // TODO: this function must be avoided since it takes symbol's owner implicitly. fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: List = emptyList()) = - irCall(symbol.owner, typeArguments) + this.irCall(symbol, symbol.owner.substitutedReturnType(typeArguments), typeArguments) -fun IrBuilderWithScope.irCall( - irFunction: IrFunction, - typeArguments: List = emptyList() -): IrCall = irCall(this.startOffset, this.endOffset, irFunction, typeArguments) +fun IrBuilderWithScope.irCall(irFunction: IrFunction, typeArguments: List = emptyList()) = + irCall(irFunction.symbol, typeArguments) internal fun irCall(startOffset: Int, endOffset: Int, irFunction: IrFunction, typeArguments: List): IrCall = IrCallImpl( @@ -512,7 +510,7 @@ fun IrBuilderWithScope.irCallOp( callee: IrFunction, dispatchReceiver: IrExpression, argument: IrExpression -): IrCall = +) = irCall(callee).apply { this.dispatchReceiver = dispatchReceiver putValueArgument(0, argument)