Type substitution relocated in DeepCopyIrWithDescriptors

This commit is contained in:
Konstantin Anisimov
2017-04-03 09:43:33 +07:00
committed by KonstantinAnisimov
parent ee3e408dcb
commit 2381e453d8
2 changed files with 217 additions and 125 deletions
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
@@ -28,9 +29,12 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -38,8 +42,12 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance
internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val context: Context) {
internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val typeSubstitutor: TypeSubstitutor?, val context: Context) {
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
private var inlinedFunctionName = ""
@@ -48,6 +56,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
//-------------------------------------------------------------------------//
fun copy(irElement: IrElement, functionName: String) {
inlinedFunctionName = functionName
descriptorSubstituteMap.clear()
irElement.acceptChildrenVoid(descriptorCollector)
@@ -58,30 +67,16 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
private val descriptorCollector = object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildren(this, null)
}
//---------------------------------------------------------------------//
override fun visitFunction(declaration: IrFunction) {
val oldDescriptor = declaration.descriptor
val newDescriptor = copyFunctionDescriptor(oldDescriptor)
descriptorSubstituteMap[oldDescriptor] = newDescriptor
super.visitFunction(declaration)
}
//---------------------------------------------------------------------//
override fun visitClass(declaration: IrClass) {
val oldDescriptor = declaration.descriptor
val newDescriptor = copyClassDescriptor(oldDescriptor)
descriptorSubstituteMap[oldDescriptor] = newDescriptor
descriptorSubstituteMap[oldDescriptor.thisAsReceiverParameter] = newDescriptor.thisAsReceiverParameter
super.visitClass(declaration)
val constructors = oldDescriptor.constructors.map {
descriptorSubstituteMap[it] as ClassConstructorDescriptor
val constructors = oldDescriptor.constructors.map { oldConstructorDescriptor ->
descriptorSubstituteMap[oldConstructorDescriptor] as ClassConstructorDescriptor
}.toSet()
var primaryConstructor: ClassConstructorDescriptor? = null
@@ -104,9 +99,60 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
)
}
//---------------------------------------------------------------------//
override fun visitFunction(declaration: IrFunction) {
val oldDescriptor = declaration.descriptor
val newDescriptor = copyFunctionDescriptor(oldDescriptor)
descriptorSubstituteMap[oldDescriptor] = newDescriptor
super.visitFunction(declaration)
}
//---------------------------------------------------------------------//
override fun visitCall(expression: IrCall) {
val descriptor = expression.descriptor as FunctionDescriptor
if (descriptor.isFunctionInvoke) {
val oldDescriptor = descriptor as SimpleFunctionDescriptor
val containingDeclaration = targetFunction.descriptor
val newReturnType = substituteType(oldDescriptor.returnType)!!
val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, containingDeclaration)
val newDescriptor = oldDescriptor.newCopyBuilder().apply {
setReturnType(newReturnType)
setValueParameters(newValueParameters)
}.build()
descriptorSubstituteMap[oldDescriptor] = newDescriptor!!
}
super.visitCall(expression)
}
//---------------------------------------------------------------------//
override fun visitVariable(declaration: IrVariable) {
val oldDescriptor = declaration.descriptor
val newDescriptor = IrTemporaryVariableDescriptorImpl(
targetFunction.descriptor,
generateName(oldDescriptor.name),
substituteType(oldDescriptor.type)!!,
oldDescriptor.isVar)
descriptorSubstituteMap[oldDescriptor] = newDescriptor
super.visitVariable(declaration)
}
//---------------------------------------------------------------------//
override fun visitElement(element: IrElement) {
element.acceptChildren(this, null)
}
//--- Copy descriptors ------------------------------------------------//
private fun generateName(name: Name): Name {
val containingName = targetFunction.descriptor.name.toString() // Name of inline target (function we inline in)
val declarationName = name.toString() // Name of declaration
val indexStr = (nameIndex++).toString() // Unique for inline target index
@@ -115,33 +161,11 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
//---------------------------------------------------------------------//
private fun copyValueParameters(oldValueParameters: List <ValueParameterDescriptor>, owner: CallableDescriptor): List <ValueParameterDescriptor> {
return oldValueParameters.map { oldDescriptor ->
val newDescriptor = ValueParameterDescriptorImpl(
owner,
oldDescriptor.original,
oldDescriptor.index,
oldDescriptor.annotations,
oldDescriptor.name,
oldDescriptor.type,
oldDescriptor.declaresDefaultValue(),
oldDescriptor.isCrossinline,
oldDescriptor.isNoinline,
oldDescriptor.varargElementType,
oldDescriptor.source
)
descriptorSubstituteMap[oldDescriptor] = newDescriptor
newDescriptor
}
}
//---------------------------------------------------------------------//
private fun copyFunctionDescriptor(oldDescriptor: FunctionDescriptor): FunctionDescriptor {
private fun copyFunctionDescriptor(oldDescriptor: CallableDescriptor): CallableDescriptor {
return when (oldDescriptor) {
is SimpleFunctionDescriptor -> copySimpleFunctionDescriptor(oldDescriptor)
is ConstructorDescriptor -> copyConstructorDescriptor(oldDescriptor)
is ConstructorDescriptor -> copyConstructorDescriptor(oldDescriptor)
is SimpleFunctionDescriptor -> copySimpleFunctionDescriptor(oldDescriptor)
else -> TODO("Unsupported FunctionDescriptor subtype")
}
}
@@ -150,30 +174,29 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
private fun copySimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor) : FunctionDescriptor {
val oldContainingDeclaration = oldDescriptor.containingDeclaration
val memberOwner = descriptorSubstituteMap[oldContainingDeclaration] ?: targetFunction.descriptor
val containingDeclaration = targetFunction.descriptor
val newDescriptor = SimpleFunctionDescriptorImpl.create(
memberOwner,
containingDeclaration,
oldDescriptor.annotations,
generateName(oldDescriptor.name),
CallableMemberDescriptor.Kind.SYNTHESIZED,
oldDescriptor.source
).apply { isTailrec = oldDescriptor.isTailrec }
val oldDispatchReceiverParameter = oldDescriptor.dispatchReceiverParameter
val newDispatchReceiverParameter =
if (oldDispatchReceiverParameter == null) null
else descriptorSubstituteMap[oldDispatchReceiverParameter]
val newTypeParameters = oldDescriptor.typeParameters
val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, newDescriptor)
val newDispatchReceiverParameter = null // TODO
val newTypeParameters = oldDescriptor.typeParameters
val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, containingDeclaration)
val receiverParameterType = substituteType(oldDescriptor.extensionReceiverParameter?.type)
val returnType = substituteType(oldDescriptor.returnType)
assert(newTypeParameters.isEmpty())
newDescriptor.initialize(
oldDescriptor.extensionReceiverParameter?.type,
newDispatchReceiverParameter as? ReceiverParameterDescriptor,
receiverParameterType,
newDispatchReceiverParameter,
newTypeParameters,
newValueParameters,
oldDescriptor.returnType,
Modality.FINAL,
returnType,
oldDescriptor.modality,
oldDescriptor.visibility
)
newDescriptor.overriddenDescriptors += oldDescriptor.overriddenDescriptors
@@ -193,14 +216,18 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
oldDescriptor.source
)
val newTypeParameters = oldDescriptor.typeParameters
val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, newDescriptor)
val newTypeParameters = oldDescriptor.typeParameters
val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, newDescriptor)
val receiverParameterType = substituteType(oldDescriptor.dispatchReceiverParameter?.type)
val returnType = substituteType(oldDescriptor.returnType)
assert(newTypeParameters.isEmpty())
newDescriptor.initialize(
oldDescriptor.dispatchReceiverParameter?.type,
receiverParameterType,
null, // TODO @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
newTypeParameters,
newValueParameters,
oldDescriptor.returnType,
returnType,
oldDescriptor.modality,
oldDescriptor.visibility
)
@@ -252,6 +279,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
//---------------------------------------------------------------------//
override fun visitFunction(declaration: IrFunction): IrStatement {
val oldDeclaration = super.visitFunction(declaration) as IrFunction
val newDescriptor = descriptorSubstituteMap[oldDeclaration.descriptor]
if (newDescriptor == null) return oldDeclaration
@@ -267,29 +295,37 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
override fun visitCall(expression: IrCall): IrExpression {
val irCall = super.visitCall(expression) as IrCall
if (irCall !is IrCallImpl) return irCall // TODO what other kinds of call can we meet?
val oldExpression = super.visitCall(expression) as IrCall
if (oldExpression !is IrCallImpl) return oldExpression // TODO what other kinds of call can we meet?
val oldDescriptor = irCall.descriptor
val newDescriptor = descriptorSubstituteMap.getOrDefault(oldDescriptor.original,
oldDescriptor) as FunctionDescriptor
val oldDescriptor = oldExpression.descriptor
val newDescriptor = descriptorSubstituteMap.getOrDefault(oldDescriptor, oldDescriptor)
val oldSuperQualifier = irCall.superQualifier
val oldSuperQualifier = oldExpression.superQualifier
var newSuperQualifier: ClassDescriptor? = oldSuperQualifier
if (newSuperQualifier != null) {
newSuperQualifier = descriptorSubstituteMap.getOrDefault(newSuperQualifier,
newSuperQualifier) as ClassDescriptor
}
return IrCallImpl(irCall.startOffset, irCall.endOffset, irCall.type, newDescriptor,
irCall.typeArguments, irCall.origin, newSuperQualifier).apply {
irCall.descriptor.valueParameters.forEach {
val valueArgument = irCall.getValueArgument(it)
val newExpression = IrCallImpl(
oldExpression.startOffset,
oldExpression.endOffset,
substituteType(oldExpression.type)!!,
newDescriptor as FunctionDescriptor,
substituteTypeArguments(oldExpression.typeArguments),
oldExpression.origin,
newSuperQualifier
).apply {
oldExpression.descriptor.valueParameters.forEach {
val valueArgument = oldExpression.getValueArgument(it)
putValueArgument(it.index, valueArgument)
}
extensionReceiver = irCall.extensionReceiver
dispatchReceiver = irCall.dispatchReceiver
extensionReceiver = oldExpression.extensionReceiver
dispatchReceiver = oldExpression.dispatchReceiver
}
return newExpression
}
//---------------------------------------------------------------------//
@@ -301,11 +337,16 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
val newDescriptor = descriptorSubstituteMap[oldDescriptor]
if (newDescriptor == null) return oldReference
val typeArguments = (oldReference as IrMemberAccessExpressionBase).typeArguments
val newReference = IrCallableReferenceImpl(expression.startOffset,
oldReference.endOffset, oldReference.type, newDescriptor as CallableDescriptor,
typeArguments, oldReference.origin)
val oldTypeArguments = (oldReference as IrMemberAccessExpressionBase).typeArguments
val newTypeArguments = substituteTypeArguments(oldTypeArguments)
val newReference = IrCallableReferenceImpl(
expression.startOffset,
oldReference.endOffset,
substituteType(oldReference.type)!!,
newDescriptor as CallableDescriptor,
newTypeArguments,
oldReference.origin
)
return newReference
}
@@ -318,9 +359,13 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
val newDescriptor = descriptorSubstituteMap[oldDescriptor]
if (newDescriptor == null) return oldReturn
val newReturn = IrReturnImpl(oldReturn.startOffset, oldReturn.endOffset,
oldReturn.type, newDescriptor as CallableDescriptor, oldReturn.value)
val newReturn = IrReturnImpl(
oldReturn.startOffset,
oldReturn.endOffset,
substituteType(oldReturn.type)!!,
newDescriptor as CallableDescriptor,
oldReturn.value
)
return newReturn
}
@@ -334,12 +379,48 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
if (newDescriptor == null) return oldExpression
val newExpression = IrGetValueImpl(
oldExpression.startOffset, oldExpression.endOffset,
newDescriptor as ValueParameterDescriptor, oldExpression.origin
oldExpression.startOffset,
oldExpression.endOffset,
newDescriptor as ValueDescriptor,
oldExpression.origin
)
return newExpression
}
//---------------------------------------------------------------------//
override fun visitSetVariable(expression: IrSetVariable): IrExpression {
val oldExpression = super.visitSetVariable(expression) as IrSetVariable
val oldDescriptor = oldExpression.descriptor
val newDescriptor = descriptorSubstituteMap[oldDescriptor]
if (newDescriptor == null) return oldExpression
val newExpression = IrSetVariableImpl(
oldExpression.startOffset,
oldExpression.endOffset,
newDescriptor as VariableDescriptor,
oldExpression.value,
oldExpression.origin
)
return newExpression
}
//---------------------------------------------------------------------//
override fun visitVariable(declaration: IrVariable): IrStatement {
val oldDeclaration = super.visitVariable(declaration) as IrVariable
val newDescriptor = descriptorSubstituteMap[oldDeclaration.descriptor]
val newDeclaration = IrVariableImpl(
oldDeclaration.startOffset,
oldDeclaration.endOffset,
oldDeclaration.origin,
newDescriptor as VariableDescriptor,
oldDeclaration.initializer
)
return newDeclaration
}
//--- Copy declarations -----------------------------------------------//
private fun copyIrFunctionImpl(oldDeclaration: IrFunction, newDescriptor: DeclarationDescriptor): IrFunction {
@@ -358,4 +439,50 @@ 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
}
//---------------------------------------------------------------------//
private fun substituteTypeArguments(oldTypeArguments: Map <TypeParameterDescriptor, KotlinType>?): Map <TypeParameterDescriptor, KotlinType>? {
if (oldTypeArguments == null) return null
if (typeSubstitutor == null) return oldTypeArguments
val newTypeArguments = oldTypeArguments.entries.associate {
val typeParameterDescriptor = it.key
val oldTypeArgument = it.value
val newTypeArgument = substituteType(oldTypeArgument)!!
typeParameterDescriptor to newTypeArgument
}
return newTypeArguments
}
//---------------------------------------------------------------------//
private fun copyValueParameters(oldValueParameters: List <ValueParameterDescriptor>, containingDeclaration: CallableDescriptor): List <ValueParameterDescriptor> {
return oldValueParameters.map { oldDescriptor ->
val newDescriptor = ValueParameterDescriptorImpl(
containingDeclaration,
oldDescriptor.original,
oldDescriptor.index,
oldDescriptor.annotations,
oldDescriptor.name,
substituteType(oldDescriptor.type)!!,
oldDescriptor.declaresDefaultValue(),
oldDescriptor.isCrossinline,
oldDescriptor.isNoinline,
substituteType(oldDescriptor.varargElementType),
oldDescriptor.source
)
descriptorSubstituteMap[oldDescriptor] = newDescriptor
newDescriptor
}
}
}
@@ -77,7 +77,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
override fun visitFunction(declaration: IrFunction): IrStatement {
currentFunction = declaration
currentScope = Scope(declaration.descriptor)
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, context)
return super.visitFunction(declaration)
}
@@ -192,8 +191,11 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
val originBlockBody = functionDeclaration.body
if (originBlockBody == null) return null // TODO workaround
val copyBlockBody = originBlockBody.accept(InlineCopyIr(), null) as IrBlockBody // Create copy of original function body.
val typeSubstitutor = createTypeSubstitutor(typeArgsMap)
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, typeSubstitutor, context)
val functionName = functionDeclaration.descriptor.name.toString()
val copyBlockBody = originBlockBody.accept(InlineCopyIr(), null) as IrBlockBody // Create copy of original function body.
copyWithDescriptors!!.copy(copyBlockBody, functionName) // TODO merge DeepCopyIrTreeWithDescriptors with InlineCopyIr
val originalDescriptor = functionDeclaration.descriptor.original
@@ -212,7 +214,8 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
if (irDeclaration == null) return irCall
val functionDeclaration = irDeclaration as IrFunction
val inlineBody = createInlineFunctionBody(functionDeclaration)
val typeArgsMap = (irCall as IrMemberAccessExpressionBase).typeArguments
val inlineBody = createInlineFunctionBody(functionDeclaration, typeArgsMap)
if (inlineBody == null) return irCall
val parametersOld = getArguments(irCall, functionDeclaration) // Create map call_site_argument -> inline_function_parameter.
@@ -222,7 +225,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
val lambdaInliner = LambdaInliner(parameterToArgument)
inlineBody.transformChildrenVoid(lambdaInliner)
val typeArgsMap = (irCall as IrMemberAccessExpressionBase).typeArguments
val transformer = ParametersTransformer(parameterToArgument, typeArgsMap, evaluationStatements)
inlineBody.transformChildrenVoid(transformer) // Replace parameters with expression.
inlineBody.statements.addAll(0, evaluationStatements)
@@ -283,6 +285,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
//---------------------------------------------------------------------//
override fun visitGetValue(expression: IrGetValue): IrExpression {
val newExpression = super.visitGetValue(expression) as IrGetValue
val descriptor = newExpression.descriptor
val argument = substituteMap[descriptor]?.accept(InlineCopyIr(), null) as IrExpression? // Find expression to replace this parameter.
@@ -293,44 +296,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
//---------------------------------------------------------------------//
private fun newVariable(oldVariable: IrVariable): IrVariable {
val initializer = oldVariable.initializer!!
val isMutable = oldVariable.descriptor.isVar
val varName = currentScope!!.scopeOwner.name.toString() + "_inline"
return currentScope!!.createTemporaryVariable(initializer, varName, isMutable) // Create new variable and init it with the parameter expression.
}
//---------------------------------------------------------------------//
override fun visitVariable(declaration: IrVariable): IrStatement {
val newDeclaration = super.visitVariable(declaration) as IrVariable // Process variable initializer.
val newVariable = newVariable(newDeclaration) // Create new local variable.
val getVal = IrGetValueImpl(0, 0, newVariable.descriptor) // Create new IR element representing access the new variable.
val descriptor = declaration.descriptor.original as ValueDescriptor
substituteMap[descriptor] = getVal
return newVariable
}
//---------------------------------------------------------------------//
override fun visitSetVariable(expression: IrSetVariable): IrExpression {
val result = super.visitSetVariable(expression)
val substitute = substituteMap[expression.descriptor] // Get substitution for this variable.
if (substitute == null) return result // If there is no substitution - do nothing.
val startOffset = expression.startOffset
val endOffset = expression.endOffset
val descriptor = (substitute as IrGetValue).descriptor as VariableDescriptor
val value = expression.value
val origin = expression.origin
return IrSetVariableImpl(startOffset, endOffset, descriptor, value, origin) // Create SetVariable expression for the new descriptor.
}
//---------------------------------------------------------------------//
private fun createTypeSubstitutor(): TypeSubstitutor {
val substitutionContext = typeArgsMap!!.entries.associate {
@@ -467,7 +432,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
val copyLambdaFunction = lambdaFunction.accept(InlineCopyIr(), // Create copy of the function.
null) as IrFunction
copyWithDescriptors!!.copy(copyLambdaFunction, "lambda") // TODO merge DeepCopyIrTreeWithDescriptors with InlineCopyIr
copyWithDescriptors!!.copy(copyLambdaFunction, "lambda") // TODO merge DeepCopyIrTreeWithDescriptors with InlineCopyIr
val lambdaStatements = (copyLambdaFunction.body as IrBlockBody).statements
val lambdaReturnType = copyLambdaFunction.descriptor.returnType!!