diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt index 0d154a11872..1a62f316a31 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt @@ -43,12 +43,15 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.typeUtil.makeNullable -internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val typeSubstitutor: TypeSubstitutor?, val context: Context) { +internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typeArgsMap: Map ?, val context: Context) { private val descriptorSubstituteMap: MutableMap = mutableMapOf() + private var typeSubstitutor = createTypeSubstitutor(typeArgsMap) private var inlinedFunctionName = "" private var nameIndex = 0 @@ -425,6 +428,51 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val return newDeclaration } + //---------------------------------------------------------------------// + + fun getTypeOperatorReturnType(operator: IrTypeOperator, type: KotlinType) : KotlinType { + return when (operator) { + IrTypeOperator.CAST, + IrTypeOperator.IMPLICIT_CAST, + IrTypeOperator.IMPLICIT_NOTNULL, + IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, + IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type + IrTypeOperator.SAFE_CAST -> type.makeNullable() + IrTypeOperator.INSTANCEOF, + IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType + } + } + + //---------------------------------------------------------------------// + + override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression { + + val oldExpression = super.visitTypeOperator(expression) as IrTypeOperatorCall + if (typeArgsMap == null) return oldExpression + + if (oldExpression.operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT) { // Nothing to do for IMPLICIT_COERCION_TO_UNIT + return oldExpression + } + + val typeOperand = oldExpression.typeOperand + val operandTypeDescriptor = typeOperand.constructor.declarationDescriptor + if (operandTypeDescriptor !is TypeParameterDescriptor) return oldExpression // It is not TypeParameter - do nothing + + var newType = typeArgsMap[operandTypeDescriptor] ?: return expression + if (typeOperand.isMarkedNullable) newType = newType.makeNullable() + val operator = oldExpression.operator + val returnType = getTypeOperatorReturnType(operator, newType) + + return IrTypeOperatorCallImpl( + oldExpression.startOffset, + oldExpression.endOffset, + returnType, + oldExpression.operator, + newType, + oldExpression.argument + ) + } + //--- Copy declarations -----------------------------------------------// private fun copyIrFunctionImpl(oldDeclaration: IrFunction, newDescriptor: DeclarationDescriptor): IrFunction { @@ -449,7 +497,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val private fun substituteType(oldType: KotlinType?): KotlinType? { if (typeSubstitutor == null) return oldType if (oldType == null) return oldType - return typeSubstitutor.substitute(oldType, Variance.INVARIANT) ?: oldType + return typeSubstitutor!!.substitute(oldType, Variance.INVARIANT) ?: oldType } //---------------------------------------------------------------------// @@ -467,6 +515,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val } return newTypeArguments } + //---------------------------------------------------------------------// private fun copyValueParameters(oldValueParameters: List , containingDeclaration: CallableDescriptor): List { @@ -489,4 +538,16 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val newDescriptor } } + + //-------------------------------------------------------------------------// + + private fun createTypeSubstitutor(typeArgsMap: Map ?): TypeSubstitutor? { + + if (typeArgsMap == null) return null + val substitutionContext = typeArgsMap.entries.associate { + (typeParameter, typeArgument) -> + typeParameter.typeConstructor to TypeProjectionImpl(typeArgument) + } + return TypeSubstitutor.create(substitutionContext) + } } \ 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 4be8f7ef4a6..1885e0e4c96 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 @@ -185,14 +185,13 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( //-------------------------------------------------------------------------// - private fun createInlineFunctionBody(functionDeclaration: IrFunction): IrInlineFunctionBody? { - functionDeclaration.transformChildrenVoid(this) // Inline recursively. + private fun createInlineFunctionBody(functionDeclaration: IrFunction, typeArgsMap: Map ?): IrInlineFunctionBody? { + functionDeclaration.transformChildrenVoid(this) // TODO recursive inline is already processed in visitCall. Check val originBlockBody = functionDeclaration.body if (originBlockBody == null) return null // TODO workaround - val typeSubstitutor = createTypeSubstitutor(typeArgsMap) - copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, typeSubstitutor, context) + copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, typeArgsMap, context) val functionName = functionDeclaration.descriptor.name.toString() val copyBlockBody = originBlockBody.accept(InlineCopyIr(), null) as IrBlockBody // Create copy of original function body. @@ -225,7 +224,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( val lambdaInliner = LambdaInliner(parameterToArgument) inlineBody.transformChildrenVoid(lambdaInliner) - val transformer = ParametersTransformer(parameterToArgument, typeArgsMap, evaluationStatements) + val transformer = ParametersTransformer(parameterToArgument) inlineBody.transformChildrenVoid(transformer) // Replace parameters with expression. inlineBody.statements.addAll(0, evaluationStatements) @@ -234,56 +233,12 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( //-------------------------------------------------------------------------// - private inner class ParametersTransformer(val substituteMap: MutableMap , - val typeArgsMap: Map ?, - val statements: MutableList): IrElementTransformerVoid() { + private inner class ParametersTransformer(val substituteMap: MutableMap ): IrElementTransformerVoid() { override fun visitElement(element: IrElement) = element.accept(this, null) //---------------------------------------------------------------------// - fun getTypeOperatorReturnType(operator: IrTypeOperator, type: KotlinType) : KotlinType { - return when (operator) { - IrTypeOperator.CAST, - IrTypeOperator.IMPLICIT_CAST, - IrTypeOperator.IMPLICIT_NOTNULL, - IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, - IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type - IrTypeOperator.SAFE_CAST -> type.makeNullable() - IrTypeOperator.INSTANCEOF, - IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType - } - } - - //---------------------------------------------------------------------// - - override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression { - - val newExpression = super.visitTypeOperator(expression) as IrTypeOperatorCall - if (typeArgsMap == null) return newExpression - - if (newExpression.operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT) { // Nothing to do for IMPLICIT_COERCION_TO_UNIT - return newExpression - } - - val operandTypeDescriptor = newExpression.typeOperand.constructor.declarationDescriptor - if (operandTypeDescriptor !is TypeParameterDescriptor) return newExpression // It is not TypeParameter - do nothing - - var typeNew = typeArgsMap[operandTypeDescriptor] - ?: return expression - if (newExpression.typeOperand.isMarkedNullable) - typeNew = typeNew.makeNullable() - val startOffset = newExpression.startOffset - val endOffset = newExpression.endOffset - val operator = newExpression.operator - val argument = newExpression.argument - val type = getTypeOperatorReturnType(operator, typeNew) - - return IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, typeNew, argument) - } - - //---------------------------------------------------------------------// - override fun visitGetValue(expression: IrGetValue): IrExpression { val newExpression = super.visitGetValue(expression) as IrGetValue @@ -293,59 +248,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( return argument } - - //---------------------------------------------------------------------// - - private fun createTypeSubstitutor(): TypeSubstitutor { - - val substitutionContext = typeArgsMap!!.entries.associate { - (typeParameter, typeArgument) -> - typeParameter.typeConstructor to TypeProjectionImpl(typeArgument) - } - return TypeSubstitutor.create(substitutionContext) - } - - //---------------------------------------------------------------------// - - private fun substituteTypeArguments(irCall: IrCall, typeSubstitutor: TypeSubstitutor): Map ? { - - val oldTypeArguments = (irCall as IrMemberAccessExpressionBase).typeArguments - if (oldTypeArguments == null) return null - - val newTypeArguments = oldTypeArguments.map { - val typeParameterDescriptor = it.key - val oldTypeArgument = it.value - val newTypeArgument = typeSubstitutor.substitute(oldTypeArgument, Variance.INVARIANT) ?: oldTypeArgument - typeParameterDescriptor to newTypeArgument - }.toMap() - - return newTypeArguments - } - - //---------------------------------------------------------------------// - - override fun visitCall(expression: IrCall): IrExpression { - - val irCall = super.visitCall(expression) as IrCall - if (irCall !is IrCallImpl) return irCall - if (typeArgsMap == null) return irCall - - val typeSubstitutor = createTypeSubstitutor() - val typeArguments = substituteTypeArguments(irCall, typeSubstitutor) - val returnType = typeSubstitutor.substitute(irCall.type, Variance.INVARIANT) ?: irCall.type - val descriptor = irCall.descriptor.substitute(typeSubstitutor)!! - val superQualifier = irCall.superQualifier?.substitute(typeSubstitutor) - - return IrCallImpl(irCall.startOffset, irCall.endOffset, returnType, descriptor, - typeArguments, irCall.origin, superQualifier).apply { - irCall.descriptor.valueParameters.forEach { - val valueArgument = irCall.getValueArgument(it) - putValueArgument(it.index, valueArgument) - } - extensionReceiver = irCall.extensionReceiver - dispatchReceiver = irCall.dispatchReceiver - } - } } //-------------------------------------------------------------------------// @@ -438,7 +340,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( val lambdaReturnType = copyLambdaFunction.descriptor.returnType!! val inlineBody = IrInlineFunctionBody(0, 0, lambdaReturnType, lambdaFunction.descriptor, null, lambdaStatements) - val transformer = ParametersTransformer(parameterToArgument, null, lambdaStatements) + val transformer = ParametersTransformer(parameterToArgument) inlineBody.accept(transformer, null) // Replace parameters with expression. inlineBody.statements.addAll(0, evaluationStatements)