Inliner: removed old copier + refactor
This commit is contained in:
+3
-825
@@ -5,24 +5,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.lower
|
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.descriptors.*
|
||||||
import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope
|
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
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.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.*
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
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.symbols.*
|
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.*
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
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.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
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,
|
internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context,
|
||||||
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?,
|
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?,
|
||||||
val parent: IrDeclarationParent?) : IrCopierForInliner {
|
val parent: IrDeclarationParent?) {
|
||||||
|
|
||||||
override fun copy(irElement: IrElement): IrElement {
|
fun copy(irElement: IrElement): IrElement {
|
||||||
// Create new symbols.
|
// Create new symbols.
|
||||||
irElement.acceptVoid(symbolRemapper)
|
irElement.acceptVoid(symbolRemapper)
|
||||||
|
|
||||||
@@ -196,8 +176,6 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>) { }
|
|
||||||
|
|
||||||
private class SymbolRemapperImpl(descriptorsRemapper: DescriptorsRemapper)
|
private class SymbolRemapperImpl(descriptorsRemapper: DescriptorsRemapper)
|
||||||
: DeepCopySymbolRemapper(descriptorsRemapper) {
|
: DeepCopySymbolRemapper(descriptorsRemapper) {
|
||||||
|
|
||||||
@@ -224,803 +202,3 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context,
|
|||||||
InlinerSymbolRenamer()
|
InlinerSymbolRenamer()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal interface IrCopierForInliner {
|
|
||||||
fun copy(irElement: IrElement): IrElement
|
|
||||||
fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor,
|
|
||||||
val parentDescriptor: DeclarationDescriptor,
|
|
||||||
val context: Context,
|
|
||||||
val typeSubstitutor: TypeSubstitutor?) : IrCopierForInliner {
|
|
||||||
|
|
||||||
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = 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<TypeParameterDescriptor> {
|
|
||||||
return oldDescriptor.declaredTypeParameters
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
inner class DescriptorCollectorInitPhase : IrElementVisitorVoidWithContext() {
|
|
||||||
|
|
||||||
private val initializedProperties = mutableSetOf<PropertyDescriptor>()
|
|
||||||
|
|
||||||
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 <ValueParameterDescriptor>, 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 : IrFunction> T.transformParameters1(original: T): T =
|
|
||||||
apply {
|
|
||||||
transformTypeParameters(original, descriptor.getTypeParametersToTransform())
|
|
||||||
transformValueParameters1(original)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun <T : IrFunction> 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 : IrFunction> 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<DeclarationDescriptor, SubstitutedDescriptor>) {
|
|
||||||
descriptorSubstituteMap.forEach { t, u ->
|
|
||||||
globalSubstituteMap[t] = SubstitutedDescriptor(targetDescriptor, u)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class SubstitutedDescriptor(val inlinedFunction: FunctionDescriptor, val descriptor: DeclarationDescriptor)
|
|
||||||
|
|
||||||
internal class DescriptorSubstitutorForExternalScope(
|
|
||||||
val globalSubstituteMap: Map<DeclarationDescriptor, SubstitutedDescriptor>,
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+43
-181
@@ -3,216 +3,95 @@
|
|||||||
* that can be found in the LICENSE file.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("FoldInitializerAndIfToElvis")
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.lower
|
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.descriptors.explicitParameters
|
||||||
import org.jetbrains.kotlin.backend.common.lower.CoroutineIntrinsicLambdaOrigin
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.createTemporaryVariableWithWrappedDescriptor
|
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.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
|
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining
|
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.descriptors.resolveFakeOverride
|
||||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass
|
||||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isInlineParameter
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isInlineParameter
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
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.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
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.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
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.symbols.impl.IrReturnableBlockSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
import org.jetbrains.kotlin.ir.util.getArguments
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
import org.jetbrains.kotlin.ir.util.referenceFunction
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
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<D> : IrElementTransformer<D> {
|
internal class FunctionInlining(val context: Context) : IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
private val scopeStack = mutableListOf<ScopeWithIr>()
|
fun inline(irModule: IrModuleFragment) = irModule.accept(this, data = null)
|
||||||
|
|
||||||
final override fun visitFile(declaration: IrFile, data: D): IrFile {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
|
val callSite = super.visitCall(expression) as IrCall
|
||||||
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<T>(var value: T)
|
|
||||||
|
|
||||||
internal class FunctionInlining(val context: Context): IrElementTransformerWithContext<Ref<Boolean>>() {
|
|
||||||
|
|
||||||
private val globalSubstituteMap = mutableMapOf<DeclarationDescriptor, SubstitutedDescriptor>()
|
|
||||||
private val inlineFunctions = mutableMapOf<FunctionDescriptor, Boolean>()
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
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<Boolean>): 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<Boolean>): IrExpression {
|
|
||||||
|
|
||||||
val argsAreBad = Ref(false)
|
|
||||||
val callSite = super.visitCall(expression, argsAreBad) as IrCall
|
|
||||||
data.value = data.value or argsAreBad.value
|
|
||||||
if (!callSite.descriptor.needsInlining)
|
if (!callSite.descriptor.needsInlining)
|
||||||
return callSite
|
return callSite
|
||||||
val functionDescriptor = callSite.descriptor.resolveFakeOverride().original
|
|
||||||
if (callSite.symbol == context.ir.symbols.isInitializedGetter)
|
if (callSite.symbol == context.ir.symbols.isInitializedGetter)
|
||||||
return callSite
|
return callSite
|
||||||
|
|
||||||
val callee = getFunctionDeclaration(functionDescriptor)
|
val callee = getFunctionDeclaration(callSite.symbol)
|
||||||
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
|
|
||||||
|
|
||||||
// TODO: do we still need this Ref<Boolean> mechanism?
|
callee.transformChildrenVoid(this) // Process recursive inline.
|
||||||
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
|
|
||||||
|
|
||||||
|
val parent = allScopes.map { it.irElement }.filterIsInstance<IrDeclarationParent>().lastOrNull()
|
||||||
val currentCalleeIsBad = false
|
val inliner = Inliner(callSite, callee, currentScope!!, parent, context)
|
||||||
val inliner = Inliner(globalSubstituteMap, callSite, callee.first, !currentCalleeIsBad, currentScope!!,
|
|
||||||
allScopes.map { it.irElement }.filterIsInstance<IrDeclarationParent>().lastOrNull(), context, this)
|
|
||||||
return inliner.inline()
|
return inliner.inline()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: do we really need this function anymore?
|
private fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction {
|
||||||
private fun getFunctionDeclaration(descriptor: FunctionDescriptor): Pair<IrFunction, Boolean>? =
|
val descriptor = symbol.descriptor.original
|
||||||
when {
|
val languageVersionSettings = context.config.configuration.languageVersionSettings
|
||||||
descriptor.isBuiltInIntercepted(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")
|
error("Continuation.intercepted is not available with release coroutines")
|
||||||
|
|
||||||
descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(context.config.configuration.languageVersionSettings) ->
|
descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
|
||||||
getFunctionDeclaration(context.ir.symbols.konanSuspendCoroutineUninterceptedOrReturn.descriptor)
|
context.ir.symbols.konanSuspendCoroutineUninterceptedOrReturn.owner
|
||||||
|
|
||||||
descriptor == context.ir.symbols.coroutineContextGetter ->
|
descriptor == context.ir.symbols.coroutineContextGetter ->
|
||||||
getFunctionDeclaration(context.ir.symbols.konanCoroutineContextGetter.descriptor)
|
context.ir.symbols.konanCoroutineContextGetter.owner
|
||||||
|
|
||||||
else ->
|
else -> (symbol.owner as? IrSimpleFunction)?.resolveFakeOverride() ?: symbol.owner
|
||||||
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 inlineConstructor = FqName("kotlin.native.internal.InlineConstructor")
|
||||||
private val FunctionDescriptor.isInlineConstructor get() = annotations.hasAnnotation(inlineConstructor)
|
private val FunctionDescriptor.isInlineConstructor get() = annotations.hasAnnotation(inlineConstructor)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------//
|
private inner class Inliner(val callSite: IrCall,
|
||||||
|
|
||||||
private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>,
|
|
||||||
val callSite: IrCall,
|
|
||||||
val callee: IrFunction,
|
val callee: IrFunction,
|
||||||
val local: Boolean,
|
|
||||||
val currentScope: ScopeWithIr,
|
val currentScope: ScopeWithIr,
|
||||||
val parent: IrDeclarationParent?,
|
val parent: IrDeclarationParent?,
|
||||||
val context: Context,
|
val context: Context) {
|
||||||
val owner: FunctionInlining /*TODO: make inner*/) {
|
|
||||||
|
|
||||||
val copyIrElement =
|
val copyIrElement = run {
|
||||||
if (!local)
|
|
||||||
DeepCopyIrTreeWithDescriptors(callee.descriptor, currentScope.scope.scopeOwner,
|
|
||||||
context, createTypeSubstitutor(callSite))
|
|
||||||
else {
|
|
||||||
val typeParameters =
|
val typeParameters =
|
||||||
if (callee is IrConstructor)
|
if (callee is IrConstructor)
|
||||||
callee.parentAsClass.typeParameters
|
callee.parentAsClass.typeParameters
|
||||||
@@ -272,8 +151,6 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
|
|
||||||
val sourceFileName = context.ir.originalModuleIndex.declarationToFile[callee.descriptor.original] ?: ""
|
val sourceFileName = context.ir.originalModuleIndex.declarationToFile[callee.descriptor.original] ?: ""
|
||||||
|
|
||||||
copyIrElement.addCurrentSubstituteMap(globalSubstituteMap)
|
|
||||||
|
|
||||||
val transformer = ParameterSubstitutor()
|
val transformer = ParameterSubstitutor()
|
||||||
statements.transform { it.transform(transformer, data = null) }
|
statements.transform { it.transform(transformer, data = null) }
|
||||||
statements.addAll(0, evaluationStatements)
|
statements.addAll(0, evaluationStatements)
|
||||||
@@ -309,9 +186,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
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
|
||||||
val descriptor = newExpression.descriptor
|
val descriptor = newExpression.descriptor
|
||||||
val argument = substituteMap[descriptor]
|
val argument = substituteMap[descriptor] ?: return newExpression
|
||||||
|
|
||||||
if (argument == null) return newExpression
|
|
||||||
|
|
||||||
argument.transformChildrenVoid(this) // Default argument can contain subjects for substitution.
|
argument.transformChildrenVoid(this) // Default argument can contain subjects for substitution.
|
||||||
return copyIrElement.copy(argument) as IrExpression
|
return copyIrElement.copy(argument) as IrExpression
|
||||||
@@ -324,12 +199,10 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
return super.visitCall(expression)
|
return super.visitCall(expression)
|
||||||
|
|
||||||
val dispatchReceiver = expression.dispatchReceiver as IrGetValue
|
val dispatchReceiver = expression.dispatchReceiver as IrGetValue
|
||||||
val functionArgument = substituteMap[dispatchReceiver.descriptor]
|
val functionArgument = substituteMap[dispatchReceiver.descriptor] ?: return super.visitCall(expression)
|
||||||
if (functionArgument == null)
|
|
||||||
return super.visitCall(expression)
|
|
||||||
val dispatchDescriptor = dispatchReceiver.descriptor
|
val dispatchDescriptor = dispatchReceiver.descriptor
|
||||||
if (dispatchDescriptor is ValueParameterDescriptor &&
|
if (dispatchDescriptor is ValueParameterDescriptor && dispatchDescriptor.isNoinline)
|
||||||
dispatchDescriptor.isNoinline) return super.visitCall(expression)
|
return super.visitCall(expression)
|
||||||
|
|
||||||
if (functionArgument is IrFunctionReference) {
|
if (functionArgument is IrFunctionReference) {
|
||||||
val functionDescriptor = functionArgument.descriptor
|
val functionDescriptor = functionArgument.descriptor
|
||||||
@@ -364,7 +237,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
for (index in 0 until functionArgument.typeArgumentsCount)
|
for (index in 0 until functionArgument.typeArgumentsCount)
|
||||||
putTypeArgument(index, functionArgument.getTypeArgument(index))
|
putTypeArgument(index, functionArgument.getTypeArgument(index))
|
||||||
}
|
}
|
||||||
return owner.visitCall(super.visitCall(immediateCall) as IrCall, Ref(false))
|
return this@FunctionInlining.visitCall(super.visitCall(immediateCall) as IrCall)
|
||||||
}
|
}
|
||||||
if (functionArgument !is IrBlock)
|
if (functionArgument !is IrBlock)
|
||||||
return super.visitCall(expression)
|
return super.visitCall(expression)
|
||||||
@@ -381,21 +254,9 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
|
|
||||||
private fun isLambdaCall(irCall: IrCall) = irCall.descriptor.isFunctionInvoke && irCall.dispatchReceiver is IrGetValue
|
private fun isLambdaCall(irCall: IrCall) = irCall.descriptor.isFunctionInvoke && irCall.dispatchReceiver is IrGetValue
|
||||||
|
|
||||||
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<TypeConstructor, TypeProjection>()
|
|
||||||
for (index in 0 until irCall.typeArgumentsCount) {
|
|
||||||
val typeArgument = irCall.getTypeArgument(index) ?: continue
|
|
||||||
substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument.toKotlinType())
|
|
||||||
}
|
|
||||||
return TypeSubstitutor.create(substitutionContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private class ParameterToArgument(val parameter: IrValueParameter,
|
private inner class ParameterToArgument(val parameter: IrValueParameter,
|
||||||
val argumentExpression: IrExpression) {
|
val argumentExpression: IrExpression) {
|
||||||
|
|
||||||
val isInlinableLambdaArgument: Boolean
|
val isInlinableLambdaArgument: Boolean
|
||||||
@@ -539,3 +400,4 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
return evaluationStatements
|
return evaluationStatements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user