Support for ClassDescriptor and FunctionDescriptor copy
This commit is contained in:
committed by
KonstantinAnisimov
parent
4572b27592
commit
14fb3b87b6
+332
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
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.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
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
|
||||
|
||||
internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val context: Context) {
|
||||
|
||||
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
|
||||
private var inlinedFunctionName = ""
|
||||
private var nameIndex = 0
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun copy(irElement: IrElement, functionName: String) {
|
||||
inlinedFunctionName = functionName
|
||||
descriptorSubstituteMap.clear()
|
||||
irElement.acceptChildrenVoid(descriptorCollector)
|
||||
irElement.transformChildrenVoid(descriptorSubstitutor)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
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
|
||||
super.visitClass(declaration)
|
||||
|
||||
val constructors = oldDescriptor.constructors.map {
|
||||
descriptorSubstituteMap[it] as ClassConstructorDescriptor
|
||||
}.toSet()
|
||||
val oldPrimaryConstructor = oldDescriptor.unsubstitutedPrimaryConstructor!!
|
||||
val primaryConstructor = descriptorSubstituteMap[oldPrimaryConstructor] as ClassConstructorDescriptor
|
||||
newDescriptor.initialize(
|
||||
oldDescriptor.unsubstitutedMemberScope,
|
||||
constructors,
|
||||
primaryConstructor
|
||||
)
|
||||
}
|
||||
|
||||
//--- 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
|
||||
return Name.identifier(containingName + "_" + inlinedFunctionName + "_" + declarationName + "_" + indexStr)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
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 {
|
||||
|
||||
return when (oldDescriptor) {
|
||||
is SimpleFunctionDescriptor -> copySimpleFunctionDescriptor(oldDescriptor)
|
||||
is ConstructorDescriptor -> copyConstructorDescriptor(oldDescriptor)
|
||||
else -> TODO("Unsupported FunctionDescriptor subtype")
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
private fun copySimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor) : FunctionDescriptor {
|
||||
|
||||
val memberOwner = targetFunction.descriptor
|
||||
val newDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
memberOwner,
|
||||
oldDescriptor.annotations,
|
||||
generateName(oldDescriptor.name),
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
oldDescriptor.source
|
||||
).apply { isTailrec = oldDescriptor.isTailrec }
|
||||
|
||||
val newDispatchReceiverParameter = null
|
||||
val newTypeParameters = oldDescriptor.typeParameters
|
||||
val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, memberOwner)
|
||||
|
||||
newDescriptor.initialize(
|
||||
oldDescriptor.extensionReceiverParameter?.type,
|
||||
newDispatchReceiverParameter,
|
||||
newTypeParameters,
|
||||
newValueParameters,
|
||||
oldDescriptor.returnType,
|
||||
Modality.FINAL,
|
||||
Visibilities.LOCAL
|
||||
)
|
||||
return newDescriptor
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
private fun copyConstructorDescriptor(oldDescriptor: ConstructorDescriptor) : FunctionDescriptor {
|
||||
|
||||
val oldContainingDeclaration = oldDescriptor.containingDeclaration
|
||||
val containingDeclaration = descriptorSubstituteMap[oldContainingDeclaration]
|
||||
val newDescriptor = ClassConstructorDescriptorImpl.create(
|
||||
containingDeclaration as ClassDescriptor,
|
||||
oldDescriptor.annotations,
|
||||
oldDescriptor.isPrimary,
|
||||
oldDescriptor.source
|
||||
)
|
||||
|
||||
val newTypeParameters = oldDescriptor.typeParameters
|
||||
val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, newDescriptor)
|
||||
newDescriptor.initialize(
|
||||
oldDescriptor.dispatchReceiverParameter?.type,
|
||||
null, // TODO @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
|
||||
newTypeParameters,
|
||||
newValueParameters,
|
||||
oldDescriptor.returnType,
|
||||
oldDescriptor.modality,
|
||||
oldDescriptor.visibility
|
||||
)
|
||||
return newDescriptor
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
private fun copyClassDescriptor(oldDescriptor: ClassDescriptor): ClassDescriptorImpl {
|
||||
|
||||
return ClassDescriptorImpl(
|
||||
targetFunction.descriptor,
|
||||
generateName(oldDescriptor.name),
|
||||
oldDescriptor.modality,
|
||||
oldDescriptor.kind,
|
||||
listOf(context.builtIns.anyType),
|
||||
oldDescriptor.source,
|
||||
oldDescriptor.isExternal
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
val descriptorSubstitutor = object : IrElementTransformerVoid() {
|
||||
|
||||
override fun visitElement(element: IrElement): IrElement {
|
||||
return super.visitElement(element)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
val oldDeclaration = super.visitClass(declaration) as IrClass
|
||||
val newDescriptor = descriptorSubstituteMap[oldDeclaration.descriptor]
|
||||
if (newDescriptor == null) return oldDeclaration
|
||||
|
||||
val newDeclaration = IrClassImpl(
|
||||
oldDeclaration.startOffset,
|
||||
oldDeclaration.endOffset,
|
||||
oldDeclaration.origin,
|
||||
newDescriptor as ClassDescriptor,
|
||||
oldDeclaration.declarations
|
||||
)
|
||||
|
||||
return newDeclaration
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
val oldDeclaration = super.visitFunction(declaration) as IrFunction
|
||||
val newDescriptor = descriptorSubstituteMap[oldDeclaration.descriptor]
|
||||
if (newDescriptor == null) return oldDeclaration
|
||||
|
||||
return when (oldDeclaration) {
|
||||
is IrFunctionImpl -> copyIrFunctionImpl(oldDeclaration, newDescriptor)
|
||||
is IrConstructorImpl -> copyIrConstructorImpl(oldDeclaration, newDescriptor)
|
||||
else -> TODO("Unsupported IrFunction subtype")
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
|
||||
val irCall = super.visitCall(expression) as IrCall
|
||||
if (irCall !is IrCallImpl) return irCall
|
||||
|
||||
val descriptor = descriptorSubstituteMap.getOrDefault(irCall.descriptor, irCall.descriptor) as FunctionDescriptor
|
||||
return IrCallImpl(irCall.startOffset, irCall.endOffset, irCall.type, descriptor,
|
||||
irCall.typeArguments, irCall.origin, irCall.superQualifier).apply {
|
||||
irCall.descriptor.valueParameters.forEach {
|
||||
val valueArgument = irCall.getValueArgument(it)
|
||||
putValueArgument(it.index, valueArgument)
|
||||
}
|
||||
extensionReceiver = irCall.extensionReceiver
|
||||
dispatchReceiver = irCall.dispatchReceiver
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
override fun visitCallableReference(expression: IrCallableReference): IrExpression {
|
||||
|
||||
val oldReference = super.visitCallableReference(expression) as IrCallableReference
|
||||
val oldDescriptor = oldReference.descriptor
|
||||
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)
|
||||
|
||||
return newReference
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||
|
||||
val oldReturn = super.visitReturn(expression) as IrReturn
|
||||
val oldDescriptor = oldReturn.returnTarget
|
||||
val newDescriptor = descriptorSubstituteMap[oldDescriptor]
|
||||
if (newDescriptor == null) return oldReturn
|
||||
|
||||
val newReturn = IrReturnImpl(oldReturn.startOffset, oldReturn.endOffset,
|
||||
oldReturn.type, newDescriptor as CallableDescriptor, oldReturn.value)
|
||||
|
||||
return newReturn
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
|
||||
val oldExpression = super.visitGetValue(expression) as IrGetValue
|
||||
val oldDescriptor = oldExpression.descriptor
|
||||
val newDescriptor = descriptorSubstituteMap[oldDescriptor]
|
||||
if (newDescriptor == null) return oldExpression
|
||||
|
||||
val newExpression = IrGetValueImpl(
|
||||
oldExpression.startOffset, oldExpression.endOffset,
|
||||
newDescriptor as ValueParameterDescriptor, oldExpression.origin
|
||||
)
|
||||
return newExpression
|
||||
}
|
||||
|
||||
//--- Copy declarations -----------------------------------------------//
|
||||
|
||||
private fun copyIrFunctionImpl(oldDeclaration: IrFunction, newDescriptor: DeclarationDescriptor): IrFunction {
|
||||
return IrFunctionImpl(
|
||||
oldDeclaration.startOffset, oldDeclaration.endOffset, oldDeclaration.origin,
|
||||
newDescriptor as FunctionDescriptor, oldDeclaration.body
|
||||
)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
private fun copyIrConstructorImpl(oldDeclaration: IrConstructor, newDescriptor: DeclarationDescriptor): IrFunction {
|
||||
return IrConstructorImpl(
|
||||
oldDeclaration.startOffset, oldDeclaration.endOffset, oldDeclaration.origin,
|
||||
newDescriptor as ClassConstructorDescriptor, oldDeclaration.body!!
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+87
-49
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.DeepCopyIrTreeWithDescriptors
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
|
||||
import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver
|
||||
@@ -31,19 +32,24 @@ import org.jetbrains.kotlin.ir.util.DeepCopyIrTree
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.*
|
||||
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 FunctionInlining(val context: Context): IrElementTransformerVoid() {
|
||||
|
||||
private var currentFile : IrFile? = null
|
||||
private var currentFunction : IrFunction? = null
|
||||
private var currentScope : Scope? = null
|
||||
private var currentFile : IrFile? = null
|
||||
private var currentFunction : IrFunction? = null
|
||||
private var currentScope : Scope? = null
|
||||
private var copyWithDescriptors: DeepCopyIrTreeWithDescriptors? = null
|
||||
|
||||
private val deserializer = DeserializerDriver(context)
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
private val deserializer = DeserializerDriver(context)
|
||||
|
||||
fun inline(irModule: IrModuleFragment) = irModule.accept(this, null)
|
||||
|
||||
@@ -68,8 +74,9 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
currentFunction = declaration
|
||||
currentScope = Scope(declaration.descriptor)
|
||||
currentFunction = declaration
|
||||
currentScope = Scope(declaration.descriptor)
|
||||
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, context)
|
||||
return super.visitFunction(declaration)
|
||||
}
|
||||
|
||||
@@ -80,14 +87,12 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
||||
val fqName = currentFile!!.packageFragmentDescriptor.fqName.asString() // TODO to be removed after stdlib compilation
|
||||
if(fqName.contains("kotlin")) return super.visitCall(expression) // TODO to be removed after stdlib compilation
|
||||
|
||||
val functionDescriptor = expression.descriptor as FunctionDescriptor
|
||||
if (functionDescriptor.isInline) {
|
||||
val inlineFunctionBody = inlineFunction(expression)
|
||||
inlineFunctionBody.transformChildrenVoid(this)
|
||||
return inlineFunctionBody // Return newly created IrInlineBody instead of IrCall.
|
||||
}
|
||||
val irCall = super.visitCall(expression) as IrCall
|
||||
|
||||
return super.visitCall(expression)
|
||||
val functionDescriptor = irCall.descriptor as FunctionDescriptor
|
||||
if (functionDescriptor.isInline) return inlineFunction(irCall) // Return newly created IrInlineBody instead of IrCall.
|
||||
|
||||
return irCall
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
@@ -166,26 +171,48 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
private fun inlineFunction(irCall: IrCall): IrExpression {
|
||||
|
||||
private fun getFunctionDeclaration(irCall: IrCall): IrDeclaration? {
|
||||
|
||||
val functionDescriptor = irCall.descriptor as FunctionDescriptor
|
||||
val originalDescriptor = functionDescriptor.original
|
||||
val functionDeclaration =
|
||||
context.ir.originalModuleIndex.functions[originalDescriptor] ?: // Function is declared in the current module.
|
||||
deserializer.deserializeInlineBody(originalDescriptor) // Function is declared in another module.
|
||||
if (functionDeclaration == null) return super.visitCall(irCall)
|
||||
val copyFuncDeclaration = functionDeclaration.accept(InlineCopyIr(), // Create copy of the function.
|
||||
null) as IrFunction
|
||||
val functionDeclaration =
|
||||
(context.ir.originalModuleIndex.functions[originalDescriptor] ?: // Function is declared in the current module.
|
||||
deserializer.deserializeInlineBody(originalDescriptor)) // Function is declared in another module.
|
||||
return functionDeclaration
|
||||
}
|
||||
|
||||
val startOffset = copyFuncDeclaration.startOffset
|
||||
val endOffset = copyFuncDeclaration.endOffset
|
||||
val returnType = copyFuncDeclaration.descriptor.returnType!!
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
if (copyFuncDeclaration.body == null) return irCall // TODO workaround
|
||||
val blockBody = copyFuncDeclaration.body!! as IrBlockBody
|
||||
val statements = blockBody.statements
|
||||
val inlineBody = IrInlineFunctionBody(startOffset, endOffset, returnType, originalDescriptor, null, statements)
|
||||
private fun createInlineFunctionBody(functionDeclaration: IrFunction): IrInlineFunctionBody? {
|
||||
|
||||
val parametersOld = getArguments(irCall, copyFuncDeclaration) // Create map call_site_argument -> inline_function_parameter.
|
||||
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 functionName = functionDeclaration.descriptor.name.toString()
|
||||
copyWithDescriptors!!.copy(copyBlockBody, functionName) // TODO merge DeepCopyIrTreeWithDescriptors with InlineCopyIr
|
||||
|
||||
val originalDescriptor = functionDeclaration.descriptor.original
|
||||
val startOffset = functionDeclaration.startOffset
|
||||
val endOffset = functionDeclaration.endOffset
|
||||
val returnType = functionDeclaration.descriptor.returnType!!
|
||||
|
||||
return IrInlineFunctionBody(startOffset, endOffset, returnType, originalDescriptor, null, copyBlockBody.statements)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun inlineFunction(irCall: IrCall): IrExpression {
|
||||
|
||||
val irDeclaration = getFunctionDeclaration(irCall)
|
||||
if (irDeclaration == null) return irCall
|
||||
|
||||
val functionDeclaration = irDeclaration as IrFunction
|
||||
val inlineBody = createInlineFunctionBody(functionDeclaration)
|
||||
if (inlineBody == null) return irCall
|
||||
|
||||
val parametersOld = getArguments(irCall, functionDeclaration) // Create map call_site_argument -> inline_function_parameter.
|
||||
val evaluatedParameters = evaluateParameters(parametersOld)
|
||||
val parameterToArgument = evaluatedParameters.parameters
|
||||
val evaluationStatements = evaluatedParameters.statements
|
||||
@@ -300,20 +327,21 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
private fun createTypeSubstitutor(): TypeSubstitutor {
|
||||
|
||||
val irCall = super.visitCall(expression) as IrCall
|
||||
if (irCall !is IrCallImpl) return irCall
|
||||
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 (typeArgsMap == null) return irCall
|
||||
if (oldTypeArguments == null) return irCall
|
||||
|
||||
val substitutionContext = typeArgsMap.entries.associate {
|
||||
(typeParameter, typeArgument) ->
|
||||
typeParameter.typeConstructor to TypeProjectionImpl(typeArgument)
|
||||
}
|
||||
val typeSubstitutor = TypeSubstitutor.create(substitutionContext)
|
||||
if (oldTypeArguments == null) return null
|
||||
|
||||
val newTypeArguments = oldTypeArguments.map {
|
||||
val typeParameterDescriptor = it.key
|
||||
@@ -322,16 +350,24 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
||||
typeParameterDescriptor to newTypeArgument
|
||||
}.toMap()
|
||||
|
||||
val descriptor = irCall.descriptor
|
||||
val type = typeSubstitutor.substitute(irCall.type, Variance.INVARIANT) ?: irCall.type
|
||||
val startOffset = irCall.startOffset
|
||||
val endOffset = irCall.endOffset
|
||||
val origin = irCall.origin
|
||||
val superQualifier = irCall.superQualifier
|
||||
return newTypeArguments
|
||||
}
|
||||
|
||||
return IrCallImpl(startOffset, endOffset, type, descriptor, newTypeArguments, origin, superQualifier)
|
||||
.apply {
|
||||
descriptor.valueParameters.forEach {
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
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
|
||||
|
||||
return IrCallImpl(irCall.startOffset, irCall.endOffset, returnType, irCall.descriptor,
|
||||
typeArguments, irCall.origin, irCall.superQualifier).apply {
|
||||
irCall.descriptor.valueParameters.forEach {
|
||||
val valueArgument = irCall.getValueArgument(it)
|
||||
putValueArgument(it.index, valueArgument)
|
||||
}
|
||||
@@ -425,6 +461,8 @@ 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
|
||||
|
||||
val lambdaStatements = (copyLambdaFunction.body as IrBlockBody).statements
|
||||
val lambdaReturnType = copyLambdaFunction.descriptor.returnType!!
|
||||
val inlineBody = IrInlineFunctionBody(0, 0, lambdaReturnType, lambdaFunction.descriptor, null, lambdaStatements)
|
||||
|
||||
Reference in New Issue
Block a user