Inliner: fixed bug with default lambda arguments
This commit is contained in:
+32
-38
@@ -18,10 +18,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.lower
|
package org.jetbrains.kotlin.backend.konan.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.DeepCopyIrTreeWithDescriptors
|
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.reportWarning
|
|
||||||
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
|
||||||
@@ -193,21 +190,6 @@ private class Inliner(val currentScope: ScopeWithIr, val context: Context) {
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun isLambdaExpression(expression: IrExpression) : Boolean {
|
|
||||||
if (expression !is IrBlock) return false // Lambda mast be represented with IrBlock.
|
|
||||||
if (expression.origin != IrStatementOrigin.LAMBDA && // Origin mast be LAMBDA or ANONYMOUS.
|
|
||||||
expression.origin != IrStatementOrigin.ANONYMOUS_FUNCTION) return false
|
|
||||||
|
|
||||||
val statements = expression.statements
|
|
||||||
val irFunction = statements[0]
|
|
||||||
val irCallableReference = statements[1]
|
|
||||||
if (irFunction !is IrFunction) return false // First statement of the block must be lambda declaration.
|
|
||||||
if (irCallableReference !is IrCallableReference) return false // Second statement of the block must be CallableReference.
|
|
||||||
return true // The expression represents lambda.
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
private fun getLambdaFunction(lambdaArgument: IrBlock): IrFunction {
|
private fun getLambdaFunction(lambdaArgument: IrBlock): IrFunction {
|
||||||
val statements = lambdaArgument.statements
|
val statements = lambdaArgument.statements
|
||||||
return statements[0] as IrFunction
|
return statements[0] as IrFunction
|
||||||
@@ -215,16 +197,6 @@ private class Inliner(val currentScope: ScopeWithIr, val context: Context) {
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun argumentNeedsEvaluation(expression: IrExpression): Boolean {
|
|
||||||
if (expression is IrGetValue) return false // Parameter is already GetValue - nothing to evaluate.
|
|
||||||
if (expression is IrConst<*>) return false // Parameter is constant - nothing to evaluate.
|
|
||||||
if (expression is IrCallableReference) return false // Parameter is callable reference - nothing to evaluate.
|
|
||||||
if (isLambdaExpression(expression)) return false // Parameter is lambda - will be inlined.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
private fun createTypeSubstitutor(irCall: IrCall): TypeSubstitutor? {
|
private fun createTypeSubstitutor(irCall: IrCall): TypeSubstitutor? {
|
||||||
|
|
||||||
val typeArgumentsMap = (irCall as IrMemberAccessExpressionBase).typeArguments
|
val typeArgumentsMap = (irCall as IrMemberAccessExpressionBase).typeArguments
|
||||||
@@ -238,10 +210,32 @@ private class Inliner(val currentScope: ScopeWithIr, val context: Context) {
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private class ParameterToArgument(
|
private class ParameterToArgument(val parameterDescriptor: ValueDescriptor,
|
||||||
val parameterDescriptor: ValueDescriptor,
|
val argumentExpression : IrExpression) {
|
||||||
val argumentExpression : IrExpression
|
val needsEvaluation: Boolean
|
||||||
)
|
get() {
|
||||||
|
if (argumentExpression is IrGetValue) return false // Parameter is already GetValue - nothing to evaluate.
|
||||||
|
if (argumentExpression is IrConst<*>) return false // Parameter is constant - nothing to evaluate.
|
||||||
|
if (argumentExpression is IrCallableReference) return false // Parameter is callable reference - nothing to evaluate.
|
||||||
|
if (isLambdaExpression(argumentExpression)
|
||||||
|
&& !(parameterDescriptor is ValueParameterDescriptor
|
||||||
|
&& parameterDescriptor.isNoinline)) return false // Parameter is lambda and it is not noInline - will be inlined.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isLambdaExpression(expression: IrExpression) : Boolean {
|
||||||
|
if (expression !is IrBlock) return false // Lambda mast be represented with IrBlock.
|
||||||
|
if (expression.origin != IrStatementOrigin.LAMBDA // Origin mast be LAMBDA or ANONYMOUS.
|
||||||
|
&& expression.origin != IrStatementOrigin.ANONYMOUS_FUNCTION) return false
|
||||||
|
|
||||||
|
val statements = expression.statements
|
||||||
|
val irFunction = statements[0]
|
||||||
|
val irCallableReference = statements[1]
|
||||||
|
if (irFunction !is IrFunction) return false // First statement of the block must be lambda declaration.
|
||||||
|
if (irCallableReference !is IrCallableReference) return false // Second statement of the block must be CallableReference.
|
||||||
|
return true // The expression represents lambda.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
@@ -330,16 +324,16 @@ private class Inliner(val currentScope: ScopeWithIr, val context: Context) {
|
|||||||
val evaluationStatements = mutableListOf<IrStatement>() // List of evaluation statements.
|
val evaluationStatements = mutableListOf<IrStatement>() // List of evaluation statements.
|
||||||
parameterToArgumentOld.forEach {
|
parameterToArgumentOld.forEach {
|
||||||
val parameterDescriptor = it.parameterDescriptor
|
val parameterDescriptor = it.parameterDescriptor
|
||||||
val argumentExpression = it.argumentExpression
|
|
||||||
|
|
||||||
if (!argumentNeedsEvaluation(argumentExpression)) { // If argument does not need evaluation
|
if (!it.needsEvaluation) { // If argument does not need evaluation
|
||||||
substituteMap[parameterDescriptor] = argumentExpression // Copy parameterDescriptor -> argumentExpression to new map.
|
substituteMap[parameterDescriptor] = it.argumentExpression // Copy parameterDescriptor -> argumentExpression to new map.
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
val newExpression = copyIrElement.copy(argumentExpression, null) as IrExpression
|
|
||||||
val newVariable = currentScope.scope.createTemporaryVariable( // Create new variable and init it with the parameter expression.
|
val newVariable = currentScope.scope.createTemporaryVariable( // Create new variable and init it with the parameter expression.
|
||||||
irExpression = newExpression,
|
irExpression = copyIrElement
|
||||||
|
.copy(it.argumentExpression, typeSubstitutor = null) // Clone expression.
|
||||||
|
.transform(ParameterSubstitutor(), data = null) as IrExpression, // Arguments may reference the previous ones - substitute them.
|
||||||
nameHint = functionDeclaration.descriptor.name.toString(),
|
nameHint = functionDeclaration.descriptor.name.toString(),
|
||||||
isMutable = false)
|
isMutable = false)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user