From fbd49a94e15ccd019ad3dccbb9fe2d4e6af5b6d7 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Mon, 28 Jan 2019 18:11:49 +0300 Subject: [PATCH] Inliner: removed old copier + refactor --- .../lower/DeepCopyIrTreeWithDescriptors.kt | 830 +----------------- .../backend/konan/lower/FunctionInlining.kt | 780 +++++++--------- 2 files changed, 325 insertions(+), 1285 deletions(-) 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 ef82572f774..3794aa2473a 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 @@ -5,24 +5,13 @@ package org.jetbrains.kotlin.backend.konan.lower -import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext -import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext import org.jetbrains.kotlin.backend.common.descriptors.* -import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.createExtensionReceiver -import org.jetbrains.kotlin.backend.konan.descriptors.initialize 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.* -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.expressions.IrCall import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.symbols.impl.createClassSymbolOrNull -import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection @@ -30,22 +19,13 @@ import org.jetbrains.kotlin.ir.util.* 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.name.Name -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces -import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeSubstitutor -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.Variance internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context, val typeArguments: Map?, - val parent: IrDeclarationParent?) : IrCopierForInliner { + val parent: IrDeclarationParent?) { - override fun copy(irElement: IrElement): IrElement { + fun copy(irElement: IrElement): IrElement { // Create new symbols. irElement.acceptVoid(symbolRemapper) @@ -196,8 +176,6 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context, } } - override fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap) { } - private class SymbolRemapperImpl(descriptorsRemapper: DescriptorsRemapper) : DeepCopySymbolRemapper(descriptorsRemapper) { @@ -223,804 +201,4 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context, InlinerTypeRemapper(symbolRemapper, typeArguments), InlinerSymbolRenamer() ) -} - -internal interface IrCopierForInliner { - fun copy(irElement: IrElement): IrElement - fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap) -} - -internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor, - val parentDescriptor: DeclarationDescriptor, - val context: Context, - val typeSubstitutor: TypeSubstitutor?) : IrCopierForInliner { - - private val descriptorSubstituteMap: MutableMap = mutableMapOf() - private var nameIndex = 0 - - //-------------------------------------------------------------------------// - - override fun copy(irElement: IrElement): IrElement { - // Create all class descriptors and all necessary descriptors in order to create KotlinTypes. - irElement.acceptVoid(DescriptorCollectorCreatePhase()) - // Initialize all created descriptors possibly using previously created types. - irElement.acceptVoid(DescriptorCollectorInitPhase()) - return irElement.accept(InlineCopyIr(), null) - } - - inner class DescriptorCollectorCreatePhase : IrElementVisitorVoidWithContext() { - - override fun visitElement(element: IrElement) { - element.acceptChildren(this, null) - } - - //---------------------------------------------------------------------// - - override fun visitClassNew(declaration: IrClass) { - val oldDescriptor = declaration.descriptor - val newDescriptor = copyClassDescriptor(oldDescriptor) - descriptorSubstituteMap[oldDescriptor] = newDescriptor - descriptorSubstituteMap[oldDescriptor.thisAsReceiverParameter] = newDescriptor.thisAsReceiverParameter - - super.visitClassNew(declaration) - - val constructors = oldDescriptor.constructors.map { oldConstructorDescriptor -> - descriptorSubstituteMap[oldConstructorDescriptor] as ClassConstructorDescriptor - }.toSet() - - val oldPrimaryConstructor = oldDescriptor.unsubstitutedPrimaryConstructor - val primaryConstructor = oldPrimaryConstructor?.let { descriptorSubstituteMap[it] as ClassConstructorDescriptor } - - val contributedDescriptors = oldDescriptor.unsubstitutedMemberScope - .getContributedDescriptors() - .map { descriptorSubstituteMap[it]!! } - newDescriptor.initialize( - SimpleMemberScope(contributedDescriptors), - constructors, - primaryConstructor - ) - } - - //---------------------------------------------------------------------// - - override fun visitPropertyNew(declaration: IrProperty) { - copyPropertyOrField(declaration.descriptor) - super.visitPropertyNew(declaration) - } - - //---------------------------------------------------------------------// - - override fun visitFieldNew(declaration: IrField) { - val oldDescriptor = declaration.descriptor - if (descriptorSubstituteMap[oldDescriptor] == null) { - copyPropertyOrField(oldDescriptor) // A field without a property or a field of a delegated property. - } - super.visitFieldNew(declaration) - } - - //---------------------------------------------------------------------// - - override fun visitFunctionNew(declaration: IrFunction) { - val oldDescriptor = declaration.descriptor - if (oldDescriptor !is PropertyAccessorDescriptor) { // Property accessors are copied along with their property. - val oldContainingDeclaration = - if (oldDescriptor.visibility == Visibilities.LOCAL) - parentDescriptor - else - oldDescriptor.containingDeclaration - descriptorSubstituteMap[oldDescriptor] = copyFunctionDescriptor(oldDescriptor, oldContainingDeclaration) - } - super.visitFunctionNew(declaration) - } - - //--- Copy descriptors ------------------------------------------------// - - private fun generateCopyName(name: Name): Name { - val declarationName = name.toString() // Name of declaration - val indexStr = (nameIndex++).toString() // Unique for inline target index - return Name.identifier(declarationName + "_" + indexStr) - } - - //---------------------------------------------------------------------// - - private fun copyFunctionDescriptor(oldDescriptor: CallableDescriptor, oldContainingDeclaration: DeclarationDescriptor) = - when (oldDescriptor) { - is ConstructorDescriptor -> copyConstructorDescriptor(oldDescriptor) - is SimpleFunctionDescriptor -> copySimpleFunctionDescriptor(oldDescriptor, oldContainingDeclaration) - else -> TODO("Unsupported FunctionDescriptor subtype: $oldDescriptor") - } - - //---------------------------------------------------------------------// - - private fun copySimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor, oldContainingDeclaration: DeclarationDescriptor) : FunctionDescriptor { - val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) - return SimpleFunctionDescriptorImpl.create( - /* containingDeclaration = */ newContainingDeclaration, - /* annotations = */ oldDescriptor.annotations, - /* name = */ generateCopyName(oldDescriptor.name), - /* kind = */ oldDescriptor.kind, - /* source = */ oldDescriptor.source - ) - } - - //---------------------------------------------------------------------// - - private fun copyConstructorDescriptor(oldDescriptor: ConstructorDescriptor) : FunctionDescriptor { - val oldContainingDeclaration = oldDescriptor.containingDeclaration - val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) - return ClassConstructorDescriptorImpl.create( - /* containingDeclaration = */ newContainingDeclaration as ClassDescriptor, - /* annotations = */ oldDescriptor.annotations, - /* isPrimary = */ oldDescriptor.isPrimary, - /* source = */ oldDescriptor.source - ) - } - - //---------------------------------------------------------------------// - - private fun copyPropertyOrField(oldDescriptor: PropertyDescriptor) { - val oldContainingDeclaration = oldDescriptor.containingDeclaration - val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) as ClassDescriptor - @Suppress("DEPRECATION") - val newDescriptor = PropertyDescriptorImpl.create( - /* containingDeclaration = */ newContainingDeclaration, - /* annotations = */ oldDescriptor.annotations, - /* modality = */ oldDescriptor.modality, - /* visibility = */ oldDescriptor.visibility, - /* isVar = */ oldDescriptor.isVar, - /* name = */ oldDescriptor.name, - /* kind = */ oldDescriptor.kind, - /* source = */ oldDescriptor.source, - /* lateInit = */ oldDescriptor.isLateInit, - /* isConst = */ oldDescriptor.isConst, - /* isExpect = */ oldDescriptor.isExpect, - /* isActual = */ oldDescriptor.isActual, - /* isExternal = */ oldDescriptor.isExternal, - /* isDelegated = */ oldDescriptor.isDelegated - ) - descriptorSubstituteMap[oldDescriptor] = newDescriptor - } - - //---------------------------------------------------------------------// - - private fun copyClassDescriptor(oldDescriptor: ClassDescriptor): ClassDescriptorImpl { - val oldSuperClass = oldDescriptor.getSuperClassOrAny() - val newSuperClass = descriptorSubstituteMap.getOrDefault(oldSuperClass, oldSuperClass) as ClassDescriptor - val oldInterfaces = oldDescriptor.getSuperInterfaces() - val newInterfaces = oldInterfaces.map { descriptorSubstituteMap.getOrDefault(it, it) as ClassDescriptor } - val oldContainingDeclaration = oldDescriptor.containingDeclaration - val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) - val newName = if (DescriptorUtils.isAnonymousObject(oldDescriptor)) // Anonymous objects are identified by their name. - oldDescriptor.name // We need to preserve it for LocalDeclarationsLowering. - else - generateCopyName(oldDescriptor.name) - - val visibility = oldDescriptor.visibility - - return object : ClassDescriptorImpl( - /* containingDeclaration = */ newContainingDeclaration, - /* name = */ newName, - /* modality = */ oldDescriptor.modality, - /* kind = */ oldDescriptor.kind, - /* supertypes = */ listOf(newSuperClass.defaultType) + newInterfaces.map { it.defaultType }, - /* source = */ oldDescriptor.source, - /* isExternal = */ oldDescriptor.isExternal, - /* storageManager = */ LockBasedStorageManager.NO_LOCKS - ) { - override fun getVisibility() = visibility - - override fun getDeclaredTypeParameters(): List { - return oldDescriptor.declaredTypeParameters - } - } - } - } - - //-------------------------------------------------------------------------// - - inner class DescriptorCollectorInitPhase : IrElementVisitorVoidWithContext() { - - private val initializedProperties = mutableSetOf() - - override fun visitElement(element: IrElement) { - element.acceptChildren(this, null) - } - - //---------------------------------------------------------------------// - - override fun visitPropertyNew(declaration: IrProperty) { - initPropertyOrField(declaration.descriptor) - super.visitPropertyNew(declaration) - } - - //---------------------------------------------------------------------// - - override fun visitFieldNew(declaration: IrField) { - val oldDescriptor = declaration.descriptor - if (!initializedProperties.contains(oldDescriptor)) { - initPropertyOrField(oldDescriptor) // A field without a property or a field of a delegated property. - } - super.visitFieldNew(declaration) - } - - //---------------------------------------------------------------------// - - override fun visitFunctionNew(declaration: IrFunction) { - val oldDescriptor = declaration.descriptor - if (oldDescriptor !is PropertyAccessorDescriptor) { // Property accessors are copied along with their property. - val newDescriptor = initFunctionDescriptor(oldDescriptor) - oldDescriptor.extensionReceiverParameter?.let { - descriptorSubstituteMap[it] = newDescriptor.extensionReceiverParameter!! - } - } - super.visitFunctionNew(declaration) - } - - //---------------------------------------------------------------------// - - override fun visitVariable(declaration: IrVariable) { - declaration.descriptor.let { descriptorSubstituteMap[it] = copyVariableDescriptor(it) } - - super.visitVariable(declaration) - } - - //---------------------------------------------------------------------// - - override fun visitCatch(aCatch: IrCatch) { - aCatch.parameter.let { descriptorSubstituteMap[it] = copyVariableDescriptor(it) } - - super.visitCatch(aCatch) - } - - //--- Copy descriptors ------------------------------------------------// - - //---------------------------------------------------------------------// - - private fun copyVariableDescriptor(oldDescriptor: VariableDescriptor): VariableDescriptor { - val oldContainingDeclaration = oldDescriptor.containingDeclaration - val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) - return IrTemporaryVariableDescriptorImpl( - containingDeclaration = newContainingDeclaration, - name = oldDescriptor.name, - outType = substituteType(oldDescriptor.type)!!, - isMutable = oldDescriptor.isVar - ) - } - - //---------------------------------------------------------------------// - - private fun initFunctionDescriptor(oldDescriptor: CallableDescriptor): CallableDescriptor = - when (oldDescriptor) { - is ConstructorDescriptor -> initConstructorDescriptor(oldDescriptor) - is SimpleFunctionDescriptor -> initSimpleFunctionDescriptor(oldDescriptor) - else -> TODO("Unsupported FunctionDescriptor subtype: $oldDescriptor") - } - - //---------------------------------------------------------------------// - - private fun initSimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor): FunctionDescriptor = - (descriptorSubstituteMap[oldDescriptor] as SimpleFunctionDescriptorImpl).apply { - val oldDispatchReceiverParameter = oldDescriptor.dispatchReceiverParameter - val newDispatchReceiverParameter = oldDispatchReceiverParameter?.let { descriptorSubstituteMap.getOrDefault(it, it) as ReceiverParameterDescriptor } - val newTypeParameters = oldDescriptor.typeParameters // TODO substitute types - val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, this) - val newReceiverParameterType = substituteType(oldDescriptor.extensionReceiverParameter?.type) - val newReturnType = substituteType(oldDescriptor.returnType) - - initialize( - /* receiverParameterType = */ newReceiverParameterType, - /* dispatchReceiverParameter = */ newDispatchReceiverParameter, - /* typeParameters = */ newTypeParameters, - /* unsubstitutedValueParameters = */ newValueParameters, - /* unsubstitutedReturnType = */ newReturnType, - /* modality = */ oldDescriptor.modality, - /* visibility = */ oldDescriptor.visibility - ) - isTailrec = oldDescriptor.isTailrec - isSuspend = oldDescriptor.isSuspend - overriddenDescriptors += oldDescriptor.overriddenDescriptors - } - - //---------------------------------------------------------------------// - - private fun initConstructorDescriptor(oldDescriptor: ConstructorDescriptor): FunctionDescriptor = - (descriptorSubstituteMap[oldDescriptor] as ClassConstructorDescriptorImpl).apply { - val newTypeParameters = oldDescriptor.typeParameters - val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, this) - val receiverParameterType = substituteType(oldDescriptor.dispatchReceiverParameter?.type) - val returnType = substituteType(oldDescriptor.returnType) - - initialize( - /* receiverParameterType = */ receiverParameterType, - /* dispatchReceiverParameter = */ null, // For constructor there is no explicit dispatch receiver. - /* typeParameters = */ newTypeParameters, - /* unsubstitutedValueParameters = */ newValueParameters, - /* unsubstitutedReturnType = */ returnType, - /* modality = */ oldDescriptor.modality, - /* visibility = */ oldDescriptor.visibility - ) - } - - //---------------------------------------------------------------------// - - private fun initPropertyOrField(oldDescriptor: PropertyDescriptor) { - val newDescriptor = (descriptorSubstituteMap[oldDescriptor] as PropertyDescriptorImpl).apply { - setType( - /* outType = */ substituteType(oldDescriptor.type)!!, - /* typeParameters = */ oldDescriptor.typeParameters, - /* dispatchReceiverParameter = */ (containingDeclaration as ClassDescriptor).thisAsReceiverParameter, - /* extensionReceiverParamter = */ substituteType(oldDescriptor.extensionReceiverParameter?.type).createExtensionReceiver(this)) - - initialize( - /* getter = */ oldDescriptor.getter?.let { copyPropertyGetterDescriptor(it, this) }, - /* setter = */ oldDescriptor.setter?.let { copyPropertySetterDescriptor(it, this) }) - - overriddenDescriptors += oldDescriptor.overriddenDescriptors - } - oldDescriptor.getter?.let { descriptorSubstituteMap[it] = newDescriptor.getter!! } - oldDescriptor.setter?.let { descriptorSubstituteMap[it] = newDescriptor.setter!! } - oldDescriptor.extensionReceiverParameter?.let { - descriptorSubstituteMap[it] = newDescriptor.extensionReceiverParameter!! - } - initializedProperties.add(oldDescriptor) - } - - //---------------------------------------------------------------------// - - private fun copyPropertyGetterDescriptor(oldDescriptor: PropertyGetterDescriptor, newPropertyDescriptor: PropertyDescriptor) = - PropertyGetterDescriptorImpl( - /* correspondingProperty = */ newPropertyDescriptor, - /* annotations = */ oldDescriptor.annotations, - /* modality = */ oldDescriptor.modality, - /* visibility = */ oldDescriptor.visibility, - /* isDefault = */ oldDescriptor.isDefault, - /* isExternal = */ oldDescriptor.isExternal, - /* isInline = */ oldDescriptor.isInline, - /* kind = */ oldDescriptor.kind, - /* original = */ null, - /* source = */ oldDescriptor.source).apply { - initialize(substituteType(oldDescriptor.returnType)) - } - - //---------------------------------------------------------------------// - - private fun copyPropertySetterDescriptor(oldDescriptor: PropertySetterDescriptor, newPropertyDescriptor: PropertyDescriptor) = - PropertySetterDescriptorImpl( - /* correspondingProperty = */ newPropertyDescriptor, - /* annotations = */ oldDescriptor.annotations, - /* modality = */ oldDescriptor.modality, - /* visibility = */ oldDescriptor.visibility, - /* isDefault = */ oldDescriptor.isDefault, - /* isExternal = */ oldDescriptor.isExternal, - /* isInline = */ oldDescriptor.isInline, - /* kind = */ oldDescriptor.kind, - /* original = */ null, - /* source = */ oldDescriptor.source).apply { - initialize(copyValueParameters(oldDescriptor.valueParameters, this).single()) - } - - //-------------------------------------------------------------------------// - - private fun copyValueParameters(oldValueParameters: List , containingDeclaration: CallableDescriptor) = - oldValueParameters.map { oldDescriptor -> - val newDescriptor = ValueParameterDescriptorImpl( - containingDeclaration = containingDeclaration, - original = oldDescriptor.original, - index = oldDescriptor.index, - annotations = oldDescriptor.annotations, - name = oldDescriptor.name, - outType = substituteType(oldDescriptor.type)!!, - declaresDefaultValue = oldDescriptor.declaresDefaultValue(), - isCrossinline = oldDescriptor.isCrossinline, - isNoinline = oldDescriptor.isNoinline, - varargElementType = substituteType(oldDescriptor.varargElementType), - source = oldDescriptor.source - ) - descriptorSubstituteMap[oldDescriptor] = newDescriptor - newDescriptor - } - - } - -//-----------------------------------------------------------------------------// - - @Suppress("DEPRECATION") - inner class InlineCopyIr : DeepCopyIrTree() { - - override fun mapClassDeclaration (descriptor: ClassDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassDescriptor - override fun mapTypeAliasDeclaration (descriptor: TypeAliasDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as TypeAliasDescriptor - override fun mapFunctionDeclaration (descriptor: FunctionDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as FunctionDescriptor - override fun mapConstructorDeclaration (descriptor: ClassConstructorDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassConstructorDescriptor - override fun mapPropertyDeclaration (descriptor: PropertyDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as PropertyDescriptor - override fun mapLocalPropertyDeclaration (descriptor: VariableDescriptorWithAccessors) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptorWithAccessors - override fun mapEnumEntryDeclaration (descriptor: ClassDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassDescriptor - override fun mapVariableDeclaration (descriptor: VariableDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptor - override fun mapErrorDeclaration (descriptor: DeclarationDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) - - override fun mapClassReference (descriptor: ClassDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassDescriptor - override fun mapValueReference (descriptor: ValueDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ValueDescriptor - override fun mapVariableReference (descriptor: VariableDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptor - override fun mapPropertyReference (descriptor: PropertyDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as PropertyDescriptor - override fun mapCallee (descriptor: FunctionDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as FunctionDescriptor - override fun mapDelegatedConstructorCallee (descriptor: ClassConstructorDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassConstructorDescriptor - override fun mapEnumConstructorCallee (descriptor: ClassConstructorDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassConstructorDescriptor - override fun mapLocalPropertyReference (descriptor: VariableDescriptorWithAccessors) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptorWithAccessors - override fun mapClassifierReference (descriptor: ClassifierDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassifierDescriptor - override fun mapReturnTarget (descriptor: FunctionDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as FunctionDescriptor - - //---------------------------------------------------------------------// - - override fun mapSuperQualifier(qualifier: ClassDescriptor?): ClassDescriptor? { - if (qualifier == null) return null - return descriptorSubstituteMap.getOrDefault(qualifier, qualifier) as ClassDescriptor - } - - //--- Visits ----------------------------------------------------------// - - override fun visitCall(expression: IrCall): IrCall { - if (expression !is IrCallImpl) return super.visitCall(expression) - val newDescriptor = mapCallee(expression.descriptor) - return IrCallImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - type = context.ir.translateErased(newDescriptor.returnType!!), - descriptor = newDescriptor, - typeArgumentsCount = expression.typeArgumentsCount, - origin = expression.origin, - superQualifierDescriptor = mapSuperQualifier(expression.superQualifier) - ).apply { - transformValueArguments(expression) - substituteTypeArguments(expression) - } - } - - override fun visitField(declaration: IrField): IrField { - val descriptor = mapPropertyDeclaration(declaration.descriptor) - return IrFieldImpl( - declaration.startOffset, declaration.endOffset, - mapDeclarationOrigin(declaration.origin), - descriptor, - context.ir.translateErased(descriptor.type), - declaration.initializer?.transform(this@InlineCopyIr, null) - ).apply { - transformAnnotations(declaration) - } - } - - //---------------------------------------------------------------------// - - 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, - returnType = context.ir.translateErased(descriptor.returnType!!), - body = declaration.body?.transform(this, null) - ).also { - it.setOverrides(context.ir.symbols.symbolTable) - }.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, - returnType = context.ir.translateErased(descriptor.returnType), - 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] - original.getDefault(originalValueParameter)?.let { irDefaultParameterValue -> - putDefault(valueParameter, irDefaultParameterValue.transform(this@InlineCopyIr, null)) - } - } - return this - } - - //---------------------------------------------------------------------// - - fun getTypeOperatorReturnType(operator: IrTypeOperator, type: IrType) : IrType { - return when (operator) { - IrTypeOperator.CAST, - IrTypeOperator.IMPLICIT_CAST, - IrTypeOperator.IMPLICIT_NOTNULL, - IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, - IrTypeOperator.IMPLICIT_INTEGER_COERCION, - IrTypeOperator.SAM_CONVERSION -> type - IrTypeOperator.SAFE_CAST -> type.makeNullable() - IrTypeOperator.INSTANCEOF, - IrTypeOperator.NOT_INSTANCEOF -> context.irBuiltIns.booleanType - } - } - - //---------------------------------------------------------------------// - - override fun visitTypeOperator(expression: IrTypeOperatorCall): IrTypeOperatorCall { - 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), - typeOperandClassifier = (typeOperand as IrSimpleType).classifier - ) - } - - //---------------------------------------------------------------------// - - override fun visitReturn(expression: IrReturn): IrReturn = - IrReturnImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - type = substituteAndEraseType(expression.type)!!, - returnTargetDescriptor = mapReturnTarget(expression.returnTarget), - value = expression.value.transform(this, null) - ) - - //---------------------------------------------------------------------// - - override fun visitBlock(expression: IrBlock): IrBlock { - return if (expression is IrReturnableBlock) { - IrReturnableBlockImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - type = expression.type, - descriptor = expression.descriptor, - origin = mapStatementOrigin(expression.origin), - statements = expression.statements.map { it.transform(this, null) }, - sourceFileName = expression.sourceFileName - ) - } else { - IrBlockImpl( - expression.startOffset, expression.endOffset, - substituteAndEraseType(expression.type)!!, - mapStatementOrigin(expression.origin), - expression.statements.map { it.transform(this, null) } - ) - } - } - - //-------------------------------------------------------------------------// - - override fun visitClassReference(expression: IrClassReference): IrClassReference { - 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( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - type = newExpressionType, - descriptor = classDescriptor, - classType = expression.classType - ) - } - - //-------------------------------------------------------------------------// - - override fun visitGetClass(expression: IrGetClass): IrGetClass { - val type = substituteAndEraseType(expression.type)!! - return IrGetClassImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - type = type, - argument = expression.argument.transform(this, null) - ) - } - - //-------------------------------------------------------------------------// - - 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) - } - } - } - } - - //-------------------------------------------------------------------------// - - private fun substituteType(type: KotlinType?): KotlinType? { - val substitutedType = (type?.let { typeSubstitutor?.substitute(it, Variance.INVARIANT) } ?: type) - ?: return null - val oldClassDescriptor = TypeUtils.getClassDescriptor(substitutedType) ?: return substitutedType - 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 = substituteAndBreakType(originalTypeArgument!!) - this.putTypeArgument(index, newTypeArgument) - } - } - - //-------------------------------------------------------------------------// - - override fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap) { - descriptorSubstituteMap.forEach { t, u -> - globalSubstituteMap[t] = SubstitutedDescriptor(targetDescriptor, u) - } - } - -} - -class SubstitutedDescriptor(val inlinedFunction: FunctionDescriptor, val descriptor: DeclarationDescriptor) - -internal class DescriptorSubstitutorForExternalScope( - val globalSubstituteMap: Map, - val context: Context -) - : IrElementTransformerVoidWithContext() { - - fun run(element: IrElement) { - element.transformChildrenVoid(this) - } - - override fun visitCall(expression: IrCall): IrExpression { - val oldExpression = super.visitCall(expression) as IrCall - - val substitutedDescriptor = globalSubstituteMap[expression.descriptor.original] - ?: return oldExpression - if (allScopes.any { it.scope.scopeOwner == substitutedDescriptor.inlinedFunction }) - return oldExpression - return when (oldExpression) { - is IrCallImpl -> copyIrCallImpl(oldExpression, substitutedDescriptor) - is IrCallWithShallowCopy -> copyIrCallWithShallowCopy(oldExpression, substitutedDescriptor) - else -> oldExpression - } - } - - //-------------------------------------------------------------------------// - - private fun copyIrCallImpl(oldExpression: IrCallImpl, substitutedDescriptor: SubstitutedDescriptor): IrCallImpl { - - val oldDescriptor = oldExpression.descriptor - val newDescriptor = substitutedDescriptor.descriptor as FunctionDescriptor - - if (newDescriptor == oldDescriptor) - return oldExpression - - return IrCallImpl( - startOffset = oldExpression.startOffset, - endOffset = oldExpression.endOffset, - type = context.ir.translateErased(newDescriptor.returnType!!), - symbol = createFunctionSymbol(newDescriptor), - descriptor = newDescriptor, - typeArgumentsCount = oldExpression.typeArgumentsCount, - origin = oldExpression.origin, - superQualifierSymbol = createClassSymbolOrNull(oldExpression.superQualifier) - ).apply { - copyTypeArgumentsFrom(oldExpression) - - oldExpression.descriptor.valueParameters.forEach { - val valueArgument = oldExpression.getValueArgument(it) - putValueArgument(it.index, valueArgument) - } - extensionReceiver = oldExpression.extensionReceiver - dispatchReceiver = oldExpression.dispatchReceiver - } - } - - //-------------------------------------------------------------------------// - - private fun copyIrCallWithShallowCopy(oldExpression: IrCallWithShallowCopy, substitutedDescriptor: SubstitutedDescriptor): IrCall { - - val oldDescriptor = oldExpression.descriptor - val newDescriptor = substitutedDescriptor.descriptor as FunctionDescriptor - - if (newDescriptor == oldDescriptor) - return oldExpression - - return oldExpression.shallowCopy(oldExpression.origin, createFunctionSymbol(newDescriptor), oldExpression.superQualifierSymbol) - } -} +} \ No newline at end of file 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 13390ac55fd..8c702091bac 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 @@ -3,539 +3,401 @@ * that can be found in the LICENSE file. */ -@file:Suppress("FoldInitializerAndIfToElvis") - package org.jetbrains.kotlin.backend.konan.lower -import org.jetbrains.kotlin.backend.common.* +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.ScopeWithIr import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters -import org.jetbrains.kotlin.backend.common.lower.CoroutineIntrinsicLambdaOrigin import org.jetbrains.kotlin.backend.common.ir.createTemporaryVariableWithWrappedDescriptor +import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted +import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn +import org.jetbrains.kotlin.backend.common.lower.CoroutineIntrinsicLambdaOrigin import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining -import org.jetbrains.kotlin.backend.konan.descriptors.propertyIfAccessor import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass import org.jetbrains.kotlin.backend.konan.irasdescriptors.isInlineParameter import org.jetbrains.kotlin.config.languageVersionSettings -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ValueDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.builders.irReturn import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl 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.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl -import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.getArguments import org.jetbrains.kotlin.ir.util.parentAsClass -import org.jetbrains.kotlin.ir.util.referenceFunction -import org.jetbrains.kotlin.ir.visitors.* +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.types.TypeConstructor -import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.types.TypeProjectionImpl -import org.jetbrains.kotlin.types.TypeSubstitutor -abstract class IrElementTransformerWithContext : IrElementTransformer { +internal class FunctionInlining(val context: Context) : IrElementTransformerVoidWithContext() { - private val scopeStack = mutableListOf() + fun inline(irModule: IrModuleFragment) = irModule.accept(this, data = null) - final override fun visitFile(declaration: IrFile, data: D): IrFile { - scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) - val result = visitFileNew(declaration, data) - scopeStack.pop() - return result - } - - final override fun visitClass(declaration: IrClass, data: D): IrStatement { - scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) - val result = visitClassNew(declaration, data) - scopeStack.pop() - return result - } - - final override fun visitProperty(declaration: IrProperty, data: D): IrStatement { - scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) - val result = visitPropertyNew(declaration, data) - scopeStack.pop() - return result - } - - final override fun visitField(declaration: IrField, data: D): IrStatement { - scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) - val result = visitFieldNew(declaration, data) - scopeStack.pop() - return result - } - - final override fun visitFunction(declaration: IrFunction, data: D): IrStatement { - scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) - val result = visitFunctionNew(declaration, data) - scopeStack.pop() - return result - } - - protected val currentFile get() = scopeStack.lastOrNull { it.irElement is IrFile }!!.irElement as IrFile - protected val currentClass get() = scopeStack.lastOrNull { it.scope.scopeOwner is ClassDescriptor } - protected val currentFunction get() = scopeStack.lastOrNull { it.scope.scopeOwner is FunctionDescriptor } - protected val currentProperty get() = scopeStack.lastOrNull { it.scope.scopeOwner is PropertyDescriptor } - protected val currentScope get() = scopeStack.peek() - protected val parentScope get() = if (scopeStack.size < 2) null else scopeStack[scopeStack.size - 2] - protected val allScopes get() = scopeStack - - fun printScopeStack() { - scopeStack.forEach { println(it.scope.scopeOwner) } - } - - open fun visitFileNew(declaration: IrFile, data: D): IrFile { - return super.visitFile(declaration, data) - } - - open fun visitClassNew(declaration: IrClass, data: D): IrStatement { - return super.visitClass(declaration, data) - } - - open fun visitFunctionNew(declaration: IrFunction, data: D): IrStatement { - return super.visitFunction(declaration, data) - } - - open fun visitPropertyNew(declaration: IrProperty, data: D): IrStatement { - return super.visitProperty(declaration, data) - } - - open fun visitFieldNew(declaration: IrField, data: D): IrStatement { - return super.visitField(declaration, data) - } -} - -internal class Ref(var value: T) - -internal class FunctionInlining(val context: Context): IrElementTransformerWithContext>() { - - private val globalSubstituteMap = mutableMapOf() - private val inlineFunctions = mutableMapOf() - - //-------------------------------------------------------------------------// - - fun inline(irModule: IrModuleFragment): IrElement { - val transformedModule = irModule.accept(this, Ref(false)) - DescriptorSubstitutorForExternalScope(globalSubstituteMap, context).run(transformedModule) // Transform calls to object that might be returned from inline function call. - return transformedModule - } - - override fun visitFunctionNew(declaration: IrFunction, data: Ref): IrStatement { - val descriptor = declaration.descriptor - - val localData = Ref(inlineFunctions[descriptor] ?: false) - val result = super.visitFunctionNew(declaration, localData) - data.value = data.value or localData.value - - if (descriptor.needsInlining) { - inlineFunctions[descriptor] = localData.value - } - return result - } - - override fun visitCall(expression: IrCall, data: Ref): IrExpression { - - val argsAreBad = Ref(false) - val callSite = super.visitCall(expression, argsAreBad) as IrCall - data.value = data.value or argsAreBad.value + override fun visitCall(expression: IrCall): IrExpression { + val callSite = super.visitCall(expression) as IrCall if (!callSite.descriptor.needsInlining) return callSite - val functionDescriptor = callSite.descriptor.resolveFakeOverride().original if (callSite.symbol == context.ir.symbols.isInitializedGetter) return callSite - val callee = getFunctionDeclaration(functionDescriptor) - if (callee == null) { - val message = "Inliner failed to obtain function declaration: " + - functionDescriptor.fqNameSafe.toString() - context.reportWarning(message, currentFile, callSite) - return callSite - } - data.value = data.value or callee.second + val callee = getFunctionDeclaration(callSite.symbol) - // TODO: do we still need this Ref mechanism? - val childIsBad = Ref(inlineFunctions[functionDescriptor] ?: false) - callee.first.transformChildren(this, childIsBad) // Process recursive inline. - inlineFunctions[functionDescriptor] = childIsBad.value - data.value = data.value or childIsBad.value + callee.transformChildrenVoid(this) // Process recursive inline. - - val currentCalleeIsBad = false - val inliner = Inliner(globalSubstituteMap, callSite, callee.first, !currentCalleeIsBad, currentScope!!, - allScopes.map { it.irElement }.filterIsInstance().lastOrNull(), context, this) + val parent = allScopes.map { it.irElement }.filterIsInstance().lastOrNull() + val inliner = Inliner(callSite, callee, currentScope!!, parent, context) return inliner.inline() } - // TODO: do we really need this function anymore? - private fun getFunctionDeclaration(descriptor: FunctionDescriptor): Pair? = - when { - descriptor.isBuiltInIntercepted(context.config.configuration.languageVersionSettings) -> - error("Continuation.intercepted is not available with release coroutines") + private fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction { + val descriptor = symbol.descriptor.original + val languageVersionSettings = context.config.configuration.languageVersionSettings + // TODO: Remove these hacks when coroutine intrinsics are fixed. + return when { + descriptor.isBuiltInIntercepted(languageVersionSettings) -> + error("Continuation.intercepted is not available with release coroutines") - descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(context.config.configuration.languageVersionSettings) -> - getFunctionDeclaration(context.ir.symbols.konanSuspendCoroutineUninterceptedOrReturn.descriptor) + descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) -> + context.ir.symbols.konanSuspendCoroutineUninterceptedOrReturn.owner - descriptor == context.ir.symbols.coroutineContextGetter -> - getFunctionDeclaration(context.ir.symbols.konanCoroutineContextGetter.descriptor) + descriptor == context.ir.symbols.coroutineContextGetter -> + context.ir.symbols.konanCoroutineContextGetter.owner - else -> - context.ir.originalModuleIndex.functions[descriptor]?.let { it to false } - ?: context.ir.symbols.symbolTable.referenceFunction(descriptor).owner to true - } -} - -private val inlineConstructor = FqName("kotlin.native.internal.InlineConstructor") -private val FunctionDescriptor.isInlineConstructor get() = annotations.hasAnnotation(inlineConstructor) - -//-----------------------------------------------------------------------------// - -private class Inliner(val globalSubstituteMap: MutableMap, - val callSite: IrCall, - val callee: IrFunction, - val local: Boolean, - val currentScope: ScopeWithIr, - val parent: IrDeclarationParent?, - val context: Context, - val owner: FunctionInlining /*TODO: make inner*/) { - - val copyIrElement = - if (!local) - DeepCopyIrTreeWithDescriptors(callee.descriptor, currentScope.scope.scopeOwner, - context, createTypeSubstitutor(callSite)) - else { - val typeParameters = - if (callee is IrConstructor) - callee.parentAsClass.typeParameters - else callee.typeParameters - val typeArguments = - (0 until callSite.typeArgumentsCount).map { - typeParameters[it].symbol to callSite.getTypeArgument(it) - }.associate { it } - DeepCopyIrTreeWithSymbolsForInliner(context, typeArguments, parent) - } - - val substituteMap = mutableMapOf() - - fun inline() = inlineFunction(callSite, callee) - - /** - * TODO: JVM inliner crashed on attempt inline this function from transform.kt with: - * j.l.IllegalStateException: Couldn't obtain compiled function body for - * public inline fun kotlin.collections.MutableList.transform... - */ - private inline fun MutableList.transform(transformation: (T) -> IrElement) { - forEachIndexed { i, item -> - set(i, transformation(item) as T) - } - } - - private fun inlineFunction(callSite: IrCall, callee: IrFunction): IrReturnableBlockImpl { - val copiedCallee = copyIrElement.copy(callee) as IrFunction - - val evaluationStatements = evaluateArguments(callSite, copiedCallee) - val statements = (copiedCallee.body as IrBlockBody).statements - - val irReturnableBlockSymbol = IrReturnableBlockSymbolImpl(copiedCallee.descriptor.original) - val descriptor = callee.descriptor.original - val startOffset = callee.startOffset - val endOffset = callee.endOffset - val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset) - - if (descriptor.isInlineConstructor) { - val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall - irBuilder.run { - val constructorDescriptor = delegatingConstructorCall.descriptor.original - val constructorCall = irCall(delegatingConstructorCall.symbol, callSite.type, - constructorDescriptor.typeParameters.map { delegatingConstructorCall.getTypeArgument(it)!! }).apply { - constructorDescriptor.valueParameters.forEach { putValueArgument(it, delegatingConstructorCall.getValueArgument(it)) } - } - val oldThis = (callee as IrConstructor).constructedClass.thisReceiver!!.descriptor - val newThis = currentScope.scope.createTemporaryVariableWithWrappedDescriptor( - irExpression = constructorCall, - nameHint = delegatingConstructorCall.descriptor.fqNameSafe.toString() + ".this" - ) - statements[0] = newThis - substituteMap[oldThis] = irGet(newThis) - statements.add(irReturn(irGet(newThis))) - } - } - - val sourceFileName = context.ir.originalModuleIndex.declarationToFile[callee.descriptor.original] ?: "" - - copyIrElement.addCurrentSubstituteMap(globalSubstituteMap) - - val transformer = ParameterSubstitutor() - statements.transform { it.transform(transformer, data = null) } - statements.addAll(0, evaluationStatements) - - val isCoroutineIntrinsicCall = callSite.descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn( - context.config.configuration.languageVersionSettings) - - return IrReturnableBlockImpl( - startOffset = startOffset, - endOffset = endOffset, - type = callSite.type, - symbol = irReturnableBlockSymbol, - origin = if (isCoroutineIntrinsicCall) CoroutineIntrinsicLambdaOrigin else null, - statements = statements, - sourceFileName = sourceFileName - ).apply { - transformChildrenVoid(object: IrElementTransformerVoid() { - override fun visitReturn(expression: IrReturn): IrExpression { - expression.transformChildrenVoid(this) - - if (expression.returnTargetSymbol == copiedCallee.symbol) - return irBuilder.irReturn(expression.value) - return expression - } - }) + else -> (symbol.owner as? IrSimpleFunction)?.resolveFakeOverride() ?: symbol.owner } } - //---------------------------------------------------------------------// + private val inlineConstructor = FqName("kotlin.native.internal.InlineConstructor") + private val FunctionDescriptor.isInlineConstructor get() = annotations.hasAnnotation(inlineConstructor) - private inner class ParameterSubstitutor: IrElementTransformerVoid() { + private inner class Inliner(val callSite: IrCall, + val callee: IrFunction, + val currentScope: ScopeWithIr, + val parent: IrDeclarationParent?, + val context: Context) { - override fun visitGetValue(expression: IrGetValue): IrExpression { - val newExpression = super.visitGetValue(expression) as IrGetValue - val descriptor = newExpression.descriptor - val argument = substituteMap[descriptor] - - if (argument == null) return newExpression - - argument.transformChildrenVoid(this) // Default argument can contain subjects for substitution. - return copyIrElement.copy(argument) as IrExpression + val copyIrElement = run { + val typeParameters = + if (callee is IrConstructor) + callee.parentAsClass.typeParameters + else callee.typeParameters + val typeArguments = + (0 until callSite.typeArgumentsCount).map { + typeParameters[it].symbol to callSite.getTypeArgument(it) + }.associate { it } + DeepCopyIrTreeWithSymbolsForInliner(context, typeArguments, parent) } - //-----------------------------------------------------------------// + val substituteMap = mutableMapOf() - override fun visitCall(expression: IrCall): IrExpression { - if (!isLambdaCall(expression)) - return super.visitCall(expression) + fun inline() = inlineFunction(callSite, callee) - val dispatchReceiver = expression.dispatchReceiver as IrGetValue - val functionArgument = substituteMap[dispatchReceiver.descriptor] - if (functionArgument == null) - return super.visitCall(expression) - val dispatchDescriptor = dispatchReceiver.descriptor - if (dispatchDescriptor is ValueParameterDescriptor && - dispatchDescriptor.isNoinline) return super.visitCall(expression) + /** + * TODO: JVM inliner crashed on attempt inline this function from transform.kt with: + * j.l.IllegalStateException: Couldn't obtain compiled function body for + * public inline fun kotlin.collections.MutableList.transform... + */ + private inline fun MutableList.transform(transformation: (T) -> IrElement) { + forEachIndexed { i, item -> + set(i, transformation(item) as T) + } + } - if (functionArgument is IrFunctionReference) { - val functionDescriptor = functionArgument.descriptor - val functionParameters = functionDescriptor.explicitParameters - val boundFunctionParameters = functionArgument.getArguments() - val unboundFunctionParameters = functionParameters - boundFunctionParameters.map { it.first } - val boundFunctionParametersMap = boundFunctionParameters.associate { it.first to it.second } + private fun inlineFunction(callSite: IrCall, callee: IrFunction): IrReturnableBlockImpl { + val copiedCallee = copyIrElement.copy(callee) as IrFunction - var unboundIndex = 0 - val unboundArgsSet = unboundFunctionParameters.toSet() - val valueParameters = expression.getArguments().drop(1) // Skip dispatch receiver. + val evaluationStatements = evaluateArguments(callSite, copiedCallee) + val statements = (copiedCallee.body as IrBlockBody).statements - val immediateCall = IrCallImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - type = expression.type, - symbol = functionArgument.symbol, - descriptor = functionArgument.descriptor).apply { - functionParameters.forEach { - val argument = - if (!unboundArgsSet.contains(it)) - boundFunctionParametersMap[it]!! - else - valueParameters[unboundIndex++].second - when (it) { - functionDescriptor.dispatchReceiverParameter -> this.dispatchReceiver = argument - functionDescriptor.extensionReceiverParameter -> this.extensionReceiver = argument - else -> putValueArgument((it as ValueParameterDescriptor).index, argument) + val irReturnableBlockSymbol = IrReturnableBlockSymbolImpl(copiedCallee.descriptor.original) + val descriptor = callee.descriptor.original + val startOffset = callee.startOffset + val endOffset = callee.endOffset + val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset) + + if (descriptor.isInlineConstructor) { + val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall + irBuilder.run { + val constructorDescriptor = delegatingConstructorCall.descriptor.original + val constructorCall = irCall(delegatingConstructorCall.symbol, callSite.type, + constructorDescriptor.typeParameters.map { delegatingConstructorCall.getTypeArgument(it)!! }).apply { + constructorDescriptor.valueParameters.forEach { putValueArgument(it, delegatingConstructorCall.getValueArgument(it)) } + } + val oldThis = (callee as IrConstructor).constructedClass.thisReceiver!!.descriptor + val newThis = currentScope.scope.createTemporaryVariableWithWrappedDescriptor( + irExpression = constructorCall, + nameHint = delegatingConstructorCall.descriptor.fqNameSafe.toString() + ".this" + ) + statements[0] = newThis + substituteMap[oldThis] = irGet(newThis) + statements.add(irReturn(irGet(newThis))) + } + } + + val sourceFileName = context.ir.originalModuleIndex.declarationToFile[callee.descriptor.original] ?: "" + + val transformer = ParameterSubstitutor() + statements.transform { it.transform(transformer, data = null) } + statements.addAll(0, evaluationStatements) + + val isCoroutineIntrinsicCall = callSite.descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn( + context.config.configuration.languageVersionSettings) + + return IrReturnableBlockImpl( + startOffset = startOffset, + endOffset = endOffset, + type = callSite.type, + symbol = irReturnableBlockSymbol, + origin = if (isCoroutineIntrinsicCall) CoroutineIntrinsicLambdaOrigin else null, + statements = statements, + sourceFileName = sourceFileName + ).apply { + transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitReturn(expression: IrReturn): IrExpression { + expression.transformChildrenVoid(this) + + if (expression.returnTargetSymbol == copiedCallee.symbol) + return irBuilder.irReturn(expression.value) + return expression + } + }) + } + } + + //---------------------------------------------------------------------// + + private inner class ParameterSubstitutor : IrElementTransformerVoid() { + + override fun visitGetValue(expression: IrGetValue): IrExpression { + val newExpression = super.visitGetValue(expression) as IrGetValue + val descriptor = newExpression.descriptor + val argument = substituteMap[descriptor] ?: return newExpression + + argument.transformChildrenVoid(this) // Default argument can contain subjects for substitution. + return copyIrElement.copy(argument) as IrExpression + } + + //-----------------------------------------------------------------// + + override fun visitCall(expression: IrCall): IrExpression { + if (!isLambdaCall(expression)) + return super.visitCall(expression) + + val dispatchReceiver = expression.dispatchReceiver as IrGetValue + val functionArgument = substituteMap[dispatchReceiver.descriptor] ?: return super.visitCall(expression) + val dispatchDescriptor = dispatchReceiver.descriptor + if (dispatchDescriptor is ValueParameterDescriptor && dispatchDescriptor.isNoinline) + return super.visitCall(expression) + + if (functionArgument is IrFunctionReference) { + val functionDescriptor = functionArgument.descriptor + val functionParameters = functionDescriptor.explicitParameters + val boundFunctionParameters = functionArgument.getArguments() + val unboundFunctionParameters = functionParameters - boundFunctionParameters.map { it.first } + val boundFunctionParametersMap = boundFunctionParameters.associate { it.first to it.second } + + var unboundIndex = 0 + val unboundArgsSet = unboundFunctionParameters.toSet() + val valueParameters = expression.getArguments().drop(1) // Skip dispatch receiver. + + val immediateCall = IrCallImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + type = expression.type, + symbol = functionArgument.symbol, + descriptor = functionArgument.descriptor).apply { + functionParameters.forEach { + val argument = + if (!unboundArgsSet.contains(it)) + boundFunctionParametersMap[it]!! + else + valueParameters[unboundIndex++].second + when (it) { + functionDescriptor.dispatchReceiverParameter -> this.dispatchReceiver = argument + functionDescriptor.extensionReceiverParameter -> this.extensionReceiver = argument + else -> putValueArgument((it as ValueParameterDescriptor).index, argument) + } } + assert(unboundIndex == valueParameters.size) { "Not all arguments of are used" } + for (index in 0 until functionArgument.typeArgumentsCount) + putTypeArgument(index, functionArgument.getTypeArgument(index)) } - assert(unboundIndex == valueParameters.size) { "Not all arguments of are used" } - for (index in 0 until functionArgument.typeArgumentsCount) - putTypeArgument(index, functionArgument.getTypeArgument(index)) + return this@FunctionInlining.visitCall(super.visitCall(immediateCall) as IrCall) } - return owner.visitCall(super.visitCall(immediateCall) as IrCall, Ref(false)) - } - if (functionArgument !is IrBlock) - return super.visitCall(expression) + if (functionArgument !is IrBlock) + return super.visitCall(expression) - val functionDeclaration = functionArgument.statements[0] as IrFunction - val newExpression = inlineFunction(expression, functionDeclaration) // Inline the lambda. Lambda parameters will be substituted with lambda arguments. - return newExpression.transform(this, null) // Substitute lambda arguments with target function arguments. + val functionDeclaration = functionArgument.statements[0] as IrFunction + val newExpression = inlineFunction(expression, functionDeclaration) // Inline the lambda. Lambda parameters will be substituted with lambda arguments. + return newExpression.transform(this, null) // Substitute lambda arguments with target function arguments. + } + + //-----------------------------------------------------------------// + + override fun visitElement(element: IrElement) = element.accept(this, null) } - //-----------------------------------------------------------------// + private fun isLambdaCall(irCall: IrCall) = irCall.descriptor.isFunctionInvoke && irCall.dispatchReceiver is IrGetValue - override fun visitElement(element: IrElement) = element.accept(this, null) - } + //-------------------------------------------------------------------------// - private fun isLambdaCall(irCall: IrCall) = irCall.descriptor.isFunctionInvoke && irCall.dispatchReceiver is IrGetValue + private inner class ParameterToArgument(val parameter: IrValueParameter, + val argumentExpression: IrExpression) { - private fun createTypeSubstitutor(irCall: IrCall): TypeSubstitutor? { - if (irCall.typeArgumentsCount == 0) return null - val descriptor = irCall.descriptor.resolveFakeOverride().original - val typeParameters = descriptor.propertyIfAccessor.typeParameters - val substitutionContext = mutableMapOf() - for (index in 0 until irCall.typeArgumentsCount) { - val typeArgument = irCall.getTypeArgument(index) ?: continue - substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument.toKotlinType()) + val isInlinableLambdaArgument: Boolean + get() { + if (!parameter.isInlineParameter()) return false + if (argumentExpression is IrFunctionReference + && !argumentExpression.descriptor.isSuspend) return true // Skip suspend functions for now since it's not supported by FE anyway. + + // Do pattern-matching on IR. + if (argumentExpression !is IrBlock) return false + if (argumentExpression.origin != IrStatementOrigin.LAMBDA && + argumentExpression.origin != IrStatementOrigin.ANONYMOUS_FUNCTION) return false + val statements = argumentExpression.statements + val irFunction = statements[0] + val irCallableReference = statements[1] + if (irFunction !is IrFunction) return false + if (irCallableReference !is IrCallableReference) return false + return true + } + + val isImmutableVariableLoad: Boolean + get() = argumentExpression.let { + it is IrGetValue && !it.descriptor.let { it is VariableDescriptor && it.isVar } + } } - return TypeSubstitutor.create(substitutionContext) - } - //-------------------------------------------------------------------------// + //-------------------------------------------------------------------------// - private class ParameterToArgument(val parameter: IrValueParameter, - val argumentExpression : IrExpression) { + private fun buildParameterToArgument(callSite: IrCall, callee: IrFunction): List { - val isInlinableLambdaArgument : Boolean - get() { - if (!parameter.isInlineParameter()) return false - if (argumentExpression is IrFunctionReference - && !argumentExpression.descriptor.isSuspend) return true // Skip suspend functions for now since it's not supported by FE anyway. + val parameterToArgument = mutableListOf() - // Do pattern-matching on IR. - if (argumentExpression !is IrBlock) return false - if (argumentExpression.origin != IrStatementOrigin.LAMBDA && - argumentExpression.origin != IrStatementOrigin.ANONYMOUS_FUNCTION) return false - val statements = argumentExpression.statements - val irFunction = statements[0] - val irCallableReference = statements[1] - if (irFunction !is IrFunction) return false - if (irCallableReference !is IrCallableReference) return false - return true + if (callSite.dispatchReceiver != null && // Only if there are non null dispatch receivers both + callee.dispatchReceiverParameter != null) // on call site and in function declaration. + parameterToArgument += ParameterToArgument( + parameter = callee.dispatchReceiverParameter!!, + argumentExpression = callSite.dispatchReceiver!! + ) + + val valueArguments = + callSite.descriptor.valueParameters.map { callSite.getValueArgument(it) }.toMutableList() + + if (callee.extensionReceiverParameter != null) { + parameterToArgument += ParameterToArgument( + parameter = callee.extensionReceiverParameter!!, + argumentExpression = if (callSite.extensionReceiver != null) { + callSite.extensionReceiver!! + } else { + // Special case: lambda with receiver is called as usual lambda: + valueArguments.removeAt(0)!! + } + ) + } else if (callSite.extensionReceiver != null) { + // Special case: usual lambda is called as lambda with receiver: + valueArguments.add(0, callSite.extensionReceiver!!) } - val isImmutableVariableLoad: Boolean - get() = argumentExpression.let { - it is IrGetValue && !it.descriptor.let { it is VariableDescriptor && it.isVar } - } - } - - //-------------------------------------------------------------------------// - - private fun buildParameterToArgument(callSite: IrCall, callee: IrFunction): List { - - val parameterToArgument = mutableListOf() - - if (callSite.dispatchReceiver != null && // Only if there are non null dispatch receivers both - callee.dispatchReceiverParameter != null) // on call site and in function declaration. - parameterToArgument += ParameterToArgument( - parameter = callee.dispatchReceiverParameter!!, - argumentExpression = callSite.dispatchReceiver!! - ) - - val valueArguments = - callSite.descriptor.valueParameters.map { callSite.getValueArgument(it) }.toMutableList() - - if (callee.extensionReceiverParameter != null) { - parameterToArgument += ParameterToArgument( - parameter = callee.extensionReceiverParameter!!, - argumentExpression = if (callSite.extensionReceiver != null) { - callSite.extensionReceiver!! - } else { - // Special case: lambda with receiver is called as usual lambda: - valueArguments.removeAt(0)!! + val parametersWithDefaultToArgument = mutableListOf() + for (parameter in callee.valueParameters) { + val argument = valueArguments[parameter.index] + when { + argument != null -> { + parameterToArgument += ParameterToArgument( + parameter = parameter, + argumentExpression = argument + ) } - ) - } else if (callSite.extensionReceiver != null) { - // Special case: usual lambda is called as lambda with receiver: - valueArguments.add(0, callSite.extensionReceiver!!) - } - val parametersWithDefaultToArgument = mutableListOf() - for (parameter in callee.valueParameters) { - val argument = valueArguments[parameter.index] - when { - argument != null -> { - parameterToArgument += ParameterToArgument( - parameter = parameter, - argumentExpression = argument - ) - } + // After ExpectDeclarationsRemoving pass default values from expect declarations + // are represented correctly in IR. + parameter.defaultValue != null -> { // There is no argument - try default value. + parametersWithDefaultToArgument += ParameterToArgument( + parameter = parameter, + argumentExpression = parameter.defaultValue!!.expression + ) + } - // After ExpectDeclarationsRemoving pass default values from expect declarations - // are represented correctly in IR. - parameter.defaultValue != null -> { // There is no argument - try default value. - parametersWithDefaultToArgument += ParameterToArgument( - parameter = parameter, - argumentExpression = parameter.defaultValue!!.expression - ) - } + parameter.varargElementType != null -> { + val emptyArray = IrVarargImpl( + startOffset = callSite.startOffset, + endOffset = callSite.endOffset, + type = parameter.type, + varargElementType = parameter.varargElementType!! + ) + parameterToArgument += ParameterToArgument( + parameter = parameter, + argumentExpression = emptyArray + ) + } - parameter.varargElementType != null -> { - val emptyArray = IrVarargImpl( - startOffset = callSite.startOffset, - endOffset = callSite.endOffset, - type = parameter.type, - varargElementType = parameter.varargElementType!! - ) - parameterToArgument += ParameterToArgument( - parameter = parameter, - argumentExpression = emptyArray - ) - } - - else -> { - val message = "Incomplete expression: call to ${callee.descriptor} " + - "has no argument at index ${parameter.index}" - throw Error(message) + else -> { + val message = "Incomplete expression: call to ${callee.descriptor} " + + "has no argument at index ${parameter.index}" + throw Error(message) + } } } + return parameterToArgument + parametersWithDefaultToArgument // All arguments except default are evaluated at callsite, + // but default arguments are evaluated inside callee. + } + + //-------------------------------------------------------------------------// + + private fun evaluateArguments(callSite: IrCall, callee: IrFunction): List { + + val parameterToArgumentOld = buildParameterToArgument(callSite, callee) + val evaluationStatements = mutableListOf() + val substitutor = ParameterSubstitutor() + parameterToArgumentOld.forEach { + val parameterDescriptor = it.parameter.descriptor + + /* + * We need to create temporary variable for each argument except inlinable lambda arguments. + * For simplicity and to produce simpler IR we don't create temporaries for every immutable variable, + * not only for those referring to inlinable lambdas. + */ + if (it.isInlinableLambdaArgument) { + substituteMap[parameterDescriptor] = it.argumentExpression + return@forEach + } + + if (it.isImmutableVariableLoad) { + substituteMap[parameterDescriptor] = it.argumentExpression.transform(substitutor, data = null) // Arguments may reference the previous ones - substitute them. + return@forEach + } + + val newVariable = currentScope.scope.createTemporaryVariableWithWrappedDescriptor( // Create new variable and init it with the parameter expression. + irExpression = it.argumentExpression.transform(substitutor, data = null), // Arguments may reference the previous ones - substitute them. + nameHint = callee.descriptor.name.toString(), + isMutable = false) + + evaluationStatements.add(newVariable) + val getVal = IrGetValueImpl( + startOffset = currentScope.irElement.startOffset, + endOffset = currentScope.irElement.endOffset, + type = newVariable.type, + symbol = newVariable.symbol + ) + substituteMap[parameterDescriptor] = getVal + } + return evaluationStatements } - return parameterToArgument + parametersWithDefaultToArgument // All arguments except default are evaluated at callsite, - // but default arguments are evaluated inside callee. } - - //-------------------------------------------------------------------------// - - private fun evaluateArguments(callSite: IrCall, callee: IrFunction): List { - - val parameterToArgumentOld = buildParameterToArgument(callSite, callee) - val evaluationStatements = mutableListOf() - val substitutor = ParameterSubstitutor() - parameterToArgumentOld.forEach { - val parameterDescriptor = it.parameter.descriptor - - /* - * We need to create temporary variable for each argument except inlinable lambda arguments. - * For simplicity and to produce simpler IR we don't create temporaries for every immutable variable, - * not only for those referring to inlinable lambdas. - */ - if (it.isInlinableLambdaArgument) { - substituteMap[parameterDescriptor] = it.argumentExpression - return@forEach - } - - if (it.isImmutableVariableLoad) { - substituteMap[parameterDescriptor] = it.argumentExpression.transform(substitutor, data = null) // Arguments may reference the previous ones - substitute them. - return@forEach - } - - val newVariable = currentScope.scope.createTemporaryVariableWithWrappedDescriptor( // Create new variable and init it with the parameter expression. - irExpression = it.argumentExpression.transform(substitutor, data = null), // Arguments may reference the previous ones - substitute them. - nameHint = callee.descriptor.name.toString(), - isMutable = false) - - evaluationStatements.add(newVariable) - val getVal = IrGetValueImpl( - startOffset = currentScope.irElement.startOffset, - endOffset = currentScope.irElement.endOffset, - type = newVariable.type, - symbol = newVariable.symbol - ) - substituteMap[parameterDescriptor] = getVal - } - return evaluationStatements - } -} +} \ No newline at end of file