Move type operations in DeepCopyIrTreeWithDescriptors
This commit is contained in:
committed by
KonstantinAnisimov
parent
276c14a896
commit
c7de1d452f
+63
-2
@@ -43,12 +43,15 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.types.Variance
|
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 <TypeParameterDescriptor, KotlinType>?, val context: Context) {
|
||||||
|
|
||||||
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
|
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
|
||||||
|
private var typeSubstitutor = createTypeSubstitutor(typeArgsMap)
|
||||||
private var inlinedFunctionName = ""
|
private var inlinedFunctionName = ""
|
||||||
private var nameIndex = 0
|
private var nameIndex = 0
|
||||||
|
|
||||||
@@ -425,6 +428,51 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
|
|||||||
return newDeclaration
|
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 -----------------------------------------------//
|
//--- Copy declarations -----------------------------------------------//
|
||||||
|
|
||||||
private fun copyIrFunctionImpl(oldDeclaration: IrFunction, newDescriptor: DeclarationDescriptor): IrFunction {
|
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? {
|
private fun substituteType(oldType: KotlinType?): KotlinType? {
|
||||||
if (typeSubstitutor == null) return oldType
|
if (typeSubstitutor == null) return oldType
|
||||||
if (oldType == 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
|
return newTypeArguments
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------//
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun copyValueParameters(oldValueParameters: List <ValueParameterDescriptor>, containingDeclaration: CallableDescriptor): List <ValueParameterDescriptor> {
|
private fun copyValueParameters(oldValueParameters: List <ValueParameterDescriptor>, containingDeclaration: CallableDescriptor): List <ValueParameterDescriptor> {
|
||||||
@@ -489,4 +538,16 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
|
|||||||
newDescriptor
|
newDescriptor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun createTypeSubstitutor(typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?): TypeSubstitutor? {
|
||||||
|
|
||||||
|
if (typeArgsMap == null) return null
|
||||||
|
val substitutionContext = typeArgsMap.entries.associate {
|
||||||
|
(typeParameter, typeArgument) ->
|
||||||
|
typeParameter.typeConstructor to TypeProjectionImpl(typeArgument)
|
||||||
|
}
|
||||||
|
return TypeSubstitutor.create(substitutionContext)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+6
-104
@@ -185,14 +185,13 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun createInlineFunctionBody(functionDeclaration: IrFunction): IrInlineFunctionBody? {
|
private fun createInlineFunctionBody(functionDeclaration: IrFunction, typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?): IrInlineFunctionBody? {
|
||||||
functionDeclaration.transformChildrenVoid(this) // Inline recursively.
|
functionDeclaration.transformChildrenVoid(this) // TODO recursive inline is already processed in visitCall. Check
|
||||||
|
|
||||||
val originBlockBody = functionDeclaration.body
|
val originBlockBody = functionDeclaration.body
|
||||||
if (originBlockBody == null) return null // TODO workaround
|
if (originBlockBody == null) return null // TODO workaround
|
||||||
|
|
||||||
val typeSubstitutor = createTypeSubstitutor(typeArgsMap)
|
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, typeArgsMap, context)
|
||||||
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, typeSubstitutor, context)
|
|
||||||
val functionName = functionDeclaration.descriptor.name.toString()
|
val functionName = functionDeclaration.descriptor.name.toString()
|
||||||
|
|
||||||
val copyBlockBody = originBlockBody.accept(InlineCopyIr(), null) as IrBlockBody // Create copy of original function body.
|
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)
|
val lambdaInliner = LambdaInliner(parameterToArgument)
|
||||||
inlineBody.transformChildrenVoid(lambdaInliner)
|
inlineBody.transformChildrenVoid(lambdaInliner)
|
||||||
|
|
||||||
val transformer = ParametersTransformer(parameterToArgument, typeArgsMap, evaluationStatements)
|
val transformer = ParametersTransformer(parameterToArgument)
|
||||||
inlineBody.transformChildrenVoid(transformer) // Replace parameters with expression.
|
inlineBody.transformChildrenVoid(transformer) // Replace parameters with expression.
|
||||||
inlineBody.statements.addAll(0, evaluationStatements)
|
inlineBody.statements.addAll(0, evaluationStatements)
|
||||||
|
|
||||||
@@ -234,56 +233,12 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private inner class ParametersTransformer(val substituteMap: MutableMap <ValueDescriptor, IrExpression>,
|
private inner class ParametersTransformer(val substituteMap: MutableMap <ValueDescriptor, IrExpression>): IrElementTransformerVoid() {
|
||||||
val typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?,
|
|
||||||
val statements: MutableList<IrStatement>): IrElementTransformerVoid() {
|
|
||||||
|
|
||||||
override fun visitElement(element: IrElement) = element.accept(this, null)
|
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 {
|
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||||
|
|
||||||
val newExpression = super.visitGetValue(expression) as IrGetValue
|
val newExpression = super.visitGetValue(expression) as IrGetValue
|
||||||
@@ -293,59 +248,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
|
|
||||||
return argument
|
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 <TypeParameterDescriptor, KotlinType>? {
|
|
||||||
|
|
||||||
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 lambdaReturnType = copyLambdaFunction.descriptor.returnType!!
|
||||||
val inlineBody = IrInlineFunctionBody(0, 0, lambdaReturnType, lambdaFunction.descriptor, null, lambdaStatements)
|
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.accept(transformer, null) // Replace parameters with expression.
|
||||||
inlineBody.statements.addAll(0, evaluationStatements)
|
inlineBody.statements.addAll(0, evaluationStatements)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user