Removed descriptors from inliner
This commit is contained in:
-46
@@ -9,10 +9,6 @@ import org.jetbrains.kotlin.backend.common.atMostOne
|
|||||||
import org.jetbrains.kotlin.backend.konan.RuntimeNames
|
import org.jetbrains.kotlin.backend.konan.RuntimeNames
|
||||||
import org.jetbrains.kotlin.backend.konan.binaryTypeIsReference
|
import org.jetbrains.kotlin.backend.konan.binaryTypeIsReference
|
||||||
import org.jetbrains.kotlin.backend.konan.isObjCClass
|
import org.jetbrains.kotlin.backend.konan.isObjCClass
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
|
||||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
|
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
|
||||||
@@ -27,9 +23,6 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|
||||||
import org.jetbrains.kotlin.ir.util.isFunction
|
|
||||||
import org.jetbrains.kotlin.ir.util.isKFunction
|
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
@@ -40,7 +33,6 @@ import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||||
|
|
||||||
|
|
||||||
@@ -76,30 +68,6 @@ private val kotlinNativeInternalPackageName = FqName.fromSegments(listOf("kotlin
|
|||||||
internal val KonanBuiltIns.kotlinNativeInternal: MemberScope
|
internal val KonanBuiltIns.kotlinNativeInternal: MemberScope
|
||||||
get() = this.builtInsModule.getPackage(kotlinNativeInternalPackageName).memberScope
|
get() = this.builtInsModule.getPackage(kotlinNativeInternalPackageName).memberScope
|
||||||
|
|
||||||
internal val KotlinType.isKFunctionType: Boolean
|
|
||||||
get() {
|
|
||||||
val kind = constructor.declarationDescriptor?.getFunctionalClassKind()
|
|
||||||
return kind == FunctionClassDescriptor.Kind.KFunction
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val FunctionDescriptor.isFunctionInvoke: Boolean
|
|
||||||
get() {
|
|
||||||
val dispatchReceiver = dispatchReceiverParameter ?: return false
|
|
||||||
assert(!dispatchReceiver.type.isKFunctionType)
|
|
||||||
|
|
||||||
return (dispatchReceiver.type.isFunctionType || dispatchReceiver.type.isSuspendFunctionType) &&
|
|
||||||
this.isOperator && this.name == OperatorNameConventions.INVOKE
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val IrFunction.isFunctionInvoke: Boolean
|
|
||||||
get() {
|
|
||||||
val dispatchReceiver = dispatchReceiverParameter ?: return false
|
|
||||||
assert(!dispatchReceiver.type.isKFunction())
|
|
||||||
|
|
||||||
return dispatchReceiver.type.isFunction() &&
|
|
||||||
/* this.isOperator &&*/ this.name == OperatorNameConventions.INVOKE
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun ClassDescriptor.isUnit() = this.defaultType.isUnit()
|
internal fun ClassDescriptor.isUnit() = this.defaultType.isUnit()
|
||||||
|
|
||||||
internal fun ClassDescriptor.isNothing() = this.defaultType.isNothing()
|
internal fun ClassDescriptor.isNothing() = this.defaultType.isNothing()
|
||||||
@@ -158,20 +126,6 @@ internal fun DeclarationDescriptor.allContainingDeclarations(): List<Declaration
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is possible to declare "external inline fun",
|
|
||||||
// but it doesn't have much sense for native,
|
|
||||||
// since externals don't have IR bodies.
|
|
||||||
// Enforce inlining of constructors annotated with @InlineConstructor.
|
|
||||||
|
|
||||||
private val inlineConstructor = FqName("kotlin.native.internal.InlineConstructor")
|
|
||||||
|
|
||||||
internal val FunctionDescriptor.needsInlining: Boolean
|
|
||||||
get() {
|
|
||||||
val inlineConstructor = annotations.hasAnnotation(inlineConstructor)
|
|
||||||
if (inlineConstructor) return true
|
|
||||||
return (this.isInline && !this.isExternal)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun AnnotationDescriptor.getStringValueOrNull(name: String): String? {
|
fun AnnotationDescriptor.getStringValueOrNull(name: String): String? {
|
||||||
val constantValue = this.allValueArguments.entries.atMostOne {
|
val constantValue = this.allValueArguments.entries.atMostOne {
|
||||||
it.key.asString() == name
|
it.key.asString() == name
|
||||||
|
|||||||
-9
@@ -173,12 +173,3 @@ val IrDeclaration.isGetter get() = this is IrSimpleFunction && this == this.corr
|
|||||||
val IrDeclaration.isSetter get() = this is IrSimpleFunction && this == this.correspondingProperty?.setter
|
val IrDeclaration.isSetter get() = this is IrSimpleFunction && this == this.correspondingProperty?.setter
|
||||||
|
|
||||||
val IrDeclaration.isAccessor get() = this.isGetter || this.isSetter
|
val IrDeclaration.isAccessor get() = this.isGetter || this.isSetter
|
||||||
|
|
||||||
val IrDeclaration.file: IrFile get() = parent.let {
|
|
||||||
when (it) {
|
|
||||||
is IrFile -> it
|
|
||||||
is IrPackageFragment -> TODO("Unknown file")
|
|
||||||
is IrDeclaration -> it.file
|
|
||||||
else -> TODO("Unexpected declaration parent")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+54
-49
@@ -7,26 +7,17 @@ package org.jetbrains.kotlin.backend.konan.lower
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
import org.jetbrains.kotlin.backend.common.ScopeWithIr
|
import org.jetbrains.kotlin.backend.common.ScopeWithIr
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
|
||||||
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.isBuiltInIntercepted
|
||||||
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
|
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
|
||||||
import org.jetbrains.kotlin.backend.common.lower.CoroutineIntrinsicLambdaOrigin
|
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.needsInlining
|
|
||||||
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.*
|
||||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.file
|
|
||||||
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.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
|
||||||
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.irCall
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
import org.jetbrains.kotlin.ir.builders.irGet
|
||||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
import org.jetbrains.kotlin.ir.builders.irReturn
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
@@ -37,12 +28,11 @@ 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.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
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.util.OperatorNameConventions
|
||||||
|
|
||||||
internal class FunctionInlining(val context: Context) : IrElementTransformerVoidWithContext() {
|
internal class FunctionInlining(val context: Context) : IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
@@ -50,7 +40,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
val callSite = super.visitCall(expression) as IrCall
|
val callSite = super.visitCall(expression) as IrCall
|
||||||
if (!callSite.descriptor.needsInlining)
|
if (!callSite.symbol.owner.needsInlining)
|
||||||
return callSite
|
return callSite
|
||||||
if (callSite.symbol == context.ir.symbols.lateinitIsInitializedPropertyGetter)
|
if (callSite.symbol == context.ir.symbols.lateinitIsInitializedPropertyGetter)
|
||||||
return callSite
|
return callSite
|
||||||
@@ -83,7 +73,10 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 IrFunction.isInlineConstructor get() = annotations.hasAnnotation(inlineConstructor)
|
||||||
|
|
||||||
|
private val IrFunction.needsInlining get() = isInlineConstructor || (this.isInline && !this.isExternal)
|
||||||
|
|
||||||
private inner class Inliner(val callSite: IrCall,
|
private inner class Inliner(val callSite: IrCall,
|
||||||
val callee: IrFunction,
|
val callee: IrFunction,
|
||||||
@@ -103,7 +96,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
DeepCopyIrTreeWithSymbolsForInliner(context, typeArguments, parent)
|
DeepCopyIrTreeWithSymbolsForInliner(context, typeArguments, parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
val substituteMap = mutableMapOf<ValueDescriptor, IrExpression>()
|
val substituteMap = mutableMapOf<IrValueParameter, IrExpression>()
|
||||||
|
|
||||||
fun inline() = inlineFunction(callSite, callee)
|
fun inline() = inlineFunction(callSite, callee)
|
||||||
|
|
||||||
@@ -125,26 +118,35 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
val statements = (copiedCallee.body as IrBlockBody).statements
|
val statements = (copiedCallee.body as IrBlockBody).statements
|
||||||
|
|
||||||
val irReturnableBlockSymbol = IrReturnableBlockSymbolImpl(copiedCallee.descriptor.original)
|
val irReturnableBlockSymbol = IrReturnableBlockSymbolImpl(copiedCallee.descriptor.original)
|
||||||
val descriptor = callee.descriptor.original
|
|
||||||
val startOffset = callee.startOffset
|
val startOffset = callee.startOffset
|
||||||
val endOffset = callee.endOffset
|
val endOffset = callee.endOffset
|
||||||
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
|
||||||
|
|
||||||
if (descriptor.isInlineConstructor) {
|
if (callee.isInlineConstructor) {
|
||||||
// Copier sets parent to be the current function but
|
// Copier sets parent to be the current function but
|
||||||
// constructor's parent cannot be a function.
|
// constructor's parent cannot be a function.
|
||||||
copiedCallee.parent = callee.parent
|
val constructedClass = callee.parentAsClass
|
||||||
|
copiedCallee.parent = constructedClass
|
||||||
val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall
|
val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall
|
||||||
irBuilder.run {
|
irBuilder.run {
|
||||||
val constructorDescriptor = delegatingConstructorCall.descriptor.original
|
val constructorCall = IrCallImpl(
|
||||||
val constructorCall = irCall(delegatingConstructorCall.symbol, callSite.type,
|
startOffset, endOffset,
|
||||||
constructorDescriptor.typeParameters.map { delegatingConstructorCall.getTypeArgument(it)!! }).apply {
|
callSite.type,
|
||||||
constructorDescriptor.valueParameters.forEach { putValueArgument(it, delegatingConstructorCall.getValueArgument(it)) }
|
delegatingConstructorCall.symbol, delegatingConstructorCall.descriptor,
|
||||||
|
constructedClass.typeParameters.size,
|
||||||
|
delegatingConstructorCall.symbol.owner.valueParameters.size
|
||||||
|
).apply {
|
||||||
|
delegatingConstructorCall.symbol.owner.valueParameters.forEach {
|
||||||
|
putValueArgument(it.index, delegatingConstructorCall.getValueArgument(it.index))
|
||||||
|
}
|
||||||
|
constructedClass.typeParameters.forEach {
|
||||||
|
putTypeArgument(it.index, delegatingConstructorCall.getTypeArgument(it.index))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val oldThis = (callee as IrConstructor).constructedClass.thisReceiver!!.descriptor
|
val oldThis = constructedClass.thisReceiver!!
|
||||||
val newThis = currentScope.scope.createTemporaryVariableWithWrappedDescriptor(
|
val newThis = currentScope.scope.createTemporaryVariableWithWrappedDescriptor(
|
||||||
irExpression = constructorCall,
|
irExpression = constructorCall,
|
||||||
nameHint = delegatingConstructorCall.descriptor.fqNameSafe.toString() + ".this"
|
nameHint = constructedClass.fqNameSafe.toString() + ".this"
|
||||||
)
|
)
|
||||||
statements[0] = newThis
|
statements[0] = newThis
|
||||||
substituteMap[oldThis] = irGet(newThis)
|
substituteMap[oldThis] = irGet(newThis)
|
||||||
@@ -188,8 +190,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
|
|
||||||
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 argument = substituteMap[newExpression.symbol.owner] ?: return newExpression
|
||||||
val argument = substituteMap[descriptor] ?: 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
|
||||||
@@ -202,15 +203,14 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
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] ?: return super.visitCall(expression)
|
val functionArgument = substituteMap[dispatchReceiver.symbol.owner] ?: return super.visitCall(expression)
|
||||||
val dispatchDescriptor = dispatchReceiver.descriptor
|
if ((dispatchReceiver.symbol.owner as? IrValueParameter)?.isNoinline == true)
|
||||||
if (dispatchDescriptor is ValueParameterDescriptor && dispatchDescriptor.isNoinline)
|
|
||||||
return super.visitCall(expression)
|
return super.visitCall(expression)
|
||||||
|
|
||||||
if (functionArgument is IrFunctionReference) {
|
if (functionArgument is IrFunctionReference) {
|
||||||
val functionDescriptor = functionArgument.descriptor
|
val function = functionArgument.symbol.owner
|
||||||
val functionParameters = functionDescriptor.explicitParameters
|
val functionParameters = function.explicitParameters
|
||||||
val boundFunctionParameters = functionArgument.getArguments()
|
val boundFunctionParameters = functionArgument.getArgumentsWithIr()
|
||||||
val unboundFunctionParameters = functionParameters - boundFunctionParameters.map { it.first }
|
val unboundFunctionParameters = functionParameters - boundFunctionParameters.map { it.first }
|
||||||
val boundFunctionParametersMap = boundFunctionParameters.associate { it.first to it.second }
|
val boundFunctionParametersMap = boundFunctionParameters.associate { it.first to it.second }
|
||||||
|
|
||||||
@@ -219,11 +219,10 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
val valueParameters = expression.getArguments().drop(1) // Skip dispatch receiver.
|
val valueParameters = expression.getArguments().drop(1) // Skip dispatch receiver.
|
||||||
|
|
||||||
val immediateCall = IrCallImpl(
|
val immediateCall = IrCallImpl(
|
||||||
startOffset = expression.startOffset,
|
expression.startOffset, expression.endOffset,
|
||||||
endOffset = expression.endOffset,
|
expression.type,
|
||||||
type = expression.type,
|
functionArgument.symbol, functionArgument.descriptor
|
||||||
symbol = functionArgument.symbol,
|
).apply {
|
||||||
descriptor = functionArgument.descriptor).apply {
|
|
||||||
functionParameters.forEach {
|
functionParameters.forEach {
|
||||||
val argument =
|
val argument =
|
||||||
if (!unboundArgsSet.contains(it))
|
if (!unboundArgsSet.contains(it))
|
||||||
@@ -231,9 +230,9 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
else
|
else
|
||||||
valueParameters[unboundIndex++].second
|
valueParameters[unboundIndex++].second
|
||||||
when (it) {
|
when (it) {
|
||||||
functionDescriptor.dispatchReceiverParameter -> this.dispatchReceiver = argument
|
function.dispatchReceiverParameter -> this.dispatchReceiver = argument
|
||||||
functionDescriptor.extensionReceiverParameter -> this.extensionReceiver = argument
|
function.extensionReceiverParameter -> this.extensionReceiver = argument
|
||||||
else -> putValueArgument((it as ValueParameterDescriptor).index, argument)
|
else -> putValueArgument(it.index, argument)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(unboundIndex == valueParameters.size) { "Not all arguments of <invoke> are used" }
|
assert(unboundIndex == valueParameters.size) { "Not all arguments of <invoke> are used" }
|
||||||
@@ -255,7 +254,15 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
override fun visitElement(element: IrElement) = element.accept(this, null)
|
override fun visitElement(element: IrElement) = element.accept(this, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isLambdaCall(irCall: IrCall) = irCall.descriptor.isFunctionInvoke && irCall.dispatchReceiver is IrGetValue
|
private fun isLambdaCall(irCall: IrCall): Boolean {
|
||||||
|
val callee = irCall.symbol.owner
|
||||||
|
val dispatchReceiver = callee.dispatchReceiverParameter ?: return false
|
||||||
|
assert(!dispatchReceiver.type.isKFunction())
|
||||||
|
|
||||||
|
return (dispatchReceiver.type.isFunction() || dispatchReceiver.type.isSuspendFunction())
|
||||||
|
&& callee.name == OperatorNameConventions.INVOKE
|
||||||
|
&& irCall.dispatchReceiver is IrGetValue
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
@@ -299,7 +306,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
)
|
)
|
||||||
|
|
||||||
val valueArguments =
|
val valueArguments =
|
||||||
callSite.descriptor.valueParameters.map { callSite.getValueArgument(it) }.toMutableList()
|
callSite.symbol.owner.valueParameters.map { callSite.getValueArgument(it.index) }.toMutableList()
|
||||||
|
|
||||||
if (callee.extensionReceiverParameter != null) {
|
if (callee.extensionReceiverParameter != null) {
|
||||||
parameterToArgument += ParameterToArgument(
|
parameterToArgument += ParameterToArgument(
|
||||||
@@ -368,26 +375,24 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
val evaluationStatements = mutableListOf<IrStatement>()
|
val evaluationStatements = mutableListOf<IrStatement>()
|
||||||
val substitutor = ParameterSubstitutor()
|
val substitutor = ParameterSubstitutor()
|
||||||
parameterToArgumentOld.forEach {
|
parameterToArgumentOld.forEach {
|
||||||
val parameterDescriptor = it.parameter.descriptor
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to create temporary variable for each argument except inlinable lambda arguments.
|
* We need to create temporary variable for each argument except inlinable lambda arguments.
|
||||||
* For simplicity and to produce simpler IR we don't create temporaries for every immutable variable,
|
* For simplicity and to produce simpler IR we don't create temporaries for every immutable variable,
|
||||||
* not only for those referring to inlinable lambdas.
|
* not only for those referring to inlinable lambdas.
|
||||||
*/
|
*/
|
||||||
if (it.isInlinableLambdaArgument) {
|
if (it.isInlinableLambdaArgument) {
|
||||||
substituteMap[parameterDescriptor] = it.argumentExpression
|
substituteMap[it.parameter] = it.argumentExpression
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.isImmutableVariableLoad) {
|
if (it.isImmutableVariableLoad) {
|
||||||
substituteMap[parameterDescriptor] = it.argumentExpression.transform(substitutor, data = null) // Arguments may reference the previous ones - substitute them.
|
substituteMap[it.parameter] = it.argumentExpression.transform(substitutor, data = null) // Arguments may reference the previous ones - substitute them.
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
val newVariable = currentScope.scope.createTemporaryVariableWithWrappedDescriptor( // Create new variable and init it with the parameter expression.
|
val newVariable = currentScope.scope.createTemporaryVariableWithWrappedDescriptor( // Create new variable and init it with the parameter expression.
|
||||||
irExpression = it.argumentExpression.transform(substitutor, data = null), // Arguments may reference the previous ones - substitute them.
|
irExpression = it.argumentExpression.transform(substitutor, data = null), // Arguments may reference the previous ones - substitute them.
|
||||||
nameHint = callee.descriptor.name.toString(),
|
nameHint = callee.symbol.owner.name.toString(),
|
||||||
isMutable = false)
|
isMutable = false)
|
||||||
|
|
||||||
evaluationStatements.add(newVariable)
|
evaluationStatements.add(newVariable)
|
||||||
@@ -397,7 +402,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
|||||||
type = newVariable.type,
|
type = newVariable.type,
|
||||||
symbol = newVariable.symbol
|
symbol = newVariable.symbol
|
||||||
)
|
)
|
||||||
substituteMap[parameterDescriptor] = getVal
|
substituteMap[it.parameter] = getVal
|
||||||
}
|
}
|
||||||
return evaluationStatements
|
return evaluationStatements
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user