From 9bbecf33d2903708d68366bb0e20032f4aada691 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 26 Apr 2018 17:37:49 +0300 Subject: [PATCH] Migrate compiler to IR types --- .../common/AbstractValueUsageTransformer.kt | 87 +- .../jetbrains/kotlin/backend/konan/Boxing.kt | 4 + .../jetbrains/kotlin/backend/konan/Context.kt | 229 +++--- .../konan/EnumSpecialDescriptorsFactory.kt | 55 +- .../kotlin/backend/konan/KonanDriver.kt | 2 +- .../kotlin/backend/konan/KonanLower.kt | 6 - .../kotlin/backend/konan/ValueTypes.kt | 73 ++ .../konan/descriptors/ClassVtablesBuilder.kt | 2 +- .../konan/descriptors/DescriptorUtils.kt | 2 +- .../KonanSharedVariablesManager.kt | 43 +- .../jetbrains/kotlin/backend/konan/ir/Ir.kt | 73 +- .../kotlin/backend/konan/ir/KonanIr.kt | 11 +- .../konan/irasdescriptors/FakeIrUtils.kt | 17 +- .../konan/irasdescriptors/IrAsDescriptors.kt | 4 +- .../irasdescriptors/IrTypeAsKotlinType.kt | 123 +++ .../konan/irasdescriptors/NewIrUtils.kt | 158 +--- .../backend/konan/llvm/BinaryInterface.kt | 43 +- .../backend/konan/llvm/CodeGenerator.kt | 4 +- .../kotlin/backend/konan/llvm/DataLayout.kt | 13 +- .../kotlin/backend/konan/llvm/DebugUtils.kt | 4 +- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 69 +- .../llvm/KotlinObjCClassInfoGenerator.kt | 1 + .../backend/konan/llvm/LlvmDeclarations.kt | 3 +- .../backend/konan/llvm/RTTIGenerator.kt | 4 +- .../kotlin/backend/konan/llvm/Runtime.kt | 3 - .../kotlin/backend/konan/llvm/StaticData.kt | 1 - .../backend/konan/llvm/StaticObjects.kt | 3 - .../backend/konan/llvm/VariableManager.kt | 6 - .../llvm/objcexport/BlockPointerSupport.kt | 5 +- .../objcexport/ObjCExportCodeGenerator.kt | 2 +- .../kotlin/backend/konan/lower/Autoboxing.kt | 117 +-- .../backend/konan/lower/BridgesBuilding.kt | 55 +- .../konan/lower/BuiltinOperatorLowering.kt | 40 +- .../konan/lower/CallableReferenceLowering.kt | 155 ++-- .../lower/CompileTimeEvaluateLowering.kt | 9 +- .../konan/lower/DataClassOperatorsLowering.kt | 41 +- .../lower/DeepCopyIrTreeWithDescriptors.kt | 171 +++- .../lower/DefaultArgumentsStubGenerator.kt | 471 ----------- .../backend/konan/lower/DelegationLowering.kt | 112 +-- .../backend/konan/lower/EnumClassLowering.kt | 343 ++++---- .../backend/konan/lower/EnumWhenLowering.kt | 40 +- .../konan/lower/ExpectDeclarationsRemoving.kt | 12 +- .../konan/lower/FinallyBlocksLowering.kt | 62 +- .../backend/konan/lower/ForLoopsLowering.kt | 92 ++- .../backend/konan/lower/FunctionInlining.kt | 30 +- .../konan/lower/InitializersLowering.kt | 35 +- .../backend/konan/lower/InnerClassLowering.kt | 41 +- .../backend/konan/lower/InteropLowering.kt | 230 +++--- .../backend/konan/lower/LateinitLowering.kt | 63 +- .../konan/lower/LocalDeclarationsLowering.kt | 754 ------------------ .../backend/konan/lower/PostInlineLowering.kt | 11 +- .../backend/konan/lower/PreInlineLowering.kt | 2 +- .../konan/lower/SuspendFunctionsLowering.kt | 454 ++++++----- .../backend/konan/lower/TestProcessor.kt | 89 ++- .../konan/lower/TypeOperatorLowering.kt | 53 +- .../backend/konan/optimizations/DFGBuilder.kt | 73 +- .../backend/konan/optimizations/DataFlowIR.kt | 16 +- .../konan/optimizations/Devirtualization.kt | 48 +- .../konan/serialization/SerializeIr.kt | 115 +-- .../kotlin/ir/util/IrUnboundSymbolReplacer.kt | 77 +- .../org/jetbrains/kotlin/ir/util/IrUtils2.kt | 497 ++++++++++-- .../property/genericProperty.kt | 1 + .../src/main/kotlin/konan/worker/Worker.kt | 2 +- 63 files changed, 2543 insertions(+), 2818 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrTypeAsKotlinType.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentsStubGenerator.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LocalDeclarationsLowering.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt index 420b625c2b2..a2fb401cf3a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt @@ -16,17 +16,21 @@ package org.jetbrains.kotlin.backend.common +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration import org.jetbrains.kotlin.ir.declarations.IrVariable -import org.jetbrains.kotlin.ir.declarations.getDefault +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.types.KotlinType /** @@ -40,45 +44,64 @@ import org.jetbrains.kotlin.types.KotlinType * * TODO: consider making this visitor non-recursive to make it more general. */ -abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrElementTransformerVoid() { +internal abstract class AbstractValueUsageTransformer( + val builtIns: KotlinBuiltIns, + val symbols: KonanSymbols, + val irBuiltIns: IrBuiltIns +): IrElementTransformerVoid() { - protected open fun IrExpression.useAs(type: KotlinType): IrExpression = this + protected open fun IrExpression.useAs(type: IrType): IrExpression = this protected open fun IrExpression.useAsStatement(): IrExpression = this - protected open fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: KotlinType): IrExpression = + protected open fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: IrType): IrExpression = this - protected open fun IrExpression.useAsValue(value: ValueDescriptor): IrExpression = this.useAs(value.type) + protected open fun IrExpression.useAsValue(value: IrValueDeclaration): IrExpression = this.useAs(value.type) protected open fun IrExpression.useAsArgument(parameter: ParameterDescriptor): IrExpression = this.useAsValue(parameter) - protected open fun IrExpression.useAsDispatchReceiver(expression: IrMemberAccessExpression): IrExpression = - this.useAsArgument(expression.descriptor.dispatchReceiverParameter!!) + protected open fun IrExpression.useAsDispatchReceiver(expression: IrFunctionAccessExpression): IrExpression = + this.useAsArgument(expression.symbol.owner.dispatchReceiverParameter!!) - protected open fun IrExpression.useAsExtensionReceiver(expression: IrMemberAccessExpression): IrExpression = - this.useAsArgument(expression.descriptor.extensionReceiverParameter!!) + protected open fun IrExpression.useAsExtensionReceiver(expression: IrFunctionAccessExpression): IrExpression = + this.useAsArgument(expression.symbol.owner.extensionReceiverParameter!!) - protected open fun IrExpression.useAsValueArgument(expression: IrMemberAccessExpression, + protected open fun IrExpression.useAsValueArgument(expression: IrFunctionAccessExpression, parameter: ValueParameterDescriptor): IrExpression = this.useAsArgument(parameter) - protected open fun IrExpression.useForVariable(variable: VariableDescriptor): IrExpression = + private fun IrExpression.useForVariable(variable: VariableDescriptor): IrExpression = this.useAsValue(variable) - protected open fun IrExpression.useForField(field: PropertyDescriptor): IrExpression = - this.useForVariable(field) + private fun IrExpression.useForField(field: IrField): IrExpression = + this.useAs(field.type) - protected open fun IrExpression.useAsReturnValue(returnTarget: CallableDescriptor): IrExpression { - val returnType = returnTarget.returnType ?: return this - return this.useAs(returnType) - } + protected open fun IrExpression.useAsReturnValue(returnTarget: IrReturnTargetSymbol): IrExpression = + when (returnTarget) { + is IrSimpleFunctionSymbol -> this.useAs(returnTarget.owner.returnType) + is IrConstructorSymbol -> this.useAs(irBuiltIns.unitType) + is IrReturnableBlockSymbol -> this.useAs(returnTarget.owner.type) + else -> error(returnTarget) + } protected open fun IrExpression.useAsResult(enclosing: IrExpression): IrExpression = this.useAs(enclosing.type) - override fun visitMemberAccess(expression: IrMemberAccessExpression): IrExpression { + override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { + TODO() + } + + override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression { + TODO() + } + + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + TODO() + } + + override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression { expression.transformChildrenVoid(this) with(expression) { @@ -86,7 +109,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl extensionReceiver = extensionReceiver?.useAsExtensionReceiver(expression) for (index in descriptor.valueParameters.indices) { val argument = getValueArgument(index) ?: continue - val parameter = descriptor.valueParameters[index] + val parameter = symbol.owner.valueParameters[index] putValueArgument(index, argument.useAsValueArgument(expression, parameter)) } } @@ -130,7 +153,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl override fun visitReturn(expression: IrReturn): IrExpression { expression.transformChildrenVoid(this) - expression.value = expression.value.useAsReturnValue(expression.returnTarget) + expression.value = expression.value.useAsReturnValue(expression.returnTargetSymbol) return expression } @@ -138,7 +161,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl override fun visitSetVariable(expression: IrSetVariable): IrExpression { expression.transformChildrenVoid(this) - expression.value = expression.value.useForVariable(expression.descriptor) + expression.value = expression.value.useForVariable(expression.symbol.owner) return expression } @@ -146,7 +169,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl override fun visitSetField(expression: IrSetField): IrExpression { expression.transformChildrenVoid(this) - expression.value = expression.value.useForField(expression.descriptor) + expression.value = expression.value.useForField(expression.symbol.owner) return expression } @@ -155,7 +178,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl declaration.transformChildrenVoid(this) declaration.initializer?.let { - it.expression = it.expression.useForField(declaration.descriptor) + it.expression = it.expression.useForField(declaration) } return declaration @@ -164,7 +187,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl override fun visitVariable(declaration: IrVariable): IrVariable { declaration.transformChildrenVoid(this) - declaration.initializer = declaration.initializer?.useForVariable(declaration.descriptor) + declaration.initializer = declaration.initializer?.useForVariable(declaration) return declaration } @@ -173,7 +196,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl expression.transformChildrenVoid(this) for (irBranch in expression.branches) { - irBranch.condition = irBranch.condition.useAs(builtIns.booleanType) + irBranch.condition = irBranch.condition.useAs(irBuiltIns.booleanType) irBranch.result = irBranch.result.useAsResult(expression) } @@ -183,7 +206,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl override fun visitLoop(loop: IrLoop): IrExpression { loop.transformChildrenVoid(this) - loop.condition = loop.condition.useAs(builtIns.booleanType) + loop.condition = loop.condition.useAs(irBuiltIns.booleanType) loop.body = loop.body?.useAsStatement() @@ -193,7 +216,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl override fun visitThrow(expression: IrThrow): IrExpression { expression.transformChildrenVoid(this) - expression.value = expression.value.useAs(builtIns.throwable.defaultType) + expression.value = expression.value.useAs(symbols.throwable.owner.defaultType) return expression } @@ -238,8 +261,8 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl override fun visitFunction(declaration: IrFunction): IrStatement { declaration.transformChildrenVoid(this) - declaration.descriptor.valueParameters.forEach { parameter -> - val defaultValue = declaration.getDefault(parameter) + declaration.valueParameters.forEach { parameter -> + val defaultValue = parameter.defaultValue if (defaultValue is IrExpressionBody) { defaultValue.expression = defaultValue.expression.useAsArgument(parameter) } @@ -247,7 +270,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl declaration.body?.let { if (it is IrExpressionBody) { - it.expression = it.expression.useAsReturnValue(declaration.descriptor) + it.expression = it.expression.useAsReturnValue(declaration.symbol) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Boxing.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Boxing.kt index e8f148ce632..488668faf8c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Boxing.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Boxing.kt @@ -21,6 +21,7 @@ import llvm.* import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols import org.jetbrains.kotlin.backend.konan.llvm.* import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.getPropertyGetter import org.jetbrains.kotlin.konan.target.KonanTarget @@ -29,6 +30,9 @@ import org.jetbrains.kotlin.types.KotlinType internal fun KonanSymbols.getTypeConversion(actualType: KotlinType, expectedType: KotlinType) = getTypeConversion(actualType.correspondingValueType, expectedType.correspondingValueType) +internal fun KonanSymbols.getTypeConversion(actualType: IrType, expectedType: IrType) = + getTypeConversion(actualType.correspondingValueType, expectedType.correspondingValueType) + internal fun KonanSymbols.getTypeConversion( actualValueType: ValueType?, expectedValueType: ValueType? diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index 7cce2ff60c4..3621e22f3ef 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -18,18 +18,16 @@ package org.jetbrains.kotlin.backend.konan import llvm.LLVMDumpModule import llvm.LLVMModuleRef +import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor import org.jetbrains.kotlin.backend.common.ReflectionTypes import org.jetbrains.kotlin.backend.common.validateIrModule -import org.jetbrains.kotlin.backend.jvm.descriptors.initialize import org.jetbrains.kotlin.backend.konan.descriptors.* -import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor import org.jetbrains.kotlin.backend.common.descriptors.DescriptorsFactory import org.jetbrains.kotlin.backend.konan.ir.KonanIr import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter import org.jetbrains.kotlin.backend.konan.library.LinkData import org.jetbrains.kotlin.backend.konan.llvm.* import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD -import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations @@ -42,23 +40,23 @@ import org.jetbrains.kotlin.ir.SourceManager import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor -import org.jetbrains.kotlin.ir.util.createParameterDeclarations -import org.jetbrains.kotlin.ir.util.endOffsetOrUndefined -import org.jetbrains.kotlin.ir.util.startOffsetOrUndefined +import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.toKotlinType +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.konan.target.CompilerOutputKind -import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature import org.jetbrains.kotlin.metadata.KonanLinkData import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext -import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor import org.jetbrains.kotlin.serialization.deserialization.getName +import org.jetbrains.kotlin.types.KotlinType import java.lang.System.out import kotlin.LazyThreadSafetyMode.PUBLICATION @@ -66,72 +64,49 @@ internal class SpecialDeclarationsFactory(val context: Context) { private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) } private val outerThisFields = mutableMapOf() private val bridgesDescriptors = mutableMapOf, IrSimpleFunction>() - private val loweredEnums = mutableMapOf() - private val ordinals = mutableMapOf>() + private val loweredEnums = mutableMapOf() + private val ordinals = mutableMapOf>() object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS") - fun getOuterThisField(innerClassDescriptor: ClassDescriptor): IrField = - if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor") - else outerThisFields.getOrPut(innerClassDescriptor) { - val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) ?: - throw AssertionError("No containing class for inner class $innerClassDescriptor") + fun getOuterThisField(innerClass: IrClass): IrField = + if (!innerClass.descriptor.isInner) throw AssertionError("Class is not inner: ${innerClass.descriptor}") + else outerThisFields.getOrPut(innerClass.descriptor) { + val outerClass = innerClass.parent as? IrClass + ?: throw AssertionError("No containing class for inner class ${innerClass.descriptor}") - val receiver = ReceiverParameterDescriptorImpl(innerClassDescriptor, ImplicitClassReceiver(innerClassDescriptor)) + val receiver = ReceiverParameterDescriptorImpl(innerClass.descriptor, ImplicitClassReceiver(innerClass.descriptor)) val descriptor = PropertyDescriptorImpl.create( - innerClassDescriptor, Annotations.EMPTY, Modality.FINAL, + innerClass.descriptor, Annotations.EMPTY, Modality.FINAL, Visibilities.PRIVATE, false, "this$0".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, false, false, false, false, false, false - ).initialize(outerClassDescriptor.defaultType, dispatchReceiverParameter = receiver) + ).apply { + val receiverType: KotlinType? = null + this.setType(outerClass.descriptor.defaultType, emptyList(), receiver, receiverType) + initialize(null, null) + } IrFieldImpl( - innerClassDescriptor.startOffsetOrUndefined, - innerClassDescriptor.endOffsetOrUndefined, + innerClass.descriptor.startOffsetOrUndefined, + innerClass.descriptor.endOffsetOrUndefined, DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS, - descriptor + descriptor, + outerClass.defaultType ) } - fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): IrSimpleFunction { - val irFunction = overriddenFunctionDescriptor.descriptor - val descriptor = irFunction.descriptor - assert(overriddenFunctionDescriptor.needBridge, - { "Function $descriptor is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor.descriptor}" }) - val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections - return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) { - val bridgeDescriptor = SimpleFunctionDescriptorImpl.create( - /* containingDeclaration = */ descriptor.containingDeclaration, - /* annotations = */ Annotations.EMPTY, - /* name = */ "${irFunction.functionName}".synthesizedName, - /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, - /* source = */ SourceElement.NO_SOURCE).apply { - initializeBridgeDescriptor(this, descriptor, bridgeDirections.array) - } - - IrFunctionImpl( - irFunction.startOffset, - irFunction.endOffset, - DECLARATION_ORIGIN_BRIDGE_METHOD(irFunction), - bridgeDescriptor - ).apply { - createParameterDeclarations() - this.parent = overriddenFunctionDescriptor.descriptor.parent - } + fun getLoweredEnum(enumClass: IrClass): LoweredEnum { + assert(enumClass.kind == ClassKind.ENUM_CLASS, { "Expected enum class but was: ${enumClass.descriptor}" }) + return loweredEnums.getOrPut(enumClass) { + enumSpecialDeclarationsFactory.createLoweredEnum(enumClass) } } - fun getLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum { - assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS, { "Expected enum class but was: $enumClassDescriptor" }) - return loweredEnums.getOrPut(enumClassDescriptor) { - enumSpecialDeclarationsFactory.createLoweredEnum(enumClassDescriptor) - } - } - - private fun assignOrdinalsToEnumEntries(irClass: IrClass): Map { + private fun assignOrdinalsToEnumEntries(classDescriptor: ClassDescriptor): Map { val enumEntryOrdinals = mutableMapOf() - irClass.declarations.filterIsInstance().forEachIndexed { index, entry -> - enumEntryOrdinals[entry.descriptor] = index + classDescriptor.enumEntries.forEachIndexed { index, entry -> + enumEntryOrdinals[entry] = index } return enumEntryOrdinals } @@ -145,54 +120,130 @@ internal class SpecialDeclarationsFactory(val context: Context) { .first { entryDescriptor.name == enumClassDescriptor.c.nameResolver.getName(it.name) } .getExtension(KonanLinkData.enumEntryOrdinal) } - val enumClass = context.ir.getEnum(enumClassDescriptor) - return ordinals.getOrPut(enumClass) { assignOrdinalsToEnumEntries(enumClass) }[entryDescriptor]!! + return ordinals.getOrPut(enumClassDescriptor) { assignOrdinalsToEnumEntries(enumClassDescriptor) }[entryDescriptor]!! } - private fun initializeBridgeDescriptor(bridgeDescriptor: SimpleFunctionDescriptorImpl, - descriptor: FunctionDescriptor, - bridgeDirections: Array) { - val returnType = when (bridgeDirections[0]) { - BridgeDirection.TO_VALUE_TYPE -> descriptor.returnType!! - BridgeDirection.NOT_NEEDED -> descriptor.returnType - BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.nullableAnyType + fun getBridge(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): IrSimpleFunction { + val irFunction = overriddenFunctionDescriptor.descriptor + assert(overriddenFunctionDescriptor.needBridge, + { "Function ${irFunction.descriptor} is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor.descriptor}" }) + val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections + return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) { + createBridge(irFunction, bridgeDirections) + } + } + + private fun createBridge(function: IrFunction, bridgeDirections: BridgeDirections): IrFunctionImpl { + val returnType = when (bridgeDirections.array[0]) { + BridgeDirection.TO_VALUE_TYPE, + BridgeDirection.NOT_NEEDED -> function.returnType + BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyNType } - val extensionReceiverType = when (bridgeDirections[1]) { - BridgeDirection.TO_VALUE_TYPE -> descriptor.extensionReceiverParameter!!.type - BridgeDirection.NOT_NEEDED -> descriptor.extensionReceiverParameter?.type - BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.nullableAnyType + val extensionReceiverType = when (bridgeDirections.array[1]) { + BridgeDirection.TO_VALUE_TYPE -> function.extensionReceiverParameter!!.type + BridgeDirection.NOT_NEEDED -> function.extensionReceiverParameter?.type + BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyNType } + val valueParameterTypes = function.valueParameters.mapIndexed { index, valueParameter -> + when (bridgeDirections.array[index + 2]) { + BridgeDirection.TO_VALUE_TYPE -> valueParameter.type + BridgeDirection.NOT_NEEDED -> valueParameter.type + BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyNType + } + } + val bridgeDescriptor = createBridgeDescriptor( + function, + bridgeDirections, + returnType, + extensionReceiverType, + valueParameterTypes + ) + + val bridge = IrFunctionImpl( + function.startOffset, + function.endOffset, + DECLARATION_ORIGIN_BRIDGE_METHOD(function), + bridgeDescriptor + ).apply { + this.returnType = returnType + this.parent = function.parent + } + + bridge.createDispatchReceiverParameter() + extensionReceiverType?.let { + val extensionReceiverParameter = function.extensionReceiverParameter!! + bridge.extensionReceiverParameter = IrValueParameterImpl( + extensionReceiverParameter.startOffset, + extensionReceiverParameter.endOffset, + extensionReceiverParameter.origin, + bridge.descriptor.extensionReceiverParameter!!, + it, null + ) + } + function.valueParameters.mapIndexedTo(bridge.valueParameters) { index, valueParameter -> + val type = valueParameterTypes[index] + + IrValueParameterImpl( + valueParameter.startOffset, + valueParameter.endOffset, + valueParameter.origin, + bridge.descriptor.valueParameters[index], + type, valueParameter.varargElementType + ) + } + + function.typeParameters.mapTo(bridge.typeParameters) { + IrTypeParameterImpl(it.startOffset, it.endOffset, it.origin, it.descriptor).apply { + superTypes += it.superTypes + } + } + + return bridge + } + + private fun createBridgeDescriptor( + function: IrFunction, + bridgeDirections: BridgeDirections, + returnType: IrType, + extensionReceiverType: IrType?, + valueParameterTypes: List + ): SimpleFunctionDescriptor { + + val descriptor = function.descriptor + val bridgeDescriptor = SimpleFunctionDescriptorImpl.create( + /* containingDeclaration = */ descriptor.containingDeclaration, + /* annotations = */ Annotations.EMPTY, + /* name = */ "${function.functionName}".synthesizedName, + /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, + /* source = */ SourceElement.NO_SOURCE) + val valueParameters = descriptor.valueParameters.mapIndexed { index, valueParameterDescriptor -> - val outType = when (bridgeDirections[index + 2]) { - BridgeDirection.TO_VALUE_TYPE -> valueParameterDescriptor.type - BridgeDirection.NOT_NEEDED -> valueParameterDescriptor.type - BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.nullableAnyType - } - ValueParameterDescriptorImpl( + ValueParameterDescriptorImpl( containingDeclaration = valueParameterDescriptor.containingDeclaration, - original = null, - index = index, - annotations = Annotations.EMPTY, - name = valueParameterDescriptor.name, - outType = outType, - declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(), - isCrossinline = valueParameterDescriptor.isCrossinline, - isNoinline = valueParameterDescriptor.isNoinline, - varargElementType = valueParameterDescriptor.varargElementType, - source = SourceElement.NO_SOURCE) + original = null, + index = index, + annotations = Annotations.EMPTY, + name = valueParameterDescriptor.name, + outType = valueParameterTypes[index].toKotlinType(), + declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(), + isCrossinline = valueParameterDescriptor.isCrossinline, + isNoinline = valueParameterDescriptor.isNoinline, + varargElementType = valueParameterDescriptor.varargElementType, + source = SourceElement.NO_SOURCE) } bridgeDescriptor.initialize( - /* receiverParameterType = */ extensionReceiverType, + /* receiverParameterType = */ extensionReceiverType?.toKotlinType(), /* dispatchReceiverParameter = */ descriptor.dispatchReceiverParameter, /* typeParameters = */ descriptor.typeParameters, /* unsubstitutedValueParameters = */ valueParameters, - /* unsubstitutedReturnType = */ returnType, + /* unsubstitutedReturnType = */ returnType.toKotlinType(), /* modality = */ descriptor.modality, /* visibility = */ descriptor.visibility).apply { - isSuspend = descriptor.isSuspend + isSuspend = descriptor.isSuspend } + return bridgeDescriptor } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt index d38033ea632..7efaccd43e0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt @@ -16,10 +16,10 @@ package org.jetbrains.kotlin.backend.konan -import org.jetbrains.kotlin.backend.jvm.descriptors.initialize +import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName -import org.jetbrains.kotlin.backend.common.ir.createSimpleDelegatingConstructorDescriptor import org.jetbrains.kotlin.backend.konan.descriptors.enumEntries +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.* @@ -31,10 +31,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.types.TypeProjectionImpl -import org.jetbrains.kotlin.types.TypeSubstitutor -import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.types.replace +import org.jetbrains.kotlin.types.* internal object DECLARATION_ORIGIN_ENUM : @@ -48,36 +45,45 @@ internal data class LoweredEnum(val implObject: IrClass, val entriesMap: Map) internal class EnumSpecialDeclarationsFactory(val context: Context) { - fun createLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum { + fun createLoweredEnum(enumClass: IrClass): LoweredEnum { + val enumClassDescriptor = enumClass.descriptor - val startOffset = enumClassDescriptor.startOffsetOrUndefined - val endOffset = enumClassDescriptor.endOffsetOrUndefined + val startOffset = enumClass.startOffset + val endOffset = enumClass.endOffset val implObjectDescriptor = ClassDescriptorImpl(enumClassDescriptor, "OBJECT".synthesizedName, Modality.FINAL, ClassKind.OBJECT, listOf(context.builtIns.anyType), SourceElement.NO_SOURCE, false, LockBasedStorageManager.NO_LOCKS) + val implObject = IrClassImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, implObjectDescriptor).apply { + createParameterDeclarations() + } + val valuesProperty = createEnumValuesField(enumClassDescriptor, implObjectDescriptor) - val valuesField = IrFieldImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesProperty) + val valuesType = context.ir.symbols.array.typeWith(enumClass.defaultType) + val valuesField = IrFieldImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesProperty, valuesType) val valuesGetterDescriptor = createValuesGetterDescriptor(enumClassDescriptor, implObjectDescriptor) - val valuesGetter = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesGetterDescriptor).apply { - createParameterDeclarations() + val valuesGetter = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesGetterDescriptor).also { + it.returnType = valuesType + it.parent = implObject + it.createDispatchReceiverParameter() } val memberScope = MemberScope.Empty - val constructorOfAny = context.builtIns.any.constructors.first() + val constructorOfAny = context.irBuiltIns.anyClass.owner.constructors.first() // TODO: why primary? - val constructorDescriptor = implObjectDescriptor.createSimpleDelegatingConstructorDescriptor(constructorOfAny, true) + val constructor = implObject.addSimpleDelegatingConstructor( + constructorOfAny, + context.irBuiltIns, + DECLARATION_ORIGIN_ENUM, + true + ) + val constructorDescriptor = constructor.descriptor implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor) - val implObject = IrClassImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, implObjectDescriptor).apply { - createParameterDeclarations() - addFakeOverrides() - setSuperSymbols(listOf(context.ir.symbols.any.owner)) - } - implObject.parent = context.ir.getEnum(enumClassDescriptor) - valuesGetter.parent = implObject + implObject.setSuperSymbolsAndAddFakeOverrides(listOf(context.irBuiltIns.anyType)) + implObject.parent = enumClass valuesField.parent = implObject val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor) @@ -115,7 +121,12 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) { val receiver = ReceiverParameterDescriptorImpl(implObjectDescriptor, ImplicitClassReceiver(implObjectDescriptor)) return PropertyDescriptorImpl.create(implObjectDescriptor, Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC, false, "VALUES".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, - false, false, false, false, false, false).initialize(valuesArrayType, dispatchReceiverParameter = receiver) + false, false, false, false, false, false).apply { + + val receiverType: KotlinType? = null + this.setType(valuesArrayType, emptyList(), receiver, receiverType) + this.initialize(null, null) + } } private val genericArrayType = context.ir.symbols.array.descriptor diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt index 677c0414687..065e690a4cf 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt @@ -79,7 +79,7 @@ fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironme context.irModule = module context.ir.symbols = symbols - validateIrModule(context, module) +// validateIrModule(context, module) } phaser.phase(KonanPhase.SERIALIZER) { markBackingFields(context) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt index 8210f3bed49..8c744f1f05c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt @@ -18,13 +18,9 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.common.lower.* -import org.jetbrains.kotlin.backend.konan.irasdescriptors.referenceAllTypeExternalClassifiers import org.jetbrains.kotlin.backend.konan.lower.* -import org.jetbrains.kotlin.backend.konan.lower.DefaultArgumentStubGenerator -import org.jetbrains.kotlin.backend.konan.lower.DefaultParameterInjector import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering import org.jetbrains.kotlin.backend.konan.lower.LateinitLowering -import org.jetbrains.kotlin.backend.konan.lower.LocalDeclarationsLowering import org.jetbrains.kotlin.backend.konan.lower.SharedVariablesLowering import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment @@ -83,12 +79,10 @@ internal class KonanLower(val context: Context) { } val symbolTable = context.ir.symbols.symbolTable - irModule.referenceAllTypeExternalClassifiers(symbolTable) do { @Suppress("DEPRECATION") irModule.replaceUnboundSymbols(context) - irModule.referenceAllTypeExternalClassifiers(symbolTable) } while (symbolTable.unboundClasses.isNotEmpty()) irModule.patchDeclarationParents() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ValueTypes.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ValueTypes.kt index 1943d83c87f..93f437cc030 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ValueTypes.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ValueTypes.kt @@ -17,7 +17,14 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.name.FqNameUnsafe +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.KotlinType /** @@ -96,3 +103,69 @@ val KotlinType.correspondingValueType: ValueType? get() = ValueType.values().firstOrNull { isRepresentedAs(it) } + + +////// + +private fun IrType.isConstructedFromGivenClass(fqName: FqNameUnsafe) = + (this.classifierOrNull as? IrClassSymbol)?.descriptor?.fqNameSafe?.toUnsafe() == fqName + +private val IrClassifierSymbol.ownerSuperTypes: List + get() = when (this) { + is IrClassSymbol -> this.owner.superTypes + is IrTypeParameterSymbol -> this.owner.superTypes + else -> error(this) + } + + +/** + * @return `true` if this type must be represented as given value type in generated code. + */ +tailrec fun IrType.isRepresentedAs(valueType: ValueType): Boolean { + if (this !is IrSimpleType) { + return false + } + + if (this.hasQuestionMark && !valueType.isNullable) { + return false + } + + if (this.isConstructedFromGivenClass(valueType.classFqName)) { + return true + } + + // Supertypes should be checked even for "final" value types (e.g. Int) + // to treat type parameter `T` with `Int` upper bound as value type. + // This behavior is observed on Kotlin JVM and used in interop implementation. + // + // However to optimize this method only first supertype is checked + // (it is supposed to be enough in all sane cases). + val firstSupertype = this.classifier.ownerSuperTypes.firstOrNull() ?: return false + return firstSupertype.isRepresentedAs(valueType) +} + +/** + * @return `true` if this type without `null` value must be represented as given value type in generated code. + * + * TODO: this method can be considered as a hack; rework its usages. + */ +tailrec fun IrType.notNullableIsRepresentedAs(valueType: ValueType): Boolean { + if (this.isConstructedFromGivenClass(valueType.classFqName)) { + return true + } + + // See comment in [isRepresentedAs]. + val firstSupertype = this.classifierOrNull?.ownerSuperTypes?.firstOrNull() ?: return false + return firstSupertype.notNullableIsRepresentedAs(valueType) +} + +fun IrType.isValueType() = ValueType.values().any { this.isRepresentedAs(it) } + +/** + * @return the [ValueType] given type represented in generated code as, + * or `null` if represented as object reference. + */ +val IrType.correspondingValueType: ValueType? + get() = ValueType.values().firstOrNull { + isRepresentedAs(it) + } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt index 2771321f3c9..9d86cc794d1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt @@ -61,7 +61,7 @@ internal class OverriddenFunctionDescriptor( } else { descriptor } - context.specialDeclarationsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor)) + context.specialDeclarationsFactory.getBridge(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor)) } return if (implementation.modality == Modality.ABSTRACT) null else implementation } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index 76c47d114ea..d387b549ef2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -21,9 +21,9 @@ import org.jetbrains.kotlin.backend.konan.isValueType import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.types.SimpleType -import org.jetbrains.kotlin.types.typeUtil.isUnit /** * List of all implemented interfaces (including those which implemented by a super class) 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 9cfe4c48c88..1daa14ac1da 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 @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.konan.descriptors import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager import org.jetbrains.kotlin.backend.konan.KonanBackendContext +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor @@ -34,8 +35,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl 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.util.constructors -import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.types.* internal class KonanSharedVariablesManager(val context: KonanBackendContext) : SharedVariablesManager { @@ -55,7 +56,7 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S } private fun refType(elementType: KotlinType): KotlinType { - return refClass.owner.defaultType.replace(listOf(TypeProjectionImpl(elementType))) + return refClass.descriptor.defaultType.replace(listOf(TypeProjectionImpl(elementType))) } private fun getElementPropertyDescriptor(sharedVariableDescriptor: VariableDescriptor): PropertyDescriptor { @@ -74,18 +75,19 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S false, false, variableDescriptor.source ) - val valueType = originalDeclaration.descriptor.type - - val refConstructorTypeArguments = mapOf(refClassConstructor.descriptor.typeParameters[0] to valueType) + val valueType = originalDeclaration.type val refConstructorCall = IrCallImpl( originalDeclaration.startOffset, originalDeclaration.endOffset, - refClassConstructor, refConstructor(valueType), refConstructorTypeArguments - ) + refClass.typeWith(valueType), + refClassConstructor, refConstructor(valueType.toKotlinType()), 1 + ).apply { + putTypeArgument(0, valueType) + } return IrVariableImpl( originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin, - sharedVariableDescriptor + sharedVariableDescriptor, refConstructorCall.type ).apply { initializer = refConstructorCall } @@ -97,16 +99,18 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableDeclaration.descriptor) val sharedVariableInitialization = - IrCallImpl(initializer.startOffset, initializer.endOffset, elementProperty.setter!!.symbol, + IrCallImpl(initializer.startOffset, initializer.endOffset, + context.irBuiltIns.unitType, elementProperty.setter!!.symbol, elementPropertyDescriptor.setter!!) sharedVariableInitialization.dispatchReceiver = - IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableDeclaration.symbol) + IrGetValueImpl(initializer.startOffset, initializer.endOffset, + sharedVariableDeclaration.type, sharedVariableDeclaration.symbol) sharedVariableInitialization.putValueArgument(0, initializer) return IrCompositeImpl( - originalDeclaration.startOffset, originalDeclaration.endOffset, context.builtIns.unitType, null, + originalDeclaration.startOffset, originalDeclaration.endOffset, context.irBuiltIns.unitType, null, listOf(sharedVariableDeclaration, sharedVariableInitialization) ) } @@ -115,18 +119,25 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableSymbol.descriptor) - return IrCallImpl(originalGet.startOffset, originalGet.endOffset, elementProperty.getter!!.symbol, + return IrCallImpl(originalGet.startOffset, originalGet.endOffset, + originalGet.type, elementProperty.getter!!.symbol, elementPropertyDescriptor.getter!!).apply { - dispatchReceiver = IrGetValueImpl(originalGet.startOffset, originalGet.endOffset, sharedVariableSymbol) + dispatchReceiver = IrGetValueImpl( + originalGet.startOffset, originalGet.endOffset, + sharedVariableSymbol.owner.type, sharedVariableSymbol + ) } } override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetVariable): IrExpression { val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableSymbol.descriptor) - return IrCallImpl(originalSet.startOffset, originalSet.endOffset, elementProperty.setter!!.symbol, - elementPropertyDescriptor.setter!!).apply { - dispatchReceiver = IrGetValueImpl(originalSet.startOffset, originalSet.endOffset, sharedVariableSymbol) + return IrCallImpl(originalSet.startOffset, originalSet.endOffset, context.irBuiltIns.unitType, + elementProperty.setter!!.symbol, elementPropertyDescriptor.setter!!).apply { + dispatchReceiver = IrGetValueImpl( + originalSet.startOffset, originalSet.endOffset, + sharedVariableSymbol.owner.type, sharedVariableSymbol + ) putValueArgument(0, originalSet.value) } } 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 e0fe4cc3531..f3fb2c28197 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 @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS import org.jetbrains.kotlin.backend.konan.ValueType import org.jetbrains.kotlin.backend.konan.descriptors.konanInternal +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint import org.jetbrains.kotlin.backend.konan.lower.TestProcessor import org.jetbrains.kotlin.builtins.KotlinBuiltIns @@ -38,12 +39,19 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl +import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl +import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.translateErased import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor import org.jetbrains.kotlin.types.KotlinType import kotlin.properties.Delegates @@ -58,9 +66,6 @@ internal class KonanIr(context: Context, irModule: IrModuleFragment): Ir { + val classifier = IrClassSymbolImpl(declarationDescriptor) + val typeArguments = type.arguments.map { + if (it.isStarProjection) { + IrStarProjectionImpl + } else { + makeTypeProjection(translateBroken(it.type), it.projectionKind) + } + } + IrSimpleTypeImpl( + classifier, + type.isMarkedNullable, + typeArguments, + emptyList() + ) + } + is TypeParameterDescriptor -> IrSimpleTypeImpl( + IrTypeParameterSymbolImpl(declarationDescriptor), + type.isMarkedNullable, + emptyList(), + emptyList() + ) + else -> error(declarationDescriptor ?: "null") + } } } @@ -105,6 +135,8 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym val throwable = symbolTable.referenceClass(builtIns.throwable) val string = symbolTable.referenceClass(builtIns.string) val enum = symbolTable.referenceClass(builtIns.enum) + val nativePtr = symbolTable.referenceClass(context.builtIns.nativePtr) + val nativePtrType = nativePtr.typeWith(arguments = emptyList()) val arrayList = symbolTable.referenceClass(getArrayListClassDescriptor(context)) @@ -225,19 +257,25 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym val getProgressionLast = context.getInternalFunctions("getProgressionLast") .map { Pair(it.returnType, symbolTable.referenceSimpleFunction(it)) }.toMap() - val arrayContentToString = arrayTypes.associateBy({ it }, { findArrayExtension(it, "contentToString") }) - val arrayContentHashCode = arrayTypes.associateBy({ it }, { findArrayExtension(it, "contentHashCode") }) + val arrayContentToString = arrays.associateBy( + { it }, + { findArrayExtension(it.descriptor, "contentToString") } + ) + val arrayContentHashCode = arrays.associateBy( + { it }, + { findArrayExtension(it.descriptor, "contentHashCode") } + ) - fun findArrayExtension(type: KotlinType, name: String): IrSimpleFunctionSymbol { - val descriptor = builtInsPackage("kotlin", "collections") + fun findArrayExtension(descriptor: ClassDescriptor, name: String): IrSimpleFunctionSymbol { + val functionDescriptor = builtInsPackage("kotlin", "collections") .getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND) .singleOrNull { it.valueParameters.isEmpty() - && (it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.defaultType == type + && it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == descriptor && !it.isExpect } - ?: throw Error(type.toString()) - return symbolTable.referenceSimpleFunction(descriptor) + ?: throw Error(descriptor.toString()) + return symbolTable.referenceSimpleFunction(functionDescriptor) } override val copyRangeTo = arrays.map { symbol -> @@ -340,6 +378,11 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym val kFunctions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS) .map { symbolTable.referenceClass(context.reflectionTypes.getKFunction(it)) } + fun getKFunctionType(returnType: IrType, parameterTypes: List): IrType { + val kFunctionClassSymbol = kFunctions[parameterTypes.size] + return kFunctionClassSymbol.typeWith(parameterTypes + returnType) + } + val suspendFunctions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS) .map { symbolTable.referenceClass(builtIns.getSuspendFunction(it)) } 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 a4b43827518..24c357aa67f 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 @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrFileSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.konan.file.File @@ -148,7 +149,7 @@ interface IrSuspendableExpression : IrExpression { var result: IrExpression } -class IrSuspensionPointImpl(startOffset: Int, endOffset: Int, type: KotlinType, +class IrSuspensionPointImpl(startOffset: Int, endOffset: Int, type: IrType, override var suspensionPointIdParameter: IrVariable, override var result: IrExpression, override var resumeResult: IrExpression) @@ -170,7 +171,7 @@ class IrSuspensionPointImpl(startOffset: Int, endOffset: Int, type: KotlinType, } } -class IrSuspendableExpressionImpl(startOffset: Int, endOffset: Int, type: KotlinType, +class IrSuspendableExpressionImpl(startOffset: Int, endOffset: Int, type: IrType, override var suspensionPointId: IrExpression, override var result: IrExpression) : IrExpressionBase(startOffset, endOffset, type), IrSuspendableExpression { @@ -198,7 +199,7 @@ internal interface IrPrivateFunctionCall : IrCall { internal class IrPrivateFunctionCallImpl(startOffset: Int, endOffset: Int, - type: KotlinType, + type: IrType, override val symbol: IrFunctionSymbol, override val descriptor: FunctionDescriptor, override val virtualCallee: IrCall?, @@ -235,9 +236,9 @@ internal interface IrPrivateClassReference : IrClassReference { internal class IrPrivateClassReferenceImpl(startOffset: Int, endOffset: Int, - type: KotlinType, + type: IrType, symbol: IrClassifierSymbol, - override val classType: KotlinType, + override val classType: IrType, override val moduleDescriptor: ModuleDescriptor, override val totalClasses: Int, override val classIndex: Int, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/FakeIrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/FakeIrUtils.kt index f44f1671727..8cd28d11806 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/FakeIrUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/FakeIrUtils.kt @@ -18,23 +18,16 @@ package org.jetbrains.kotlin.backend.konan.irasdescriptors import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.llvm.llvmSymbolOrigin -import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.idea.MainFunctionDetector -import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.constants.* -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.module // This file contains some IR utilities which actually use descriptors. // TODO: port this code to IR. -internal val IrDeclaration.annotations get() = this.descriptor.annotations internal val IrDeclaration.isAnonymousObject get() = DescriptorUtils.isAnonymousObject(this.descriptor) internal val IrFunction.isExternal get() = this.descriptor.isExternal internal val IrDeclaration.isLocal get() = DescriptorUtils.isLocal(this.descriptor) @@ -59,9 +52,5 @@ internal val IrDeclaration.llvmSymbolOrigin get() = this.descriptor.llvmSymbolOr internal fun IrFunction.isMain() = MainFunctionDetector.isMain(this.descriptor) -internal fun IrTypeOperatorCall.getTypeOperandClass(context: Context): IrClass? = - context.ir.getClass(this.typeOperand) - -internal fun IrCatch.getCatchParameterTypeClass(context: Context): IrClass? = - context.ir.getClass(this.catchParameter.type) +internal fun IrType.isObjCObjectType() = this.toKotlinType().isObjCObjectType() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrAsDescriptors.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrAsDescriptors.kt index b982e51befe..5d17c0b88a0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrAsDescriptors.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrAsDescriptors.kt @@ -27,5 +27,7 @@ internal typealias ConstructorDescriptor = IrConstructor internal typealias ClassConstructorDescriptor = IrConstructor internal typealias PackageFragmentDescriptor = IrPackageFragment internal typealias VariableDescriptor = IrVariable -internal typealias ValueDescriptor = IrSymbolDeclaration +internal typealias ValueDescriptor = IrValueDeclaration internal typealias ParameterDescriptor = IrValueParameter +internal typealias ValueParameterDescriptor = IrValueParameter +internal typealias TypeParameterDescriptor = IrTypeParameter diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrTypeAsKotlinType.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrTypeAsKotlinType.kt new file mode 100644 index 00000000000..af48b0d7556 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrTypeAsKotlinType.kt @@ -0,0 +1,123 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan.irasdescriptors + +import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor +import org.jetbrains.kotlin.builtins.getFunctionalClassKind +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl +import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl +import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf + +val IrClassifierSymbol.typeWithoutArguments: IrType + get() = when (this) { + is IrClassSymbol -> { + require(this.descriptor.declaredTypeParameters.isEmpty()) + this.typeWith(arguments = emptyList()) + } + is IrTypeParameterSymbol -> this.defaultType + else -> error(this) + } + +val IrClassifierSymbol.typeWithStarProjections + get() = when (this) { + is IrClassSymbol -> createType( + hasQuestionMark = false, + arguments = this.descriptor.declaredTypeParameters.map { IrStarProjectionImpl } + ) + is IrTypeParameterSymbol -> this.defaultType + else -> error(this) + } + +val IrTypeParameterSymbol.defaultType: IrType get() = IrSimpleTypeImpl( + this, + false, + emptyList(), + emptyList() +) +val IrTypeParameter.defaultType: IrType get() = this.symbol.defaultType + +fun IrClassifierSymbol.typeWith(vararg arguments: IrType): IrSimpleType = typeWith(arguments.toList()) + +fun IrClassifierSymbol.typeWith(arguments: List): IrSimpleType = + IrSimpleTypeImpl( + this, + false, + arguments.map { makeTypeProjection(it, Variance.INVARIANT) }, + emptyList() + ) + +fun IrClass.typeWith(arguments: List) = this.symbol.typeWith(arguments) + +fun IrClassSymbol.createType(hasQuestionMark: Boolean, arguments: List): IrSimpleType = + IrSimpleTypeImpl( + this, + hasQuestionMark, + arguments, + emptyList() + ) + +fun IrType.getClass(): IrClass? = + (this.classifierOrNull as? IrClassSymbol)?.owner + +fun IrType.makeNullableAsSpecified(nullable: Boolean): IrType = + if (nullable) this.makeNullable() else this.makeNotNull() + +fun IrType.containsNull(): Boolean = if (this is IrSimpleType) { + if (this.hasQuestionMark) { + true + } else { + val classifier = this.classifier + when (classifier) { + is IrClassSymbol -> false + is IrTypeParameterSymbol -> classifier.owner.superTypes.any { it.containsNull() } + else -> error(classifier) + } + } +} else { + true +} + +// TODO: get rid of these: +fun IrType.isSubtypeOf(other: KotlinType): Boolean = this.toKotlinType().isSubtypeOf(other) +fun IrType.isSubtypeOf(other: IrType): Boolean = this.isSubtypeOf(other.toKotlinType()) + +val IrType.isFunctionOrKFunctionType: Boolean + get() = when (this) { + is IrSimpleType -> { + val kind = classifier.descriptor.getFunctionalClassKind() + kind == FunctionClassDescriptor.Kind.Function || kind == FunctionClassDescriptor.Kind.KFunction + } + else -> false + } + +internal tailrec fun IrType.getErasedTypeClass(): IrClassSymbol { + val classifier = this.classifierOrFail + return when (classifier) { + is IrClassSymbol -> classifier + is IrTypeParameterSymbol -> classifier.owner.superTypes.first().getErasedTypeClass() + else -> error(classifier) + } +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt index 1eaf45b4b7f..b19673feed0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt @@ -23,28 +23,15 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor -import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl -import org.jetbrains.kotlin.ir.expressions.IrConst -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression -import org.jetbrains.kotlin.ir.expressions.getTypeArgumentOrDefault -import org.jetbrains.kotlin.ir.util.SymbolTable -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid -import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.explicitParameters import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.constants.* -import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor -import org.jetbrains.kotlin.types.ErrorUtils -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils val IrConstructor.constructedClass get() = this.parent as IrClass @@ -88,26 +75,6 @@ val IrFunction.allParameters: List explicitParameters } -/** - * @return naturally-ordered list of the parameters that can have values specified at call site. - */ -val IrFunction.explicitParameters: List - get() { - val result = ArrayList(valueParameters.size + 2) - - this.dispatchReceiverParameter?.let { - result.add(it) - } - - this.extensionReceiverParameter?.let { - result.add(it) - } - - result.addAll(valueParameters) - - return result - } - val IrValueParameter.isVararg get() = this.varargElementType != null val IrFunction.isSuspend get() = this is IrSimpleFunction && this.isSuspend @@ -116,6 +83,7 @@ fun IrClass.isUnit() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.unit.toSafe() fun IrClass.isKotlinArray() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.array.toSafe() +val IrClass.superClasses get() = this.superTypes.map { it.classifierOrFail as IrClassSymbol } fun IrClass.getSuperClassNotAny() = this.superClasses.map { it.owner }.atMostOne { !it.isInterface && !it.isAny() } fun IrClass.isAny() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.any.toSafe() @@ -132,7 +100,8 @@ val IrProperty.konanBackingField: IrField? this.startOffset, this.endOffset, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, - backingFieldDescriptor + backingFieldDescriptor, + this.getter!!.returnType // TODO: this copies the behaviour found in backing field descriptor creation, but both are incorrect for property delegation. ).also { it.parent = this.parent } @@ -143,9 +112,6 @@ val IrProperty.konanBackingField: IrField? return null } -val IrClass.defaultType: KotlinType - get() = this.thisReceiver!!.type - val IrField.containingClass get() = this.parent as? IrClass val IrFunction.isReal get() = this.origin != IrDeclarationOrigin.FAKE_OVERRIDE @@ -177,109 +143,17 @@ fun IrSimpleFunction.overrides(other: IrSimpleFunction): Boolean { fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing() -val IrClass.constructors get() = this.declarations.filterIsInstance() - internal val IrValueParameter.isValueParameter get() = this.index >= 0 -fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTable) { - val moduleDescriptor = this.descriptor +private val IrCall.annotationClass + get() = (this.symbol.owner as IrConstructor).constructedClass - fun KotlinType.referenceAllClassifiers() { - TypeUtils.getClassDescriptor(this)?.let { - if (!ErrorUtils.isError(it) && it.module != moduleDescriptor) { - if (it.kind == ClassKind.ENUM_ENTRY) { - symbolTable.referenceEnumEntry(it) - } else { - symbolTable.referenceClass(it) - } - } - } +fun List.hasAnnotation(fqName: FqName): Boolean = + this.any { it.annotationClass.fqNameSafe == fqName } - this.constructor.supertypes.forEach { - it.referenceAllClassifiers() - } - } +fun IrAnnotationContainer.hasAnnotation(fqName: FqName) = + this.annotations.hasAnnotation(fqName) - val visitor = object : IrElementVisitorVoid { - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitValueParameter(declaration: IrValueParameter) { - super.visitValueParameter(declaration) - declaration.type.referenceAllClassifiers() - } - - override fun visitVariable(declaration: IrVariable) { - super.visitVariable(declaration) - declaration.type.referenceAllClassifiers() - } - - override fun visitExpression(expression: IrExpression) { - super.visitExpression(expression) - expression.type.referenceAllClassifiers() - } - - override fun visitDeclaration(declaration: IrDeclaration) { - super.visitDeclaration(declaration) - declaration.descriptor.annotations.getAllAnnotations().forEach { - handleClassReferences(it.annotation) - } - } - - private fun handleClassReferences(annotation: AnnotationDescriptor) { - annotation.allValueArguments.values.forEach { - it.accept(object : AnnotationArgumentVisitor { - - override fun visitKClassValue(p0: KClassValue?, p1: Nothing?) { - p0?.value?.referenceAllClassifiers() - } - - override fun visitArrayValue(p0: ArrayValue?, p1: Nothing?) { - p0?.value?.forEach { it.accept(this, null) } - } - - override fun visitAnnotationValue(p0: AnnotationValue?, p1: Nothing?) { - p0?.let { handleClassReferences(p0.value) } - } - - override fun visitBooleanValue(p0: BooleanValue?, p1: Nothing?) {} - override fun visitShortValue(p0: ShortValue?, p1: Nothing?) {} - override fun visitByteValue(p0: ByteValue?, p1: Nothing?) {} - override fun visitNullValue(p0: NullValue?, p1: Nothing?) {} - override fun visitDoubleValue(p0: DoubleValue?, p1: Nothing?) {} - override fun visitLongValue(p0: LongValue, p1: Nothing?) {} - override fun visitCharValue(p0: CharValue?, p1: Nothing?) {} - override fun visitIntValue(p0: IntValue?, p1: Nothing?) {} - override fun visitUIntValue(p0: UIntValue?, p1: Nothing?) {} - override fun visitUShortValue(p0: UShortValue?, p1: Nothing?) {} - override fun visitUByteValue(p0: UByteValue?, p1: Nothing?) {} - override fun visitULongValue(p0: ULongValue?, p1: Nothing?) {} - override fun visitErrorValue(p0: ErrorValue?, p1: Nothing?) {} - override fun visitFloatValue(p0: FloatValue?, p1: Nothing?) {} - override fun visitEnumValue(p0: EnumValue?, p1: Nothing?) {} - override fun visitStringValue(p0: StringValue?, p1: Nothing?) {} - }, null) - } - } - - override fun visitFunction(declaration: IrFunction) { - super.visitFunction(declaration) - declaration.returnType.referenceAllClassifiers() - } - - override fun visitFunctionAccess(expression: IrFunctionAccessExpression) { - super.visitFunctionAccess(expression) - expression.descriptor.original.typeParameters.forEach { - expression.getTypeArgumentOrDefault(it).referenceAllClassifiers() - } - } - } - - this.acceptVoid(visitor) - this.dependencyModules.forEach { module -> - module.externalPackageFragments.forEach { - it.acceptVoid(visitor) - } - } -} \ No newline at end of file +fun List.findAnnotation(fqName: FqName): IrCall? = this.firstOrNull { + it.annotationClass.fqNameSafe == fqName +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt index bf3393b4d4a..12f4e616f6c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt @@ -17,25 +17,19 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.LLVMTypeRef -import llvm.LLVMVoidType -import org.jetbrains.kotlin.backend.common.descriptors.allParameters import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.isValueType import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.constants.StringValue -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty @@ -128,14 +122,14 @@ private val publishedApiAnnotation = FqName("kotlin.PublishedApi") private val inlineExposedAnnotation = FqName("kotlin.internal.InlineExposed") -private fun acyclicTypeMangler(visited: MutableSet, type: KotlinType): String { - val descriptor = TypeUtils.getTypeParameterDescriptorOrNull(type) +private fun acyclicTypeMangler(visited: MutableSet, type: IrType): String { + val descriptor = (type.classifierOrNull as? IrTypeParameterSymbol)?.owner if (descriptor != null) { val upperBounds = if (visited.contains(descriptor)) "" else { visited.add(descriptor) - descriptor.upperBounds.map { + descriptor.superTypes.map { val bound = acyclicTypeMangler(visited, it) if (bound == "kotlin.Any?") "" else "_$bound" }.joinToString("") @@ -143,24 +137,27 @@ private fun acyclicTypeMangler(visited: MutableSet, typ return "#GENERIC" + upperBounds } - var hashString = TypeUtils.getClassDescriptor(type)!!.fqNameSafe.asString() + var hashString = type.getClass()!!.fqNameSafe.asString() + if (type !is IrSimpleType) error(type) if (!type.arguments.isEmpty()) { hashString += "<${type.arguments.map { - if (it.isStarProjection()) { - "#STAR" - } else { - val variance = it.projectionKind.label - val projection = if (variance == "") "" else "${variance}_" - projection + acyclicTypeMangler(visited, it.type) + when (it) { + is IrStarProjection -> "#STAR" + is IrTypeProjection -> { + val variance = it.variance.label + val projection = if (variance == "") "" else "${variance}_" + projection + acyclicTypeMangler(visited, it.type) + } + else -> error(it) } }.joinToString(",")}>" } - if (type.isMarkedNullable) hashString += "?" + if (type.hasQuestionMark) hashString += "?" return hashString } -private fun typeToHashString(type: KotlinType) +private fun typeToHashString(type: IrType) = acyclicTypeMangler(mutableSetOf(), type) private val FunctionDescriptor.signature: String @@ -175,7 +172,7 @@ private val FunctionDescriptor.signature: String when { this.typeParameters.isNotEmpty() -> "Generic" returnType.isValueType() -> "ValueType" - !KotlinBuiltIns.isUnitOrNullableUnit(returnType) -> typeToHashString(returnType) + !returnType.isUnitOrNullableUnit() -> typeToHashString(returnType) else -> "" } return "$extensionReceiverPart($argsPart)$signatureSuffix" @@ -188,7 +185,7 @@ internal val FunctionDescriptor.functionName: String this.getObjCMethodInfo()?.let { return buildString { if (extensionReceiverParameter != null) { - append(TypeUtils.getClassDescriptor(extensionReceiverParameter!!.type)!!.name) + append(extensionReceiverParameter!!.type.getClass()!!.name) append(".") } @@ -235,7 +232,7 @@ internal val IrField.symbolName: String } -private fun getStringValue(annotation: AnnotationDescriptor): String? { +internal fun getStringValue(annotation: AnnotationDescriptor): String? { return annotation.allValueArguments.values.ifNotEmpty { val stringValue = single() as? StringValue stringValue?.value 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 c38f5e28628..3ba5605faed 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 @@ -25,6 +25,8 @@ import org.jetbrains.kotlin.backend.konan.descriptors.stdlibModule import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.llvm.objc.ObjCDataGenerator +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.konan.target.KonanTarget internal class CodeGenerator(override val context: Context) : ContextUtils { @@ -709,7 +711,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, */ fun getEnumEntry(descriptor: IrEnumEntry, exceptionHandler: ExceptionHandler): LLVMValueRef { val enumClassDescriptor = descriptor.containingDeclaration as ClassDescriptor - val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor.descriptor) + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor) val ordinal = loweredEnum.entriesMap[descriptor.name]!! val values = call( diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt index be277f8737a..c6a2145e158 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt @@ -20,9 +20,8 @@ import llvm.* import org.jetbrains.kotlin.backend.konan.ValueType import org.jetbrains.kotlin.backend.konan.isRepresentedAs import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.isNothing -import org.jetbrains.kotlin.types.typeUtil.isUnit +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isUnit private val valueTypes = ValueType.values().associate { it to when (it) { @@ -41,7 +40,7 @@ private val valueTypes = ValueType.values().associate { internal val ValueType.llvmType get() = valueTypes[this]!! -internal fun RuntimeAware.getLLVMType(type: KotlinType): LLVMTypeRef { +internal fun RuntimeAware.getLLVMType(type: IrType): LLVMTypeRef { for ((valueType, llvmType) in valueTypes) { if (type.isRepresentedAs(valueType)) { return llvmType @@ -54,13 +53,11 @@ internal fun RuntimeAware.getLLVMType(type: KotlinType): LLVMTypeRef { internal fun RuntimeAware.getLLVMType(type: DataFlowIR.Type) = type.correspondingValueType?.let { valueTypes[it]!! } ?: this.kObjHeaderPtr -internal fun RuntimeAware.getLLVMReturnType(type: KotlinType): LLVMTypeRef { +internal fun RuntimeAware.getLLVMReturnType(type: IrType): LLVMTypeRef { return when { type.isUnit() -> LLVMVoidType()!! // TODO: stdlib have methods taking Nothing, such as kotlin.collections.EmptySet.contains(). // KotlinBuiltIns.isNothing(type) -> LLVMVoidType() else -> getLLVMType(type) } -} - -fun RuntimeAware.isObjectType(type: KotlinType) : Boolean = isObjectType(getLLVMType(type)) \ No newline at end of file +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt index fcb73b27f10..2d1deab280c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt @@ -184,8 +184,8 @@ private fun debugInfoBaseType(context:Context, targetData:LLVMTargetDataRef, typ internal val FunctionDescriptor.types:List get() { - val parameters = valueParameters.map{it.type} - return listOf(returnType, *parameters.toTypedArray()) + val parameters = descriptor.valueParameters.map{it.type} + return listOf(descriptor.returnType!!, *parameters.toTypedArray()) } internal fun KotlinType.size(context:Context) = context.debugInfo.llvmTypeSizes.getOrDefault(this, context.debugInfo.otherTypeSize) 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 94b25bb05c5..d9a2fbc60e0 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 @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport import org.jetbrains.kotlin.backend.konan.optimizations.* -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.IrElement @@ -36,6 +35,8 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.getArguments import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -43,11 +44,6 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.typeUtil.isNothing -import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType -import org.jetbrains.kotlin.types.typeUtil.isUnit val IrClassSymbol.objectIsShared get() = owner.origin == DECLARATION_ORIGIN_ENUM @@ -862,7 +858,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map Unit = {}): ContinuationBlock { val entry = functionGenerationContext.basicBlock("continuation_block", locationInfo) @@ -893,7 +889,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map = when (symbol) { - is IrVariableSymbol -> symbol.owner - is IrValueParameterSymbol -> symbol.owner - else -> error(symbol) - } - - return currentCodeContext.genGetValue(ir) + return currentCodeContext.genGetValue(value.symbol.owner) } //-------------------------------------------------------------------------// @@ -1221,11 +1210,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map): LLVMValueRef { val descriptor = callee.descriptor.original + val function = callee.symbol.owner val name = descriptor.fqNameUnsafe.asString() when (name) { @@ -2137,13 +2128,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map args.single() in interop.readPrimitive -> { - val pointerType = pointerType(codegen.getLLVMType(descriptor.returnType!!)) + val pointerType = pointerType(codegen.getLLVMType(function.returnType)) val rawPointer = args.last() val pointer = functionGenerationContext.bitcast(pointerType, rawPointer) functionGenerationContext.load(pointer) } in interop.writePrimitive -> { - val pointerType = pointerType(codegen.getLLVMType(descriptor.valueParameters.last().type)) + val pointerType = pointerType(codegen.getLLVMType(function.valueParameters.last().type)) val rawPointer = args[1] val pointer = functionGenerationContext.bitcast(pointerType, rawPointer) functionGenerationContext.store(args[2], pointer) @@ -2154,7 +2145,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map Int32(LLVMPointerSize(codegen.llvmTargetData)).llvm context.builtIns.nativePtrToLong -> { val intPtrValue = functionGenerationContext.ptrToInt(args.single(), codegen.intPtrType) - val resultType = functionGenerationContext.getLLVMType(descriptor.returnType!!) + val resultType = functionGenerationContext.getLLVMType(function.returnType) if (resultType == intPtrValue.type) { intPtrValue @@ -2169,7 +2160,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map { val typeArgument = callee.getTypeArgument(descriptor.typeParameters.single()) - val irClass = context.ir.getClass(typeArgument!!)!! + val irClass = typeArgument!!.getClass()!! genGetObjCClass(irClass) } @@ -2184,8 +2175,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map genWriteBits(args) context.ir.symbols.getClassTypeInfo.descriptor -> { - val typeArgument = callee.getTypeArgumentOrDefault(descriptor.typeParameters.single()) - val typeArgumentClass = context.ir.getClass(typeArgument) + val typeArgument = callee.getTypeArgument(0)!! + val typeArgumentClass = typeArgument.getClass() if (typeArgumentClass == null) { // E.g. for `T::class` in a body of an inline function itself. functionGenerationContext.unreachable() @@ -2202,7 +2193,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map { val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0] val enumClass = callee.getTypeArgument(typeParameterT)!! - val enumIrClass = context.ir.getClass(enumClass)!! + val enumIrClass = enumClass.getClass()!! functionGenerationContext.allocInstance(enumIrClass, resultLifetime(callee)) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/KotlinObjCClassInfoGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/KotlinObjCClassInfoGenerator.kt index ab08220b0fa..8b147202d99 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/KotlinObjCClassInfoGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/KotlinObjCClassInfoGenerator.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.getStringValueOrNull import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.simpleFunctions import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe 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 9f0658ead9d..4e197fdf4f6 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 @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.name.FqName @@ -140,7 +141,7 @@ private fun Context.getDeclaredFields(classDescriptor: ClassDescriptor): List): LLVMTypeRef { val fieldTypes = fields.map { @Suppress("DEPRECATION") - getLLVMType(if (it.isDelegate) context.builtIns.nullableAnyType else it.type) + getLLVMType(if (it.isDelegate) context.irBuiltIns.anyNType else it.type) } val classType = LLVMStructCreateNamed(LLVMGetModuleContext(context.llvmModule), name)!! diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt index 84cd1f0a033..19d29ac07ee 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt @@ -101,9 +101,9 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { private fun exportTypeInfoIfRequired(classDesc: ClassDescriptor, typeInfoGlobal: LLVMValueRef?) { val annot = classDesc.descriptor.annotations.findAnnotation(FqName("konan.ExportTypeInfo")) if (annot != null) { - val nameValue = annot.allValueArguments.values.single() as StringValue + val name = getStringValue(annot)!! // TODO: use LLVMAddAlias? - val global = addGlobal(nameValue.value, pointerType(runtime.typeInfoType), isExported = true) + val global = addGlobal(name, pointerType(runtime.typeInfoType), isExported = true) LLVMSetInitializer(global, typeInfoGlobal) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt index 3281f7866bd..acc3da5a9bb 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt @@ -18,9 +18,6 @@ package org.jetbrains.kotlin.backend.konan.llvm import kotlinx.cinterop.* import llvm.* -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.isNothing -import org.jetbrains.kotlin.types.typeUtil.isUnit interface RuntimeAware { val runtime: Runtime diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticData.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticData.kt index 3cfa999c3a7..e46abe22f59 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticData.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticData.kt @@ -19,7 +19,6 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.* import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.ir.expressions.IrConst -import org.jetbrains.kotlin.types.KotlinType /** * Provides utilities to create static data. diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt index 933cc6b08e9..8357808cd32 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt @@ -20,7 +20,6 @@ import llvm.LLVMLinkage import llvm.LLVMSetLinkage import llvm.LLVMTypeRef import llvm.LLVMValueRef -import org.jetbrains.kotlin.backend.konan.irasdescriptors.defaultType import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe import org.jetbrains.kotlin.backend.konan.irasdescriptors.llvmSymbolOrigin import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -28,8 +27,6 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.types.replace private fun StaticData.objHeader(typeInfo: ConstPointer): Struct { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VariableManager.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VariableManager.kt index d1b2875adca..ad14d8e28a2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VariableManager.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VariableManager.kt @@ -176,9 +176,3 @@ internal fun debugInfoParameterLocation(builder: DIBuilderRef?, return VariableDebugLocation(localVariable = variableDeclaration!!, location = location, file = file, line = line) } - -private val ValueDescriptor.type get() = when (this) { - is IrVariable -> this.type - is IrValueParameter -> this.type - else -> error(this) -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt index e5bfbbecd68..33d091a18da 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt @@ -19,18 +19,17 @@ package org.jetbrains.kotlin.backend.konan.llvm.objcexport import llvm.* import org.jetbrains.kotlin.backend.konan.descriptors.CurrentKonanModule import org.jetbrains.kotlin.backend.konan.llvm.* -import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.util.OperatorNameConventions -internal fun ObjCExportCodeGenerator.generateKotlinFunctionImpl(invokeMethod: FunctionDescriptor): ConstPointer { +internal fun ObjCExportCodeGenerator.generateKotlinFunctionImpl(invokeMethod: IrSimpleFunction): ConstPointer { // TODO: consider also overriding methods of `Any`. val numberOfParameters = invokeMethod.valueParameters.size val function = generateFunction( codegen, - codegen.getLlvmFunctionType(context.ir.get(invokeMethod)), + codegen.getLlvmFunctionType(invokeMethod), "invokeFunction$numberOfParameters" ) { val args = (0 until numberOfParameters).map { index -> kotlinReferenceToObjC(param(index + 1)) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index e5685f251b4..41612f6bbbc 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -380,7 +380,7 @@ private fun ObjCExportCodeGenerator.generateKotlinFunctionAdapterToBlock(numberO val invokeMethod = irInterface.declarations.filterIsInstance() .single { it.name == OperatorNameConventions.INVOKE } - val invokeImpl = generateKotlinFunctionImpl(invokeMethod.descriptor) + val invokeImpl = generateKotlinFunctionImpl(invokeMethod) return rttiGenerator.generateSyntheticInterfaceImpl( irInterface, 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 1aea9151e44..707075fc1b1 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 @@ -18,22 +18,25 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.AbstractValueUsageTransformer import org.jetbrains.kotlin.backend.common.FileLoweringPass -import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters -import org.jetbrains.kotlin.backend.common.descriptors.isSuspend import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.descriptors.target -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.backend.konan.irasdescriptors.containsNull +import org.jetbrains.kotlin.backend.konan.irasdescriptors.isOverridable +import org.jetbrains.kotlin.backend.konan.irasdescriptors.isSuspend +import org.jetbrains.kotlin.backend.konan.irasdescriptors.makeNullableAsSpecified import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.typeUtil.makeNullable /** * Boxes and unboxes values of value types when necessary. @@ -48,9 +51,11 @@ internal class Autoboxing(val context: Context) : FileLoweringPass { } -private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTransformer(context.builtIns) { - - val symbols = context.ir.symbols +private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTransformer( + context.builtIns, + context.ir.symbols, + context.irBuiltIns +) { // TODO: should we handle the cases when expression type // is not equal to e.g. called function return type? @@ -59,23 +64,23 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr /** * @return type to use for runtime type checks instead of given one (e.g. `IntBox` instead of `Int`) */ - private fun getRuntimeReferenceType(type: KotlinType): KotlinType { + private fun getRuntimeReferenceType(type: IrType): IrType { ValueType.values().forEach { if (type.notNullableIsRepresentedAs(it)) { - return getBoxType(it).makeNullableAsSpecified(TypeUtils.isNullableType(type)) + return getBoxType(it).makeNullableAsSpecified(type.containsNull()) } } return type } - override fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: KotlinType): IrExpression { + override fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: IrType): IrExpression { return if (operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT || operator == IrTypeOperator.IMPLICIT_INTEGER_COERCION) { this } else { // Codegen expects the argument of type-checking operator to be an object reference: - this.useAs(builtIns.nullableAnyType) + this.useAs(context.irBuiltIns.anyNType) } } @@ -86,6 +91,7 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr } val newTypeOperand = getRuntimeReferenceType(expression.typeOperand) + val newTypeOperandClassifier = newTypeOperand.classifierOrFail return when (expression.operator) { IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, @@ -101,7 +107,7 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr } IrTypeOperatorCallImpl(expression.startOffset, expression.endOffset, - newExpressionType, expression.operator, newTypeOperand, + newExpressionType, expression.operator, newTypeOperand, newTypeOperandClassifier, expression.argument).useAs(expression.type) } @@ -110,40 +116,49 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr expression } else { IrTypeOperatorCallImpl(expression.startOffset, expression.endOffset, - expression.type, expression.operator, newTypeOperand, expression.argument) + expression.type, expression.operator, newTypeOperand, newTypeOperandClassifier, + expression.argument) } } } - private var currentFunctionDescriptor: FunctionDescriptor? = null + private var currentFunctionDescriptor: IrFunction? = null override fun visitFunction(declaration: IrFunction): IrStatement { - currentFunctionDescriptor = declaration.descriptor + currentFunctionDescriptor = declaration val result = super.visitFunction(declaration) currentFunctionDescriptor = null return result } - override fun IrExpression.useAsReturnValue(returnTarget: CallableDescriptor): IrExpression { - if (returnTarget.isSuspend && returnTarget == currentFunctionDescriptor) - return this.useAs(context.builtIns.nullableAnyType) - val returnType = returnTarget.returnType - ?: return this - return this.useAs(returnType) + override fun IrExpression.useAsReturnValue(returnTarget: IrReturnTargetSymbol): IrExpression = when (returnTarget) { + is IrSimpleFunctionSymbol -> if (returnTarget.owner.isSuspend && returnTarget == currentFunctionDescriptor?.symbol) { + this.useAs(irBuiltIns.anyNType) + } else { + this.useAs(returnTarget.owner.returnType) + } + is IrConstructorSymbol -> this.useAs(irBuiltIns.unitType) + is IrReturnableBlockSymbol -> this.useAs(returnTarget.owner.type) + else -> error(returnTarget) } - override fun IrExpression.useAs(type: KotlinType): IrExpression { + override fun IrExpression.useAs(type: IrType): IrExpression { val interop = context.interopBuiltIns if (this.isNullConst() && interop.nullableInteropValueTypes.any { type.isRepresentedAs(it) }) { - return IrCallImpl(startOffset, endOffset, symbols.getNativeNullPtr).uncheckedCast(type) + return IrCallImpl( + startOffset, + endOffset, + symbols.getNativeNullPtr.owner.returnType, + symbols.getNativeNullPtr + ).uncheckedCast(type) } val actualType = when (this) { is IrCall -> { - if (this.descriptor.isSuspend) context.builtIns.nullableAnyType - else this.callTarget.returnType ?: this.type + if (this.symbol.owner.isSuspend) irBuiltIns.anyNType + else this.callTarget.returnType } - is IrGetField -> this.descriptor.original.type + is IrGetField -> this.symbol.owner.type is IrTypeOperatorCall -> when (this.operator) { IrTypeOperator.IMPLICIT_INTEGER_COERCION -> @@ -159,65 +174,63 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr return this.adaptIfNecessary(actualType, type) } - private val IrMemberAccessExpression.target: CallableDescriptor get() = when (this) { + private val IrFunctionAccessExpression.target: IrFunction get() = when (this) { is IrCall -> this.callTarget - is IrDelegatingConstructorCall -> this.descriptor.original + is IrDelegatingConstructorCall -> this.symbol.owner else -> TODO(this.render()) } - private val IrCall.callTarget: FunctionDescriptor - get() = if (superQualifier == null && descriptor.isOverridable) { + private val IrCall.callTarget: IrFunction + get() = if (superQualifier == null && symbol.owner.isOverridable) { // A virtual call. - descriptor.original + symbol.owner } else { - descriptor.target + symbol.owner.target } - override fun IrExpression.useAsDispatchReceiver(expression: IrMemberAccessExpression): IrExpression { + override fun IrExpression.useAsDispatchReceiver(expression: IrFunctionAccessExpression): IrExpression { return this.useAsArgument(expression.target.dispatchReceiverParameter!!) } - override fun IrExpression.useAsExtensionReceiver(expression: IrMemberAccessExpression): IrExpression { + override fun IrExpression.useAsExtensionReceiver(expression: IrFunctionAccessExpression): IrExpression { return this.useAsArgument(expression.target.extensionReceiverParameter!!) } - override fun IrExpression.useAsValueArgument(expression: IrMemberAccessExpression, - parameter: ValueParameterDescriptor): IrExpression { + override fun IrExpression.useAsValueArgument(expression: IrFunctionAccessExpression, + parameter: IrValueParameter): IrExpression { return this.useAsArgument(expression.target.valueParameters[parameter.index]) } - override fun IrExpression.useForField(field: PropertyDescriptor): IrExpression { - return this.useForVariable(field.original) - } - - private fun IrExpression.adaptIfNecessary(actualType: KotlinType, expectedType: KotlinType): IrExpression { + private fun IrExpression.adaptIfNecessary(actualType: IrType, expectedType: IrType): IrExpression { val conversion = symbols.getTypeConversion(actualType, expectedType) return if (conversion == null) { this } else { - val parameter = conversion.descriptor.explicitParameters.single() + val parameter = conversion.owner.explicitParameters.single() val argument = this.uncheckedCast(parameter.type) - IrCallImpl(startOffset, endOffset, conversion).apply { - addArguments(listOf(parameter to argument)) + IrCallImpl(startOffset, endOffset, conversion.owner.returnType, conversion).apply { + addArguments(mapOf(parameter to argument)) }.uncheckedCast(this.type) // Try not to bring new type incompatibilities. } } + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + expression.transformChildrenVoid() + assert(expression.getArgumentsWithIr().isEmpty()) + return expression + } + /** * Casts this expression to `type` without changing its representation in generated code. */ @Suppress("UNUSED_PARAMETER") - private fun IrExpression.uncheckedCast(type: KotlinType): IrExpression { + private fun IrExpression.uncheckedCast(type: IrType): IrExpression { // TODO: apply some cast if types are incompatible; not required currently. return this } - private val ValueType.shortName - get() = this.classFqName.shortName() - - private fun getBoxType(valueType: ValueType) = - context.getInternalClass("${valueType.shortName}Box").defaultType + private fun getBoxType(valueType: ValueType) = symbols.boxClasses[valueType]!!.owner.defaultType } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt index f22a6d2fdfb..c202e0bbd31 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt @@ -23,26 +23,27 @@ import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.* -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.util.createParameterDeclarations +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isNullableAny +import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.util.simpleFunctions import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature -import org.jetbrains.kotlin.types.KotlinType internal class WorkersBridgesBuilding(val context: Context) : DeclarationContainerLoweringPass, IrElementTransformerVoid() { @@ -100,7 +101,16 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain IrDeclarationOrigin.DEFINED, runtimeJobDescriptor ).also { - it.createParameterDeclarations() + it.returnType = context.irBuiltIns.anyNType + + it.valueParameters += IrValueParameterImpl( + it.startOffset, + it.endOffset, + IrDeclarationOrigin.DEFINED, + it.descriptor.valueParameters.single(), + context.irBuiltIns.anyNType, + null + ) } } val overriddenJobDescriptor = OverriddenFunctionDescriptor(jobFunction, runtimeJobFunction) @@ -118,7 +128,7 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain type = job.type, symbol = bridge.symbol, descriptor = bridge.descriptor, - typeArguments = null) + typeArgumentsCount = 0) ) return expression } @@ -158,7 +168,7 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass { val irBuilder = context.createIrBuilder(declaration.symbol, declaration.startOffset, declaration.endOffset) declaration.body = irBuilder.irBlockBody(declaration) { - buildTypeSafeBarrier(declaration, descriptor, typeSafeBarrierDescription) + buildTypeSafeBarrier(declaration, declaration, typeSafeBarrierDescription) body.statements.forEach { +it } } return declaration @@ -187,7 +197,7 @@ internal val IrFunction.bridgeTarget: IrFunction? get() = (origin as? DECLARATION_ORIGIN_BRIDGE_METHOD)?.bridgeTarget private fun IrBuilderWithScope.returnIfBadType(value: IrExpression, - type: KotlinType, + type: IrType, returnValueOnFail: IrExpression) = irIfThen(irNotIs(value, type), irReturn(returnValueOnFail)) @@ -199,18 +209,18 @@ private fun IrBuilderWithScope.irConst(value: Any?) = when (value) { } private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction, - originalDescriptor: FunctionDescriptor, + originalFunction: IrFunction, typeSafeBarrierDescription: BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription) { val valueParameters = function.valueParameters - val originalValueParameters = originalDescriptor.valueParameters + val originalValueParameters = originalFunction.valueParameters for (i in valueParameters.indices) { if (!typeSafeBarrierDescription.checkParameter(i)) continue val type = originalValueParameters[i].type - if (type != context.builtIns.nullableAnyType) { - +returnIfBadType(irGet(valueParameters[i].symbol), type, + if (!type.isNullableAny()) { + +returnIfBadType(irGet(valueParameters[i]), type, if (typeSafeBarrierDescription == BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT) - irGet(valueParameters[2].symbol) + irGet(valueParameters[2]) else irConst(typeSafeBarrierDescription.defaultValue) ) } @@ -221,7 +231,7 @@ private fun Context.buildBridge(startOffset: Int, endOffset: Int, descriptor: OverriddenFunctionDescriptor, targetSymbol: IrFunctionSymbol, superQualifierSymbol: IrClassSymbol? = null): IrFunction { - val bridge = specialDeclarationsFactory.getBridgeDescriptor(descriptor) + val bridge = specialDeclarationsFactory.getBridge(descriptor) if (bridge.modality == Modality.ABSTRACT) { return bridge @@ -230,23 +240,28 @@ private fun Context.buildBridge(startOffset: Int, endOffset: Int, val irBuilder = createIrBuilder(bridge.symbol, startOffset, endOffset) bridge.body = irBuilder.irBlockBody(bridge) { val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor.descriptor) - typeSafeBarrierDescription?.let { buildTypeSafeBarrier(bridge, descriptor.descriptor.descriptor, it) } + typeSafeBarrierDescription?.let { buildTypeSafeBarrier(bridge, descriptor.descriptor, it) } - val delegatingCall = IrCallImpl(startOffset, endOffset, targetSymbol, targetSymbol.descriptor, + val delegatingCall = IrCallImpl( + startOffset, + endOffset, + (targetSymbol.owner as IrFunction).returnType, + targetSymbol, + targetSymbol.descriptor, superQualifierSymbol = superQualifierSymbol /* Call non-virtually */ ).apply { bridge.dispatchReceiverParameter?.let { - dispatchReceiver = irGet(it.symbol) + dispatchReceiver = irGet(it) } bridge.extensionReceiverParameter?.let { - extensionReceiver = irGet(it.symbol) + extensionReceiver = irGet(it) } bridge.valueParameters.forEachIndexed { index, parameter -> - this.putValueArgument(index, irGet(parameter.symbol)) + this.putValueArgument(index, irGet(parameter)) } } - if (KotlinBuiltIns.isUnitOrNullableUnit(bridge.returnType)) + if (bridge.returnType.isUnit()) +delegatingCall else +irReturn(delegatingCall) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt index 467400d2803..0eb6fb1776b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt @@ -22,6 +22,8 @@ import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer import org.jetbrains.kotlin.backend.common.lower.at import org.jetbrains.kotlin.backend.common.lower.irNot import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.irasdescriptors.containsNull +import org.jetbrains.kotlin.backend.konan.irasdescriptors.isSubtypeOf import org.jetbrains.kotlin.backend.konan.isValueType import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.builders.* @@ -33,13 +35,13 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.makeNullable +import org.jetbrains.kotlin.ir.util.irCall +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isNothing import org.jetbrains.kotlin.ir.util.isNullConst import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.isNullable -import org.jetbrains.kotlin.types.typeUtil.isNothing -import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf -import org.jetbrains.kotlin.types.typeUtil.makeNullable /** * This lowering pass lowers some calls to [IrBuiltinOperatorDescriptor]s. @@ -82,9 +84,11 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass, irBuiltins.eqeqeq -> lowerEqeqeq(expression) irBuiltins.throwNpe -> IrCallImpl(expression.startOffset, expression.endOffset, + context.ir.symbols.ThrowNullPointerException.owner.returnType, context.ir.symbols.ThrowNullPointerException) irBuiltins.noWhenBranchMatchedException -> IrCallImpl(expression.startOffset, expression.endOffset, + context.ir.symbols.ThrowNoWhenBranchMatchedException.owner.returnType, context.ir.symbols.ThrowNoWhenBranchMatchedException) else -> expression @@ -148,8 +152,8 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass, putValueArgument(0, rhs) } - val lhsIsNotNullable = !lhs.type.isNullable() - val rhsIsNotNullable = !rhs.type.isNullable() + val lhsIsNotNullable = !lhs.type.containsNull() + val rhsIsNotNullable = !rhs.type.containsNull() return if (expression.descriptor in ieee754EqualsDescriptors()) { if (lhsIsNotNullable && rhsIsNotNullable) @@ -159,15 +163,15 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass, val rhsTemp = irTemporary(rhs) if (lhsIsNotNullable xor rhsIsNotNullable) { // Exactly one nullable. +irLogicalAnd( - irIsNotNull(irGet((if (lhsIsNotNullable) rhsTemp else lhsTemp).symbol)), - callEquals(irGet(lhsTemp.symbol), irGet(rhsTemp.symbol)) + irIsNotNull(irGet(if (lhsIsNotNullable) rhsTemp else lhsTemp)), + callEquals(irGet(lhsTemp), irGet(rhsTemp)) ) } else { // Both are nullable. - +irIfThenElse(builtIns.booleanType, irIsNull(irGet(lhsTemp.symbol)), - irIsNull(irGet(rhsTemp.symbol)), + +irIfThenElse(context.irBuiltIns.booleanType, irIsNull(irGet(lhsTemp)), + irIsNull(irGet(rhsTemp)), irLogicalAnd( - irIsNotNull(irGet(rhsTemp.symbol)), - callEquals(irGet(lhsTemp.symbol), irGet(rhsTemp.symbol)) + irIsNotNull(irGet(rhsTemp)), + callEquals(irGet(lhsTemp), irGet(rhsTemp)) ) ) } @@ -179,12 +183,12 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass, irBlock { val lhsTemp = irTemporary(lhs) if (rhsIsNotNullable) - +irLogicalAnd(irIsNotNull(irGet(lhsTemp.symbol)), callEquals(irGet(lhsTemp.symbol), rhs)) + +irLogicalAnd(irIsNotNull(irGet(lhsTemp)), callEquals(irGet(lhsTemp), rhs)) else { val rhsTemp = irTemporary(rhs) - +irIfThenElse(builtIns.booleanType, irIsNull(irGet(lhsTemp.symbol)), - irIsNull(irGet(rhsTemp.symbol)), - callEquals(irGet(lhsTemp.symbol), irGet(rhsTemp.symbol)) + +irIfThenElse(irBuiltins.booleanType, irIsNull(irGet(lhsTemp)), + irIsNull(irGet(rhsTemp)), + callEquals(irGet(lhsTemp), irGet(rhsTemp)) ) } } @@ -193,7 +197,7 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass, } } - private fun selectIntrinsic(from: List, lhsType: KotlinType, rhsType: KotlinType, allowNullable: Boolean) = + private fun selectIntrinsic(from: List, lhsType: IrType, rhsType: IrType, allowNullable: Boolean) = from.atMostOne { val leftParamType = it.owner.valueParameters[0].type val rightParamType = it.owner.valueParameters[1].type diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt index 0697327adf5..79572c6f7d1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt @@ -18,16 +18,14 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext -import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters -import org.jetbrains.kotlin.backend.common.descriptors.getFunction -import org.jetbrains.kotlin.backend.common.descriptors.isFunctionOrKFunctionType -import org.jetbrains.kotlin.backend.common.descriptors.replace import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe +import org.jetbrains.kotlin.backend.konan.irasdescriptors.isFunctionOrKFunctionType +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations @@ -47,19 +45,20 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classifierOrNull +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils internal class CallableReferenceLowering(val context: Context): FileLoweringPass { @@ -161,15 +160,16 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass val parent: IrDeclarationParent, val functionReference: IrFunctionReference) { - private val functionDescriptor = functionReference.descriptor - private val functionParameters = functionDescriptor.explicitParameters - private val boundFunctionParameters = functionReference.getArguments().map { it.first } + private val functionDescriptor = functionReference.descriptor.original + private val irFunction = functionReference.symbol.owner + private val functionParameters = irFunction.explicitParameters + private val boundFunctionParameters = functionReference.getArgumentsWithIr().map { it.first } private val unboundFunctionParameters = functionParameters - boundFunctionParameters private lateinit var functionReferenceClassDescriptor: ClassDescriptorImpl private lateinit var functionReferenceClass: IrClassImpl private lateinit var functionReferenceThis: IrValueParameterSymbol - private lateinit var argumentToPropertiesMap: Map + private lateinit var argumentToPropertiesMap: Map private val kFunctionImplSymbol = context.ir.symbols.kFunctionImpl @@ -177,29 +177,26 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass val startOffset = functionReference.startOffset val endOffset = functionReference.endOffset - val returnType = functionDescriptor.returnType!! - val superTypes = mutableListOf( - kFunctionImplSymbol.owner.defaultType.replace(listOf(returnType)) - ) - val superClasses = mutableListOf(kFunctionImplSymbol.owner) + val returnType = irFunction.returnType + val superTypes = mutableListOf(kFunctionImplSymbol.typeWith(returnType)) val numberOfParameters = unboundFunctionParameters.size - val functionClassDescriptor = context.reflectionTypes.getKFunction(numberOfParameters) + + val functionIrClass = context.ir.symbols.kFunctions[numberOfParameters].owner val functionParameterTypes = unboundFunctionParameters.map { it.type } val functionClassTypeParameters = functionParameterTypes + returnType - superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeParameters) - superClasses += context.ir.symbols.kFunctions[numberOfParameters].owner + superTypes += functionIrClass.symbol.typeWith(functionClassTypeParameters) - var suspendFunctionClassDescriptor: ClassDescriptor? = null - var suspendFunctionClassTypeParameters: List? = null + var suspendFunctionIrClass: IrClass? = null + var suspendFunctionClassTypeParameters: List? = null val lastParameterType = unboundFunctionParameters.lastOrNull()?.type - if (lastParameterType != null && TypeUtils.getClassDescriptor(lastParameterType) == continuationClassDescriptor) { + if (lastParameterType != null && lastParameterType.classifierOrNull?.descriptor == continuationClassDescriptor) { + lastParameterType as IrSimpleType // If the last parameter is Continuation<> inherit from SuspendFunction. - suspendFunctionClassDescriptor = kotlinPackageScope.getContributedClassifier( - Name.identifier("SuspendFunction${numberOfParameters - 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor - suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) + lastParameterType.arguments.single().type - superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeParameters) - superClasses += context.ir.symbols.suspendFunctions[numberOfParameters - 1].owner + suspendFunctionIrClass = context.ir.symbols.suspendFunctions[numberOfParameters - 1].owner + suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) + + (lastParameterType.arguments.single().typeOrNull ?: context.irBuiltIns.anyNType) + superTypes += suspendFunctionIrClass.symbol.typeWith(suspendFunctionClassTypeParameters) } functionReferenceClassDescriptor = object : ClassDescriptorImpl( @@ -207,7 +204,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass /* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName, /* modality = */ Modality.FINAL, /* kind = */ ClassKind.CLASS, - /* superTypes = */ superTypes, + /* superTypes = */ superTypes.map { it.toKotlinType() }, /* source = */ SourceElement.NO_SOURCE, /* isExternal = */ false, /* storageManager = */ LockBasedStorageManager.NO_LOCKS @@ -225,13 +222,15 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass val constructorBuilder = createConstructorBuilder() - val invokeFunctionDescriptor = functionClassDescriptor.getFunction("invoke", functionClassTypeParameters) - val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionDescriptor) + val invokeFunctionSymbol = + functionIrClass.simpleFunctions().single { it.name.asString() == "invoke" }.symbol + val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionSymbol, functionReferenceClass) var suspendInvokeMethodBuilder: SymbolWithIrBuilder? = null - if (suspendFunctionClassDescriptor != null) { - val suspendInvokeFunctionDescriptor = suspendFunctionClassDescriptor.getFunction("invoke", suspendFunctionClassTypeParameters!!) - suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionDescriptor) + if (suspendFunctionIrClass != null) { + val suspendInvokeFunctionSymbol = + suspendFunctionIrClass.simpleFunctions().single { it.name.asString() == "invoke" }.symbol + suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionSymbol, functionReferenceClass) } val memberScope = stub("callable reference class") @@ -253,7 +252,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass functionReferenceClass.addChild(it.ir) } - functionReferenceClass.setSuperSymbolsAndAddFakeOverrides(superClasses) + functionReferenceClass.setSuperSymbolsAndAddFakeOverrides(superTypes) return BuiltFunctionReference(functionReferenceClass, constructorBuilder.ir) } @@ -275,15 +274,19 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass override fun doInitialize() { val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl val constructorParameters = boundFunctionParameters.mapIndexed { index, parameter -> - parameter.copyAsValueParameter(descriptor, index) + parameter.descriptor.copyAsValueParameter(descriptor, index) } descriptor.initialize(constructorParameters, Visibilities.PUBLIC) descriptor.returnType = functionReferenceClassDescriptor.defaultType } override fun buildIr(): IrConstructor { + + val symbols = this@CallableReferenceLowering.context.ir.symbols + val irBuiltIns = context.irBuiltIns + argumentToPropertiesMap = boundFunctionParameters.associate { - it to buildPropertyWithBackingField(it.name, it.type, false) + it.descriptor to buildField(it.name, it.type, false) } val startOffset = functionReference.startOffset @@ -294,30 +297,36 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, symbol = symbol).apply { + returnType = functionReferenceClass.defaultType + val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset) - createParameterDeclarations() + boundFunctionParameters.mapIndexedTo(this.valueParameters) { index, parameter -> + parameter.copy(descriptor.valueParameters[index]) + } body = irBuilder.irBlockBody { +IrDelegatingConstructorCallImpl(startOffset, endOffset, - kFunctionImplConstructorSymbol, kFunctionImplConstructorSymbol.descriptor).apply { - val name = IrConstImpl(startOffset, endOffset, context.builtIns.stringType, + context.irBuiltIns.unitType, + kFunctionImplConstructorSymbol, kFunctionImplConstructorSymbol.descriptor, 0).apply { + val stringType = irBuiltIns.stringType + val name = IrConstImpl(startOffset, endOffset, stringType, IrConstKind.String, functionDescriptor.name.asString()) putValueArgument(0, name) - val fqName = IrConstImpl(startOffset, endOffset, context.builtIns.stringType, IrConstKind.String, + val fqName = IrConstImpl(startOffset, endOffset, stringType, IrConstKind.String, (functionReference.symbol.owner).fullName) putValueArgument(1, fqName) - val bound = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType, + val bound = IrConstImpl.boolean(startOffset, endOffset, context.irBuiltIns.booleanType, boundFunctionParameters.isNotEmpty()) putValueArgument(2, bound) - val needReceiver = boundFunctionParameters.singleOrNull() is ReceiverParameterDescriptor - val receiver = if (needReceiver) irGet(valueParameters.single().symbol) else irNull() + val needReceiver = boundFunctionParameters.singleOrNull()?.descriptor is ReceiverParameterDescriptor + val receiver = if (needReceiver) irGet(valueParameters.single()) else irNull() putValueArgument(3, receiver) } - +IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol) + +IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, irBuiltIns.unitType) // Save all arguments to fields. boundFunctionParameters.forEachIndexed { index, parameter -> - +irSetField(irGet(functionReferenceThis), argumentToPropertiesMap[parameter]!!, irGet(valueParameters[index].symbol)) + +irSetField(irGet(functionReferenceThis.owner), argumentToPropertiesMap[parameter.descriptor]!!, irGet(valueParameters[index])) } } } @@ -327,9 +336,11 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass private val IrFunction.fullName: String get() = parent.fqNameSafe.child(Name.identifier(functionName)).asString() - private fun createInvokeMethodBuilder(superFunctionDescriptor: FunctionDescriptor) + private fun createInvokeMethodBuilder(superFunctionSymbol: IrSimpleFunctionSymbol, parent: IrClass) = object : SymbolWithIrBuilder() { + val superFunctionDescriptor: FunctionDescriptor = superFunctionSymbol.descriptor + override fun buildSymbol() = IrSimpleFunctionSymbolImpl( SimpleFunctionDescriptorImpl.create( /* containingDeclaration = */ functionReferenceClassDescriptor, @@ -368,10 +379,18 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, symbol = ourSymbol).apply { + returnType = superFunctionSymbol.owner.returnType // FIXME: substitute + val function = this val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) - createParameterDeclarations() + this.parent = parent + + this.createDispatchReceiverParameter() + + superFunctionSymbol.owner.valueParameters.mapTo(this.valueParameters) { + it.copy(descriptor.valueParameters[it.index]) // FIXME: substitute + } body = irBuilder.irBlockBody(startOffset, endOffset) { +irReturn( @@ -383,21 +402,21 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass if (!unboundArgsSet.contains(it)) // Bound parameter - read from field. irGetField( - irGet(function.dispatchReceiverParameter!!.symbol), - argumentToPropertiesMap[it]!! + irGet(function.dispatchReceiverParameter!!), + argumentToPropertiesMap[it.descriptor]!! ) else { if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size) // For suspend functions the last argument is continuation and it is implicit. - irCall(getContinuationSymbol, - listOf(ourSymbol.descriptor.returnType!!)) + irCall(getContinuationSymbol.owner, + listOf(returnType)) else - irGet(valueParameters[unboundIndex++].symbol) + irGet(valueParameters[unboundIndex++]) } when (it) { - functionDescriptor.dispatchReceiverParameter -> dispatchReceiver = argument - functionDescriptor.extensionReceiverParameter -> extensionReceiver = argument - else -> putValueArgument((it as ValueParameterDescriptor).index, argument) + irFunction.dispatchReceiverParameter -> dispatchReceiver = argument + irFunction.extensionReceiverParameter -> extensionReceiver = argument + else -> putValueArgument(it.index, argument) } } assert(unboundIndex == valueParameters.size, { "Not all arguments of are used" }) @@ -408,21 +427,17 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass } } - private fun buildPropertyWithBackingField(name: Name, type: KotlinType, isMutable: Boolean): IrFieldSymbol { - val propertyBuilder = context.createPropertyWithBackingFieldBuilder( - startOffset = functionReference.startOffset, - endOffset = functionReference.endOffset, - origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, - owner = functionReferenceClassDescriptor, - name = name, - type = type, - isMutable = isMutable).apply { - initialize() - } - - functionReferenceClass.addChild(propertyBuilder.ir) - return propertyBuilder.ir.backingField!!.symbol + private fun buildField(name: Name, type: IrType, isMutable: Boolean): IrField = createField( + functionReference.startOffset, + functionReference.endOffset, + type, + name, + isMutable, + DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + functionReferenceClassDescriptor + ).also { + functionReferenceClass.addChild(it) } - } } + diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CompileTimeEvaluateLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CompileTimeEvaluateLowering.kt index 5c4cbf57f5d..e6436445bb7 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CompileTimeEvaluateLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CompileTimeEvaluateLowering.kt @@ -4,10 +4,11 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer import org.jetbrains.kotlin.backend.common.lower.at import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.builders.irCall import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.types.isString +import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe @@ -29,14 +30,14 @@ internal class CompileTimeEvaluateLowering(val context: Context): FileLoweringPa // TODO: refer functions more reliably. if (elementsArr.elements.any { it is IrSpreadElement } - || !elementsArr.elements.all { it is IrConst<*> && KotlinBuiltIns.isString(it.type) }) + || !elementsArr.elements.all { it is IrConst<*> && it.type.isString() }) return expression builder.at(expression) - val typeArguments = descriptor.typeParameters.map { expression.getTypeArgument(it)!! } - return builder.irCall(context.ir.symbols.listOfInternal, typeArguments).apply { + val typeArgument = expression.getTypeArgument(0)!! + return builder.irCall(context.ir.symbols.listOfInternal.owner, listOf(typeArgument)).apply { putValueArgument(0, elementsArr) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DataClassOperatorsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DataClassOperatorsLowering.kt index 9d52b7ad781..a870831075b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DataClassOperatorsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DataClassOperatorsLowering.kt @@ -20,15 +20,15 @@ import org.jetbrains.kotlin.backend.common.FunctionLoweringPass import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlock import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.makeNotNullable internal class DataClassOperatorsLowering(val context: Context): FunctionLoweringPass { @@ -45,40 +45,37 @@ internal class DataClassOperatorsLowering(val context: Context): FunctionLowerin return expression val argument = expression.getValueArgument(0)!! - val argumentType = argument.type.makeNotNullable() - val genericType = - if (argumentType.arguments.isEmpty()) - argumentType - else - (argumentType.constructor.declarationDescriptor as ClassDescriptor).defaultType - val isToString = descriptor == irBuiltins.dataClassArrayMemberToString - val newSymbol = if (isToString) - context.ir.symbols.arrayContentToString[genericType]!! + val argumentClassifier = argument.type.classifierOrFail + + val isToString = expression.symbol == irBuiltins.dataClassArrayMemberToStringSymbol + val newCalleeSymbol = if (isToString) + context.ir.symbols.arrayContentToString[argumentClassifier]!! else - context.ir.symbols.arrayContentHashCode[genericType]!! + context.ir.symbols.arrayContentHashCode[argumentClassifier]!! + + val newCallee = newCalleeSymbol.owner val startOffset = expression.startOffset val endOffset = expression.endOffset val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset) return irBuilder.run { - val typeArguments = - if (argumentType.arguments.isEmpty()) - emptyList() - else argumentType.arguments.map { it.type } - if (!argument.type.isMarkedNullable) { - irCall(newSymbol, typeArguments).apply { + // TODO: use more precise type arguments. + val typeArguments = (0 until newCallee.typeParameters.size).map { irBuiltins.anyNType } + + if (!argument.type.isSimpleTypeWithQuestionMark) { + irCall(newCallee, typeArguments).apply { extensionReceiver = argument } } else { val tmp = scope.createTemporaryVariable(argument) - val call = irCall(newSymbol, typeArguments).apply { - extensionReceiver = irGet(tmp.symbol) + val call = irCall(newCallee, typeArguments).apply { + extensionReceiver = irGet(tmp) } irBlock(argument) { +tmp +irIfThenElse(call.type, - irEqeqeq(irGet(tmp.symbol), irNull()), + irEqeqeq(irGet(tmp), irNull()), if (isToString) irString("null") else 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 19b07012a2b..d06c1be1107 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 @@ -24,14 +24,17 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.impl.createClassSymbolOrNull import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.makeNullable +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -46,7 +49,6 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.types.typeUtil.makeNullable internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor, val parentDescriptor: DeclarationDescriptor, @@ -484,7 +486,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr return IrCallImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, - type = newDescriptor.returnType!!, + type = context.ir.translateErased(newDescriptor.returnType!!), descriptor = newDescriptor, typeArgumentsCount = expression.typeArgumentsCount, origin = expression.origin, @@ -497,19 +499,100 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr //---------------------------------------------------------------------// - override fun visitFunction(declaration: IrFunction): IrFunction = - IrFunctionImpl( - startOffset = declaration.startOffset, - endOffset = declaration.endOffset, - origin = mapDeclarationOrigin(declaration.origin), - descriptor = mapFunctionDeclaration(declaration.descriptor), - body = declaration.body?.transform(this, null) + override fun visitSimpleFunction(declaration: IrSimpleFunction): IrFunction { + val descriptor = mapFunctionDeclaration(declaration.descriptor) + return IrFunctionImpl( + startOffset = declaration.startOffset, + endOffset = declaration.endOffset, + origin = mapDeclarationOrigin(declaration.origin), + descriptor = descriptor ).also { + it.returnType = context.ir.translateErased(descriptor.returnType!!) + it.body = declaration.body?.transform(this, null) + it.setOverrides(context.ir.symbols.symbolTable) - }.transformParameters(declaration) + }.transformParameters1(declaration) + } + + override fun visitConstructor(declaration: IrConstructor): IrConstructor { + val descriptor = mapConstructorDeclaration(declaration.descriptor) + return IrConstructorImpl( + startOffset = declaration.startOffset, + endOffset = declaration.endOffset, + origin = mapDeclarationOrigin(declaration.origin), + descriptor = descriptor + ).also { + it.returnType = context.ir.translateErased(descriptor.returnType) + it.body = declaration.body?.transform(this, null) + }.transformParameters1(declaration) + } + + private fun FunctionDescriptor.getTypeParametersToTransform() = + when { + this is PropertyAccessorDescriptor -> correspondingProperty.typeParameters + else -> typeParameters + } + + protected fun T.transformParameters1(original: T): T = + apply { + transformTypeParameters(original, descriptor.getTypeParametersToTransform()) + transformValueParameters1(original) + } + + protected fun T.transformValueParameters1(original: T) = + apply { + dispatchReceiverParameter = + original.dispatchReceiverParameter?.replaceDescriptor1( + descriptor.dispatchReceiverParameter ?: throw AssertionError("No dispatch receiver in $descriptor") + ) + + extensionReceiverParameter = + original.extensionReceiverParameter?.replaceDescriptor1( + descriptor.extensionReceiverParameter ?: throw AssertionError("No extension receiver in $descriptor") + ) + + original.valueParameters.mapIndexedTo(valueParameters) { i, originalValueParameter -> + originalValueParameter.replaceDescriptor1(descriptor.valueParameters[i]) + } + } + + protected fun IrValueParameter.replaceDescriptor1(newDescriptor: ParameterDescriptor) = + IrValueParameterImpl( + startOffset, endOffset, + mapDeclarationOrigin(origin), + newDescriptor, + context.ir.translateErased(newDescriptor.type), + (newDescriptor as? ValueParameterDescriptor)?.varargElementType?.let { context.ir.translateErased(it) }, + defaultValue?.transform(this@InlineCopyIr, null) + ).apply { + transformAnnotations(this) + } //---------------------------------------------------------------------// + override fun visitGetValue(expression: IrGetValue): IrGetValue { + val descriptor = mapValueReference(expression.descriptor) + return IrGetValueImpl( + expression.startOffset, expression.endOffset, + context.ir.translateErased(descriptor.type), + descriptor, + mapStatementOrigin(expression.origin) + ) + } + + override fun visitVariable(declaration: IrVariable): IrVariable { + val descriptor = mapVariableDeclaration(declaration.descriptor) + return IrVariableImpl( + declaration.startOffset, declaration.endOffset, + mapDeclarationOrigin(declaration.origin), + descriptor, + context.ir.translateErased(descriptor.type), + declaration.initializer?.transform(this, null) + ).apply { + transformAnnotations(declaration) + } + } + private fun T.transformDefaults(original: T): T { for (originalValueParameter in original.descriptor.valueParameters) { val valueParameter = descriptor.valueParameters[originalValueParameter.index] @@ -522,7 +605,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr //---------------------------------------------------------------------// - fun getTypeOperatorReturnType(operator: IrTypeOperator, type: KotlinType) : KotlinType { + fun getTypeOperatorReturnType(operator: IrTypeOperator, type: IrType) : IrType { return when (operator) { IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST, @@ -531,22 +614,24 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type IrTypeOperator.SAFE_CAST -> type.makeNullable() IrTypeOperator.INSTANCEOF, - IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType + IrTypeOperator.NOT_INSTANCEOF -> context.irBuiltIns.booleanType } } //---------------------------------------------------------------------// override fun visitTypeOperator(expression: IrTypeOperatorCall): IrTypeOperatorCall { - val typeOperand = substituteType(expression.typeOperand)!! - val returnType = getTypeOperatorReturnType(expression.operator, typeOperand) + val erasedTypeOperand = substituteAndEraseType(expression.typeOperand)!! + val typeOperand = substituteAndBreakType(expression.typeOperand) + val returnType = getTypeOperatorReturnType(expression.operator, erasedTypeOperand) return IrTypeOperatorCallImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, type = returnType, operator = expression.operator, typeOperand = typeOperand, - argument = expression.argument.transform(this, null) + argument = expression.argument.transform(this, null), + typeOperandClassifier = (typeOperand as IrSimpleType).classifier ) } @@ -556,7 +641,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr IrReturnImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, - type = substituteType(expression.type)!!, + type = substituteAndEraseType(expression.type)!!, returnTargetDescriptor = mapReturnTarget(expression.returnTarget), value = expression.value.transform(this, null) ) @@ -577,7 +662,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr } else { IrBlockImpl( expression.startOffset, expression.endOffset, - substituteType(expression.type)!!, + substituteAndEraseType(expression.type)!!, mapStatementOrigin(expression.origin), expression.statements.map { it.transform(this, null) } ) @@ -587,7 +672,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr //-------------------------------------------------------------------------// override fun visitClassReference(expression: IrClassReference): IrClassReference { - val newExpressionType = substituteType(expression.type)!! // Substituted expression type. + val newExpressionType = substituteAndEraseType(expression.type)!! // Substituted expression type. val newDescriptorType = substituteType(expression.descriptor.defaultType)!! // Substituted type of referenced class. val classDescriptor = newDescriptorType.constructor.declarationDescriptor!! // Get ClassifierDescriptor of the referenced class. return IrClassReferenceImpl( @@ -602,7 +687,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr //-------------------------------------------------------------------------// override fun visitGetClass(expression: IrGetClass): IrGetClass { - val type = substituteType(expression.type)!! + val type = substituteAndEraseType(expression.type)!! return IrGetClassImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, @@ -616,6 +701,27 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop { return irLoop } + + override fun visitClass(declaration: IrClass): IrClass { + val descriptor = this.mapClassDeclaration(declaration.descriptor) + + return context.ir.symbols.symbolTable.declareClass( + declaration.startOffset, declaration.endOffset, mapDeclarationOrigin(declaration.origin), + descriptor + ).apply { + declaration.declarations.mapTo(this.declarations) { + it.transform(this@InlineCopyIr, null) as IrDeclaration + } + this.transformAnnotations(declaration) + this.thisReceiver = declaration.thisReceiver?.replaceDescriptor1(this.descriptor.thisAsReceiverParameter) + + this.transformTypeParameters(declaration, this.descriptor.declaredTypeParameters) + + descriptor.defaultType.constructor.supertypes.mapTo(this.superTypes) { + context.ir.translateErased(it) + } + } + } } //-------------------------------------------------------------------------// @@ -627,12 +733,24 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr return descriptorSubstituteMap[oldClassDescriptor]?.let { (it as ClassDescriptor).defaultType } ?: substitutedType } + private fun substituteAndEraseType(oldType: IrType?): IrType? { + oldType ?: return null + + val substitutedKotlinType = substituteType(oldType.toKotlinType()) + ?: return oldType + return context.ir.translateErased(substitutedKotlinType) + } + + private fun substituteAndBreakType(oldType: IrType): IrType { + return context.ir.translateBroken(substituteType(oldType.toKotlinType())!!) + } + //-------------------------------------------------------------------------// private fun IrMemberAccessExpression.substituteTypeArguments(original: IrMemberAccessExpression) { for (index in 0 until original.typeArgumentsCount) { val originalTypeArgument = original.getTypeArgument(index) - val newTypeArgument = substituteType(originalTypeArgument)!! + val newTypeArgument = substituteAndBreakType(originalTypeArgument!!) this.putTypeArgument(index, newTypeArgument) } } @@ -649,7 +767,10 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr class SubstitutedDescriptor(val inlinedFunction: FunctionDescriptor, val descriptor: DeclarationDescriptor) -class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap) +internal class DescriptorSubstitutorForExternalScope( + val globalSubstituteMap: MutableMap, + val context: Context +) : IrElementTransformerVoidWithContext() { private val variableSubstituteMap = mutableMapOf() @@ -710,6 +831,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap< endOffset = declaration.endOffset, origin = declaration.origin, descriptor = newDescriptor, + type = context.ir.translateErased(newDescriptor.type), initializer = declaration.initializer ) } @@ -725,6 +847,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap< return IrGetValueImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, + type = context.ir.translateErased(newDescriptor.type), origin = expression.origin, symbol = createValueSymbol(newDescriptor) ) @@ -743,7 +866,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap< return IrCallImpl( startOffset = oldExpression.startOffset, endOffset = oldExpression.endOffset, - type = newDescriptor.returnType!!, + type = context.ir.translateErased(newDescriptor.returnType!!), symbol = createFunctionSymbol(newDescriptor), descriptor = newDescriptor, typeArgumentsCount = oldExpression.typeArgumentsCount, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentsStubGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentsStubGenerator.kt deleted file mode 100644 index a8154ad474a..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentsStubGenerator.kt +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.konan.lower - -import org.jetbrains.kotlin.backend.common.BodyLoweringPass -import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass -import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName -import org.jetbrains.kotlin.backend.common.ir.ir2string -import org.jetbrains.kotlin.backend.common.lower.createIrBuilder -import org.jetbrains.kotlin.backend.common.lower.irBlockBody -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl -import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl -import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns -import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue -import org.jetbrains.kotlin.resolve.calls.components.isVararg -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.builtIns - -open class DefaultArgumentStubGenerator constructor(val context: CommonBackendContext): DeclarationContainerLoweringPass { - override fun lower(irDeclarationContainer: IrDeclarationContainer) { - irDeclarationContainer.declarations.transformFlat { memberDeclaration -> - if (memberDeclaration is IrFunction) - lower(memberDeclaration).also { functions -> - functions.forEach { - it.parent = irDeclarationContainer - } - } - else - null - } - - } - - private val symbols = context.ir.symbols - - private fun lower(irFunction: IrFunction): List { - val functionDescriptor = irFunction.descriptor - - if (!functionDescriptor.needsDefaultArgumentsLowering) - return listOf(irFunction) - - val bodies = functionDescriptor.valueParameters - .mapNotNull{irFunction.getDefault(it)} - - - log { "detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions" } - functionDescriptor.overriddenDescriptors.forEach { context.log{"DEFAULT-REPLACER: $it"} } - if (bodies.isNotEmpty()) { - val newIrFunction = functionDescriptor.generateDefaultsFunction(context) - newIrFunction.parent = irFunction.parent - val descriptor = newIrFunction.descriptor - log { "$functionDescriptor -> $descriptor" } - val builder = context.createIrBuilder(newIrFunction.symbol) - newIrFunction.body = builder.irBlockBody(newIrFunction) { - val params = mutableListOf() - val variables = mutableMapOf() - - irFunction.dispatchReceiverParameter?.let { - variables[it.descriptor] = newIrFunction.dispatchReceiverParameter!!.symbol - } - - if (descriptor.extensionReceiverParameter != null) { - variables[functionDescriptor.extensionReceiverParameter!!] = - newIrFunction.extensionReceiverParameter!!.symbol - } - - for (valueParameter in functionDescriptor.valueParameters) { - val parameterSymbol = newIrFunction.valueParameters[valueParameter.index].symbol - val temporaryVariableSymbol = - IrVariableSymbolImpl(scope.createTemporaryVariableDescriptor(parameterSymbol.descriptor)) - params.add(temporaryVariableSymbol) - variables.put(valueParameter, temporaryVariableSymbol) - if (valueParameter.hasDefaultValue()) { - val kIntAnd = symbols.intAnd - val condition = irNotEquals(irCall(kIntAnd).apply { - dispatchReceiver = irGet(maskParameterSymbol(newIrFunction, valueParameter.index / 32)) - putValueArgument(0, irInt(1 shl (valueParameter.index % 32))) - }, irInt(0)) - val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter) - - /* Use previously calculated values in next expression. */ - expressionBody.transformChildrenVoid(object: IrElementTransformerVoid() { - override fun visitGetValue(expression: IrGetValue): IrExpression { - log { "GetValue: ${expression.descriptor}" } - val valueSymbol = variables[expression.descriptor] ?: return expression - return irGet(valueSymbol) - } - }) - val variableInitialization = irIfThenElse( - type = temporaryVariableSymbol.descriptor.type, - condition = condition, - thenPart = expressionBody.expression, - elsePart = irGet(parameterSymbol)) - + scope.createTemporaryVariable( - symbol = temporaryVariableSymbol, - initializer = variableInitialization) - /* Mapping calculated values with its origin variables. */ - } else { - + scope.createTemporaryVariable( - symbol = temporaryVariableSymbol, - initializer = irGet(parameterSymbol)) - } - } - if (irFunction is IrConstructor) { - + IrDelegatingConstructorCallImpl( - startOffset = irFunction.startOffset, - endOffset = irFunction.endOffset, - symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor - ).apply { - params.forEachIndexed { i, variable -> - putValueArgument(i, irGet(variable)) - } - if (functionDescriptor.dispatchReceiverParameter != null) { - dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol) - } - } - } else { - +irReturn(irCall(irFunction.symbol).apply { - if (functionDescriptor.dispatchReceiverParameter != null) { - dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol) - } - if (functionDescriptor.extensionReceiverParameter != null) { - extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!]!!) - } - params.forEachIndexed { i, variable -> - putValueArgument(i, irGet(variable)) - } - }) - } - } - // Remove default argument initializers. - irFunction.valueParameters.forEach { - it.defaultValue = null - } - - return listOf(irFunction, newIrFunction) - } - return listOf(irFunction) - } - - - private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" } -} - -private fun Scope.createTemporaryVariableDescriptor(parameterDescriptor: ParameterDescriptor?): VariableDescriptor = - IrTemporaryVariableDescriptorImpl( - containingDeclaration = this.scopeOwner, - name = parameterDescriptor!!.name.asString().synthesizedName, - outType = parameterDescriptor.type, - isMutable = false) - -private fun Scope.createTemporaryVariable(symbol: IrVariableSymbol, initializer: IrExpression) = - IrVariableImpl( - startOffset = initializer.startOffset, - endOffset = initializer.endOffset, - origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, - symbol = symbol).apply { - - this.initializer = initializer - } - -private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor): IrExpressionBody { - return irFunction.getDefault(valueParameter) ?: TODO("FIXME!!!") -} - -private fun maskParameterDescriptor(function: IrFunction, number: Int) = - maskParameterSymbol(function, number).descriptor as ValueParameterDescriptor -private fun maskParameterSymbol(function: IrFunction, number: Int) = - function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }.symbol - -private fun markerParameterDescriptor(descriptor: FunctionDescriptor) = descriptor.valueParameters.single { it.name == kConstructorMarkerName } - -fun nullConst(expression: IrElement, type: KotlinType) = when { - KotlinBuiltIns.isFloat(type) -> IrConstImpl.float (expression.startOffset, expression.endOffset, type, 0.0F) - KotlinBuiltIns.isDouble(type) -> IrConstImpl.double (expression.startOffset, expression.endOffset, type, 0.0) - KotlinBuiltIns.isBoolean(type) -> IrConstImpl.boolean (expression.startOffset, expression.endOffset, type, false) - KotlinBuiltIns.isByte(type) -> IrConstImpl.byte (expression.startOffset, expression.endOffset, type, 0) - KotlinBuiltIns.isChar(type) -> IrConstImpl.char (expression.startOffset, expression.endOffset, type, 0.toChar()) - KotlinBuiltIns.isShort(type) -> IrConstImpl.short (expression.startOffset, expression.endOffset, type, 0) - KotlinBuiltIns.isInt(type) -> IrConstImpl.int (expression.startOffset, expression.endOffset, type, 0) - KotlinBuiltIns.isLong(type) -> IrConstImpl.long (expression.startOffset, expression.endOffset, type, 0) - else -> IrConstImpl.constNull (expression.startOffset, expression.endOffset, type.builtIns.nullableNothingType) -} - -class DefaultParameterInjector constructor(val context: CommonBackendContext): BodyLoweringPass { - override fun lower(irBody: IrBody) { - - irBody.transformChildrenVoid(object : IrElementTransformerVoid() { - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { - super.visitDelegatingConstructorCall(expression) - val descriptor = expression.descriptor - if (!descriptor.needsDefaultArgumentsLowering) - return expression - val argumentsCount = argumentCount(expression) - if (argumentsCount == descriptor.valueParameters.size) - return expression - val (symbolForCall, params) = parametersForCall(expression) - return IrDelegatingConstructorCallImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - symbol = symbolForCall as IrConstructorSymbol, - descriptor = symbolForCall.descriptor) - .apply { - params.forEach { - log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" } - putValueArgument(it.first.index, it.second) - } - dispatchReceiver = expression.dispatchReceiver - } - - } - - override fun visitCall(expression: IrCall): IrExpression { - super.visitCall(expression) - val functionDescriptor = expression.descriptor - - if (!functionDescriptor.needsDefaultArgumentsLowering) - return expression - - val argumentsCount = argumentCount(expression) - if (argumentsCount == functionDescriptor.valueParameters.size) - return expression - val (symbol, params) = parametersForCall(expression) - val descriptor = symbol.descriptor - descriptor.typeParameters.forEach { log { "$descriptor [${it.index}]: $it" } } - descriptor.original.typeParameters.forEach { log { "${descriptor.original}[${it.index}] : $it" } } - return IrCallImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - symbol = symbol, - descriptor = descriptor, - typeArguments = expression.descriptor.typeParameters.map{it to (expression.getTypeArgument(it) ?: it.defaultType) }.toMap()) - .apply { - params.forEach { - log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" } - putValueArgument(it.first.index, it.second) - } - expression.extensionReceiver?.apply{ - extensionReceiver = expression.extensionReceiver - } - expression.dispatchReceiver?.apply { - dispatchReceiver = expression.dispatchReceiver - } - log { "call::extension@: ${ir2string(expression.extensionReceiver)}" } - log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" } - } - } - - private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? { - if (!this.descriptor.needsDefaultArgumentsLowering) return null - - if (this !is IrSimpleFunction) return this - - this.overriddenSymbols.forEach { - it.owner.findSuperMethodWithDefaultArguments()?.let { return it } - } - - return this - } - - private fun parametersForCall(expression: IrFunctionAccessExpression): Pair>> { - val descriptor = expression.descriptor - val keyFunction = expression.symbol.owner.findSuperMethodWithDefaultArguments()!! - val keyDescriptor = keyFunction.descriptor - val realFunction = keyDescriptor.generateDefaultsFunction(context) - realFunction.parent = keyFunction.parent - val realDescriptor = realFunction.descriptor - - log { "$descriptor -> $realDescriptor" } - val maskValues = Array((descriptor.valueParameters.size + 31) / 32, { 0 }) - val params = mutableListOf>() - params.addAll(descriptor.valueParameters.mapIndexed { i, _ -> - val valueArgument = expression.getValueArgument(i) - if (valueArgument == null) { - val maskIndex = i / 32 - maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (i % 32)) - } - val valueParameterDescriptor = realDescriptor.valueParameters[i] - val defaultValueArgument = if (valueParameterDescriptor.isVararg) null else nullConst(expression, valueParameterDescriptor.type) - valueParameterDescriptor to (valueArgument ?: defaultValueArgument) - }) - maskValues.forEachIndexed { i, maskValue -> - params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int( - startOffset = irBody.startOffset, - endOffset = irBody.endOffset, - type = descriptor.builtIns.intType, - value = maskValue) - } - if (expression.descriptor is ClassConstructorDescriptor) { - val defaultArgumentMarker = context.ir.symbols.defaultConstructorMarker - params += markerParameterDescriptor(realDescriptor) to IrGetObjectValueImpl( - startOffset = irBody.startOffset, - endOffset = irBody.endOffset, - type = defaultArgumentMarker.owner.defaultType, - symbol = defaultArgumentMarker) - } - else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { - params += realDescriptor.valueParameters.last() to - IrConstImpl.constNull(irBody.startOffset, irBody.endOffset, context.builtIns.any.defaultType) - } - params.forEach { - log { "descriptor::${realDescriptor.name.asString()}#${it.first.index}: ${it.first.name.asString()}" } - } - return Pair(realFunction.symbol, params) - } - - private fun argumentCount(expression: IrMemberAccessExpression) = - expression.descriptor.valueParameters.count { expression.getValueArgument(it) != null } - }) - } - - private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" } -} - -private val CallableMemberDescriptor.needsDefaultArgumentsLowering - get() = valueParameters.any { it.hasDefaultValue() } && !(this is FunctionDescriptor && isInline) - -private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendContext): IrFunction { - return context.ir.defaultParameterDeclarationsCache.getOrPut(this) { - val descriptor = when (this) { - is ClassConstructorDescriptor -> - ClassConstructorDescriptorImpl.create( - /* containingDeclaration = */ containingDeclaration, - /* annotations = */ annotations, - /* isPrimary = */ false, - /* source = */ source) - else -> { - val name = Name.identifier("$name\$default") - - SimpleFunctionDescriptorImpl.create( - /* containingDeclaration = */ containingDeclaration, - /* annotations = */ annotations, - /* name = */ name, - /* kind = */ CallableMemberDescriptor.Kind.SYNTHESIZED, - /* source = */ source) - } - } - - val syntheticParameters = MutableList((valueParameters.size + 31) / 32) { i -> - valueParameter(descriptor, valueParameters.size + i, parameterMaskName(i), descriptor.builtIns.intType) - } - if (this is ClassConstructorDescriptor) { - syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1, - kConstructorMarkerName, - context.ir.symbols.defaultConstructorMarker.owner.defaultType) - } - else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { - syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1, - "handler".synthesizedName, - context.ir.symbols.any.owner.defaultType) - } - - descriptor.initialize( - /* receiverParameterType = */ extensionReceiverParameter?.type, - /* dispatchReceiverParameter = */ dispatchReceiverParameter, - /* typeParameters = */ typeParameters.map { - TypeParameterDescriptorImpl.createForFurtherModification( - /* containingDeclaration = */ descriptor, - /* annotations = */ it.annotations, - /* reified = */ it.isReified, - /* variance = */ it.variance, - /* name = */ it.name, - /* index = */ it.index, - /* source = */ it.source, - /* reportCycleError = */ null, - /* supertypeLoopsChecker = */ SupertypeLoopChecker.EMPTY - ).apply { - it.upperBounds.forEach { addUpperBound(it) } - setInitialized() - } - }, - /* unsubstitutedValueParameters = */ valueParameters.map { - ValueParameterDescriptorImpl( - containingDeclaration = descriptor, - original = null, /* ValueParameterDescriptorImpl::copy do not save original. */ - index = it.index, - annotations = it.annotations, - name = it.name, - outType = it.type, - declaresDefaultValue = false, - isCrossinline = it.isCrossinline, - isNoinline = it.isNoinline, - varargElementType = it.varargElementType, - source = it.source) - } + syntheticParameters, - /* unsubstitutedReturnType = */ returnType, - /* modality = */ Modality.FINAL, - /* visibility = */ this.visibility) - descriptor.isSuspend = this.isSuspend - context.log{"adds to cache[$this] = $descriptor"} - - val startOffset = this.startOffsetOrUndefined - val endOffset = this.endOffsetOrUndefined - - val result: IrFunction = when (descriptor) { - is ClassConstructorDescriptor -> IrConstructorImpl( - startOffset, endOffset, - DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, - descriptor - ) - - else -> IrFunctionImpl( - startOffset, endOffset, - DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, - descriptor - ) - } - - result.createParameterDeclarations() - - result - } -} - -object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER : - IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT") - -private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: KotlinType): ValueParameterDescriptor { - return ValueParameterDescriptorImpl( - containingDeclaration = descriptor, - original = null, - index = index, - annotations = Annotations.EMPTY, - name = name, - outType = type, - declaresDefaultValue = false, - isCrossinline = false, - isNoinline = false, - varargElementType = null, - source = SourceElement.NO_SOURCE - ) -} - -internal val kConstructorMarkerName = "marker".synthesizedName - -private fun parameterMaskName(number: Int) = "mask$number".synthesizedName diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt index a64c96c9923..19f35c0abf9 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt @@ -16,15 +16,13 @@ package org.jetbrains.kotlin.backend.konan.lower -import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlock -import org.jetbrains.kotlin.backend.jvm.descriptors.initialize import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName -import org.jetbrains.kotlin.backend.common.ir.createArrayOfExpression import org.jetbrains.kotlin.backend.konan.KonanBackendContext +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl @@ -35,15 +33,14 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrLocalDelegatedProperty import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrLocalDelegatedPropertyReference import org.jetbrains.kotlin.ir.expressions.IrPropertyReference import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.ir.util.addChild -import org.jetbrains.kotlin.ir.util.constructors -import org.jetbrains.kotlin.ir.util.functions +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.toKotlinType +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType @@ -55,10 +52,10 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi private val reflectionTypes = context.reflectionTypes private var tempIndex = 0 - private fun getKPropertyImplConstructor(receiverTypes: List, - returnType: KotlinType, + private fun getKPropertyImplConstructor(receiverTypes: List, + returnType: IrType, isLocal: Boolean, - isMutable: Boolean) : Pair> { + isMutable: Boolean) : Pair> { val symbols = context.ir.symbols @@ -87,10 +84,7 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi } } - val typeParameters = classSymbol.descriptor.declaredTypeParameters val arguments = (receiverTypes + listOf(returnType)) - .mapIndexed { index, type -> typeParameters[index] to type } - .toMap() return classSymbol.constructors.single() to arguments } @@ -102,17 +96,21 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi override fun lower(irFile: IrFile) { val kProperties = mutableMapOf>() - val arrayClass = context.ir.symbols.array + val arrayClass = context.ir.symbols.array.owner val arrayItemGetter = arrayClass.functions.single { it.descriptor.name == Name.identifier("get") } - val kPropertyImplType = reflectionTypes.kProperty1Impl.replace(context.builtIns.anyType, context.builtIns.anyType) + val anyType = context.irBuiltIns.anyType + val kPropertyImplType = context.ir.symbols.kProperty1Impl.typeWith(anyType, anyType) + + val kPropertiesFieldType: IrType = context.ir.symbols.array.typeWith(kPropertyImplType) val kPropertiesField = IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION, createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor, - context.builtIns.array.replace(kPropertyImplType) - ) + kPropertiesFieldType.toKotlinType() + ), + kPropertiesFieldType ) irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() { @@ -148,11 +146,9 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi createKProperty(expression, this) to kProperties.size } - return irCall(arrayItemGetter, typeArguments = listOf(kPropertyImplType)).apply { - dispatchReceiver = - IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField.symbol) - - putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second)) + return irCall(arrayItemGetter).apply { + dispatchReceiver = irGetField(null, kPropertiesField) + putValueArgument(0, irInt(field.second)) } } } @@ -173,14 +169,16 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi else { // Cache KProperties with no arguments. // TODO: what about `receiversCount == 1` case? val field = kProperties.getOrPut(propertyDescriptor) { - createLocalKProperty(propertyDescriptor, this) to kProperties.size + createLocalKProperty( + propertyDescriptor, + expression.getter.owner.returnType, + this + ) to kProperties.size } - return irCall(arrayItemGetter, typeArguments = listOf(kPropertyImplType)).apply { - dispatchReceiver = - IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField.symbol) - - putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second)) + return irCall(arrayItemGetter).apply { + dispatchReceiver = irGetField(null, kPropertiesField) + putValueArgument(0, irInt(field.second)) } } } @@ -203,23 +201,23 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi val startOffset = expression.startOffset val endOffset = expression.endOffset return irBuilder.irBlock(expression) { - val receiverTypes = mutableListOf() + val receiverTypes = mutableListOf() val dispatchReceiver = expression.dispatchReceiver.let { if (it == null) null else - irTemporary(value = it, nameHint = "\$dispatchReceiver${tempIndex++}").symbol + irTemporary(value = it, nameHint = "\$dispatchReceiver${tempIndex++}") } val extensionReceiver = expression.extensionReceiver.let { if (it == null) null else - irTemporary(value = it, nameHint = "\$extensionReceiver${tempIndex++}").symbol + irTemporary(value = it, nameHint = "\$extensionReceiver${tempIndex++}") } val propertyDescriptor = expression.descriptor + val returnType = expression.getter?.owner?.returnType ?: expression.field!!.owner.type - val returnType = propertyDescriptor.type - val getterCallableReference = propertyDescriptor.getter?.let { getter -> + val getterCallableReference = expression.getter?.owner?.let { getter -> getter.extensionReceiverParameter.let { if (it != null && expression.extensionReceiver == null) receiverTypes.add(it.type) @@ -228,39 +226,37 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi if (it != null && expression.dispatchReceiver == null) receiverTypes.add(it.type) } - val getterKFunctionType = reflectionTypes.getKFunctionType( - annotations = Annotations.EMPTY, - receiverType = receiverTypes.firstOrNull(), - parameterTypes = if (receiverTypes.size < 2) listOf() else listOf(receiverTypes[1]), - returnType = returnType) + val getterKFunctionType = this@PropertyDelegationLowering.context.ir.symbols.getKFunctionType( + returnType, + receiverTypes + ) IrFunctionReferenceImpl( startOffset = startOffset, endOffset = endOffset, type = getterKFunctionType, symbol = expression.getter!!, - descriptor = getter, - typeArguments = null + descriptor = getter.descriptor, + typeArgumentsCount = 0 ).apply { this.dispatchReceiver = dispatchReceiver?.let { irGet(it) } this.extensionReceiver = extensionReceiver?.let { irGet(it) } } } - val setterCallableReference = propertyDescriptor.setter?.let { - if (!isKMutablePropertyType(expression.type)) null + val setterCallableReference = expression.setter?.owner?.let { + if (!isKMutablePropertyType(expression.type.toKotlinType())) null else { - val setterKFunctionType = reflectionTypes.getKFunctionType( - annotations = Annotations.EMPTY, - receiverType = receiverTypes.firstOrNull(), - parameterTypes = if (receiverTypes.size < 2) listOf(returnType) else listOf(receiverTypes[1], returnType), - returnType = context.builtIns.unitType) + val setterKFunctionType = this@PropertyDelegationLowering.context.ir.symbols.getKFunctionType( + context.irBuiltIns.unitType, + receiverTypes + returnType + ) IrFunctionReferenceImpl( startOffset = startOffset, endOffset = endOffset, type = setterKFunctionType, symbol = expression.setter!!, - descriptor = it, - typeArguments = null + descriptor = it.descriptor, + typeArgumentsCount = 0 ).apply { this.dispatchReceiver = dispatchReceiver?.let { irGet(it) } this.extensionReceiver = extensionReceiver?.let { irGet(it) } @@ -273,7 +269,7 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi returnType = returnType, isLocal = false, isMutable = setterCallableReference != null) - val initializer = irCall(symbol, constructorTypeArguments).apply { + val initializer = irCall(symbol.owner, constructorTypeArguments).apply { putValueArgument(0, irString(propertyDescriptor.name.asString())) if (getterCallableReference != null) putValueArgument(1, getterCallableReference) @@ -285,16 +281,15 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi } private fun createLocalKProperty(propertyDescriptor: VariableDescriptorWithAccessors, + propertyType: IrType, irBuilder: IrBuilderWithScope): IrExpression { irBuilder.run { - val returnType = propertyDescriptor.type - val (symbol, constructorTypeArguments) = getKPropertyImplConstructor( receiverTypes = emptyList(), - returnType = returnType, + returnType = propertyType, isLocal = true, isMutable = false) - val initializer = irCall(symbol, constructorTypeArguments).apply { + val initializer = irCall(symbol.owner, constructorTypeArguments).apply { putValueArgument(0, irString(propertyDescriptor.name.asString())) } return initializer @@ -316,10 +311,15 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi private object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION : IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION") - private fun createKPropertiesFieldDescriptor(containingDeclaration: DeclarationDescriptor, fieldType: SimpleType): PropertyDescriptorImpl { + private fun createKPropertiesFieldDescriptor(containingDeclaration: DeclarationDescriptor, fieldType: KotlinType): PropertyDescriptorImpl { return PropertyDescriptorImpl.create(containingDeclaration, Annotations.EMPTY, Modality.FINAL, Visibilities.PRIVATE, false, "KPROPERTIES".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, - false, false, false, false, false, false).initialize(fieldType) + false, false, false, false, false, false).apply { + + val receiverType: KotlinType? = null + this.setType(fieldType, emptyList(), null, receiverType) + this.initialize(null, null) + } } } 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 8db06af553b..1192a65723e 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 @@ -20,16 +20,19 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.deepCopyWithVariables import org.jetbrains.kotlin.backend.common.runOnFilePostfix -import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor -import org.jetbrains.kotlin.backend.common.ir.createArrayOfExpression -import org.jetbrains.kotlin.backend.common.ir.createSimpleDelegatingConstructorDescriptor import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody +import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.ir.IrStatement @@ -38,61 +41,60 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.types.* - internal class EnumSyntheticFunctionsBuilder(val context: Context) { fun buildValuesExpression(startOffset: Int, endOffset: Int, - enumClassDescriptor: ClassDescriptor): IrExpression { - val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor) + enumClass: IrClass): IrExpression { - val typeParameterT = genericValuesDescriptor.typeParameters[0] - val enumClassType = enumClassDescriptor.defaultType - val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType))) - val substitutedValueOf = genericValuesDescriptor.substitute(typeSubstitutor)!! + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass) - return IrCallImpl(startOffset, endOffset, - genericValuesSymbol, substitutedValueOf, mapOf(typeParameterT to enumClassType)) + return irCall(startOffset, endOffset, genericValuesSymbol.owner, listOf(enumClass.defaultType)) .apply { val receiver = IrGetObjectValueImpl(startOffset, endOffset, - loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol) - putValueArgument(0, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver)) + loweredEnum.implObject.defaultType, + loweredEnum.implObject.symbol) + putValueArgument(0, IrGetFieldImpl( + startOffset, + endOffset, + loweredEnum.valuesField.symbol, + loweredEnum.valuesField.type, + receiver + )) } } fun buildValueOfExpression(startOffset: Int, endOffset: Int, - enumClassDescriptor: ClassDescriptor, + enumClass: IrClass, value: IrExpression): IrExpression { - val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor) + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass) - val typeParameterT = genericValueOfDescriptor.typeParameters[0] - val enumClassType = enumClassDescriptor.defaultType - val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType))) - val substitutedValueOf = genericValueOfDescriptor.substitute(typeSubstitutor)!! - - return IrCallImpl(startOffset, endOffset, - genericValueOfSymbol, substitutedValueOf, mapOf(typeParameterT to enumClassType)) + return irCall(startOffset, endOffset, genericValueOfSymbol.owner, listOf(enumClass.defaultType)) .apply { putValueArgument(0, value) val receiver = IrGetObjectValueImpl(startOffset, endOffset, loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol) - putValueArgument(1, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver)) + putValueArgument(1, IrGetFieldImpl( + startOffset, + endOffset, + loweredEnum.valuesField.symbol, + loweredEnum.valuesField.type, + receiver + )) } } private val genericValueOfSymbol = context.ir.symbols.valueOfForEnum - private val genericValueOfDescriptor = genericValueOfSymbol.descriptor private val genericValuesSymbol = context.ir.symbols.valuesForEnum - private val genericValuesDescriptor = genericValuesSymbol.descriptor } internal class EnumUsageLowering(val context: Context) @@ -105,16 +107,13 @@ internal class EnumUsageLowering(val context: Context) } override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression { - val enumClassDescriptor = expression.descriptor.containingDeclaration as ClassDescriptor - return loadEnumEntry(expression.startOffset, expression.endOffset, enumClassDescriptor, expression.descriptor.name) - } - - // TODO: remove as soon IR is fixed (there should no be any enum get with GET_OBJECT operation). - override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression { - if (expression.descriptor.kind != ClassKind.ENUM_ENTRY) - return super.visitGetObjectValue(expression) - val enumClassDescriptor = expression.descriptor.containingDeclaration as ClassDescriptor - return loadEnumEntry(expression.startOffset, expression.endOffset, enumClassDescriptor, expression.descriptor.name) + val entry = expression.symbol.owner + return loadEnumEntry( + expression.startOffset, + expression.endOffset, + entry.parentAsClass, + entry.name + ) } override fun visitCall(expression: IrCall): IrExpression { @@ -125,18 +124,20 @@ internal class EnumUsageLowering(val context: Context) if (descriptor.original != enumValuesDescriptor && descriptor.original != enumValueOfDescriptor) return expression - val genericT = descriptor.original.typeParameters[0] - val substitutedT = expression.getTypeArgument(genericT)!! - val classDescriptor = substitutedT.constructor.declarationDescriptor as? ClassDescriptor + val irClassSymbol = expression.getTypeArgument(0)!!.classifierOrNull as? IrClassSymbol ?: return expression // Type parameter. - assert (classDescriptor.kind == ClassKind.ENUM_CLASS) + if (irClassSymbol == context.ir.symbols.enum) return expression // Type parameter erased to 'Enum'. + + val irClass = irClassSymbol.owner + + assert (irClass.kind == ClassKind.ENUM_CLASS) return if (descriptor.original == enumValuesDescriptor) { - enumSyntheticFunctionsBuilder.buildValuesExpression(expression.startOffset, expression.endOffset, classDescriptor) + enumSyntheticFunctionsBuilder.buildValuesExpression(expression.startOffset, expression.endOffset, irClass) } else { val value = expression.getValueArgument(0)!! - enumSyntheticFunctionsBuilder.buildValueOfExpression(expression.startOffset, expression.endOffset, classDescriptor, value) + enumSyntheticFunctionsBuilder.buildValueOfExpression(expression.startOffset, expression.endOffset, irClass, value) } } @@ -146,12 +147,12 @@ internal class EnumUsageLowering(val context: Context) private val enumValuesSymbol = context.ir.symbols.enumValues private val enumValuesDescriptor = enumValuesSymbol.descriptor - private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClassDescriptor: ClassDescriptor, name: Name): IrExpression { - val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor) + private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClass: IrClass, name: Name): IrExpression { + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass) val ordinal = loweredEnum.entriesMap[name]!! - return IrCallImpl(startOffset, endOffset, loweredEnum.itemGetterSymbol, loweredEnum.itemGetterDescriptor).apply { - dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol) - putValueArgument(0, IrConstImpl.int(startOffset, endOffset, enumClassDescriptor.module.builtIns.intType, ordinal)) + return irCall(startOffset, endOffset, loweredEnum.itemGetterSymbol.owner, emptyList()).apply { + dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter.returnType, loweredEnum.valuesGetter.symbol) + putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal)) } } } @@ -178,7 +179,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { } private inner class EnumClassTransformer(val irClass: IrClass) { - private val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(irClass.descriptor) + private val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(irClass) private val loweredEnumConstructors = mutableMapOf() private val descriptorToIrConstructorWithDefaultArguments = mutableMapOf() private val defaultEnumEntryConstructors = mutableMapOf() @@ -212,7 +213,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { blockBody.statements.transformFlat { if (it is IrEnumConstructorCall) listOf(it, IrInstanceInitializerCallImpl(declaration.startOffset, declaration.startOffset, - irClass.symbol)) + irClass.symbol, context.irBuiltIns.unitType)) else null } } @@ -245,17 +246,22 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val defaultClassDescriptor = ClassDescriptorImpl(descriptor, "DEFAULT".synthesizedName, Modality.FINAL, ClassKind.CLASS, listOf(descriptor.defaultType), SourceElement.NO_SOURCE, false, LockBasedStorageManager.NO_LOCKS) val defaultClass = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, defaultClassDescriptor) + defaultClass.createParameterDeclarations() val constructors = mutableSetOf() descriptor.constructors.forEach { - val loweredEnumConstructorSymbol = loweredEnumConstructors[it]!!.symbol - val loweredEnumConstructor = loweredEnumConstructorSymbol.descriptor - val constructorDescriptor = defaultClassDescriptor.createSimpleDelegatingConstructorDescriptor(loweredEnumConstructor) + val loweredEnumIrConstructor = loweredEnumConstructors[it]!! + val loweredEnumConstructor = loweredEnumIrConstructor.descriptor + val constructor = defaultClass.addSimpleDelegatingConstructor( - loweredEnumConstructorSymbol, constructorDescriptor, - DECLARATION_ORIGIN_ENUM) + loweredEnumIrConstructor, + context.irBuiltIns, + DECLARATION_ORIGIN_ENUM + ) + + val constructorDescriptor = constructor.descriptor constructors.add(constructorDescriptor) defaultEnumEntryConstructors.put(loweredEnumConstructor, constructor) @@ -273,8 +279,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val memberScope = stub("enum default class") defaultClassDescriptor.initialize(memberScope, constructors, null) - defaultClass.createParameterDeclarations() - defaultClass.setSuperSymbolsAndAddFakeOverrides(listOf(irClass)) + defaultClass.setSuperSymbolsAndAddFakeOverrides(listOf(irClass.defaultType)) return defaultClass } @@ -310,12 +315,6 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { ++i } - val constructorOfAny = context.ir.symbols.any.constructors.single() - - implObject.addSimpleDelegatingConstructor( - constructorOfAny, implObject.descriptor.constructors.single(), - DECLARATION_ORIGIN_ENUM) - implObject.addChild(createSyntheticValuesPropertyDeclaration(enumEntries)) implObject.addChild(createValuesPropertyInitializer(enumEntries)) @@ -329,17 +328,19 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val startOffset = irClass.startOffset val endOffset = irClass.endOffset - val irValuesInitializer = context.createArrayOfExpression(irClass.descriptor.defaultType, + val irValuesInitializer = context.createArrayOfExpression(irClass.defaultType, enumEntries .sortedBy { it.descriptor.name } .map { - val enumEntryClass = ((it.initializerExpression!! as IrCall).descriptor as ConstructorDescriptor).constructedClass - val typeParameterT = genericCreateUninitializedInstanceDescriptor.typeParameters[0] - val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumEntryClass.defaultType))) - val substitutedCreateUninitializedInstance = genericCreateUninitializedInstanceDescriptor.substitute(typeSubstitutor)!! - IrCallImpl(startOffset, endOffset, - genericCreateUninitializedInstanceSymbol, substitutedCreateUninitializedInstance, mapOf(typeParameterT to enumEntryClass.defaultType) + val entryConstructorCall = it.initializerExpression!! as IrCall + val entryConstructor = entryConstructorCall.symbol.owner as IrConstructor + val entryClass = entryConstructor.constructedClass + + irCall(startOffset, endOffset, + genericCreateUninitializedInstanceSymbol.owner, + listOf(entryClass.defaultType) ) + }, startOffset, endOffset) val irField = loweredEnum.valuesField.apply { initializer = IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer) @@ -349,8 +350,20 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val receiver = IrGetObjectValueImpl(startOffset, endOffset, loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol) - val value = IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver) - val returnStatement = IrReturnImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol, value) + val value = IrGetFieldImpl( + startOffset, + endOffset, + loweredEnum.valuesField.symbol, + loweredEnum.valuesField.type, + receiver + ) + val returnStatement = IrReturnImpl( + startOffset, + endOffset, + context.irBuiltIns.nothingType, + loweredEnum.valuesGetter.symbol, + value + ) getter.body = IrBlockBodyImpl(startOffset, endOffset, listOf(returnStatement)) return IrPropertyImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, @@ -363,7 +376,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { private val arrayGetSymbol = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") } - private val arrayType = context.builtIns.getArrayType(Variance.INVARIANT, irClass.defaultType) + private val arrayType = context.ir.symbols.array.typeWith(irClass.defaultType) private fun createValuesPropertyInitializer(enumEntries: List): IrAnonymousInitializerImpl { val startOffset = irClass.startOffset @@ -371,13 +384,13 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { return IrAnonymousInitializerImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, loweredEnum.implObject.descriptor).apply { body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody(irClass) { - val instances = irTemporary(irGetField(irGet(loweredEnum.implObject.thisReceiver!!.symbol), loweredEnum.valuesField.symbol)) + val instances = irTemporary(irGetField(irGet(loweredEnum.implObject.thisReceiver!!), loweredEnum.valuesField)) enumEntries .sortedBy { it.descriptor.name } .withIndex() .forEach { val instance = irCall(arrayGetSymbol).apply { - dispatchReceiver = irGet(instances.symbol) + dispatchReceiver = irGet(instances) putValueArgument(0, irInt(it.index)) } val initializer = it.value.initializerExpression!! as IrCall @@ -387,7 +400,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { } } +irCall(this@EnumClassLowering.context.ir.symbols.freeze, listOf(arrayType)).apply { - extensionReceiver = irGet(loweredEnum.implObject.thisReceiver!!.symbol) + extensionReceiver = irGet(loweredEnum.implObject.thisReceiver!!) } } } @@ -396,23 +409,35 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { private fun createSyntheticValuesMethodBody(declaration: IrFunction): IrBody { val startOffset = irClass.startOffset val endOffset = irClass.endOffset - val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass.descriptor) + val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass) - return IrBlockBodyImpl(startOffset, endOffset, - listOf(IrReturnImpl(startOffset, endOffset, declaration.symbol, valuesExpression)) - ) + return IrBlockBodyImpl(startOffset, endOffset).apply { + statements += IrReturnImpl( + startOffset, + endOffset, + context.irBuiltIns.nothingType, + declaration.symbol, + valuesExpression + ) + } } private fun createSyntheticValueOfMethodBody(declaration: IrFunction): IrBody { val startOffset = irClass.startOffset val endOffset = irClass.endOffset - val value = IrGetValueImpl(startOffset, endOffset, declaration.valueParameters[0].symbol) - val valueOfExpression = enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass.descriptor, value) + val parameter = declaration.valueParameters[0] + val value = IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol) + val valueOfExpression = enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass, value) - return IrBlockBodyImpl( - startOffset, endOffset, - listOf(IrReturnImpl(startOffset, endOffset, declaration.symbol, valueOfExpression)) - ) + return IrBlockBodyImpl(startOffset, endOffset).apply { + statements += IrReturnImpl( + startOffset, + endOffset, + context.irBuiltIns.nothingType, + declaration.symbol, + valueOfExpression + ) + } } private fun lowerEnumConstructors(irClass: IrClass) { @@ -423,18 +448,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { } private fun transformEnumConstructor(enumConstructor: IrConstructor): IrConstructor { - val constructorDescriptor = enumConstructor.descriptor - val loweredConstructorDescriptor = lowerEnumConstructor(constructorDescriptor) - val loweredEnumConstructor = IrConstructorImpl( - enumConstructor.startOffset, enumConstructor.endOffset, enumConstructor.origin, - loweredConstructorDescriptor, - enumConstructor.body!! // will be transformed later - ) - loweredEnumConstructor.parent = enumConstructor.parent - - loweredEnumConstructors[constructorDescriptor] = loweredEnumConstructor - - loweredEnumConstructor.createParameterDeclarations() + val loweredEnumConstructor = lowerEnumConstructor(enumConstructor) enumConstructor.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { val body = enumConstructor.getDefault(it)!! @@ -443,54 +457,75 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val descriptor = expression.descriptor when (descriptor) { is ValueParameterDescriptor -> { + val parameter = loweredEnumConstructor.valueParameters[descriptor.loweredIndex()] return IrGetValueImpl(expression.startOffset, expression.endOffset, - loweredEnumConstructor.valueParameters[descriptor.loweredIndex()].symbol) + parameter.type, + parameter.symbol) } } return expression } }) - loweredEnumConstructor.putDefault(loweredConstructorDescriptor.valueParameters[it.loweredIndex()], body) - descriptorToIrConstructorWithDefaultArguments[loweredConstructorDescriptor] = loweredEnumConstructor + loweredEnumConstructor.valueParameters[it.loweredIndex()].defaultValue = body + descriptorToIrConstructorWithDefaultArguments[loweredEnumConstructor.descriptor] = loweredEnumConstructor } return loweredEnumConstructor } - private fun lowerEnumConstructor(constructorDescriptor: ClassConstructorDescriptor): ClassConstructorDescriptor { + private fun lowerEnumConstructor(enumConstructor: IrConstructor): IrConstructorImpl { val loweredConstructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized( - constructorDescriptor.containingDeclaration, - constructorDescriptor.annotations, - constructorDescriptor.isPrimary, - constructorDescriptor.source + enumConstructor.descriptor.containingDeclaration, + enumConstructor.descriptor.annotations, + enumConstructor.descriptor.isPrimary, + enumConstructor.descriptor.source ) - val valueParameters = listOf( - loweredConstructorDescriptor.createValueParameter(0, "name", context.builtIns.stringType), - loweredConstructorDescriptor.createValueParameter(1, "ordinal", context.builtIns.intType) + loweredConstructorDescriptor.createValueParameter( + 0, + "name", + context.irBuiltIns.stringType, + enumConstructor.startOffset, + enumConstructor.endOffset + ), + loweredConstructorDescriptor.createValueParameter( + 1, + "ordinal", + context.irBuiltIns.intType, + enumConstructor.startOffset, + enumConstructor.endOffset + ) ) + - constructorDescriptor.valueParameters.map { - lowerConstructorValueParameter(loweredConstructorDescriptor, it) + enumConstructor.valueParameters.map { + val descriptor = it.descriptor as ValueParameterDescriptor + val loweredValueParameterDescriptor = descriptor.copy( + loweredConstructorDescriptor, + it.name, + descriptor.loweredIndex() + ) + loweredEnumConstructorParameters[descriptor] = loweredValueParameterDescriptor + it.copy(loweredValueParameterDescriptor) } - loweredConstructorDescriptor.initialize(valueParameters, Visibilities.PROTECTED) - loweredConstructorDescriptor.returnType = constructorDescriptor.returnType - - return loweredConstructorDescriptor - } - - private fun lowerConstructorValueParameter( - loweredConstructorDescriptor: ClassConstructorDescriptor, - valueParameterDescriptor: ValueParameterDescriptor - ): ValueParameterDescriptor { - val loweredValueParameterDescriptor = valueParameterDescriptor.copy( - loweredConstructorDescriptor, - valueParameterDescriptor.name, - valueParameterDescriptor.loweredIndex() + loweredConstructorDescriptor.initialize( + valueParameters.map { it.descriptor as ValueParameterDescriptor }, + Visibilities.PROTECTED ) - loweredEnumConstructorParameters[valueParameterDescriptor] = loweredValueParameterDescriptor - return loweredValueParameterDescriptor + loweredConstructorDescriptor.returnType = enumConstructor.descriptor.returnType + val loweredEnumConstructor = IrConstructorImpl( + enumConstructor.startOffset, enumConstructor.endOffset, enumConstructor.origin, + loweredConstructorDescriptor + ).apply { + returnType = enumConstructor.returnType + body = enumConstructor.body!! // will be transformed later + } + loweredEnumConstructor.valueParameters += valueParameters + loweredEnumConstructor.parent = enumConstructor.parent + + loweredEnumConstructors[enumConstructor.descriptor] = loweredEnumConstructor + + return loweredEnumConstructor } private fun lowerEnumClassBody() { @@ -505,7 +540,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val origin = enumConstructorCall.origin val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, - enumConstructorCall.symbol, enumConstructorCall.descriptor) + context.irBuiltIns.unitType, + enumConstructorCall.symbol, enumConstructorCall.descriptor, enumConstructorCall.typeArgumentsCount) assert(result.descriptor.valueParameters.size == 2) { "Enum(String, Int) constructor call expected:\n${result.dump()}" @@ -519,8 +555,12 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor") } - result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, nameParameter.symbol, origin)) - result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, ordinalParameter.symbol, origin)) + result.putValueArgument(0, + IrGetValueImpl(startOffset, endOffset, nameParameter.type, nameParameter.symbol, origin) + ) + result.putValueArgument(1, + IrGetValueImpl(startOffset, endOffset, ordinalParameter.type, ordinalParameter.symbol, origin) + ) return result } @@ -534,13 +574,15 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor") } - val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, - loweredDelegatedConstructor.symbol, loweredDelegatedConstructor.descriptor) + val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType, + loweredDelegatedConstructor.symbol, loweredDelegatedConstructor.descriptor, 0) + val firstParameter = enumClassConstructor.valueParameters[0] result.putValueArgument(0, - IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[0].symbol)) + IrGetValueImpl(startOffset, endOffset, firstParameter.type, firstParameter.symbol)) + val secondParameter = enumClassConstructor.valueParameters[1] result.putValueArgument(1, - IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[1].symbol)) + IrGetValueImpl(startOffset, endOffset, secondParameter.type, secondParameter.symbol)) descriptor.valueParameters.forEach { valueParameter -> result.putValueArgument(valueParameter.loweredIndex(), delegatingConstructorCall.getValueArgument(valueParameter)) @@ -565,8 +607,10 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val result = createConstructorCall(startOffset, endOffset, loweredConstructor.symbol) - result.putValueArgument(0, IrConstImpl.string(startOffset, endOffset, context.builtIns.stringType, name)) - result.putValueArgument(1, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, ordinal)) + result.putValueArgument(0, + IrConstImpl.string(startOffset, endOffset, context.irBuiltIns.stringType, name)) + result.putValueArgument(1, + IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal)) descriptor.valueParameters.forEach { valueParameter -> val i = valueParameter.index @@ -584,14 +628,25 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { } private inner class InEnumEntryClassConstructor(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) { - override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol) - = IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor, loweredConstructor.descriptor) + override fun createConstructorCall( + startOffset: Int, + endOffset: Int, + loweredConstructor: IrConstructorSymbol + ) = IrDelegatingConstructorCallImpl( + startOffset, + endOffset, + context.irBuiltIns.unitType, + loweredConstructor, + loweredConstructor.descriptor, + 0 + ) } private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) { override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrCall { - return IrCallImpl(startOffset, endOffset, - defaultEnumEntryConstructors[loweredConstructor.descriptor]?.symbol ?: loweredConstructor) + val irConstructorSymbol = defaultEnumEntryConstructors[loweredConstructor.descriptor]?.symbol + ?: loweredConstructor + return IrCallImpl(startOffset, endOffset, irConstructorSymbol.owner.returnType, irConstructorSymbol) } } @@ -668,7 +723,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val loweredEnumConstructor = loweredEnumConstructors[expression.descriptor.containingDeclaration]!! val loweredIrParameter = loweredEnumConstructor.valueParameters[loweredParameter.index] assert(loweredIrParameter.descriptor == loweredParameter) - return IrGetValueImpl(expression.startOffset, expression.endOffset, + return IrGetValueImpl(expression.startOffset, expression.endOffset, loweredIrParameter.type, loweredIrParameter.symbol, expression.origin) } else { return expression @@ -685,9 +740,11 @@ private class ParameterMapper(val originalConstructor: IrConstructor) : IrElemen val descriptor = expression.descriptor when (descriptor) { is ValueParameterDescriptor -> { + val parameter = originalConstructor.valueParameters[descriptor.index] return IrGetValueImpl(expression.startOffset, expression.endOffset, - originalConstructor.valueParameters[descriptor.index].symbol) + parameter.type, + parameter.symbol) } } return expression diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumWhenLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumWhenLowering.kt index c92036262a9..6fff0792493 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumWhenLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumWhenLowering.kt @@ -5,6 +5,8 @@ import org.jetbrains.kotlin.backend.common.peek import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.irasdescriptors.containsNull +import org.jetbrains.kotlin.backend.konan.irasdescriptors.getClass import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin @@ -16,6 +18,7 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.util.getArguments import org.jetbrains.kotlin.ir.util.getPropertyGetter import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -50,11 +53,11 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo } val subject = irBlock.statements[0] as IrVariable // Subject should not be nullable because we will access the `ordinal` property. - if (subject.type.isNullable()) { + if (subject.type.containsNull()) { return false } // Check that subject is enum entry. - val enumClass = subject.type.constructor.declarationDescriptor as? ClassDescriptor + val enumClass = subject.type.getClass() ?: return false return enumClass.kind == ClassKind.ENUM_CLASS } @@ -83,14 +86,22 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo private fun createEnumOrdinalVariable(enumVariable: IrVariable): IrVariable { val ordinalPropertyGetter = context.ir.symbols.enum.getPropertyGetter("ordinal")!! - val getOrdinal = IrCallImpl(enumVariable.startOffset, enumVariable.endOffset, ordinalPropertyGetter).apply { - dispatchReceiver = IrGetValueImpl(enumVariable.startOffset, enumVariable.endOffset, enumVariable.symbol) + val getOrdinal = IrCallImpl( + enumVariable.startOffset, enumVariable.endOffset, + ordinalPropertyGetter.owner.returnType, + ordinalPropertyGetter + ).apply { + dispatchReceiver = IrGetValueImpl( + enumVariable.startOffset, enumVariable.endOffset, + enumVariable.type, enumVariable.symbol + ) } // Create temporary variable for subject's ordinal. val ordinalDescriptor = IrTemporaryVariableDescriptorImpl(enumVariable.descriptor.containingDeclaration, Name.identifier(enumVariable.name.asString() + "_ordinal"), context.builtIns.intType) return IrVariableImpl(enumVariable.startOffset, enumVariable.endOffset, - IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, ordinalDescriptor, getOrdinal) + IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, ordinalDescriptor, + context.irBuiltIns.intType, getOrdinal) } override fun visitCall(expression: IrCall): IrExpression { @@ -100,7 +111,7 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo } private val areEqualByValue = context.ir.symbols.areEqualByValue.first { - it.owner.valueParameters[0].type == context.builtIns.intType + it.owner.valueParameters[0].type.classifierOrNull == context.ir.symbols.int } // We are looking for branch that is a comparison of the subject and another enum entry. @@ -114,19 +125,20 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo } val lhs = callArgs[0].second val rhs = callArgs[1].second - // Both entries should belong to the same class. - if (lhs.type != rhs.type) { - return call - } + // If there is nothing on stack then nothing we can do. val (topmostSubject, topmostOrdinalProvider) = subjectWithOrdinalStack.peek() ?: return call - if (lhs is IrValueAccessExpression && lhs.symbol.owner == topmostSubject && rhs is IrGetEnumValue) { + if (lhs is IrValueAccessExpression && lhs.symbol.owner == topmostSubject && rhs is IrGetEnumValue && + // Both entries should belong to the same class: + topmostSubject.type.classifierOrNull?.owner == rhs.symbol.owner.parent) { val entryOrdinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(rhs.descriptor) val subjectOrdinal = topmostOrdinalProvider.value - return IrCallImpl(call.startOffset, call.endOffset, areEqualByValue).apply { - putValueArgument(0, IrGetValueImpl(lhs.startOffset, lhs.endOffset, subjectOrdinal.symbol)) - putValueArgument(1, IrConstImpl.int(rhs.startOffset, rhs.endOffset, context.builtIns.intType, entryOrdinal)) + return IrCallImpl(call.startOffset, call.endOffset, areEqualByValue.owner.returnType, areEqualByValue).apply { + putValueArgument(0, + IrGetValueImpl(lhs.startOffset, lhs.endOffset, subjectOrdinal.type, subjectOrdinal.symbol)) + putValueArgument(1, + IrConstImpl.int(rhs.startOffset, rhs.endOffset, context.irBuiltIns.intType, entryOrdinal)) } } return call 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 7468b3269d8..40fbcc19b6c 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 @@ -3,10 +3,7 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.MemberDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -79,20 +76,21 @@ internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPa override fun visitGetValue(expression: IrGetValue): IrExpression { expression.transformChildrenVoid() - val newSymbol = remapExpectValueSymbol(expression.symbol) + val newValue = remapExpectValue(expression.symbol) ?: return expression return IrGetValueImpl( expression.startOffset, expression.endOffset, - newSymbol, + newValue.type, + newValue.symbol, expression.origin ) } }, data = null) } - private fun remapExpectValueSymbol(symbol: IrValueSymbol): IrValueParameterSymbol? { + private fun remapExpectValue(symbol: IrValueSymbol): IrValueParameter? { if (symbol !is IrValueParameterSymbol) { return null } @@ -120,6 +118,6 @@ internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPa } else -> error(parent) - }.symbol + } } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt index 6fa668ccdb4..bdf0a2f3d96 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt @@ -36,39 +36,44 @@ import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.types.toKotlinType +import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isUnit internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, IrElementTransformerVoidWithContext() { + private val symbols get() = context.ir.symbols + private interface HighLevelJump { fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression): IrExpression } private data class Return(val target: IrReturnTargetSymbol): HighLevelJump { override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression) - = IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, target, value) + = IrReturnImpl(startOffset, endOffset, context.irBuiltIns.nothingType, target, value) } private data class Break(val loop: IrLoop): HighLevelJump { override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression) - = IrBlockImpl(startOffset, endOffset, context.builtIns.nothingType, null, + = IrBlockImpl(startOffset, endOffset, context.irBuiltIns.nothingType, null, statements = listOf( value, - IrBreakImpl(startOffset, endOffset, context.builtIns.nothingType, loop) + IrBreakImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop) )) } private data class Continue(val loop: IrLoop): HighLevelJump { override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression) - = IrBlockImpl(startOffset, endOffset, context.builtIns.nothingType, null, + = IrBlockImpl(startOffset, endOffset, context.irBuiltIns.nothingType, null, statements = listOf( value, - IrContinueImpl(startOffset, endOffset, context.builtIns.nothingType, loop) + IrContinueImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop) )) } @@ -183,10 +188,11 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir val currentTryScope = tryScopes[index] currentTryScope.jumps.getOrPut(jump) { - val symbol = getIrReturnableBlockSymbol(jump.toString(), value.type) + val type = value.type + val symbol = getIrReturnableBlockSymbol(jump.toString(), type) with(currentTryScope) { irBuilder.run { - val inlinedFinally = irInlineFinally(symbol, expression, finallyExpression) + val inlinedFinally = irInlineFinally(symbol, type, expression, finallyExpression) expression = performHighLevelJump( tryScopes = tryScopes, index = index + 1, @@ -201,7 +207,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir return IrReturnImpl( startOffset = startOffset, endOffset = endOffset, - type = context.builtIns.nothingType, + type = context.irBuiltIns.nothingType, returnTargetSymbol = it, value = value) } @@ -219,7 +225,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir val transformedTry = IrTryImpl( startOffset = startOffset, endOffset = endOffset, - type = context.builtIns.nothingType + type = context.irBuiltIns.nothingType ) val transformedFinallyExpression = finallyExpression.transform(transformer, null) val parameter = IrTemporaryVariableDescriptorImpl( @@ -228,24 +234,26 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir outType = context.builtIns.throwable.defaultType ) val catchParameter = IrVariableImpl( - startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter) + startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter, + symbols.throwable.owner.defaultType) val syntheticTry = IrTryImpl( startOffset = startOffset, endOffset = endOffset, - type = context.builtIns.nothingType, + type = context.irBuiltIns.nothingType, tryResult = transformedTry, catches = listOf( irCatch(catchParameter).apply { result = irBlock { +finallyExpression.copy() - +irThrow(irGet(catchParameter.symbol)) + +irThrow(irGet(catchParameter)) } }), finallyExpression = null ) using(TryScope(syntheticTry, transformedFinallyExpression, this)) { - val fallThroughSymbol = getIrReturnableBlockSymbol("fallThrough", aTry.type) + val fallThroughType = aTry.type + val fallThroughSymbol = getIrReturnableBlockSymbol("fallThrough", fallThroughType) val transformedResult = aTry.tryResult.transform(transformer, null) transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult) for (aCatch in aTry.catches) { @@ -253,28 +261,28 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir transformedCatch.result = irReturn(fallThroughSymbol, transformedCatch.result) transformedTry.catches.add(transformedCatch) } - return irInlineFinally(fallThroughSymbol, it.expression, it.finallyExpression) + return irInlineFinally(fallThroughSymbol, fallThroughType, it.expression, it.finallyExpression) } } } - private fun IrBuilderWithScope.irInlineFinally(symbol: IrReturnableBlockSymbol, + private fun IrBuilderWithScope.irInlineFinally(symbol: IrReturnableBlockSymbol, type: IrType, value: IrExpression, finallyExpression: IrExpression): IrExpression { val returnType = symbol.descriptor.returnType!! return when { - returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, returnType) { - +irReturnableBlock(symbol) { + returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, type) { + +irReturnableBlock(symbol, type) { +value } +finallyExpression.copy() } - else -> irBlock(value, null, returnType) { - val tmp = irTemporary(irReturnableBlock(symbol) { + else -> irBlock(value, null, type) { + val tmp = irTemporary(irReturnableBlock(symbol, type) { +irReturn(symbol, value) }) +finallyExpression.copy() - +irGet(tmp.symbol) + +irGet(tmp) } } } @@ -285,16 +293,16 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir initialize(null, null, emptyList(), emptyList(), returnType, Modality.ABSTRACT, Visibilities.PRIVATE) } - private fun getIrReturnableBlockSymbol(name: String, returnType: KotlinType): IrReturnableBlockSymbol = - IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType)) + private fun getIrReturnableBlockSymbol(name: String, returnType: IrType): IrReturnableBlockSymbol = + IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType.toKotlinType())) private inline fun T.copy() = this.deepCopyWithVariables() fun IrBuilderWithScope.irReturn(target: IrReturnTargetSymbol, value: IrExpression) = - IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, target, value) + IrReturnImpl(startOffset, endOffset, context.irBuiltIns.nothingType, target, value) - inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, body: IrBlockBuilder.() -> Unit) = - IrReturnableBlockImpl(startOffset, endOffset, symbol.descriptor.returnType!!, symbol, null, - IrBlockBuilder(context, scope, startOffset, endOffset, null, symbol.descriptor.returnType!!) + inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, type: IrType, body: IrBlockBuilder.() -> Unit) = + IrReturnableBlockImpl(startOffset, endOffset, type, symbol, null, + IrBlockBuilder(context, scope, startOffset, endOffset, null, type) .block(body).statements) } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ForLoopsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ForLoopsLowering.kt index 4c8d2111d95..804e487abbd 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ForLoopsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ForLoopsLowering.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation @@ -36,6 +37,9 @@ import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.types.makeNotNull +import org.jetbrains.kotlin.ir.types.toKotlinType +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -134,36 +138,40 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo //region Util methods ============================================================================================== private fun IrExpression.castIfNecessary(progressionType: ProgressionType): IrExpression { + val type = this.type.toKotlinType() assert(type in progressionElementClassesTypes || type in progressionElementClassesNullableTypes) return if (type == progressionType.elementType) { this } else { - IrCallImpl(startOffset, endOffset, symbols.getFunction(progressionType.numberCastFunctionName, type)) + val function = symbols.getFunction(progressionType.numberCastFunctionName, type) + IrCallImpl(startOffset, endOffset, function.owner.returnType, function) .apply { dispatchReceiver = this@castIfNecessary } } } private fun DeclarationIrBuilder.ensureNotNullable(expression: IrExpression): IrExpression { - return if (expression.type.isMarkedNullable) { - irImplicitCast(expression, expression.type.makeNotNullable()) + return if (expression.type.isSimpleTypeWithQuestionMark) { + irImplicitCast(expression, expression.type.makeNotNull()) } else { expression } } - private fun IrExpression.unaryMinus(): IrExpression = - IrCallImpl(startOffset, endOffset, symbols.getUnaryOperator(OperatorNameConventions.UNARY_MINUS, type)).apply { - dispatchReceiver = this@unaryMinus - } + private fun IrExpression.unaryMinus(): IrExpression { + val unaryOperator = symbols.getUnaryOperator(OperatorNameConventions.UNARY_MINUS, type.toKotlinType()) + return IrCallImpl(startOffset, endOffset, unaryOperator.owner.returnType, unaryOperator).apply { + dispatchReceiver = this@unaryMinus + } + } private fun ProgressionInfo.defaultStep(startOffset: Int, endOffset: Int): IrExpression = progressionType.elementType.let { type -> val step = if (increasing) 1 else -1 when { KotlinBuiltIns.isInt(type) || KotlinBuiltIns.isChar(type) -> - IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, step) + IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, step) KotlinBuiltIns.isLong(type) -> - IrConstImpl.long(startOffset, endOffset, context.builtIns.longType, step.toLong()) + IrConstImpl.long(startOffset, endOffset, context.irBuiltIns.longType, step.toLong()) else -> throw IllegalArgumentException() } } @@ -178,9 +186,9 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo // Used only by the assert. private fun stepHasRightType(step: IrExpression, progressionType: ProgressionType) = ((progressionType.isCharProgression() || progressionType.isIntProgression()) && - KotlinBuiltIns.isInt(step.type.makeNotNullable())) || + KotlinBuiltIns.isInt(step.type.toKotlinType().makeNotNullable())) || (progressionType.isLongProgression() && - KotlinBuiltIns.isLong(step.type.makeNotNullable())) + KotlinBuiltIns.isLong(step.type.toKotlinType().makeNotNullable())) private fun irCheckProgressionStep(progressionType: ProgressionType, step: IrExpression): Pair { @@ -193,25 +201,25 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo // so there is no need to cast it. assert(stepHasRightType(step, progressionType)) - val symbol = symbols.checkProgressionStep[step.type.makeNotNullable()] + val symbol = symbols.checkProgressionStep[step.type.toKotlinType().makeNotNullable()] ?: throw IllegalArgumentException("Unknown progression element type: ${step.type}") - return IrCallImpl(step.startOffset, step.endOffset, symbol).apply { + return IrCallImpl(step.startOffset, step.endOffset, symbol.owner.returnType, symbol).apply { putValueArgument(0, step) } to true } private fun irGetProgressionLast(progressionType: ProgressionType, - first: IrVariableSymbol, + first: IrVariable, lastExpression: IrExpression, - step: IrVariableSymbol): IrExpression { + step: IrVariable): IrExpression { val symbol = symbols.getProgressionLast[progressionType.elementType] ?: throw IllegalArgumentException("Unknown progression element type: ${lastExpression.type}") val startOffset = lastExpression.startOffset val endOffset = lastExpression.endOffset - return IrCallImpl(startOffset, lastExpression.endOffset, symbol).apply { - putValueArgument(0, IrGetValueImpl(startOffset, endOffset, first)) + return IrCallImpl(startOffset, lastExpression.endOffset, symbol.owner.returnType, symbol).apply { + putValueArgument(0, IrGetValueImpl(startOffset, endOffset, first.type, first.symbol)) putValueArgument(1, lastExpression.castIfNecessary(progressionType)) - putValueArgument(2, IrGetValueImpl(startOffset, endOffset, step)) + putValueArgument(2, IrGetValueImpl(startOffset, endOffset, step.type, step.symbol)) } } //endregion @@ -236,11 +244,11 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo /** Contains information about variables used in the loop. */ private data class ForLoopInfo( val progressionInfo: ProgressionInfo, - val inductionVariable: IrVariableSymbol, - val bound: IrVariableSymbol, - val last: IrVariableSymbol, - val step: IrVariableSymbol, - var loopVariable: IrVariableSymbol? = null) + val inductionVariable: IrVariable, + val bound: IrVariable, + val last: IrVariable, + val step: IrVariable, + var loopVariable: IrVariable? = null) private inner class ProgressionInfoBuilder : IrElementVisitor { @@ -287,7 +295,7 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo override fun visitElement(element: IrElement, data: Nothing?): ProgressionInfo? = null override fun visitCall(expression: IrCall, data: Nothing?): ProgressionInfo? { - val type = expression.type + val type = expression.type.toKotlinType() val progressionType = when { type.isSubtypeOf(symbols.charProgression.descriptor.defaultType) -> CHAR_PROGRESSION type.isSubtypeOf(symbols.intProgression.descriptor.defaultType) -> INT_PROGRESSION @@ -362,15 +370,15 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo var lastExpression: IrExpression? = null if (!closed) { val decrementSymbol = symbols.getUnaryOperator(OperatorNameConventions.DEC, boundValue.descriptor.type) - lastExpression = irCall(decrementSymbol).apply { - dispatchReceiver = irGet(boundValue.symbol) + lastExpression = irCall(decrementSymbol.owner).apply { + dispatchReceiver = irGet(boundValue) } } if (needLastCalculation) { lastExpression = irGetProgressionLast(progressionType, - inductionVariable.symbol, - lastExpression ?: irGet(boundValue.symbol), - stepValue.symbol) + inductionVariable, + lastExpression ?: irGet(boundValue), + stepValue) } val lastValue = if (lastExpression != null) { scope.createTemporaryVariable(lastExpression, @@ -383,12 +391,12 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo } iteratorToLoopInfo[symbol] = ForLoopInfo(progressionInfo, - inductionVariable.symbol, - boundValue.symbol, - lastValue.symbol, - stepValue.symbol) + inductionVariable, + boundValue, + lastValue, + stepValue) - return IrCompositeImpl(startOffset, endOffset, context.builtIns.unitType, null, statements) + return IrCompositeImpl(startOffset, endOffset, context.irBuiltIns.unitType, null, statements) } } } @@ -406,15 +414,15 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo forLoopInfo.inductionVariable.descriptor.type, forLoopInfo.step.descriptor.type ) - forLoopInfo.loopVariable = variable.symbol + forLoopInfo.loopVariable = variable with(builder) { variable.initializer = irGet(forLoopInfo.inductionVariable) val increment = irSetVar(forLoopInfo.inductionVariable, - irCallOp(plusOperator, irGet(forLoopInfo.inductionVariable), irGet(forLoopInfo.step))) + irCallOp(plusOperator.owner, irGet(forLoopInfo.inductionVariable), irGet(forLoopInfo.step))) return IrCompositeImpl(variable.startOffset, variable.endOffset, - context.irBuiltIns.unit, + context.irBuiltIns.unitType, IrStatementOrigin.FOR_LOOP_NEXT, listOf(variable, increment)) } @@ -427,16 +435,16 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo return irCall(context.irBuiltIns.greaterFunByOperandType[context.irBuiltIns.int]?.symbol!!).apply { val minConst = when { progressionType.isIntProgression() -> IrConstImpl - .int(startOffset, endOffset, context.builtIns.intType, Int.MIN_VALUE) + .int(startOffset, endOffset, context.irBuiltIns.intType, Int.MIN_VALUE) progressionType.isCharProgression() -> IrConstImpl - .char(startOffset, endOffset, context.builtIns.charType, 0.toChar()) + .char(startOffset, endOffset, context.irBuiltIns.charType, 0.toChar()) progressionType.isLongProgression() -> IrConstImpl - .long(startOffset, endOffset, context.builtIns.longType, Long.MIN_VALUE) + .long(startOffset, endOffset, context.irBuiltIns.longType, Long.MIN_VALUE) else -> throw IllegalArgumentException("Unknown progression type") } val compareToCall = irCall(symbols.getBinaryOperator(OperatorNameConventions.COMPARE_TO, forLoopInfo.bound.descriptor.type, - minConst.type)).apply { + minConst.type.toKotlinType())).apply { dispatchReceiver = irGet(forLoopInfo.bound) putValueArgument(0, minConst) } @@ -458,7 +466,7 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo forLoopInfo.last.descriptor.type) val check: IrExpression = irCall(comparingBuiltIn!!).apply { - putValueArgument(0, irCallOp(compareTo, irGet(forLoopInfo.inductionVariable), irGet(forLoopInfo.last))) + putValueArgument(0, irCallOp(compareTo.owner, irGet(forLoopInfo.inductionVariable), irGet(forLoopInfo.last))) putValueArgument(1, irInt(0)) } 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 d71fb8acd94..f5462b88579 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 @@ -41,8 +41,9 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.getArguments +import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName @@ -66,7 +67,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW fun inline(irModule: IrModuleFragment): IrElement { val transformedModule = irModule.accept(this, null) - DescriptorSubstitutorForExternalScope(globalSubstituteMap).run(transformedModule) // Transform calls to object that might be returned from inline function call. + DescriptorSubstitutorForExternalScope(globalSubstituteMap, context).run(transformedModule) // Transform calls to object that might be returned from inline function call. return transformedModule } @@ -157,8 +158,8 @@ private class Inliner(val globalSubstituteMap: MutableMap() for (index in 0 until irCall.typeArgumentsCount) { val typeArgument = irCall.getTypeArgument(index) ?: continue - substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument) + substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument.toKotlinType()) } return TypeSubstitutor.create(substitutionContext) } @@ -359,8 +361,9 @@ private class Inliner(val globalSubstituteMap: MutableMap() - functionDescriptor.valueParameters.forEach { parameterDescriptor -> // Iterate value parameter descriptors. - val argument = valueArguments[parameterDescriptor.index] // Get appropriate argument from call site. + irFunction.valueParameters.forEach { parameter -> // Iterate value parameters. + val parameterDescriptor = parameter.descriptor as ValueParameterDescriptor + val argument = valueArguments[parameterDescriptor.index] // Get appropriate argument from call site. when { argument != null -> { // Argument is good enough. parameterToArgument += ParameterToArgument( // Associate current parameter with the argument. @@ -381,8 +384,8 @@ private class Inliner(val globalSubstituteMap: MutableMap() @@ -131,7 +129,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme val superClass = irClass.getSuperClassNotAny()!! val superConstructors = superClass.constructors.filter { constructor.overridesConstructor(it) - } + }.toList() val superConstructor = superConstructors.singleOrNull() ?: run { val annotation = context.interopBuiltIns.objCOverrideInit.name @@ -179,38 +177,42 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme initMethod.name, CallableMemberDescriptor.Kind.DECLARATION, SourceElement.NO_SOURCE - ).apply { - val valueParameters = initMethod.valueParameters.map { - ValueParameterDescriptorImpl( - this, - null, - it.index, - Annotations.EMPTY, - it.name, - it.type, - false, - false, - false, - it.varargElementType, - SourceElement.NO_SOURCE - ) - } - initialize( + ) + + val valueParameters = initMethod.valueParameters.map { + val descriptor = ValueParameterDescriptorImpl( + resultDescriptor, null, - irClass.descriptor.thisAsReceiverParameter, - emptyList(), - valueParameters, - irClass.defaultType, - Modality.OPEN, - Visibilities.PUBLIC + it.index, + Annotations.EMPTY, + it.name, + it.descriptor.type, + false, + false, + false, + it.varargElementType?.toKotlinType(), + SourceElement.NO_SOURCE ) + it.copy(descriptor) } + resultDescriptor.initialize( + null, + irClass.descriptor.thisAsReceiverParameter, + emptyList(), + valueParameters.map { it.descriptor as ValueParameterDescriptor }, + irClass.descriptor.defaultType, + Modality.OPEN, + Visibilities.PUBLIC + ) return IrFunctionImpl( constructor.startOffset, constructor.endOffset, OVERRIDING_INITIALIZER_BY_CONSTRUCTOR, resultDescriptor ).also { result -> - result.createParameterDeclarations() + result.returnType = irClass.defaultType + result.parent = irClass + result.createDispatchReceiverParameter() + result.valueParameters += valueParameters result.overriddenSymbols.add(initMethod.symbol) result.descriptor.overriddenDescriptors = listOf(initMethod.descriptor) @@ -218,10 +220,10 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme result.body = context.createIrBuilder(result.symbol).irBlockBody(result) { +irReturn( irCall(symbols.interopObjCObjectInitBy, listOf(irClass.defaultType)).apply { - extensionReceiver = irGet(result.dispatchReceiverParameter!!.symbol) - putValueArgument(0, irCall(constructor.symbol).also { + extensionReceiver = irGet(result.dispatchReceiverParameter!!) + putValueArgument(0, irCall(constructor).also { result.valueParameters.forEach { parameter -> - it.putValueArgument(parameter.index, irGet(parameter.symbol)) + it.putValueArgument(parameter.index, irGet(parameter)) } }) } @@ -236,9 +238,9 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme IrDeclarationOriginImpl("OVERRIDING_INITIALIZER_BY_CONSTRUCTOR") private fun IrConstructor.overridesConstructor(other: IrConstructor): Boolean { - return this.valueParameters.size == other.valueParameters.size && - this.valueParameters.all { - val otherParameter = other.valueParameters[it.index] + return this.descriptor.valueParameters.size == other.descriptor.valueParameters.size && + this.descriptor.valueParameters.all { + val otherParameter = other.descriptor.valueParameters[it.index] it.name == otherParameter.name && it.type == otherParameter.type } } @@ -260,10 +262,10 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme } } - val returnType = function.descriptor.returnType!! + val returnType = function.returnType if (!returnType.isUnit()) { - context.reportCompilationError("Unexpected $action method return type: $returnType\n" + + context.reportCompilationError("Unexpected $action method return type: ${returnType.toKotlinType()}\n" + "Only 'Unit' is supported here", currentFile, function ) @@ -303,7 +305,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme private fun getMethodSignatureEncoding(function: IrFunction): String { assert(function.extensionReceiverParameter == null) assert(function.valueParameters.all { it.type.isObjCObjectType() }) - assert(function.descriptor.returnType!!.isUnit()) + assert(function.returnType.isUnit()) // Note: these values are valid for x86_64 and arm64. return when (function.valueParameters.size) { @@ -319,10 +321,10 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme private fun generateFunctionImp(selector: String, function: IrFunction): IrSimpleFunction { val signatureEncoding = getMethodSignatureEncoding(function) - val returnType = function.descriptor.returnType!! + val returnType = function.returnType assert(returnType.isUnit()) - val nativePtrType = context.builtIns.nativePtr.defaultType + val nativePtrType = context.ir.symbols.nativePtrType val parameterTypes = mutableListOf(nativePtrType) // id self @@ -353,7 +355,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme index, Annotations.EMPTY, Name.identifier("p$index"), - it, + it.toKotlinType(), false, false, false, @@ -366,7 +368,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme null, null, emptyList(), valueParameters, - returnType, + function.descriptor.returnType, Modality.FINAL, Visibilities.PRIVATE ) @@ -375,20 +377,33 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme function.startOffset, function.endOffset, IrDeclarationOrigin.DEFINED, newDescriptor - ).apply { createParameterDeclarations() } + ).apply { + this.returnType = function.returnType + + parameterTypes.mapIndexedTo(this.valueParameters) { index, it -> + IrValueParameterImpl( + startOffset, + endOffset, + IrDeclarationOrigin.DEFINED, + descriptor.valueParameters[index], + it, + null + ) + } + } val builder = context.createIrBuilder(newFunction.symbol) newFunction.body = builder.irBlockBody(newFunction) { - +irCall(function.symbol).apply { + +irCall(function).apply { dispatchReceiver = interpretObjCPointer( - irGet(newFunction.valueParameters[0].symbol), + irGet(newFunction.valueParameters[0]), function.dispatchReceiverParameter!!.type ) function.valueParameters.forEachIndexed { index, parameter -> putValueArgument(index, interpretObjCPointer( - irGet(newFunction.valueParameters[index + 2].symbol), + irGet(newFunction.valueParameters[index + 2]), parameter.type ) ) @@ -399,8 +414,8 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme return newFunction } - private fun IrBuilderWithScope.interpretObjCPointer(expression: IrExpression, type: KotlinType): IrExpression { - val callee: IrFunctionSymbol = if (TypeUtils.isNullableType(type)) { + private fun IrBuilderWithScope.interpretObjCPointer(expression: IrExpression, type: IrType): IrExpression { + val callee: IrFunctionSymbol = if (type.containsNull()) { symbols.interopInterpretObjCPointerOrNull } else { symbols.interopInterpretObjCPointer @@ -534,7 +549,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme val initCall = builder.genLoweredObjCMethodCall( initMethodInfo, superQualifier = symbolTable.referenceClass(expression.descriptor.constructedClass), - receiver = builder.getRawPtr(builder.irGet(constructedClass.thisReceiver!!.symbol)), + receiver = builder.getRawPtr(builder.irGet(constructedClass.thisReceiver!!)), arguments = initMethod.valueParameters.map { expression.getValueArgument(it)!! } ) @@ -544,10 +559,17 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme return builder.irBlock(expression) { // Required for the IR to be valid, will be ignored in codegen: - +IrDelegatingConstructorCallImpl(startOffset, endOffset, superConstructor, superConstructor.descriptor) + +IrDelegatingConstructorCallImpl( + startOffset, + endOffset, + context.irBuiltIns.unitType, + superConstructor, + superConstructor.descriptor, + 0 + ) +irCall(symbols.interopObjCObjectSuperInitCheck).apply { - extensionReceiver = irGet(constructedClass.thisReceiver!!.symbol) + extensionReceiver = irGet(constructedClass.thisReceiver!!) putValueArgument(0, initCall) } } @@ -560,10 +582,10 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme receiver: IrExpression, arguments: List): IrExpression { val superClass = superQualifier?.let { getObjCClass(it) } ?: - irCall(symbols.getNativeNullPtr) + irCall(symbols.getNativeNullPtr, symbols.nativePtrType) val bridge = symbolTable.referenceSimpleFunction(info.bridge) - return irCall(bridge).apply { + return irCall(bridge, symbolTable.translateErased(info.bridge.returnType!!)).apply { putValueArgument(0, superClass) putValueArgument(1, receiver) @@ -646,18 +668,16 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme return when (descriptor) { context.interopBuiltIns.typeOf -> { val typeArgument = expression.getSingleTypeArgument() - val classDescriptor = TypeUtils.getClassDescriptor(typeArgument) + val classSymbol = typeArgument.classifierOrNull as? IrClassSymbol - if (classDescriptor == null) { + if (classSymbol == null) { expression } else { - val companionObjectDescriptor = classDescriptor.companionObjectDescriptor ?: + val classDescriptor = classSymbol.descriptor + val companionObject = classDescriptor.companionObjectDescriptor ?: error("native variable class $classDescriptor must have the companion object") - IrGetObjectValueImpl( - expression.startOffset, expression.endOffset, companionObjectDescriptor.defaultType, - symbolTable.referenceClass(companionObjectDescriptor) - ) + builder.at(expression).irGetObject(symbolTable.referenceClass(companionObject)) } } else -> expression @@ -674,14 +694,14 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme val initCall = genLoweredObjCMethodCall( initMethodInfo, superQualifier = null, - receiver = irGet(allocated.symbol), + receiver = irGet(allocated), arguments = arguments ) +IrTryImpl(startOffset, endOffset, initCall.type).apply { tryResult = initCall finallyExpression = irCall(symbols.interopObjCRelease).apply { - putValueArgument(0, irGet(allocated.symbol)) // Balance pointer retained by alloc. + putValueArgument(0, irGet(allocated)) // Balance pointer retained by alloc. } } } @@ -770,8 +790,8 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB } val targetSymbol = irCallableReference.symbol - val target = targetSymbol.descriptor - val signatureTypes = target.allParameters.map { it.type } + target.returnType!! + val target = targetSymbol.owner + val signatureTypes = target.allParameters.map { it.type } + target.returnType signatureTypes.forEachIndexed { index, type -> type.ensureSupportedInCallbacks( @@ -781,9 +801,10 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB } descriptor.typeParameters.forEachIndexed { index, typeParameterDescriptor -> - val typeArgument = expression.getTypeArgument(typeParameterDescriptor)!! - val signatureType = signatureTypes[index] - if (typeArgument != signatureType) { + val typeArgument = expression.getTypeArgument(typeParameterDescriptor)!!.toKotlinType() + val signatureType = signatureTypes[index].toKotlinType() + if (typeArgument.constructor != signatureType.constructor || + typeArgument.isMarkedNullable != signatureType.isMarkedNullable) { context.reportCompilationError( "C function signature element mismatch: expected '$signatureType', got '$typeArgument'", irFile, expression @@ -794,8 +815,8 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB IrFunctionReferenceImpl( builder.startOffset, builder.endOffset, expression.type, - targetSymbol, target, - typeArguments = null) + targetSymbol, target.descriptor, + typeArgumentsCount = 0) } interop.scheduleFunction -> { @@ -812,9 +833,9 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB val target = targetSymbol.descriptor val jobPointer = IrFunctionReferenceImpl( builder.startOffset, builder.endOffset, - interop.cPointer.defaultType, + symbols.scheduleImpl.owner.valueParameters[3].type, targetSymbol, target, - typeArguments = null) + typeArgumentsCount = 0) builder.irCall(symbols.scheduleImpl).apply { putValueArgument(0, expression.dispatchReceiver) @@ -827,33 +848,36 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB interop.signExtend, interop.narrow -> { val integerTypePredicates = arrayOf( - KotlinBuiltIns::isByte, KotlinBuiltIns::isShort, KotlinBuiltIns::isInt, KotlinBuiltIns::isLong + IrType::isByte, IrType::isShort, IrType::isInt, IrType::isLong ) val receiver = expression.extensionReceiver!! val typeOperand = expression.getSingleTypeArgument() + val kotlinTypeOperand = typeOperand.toKotlinType() val receiverTypeIndex = integerTypePredicates.indexOfFirst { it(receiver.type) } val typeOperandIndex = integerTypePredicates.indexOfFirst { it(typeOperand) } + val receiverKotlinType = receiver.type.toKotlinType() + if (receiverTypeIndex == -1) { - context.reportCompilationError("Receiver's type ${receiver.type} is not an integer type", + context.reportCompilationError("Receiver's type $receiverKotlinType is not an integer type", irFile, receiver) } if (typeOperandIndex == -1) { - context.reportCompilationError("Type argument $typeOperand is not an integer type", + context.reportCompilationError("Type argument $kotlinTypeOperand is not an integer type", irFile, expression) } when (descriptor) { interop.signExtend -> if (receiverTypeIndex > typeOperandIndex) { - context.reportCompilationError("unable to sign extend ${receiver.type} to $typeOperand", + context.reportCompilationError("unable to sign extend $receiverKotlinType to $kotlinTypeOperand", irFile, expression) } interop.narrow -> if (receiverTypeIndex < typeOperandIndex) { - context.reportCompilationError("unable to narrow ${receiver.type} to $typeOperand", + context.reportCompilationError("unable to narrow $receiverKotlinType to $kotlinTypeOperand", irFile, expression) } @@ -863,8 +887,12 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB val receiverClass = symbols.integerClasses.single { receiver.type.isSubtypeOf(it.owner.defaultType) } + val targetClass = symbols.integerClasses.single { + typeOperand.isSubtypeOf(it.owner.defaultType) + } + val conversionSymbol = receiverClass.functions.single { - it.descriptor.name == Name.identifier("to$typeOperand") + it.descriptor.name == Name.identifier("to${targetClass.owner.name}") } builder.irCall(conversionSymbol).apply { @@ -880,16 +908,16 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB returnType.checkCTypeNullability(::reportError) - val invokeImpl = symbols.interopInvokeImpls[TypeUtils.getClassDescriptor(returnType)] ?: + val invokeImpl = symbols.interopInvokeImpls[returnType.getClass()?.descriptor] ?: context.reportCompilationError( - "Invocation of C function pointer with return type '$returnType' is not supported yet", + "Invocation of C function pointer with return type '${returnType.toKotlinType()}' is not supported yet", irFile, expression ) builder.irCall(invokeImpl).apply { putValueArgument(0, expression.extensionReceiver) - val varargParameter = invokeImpl.descriptor.valueParameters[1] + val varargParameter = invokeImpl.owner.valueParameters[1] val varargArgument = IrVarargImpl( startOffset, endOffset, varargParameter.type, varargParameter.varargElementType!! ).apply { @@ -897,7 +925,7 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB this.addElement(expression.getValueArgument(it)!!) } } - putValueArgument(varargParameter, varargArgument) + putValueArgument(varargParameter.index, varargArgument) } } @@ -928,31 +956,31 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB } } - private fun KotlinType.ensureSupportedInCallbacks(isReturnType: Boolean, reportError: (String) -> Nothing) { + private fun IrType.ensureSupportedInCallbacks(isReturnType: Boolean, reportError: (String) -> Nothing) { this.checkCTypeNullability(reportError) - if (isReturnType && KotlinBuiltIns.isUnit(this)) { + if (isReturnType && this.isUnit()) { return } - if (KotlinBuiltIns.isPrimitiveType(this)) { + if (this.isPrimitiveType()) { return } - if (TypeUtils.getClassDescriptor(this) == interop.cPointer) { + if (this.getClass()?.descriptor == interop.cPointer) { return } - reportError("Type $this is not supported in callback signature") + reportError("Type ${this.toKotlinType()} is not supported in callback signature") } - private fun KotlinType.checkCTypeNullability(reportError: (String) -> Nothing) { - if (KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType(this) && this.isMarkedNullable) { - reportError("Type $this must not be nullable when used in C function signature") + private fun IrType.checkCTypeNullability(reportError: (String) -> Nothing) { + if (this.isNullablePrimitiveType()) { + reportError("Type ${this.toKotlinType()} must not be nullable when used in C function signature") } - if (TypeUtils.getClassDescriptor(this) == interop.cPointer && !this.isMarkedNullable) { - reportError("Type $this must be nullable when used in C function signature") + if (this.getClass() == interop.cPointer && !this.isSimpleTypeWithQuestionMark) { + reportError("Type ${this.toKotlinType()} must be nullable when used in C function signature") } } @@ -986,15 +1014,15 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB } } -private fun IrCall.getSingleTypeArgument(): KotlinType { +private fun IrCall.getSingleTypeArgument(): IrType { val typeParameter = descriptor.original.typeParameters.single() return getTypeArgument(typeParameter)!! } private fun IrBuilder.irFloat(value: Float) = - IrConstImpl.float(startOffset, endOffset, context.builtIns.floatType, value) + IrConstImpl.float(startOffset, endOffset, context.irBuiltIns.floatType, value) private fun IrBuilder.irDouble(value: Double) = - IrConstImpl.double(startOffset, endOffset, context.builtIns.doubleType, value) + IrConstImpl.double(startOffset, endOffset, context.irBuiltIns.doubleType, value) private fun Annotations.hasAnnotation(descriptor: ClassDescriptor) = this.hasAnnotation(descriptor.fqNameSafe) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt index 058577c1cac..7c8a47467ab 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt @@ -21,23 +21,23 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.IrProperty -import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.IrPropertyReference import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl -import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor @@ -59,6 +59,21 @@ internal class LateinitLowering( private val isInitializedGetterDescriptor = isInitializedPropertyDescriptor.getter!! override fun lower(irFile: IrFile) { + val lateinitPropertyToField = mutableMapOf() + irFile.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitProperty(declaration: IrProperty) { + super.visitProperty(declaration) + + if (declaration.isLateinit && declaration.descriptor.kind.isReal) { + lateinitPropertyToField[declaration.descriptor] = declaration.backingField!! + } + } + }) + irFile.transformChildrenVoid(object : IrBuildingTransformer(context) { override fun visitVariable(declaration: IrVariable): IrStatement { @@ -85,10 +100,10 @@ internal class LateinitLowering( return irBlock(expression) { // TODO: do data flow analysis to check if value is proved to be not-null. +irIfThen( - irEqualsNull(irGet(symbol)), + irEqualsNull(irGet(expression.type, symbol)), throwUninitializedPropertyAccessException(symbol) ) - +irGet(symbol) + +irGet(expression.type, symbol) } } } @@ -101,19 +116,13 @@ internal class LateinitLowering( val propertyReference = expression.extensionReceiver!! as IrPropertyReference assert(propertyReference.extensionReceiver == null, { "'lateinit' modifier is not allowed on extension properties" }) - // TODO: Take propertyReference.fieldSymbol as soon as it will show up in IR. val propertyDescriptor = propertyReference.descriptor.resolveFakeOverride().original val type = propertyDescriptor.type assert(!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" }) builder.at(expression).run { - @Suppress("DEPRECATION") - val fieldValue = IrGetFieldImpl( - expression.startOffset, - expression.endOffset, - propertyDescriptor, - propertyReference.dispatchReceiver - ) + val field = lateinitPropertyToField[propertyDescriptor]!! + val fieldValue = irGetField(propertyReference.dispatchReceiver, field) return irNotEquals(fieldValue, irNull()) } } @@ -125,7 +134,7 @@ internal class LateinitLowering( return declaration val backingField = declaration.backingField!! - transformGetter(backingField.symbol, declaration.getter!!) + transformGetter(backingField, declaration.getter!!) assert(backingField.initializer == null, { "'lateinit' modifier is not allowed for properties with initializer" }) val irBuilder = context.createIrBuilder(backingField.symbol, declaration.startOffset, declaration.endOffset) @@ -136,20 +145,20 @@ internal class LateinitLowering( return declaration } - private fun transformGetter(backingFieldSymbol: IrFieldSymbol, getter: IrFunction) { - val type = backingFieldSymbol.descriptor.type + private fun transformGetter(backingField: IrField, getter: IrFunction) { + val type = backingField.descriptor.type assert(!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" }) val irBuilder = context.createIrBuilder(getter.symbol, getter.startOffset, getter.endOffset) irBuilder.run { getter.body = irBlockBody { val resultVar = irTemporary( - irGetField(getter.dispatchReceiverParameter?.let { irGet(it.symbol) }, backingFieldSymbol) + irGetField(getter.dispatchReceiverParameter?.let { irGet(it) }, backingField) ) +irIfThenElse( - context.builtIns.nothingType, - irNotEquals(irGet(resultVar.symbol), irNull()), - irReturn(irGet(resultVar.symbol)), - throwUninitializedPropertyAccessException(backingFieldSymbol) + context.irBuiltIns.nothingType, + irNotEquals(irGet(resultVar), irNull()), + irReturn(irGet(resultVar)), + throwUninitializedPropertyAccessException(backingField.symbol) ) } } @@ -158,14 +167,14 @@ internal class LateinitLowering( } private fun IrBuilderWithScope.throwUninitializedPropertyAccessException(backingFieldSymbol: IrSymbol) = - irCall(throwErrorFunction).apply { + irCall(throwErrorFunction, context.irBuiltIns.nothingType).apply { if (generateParameterNameInAssertion) { putValueArgument( 0, IrConstImpl.string( startOffset, endOffset, - context.builtIns.stringType, + context.irBuiltIns.stringType, backingFieldSymbol.descriptor.name.asString() ) ) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LocalDeclarationsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LocalDeclarationsLowering.kt deleted file mode 100644 index d7f4589cc1c..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LocalDeclarationsLowering.kt +++ /dev/null @@ -1,754 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.konan.lower - -import org.jetbrains.kotlin.backend.common.BackendContext -import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass -import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName -import org.jetbrains.kotlin.backend.common.lower.Closure -import org.jetbrains.kotlin.backend.common.lower.ClosureAnnotator -import org.jetbrains.kotlin.backend.common.lower.callsSuper -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.* -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.* -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.util.addChild -import org.jetbrains.kotlin.ir.util.createParameterDeclarations -import org.jetbrains.kotlin.ir.util.transformFlat -import org.jetbrains.kotlin.ir.visitors.* -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.parents -import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf -import org.jetbrains.kotlin.types.KotlinType -import java.util.* - -// TODO: Remove as soon as its version is fixed in common code. -class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContainerLoweringPass { - - private object DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE : - IrDeclarationOriginImpl("FIELD_FOR_CAPTURED_VALUE") {} - - private object STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE : - IrStatementOriginImpl("INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE") {} - - override fun lower(irDeclarationContainer: IrDeclarationContainer) { - if (irDeclarationContainer is IrDeclaration && - irDeclarationContainer.descriptor.parents.any { it is CallableDescriptor }) { - - // Lowering of non-local declarations handles all local declarations inside. - // This declaration is local and shouldn't be considered. - return - } - - // Continuous numbering across all declarations in the container. - lambdasCount = 0 - - irDeclarationContainer.declarations.transformFlat { memberDeclaration -> - // TODO: may be do the opposite - specify the list of IR elements which need not to be transformed - when (memberDeclaration) { - is IrFunction -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() - is IrProperty -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() - is IrField -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() - is IrAnonymousInitializer -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() - else -> null - } - } - } - - private var lambdasCount = 0 - - private abstract class LocalContext { - /** - * @return the expression to get the value for given descriptor, or `null` if [IrGetValue] should be used. - */ - abstract fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? - } - - private abstract class LocalContextWithClosureAsParameters : LocalContext() { - - abstract val declaration: IrFunction - open val descriptor: FunctionDescriptor - get() = declaration.descriptor - - abstract val transformedDescriptor: FunctionDescriptor - abstract val transformedDeclaration: IrFunction - - val capturedValueToParameter: MutableMap = HashMap() - - override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { - val newSymbol = capturedValueToParameter[descriptor] ?: return null - - return IrGetValueImpl(startOffset, endOffset, newSymbol) - } - } - - private class LocalFunctionContext(override val declaration: IrFunction) : LocalContextWithClosureAsParameters() { - lateinit var closure: Closure - - override lateinit var transformedDescriptor: FunctionDescriptor - override lateinit var transformedDeclaration: IrSimpleFunction - - var index: Int = -1 - - override fun toString(): String = - "LocalFunctionContext for $descriptor" - } - - private class LocalClassConstructorContext(override val declaration: IrConstructor) : LocalContextWithClosureAsParameters() { - override val descriptor: ClassConstructorDescriptor - get() = declaration.descriptor - - override lateinit var transformedDescriptor: ClassConstructorDescriptor - override lateinit var transformedDeclaration: IrConstructor - - override fun toString(): String = - "LocalClassConstructorContext for $descriptor" - } - - private class LocalClassContext(val declaration: IrClass) : LocalContext() { - val descriptor: ClassDescriptor - get() = declaration.descriptor - - lateinit var closure: Closure - - val capturedValueToField: MutableMap = HashMap() - - override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { - val field = capturedValueToField[descriptor] ?: return null - - return IrGetFieldImpl(startOffset, endOffset, field.symbol, - receiver = IrGetValueImpl(startOffset, endOffset, declaration.thisReceiver!!.symbol) - ) - } - - override fun toString(): String = - "LocalClassContext for ${descriptor}" - } - - private class LocalClassMemberContext(val member: IrFunction, val classContext: LocalClassContext) : LocalContext() { - override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { - val field = classContext.capturedValueToField[descriptor] ?: return null - - return IrGetFieldImpl(startOffset, endOffset, field.symbol, - receiver = IrGetValueImpl(startOffset, endOffset, member.dispatchReceiverParameter!!.symbol) - ) - } - - } - - private inner class LocalDeclarationsTransformer(val memberDeclaration: IrDeclaration) { - val localFunctions: MutableMap = LinkedHashMap() - val localClasses: MutableMap = LinkedHashMap() - val localClassConstructors: MutableMap = LinkedHashMap() - - val transformedDeclarations = mutableMapOf() - - val FunctionDescriptor.transformed: IrFunctionSymbol? - get() = transformedDeclarations[this] as IrFunctionSymbol? - - val oldParameterToNew: MutableMap = HashMap() - val newParameterToOld: MutableMap = HashMap() - val newParameterToCaptured: MutableMap = HashMap() - - fun lowerLocalDeclarations(): List? { - collectLocalDeclarations() - if (localFunctions.isEmpty() && localClasses.isEmpty()) return null - - collectClosures() - - transformDescriptors() - - rewriteDeclarations() - - val result = collectRewrittenDeclarations() - result.forEach { it.parent = memberDeclaration.parent } - return result - } - - private fun collectRewrittenDeclarations(): ArrayList = - ArrayList(localFunctions.size + localClasses.size + 1).apply { - add(memberDeclaration) - - localFunctions.values.mapTo(this) { - val original = it.declaration - it.transformedDeclaration.apply { - this.body = original.body - - original.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> - val body = original.getDefault(argument)!! - oldParameterToNew[argument]!!.owner.defaultValue = body - } - } - } - - localClasses.values.mapTo(this) { - it.declaration - } - } - - private inner class FunctionBodiesRewriter(val localContext: LocalContext?) : IrElementTransformerVoid() { - - override fun visitClass(declaration: IrClass): IrStatement { - if (declaration.descriptor in localClasses) { - // Replace local class definition with an empty composite. - return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType) - } else { - return super.visitClass(declaration) - } - } - - override fun visitFunction(declaration: IrFunction): IrStatement { - if (declaration.descriptor in localFunctions) { - // Replace local function definition with an empty composite. - return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType) - } else { - if (localContext is LocalClassContext && declaration.parent == localContext.declaration) { - return declaration.apply { - val classMemberLocalContext = LocalClassMemberContext(declaration, localContext) - transformChildrenVoid(FunctionBodiesRewriter(classMemberLocalContext)) - } - } else { - return super.visitFunction(declaration) - } - } - } - - override fun visitConstructor(declaration: IrConstructor): IrStatement { - // Body is transformed separately. See loop over constructors in rewriteDeclarations(). - - val constructorContext = localClassConstructors[declaration.descriptor] - if (constructorContext != null) { - return constructorContext.transformedDeclaration.apply { - this.parent = declaration.parent - this.body = declaration.body!! - - declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> - val body = declaration.getDefault(argument)!! - oldParameterToNew[argument]!!.owner.defaultValue = body - } - } - } else { - return super.visitConstructor(declaration) - } - } - - override fun visitGetValue(expression: IrGetValue): IrExpression { - val descriptor = expression.descriptor - - localContext?.irGet(expression.startOffset, expression.endOffset, descriptor)?.let { - return it - } - - oldParameterToNew[descriptor]?.let { - return IrGetValueImpl(expression.startOffset, expression.endOffset, it) - } - - return expression - } - - override fun visitCall(expression: IrCall): IrExpression { - expression.transformChildrenVoid(this) - - val oldCallee = expression.descriptor.original - val newCallee = oldCallee.transformed ?: return expression - - val newCall = createNewCall(expression, newCallee).fillArguments(expression) - - return newCall - } - - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { - expression.transformChildrenVoid(this) - - val oldCallee = expression.descriptor.original - val newCallee = transformedDeclarations[oldCallee] as IrConstructorSymbol? ?: return expression - - val newExpression = IrDelegatingConstructorCallImpl( - expression.startOffset, expression.endOffset, - newCallee, - newCallee.descriptor, - remapTypeArguments(expression, newCallee.descriptor) - ).fillArguments(expression) - - return newExpression - } - - private fun T.fillArguments(oldExpression: IrMemberAccessExpression): T { - - mapValueParameters { newValueParameterDescriptor -> - val oldParameter = newParameterToOld[newValueParameterDescriptor] - - if (oldParameter != null) { - oldExpression.getValueArgument(oldParameter as ValueParameterDescriptor) - } else { - // The callee expects captured value as argument. - val capturedValueSymbol = - newParameterToCaptured[newValueParameterDescriptor] ?: - throw AssertionError("Non-mapped parameter $newValueParameterDescriptor") - - val capturedValueDescriptor = capturedValueSymbol.descriptor - localContext?.irGet( - oldExpression.startOffset, oldExpression.endOffset, - capturedValueDescriptor - ) ?: - // Captured value is directly available for the caller. - IrGetValueImpl(oldExpression.startOffset, oldExpression.endOffset, - oldParameterToNew[capturedValueDescriptor] ?: capturedValueSymbol) - } - - } - - dispatchReceiver = oldExpression.dispatchReceiver - extensionReceiver = oldExpression.extensionReceiver - - return this - } - - override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { - expression.transformChildrenVoid(this) - - val oldCallee = expression.descriptor.original - val newCallee = oldCallee.transformed ?: return expression - - val newCallableReference = IrFunctionReferenceImpl( - expression.startOffset, expression.endOffset, - expression.type, // TODO functional type for transformed descriptor - newCallee, - newCallee.descriptor, - remapTypeArguments(expression, newCallee.descriptor), - expression.origin - ).fillArguments(expression) - - return newCallableReference - } - - override fun visitReturn(expression: IrReturn): IrExpression { - expression.transformChildrenVoid(this) - - val oldReturnTarget = expression.returnTarget - val newReturnTarget = oldReturnTarget.transformed ?: return expression - - return IrReturnImpl(expression.startOffset, expression.endOffset, newReturnTarget, expression.value) - } - - override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression { - if (expression.descriptor in transformedDeclarations) { - TODO() - } - return super.visitDeclarationReference(expression) - } - - override fun visitDeclaration(declaration: IrDeclaration): IrStatement { - if (declaration.descriptor in transformedDeclarations) { - TODO() - } - return super.visitDeclaration(declaration) - } - } - - private fun rewriteFunctionBody(irDeclaration: IrDeclaration, localContext: LocalContext?) { - irDeclaration.transformChildrenVoid(FunctionBodiesRewriter(localContext)) - } - - private fun rewriteClassMembers(irClass: IrClass, localClassContext: LocalClassContext) { - irClass.transformChildrenVoid(FunctionBodiesRewriter(localClassContext)) - - val classDescriptor = irClass.descriptor - val constructorsCallingSuper = classDescriptor.constructors - .map { localClassConstructors[it]!! } - .filter { it.declaration.callsSuper() } - assert(constructorsCallingSuper.any(), { "Expected at least one constructor calling super; class: $classDescriptor" }) - - localClassContext.capturedValueToField.forEach { capturedValue, field -> - val startOffset = irClass.startOffset - val endOffset = irClass.endOffset - irClass.addChild(field) - - for (constructorContext in constructorsCallingSuper) { - val blockBody = constructorContext.declaration.body as? IrBlockBody - ?: throw AssertionError("Unexpected constructor body: ${constructorContext.declaration.body}") - val capturedValueExpression = constructorContext.irGet(startOffset, endOffset, capturedValue)!! - blockBody.statements.add(0, - IrSetFieldImpl(startOffset, endOffset, field.symbol, - IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol), - capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE)) - } - } - } - - private fun rewriteDeclarations() { - localFunctions.values.forEach { - rewriteFunctionBody(it.declaration, it) - } - - localClassConstructors.values.forEach { - rewriteFunctionBody(it.declaration, it) - } - - localClasses.values.forEach { - rewriteClassMembers(it.declaration, it) - } - - rewriteFunctionBody(memberDeclaration, null) - } - - private fun createNewCall(oldCall: IrCall, newCallee: IrFunctionSymbol) = - if (oldCall is IrCallWithShallowCopy) - oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifierSymbol) - else - IrCallImpl( - oldCall.startOffset, oldCall.endOffset, - newCallee, - newCallee.descriptor, - remapTypeArguments(oldCall, newCallee.descriptor), - oldCall.origin, oldCall.superQualifierSymbol - ) - - private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: CallableDescriptor): Map? { - val oldCallee = oldExpression.descriptor.original - - return if (oldCallee.typeParameters.isEmpty()) - null - else oldCallee.typeParameters.associateBy( - { newCallee.typeParameters[it.index] }, - { oldExpression.getTypeArgumentOrDefault(it) } - ) - } - - private fun transformDescriptors() { - localFunctions.values.forEach { - createLiftedDescriptor(it) - } - - localClasses.values.forEach { - createFieldsForCapturedValues(it) - } - - localClassConstructors.values.forEach { - createTransformedConstructorDescriptor(it) - } - } - - private fun suggestLocalName(descriptor: DeclarationDescriptor): String { - localFunctions[descriptor]?.let { - if (it.index >= 0) - return "lambda-${it.index}" - } - - return descriptor.name.asString() - } - - private fun generateNameForLiftedDeclaration(descriptor: DeclarationDescriptor, - newOwner: DeclarationDescriptor): Name = - Name.identifier( - descriptor.parentsWithSelf - .takeWhile { it != newOwner } - .toList().reversed() - .map { suggestLocalName(it) } - .joinToString(separator = "$") - ) - - private fun createLiftedDescriptor(localFunctionContext: LocalFunctionContext) { - val oldDescriptor = localFunctionContext.descriptor - - val memberOwner = memberDeclaration.descriptor.containingDeclaration!! - val newDescriptor = SimpleFunctionDescriptorImpl.create( - memberOwner, - oldDescriptor.annotations, - generateNameForLiftedDeclaration(oldDescriptor, memberOwner), - CallableMemberDescriptor.Kind.SYNTHESIZED, - oldDescriptor.source - ).apply { - isTailrec = oldDescriptor.isTailrec - isSuspend = oldDescriptor.isSuspend - // TODO: copy other properties or consider using `FunctionDescriptor.CopyBuilder`. - } - - localFunctionContext.transformedDescriptor = newDescriptor - - if (oldDescriptor.dispatchReceiverParameter != null) { - throw AssertionError("local functions must not have dispatch receiver") - } - - val newDispatchReceiverParameter = null - - // Do not substitute type parameters for now. - val newTypeParameters = oldDescriptor.typeParameters - - // TODO: consider using fields to access the closure of enclosing class. - val capturedValues = localFunctionContext.closure.capturedValues - - val newValueParameters = createTransformedValueParameters(localFunctionContext, capturedValues) - - newDescriptor.initialize( - oldDescriptor.extensionReceiverParameter?.type, - newDispatchReceiverParameter, - newTypeParameters, - newValueParameters, - oldDescriptor.returnType, - Modality.FINAL, - Visibilities.PRIVATE - ) - - oldDescriptor.extensionReceiverParameter?.let { - newParameterToOld.putAbsentOrSame(newDescriptor.extensionReceiverParameter!!, it) - } - - localFunctionContext.transformedDeclaration = with(localFunctionContext.declaration) { - IrFunctionImpl(startOffset, endOffset, origin, newDescriptor) - }.apply { - createParameterDeclarations() - recordTransformedValueParameters(localFunctionContext) - transformedDeclarations[oldDescriptor] = this.symbol - } - } - - private fun createTransformedValueParameters(localContext: LocalContextWithClosureAsParameters, - capturedValues: List) - : List { - - val oldDescriptor = localContext.descriptor - val newDescriptor = localContext.transformedDescriptor - - val closureParametersCount = capturedValues.size - val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size - - val newValueParameters = ArrayList(newValueParametersCount).apply { - capturedValues.mapIndexedTo(this) { i, capturedValue -> - createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply { - newParameterToCaptured[this] = capturedValue - } - } - - oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor -> - createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply { - newParameterToOld.putAbsentOrSame(this, oldValueParameterDescriptor) - } - } - } - return newValueParameters - } - - private fun IrFunction.recordTransformedValueParameters(localContext: LocalContextWithClosureAsParameters) { - - valueParameters.forEach { - val capturedValue = newParameterToCaptured[it.descriptor] - if (capturedValue != null) { - localContext.capturedValueToParameter[capturedValue.descriptor] = it.symbol - } - } - - (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).forEach { - val oldParameter = newParameterToOld[it.descriptor] - if (oldParameter != null) { - oldParameterToNew.putAbsentOrSame(oldParameter, it.symbol) - } - } - - } - - private fun createTransformedConstructorDescriptor(constructorContext: LocalClassConstructorContext) { - val oldDescriptor = constructorContext.descriptor - val localClassContext = localClasses[oldDescriptor.containingDeclaration]!! - val newDescriptor = ClassConstructorDescriptorImpl.create( - localClassContext.descriptor, - Annotations.EMPTY, oldDescriptor.isPrimary, oldDescriptor.source) - - constructorContext.transformedDescriptor = newDescriptor - - // Do not substitute type parameters for now. - val newTypeParameters = oldDescriptor.typeParameters - - val capturedValues = localClasses[oldDescriptor.containingDeclaration]!!.closure.capturedValues - - val newValueParameters = createTransformedValueParameters(constructorContext, capturedValues) - - newDescriptor.initialize( - newValueParameters, - Visibilities.PRIVATE, - newTypeParameters - ) - newDescriptor.returnType = oldDescriptor.returnType - - oldDescriptor.dispatchReceiverParameter?.let { - newParameterToOld.putAbsentOrSame(newDescriptor.dispatchReceiverParameter!!, it) - } - - oldDescriptor.extensionReceiverParameter?.let { - throw AssertionError("constructors can't have extension receiver") - } - - constructorContext.transformedDeclaration = with(constructorContext.declaration) { - IrConstructorImpl(startOffset, endOffset, origin, newDescriptor) - }.apply { - createParameterDeclarations() - recordTransformedValueParameters(constructorContext) - transformedDeclarations[oldDescriptor] = this.symbol - } - } - - private fun createFieldsForCapturedValues(localClassContext: LocalClassContext) { - val classDescriptor = localClassContext.descriptor - - localClassContext.closure.capturedValues.forEach { capturedValue -> - val fieldDescriptor = PropertyDescriptorImpl.create( - classDescriptor, - Annotations.EMPTY, - Modality.FINAL, - Visibilities.PRIVATE, - /* isVar = */ false, - suggestNameForCapturedValue(capturedValue.descriptor), - CallableMemberDescriptor.Kind.SYNTHESIZED, - SourceElement.NO_SOURCE, - /* lateInit = */ false, - /* isConst = */ false, - /* isExpect = */ false, - /* isActual = */ false, - /* isExternal = */ false, - /* isDelegated = */ false) - - fieldDescriptor.initialize(/* getter = */ null, /* setter = */ null) - - val extensionReceiverParameter: ReceiverParameterDescriptor? = null - - fieldDescriptor.setType( - capturedValue.descriptor.type, - emptyList(), - classDescriptor.thisAsReceiverParameter, - extensionReceiverParameter) - - localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl( - localClassContext.declaration.startOffset, localClassContext.declaration.endOffset, - DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE, - fieldDescriptor - ) - } - } - - private fun MutableMap.putAbsentOrSame(key: K, value: V) { - val current = this.getOrPut(key, { value }) - - if (current != value) { - error("$current != $value") - } - } - - private fun suggestNameForCapturedValue(valueDescriptor: ValueDescriptor): Name = - if (valueDescriptor.name.isSpecial) { - val oldNameStr = valueDescriptor.name.asString() - oldNameStr.substring(1, oldNameStr.length - 1).synthesizedName - } else - valueDescriptor.name - - private fun createUnsubstitutedCapturedValueParameter( - newParameterOwner: CallableMemberDescriptor, - valueDescriptor: ValueDescriptor, - index: Int - ): ValueParameterDescriptor = - ValueParameterDescriptorImpl( - newParameterOwner, null, index, - valueDescriptor.annotations, - suggestNameForCapturedValue(valueDescriptor), - valueDescriptor.type, - false, false, false, null, valueDescriptor.source - ) - - private fun createUnsubstitutedParameter( - newParameterOwner: CallableMemberDescriptor, - valueParameterDescriptor: ValueParameterDescriptor, - newIndex: Int - ): ValueParameterDescriptor = - valueParameterDescriptor.copy(newParameterOwner, valueParameterDescriptor.name, newIndex) - - - private fun collectClosures() { - val annotator = ClosureAnnotator(memberDeclaration) - localFunctions.forEach { descriptor, context -> - context.closure = annotator.getFunctionClosure(descriptor) - } - - localClasses.forEach { descriptor, context -> - context.closure = annotator.getClassClosure(descriptor) - } - } - - private fun collectLocalDeclarations() { - memberDeclaration.acceptChildrenVoid(object : IrElementVisitorVoid { - - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - private fun ClassDescriptor.declaredInFunction() = when (this.containingDeclaration) { - is CallableDescriptor -> true - is ClassDescriptor -> false - is PackageFragmentDescriptor -> false - else -> TODO(this.toString() + "\n" + this.containingDeclaration.toString()) - } - - override fun visitFunction(declaration: IrFunction) { - declaration.acceptChildrenVoid(this) - - val descriptor = declaration.descriptor - - if (descriptor.visibility == Visibilities.LOCAL) { - val localFunctionContext = LocalFunctionContext(declaration) - - localFunctions[descriptor] = localFunctionContext - - if (descriptor.name.isSpecial) { - localFunctionContext.index = lambdasCount++ - } - } - - } - - override fun visitConstructor(declaration: IrConstructor) { - declaration.acceptChildrenVoid(this) - - val descriptor = declaration.descriptor - assert(descriptor.visibility != Visibilities.LOCAL) - - if (descriptor.constructedClass.isInner) return - - localClassConstructors[descriptor] = LocalClassConstructorContext(declaration) - } - - override fun visitClass(declaration: IrClass) { - declaration.acceptChildrenVoid(this) - - val descriptor = declaration.descriptor - - if (descriptor.isInner) return - - // Local nested classes can only be inner. - assert(descriptor.declaredInFunction()) - - val localClassContext = LocalClassContext(declaration) - localClasses[descriptor] = localClassContext - } - }) - } - } - -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PostInlineLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PostInlineLowering.kt index 065eebf687a..91b420524fd 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PostInlineLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PostInlineLowering.kt @@ -20,11 +20,14 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer import org.jetbrains.kotlin.backend.common.lower.at import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithoutArguments import org.jetbrains.kotlin.backend.konan.reportCompilationError -import org.jetbrains.kotlin.ir.builders.irCall import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid /** @@ -43,7 +46,7 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass { expression.transformChildrenVoid() builder.at(expression) - val typeArgument = expression.descriptor.defaultType + val typeArgument = expression.symbol.typeWithStarProjections return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply { putValueArgument(0, builder.irCall(symbols.getClassTypeInfo, listOf(typeArgument))) @@ -54,7 +57,7 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass { expression.transformChildrenVoid() builder.at(expression) - val typeArgument = expression.type.arguments.single().type + val typeArgument = expression.argument.type return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply { val typeInfo = builder.irCall(symbols.getObjectTypeInfo).apply { putValueArgument(0, expression.argument) @@ -95,7 +98,7 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass { } expression.putValueArgument(0, IrConstImpl( expression.startOffset, expression.endOffset, - context.ir.symbols.immutableBinaryBlob.descriptor.defaultType, + context.ir.symbols.immutableBinaryBlob.typeWithoutArguments, IrConstKind.String, builder.toString())) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PreInlineLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PreInlineLowering.kt index fc1f3789be5..058d2b88e9c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PreInlineLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PreInlineLowering.kt @@ -24,8 +24,8 @@ import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl +import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.types.typeUtil.isUnit /** * This pass runs before inlining and performs the following additional transformations over some operations: 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 ce17d823132..95d5f05f861 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 @@ -17,9 +17,7 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.* -import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters import org.jetbrains.kotlin.backend.common.descriptors.getFunction -import org.jetbrains.kotlin.backend.common.descriptors.replace import org.jetbrains.kotlin.backend.common.ir.createOverriddenDescriptor import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.konan.Context @@ -27,6 +25,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.ir.IrSuspendableExpressionImpl import org.jetbrains.kotlin.backend.konan.ir.IrSuspensionPoint import org.jetbrains.kotlin.backend.konan.ir.IrSuspensionPointImpl +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl @@ -35,12 +34,10 @@ import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* @@ -48,15 +45,12 @@ import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.isUnit -import org.jetbrains.kotlin.types.typeUtil.makeNotNullable internal class SuspendFunctionsLowering(val context: Context): DeclarationContainerLoweringPass { @@ -212,7 +206,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai } private val symbols = context.ir.symbols - private val getContinuationSymbol = symbols.getContinuation + private val getContinuation = symbols.getContinuation.owner + private val continuationClassSymbol = getContinuation.returnType.classifierOrFail as IrClassSymbol private val returnIfSuspendedDescriptor = context.getInternalFunctions("returnIfSuspended").single() private fun removeReturnIfSuspendedCallAndSimplifyDelegatingCall(irFunction: IrFunction, delegatingCall: IrCall) { @@ -245,7 +240,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai putValueArgument(index, irGet(argument)) } putValueArgument(functionParameters.size, - irCall(getContinuationSymbol, listOf(descriptor.returnType!!))) + irCall(getContinuation, listOf(irFunction.returnType))) } putValueArgument(0, irGetObject(symbols.unit)) // value putValueArgument(1, irNull()) // exception @@ -268,59 +263,50 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai private val coroutinesScope = context.irModule!!.descriptor.getPackage(COROUTINES_FQ_NAME).memberScope private val kotlinPackageScope = context.irModule!!.descriptor.getPackage(KOTLIN_FQ_NAME).memberScope - private val continuationClassDescriptor = coroutinesScope - .getContributedClassifier(Name.identifier("Continuation"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor - private inner class CoroutineBuilder(val irFunction: IrFunction, val functionReference: IrFunctionReference?) { - private val functionParameters = irFunction.descriptor.explicitParameters - private val boundFunctionParameters = functionReference?.getArguments()?.map { it.first } + private val functionParameters = irFunction.explicitParameters + private val boundFunctionParameters = functionReference?.getArgumentsWithIr()?.map { it.first } private val unboundFunctionParameters = boundFunctionParameters?.let { functionParameters - it } private var tempIndex = 0 private var suspensionPointIdIndex = 0 - private lateinit var suspendResult: IrVariableSymbol - private lateinit var dataArgument: IrValueParameterSymbol - private lateinit var exceptionArgument: IrValueParameterSymbol + private lateinit var suspendResult: IrVariable + private lateinit var dataArgument: IrValueParameter + private lateinit var exceptionArgument: IrValueParameter private lateinit var coroutineClassDescriptor: ClassDescriptorImpl private lateinit var coroutineClass: IrClassImpl - private lateinit var coroutineClassThis: IrValueParameterSymbol - private lateinit var argumentToPropertiesMap: Map + private lateinit var coroutineClassThis: IrValueParameter + private lateinit var argumentToPropertiesMap: Map private val coroutineImplSymbol = symbols.coroutineImpl private val coroutineImplConstructorSymbol = coroutineImplSymbol.constructors.single() private val coroutineImplClassDescriptor = coroutineImplSymbol.descriptor - private val create1FunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope - .getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND) - .single { it.valueParameters.size == 1 } - private val create1CompletionParameter = create1FunctionDescriptor.valueParameters[0] + private val create1Function = coroutineImplSymbol.owner.simpleFunctions() + .single { it.name.asString() == "create" && it.valueParameters.size == 1 } + private val create1CompletionParameter = create1Function.valueParameters[0] private val coroutineImplLabelGetterSymbol = coroutineImplSymbol.getPropertyGetter("label")!! private val coroutineImplLabelSetterSymbol = coroutineImplSymbol.getPropertySetter("label")!! fun build(): BuiltCoroutine { - val superTypes = mutableListOf(coroutineImplClassDescriptor.defaultType) - val superClasses = mutableListOf(coroutineImplSymbol.owner) - var suspendFunctionClassDescriptor: ClassDescriptor? = null - var functionClassDescriptor: ClassDescriptor? = null - var suspendFunctionClassTypeArguments: List? = null - var functionClassTypeArguments: List? = null + val superTypes = mutableListOf(coroutineImplSymbol.owner.defaultType) + var suspendFunctionClass: IrClass? = null + var functionClass: IrClass? = null + var suspendFunctionClassTypeArguments: List? = null + var functionClassTypeArguments: List? = null if (unboundFunctionParameters != null) { // Suspend lambda inherits SuspendFunction. val numberOfParameters = unboundFunctionParameters.size - suspendFunctionClassDescriptor = kotlinPackageScope.getContributedClassifier( - Name.identifier("SuspendFunction$numberOfParameters"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor + suspendFunctionClass = context.ir.symbols.suspendFunctions[numberOfParameters].owner val unboundParameterTypes = unboundFunctionParameters.map { it.type } - suspendFunctionClassTypeArguments = unboundParameterTypes + irFunction.descriptor.returnType!! - superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeArguments) - superClasses += context.ir.symbols.suspendFunctions[numberOfParameters].owner + suspendFunctionClassTypeArguments = unboundParameterTypes + irFunction.returnType + superTypes += suspendFunctionClass.typeWith(suspendFunctionClassTypeArguments) - functionClassDescriptor = kotlinPackageScope.getContributedClassifier( - Name.identifier("Function${numberOfParameters + 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor - val continuationType = continuationClassDescriptor.defaultType.replace(listOf(irFunction.descriptor.returnType!!)) - functionClassTypeArguments = unboundParameterTypes + continuationType + context.builtIns.nullableAnyType - superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeArguments) - superClasses += context.ir.symbols.functions[numberOfParameters + 1].owner + functionClass = context.ir.symbols.functions[numberOfParameters + 1].owner + val continuationType = continuationClassSymbol.typeWith(irFunction.returnType) + functionClassTypeArguments = unboundParameterTypes + continuationType + context.irBuiltIns.anyNType + superTypes += functionClass.typeWith(functionClassTypeArguments) } coroutineClassDescriptor = ClassDescriptorImpl( @@ -328,11 +314,13 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai /* name = */ "${irFunction.descriptor.name}\$${coroutineId++}".synthesizedName, /* modality = */ Modality.FINAL, /* kind = */ ClassKind.CLASS, - /* superTypes = */ superTypes, + /* superTypes = */ superTypes.map { it.toKotlinType() }, /* source = */ SourceElement.NO_SOURCE, /* isExternal = */ false, /* storageManager = */ LockBasedStorageManager.NO_LOCKS - ) + ).also { + it.initialize(stub("coroutine class"), stub("coroutine class constructors"), null) + } coroutineClass = IrClassImpl( startOffset = irFunction.startOffset, endOffset = irFunction.endOffset, @@ -340,17 +328,19 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai descriptor = coroutineClassDescriptor ) coroutineClass.parent = irFunction.parent + coroutineClass.createParameterDeclarations() + coroutineClassThis = coroutineClass.thisReceiver!! val overriddenMap = mutableMapOf() - val constructors = mutableSetOf() val coroutineConstructorBuilder = createConstructorBuilder() - constructors.add(coroutineConstructorBuilder.symbol.descriptor) + coroutineConstructorBuilder.initialize() - val doResumeFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope - .getContributedFunctions(Name.identifier("doResume"), NoLookupLocation.FROM_BACKEND).single() - val doResumeMethodBuilder = createDoResumeMethodBuilder(doResumeFunctionDescriptor) - overriddenMap += doResumeFunctionDescriptor to doResumeMethodBuilder.symbol.descriptor + val doResumeFunction = coroutineImplSymbol.owner.simpleFunctions() + .single { it.name.asString() == "doResume" } + val doResumeMethodBuilder = createDoResumeMethodBuilder(doResumeFunction, coroutineClass) + doResumeMethodBuilder.initialize() + overriddenMap += doResumeFunction.descriptor to doResumeMethodBuilder.symbol.descriptor var coroutineFactoryConstructorBuilder: SymbolWithIrBuilder? = null var createMethodBuilder: SymbolWithIrBuilder? = null @@ -358,7 +348,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai if (functionReference != null) { // Suspend lambda - create factory methods. coroutineFactoryConstructorBuilder = createFactoryConstructorBuilder(boundFunctionParameters!!) - constructors.add(coroutineFactoryConstructorBuilder.symbol.descriptor) val createFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope .getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND) @@ -366,27 +355,24 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai createMethodBuilder = createCreateMethodBuilder( unboundArgs = unboundFunctionParameters!!, superFunctionDescriptor = createFunctionDescriptor, - coroutineConstructorSymbol = coroutineConstructorBuilder.symbol) + coroutineConstructor = coroutineConstructorBuilder.ir, + coroutineClass = coroutineClass) + createMethodBuilder.initialize() if (createFunctionDescriptor != null) overriddenMap += createFunctionDescriptor to createMethodBuilder.symbol.descriptor - val invokeFunctionDescriptor = functionClassDescriptor!!.getFunction("invoke", functionClassTypeArguments!!) - val suspendInvokeFunctionDescriptor = suspendFunctionClassDescriptor!!.getFunction("invoke", suspendFunctionClassTypeArguments!!) + val invokeFunctionDescriptor = functionClass!!.descriptor + .getFunction("invoke", functionClassTypeArguments!!.map { it.toKotlinType() }) + val suspendInvokeFunctionDescriptor = suspendFunctionClass!!.descriptor + .getFunction("invoke", suspendFunctionClassTypeArguments!!.map { it.toKotlinType() }) invokeMethodBuilder = createInvokeMethodBuilder( suspendFunctionInvokeFunctionDescriptor = suspendInvokeFunctionDescriptor, functionInvokeFunctionDescriptor = invokeFunctionDescriptor, - createFunctionSymbol = createMethodBuilder.symbol, - doResumeFunctionSymbol = doResumeMethodBuilder.symbol) + createFunction = createMethodBuilder.ir, + doResumeFunction = doResumeMethodBuilder.ir, + coroutineClass = coroutineClass) } - val memberScope = stub("coroutine class") - coroutineClassDescriptor.initialize(memberScope, constructors, null) - - coroutineClass.createParameterDeclarations() - - coroutineClassThis = coroutineClass.thisReceiver!!.symbol - - coroutineConstructorBuilder.initialize() coroutineClass.addChild(coroutineConstructorBuilder.ir) coroutineFactoryConstructorBuilder?.let { @@ -395,7 +381,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai } createMethodBuilder?.let { - it.initialize() coroutineClass.addChild(it.ir) } @@ -404,10 +389,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai coroutineClass.addChild(it.ir) } - doResumeMethodBuilder.initialize() coroutineClass.addChild(doResumeMethodBuilder.ir) - coroutineClass.setSuperSymbolsAndAddFakeOverrides(superClasses) + coroutineClass.setSuperSymbolsAndAddFakeOverrides(superTypes) return BuiltCoroutine( coroutineClass = coroutineClass, @@ -428,21 +412,30 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai ) ) + private lateinit var constructorParameters: List + override fun doInitialize() { val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl - val constructorParameters = ( + constructorParameters = ( functionParameters - + coroutineImplConstructorSymbol.descriptor.valueParameters[0] // completion. - ).mapIndexed { index, parameter -> parameter.copyAsValueParameter(descriptor, index) } + + coroutineImplConstructorSymbol.owner.valueParameters[0] // completion. + ).mapIndexed { index, parameter -> - descriptor.initialize(constructorParameters, Visibilities.PUBLIC) + val parameterDescriptor = parameter.descriptor.copyAsValueParameter(descriptor, index) + parameter.copy(parameterDescriptor) + } + + descriptor.initialize( + constructorParameters.map { it.descriptor as ValueParameterDescriptor }, + Visibilities.PUBLIC + ) descriptor.returnType = coroutineClassDescriptor.defaultType } override fun buildIr(): IrConstructor { // Save all arguments to fields. argumentToPropertiesMap = functionParameters.associate { - it to buildPropertyWithBackingField(it.name, it.type, false) + it.descriptor to addField(it.name, it.type, false) } val startOffset = irFunction.startOffset @@ -453,25 +446,32 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai origin = DECLARATION_ORIGIN_COROUTINE_IMPL, symbol = symbol).apply { - createParameterDeclarations() + returnType = coroutineClass.defaultType + + this.valueParameters += constructorParameters val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) body = irBuilder.irBlockBody { val completionParameter = valueParameters.last() +IrDelegatingConstructorCallImpl(startOffset, endOffset, + context.irBuiltIns.unitType, coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply { - putValueArgument(0, irGet(completionParameter.symbol)) + putValueArgument(0, irGet(completionParameter)) } - +IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol) + +IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol, context.irBuiltIns.unitType) functionParameters.forEachIndexed { index, parameter -> - +irSetField(irGet(coroutineClassThis), argumentToPropertiesMap[parameter]!!, irGet(valueParameters[index].symbol)) + +irSetField( + irGet(coroutineClassThis), + argumentToPropertiesMap[parameter.descriptor]!!, + irGet(valueParameters[index]) + ) } } } } } - private fun createFactoryConstructorBuilder(boundParams: List) + private fun createFactoryConstructorBuilder(boundParams: List) = object : SymbolWithIrBuilder() { override fun buildSymbol() = IrConstructorSymbolImpl( @@ -483,12 +483,18 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai ) ) + lateinit var constructorParameters: List + override fun doInitialize() { val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl - val constructorParameters = boundParams.mapIndexed { index, parameter -> - parameter.copyAsValueParameter(descriptor, index) + constructorParameters = boundParams.mapIndexed { index, parameter -> + val parameterDescriptor = parameter.descriptor.copyAsValueParameter(descriptor, index) + parameter.copy(parameterDescriptor) } - descriptor.initialize(constructorParameters, Visibilities.PUBLIC) + descriptor.initialize( + constructorParameters.map { it.descriptor as ValueParameterDescriptor }, + Visibilities.PUBLIC + ) descriptor.returnType = coroutineClassDescriptor.defaultType } @@ -501,27 +507,32 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai origin = DECLARATION_ORIGIN_COROUTINE_IMPL, symbol = symbol).apply { - createParameterDeclarations() + returnType = coroutineClass.defaultType + + this.valueParameters += constructorParameters val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) body = irBuilder.irBlockBody { - +IrDelegatingConstructorCallImpl(startOffset, endOffset, + +IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType, coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply { putValueArgument(0, irNull()) // Completion. } - +IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol) + +IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol, + context.irBuiltIns.unitType) // Save all arguments to fields. boundParams.forEachIndexed { index, parameter -> - +irSetField(irGet(coroutineClassThis), argumentToPropertiesMap[parameter]!!, irGet(valueParameters[index].symbol)) + +irSetField(irGet(coroutineClassThis), argumentToPropertiesMap[parameter.descriptor]!!, + irGet(valueParameters[index])) } } } } } - private fun createCreateMethodBuilder(unboundArgs: List, + private fun createCreateMethodBuilder(unboundArgs: List, superFunctionDescriptor: FunctionDescriptor?, - coroutineConstructorSymbol: IrConstructorSymbol) + coroutineConstructor: IrConstructor, + coroutineClass: IrClass) = object: SymbolWithIrBuilder() { override fun buildSymbol() = IrSimpleFunctionSymbolImpl( @@ -534,19 +545,21 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai ) ) + lateinit var parameters: List + override fun doInitialize() { val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl - val valueParameters = ( + parameters = ( unboundArgs + create1CompletionParameter ).mapIndexed { index, parameter -> - parameter.copyAsValueParameter(descriptor, index) + parameter.copy(parameter.descriptor.copyAsValueParameter(descriptor, index)) } descriptor.initialize( /* receiverParameterType = */ null, /* dispatchReceiverParameter = */ coroutineClassDescriptor.thisAsReceiverParameter, /* typeParameters = */ emptyList(), - /* unsubstitutedValueParameters = */ valueParameters, + /* unsubstitutedValueParameters = */ parameters.map { it.descriptor as ValueParameterDescriptor }, /* unsubstitutedReturnType = */ coroutineClassDescriptor.defaultType, /* modality = */ Modality.FINAL, /* visibility = */ Visibilities.PRIVATE).apply { @@ -566,25 +579,29 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai origin = DECLARATION_ORIGIN_COROUTINE_IMPL, symbol = symbol).apply { - createParameterDeclarations() + returnType = coroutineClass.defaultType + parent = coroutineClass - val thisReceiver = this.dispatchReceiverParameter!!.symbol + this.valueParameters += parameters + this.createDispatchReceiverParameter() + + val thisReceiver = this.dispatchReceiverParameter!! val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) body = irBuilder.irBlockBody(startOffset, endOffset) { +irReturn( - irCall(coroutineConstructorSymbol).apply { + irCall(coroutineConstructor).apply { var unboundIndex = 0 val unboundArgsSet = unboundArgs.toSet() functionParameters.map { if (unboundArgsSet.contains(it)) - irGet(valueParameters[unboundIndex++].symbol) + irGet(valueParameters[unboundIndex++]) else - irGetField(irGet(thisReceiver), argumentToPropertiesMap[it]!!) + irGetField(irGet(thisReceiver), argumentToPropertiesMap[it.descriptor]!!) }.forEachIndexed { index, argument -> putValueArgument(index, argument) } - putValueArgument(functionParameters.size, irGet(valueParameters[unboundIndex].symbol)) + putValueArgument(functionParameters.size, irGet(valueParameters[unboundIndex])) assert(unboundIndex == valueParameters.size - 1, { "Not all arguments of are used" }) }) @@ -595,8 +612,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai private fun createInvokeMethodBuilder(suspendFunctionInvokeFunctionDescriptor: FunctionDescriptor, functionInvokeFunctionDescriptor: FunctionDescriptor, - createFunctionSymbol: IrFunctionSymbol, - doResumeFunctionSymbol: IrFunctionSymbol) + createFunction: IrFunction, + doResumeFunction: IrFunction, + coroutineClass: IrClass) = object: SymbolWithIrBuilder() { override fun buildSymbol() = IrSimpleFunctionSymbolImpl( @@ -609,18 +627,20 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai ) ) + lateinit var parameters: List + override fun doInitialize() { val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl - val valueParameters = createFunctionSymbol.descriptor.valueParameters + parameters = createFunction.valueParameters // Skip completion - invoke() already has it implicitly as a suspend function. - .take(createFunctionSymbol.descriptor.valueParameters.size - 1) - .map { it.copyAsValueParameter(descriptor, it.index) } + .take(createFunction.valueParameters.size - 1) + .map { it.copy(it.descriptor.copyAsValueParameter(descriptor, it.index)) } descriptor.initialize( /* receiverParameterType = */ null, /* dispatchReceiverParameter = */ coroutineClassDescriptor.thisAsReceiverParameter, /* typeParameters = */ emptyList(), - /* unsubstitutedValueParameters = */ valueParameters, + /* unsubstitutedValueParameters = */ parameters.map { it.descriptor as ValueParameterDescriptor }, /* unsubstitutedReturnType = */ irFunction.descriptor.returnType, /* modality = */ Modality.FINAL, /* visibility = */ Visibilities.PRIVATE).apply { @@ -639,21 +659,25 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai origin = DECLARATION_ORIGIN_COROUTINE_IMPL, symbol = symbol).apply { - createParameterDeclarations() + returnType = irFunction.returnType + parent = coroutineClass - val thisReceiver = this.dispatchReceiverParameter!!.symbol + valueParameters += parameters + this.createDispatchReceiverParameter() + + val thisReceiver = this.dispatchReceiverParameter!! val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) body = irBuilder.irBlockBody(startOffset, endOffset) { +irReturn( - irCall(doResumeFunctionSymbol).apply { - dispatchReceiver = irCall(createFunctionSymbol).apply { + irCall(doResumeFunction).apply { + dispatchReceiver = irCall(createFunction).apply { dispatchReceiver = irGet(thisReceiver) valueParameters.forEachIndexed { index, parameter -> - putValueArgument(index, irGet(parameter.symbol)) + putValueArgument(index, irGet(parameter)) } putValueArgument(valueParameters.size, - irCall(getContinuationSymbol, listOf(symbol.descriptor.returnType!!))) + irCall(getContinuation, listOf(returnType))) } putValueArgument(0, irGetObject(symbols.unit)) // value putValueArgument(1, irNull()) // exception @@ -664,27 +688,23 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai } } - private fun buildPropertyWithBackingField(name: Name, type: KotlinType, isMutable: Boolean): IrFieldSymbol { - val propertyBuilder = context.createPropertyWithBackingFieldBuilder( - startOffset = irFunction.startOffset, - endOffset = irFunction.endOffset, - origin = DECLARATION_ORIGIN_COROUTINE_IMPL, - owner = coroutineClassDescriptor, - name = name, - type = type, - isMutable = isMutable).apply { - initialize() - } - - coroutineClass.addChild(propertyBuilder.ir) - return propertyBuilder.symbol + private fun addField(name: Name, type: IrType, isMutable: Boolean): IrField = createField( + irFunction.startOffset, + irFunction.endOffset, + type, + name, + isMutable, + DECLARATION_ORIGIN_COROUTINE_IMPL, + coroutineClassDescriptor + ).also { + coroutineClass.addChild(it) } - private fun createDoResumeMethodBuilder(doResumeFunctionDescriptor: FunctionDescriptor) + private fun createDoResumeMethodBuilder(doResumeFunction: IrFunction, coroutineClass: IrClass) = object: SymbolWithIrBuilder() { override fun buildSymbol() = IrSimpleFunctionSymbolImpl( - doResumeFunctionDescriptor.createOverriddenDescriptor(coroutineClassDescriptor) + doResumeFunction.descriptor.createOverriddenDescriptor(coroutineClassDescriptor) ) override fun doInitialize() { } @@ -699,58 +719,76 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai origin = DECLARATION_ORIGIN_COROUTINE_IMPL, symbol = symbol).apply { - createParameterDeclarations() + returnType = context.irBuiltIns.anyNType + parent = coroutineClass + + this.createDispatchReceiverParameter() + + doResumeFunction.valueParameters.mapIndexedTo(this.valueParameters) { index, it -> + it.copy(descriptor.valueParameters[index]) + } } - dataArgument = function.valueParameters[0].symbol - exceptionArgument = function.valueParameters[1].symbol - suspendResult = IrVariableSymbolImpl( - IrTemporaryVariableDescriptorImpl( - containingDeclaration = irFunction.descriptor, - name = "suspendResult".synthesizedName, - outType = context.builtIns.nullableAnyType, - isMutable = true) - ) - val label = coroutineImplClassDescriptor.unsubstitutedMemberScope - .getContributedVariables(Name.identifier("label"), NoLookupLocation.FROM_BACKEND).single() + dataArgument = function.valueParameters[0] + exceptionArgument = function.valueParameters[1] + + val label = coroutineImplSymbol.owner.declarations.filterIsInstance() + .single { it.name.asString() == "label" } val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) function.body = irBuilder.irBlockBody(startOffset, endOffset) { + suspendResult = irVar(IrTemporaryVariableDescriptorImpl( + containingDeclaration = irFunction.descriptor, + name = "suspendResult".synthesizedName, + outType = context.builtIns.nullableAnyType, + isMutable = true) + , context.irBuiltIns.anyNType) + // Extract all suspend calls to temporaries in order to make correct jumps to them. - originalBody.transformChildrenVoid(ExpressionSlicer(label.type)) + originalBody.transformChildrenVoid(ExpressionSlicer(label.getter!!.returnType)) val liveLocals = computeLivenessAtSuspensionPoints(originalBody) val immutableLiveLocals = liveLocals.values.flatten().filterNot { it.descriptor.isVar }.toSet() val localsMap = immutableLiveLocals.associate { // TODO: Remove .descriptor as soon as all symbols are bound. - it.descriptor to IrVariableSymbolImpl( + val symbol = IrVariableSymbolImpl( IrTemporaryVariableDescriptorImpl( containingDeclaration = irFunction.descriptor, - name = it.descriptor.name, - outType = it.descriptor.type, - isMutable = true) + name = it.descriptor.name, + outType = it.descriptor.type, + isMutable = true) ) + + val variable = IrVariableImpl( + startOffset = it.startOffset, + endOffset = it.endOffset, + origin = it.origin, + symbol = symbol, + type = it.type + ) + + it.descriptor to variable } if (localsMap.isNotEmpty()) transformVariables(originalBody, localsMap) // Make variables mutable in order to save/restore them. - val localToPropertyMap = mutableMapOf() + val localToPropertyMap = mutableMapOf() // TODO: optimize by using the same property for different locals. liveLocals.values.forEach { scope -> scope.forEach { - localToPropertyMap.getOrPut(it) { - buildPropertyWithBackingField(it.descriptor.name, it.descriptor.type, true) + localToPropertyMap.getOrPut(it.symbol) { + addField(it.descriptor.name, it.type, true) } } } originalBody.transformChildrenVoid(object : IrElementTransformerVoid() { - private val thisReceiver = function.dispatchReceiverParameter!!.symbol + private val thisReceiver = function.dispatchReceiverParameter!! // Replace returns to refer to the new function. override fun visitReturn(expression: IrReturn): IrExpression { @@ -783,23 +821,24 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai expression.transformChildrenVoid(this) when (expression.symbol) { - saveStateSymbol -> { + saveState.symbol -> { val scope = liveLocals[suspensionPoint]!! return irBlock(expression) { scope.forEach { - +irSetField(irGet(thisReceiver), localToPropertyMap[it]!!, irGet(localsMap[it.descriptor] ?: it)) + val variable = localsMap[it.descriptor] ?: it + +irSetField(irGet(thisReceiver), localToPropertyMap[it.symbol]!!, irGet(variable)) } +irCall(coroutineImplLabelSetterSymbol).apply { dispatchReceiver = irGet(thisReceiver) - putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter.symbol)) + putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter)) } } } - restoreStateSymbol -> { + restoreState.symbol -> { val scope = liveLocals[suspensionPoint]!! return irBlock(expression) { scope.forEach { - +irSetVar(localsMap[it.descriptor] ?: it, irGetField(irGet(thisReceiver), localToPropertyMap[it]!!)) + +irSetVar(localsMap[it.descriptor] ?: it, irGetField(irGet(thisReceiver), localToPropertyMap[it.symbol]!!)) } } } @@ -812,26 +851,26 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai } }) val statements = (originalBody as IrBlockBody).statements - +irVar(suspendResult, null) + +suspendResult +IrSuspendableExpressionImpl( startOffset = startOffset, endOffset = endOffset, - type = context.builtIns.unitType, + type = context.irBuiltIns.unitType, suspensionPointId = irCall(coroutineImplLabelGetterSymbol).apply { - dispatchReceiver = irGet(function.dispatchReceiverParameter!!.symbol) + dispatchReceiver = irGet(function.dispatchReceiverParameter!!) }, result = irBlock(startOffset, endOffset) { +irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception. statements.forEach { +it } }) - if (irFunction.descriptor.returnType!!.isUnit()) + if (irFunction.returnType.isUnit()) +irReturn(irGetObject(symbols.unit)) // Insert explicit return for Unit functions. } return function } } - private fun transformVariables(element: IrElement, variablesMap: Map) { + private fun transformVariables(element: IrElement, variablesMap: Map) { element.transformChildrenVoid(object: IrElementTransformerVoid() { override fun visitGetValue(expression: IrGetValue): IrExpression { @@ -843,7 +882,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai return IrGetValueImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, - symbol = newVariable, + type = newVariable.type, + symbol = newVariable.symbol, origin = expression.origin) } @@ -856,7 +896,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai return IrSetVariableImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, - symbol = newVariable, + type = context.irBuiltIns.unitType, + symbol = newVariable.symbol, value = expression.value, origin = expression.origin) } @@ -867,21 +908,17 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai val newVariable = variablesMap[declaration.symbol.descriptor] ?: return declaration - return IrVariableImpl( - startOffset = declaration.startOffset, - endOffset = declaration.endOffset, - origin = declaration.origin, - symbol = newVariable).apply { - initializer = declaration.initializer - } + newVariable.initializer = declaration.initializer + + return newVariable } }) } - private fun computeLivenessAtSuspensionPoints(body: IrBody): Map> { + private fun computeLivenessAtSuspensionPoints(body: IrBody): Map> { // TODO: data flow analysis. // Just save all visible for now. - val result = mutableMapOf>() + val result = mutableMapOf>() body.acceptChildrenVoid(object: VariablesScopeTracker() { override fun visitExpression(expression: IrExpression) { @@ -894,7 +931,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai suspensionPoint.result.acceptChildrenVoid(this) suspensionPoint.resumeResult.acceptChildrenVoid(this) - val visibleVariables = mutableListOf() + val visibleVariables = mutableListOf() scopeStack.forEach { visibleVariables += it } result.put(suspensionPoint, visibleVariables) } @@ -904,7 +941,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai } // These are marker descriptors to split up the lowering on two parts. - private val saveStateSymbol = IrSimpleFunctionSymbolImpl( + private val saveState = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, SimpleFunctionDescriptorImpl.create( irFunction.descriptor, Annotations.EMPTY, @@ -912,10 +949,11 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE).apply { initialize(null, null, emptyList(), emptyList(), context.builtIns.unitType, Modality.ABSTRACT, Visibilities.PRIVATE) - } - ) + }).apply { + returnType = context.irBuiltIns.unitType + } - private val restoreStateSymbol = IrSimpleFunctionSymbolImpl( + private val restoreState = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, SimpleFunctionDescriptorImpl.create( irFunction.descriptor, Annotations.EMPTY, @@ -923,10 +961,11 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE).apply { initialize(null, null, emptyList(), emptyList(), context.builtIns.unitType, Modality.ABSTRACT, Visibilities.PRIVATE) - } - ) + }).apply { + returnType = context.irBuiltIns.unitType + } - private inner class ExpressionSlicer(val suspensionPointIdType: KotlinType): IrElementTransformerVoid() { + private inner class ExpressionSlicer(val suspensionPointIdType: IrType): IrElementTransformerVoid() { // TODO: optimize - it has square complexity. override fun visitSetField(expression: IrSetField): IrExpression { @@ -983,13 +1022,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai newChildren[index] = transformedChild else { // Save to temporary in order to save execution order. - val tmp = IrVariableSymbolImpl( - IrTemporaryVariableDescriptorImpl( - containingDeclaration = irFunction.descriptor, - name = "tmp${tempIndex++}".synthesizedName, - outType = transformedChild.type) - ) - tempStatements += irVar(tmp, transformedChild) + val tmp = irVar(transformedChild) + + tempStatements += tmp newChildren[index] = irGet(tmp) } } @@ -1001,7 +1036,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai calledSaveState = true val firstArgument = newChildren[2]!! newChildren[2] = irBlock(firstArgument) { - +irCall(saveStateSymbol) + +irCall(saveState) +firstArgument } suspendCall = newChildren[2] @@ -1014,17 +1049,12 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai newChildren[numberOfChildren - 1] = irBlock(lastChild) { if (lastChild.isPure()) { - +irCall(saveStateSymbol) + +irCall(saveState) +lastChild } else { - val tmp = IrVariableSymbolImpl( - IrTemporaryVariableDescriptorImpl( - containingDeclaration = irFunction.descriptor, - name = "tmp${tempIndex++}".synthesizedName, - outType = lastChild.type) - ) - +irVar(tmp, lastChild) - +irCall(saveStateSymbol) + val tmp = irVar(lastChild) + +tmp + +irCall(saveState) +irGet(tmp) } } @@ -1053,27 +1083,27 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai val suspensionPointIdParameter = IrTemporaryVariableDescriptorImpl( containingDeclaration = irFunction.descriptor, name = "suspensionPointId${suspensionPointIdIndex++}".synthesizedName, - outType = suspensionPointIdType) + outType = suspensionPointIdType.toKotlinType()) val suspensionPoint = IrSuspensionPointImpl( startOffset = startOffset, endOffset = endOffset, - type = context.builtIns.nullableAnyType, - suspensionPointIdParameter = irVar(suspensionPointIdParameter, null), + type = context.irBuiltIns.anyNType, + suspensionPointIdParameter = irVar(suspensionPointIdParameter, suspensionPointIdType), result = irBlock(startOffset, endOffset) { if (!calledSaveState) - +irCall(saveStateSymbol) - +irSetVar(suspendResult, suspendCall) + +irCall(saveState) + +irSetVar(suspendResult.symbol, suspendCall) +irReturnIfSuspended(suspendResult) +irGet(suspendResult) }, resumeResult = irBlock(startOffset, endOffset) { - +irCall(restoreStateSymbol) + +irCall(restoreState) +irThrowIfNotNull(exceptionArgument) +irGet(dataArgument) }) val expressionResult = when { suspendCall.type.isUnit() -> irImplicitCoercionToUnit(suspensionPoint) - else -> irCast(suspensionPoint, suspendCall.type, suspendCall.type) + else -> irAs(suspensionPoint, suspendCall.type) } return irBlock(expression) { tempStatements.forEach { +it } @@ -1132,27 +1162,31 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai get() = this is IrCall && this.descriptor.original == returnIfSuspendedDescriptor } + private fun IrBuilderWithScope.irVar(initializer: IrExpression) = + irVar( + IrTemporaryVariableDescriptorImpl( + containingDeclaration = irFunction.descriptor, + name = "tmp${tempIndex++}".synthesizedName, + outType = initializer.type.toKotlinType() + ), + initializer.type + ).apply { this.initializer = initializer } - private fun IrBuilderWithScope.irVar(descriptor: VariableDescriptor, initializer: IrExpression?) = - IrVariableImpl(startOffset, endOffset, DECLARATION_ORIGIN_COROUTINE_IMPL, descriptor, initializer) + private fun IrBuilderWithScope.irVar(descriptor: VariableDescriptor, type: IrType) = + IrVariableImpl(startOffset, endOffset, DECLARATION_ORIGIN_COROUTINE_IMPL, descriptor, type) - private fun IrBuilderWithScope.irVar(symbol: IrVariableSymbol, initializer: IrExpression?) = - IrVariableImpl(startOffset, endOffset, DECLARATION_ORIGIN_COROUTINE_IMPL, symbol).apply { - this.initializer = initializer - } - - private fun IrBuilderWithScope.irReturnIfSuspended(value: IrValueSymbol) = + private fun IrBuilderWithScope.irReturnIfSuspended(value: IrValueDeclaration) = irIfThen(irEqeqeq(irGet(value), irCall(symbols.coroutineSuspendedGetter)), irReturn(irGet(value))) - private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueSymbol) = + private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueDeclaration) = irIfThen(irNot(irEqeqeq(irGet(exception), irNull())), - irThrow(irImplicitCast(irGet(exception), exception.descriptor.type.makeNotNullable()))) + irThrow(irImplicitCast(irGet(exception), exception.type.makeNotNull()))) } private open class VariablesScopeTracker: IrElementVisitorVoid { - protected val scopeStack = mutableListOf>(mutableSetOf()) + protected val scopeStack = mutableListOf>(mutableSetOf()) override fun visitElement(element: IrElement) { element.acceptChildrenVoid(this) @@ -1174,7 +1208,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai override fun visitVariable(declaration: IrVariable) { super.visitVariable(declaration) - scopeStack.peek()!!.add(declaration.symbol) + scopeStack.peek()!!.add(declaration) } } } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TestProcessor.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TestProcessor.kt index 8048ded6403..6d6f3f76c53 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TestProcessor.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TestProcessor.kt @@ -25,6 +25,8 @@ import org.jetbrains.kotlin.backend.common.reportWarning import org.jetbrains.kotlin.backend.konan.KonanBackendContext import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithoutArguments import org.jetbrains.kotlin.backend.konan.reportCompilationError import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.isFunctionType @@ -38,15 +40,14 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -98,50 +99,50 @@ internal class TestProcessor (val context: KonanBackendContext) { add(TestFunction(function, kind)) private fun IrStatementsBuilder.generateFunctionRegistration( - receiver: IrValueSymbol, + receiver: IrValueDeclaration, registerTestCase: IrFunctionSymbol, registerFunction: IrFunctionSymbol, functions: Collection) { functions.forEach { if (it.kind == FunctionKind.TEST) { // Call registerTestCase(name: String, testFunction: () -> Unit) method. - +irCall(registerTestCase).apply { + +irCall(registerTestCase, registerTestCase.descriptor.returnType!!.toErasedIrType()).apply { dispatchReceiver = irGet(receiver) putValueArgument(0, IrConstImpl.string( UNDEFINED_OFFSET, UNDEFINED_OFFSET, - context.builtIns.stringType, + context.irBuiltIns.stringType, it.function.descriptor.name.identifier) ) putValueArgument(1, IrFunctionReferenceImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, - descriptor.valueParameters[1].type, + descriptor.valueParameters[1].type.toErasedIrType(), it.function, - it.function.descriptor, emptyMap())) + it.function.descriptor, 0)) putValueArgument(2, IrConstImpl.boolean( UNDEFINED_OFFSET, UNDEFINED_OFFSET, - context.builtIns.booleanType, + context.irBuiltIns.booleanType, it.ignored )) } } else { // Call registerFunction(kind: TestFunctionKind, () -> Unit) method. - +irCall(registerFunction).apply { + +irCall(registerFunction, registerFunction.descriptor.returnType!!.toErasedIrType()).apply { dispatchReceiver = irGet(receiver) val testKindEntry = it.kind.runtimeKind putValueArgument(0, IrGetEnumValueImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, - testKindEntry.descriptor.defaultType, + symbols.testFunctionKind.typeWithoutArguments, testKindEntry) ) putValueArgument(1, IrFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, - descriptor.valueParameters[1].type, + descriptor.valueParameters[1].type.toErasedIrType(), it.function, - it.function.descriptor, emptyMap())) + it.function.descriptor, 0)) } } } @@ -282,7 +283,7 @@ internal class TestProcessor (val context: KonanBackendContext) { //region Symbol and IR builders /** Base class for getters (createInstance and getCompanion). */ - private abstract inner class GetterBuilder(val returnType: KotlinType, + private abstract inner class GetterBuilder(val returnType: IrType, val testSuite: IrClassSymbol, val getterName: Name) : SymbolWithIrBuilder() { @@ -300,7 +301,7 @@ internal class TestProcessor (val context: KonanBackendContext) { /* dispatchReceiverParameter = */ testSuite.descriptor.thisAsReceiverParameter, /* typeParameters = */ emptyList(), /* unsubstitutedValueParameters = */ emptyList(), - /* returnType = */ returnType, + /* returnType = */ returnType.toKotlinType(), /* modality = */ Modality.FINAL, /* visibility = */ Visibilities.PROTECTED ).apply { @@ -324,18 +325,21 @@ internal class TestProcessor (val context: KonanBackendContext) { * returning a reference to an object represented by `[objectSymbol]`. */ private inner class ObjectGetterBuilder(val objectSymbol: IrClassSymbol, testSuite: IrClassSymbol, getterName: Name) - : GetterBuilder(objectSymbol.descriptor.defaultType, testSuite, getterName) { + : GetterBuilder(objectSymbol.typeWithoutArguments, testSuite, getterName) { override fun buildIr(): IrFunction = IrFunctionImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, TEST_SUITE_GENERATED_MEMBER, symbol).apply { + + this.returnType = this@ObjectGetterBuilder.returnType + val builder = context.createIrBuilder(symbol) - createParameterDeclarations() + createParameterDeclarations(context.ir.symbols.symbolTable) body = builder.irBlockBody { +irReturn(IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, - objectSymbol.descriptor.defaultType, objectSymbol) + objectSymbol.typeWithoutArguments, objectSymbol) ) } } @@ -346,17 +350,20 @@ internal class TestProcessor (val context: KonanBackendContext) { * returning a new instance of class referenced by [classSymbol]. */ private inner class InstanceGetterBuilder(val classSymbol: IrClassSymbol, testSuite: IrClassSymbol, getterName: Name) - : GetterBuilder(classSymbol.descriptor.defaultType, testSuite, getterName) { + : GetterBuilder(classSymbol.typeWithStarProjections, testSuite, getterName) { override fun buildIr() = IrFunctionImpl( startOffset = UNDEFINED_OFFSET, endOffset = UNDEFINED_OFFSET, origin = TEST_SUITE_GENERATED_MEMBER, symbol = symbol).apply { + + this.returnType = this@InstanceGetterBuilder.returnType + val builder = context.createIrBuilder(symbol) - createParameterDeclarations() + createParameterDeclarations(context.ir.symbols.symbolTable) body = builder.irBlockBody { - val constructor = classSymbol.constructors.single { it.descriptor.valueParameters.isEmpty() } + val constructor = classSymbol.owner.constructors.single { it.valueParameters.isEmpty() } +irReturn(irCall(constructor)) } } @@ -385,15 +392,18 @@ internal class TestProcessor (val context: KonanBackendContext) { UNDEFINED_OFFSET, TEST_SUITE_GENERATED_MEMBER, symbol).apply { - createParameterDeclarations() - val registerTestCase = testSuite.getFunction("registerTestCase") { + returnType = testSuite.typeWithStarProjections + + createParameterDeclarations(context.ir.symbols.symbolTable) + + val registerTestCase = symbols.baseClassSuite.getFunction("registerTestCase") { it.valueParameters.size == 3 && KotlinBuiltIns.isString(it.valueParameters[0].type) && // name: String it.valueParameters[1].type.isFunctionType && // function: testClassType.() -> Unit KotlinBuiltIns.isBoolean(it.valueParameters[2].type) // ignored: Boolean } - val registerFunction = testSuite.getFunction("registerFunction") { + val registerFunction = symbols.baseClassSuite.getFunction("registerFunction") { it.valueParameters.size == 2 && it.valueParameters[0].type == symbols.testFunctionKind.descriptor.defaultType && // kind: TestFunctionKind it.valueParameters[1].type.isFunctionType // function: () -> Unit @@ -404,26 +414,28 @@ internal class TestProcessor (val context: KonanBackendContext) { +IrDelegatingConstructorCallImpl( startOffset = UNDEFINED_OFFSET, endOffset = UNDEFINED_OFFSET, + type = context.irBuiltIns.unitType, symbol = symbols.symbolTable.referenceConstructor(superConstructor), descriptor = superConstructor, typeArgumentsCount = 2 ).apply { - copyTypeArgumentsFrom(mapOf(superConstructor.typeParameters[0] to testClassType, - superConstructor.typeParameters[1] to testCompanionType)) + putTypeArgument(0, testClassType.toErasedIrType()) + putTypeArgument(1, testCompanionType.toErasedIrType()) + putValueArgument(0, IrConstImpl.string( UNDEFINED_OFFSET, UNDEFINED_OFFSET, - context.builtIns.stringType, + context.irBuiltIns.stringType, suiteName) ) putValueArgument(1, IrConstImpl.boolean( UNDEFINED_OFFSET, UNDEFINED_OFFSET, - context.builtIns.booleanType, + context.irBuiltIns.booleanType, ignored )) } - generateFunctionRegistration(testSuite.owner.thisReceiver!!.symbol, + generateFunctionRegistration(testSuite.owner.thisReceiver!!, registerTestCase, registerFunction, functions) } } @@ -445,6 +457,8 @@ internal class TestProcessor (val context: KonanBackendContext) { ) } + private fun KotlinType.toErasedIrType(): IrType = context.ir.translateErased(this) + /** * Builds a test suite class representing a test class (any class in the original IrFile with method(s) * annotated with @Test). The test suite class is a subclass of ClassTestSuite where T is the test class. @@ -489,17 +503,17 @@ internal class TestProcessor (val context: KonanBackendContext) { } } - override fun buildIr() = IrClassImpl( + override fun buildIr() = symbols.symbolTable.declareClass( UNDEFINED_OFFSET, UNDEFINED_OFFSET, TEST_SUITE_CLASS, - symbol).apply { + symbol.descriptor).apply { createParameterDeclarations() addMember(constructorBuilder.ir) addMember(instanceGetterBuilder.ir) companionGetterBuilder?.let { addMember(it.ir) } - addFakeOverrides() - setSuperSymbols(context.ir.symbols.symbolTable) + addFakeOverrides(symbols.symbolTable) + setSuperSymbols(symbols.symbolTable) } override fun doInitialize() { @@ -526,7 +540,7 @@ internal class TestProcessor (val context: KonanBackendContext) { companionGetterBuilder?.initialize() } - override fun buildSymbol() = IrClassSymbolImpl( + override fun buildSymbol() = symbols.symbolTable.referenceClass( ClassDescriptorImpl( /* containingDeclaration = */ containingDeclaration, /* name = */ suiteClassName, @@ -549,8 +563,9 @@ internal class TestProcessor (val context: KonanBackendContext) { testClass.functions)) { initialize() irFile.addChild(ir) + val irConstructor = ir.constructors.single() irFile.addTopLevelInitializer( - IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, ir.symbol.constructors.single()) + IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irConstructor.returnType, irConstructor.symbol) ) } @@ -575,10 +590,10 @@ internal class TestProcessor (val context: KonanBackendContext) { irFile.addTopLevelInitializer(builder.irBlock { val constructorCall = irCall(symbols.topLevelSuiteConstructor).apply { putValueArgument(0, IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, - context.builtIns.stringType, suiteName)) + context.irBuiltIns.stringType, suiteName)) } val testSuiteVal = irTemporary(constructorCall, "topLevelTestSuite") - generateFunctionRegistration(testSuiteVal.symbol, + generateFunctionRegistration(testSuiteVal, symbols.topLevelSuiteRegisterTestCase, symbols.topLevelSuiteRegisterFunction, functions) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt index 4ce59345cb2..2013b7144e7 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt @@ -21,22 +21,27 @@ import org.jetbrains.kotlin.backend.common.FunctionLoweringPass import org.jetbrains.kotlin.backend.common.lower.at import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlock -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark +import org.jetbrains.kotlin.backend.konan.irasdescriptors.containsNull +import org.jetbrains.kotlin.backend.konan.irasdescriptors.isSubtypeOf import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.makeNotNull +import org.jetbrains.kotlin.ir.types.makeNullable +import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf -import org.jetbrains.kotlin.types.typeUtil.makeNotNullable -import org.jetbrains.kotlin.types.typeUtil.makeNullable /** * This lowering pass lowers some [IrTypeOperatorCall]s. @@ -60,22 +65,24 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun return declaration } - private fun KotlinType.erasure(): KotlinType { - val descriptor = this.constructor.declarationDescriptor - return when (descriptor) { - is ClassDescriptor -> this - is TypeParameterDescriptor -> { - val upperBound = descriptor.upperBounds.singleOrNull() ?: - TODO("$descriptor : ${descriptor.upperBounds}") + private fun IrType.erasure(): IrType { + if (this !is IrSimpleType) return this - if (this.isMarkedNullable) { + val classifier = this.classifier + return when (classifier) { + is IrClassSymbol -> this + is IrTypeParameterSymbol -> { + val upperBound = classifier.owner.superTypes.singleOrNull() ?: + TODO("${classifier.descriptor} : ${classifier.descriptor.upperBounds}") + + if (this.hasQuestionMark) { // `T?` upperBound.erasure().makeNullable() } else { upperBound.erasure() } } - else -> TODO(this.toString()) + else -> TODO(classifier.toString()) } } @@ -83,32 +90,32 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun builder.at(expression) val typeOperand = expression.typeOperand.erasure() - assert (!TypeUtils.hasNullableSuperType(typeOperand)) // So that `isNullable()` <=> `isMarkedNullable`. +// assert (!TypeUtils.hasNullableSuperType(typeOperand)) // So that `isNullable()` <=> `isMarkedNullable`. // TODO: consider the case when expression type is wrong e.g. due to generics-related unchecked casts. return when { expression.argument.type.isSubtypeOf(typeOperand) -> expression.argument - expression.argument.type.isNullable() -> { + expression.argument.type.containsNull() -> { with (builder) { irLetS(expression.argument) { argument -> irIfThenElse( type = expression.type, - condition = irEqeqeq(irGet(argument), irNull()), + condition = irEqeqeq(irGet(argument.owner), irNull()), - thenPart = if (typeOperand.isMarkedNullable) + thenPart = if (typeOperand.isSimpleTypeWithQuestionMark) irNull() else - irCall(throwTypeCastException), + irCall(throwTypeCastException.owner), - elsePart = irAs(irGet(argument), typeOperand.makeNotNullable()) + elsePart = irAs(irGet(argument.owner), typeOperand.makeNotNull()) ) } } } - typeOperand.isMarkedNullable -> builder.irAs(expression.argument, typeOperand.makeNotNullable()) + typeOperand.isSimpleTypeWithQuestionMark -> builder.irAs(expression.argument, typeOperand.makeNotNull()) typeOperand == expression.typeOperand -> expression @@ -124,8 +131,8 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun return builder.irBlock(expression) { +irLetS(expression.argument) { variable -> irIfThenElse(expression.type, - condition = irIs(irGet(variable), typeOperand), - thenPart = irImplicitCast(irGet(variable), typeOperand), + condition = irIs(irGet(variable.owner), typeOperand), + thenPart = irImplicitCast(irGet(variable.owner), typeOperand), elsePart = irNull()) } } 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 3b15d92563a..5d6a84fdf05 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 @@ -35,24 +35,23 @@ import org.jetbrains.kotlin.backend.konan.isValueType import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.localHash import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.backend.js.utils.constructedClass import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.getArguments import org.jetbrains.kotlin.ir.util.simpleFunctions import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.util.OperatorNameConventions -private fun getClassWithBoxingIncluded(type: KotlinType, ir: KonanIr): ClassDescriptor? { +private fun getClassWithBoxingIncluded(type: IrType, ir: KonanIr): ClassDescriptor? { /* * Some primitive types can be null and some can't. Those that can't must be replaced with the corresponding box. * Int -> Int @@ -61,29 +60,29 @@ private fun getClassWithBoxingIncluded(type: KotlinType, ir: KonanIr): ClassDesc * CPointer -> CPointer * CPointer? -> CPointer */ - return if (type.correspondingValueType == null && type.makeNotNullable().correspondingValueType != null) - ir.getClass(ir.symbols.getTypeConversion(type.makeNotNullable(), type)!!.descriptor.returnType!!)!! + return if (type.correspondingValueType == null && type.makeNotNull().correspondingValueType != null) + ir.symbols.getTypeConversion(type.makeNotNull(), type)!!.owner.returnType.getClass()!! else - ir.getClass(type) + type.getClass() } -private fun computeErasure(type: KotlinType, ir: KonanIr, erasure: MutableList) { +private fun computeErasure(type: IrType, ir: KonanIr, erasure: MutableList) { val irClass = getClassWithBoxingIncluded(type, ir) if (irClass != null) { erasure += irClass } else { - val descriptor = type.constructor.declarationDescriptor - if (descriptor is TypeParameterDescriptor) { - descriptor.upperBounds.forEach { + val classifier = type.classifierOrFail + if (classifier is IrTypeParameterSymbol) { + classifier.owner.superTypes.forEach { computeErasure(it, ir, erasure) } } else { - TODO(descriptor.toString()) + TODO(classifier.descriptor.toString()) } } } -internal fun KotlinType.erasure(context: Context): List { +internal fun IrType.erasure(context: Context): List { val result = mutableListOf() computeErasure(this, context.ir, result) return result @@ -163,7 +162,7 @@ private class ExpressionValuesExtractor(val context: Context, forEachValue( expression = (expression.statements.last() as? IrExpression) ?: IrGetObjectValueImpl(expression.startOffset, expression.endOffset, - context.builtIns.unitType, context.ir.symbols.unit), + context.irBuiltIns.unitType, context.ir.symbols.unit), block = block ) } @@ -187,7 +186,8 @@ private class ExpressionValuesExtractor(val context: Context, else { // Propagate cast to sub-values. forEachValue(expression.argument) { value -> with(expression) { - block(IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, typeOperand, value)) + block(IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, typeOperand, + typeOperand.classifierOrFail, value)) } } } @@ -254,7 +254,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag override fun visitConstructor(declaration: IrConstructor) { val body = declaration.body - assert (body != null || declaration.symbol.constructedClass.kind == ClassKind.ANNOTATION_CLASS) { + assert (body != null || declaration.constructedClass.kind == ClassKind.ANNOTATION_CLASS) { "Non-annotation class constructor has empty body" } DEBUG_OUTPUT(0) { @@ -280,7 +280,8 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag println("Analysing global field ${declaration.descriptor}") println("IR: ${ir2stringWhole(declaration)}") } - analyze(declaration, IrSetFieldImpl(it.startOffset, it.endOffset, declaration.symbol, null, it.expression)) + analyze(declaration, IrSetFieldImpl(it.startOffset, it.endOffset, declaration.symbol, null, + it.expression, context.irBuiltIns.unitType)) } } @@ -379,11 +380,13 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag if (expression is IrCall && expression.symbol == scheduleImplSymbol) { // Producer and job of scheduleImpl are called externally, we need to reflect this somehow. val producerInvocation = IrCallImpl(expression.startOffset, expression.endOffset, + scheduleImplProducerInvoke.returnType, scheduleImplProducerInvoke.symbol, scheduleImplProducerInvoke.descriptor) producerInvocation.dispatchReceiver = expression.getValueArgument(2) val jobFunctionReference = expression.getValueArgument(3) as? IrFunctionReference ?: error("A function reference expected") val jobInvocation = IrCallImpl(expression.startOffset, expression.endOffset, + jobFunctionReference.symbol.owner.returnType, jobFunctionReference.symbol, jobFunctionReference.descriptor) jobInvocation.putValueArgument(0, producerInvocation) @@ -447,6 +450,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag .filterIsInstance().single { it.name.asString() == "doResume" }.symbol private val getContinuationSymbol = context.ir.symbols.getContinuation + private val continuationType = getContinuationSymbol.owner.returnType private val arrayGetSymbol = context.ir.symbols.arrayGet private val arraySetSymbol = context.ir.symbols.arraySet @@ -631,21 +635,27 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag val owner = callee.containingDeclaration as ClassDescriptor val actualReceiverType = value.dispatchReceiver!!.type val receiverType = - if (actualReceiverType.constructor.declarationDescriptor is TypeParameterDescriptor + if (actualReceiverType.classifierOrNull is IrTypeParameterSymbol || !callee.isReal /* Could be a bridge. */) symbolTable.mapClass(owner) else { - val actualClassAtCallsite = actualReceiverType.constructor.declarationDescriptor as org.jetbrains.kotlin.descriptors.ClassDescriptor - assert (DescriptorUtils.isSubclass(actualClassAtCallsite, owner.descriptor)) { - "Expected an inheritor of ${owner.descriptor}, but was $actualClassAtCallsite" + val actualClassAtCallsite = + actualReceiverType.classifierOrFail.descriptor + as org.jetbrains.kotlin.descriptors.ClassDescriptor +// assert (DescriptorUtils.isSubclass(actualClassAtCallsite, owner.descriptor)) { +// "Expected an inheritor of ${owner.descriptor}, but was $actualClassAtCallsite" +// } + if (DescriptorUtils.isSubclass(actualClassAtCallsite, owner.descriptor)) { + symbolTable.mapType( + actualReceiverType.let { + if (it.isValueType()) // A virtual call on a value type - it must be boxed. + context.ir.symbols.getTypeConversion(it, it.makeNullable())!!.owner.returnType + else it + } + ) + } else { + symbolTable.mapClass(owner) } - symbolTable.mapType( - actualReceiverType.let { - if (it.isValueType()) // A virtual call on a value type - it must be boxed. - context.ir.symbols.getTypeConversion(it, it.makeNullable())!!.descriptor.returnType!! - else it - } - ) } if (owner.isInterface) { val calleeHash = callee.functionName.localHash.value @@ -681,8 +691,9 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag } is IrDelegatingConstructorCall -> { - val thiz = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, - (descriptor as ConstructorDescriptor).constructedClass.thisReceiver!!.symbol) + val thisReceiver = (descriptor as ConstructorDescriptor).constructedClass.thisReceiver!! + val thiz = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, thisReceiver.type, + thisReceiver.symbol) val arguments = listOf(thiz) + value.getArguments().map { it.second } DataFlowIR.Node.StaticCall( symbolTable.mapFunction(value.symbol.owner), 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 0f45a7cc270..adfa90bd944 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 @@ -35,6 +35,10 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrGetField +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isNothing +import org.jetbrains.kotlin.ir.types.isUnit +import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature @@ -42,10 +46,6 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.IntValue -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes -import org.jetbrains.kotlin.types.typeUtil.isNothing -import org.jetbrains.kotlin.types.typeUtil.isUnit internal object DataFlowIR { @@ -468,7 +468,7 @@ internal object DataFlowIR { private val pointsToOnWhomDescriptor = pointsToAnnotationDescriptor.unsubstitutedPrimaryConstructor!!.valueParameters.single() private val getContinuationSymbol = context.ir.symbols.getContinuation - private val continuationType = getContinuationSymbol.descriptor.returnType!! + private val continuationType = getContinuationSymbol.owner.returnType var privateTypeIndex = 0 var privateFunIndex = 0 @@ -524,7 +524,7 @@ internal object DataFlowIR { classMap[descriptor] = type - type.superTypes += descriptor.defaultType.immediateSupertypes().map { mapType(it) } + type.superTypes += descriptor.superTypes.map { mapType(it) } if (!isAbstract) { val vtableBuilder = context.getVtableBuilder(descriptor) type.vtable += vtableBuilder.vtableEntries.map { mapFunction(it.getImplementation(context)!!) } @@ -541,7 +541,7 @@ internal object DataFlowIR { return erasure.singleOrNull { !it.isInterface } ?: context.ir.symbols.any.owner } - fun mapType(type: KotlinType) = mapClass(choosePrimary(type.erasure(context))) + fun mapType(type: IrType) = mapClass(choosePrimary(type.erasure(context))) // TODO: use from LlvmDeclarations. private fun getFqName(descriptor: DeclarationDescriptor): FqName = @@ -605,7 +605,7 @@ internal object DataFlowIR { .map { mapClass(choosePrimary(it.erasure(context))) } .toTypedArray() symbol.returnType = mapType(if (descriptor.isSuspend) - context.builtIns.anyType + context.irBuiltIns.anyType else descriptor.returnType) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt index 61e00f7e9f9..1955cde781f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt @@ -27,8 +27,7 @@ import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.descriptors.isInterface import org.jetbrains.kotlin.backend.konan.ir.IrPrivateClassReferenceImpl import org.jetbrains.kotlin.backend.konan.ir.IrPrivateFunctionCallImpl -import org.jetbrains.kotlin.backend.konan.lower.nullConst -import org.jetbrains.kotlin.backend.konan.objcexport.getErasedTypeClass +import org.jetbrains.kotlin.backend.konan.irasdescriptors.getErasedTypeClass import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.ir.IrElement @@ -40,14 +39,14 @@ import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.getValueArgument import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrWhenImpl import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.util.addArguments import org.jetbrains.kotlin.ir.util.getArguments +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.irCall +import org.jetbrains.kotlin.ir.util.explicitParameters import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.types.KotlinType import java.util.* import kotlin.collections.ArrayList @@ -1009,7 +1008,7 @@ internal object Devirtualization { class PossiblyCoercedValue(val value: IrVariable, val coercion: IrFunctionSymbol?) { fun getFullValue(irBuilder: IrBuilderWithScope) = irBuilder.run { - irCoerce(irGet(value.symbol), coercion) + irCoerce(irGet(value), coercion) } } @@ -1020,7 +1019,7 @@ internal object Devirtualization { val coercion = expression as IrCall PossiblyCoercedValue( irTemporary(irImplicitCast(coercion.getArguments().single().second, - coercion.descriptor.explicitParameters.single().type)) + coercion.symbol.owner.explicitParameters.single().type)) , coercion.symbol) } @@ -1041,12 +1040,12 @@ internal object Devirtualization { val coercion = context.ir.symbols.getTypeConversion(type.correspondingValueType, targetType.correspondingValueType) ?: return possiblyCoercedValue.getFullValue(this) if (prevCoercion == null) - return irCoerce(irGet(value.symbol), coercion) + return irCoerce(irGet(value), coercion) assertCoercionsMatch(coercion, prevCoercion) - return irGet(value.symbol) + return irGet(value) } - fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: KotlinType, + fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: IrType, devirtualizedCallee: DataFlowIR.FunctionSymbol.Declared) = IrPrivateFunctionCallImpl( startOffset = startOffset, @@ -1062,7 +1061,7 @@ internal object Devirtualization { virtualCallee = callee ) - fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: KotlinType, + fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: IrType, actualCallee: DataFlowIR.FunctionSymbol.Declared, receiver: IrVariable, extensionReceiver: PossiblyCoercedValue?, @@ -1070,7 +1069,7 @@ internal object Devirtualization { actualCallee.bridgeTarget.let { if (it == null) irDevirtualizedCall(callee, actualType, actualCallee).apply { - this.dispatchReceiver = irGet(receiver.symbol) + this.dispatchReceiver = irGet(receiver) this.extensionReceiver = extensionReceiver?.getFullValue(this@irDevirtualizedCall) callee.descriptor.valueParameters.forEach { putValueArgument(it.index, parameters[it]!!.getFullValue(this@irDevirtualizedCall)) @@ -1079,7 +1078,7 @@ internal object Devirtualization { else { val bridgeTarget = it.resolved() as DataFlowIR.FunctionSymbol.Declared val callResult = irDevirtualizedCall(callee, actualType, bridgeTarget).apply { - this.dispatchReceiver = irGet(receiver.symbol) + this.dispatchReceiver = irGet(receiver) this.extensionReceiver = extensionReceiver?.let { irCoerceIfNeeded( type = actualCallee.parameterTypes[1].resolved(), @@ -1140,21 +1139,22 @@ internal object Devirtualization { val startOffset = expression.startOffset val endOffset = expression.endOffset val type = if (descriptor.isSuspend) - context.builtIns.nullableAnyType - else descriptor.original.returnType!! + context.irBuiltIns.anyNType + else expression.symbol.owner.returnType val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset) irBuilder.run { val dispatchReceiver = expression.dispatchReceiver!! return when { possibleCallees.isEmpty() -> irBlock(expression) { - +irCall(context.ir.symbols.throwInvalidReceiverTypeException).apply { - putValueArgument(0, irCall(context.ir.symbols.kClassImplConstructor, listOf(dispatchReceiver.type)).apply { - putValueArgument(0, irCall(context.ir.symbols.getObjectTypeInfo).apply { + val throwExpr = irCall(context.ir.symbols.throwInvalidReceiverTypeException.owner).apply { + putValueArgument(0, irCall(context.ir.symbols.kClassImplConstructor.owner, listOf(dispatchReceiver.type)).apply { + putValueArgument(0, irCall(context.ir.symbols.getObjectTypeInfo.owner).apply { putValueArgument(0, dispatchReceiver) }) }) } - +nullConst(expression, type) + // Insert proper unboxing (unreachable code): + +irCoerce(throwExpr, context.ir.symbols.getTypeConversion(throwExpr.type, type)) } optimize && possibleCallees.size == 1 -> { // Monomorphic callsite. @@ -1176,7 +1176,7 @@ internal object Devirtualization { it to irSplitCoercion(expression.getValueArgument(it)!!) } val typeInfo = irTemporary(irCall(context.ir.symbols.getObjectTypeInfo).apply { - putValueArgument(0, irGet(receiver.symbol)) + putValueArgument(0, irGet(receiver)) }) val branches = mutableListOf() @@ -1186,8 +1186,8 @@ internal object Devirtualization { val expectedTypeInfo = IrPrivateClassReferenceImpl( startOffset = startOffset, endOffset = endOffset, - type = nativePtrType, - symbol = IrClassSymbolImpl(dispatchReceiver.type.getErasedTypeClass()), + type = context.ir.symbols.nativePtrType, + symbol = dispatchReceiver.type.getErasedTypeClass(), classType = receiver.type, moduleDescriptor = actualReceiverType.module!!.descriptor, totalClasses = actualReceiverType.module.numberOfClasses, @@ -1198,7 +1198,7 @@ internal object Devirtualization { irTrue() // Don't check last type in optimize mode. else irCall(nativePtrEqualityOperatorSymbol).apply { - putValueArgument(0, irGet(typeInfo.symbol)) + putValueArgument(0, irGet(typeInfo)) putValueArgument(1, expectedTypeInfo) } IrBranchImpl( @@ -1218,7 +1218,7 @@ internal object Devirtualization { irCall(context.ir.symbols.kClassImplConstructor, listOf(dispatchReceiver.type) ).apply { - putValueArgument(0, irGet(typeInfo.symbol)) + putValueArgument(0, irGet(typeInfo)) } ) }) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt index b2cae0926db..2e591bd77d0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt @@ -37,10 +37,10 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.impl.* -import org.jetbrains.kotlin.ir.util.addFakeOverrides -import org.jetbrains.kotlin.ir.util.createParameterDeclarations -import org.jetbrains.kotlin.ir.util.setOverrides -import org.jetbrains.kotlin.ir.util.setSuperSymbols +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.types.toKotlinType +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer import org.jetbrains.kotlin.metadata.KonanIr import org.jetbrains.kotlin.metadata.KonanIr.IrConst.ValueCase.* @@ -82,6 +82,8 @@ internal class IrSerializer(val context: Context, return irDescriptorSerializer.serializeKotlinType(type) } + private fun serializeKotlinType(type: IrType) = serializeKotlinType(type.toKotlinType()) + private fun serializeDescriptor(descriptor: DeclarationDescriptor): KonanIr.KotlinDescriptor { context.log{"### serializeDescriptor $descriptor"} @@ -719,12 +721,12 @@ internal class IrDeserializer(val context: Context, private fun deserializeDescriptor(proto: KonanIr.KotlinDescriptor) = descriptorDeserializer.deserializeDescriptor(proto) - private fun deserializeTypeArguments(proto: KonanIr.TypeArguments): List { + private fun deserializeTypeArguments(proto: KonanIr.TypeArguments): List { context.log{"### deserializeTypeArguments"} - val result = mutableListOf() + val result = mutableListOf() proto.typeArgumentList.forEach { type -> val kotlinType = deserializeKotlinType(type) - result.add(kotlinType) + result.add(kotlinType.brokenIr) context.log{"$kotlinType"} } return result @@ -782,6 +784,9 @@ internal class IrDeserializer(val context: Context, return element } + private val KotlinType.ir: IrType get() = context.ir.translateErased(this) + private val KotlinType.brokenIr: IrType get() = context.ir.translateBroken(this) + private fun deserializeBlock(proto: KonanIr.IrBlock, start: Int, end: Int, type: KotlinType): IrBlock { val statements = mutableListOf() val statementProtos = proto.statementList @@ -791,7 +796,7 @@ internal class IrDeserializer(val context: Context, val isLambdaOrigin = if (proto.isLambdaOrigin) IrStatementOrigin.LAMBDA else null - return IrBlockImpl(start, end, type, isLambdaOrigin, statements) + return IrBlockImpl(start, end, type.ir, isLambdaOrigin, statements) } private fun deserializeMemberAccessCommon(access: IrMemberAccessExpression, proto: KonanIr.MemberAccessCommon) { @@ -819,7 +824,7 @@ internal class IrDeserializer(val context: Context, val descriptor = deserializeDescriptor(proto.classDescriptor) as ClassifierDescriptor /** TODO: [createClassifierSymbolForClassReference] is internal function */ @Suppress("DEPRECATION") - return IrClassReferenceImpl(start, end, type, descriptor, descriptor.defaultType) + return IrClassReferenceImpl(start, end, type.ir, descriptor, descriptor.defaultType.ir) } private fun deserializeCall(proto: KonanIr.IrCall, start: Int, end: Int, type: KotlinType): IrCall { @@ -832,13 +837,13 @@ internal class IrDeserializer(val context: Context, val call: IrCall = when (proto.kind) { KonanIr.IrCall.Primitive.NOT_PRIMITIVE -> // TODO: implement the last three args here. - IrCallImpl(start, end, type, createFunctionSymbol(descriptor), descriptor, proto.memberAccess.typeArguments.typeArgumentCount, null, createClassSymbolOrNull(superDescriptor)) + IrCallImpl(start, end, type.ir, createFunctionSymbol(descriptor), descriptor, proto.memberAccess.typeArguments.typeArgumentCount, null, createClassSymbolOrNull(superDescriptor)) KonanIr.IrCall.Primitive.NULLARY -> - IrNullaryPrimitiveImpl(start, end, null, createFunctionSymbol(descriptor)) + IrNullaryPrimitiveImpl(start, end, type.ir, null, createFunctionSymbol(descriptor)) KonanIr.IrCall.Primitive.UNARY -> - IrUnaryPrimitiveImpl(start, end, null, createFunctionSymbol(descriptor)) + IrUnaryPrimitiveImpl(start, end, type.ir, null, createFunctionSymbol(descriptor)) KonanIr.IrCall.Primitive.BINARY -> - IrBinaryPrimitiveImpl(start, end, null, createFunctionSymbol(descriptor)) + IrBinaryPrimitiveImpl(start, end, type.ir, null, createFunctionSymbol(descriptor)) else -> TODO("Unexpected primitive IrCall.") } deserializeMemberAccessCommon(call, proto.memberAccess) @@ -850,7 +855,7 @@ internal class IrDeserializer(val context: Context, val descriptor = deserializeDescriptor(proto.descriptor) as CallableDescriptor val callable = when (descriptor) { - is FunctionDescriptor -> IrFunctionReferenceImpl(start, end, type, createFunctionSymbol(descriptor), descriptor, proto.typeArguments.typeArgumentCount, null) + is FunctionDescriptor -> IrFunctionReferenceImpl(start, end, type.ir, createFunctionSymbol(descriptor), descriptor, proto.typeArguments.typeArgumentCount, null) else -> TODO() } @@ -866,12 +871,12 @@ internal class IrDeserializer(val context: Context, statementProtos.forEach { statements.add(deserializeStatement(it) as IrStatement) } - return IrCompositeImpl(start, end, type, null, statements) + return IrCompositeImpl(start, end, type.ir, null, statements) } private fun deserializeDelegatingConstructorCall(proto: KonanIr.IrDelegatingConstructorCall, start: Int, end: Int): IrDelegatingConstructorCall { val descriptor = deserializeDescriptor(proto.descriptor) as ClassConstructorDescriptor - val call = IrDelegatingConstructorCallImpl(start, end, IrConstructorSymbolImpl(descriptor.original), descriptor, proto.memberAccess.typeArguments.typeArgumentCount) + val call = IrDelegatingConstructorCallImpl(start, end, context.irBuiltIns.unitType, IrConstructorSymbolImpl(descriptor.original), descriptor, proto.memberAccess.typeArguments.typeArgumentCount) deserializeMemberAccessCommon(call, proto.memberAccess) return call @@ -879,7 +884,7 @@ internal class IrDeserializer(val context: Context, private fun deserializeGetClass(proto: KonanIr.IrGetClass, start: Int, end: Int, type: KotlinType): IrGetClass { val argument = deserializeExpression(proto.argument) - return IrGetClassImpl(start, end, type, argument) + return IrGetClassImpl(start, end, type.ir, argument) } private fun deserializeGetField(proto: KonanIr.IrGetField, start: Int, end: Int): IrGetField { @@ -892,39 +897,39 @@ internal class IrDeserializer(val context: Context, deserializeExpression(access.receiver) } else null - return IrGetFieldImpl(start, end, IrFieldSymbolImpl(descriptor), receiver, null, createClassSymbolOrNull(superQualifier)) + return IrGetFieldImpl(start, end, IrFieldSymbolImpl(descriptor), descriptor.type.ir, receiver, null, createClassSymbolOrNull(superQualifier)) } private fun deserializeGetValue(proto: KonanIr.IrGetValue, start: Int, end: Int): IrGetValue { val descriptor = deserializeDescriptor(proto.descriptor) as ValueDescriptor // TODO: origin! - return IrGetValueImpl(start, end, createValueSymbol(descriptor), null) + return IrGetValueImpl(start, end, descriptor.type.ir, createValueSymbol(descriptor), null) } private fun deserializeGetEnumValue(proto: KonanIr.IrGetEnumValue, start: Int, end: Int): IrGetEnumValue { val type = deserializeKotlinType(proto.type) val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor - return IrGetEnumValueImpl(start, end, type, IrEnumEntrySymbolImpl(descriptor)) + return IrGetEnumValueImpl(start, end, type.ir, IrEnumEntrySymbolImpl(descriptor)) } private fun deserializeGetObject(proto: KonanIr.IrGetObject, start: Int, end: Int, type: KotlinType): IrGetObjectValue { val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor - return IrGetObjectValueImpl(start, end, type, IrClassSymbolImpl(descriptor)) + return IrGetObjectValueImpl(start, end, type.ir, IrClassSymbolImpl(descriptor)) } private fun deserializeInstanceInitializerCall(proto: KonanIr.IrInstanceInitializerCall, start: Int, end: Int): IrInstanceInitializerCall { val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor - return IrInstanceInitializerCallImpl(start, end, IrClassSymbolImpl(descriptor)) + return IrInstanceInitializerCallImpl(start, end, IrClassSymbolImpl(descriptor), context.irBuiltIns.unitType) } private fun deserializeReturn(proto: KonanIr.IrReturn, start: Int, end: Int, type: KotlinType): IrReturn { val descriptor = deserializeDescriptor(proto.returnTarget) as FunctionDescriptor val value = deserializeExpression(proto.value) - return IrReturnImpl(start, end, type, createFunctionSymbol(descriptor), value) + return IrReturnImpl(start, end, context.irBuiltIns.nothingType, createFunctionSymbol(descriptor), value) } private fun deserializeSetField(proto: KonanIr.IrSetField, start: Int, end: Int): IrSetField { @@ -938,13 +943,13 @@ internal class IrDeserializer(val context: Context, } else null val value = deserializeExpression(proto.value) - return IrSetFieldImpl(start, end, IrFieldSymbolImpl(descriptor), receiver, value, null, createClassSymbolOrNull(superQualifier)) + return IrSetFieldImpl(start, end, IrFieldSymbolImpl(descriptor), receiver, value, context.irBuiltIns.unitType, null, createClassSymbolOrNull(superQualifier)) } private fun deserializeSetVariable(proto: KonanIr.IrSetVariable, start: Int, end: Int): IrSetVariable { val descriptor = deserializeDescriptor(proto.descriptor) as VariableDescriptor val value = deserializeExpression(proto.value) - return IrSetVariableImpl(start, end, IrVariableSymbolImpl(descriptor), value, null) + return IrSetVariableImpl(start, end, context.irBuiltIns.unitType, IrVariableSymbolImpl(descriptor), value, null) } private fun deserializeSpreadElement(proto: KonanIr.IrSpreadElement): IrSpreadElement { @@ -959,11 +964,11 @@ internal class IrDeserializer(val context: Context, argumentProtos.forEach { arguments.add(deserializeExpression(it)) } - return IrStringConcatenationImpl(start, end, type, arguments) + return IrStringConcatenationImpl(start, end, type.ir, arguments) } private fun deserializeThrow(proto: KonanIr.IrThrow, start: Int, end: Int, type: KotlinType): IrThrowImpl { - return IrThrowImpl(start, end, type, deserializeExpression(proto.value)) + return IrThrowImpl(start, end, context.irBuiltIns.nothingType, deserializeExpression(proto.value)) } private fun deserializeTry(proto: KonanIr.IrTry, start: Int, end: Int, type: KotlinType): IrTryImpl { @@ -974,7 +979,7 @@ internal class IrDeserializer(val context: Context, } val finallyExpression = if (proto.hasFinally()) deserializeExpression(proto.getFinally()) else null - return IrTryImpl(start, end, type, result, catches, finallyExpression) + return IrTryImpl(start, end, type.ir, result, catches, finallyExpression) } private fun deserializeTypeOperator(operator: KonanIr.IrTypeOperator): IrTypeOperator { @@ -999,9 +1004,12 @@ internal class IrDeserializer(val context: Context, private fun deserializeTypeOp(proto: KonanIr.IrTypeOp, start: Int, end: Int, type: KotlinType) : IrTypeOperatorCall { val operator = deserializeTypeOperator(proto.operator) - val operand = deserializeKotlinType(proto.operand) + val operand = deserializeKotlinType(proto.operand).brokenIr val argument = deserializeExpression(proto.argument) - return IrTypeOperatorCallImpl(start, end, type, operator, operand, argument) + return IrTypeOperatorCallImpl(start, end, type.ir, operator, operand).apply { + this.argument = argument + this.typeOperandClassifier = operand.classifierOrFail + } } private fun deserializeVararg(proto: KonanIr.IrVararg, start: Int, end: Int, type: KotlinType): IrVararg { @@ -1011,7 +1019,7 @@ internal class IrDeserializer(val context: Context, proto.elementList.forEach { elements.add(deserializeVarargElement(it)) } - return IrVarargImpl(start, end, type, elementType, elements) + return IrVarargImpl(start, end, type.ir, elementType.ir, elements) } private fun deserializeVarargElement(element: KonanIr.IrVarargElement): IrVarargElement { @@ -1033,7 +1041,7 @@ internal class IrDeserializer(val context: Context, } // TODO: provide some origin! - return IrWhenImpl(start, end, type, null, branches) + return IrWhenImpl(start, end, type.ir, null, branches) } private fun deserializeLoop(proto: KonanIr.Loop, loop: IrLoopBase): IrLoopBase { @@ -1054,7 +1062,7 @@ internal class IrDeserializer(val context: Context, private fun deserializeDoWhile(proto: KonanIr.IrDoWhile, start: Int, end: Int, type: KotlinType): IrDoWhileLoop { // we create the loop before deserializing the body, so that // IrBreak statements have something to put into 'loop' field. - val loop = IrDoWhileLoopImpl(start, end, type, null) + val loop = IrDoWhileLoopImpl(start, end, type.ir, null) deserializeLoop(proto.loop, loop) return loop } @@ -1062,7 +1070,7 @@ internal class IrDeserializer(val context: Context, private fun deserializeWhile(proto: KonanIr.IrWhile, start: Int, end: Int, type: KotlinType): IrWhileLoop { // we create the loop before deserializing the body, so that // IrBreak statements have something to put into 'loop' field. - val loop = IrWhileLoopImpl(start, end, type, null) + val loop = IrWhileLoopImpl(start, end, type.ir, null) deserializeLoop(proto.loop, loop) return loop } @@ -1071,7 +1079,7 @@ internal class IrDeserializer(val context: Context, val label = if(proto.hasLabel()) proto.label else null val loopId = proto.loopId val loop = loopIndex[loopId]!! - val irBreak = IrBreakImpl(start, end, type, loop) + val irBreak = IrBreakImpl(start, end, type.ir, loop) irBreak.label = label return irBreak @@ -1081,7 +1089,7 @@ internal class IrDeserializer(val context: Context, val label = if(proto.hasLabel()) proto.label else null val loopId = proto.loopId val loop = loopIndex[loopId]!! - val irContinue = IrContinueImpl(start, end, type, loop) + val irContinue = IrContinueImpl(start, end, type.ir, loop) irContinue.label = label return irContinue @@ -1090,23 +1098,23 @@ internal class IrDeserializer(val context: Context, private fun deserializeConst(proto: KonanIr.IrConst, start: Int, end: Int, type: KotlinType): IrExpression = when(proto.valueCase) { NULL - -> IrConstImpl.constNull(start, end, type) + -> IrConstImpl.constNull(start, end, type.ir) BOOLEAN - -> IrConstImpl.boolean(start, end, type, proto.boolean) + -> IrConstImpl.boolean(start, end, type.ir, proto.boolean) BYTE - -> IrConstImpl.byte(start, end, type, proto.byte.toByte()) + -> IrConstImpl.byte(start, end, type.ir, proto.byte.toByte()) SHORT - -> IrConstImpl.short(start, end, type, proto.short.toShort()) + -> IrConstImpl.short(start, end, type.ir, proto.short.toShort()) INT - -> IrConstImpl.int(start, end, type, proto.int) + -> IrConstImpl.int(start, end, type.ir, proto.int) LONG - -> IrConstImpl.long(start, end, type, proto.long) + -> IrConstImpl.long(start, end, type.ir, proto.long) STRING - -> IrConstImpl.string(start, end, type, proto.string) + -> IrConstImpl.string(start, end, type.ir, proto.string) FLOAT - -> IrConstImpl.float(start, end, type, proto.float) + -> IrConstImpl.float(start, end, type.ir, proto.float) DOUBLE - -> IrConstImpl.double(start, end, type, proto.double) + -> IrConstImpl.double(start, end, type.ir, proto.double) else -> { TODO("Not all const types have been implemented") } @@ -1191,9 +1199,10 @@ internal class IrDeserializer(val context: Context, val clazz = IrClassImpl(start, end, origin, descriptor, members) - clazz.createParameterDeclarations() - clazz.addFakeOverrides() - clazz.setSuperSymbols(context.ir.symbols.symbolTable) + val symbolTable = context.ir.symbols.symbolTable + clazz.createParameterDeclarations(symbolTable) + clazz.addFakeOverrides(symbolTable) + clazz.setSuperSymbols(symbolTable) return clazz @@ -1203,10 +1212,12 @@ internal class IrDeserializer(val context: Context, start: Int, end: Int, origin: IrDeclarationOrigin): IrFunction { val body = deserializeStatement(proto.body) - val function = IrFunctionImpl(start, end, origin, - descriptor, body as IrBody) + val function = IrFunctionImpl(start, end, origin, descriptor) - function.createParameterDeclarations() + function.returnType = descriptor.returnType!!.ir + function.body = body as IrBody + + function.createParameterDeclarations(context.ir.symbols.symbolTable) function.setOverrides(context.ir.symbols.symbolTable) proto.defaultArgumentList.forEach { @@ -1226,7 +1237,7 @@ internal class IrDeserializer(val context: Context, deserializeExpression(proto.initializer) } else null - return IrVariableImpl(start, end, origin, descriptor, initializer) + return IrVariableImpl(start, end, origin, descriptor, descriptor.type.ir, initializer) } private fun deserializeIrEnumEntry(proto: KonanIr.IrEnumEntry, descriptor: ClassDescriptor, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt index 0a8fc245b0a..63eaeaae948 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt @@ -19,6 +19,8 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith +import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement @@ -26,6 +28,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.visitors.* @Deprecated("") @@ -47,11 +50,15 @@ internal fun IrModuleFragment.replaceUnboundSymbols(context: Context) { val symbolTable = context.ir.symbols.symbolTable - this.transformChildrenVoid(IrUnboundSymbolReplacer(symbolTable, collector.descriptorToSymbol)) + this.transformChildrenVoid(IrUnboundSymbolReplacer(symbolTable, collector.descriptorToSymbol, context)) // Generate missing external stubs: @Suppress("DEPRECATION") - ExternalDependenciesGenerator(symbolTable = context.psi2IrGeneratorContext.symbolTable, irBuiltIns = context.irBuiltIns).generateUnboundSymbolsAsDependencies(this) + ExternalDependenciesGenerator( + context.moduleDescriptor, + symbolTable = context.psi2IrGeneratorContext.symbolTable, + irBuiltIns = context.irBuiltIns + ).generateUnboundSymbolsAsDependencies(this) // Merge duplicated module and package declarations: this.acceptVoid(object : IrElementVisitorVoid { @@ -111,7 +118,8 @@ private class DeclarationSymbolCollector : IrElementVisitorVoid { private class IrUnboundSymbolReplacer( val symbolTable: SymbolTable, - val descriptorToSymbol: Map + val descriptorToSymbol: Map, + val context: Context ) : IrElementTransformerVoid() { private val localDescriptorToSymbol = mutableMapOf>() @@ -163,7 +171,7 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { - IrGetValueImpl(startOffset, endOffset, symbol, origin) + IrGetValueImpl(startOffset, endOffset, expression.type, symbol, origin) } } @@ -172,7 +180,7 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { - IrSetVariableImpl(startOffset, endOffset, symbol, value, origin) + IrSetVariableImpl(startOffset, endOffset, expression.type, symbol, value, origin) } } @@ -202,17 +210,11 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { - IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.descriptor.defaultType) + IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.typeWithStarProjections) } } override fun visitClass(declaration: IrClass): IrStatement { - declaration.superClasses.forEachIndexed { index, symbol -> - val newSymbol = symbol.replace(SymbolTable::referenceClass) - if (newSymbol != null) { - declaration.superClasses[index] = newSymbol - } - } withLocal(declaration.thisReceiver?.symbol) { return super.visitClass(declaration) } @@ -229,7 +231,7 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { - IrGetFieldImpl(startOffset, endOffset, symbol, receiver, origin, superQualifierSymbol) + IrGetFieldImpl(startOffset, endOffset, symbol, type, receiver, origin, superQualifierSymbol) } } @@ -244,11 +246,13 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { - IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, origin, superQualifierSymbol) + IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, type, origin, superQualifierSymbol) } } override fun visitCall(expression: IrCall): IrExpression { + expression.replaceTypeArguments() + val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: expression.symbol val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass) @@ -259,17 +263,21 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid() return with(expression) { - IrCallImpl(startOffset, endOffset, symbol, descriptor, - getTypeArgumentsMap(), + IrCallImpl(startOffset, endOffset, type, symbol, descriptor, + typeArgumentsCount, origin, superQualifierSymbol).also { it.copyArgumentsFrom(this) + it.copyTypeArgumentsFrom(this) } } } - private fun IrMemberAccessExpression.getTypeArgumentsMap() = - descriptor.original.typeParameters.associate { it to getTypeArgumentOrDefault(it) } + private fun IrMemberAccessExpression.replaceTypeArguments() { + repeat(typeArgumentsCount) { + putTypeArgument(it, getTypeArgument(it)?.toKotlinType()?.let { context.ir.translateErased(it) }) + } + } private fun IrMemberAccessExpressionBase.copyArgumentsFrom(original: IrMemberAccessExpression) { dispatchReceiver = original.dispatchReceiver @@ -284,37 +292,45 @@ private class IrUnboundSymbolReplacer( return super.visitEnumConstructorCall(expression) return with(expression) { - IrEnumConstructorCallImpl(startOffset, endOffset, symbol, null).also { + IrEnumConstructorCallImpl(startOffset, endOffset, expression.type, symbol, 0).also { it.copyArgumentsFrom(this) } } } override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { + expression.replaceTypeArguments() + val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?: return super.visitDelegatingConstructorCall(expression) expression.transformChildrenVoid() return with(expression) { - IrDelegatingConstructorCallImpl(startOffset, endOffset, symbol, descriptor, getTypeArgumentsMap()).also { + IrDelegatingConstructorCallImpl(startOffset, endOffset, type, symbol, descriptor, typeArgumentsCount).also { it.copyArgumentsFrom(this) + it.copyTypeArgumentsFrom(this) } } } override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + expression.replaceTypeArguments() + val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: return super.visitFunctionReference(expression) expression.transformChildrenVoid(this) return with(expression) { - IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, getTypeArgumentsMap()).also { + IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, 0).also { it.copyArgumentsFrom(this) + it.copyTypeArgumentsFrom(this) } } } override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { + expression.replaceTypeArguments() + val field = expression.field?.replaceOrSame(SymbolTable::referenceField) val getter = expression.getter?.replace(SymbolTable::referenceFunction) ?: expression.getter val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter @@ -325,13 +341,14 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { - IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor, + IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor, 0, field, getter, setter, - getTypeArgumentsMap(), origin).also { + origin).also { it.copyArgumentsFrom(this) + it.copyTypeArgumentsFrom(this) } } } @@ -413,7 +430,19 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { - IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol) + IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol, type) + } + } + + override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression { + expression.transformChildrenVoid(this) + + return with(expression) { + val newTypeOperand = context.ir.translateErased(typeOperand.toKotlinType()) + IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, newTypeOperand).also { + it.argument = argument + it.typeOperandClassifier = newTypeOperand.classifier + } } } } 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 c641592a4e1..1eddd7ed63a 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 @@ -17,26 +17,40 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.backend.common.descriptors.substitute import org.jetbrains.kotlin.backend.konan.KonanBackendContext import org.jetbrains.kotlin.backend.konan.KonanCompilationException import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ParameterDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl -import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl +import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl +import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.OverridingStrategy import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes import java.lang.reflect.Proxy //TODO: delete file on next kotlin dependency update @@ -63,25 +77,20 @@ internal fun IrFile.addTopLevelInitializer(expression: IrExpression) { ) val builtIns = fieldDescriptor.builtIns - fieldDescriptor.setType(builtIns.unitType, emptyList(), null, null as KotlinType?) + fieldDescriptor.setType(expression.type.toKotlinType(), emptyList(), null, null as KotlinType?) fieldDescriptor.initialize(null, null) val irField = IrFieldImpl( expression.startOffset, expression.endOffset, - IrDeclarationOrigin.DEFINED, fieldDescriptor + IrDeclarationOrigin.DEFINED, fieldDescriptor, expression.type ) - val initializer = IrTypeOperatorCallImpl( - expression.startOffset, expression.endOffset, builtIns.unitType, - IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, builtIns.unitType, expression - ) - - irField.initializer = IrExpressionBodyImpl(expression.startOffset, expression.endOffset, initializer) + irField.initializer = IrExpressionBodyImpl(expression.startOffset, expression.endOffset, expression) this.addChild(irField) } -fun IrClass.addFakeOverrides() { +fun IrClass.addFakeOverrides(symbolTable: SymbolTable) { val startOffset = this.startOffset val endOffset = this.endOffset @@ -90,17 +99,23 @@ fun IrClass.addFakeOverrides() { .filterIsInstance() .filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE } .forEach { - this.addChild(createFakeOverride(it, startOffset, endOffset)) + this.addChild(createFakeOverride(it, startOffset, endOffset, symbolTable)) } } -private fun createFakeOverride(descriptor: CallableMemberDescriptor, startOffset: Int, endOffset: Int): IrDeclaration { +private fun createFakeOverride( + descriptor: CallableMemberDescriptor, + startOffset: Int, + endOffset: Int, + symbolTable: SymbolTable +): IrDeclaration { - fun FunctionDescriptor.createFunction(): IrFunction = IrFunctionImpl( + fun FunctionDescriptor.createFunction(): IrSimpleFunction = IrFunctionImpl( startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, this ).apply { - createParameterDeclarations() + returnType = symbolTable.translateErased(this@createFunction.returnType!!) + createParameterDeclarations(symbolTable) } return when (descriptor) { @@ -115,11 +130,13 @@ private fun createFakeOverride(descriptor: CallableMemberDescriptor, startOffset } } -fun IrFunction.createParameterDeclarations() { +fun IrFunction.createParameterDeclarations(symbolTable: SymbolTable) { + fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl( innerStartOffset(this), innerEndOffset(this), IrDeclarationOrigin.DEFINED, - this + this, symbolTable.translateErased(this.type), + (this as? ValueParameterDescriptor)?.varargElementType?.let { symbolTable.translateErased(it) } ).also { it.parent = this@createParameterDeclarations } @@ -138,18 +155,84 @@ fun IrFunction.createParameterDeclarations() { it ).also { typeParameter -> typeParameter.parent = this + typeParameter.descriptor.upperBounds.mapTo(typeParameter.superTypes, symbolTable::translateErased) } } } +private fun createFakeOverride( + descriptor: CallableMemberDescriptor, + overriddenDeclarations: List, + irClass: IrClass +): IrDeclaration { + + // TODO: this function doesn't substitute types. + fun IrSimpleFunction.copyFake(descriptor: FunctionDescriptor): IrSimpleFunction = IrFunctionImpl( + irClass.startOffset, irClass.endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, descriptor + ).also { + it.returnType = returnType + it.parent = irClass + it.createDispatchReceiverParameter() + + it.extensionReceiverParameter = this.extensionReceiverParameter?.let { + IrValueParameterImpl( + it.startOffset, + it.endOffset, + IrDeclarationOrigin.DEFINED, + it.descriptor.extensionReceiverParameter!!, + it.type, + null + ) + } + + this.valueParameters.mapTo(it.valueParameters) { oldParameter -> + IrValueParameterImpl( + oldParameter.startOffset, + oldParameter.endOffset, + IrDeclarationOrigin.DEFINED, + it.descriptor.valueParameters[oldParameter.index], + oldParameter.type, + (oldParameter as? IrValueParameter)?.varargElementType + ) + } + + this.typeParameters.mapTo(it.typeParameters) { oldParameter -> + IrTypeParameterImpl( + irClass.startOffset, + irClass.endOffset, + IrDeclarationOrigin.DEFINED, + it.descriptor.typeParameters[oldParameter.index] + ).apply { + superTypes += oldParameter.superTypes + } + } + } + + val copiedDeclaration = overriddenDeclarations.first() + + return when (copiedDeclaration) { + is IrSimpleFunction -> copiedDeclaration.copyFake(descriptor as FunctionDescriptor) + is IrProperty -> IrPropertyImpl( + irClass.startOffset, + irClass.endOffset, + IrDeclarationOrigin.FAKE_OVERRIDE, + descriptor as PropertyDescriptor + ).apply { + parent = irClass + getter = copiedDeclaration.getter?.copyFake(descriptor.getter!!) + setter = copiedDeclaration.setter?.copyFake(descriptor.setter!!) + } + else -> error(copiedDeclaration) + } +} + + fun IrSimpleFunction.setOverrides(symbolTable: SymbolTable) { assert(this.overriddenSymbols.isEmpty()) this.descriptor.overriddenDescriptors.mapTo(this.overriddenSymbols) { symbolTable.referenceSimpleFunction(it.original) } - - this.typeParameters.forEach { it.setSupers(symbolTable) } } fun IrClass.simpleFunctions(): List = this.declarations.flatMap { @@ -161,32 +244,56 @@ fun IrClass.simpleFunctions(): List = this.declarations.flatMa } fun IrClass.createParameterDeclarations() { - descriptor.thisAsReceiverParameter.let { - thisReceiver = IrValueParameterImpl( - innerStartOffset(it), innerEndOffset(it), - IrDeclarationOrigin.INSTANCE_RECEIVER, - it - ).also { valueParameter -> - valueParameter.parent = this - } + thisReceiver = IrValueParameterImpl( + startOffset, endOffset, + IrDeclarationOrigin.INSTANCE_RECEIVER, + descriptor.thisAsReceiverParameter, + this.symbol.typeWith(this.typeParameters.map { it.defaultType }), + null + ).also { valueParameter -> + valueParameter.parent = this } assert(typeParameters.isEmpty()) - descriptor.declaredTypeParameters.mapTo(typeParameters) { - IrTypeParameterImpl( - innerStartOffset(it), innerEndOffset(it), - IrDeclarationOrigin.DEFINED, - it - ).also { typeParameter -> - typeParameter.parent = this - } - } + assert(descriptor.declaredTypeParameters.isEmpty()) } -fun IrClass.setSuperSymbols(supers: List) { +fun IrFunction.createDispatchReceiverParameter() { + assert(this.dispatchReceiverParameter == null) + + val descriptor = this.descriptor.dispatchReceiverParameter ?: return + + this.dispatchReceiverParameter = IrValueParameterImpl( + startOffset, + endOffset, + IrDeclarationOrigin.DEFINED, + descriptor, + (parent as IrClass).defaultType, + null + ).also { it.parent = this } +} + +fun IrClass.createParameterDeclarations(symbolTable: SymbolTable) { + this.descriptor.declaredTypeParameters.mapTo(this.typeParameters) { + IrTypeParameterImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, it).apply { + it.upperBounds.mapTo(this.superTypes, symbolTable::translateErased) + } + } + + this.thisReceiver = IrValueParameterImpl( + startOffset, endOffset, + IrDeclarationOrigin.DEFINED, + this.descriptor.thisAsReceiverParameter, + this.symbol.typeWith(this.typeParameters.map { it.defaultType }), + null + ) +} + +fun IrClass.setSuperSymbols(superTypes: List) { + val supers = superTypes.map { it.getClass()!! } assert(this.superDescriptors().toSet() == supers.map { it.descriptor }.toSet()) - assert(this.superClasses.isEmpty()) - supers.mapTo(this.superClasses) { it.symbol } + assert(this.superTypes.isEmpty()) + this.superTypes += superTypes val superMembers = supers.flatMap { it.simpleFunctions() @@ -206,48 +313,38 @@ private fun IrClass.superDescriptors() = this.descriptor.typeConstructor.supertypes.map { it.constructor.declarationDescriptor as ClassDescriptor } fun IrClass.setSuperSymbols(symbolTable: SymbolTable) { - assert(this.superClasses.isEmpty()) - this.superDescriptors().mapTo(this.superClasses) { symbolTable.referenceClass(it) } + assert(this.superTypes.isEmpty()) + this.descriptor.typeConstructor.supertypes.mapTo(this.superTypes) { symbolTable.translateErased(it) } + this.simpleFunctions().forEach { it.setOverrides(symbolTable) } - this.typeParameters.forEach { - it.setSupers(symbolTable) - } } -fun IrTypeParameter.setSupers(symbolTable: SymbolTable) { - assert(this.superClassifiers.isEmpty()) - this.descriptor.upperBounds.mapNotNullTo(this.superClassifiers) { - it.constructor.declarationDescriptor?.let { - if (it is TypeParameterDescriptor) { - IrTypeParameterSymbolImpl(it) // Workaround for deserialized inline functions - } else { - symbolTable.referenceClassifier(it) - } - } - } -} - -fun IrClass.setSuperSymbolsAndAddFakeOverrides(supers: List) { +fun IrClass.setSuperSymbolsAndAddFakeOverrides(superTypes: List) { val overriddenSuperMembers = this.declarations.map { it.descriptor } - .filterIsInstance().flatMap { it.overriddenDescriptors.map { it.original } } + .filterIsInstance().flatMap { it.overriddenDescriptors.map { it.original } }.toSet() - val unoverriddenSuperMembers = supers.flatMap { - it.declarations.mapNotNull { + val unoverriddenSuperMembers = superTypes.map { it.getClass()!! }.flatMap { + it.declarations.filter { it.descriptor !in overriddenSuperMembers }.mapNotNull { when (it) { - is IrSimpleFunction -> it.descriptor - is IrProperty -> it.descriptor + is IrSimpleFunction -> it.descriptor to it + is IrProperty -> it.descriptor to it else -> null } } - } - overriddenSuperMembers + }.toMap() val irClass = this val overridingStrategy = object : OverridingStrategy() { override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) { - irClass.addChild(createFakeOverride(fakeOverride, startOffset, endOffset)) + val overriddenDeclarations = + fakeOverride.overriddenDescriptors.map { unoverriddenSuperMembers[it]!! } + + assert(overriddenDeclarations.isNotEmpty()) + + irClass.declarations.add(createFakeOverride(fakeOverride, overriddenDeclarations, irClass)) } override fun inheritanceConflict(first: CallableMemberDescriptor, second: CallableMemberDescriptor) { @@ -259,7 +356,7 @@ fun IrClass.setSuperSymbolsAndAddFakeOverrides(supers: List) { } } - unoverriddenSuperMembers.groupBy { it.name }.forEach { (name, members) -> + unoverriddenSuperMembers.keys.groupBy { it.name }.forEach { (name, members) -> OverridingUtil.generateOverridesInFunctionGroup( name, members, @@ -269,7 +366,7 @@ fun IrClass.setSuperSymbolsAndAddFakeOverrides(supers: List) { ) } - this.setSuperSymbols(supers) + this.setSuperSymbols(superTypes) } private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int = @@ -327,7 +424,7 @@ object CheckDeclarationParentsVisitor : IrElementVisitor) { + val unhandledParameters = args.keys.toMutableSet() + fun getArg(parameter: IrValueParameter) = args[parameter]?.also { unhandledParameters -= parameter } + + symbol.owner.dispatchReceiverParameter?.let { + val arg = getArg(it) + if (arg != null) { + this.dispatchReceiver = arg + } + } + + symbol.owner.extensionReceiverParameter?.let { + val arg = getArg(it) + if (arg != null) { + this.extensionReceiver = arg + } + } + + symbol.owner.valueParameters.forEach { + val arg = getArg(it) + if (arg != null) { + this.putValueArgument(it.index, arg) + } + } +} + +private fun FunctionDescriptor.substitute( + typeArguments: List +): FunctionDescriptor = if (typeArguments.isEmpty()) { + this +} else { + this.substitute(*typeArguments.map { it.toKotlinType() }.toTypedArray()) +} + +fun IrType.substitute(map: Map): IrType { + if (this !is IrSimpleType) return this + + val classifier = this.classifier + return when (classifier) { + is IrTypeParameterSymbol -> + map[classifier]?.let { if (this.hasQuestionMark) it.makeNullable() else it } + ?: this + + is IrClassSymbol -> if (this.arguments.isEmpty()) { + this // Fast path. + } else { + val newArguments = this.arguments.map { + when (it) { + is IrTypeProjection -> makeTypeProjection(it.type.substitute(map), it.variance) + is IrStarProjection -> it + else -> error(it) + } + } + IrSimpleTypeImpl(classifier, hasQuestionMark, newArguments, annotations) + } + else -> error(classifier) + } + +} + +private fun IrFunction.substitutedReturnType(typeArguments: List): IrType { + val unsubstituted = this.returnType + if (typeArguments.isEmpty()) return unsubstituted // Fast path. + if (this is IrConstructor) { + // Workaround for missing type parameters in constructors. TODO: remove. + return this.returnType.classifierOrFail.typeWith(typeArguments) + } + + assert(this.typeParameters.size >= typeArguments.size) // TODO: check equality. + // TODO: receiver type must also be considered. + return unsubstituted.substitute(this.typeParameters.map { it.symbol }.zip(typeArguments).toMap()) +} + +// 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) + +fun IrBuilderWithScope.irCall( + irFunction: IrFunction, + typeArguments: List = emptyList() +): IrCall = irCall(this.startOffset, this.endOffset, irFunction, typeArguments) + +internal fun irCall(startOffset: Int, endOffset: Int, irFunction: IrFunction, typeArguments: List): IrCall = + IrCallImpl( + startOffset, endOffset, irFunction.substitutedReturnType(typeArguments), + irFunction.symbol, irFunction.descriptor.substitute(typeArguments), typeArguments.size + ).apply { + typeArguments.forEachIndexed { index, irType -> + this.putTypeArgument(index, irType) + } + } + +fun IrBuilderWithScope.irCall( + irFunction: IrFunctionSymbol, + type: IrType, + typeArguments: List = emptyList() +): IrCall = IrCallImpl( + startOffset, endOffset, type, + irFunction, irFunction.descriptor.substitute(typeArguments), typeArguments.size +).apply { + typeArguments.forEachIndexed { index, irType -> + this.putTypeArgument(index, irType) + } +} + +fun IrBuilderWithScope.irCallOp( + callee: IrFunction, + dispatchReceiver: IrExpression, + argument: IrExpression +): IrCall = + irCall(callee).apply { + this.dispatchReceiver = dispatchReceiver + putValueArgument(0, argument) + } + +fun IrBuilderWithScope.irSetVar(variable: IrVariable, value: IrExpression) = + irSetVar(variable.symbol, value) + +fun IrBuilderWithScope.irSetField(receiver: IrExpression, irField: IrField, value: IrExpression): IrExpression = + IrSetFieldImpl( + startOffset, + endOffset, + irField.symbol, + receiver = receiver, + value = value, + type = context.irBuiltIns.unitType + ) + +/** + * Binds the arguments explicitly represented in the IR to the parameters of the accessed function. + * The arguments are to be evaluated in the same order as they appear in the resulting list. + */ +fun IrMemberAccessExpression.getArgumentsWithIr(): List> { + val res = mutableListOf>() + val irFunction = when (this) { + is IrFunctionAccessExpression -> this.symbol.owner + is IrFunctionReference -> this.symbol.owner + else -> error(this) + } + + dispatchReceiver?.let { + res += (irFunction.dispatchReceiverParameter!! to it) + } + + extensionReceiver?.let { + res += (irFunction.extensionReceiverParameter!! to it) + } + + irFunction.valueParameters.forEachIndexed { index, it -> + val arg = getValueArgument(index) + if (arg != null) { + res += (it to arg) + } + } + + return res +} + +fun CallableMemberDescriptor.createValueParameter( + index: Int, + name: String, + type: IrType, + startOffset: Int, + endOffset: Int +): IrValueParameter { + val descriptor = ValueParameterDescriptorImpl( + this, null, + index, + Annotations.EMPTY, + Name.identifier(name), + type.toKotlinType(), + false, false, false, null, SourceElement.NO_SOURCE + ) + + return IrValueParameterImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, descriptor, type, null) +} + +fun SymbolTable.translateErased(type: KotlinType): IrSimpleType { + val descriptor = TypeUtils.getClassDescriptor(type) + if (descriptor == null) return translateErased(type.immediateSupertypes().first()) + val classSymbol = this.referenceClass(descriptor) + + val nullable = type.isMarkedNullable + val arguments = type.arguments.map { IrStarProjectionImpl } + + return classSymbol.createType(nullable, arguments) +} + +fun CommonBackendContext.createArrayOfExpression( + arrayElementType: IrType, + arrayElements: List, + startOffset: Int, endOffset: Int +): IrExpression { + + val arrayType = ir.symbols.array.typeWith(arrayElementType) + val arg0 = IrVarargImpl(startOffset, endOffset, arrayType, arrayElementType, arrayElements) + + return irCall(startOffset, endOffset, ir.symbols.arrayOf.owner, listOf(arrayElementType)).apply { + putValueArgument(0, arg0) + } +} + +fun createField( + startOffset: Int, + endOffset: Int, + type: IrType, + name: Name, + isMutable: Boolean, + origin: IrDeclarationOrigin, + owner: ClassDescriptor +): IrField { + val descriptor = PropertyDescriptorImpl.create( + /* containingDeclaration = */ owner, + /* annotations = */ Annotations.EMPTY, + /* modality = */ Modality.FINAL, + /* visibility = */ Visibilities.PRIVATE, + /* isVar = */ isMutable, + /* name = */ name, + /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, + /* source = */ SourceElement.NO_SOURCE, + /* lateInit = */ false, + /* isConst = */ false, + /* isExpect = */ false, + /* isActual = */ false, + /* isExternal = */ false, + /* isDelegated = */ false + ).apply { + initialize(null, null) + + val receiverType: KotlinType? = null + setType(type.toKotlinType(), emptyList(), owner.thisAsReceiverParameter, receiverType) + } + + return IrFieldImpl(startOffset, endOffset, origin, descriptor, type) +} + +fun IrValueParameter.copy(newDescriptor: ParameterDescriptor): IrValueParameter { + assert(this.descriptor.type == newDescriptor.type) + + return IrValueParameterImpl( + startOffset, + endOffset, + IrDeclarationOrigin.DEFINED, + newDescriptor, + type, + varargElementType + ) +} + +val IrTypeArgument.typeOrNull: IrType? get() = (this as? IrTypeProjection)?.type + +val IrType.isSimpleTypeWithQuestionMark: Boolean + get() = this is IrSimpleType && this.hasQuestionMark diff --git a/backend.native/tests/external/codegen/box/callableReference/property/genericProperty.kt b/backend.native/tests/external/codegen/box/callableReference/property/genericProperty.kt index a30bcbd89bd..63de5fccffe 100644 --- a/backend.native/tests/external/codegen/box/callableReference/property/genericProperty.kt +++ b/backend.native/tests/external/codegen/box/callableReference/property/genericProperty.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND: NATIVE //For KT-6020 import kotlin.reflect.KProperty1 import kotlin.reflect.KMutableProperty1 diff --git a/runtime/src/main/kotlin/konan/worker/Worker.kt b/runtime/src/main/kotlin/konan/worker/Worker.kt index c9972bdaa1a..17a7bde7e2a 100644 --- a/runtime/src/main/kotlin/konan/worker/Worker.kt +++ b/runtime/src/main/kotlin/konan/worker/Worker.kt @@ -47,7 +47,7 @@ class Worker(val id: WorkerId) { * until all scheduled jobs processed, or terminate immediately. */ fun requestTermination(processScheduledJobs: Boolean = true) = - Future(requestTerminationInternal(id, processScheduledJobs)) + Future(requestTerminationInternal(id, processScheduledJobs)) /** * Schedule a job for further execution in the worker. Schedule is a two-phase operation,