Extract simple inlining utility from ArrayConstructorLowering
This commit is contained in:
committed by
max-kammerer
parent
d11344ce2e
commit
7b2edc6de8
+51
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.common.ir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.isVararg
|
||||||
|
import org.jetbrains.kotlin.ir.util.statements
|
||||||
|
|
||||||
|
// Return the underlying function for a lambda argument without bound or default parameters or varargs.
|
||||||
|
fun IrExpression.asSimpleLambda(): IrSimpleFunction? {
|
||||||
|
// A lambda is represented as a block with a function declaration and a reference to it.
|
||||||
|
if (this !is IrBlock || statements.size != 2)
|
||||||
|
return null
|
||||||
|
val (function, reference) = statements
|
||||||
|
if (function !is IrSimpleFunction || reference !is IrFunctionReference || function.symbol != reference.symbol)
|
||||||
|
return null
|
||||||
|
if ((0 until reference.valueArgumentsCount).any { reference.getValueArgument(it) != null })
|
||||||
|
return null
|
||||||
|
if (function.valueParameters.any { it.isVararg || it.defaultValue != null })
|
||||||
|
return null
|
||||||
|
return function
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO use a generic inliner (e.g. JS/Native's FunctionInlining.Inliner)
|
||||||
|
// Inline simple function calls without type parameters, default parameters, or varargs.
|
||||||
|
fun IrFunction.inline(arguments: List<IrValueDeclaration> = listOf()): IrReturnableBlock {
|
||||||
|
require(body != null)
|
||||||
|
val argumentMap = valueParameters.zip(arguments).toMap()
|
||||||
|
val blockSymbol = IrReturnableBlockSymbolImpl(descriptor)
|
||||||
|
val block = IrReturnableBlockImpl(startOffset, endOffset, returnType, blockSymbol, null, symbol)
|
||||||
|
val remapper = object : VariableRemapper(argumentMap) {
|
||||||
|
override fun visitReturn(expression: IrReturn): IrExpression = super.visitReturn(
|
||||||
|
if (expression.returnTargetSymbol == symbol)
|
||||||
|
IrReturnImpl(expression.startOffset, expression.endOffset, expression.type, blockSymbol, expression.value)
|
||||||
|
else
|
||||||
|
expression
|
||||||
|
)
|
||||||
|
}
|
||||||
|
body!!.statements.mapTo(block.statements) { it.transform(remapper, null) }
|
||||||
|
return block
|
||||||
|
}
|
||||||
+14
-37
@@ -8,16 +8,22 @@ package org.jetbrains.kotlin.backend.common.lower
|
|||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.asSimpleLambda
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.inline
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
|
||||||
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.types.getClass
|
import org.jetbrains.kotlin.ir.types.getClass
|
||||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.constructedClass
|
||||||
|
import org.jetbrains.kotlin.ir.util.constructors
|
||||||
|
import org.jetbrains.kotlin.ir.util.functions
|
||||||
|
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
@@ -38,15 +44,10 @@ class ArrayConstructorLowering(val context: CommonBackendContext) : IrElementTra
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrExpression.asSingleArgumentLambda(): IrSimpleFunction? {
|
private fun IrExpression.asSingleArgumentLambda(): IrSimpleFunction? {
|
||||||
// A lambda is represented as a block with a function declaration and a reference to it.
|
val function = asSimpleLambda() ?: return null
|
||||||
if (this !is IrBlock || statements.size != 2)
|
|
||||||
return null
|
|
||||||
val (function, reference) = statements
|
|
||||||
if (function !is IrSimpleFunction || reference !is IrFunctionReference || function.symbol != reference.symbol)
|
|
||||||
return null
|
|
||||||
// Only match the one that has exactly one non-vararg argument, as the code below
|
// Only match the one that has exactly one non-vararg argument, as the code below
|
||||||
// does not handle defaults or varargs.
|
// does not handle defaults or varargs.
|
||||||
if (function.valueParameters.size != 1 || function.valueParameters[0].isVararg || reference.getValueArgument(0) != null)
|
if (function.valueParameters.size != 1)
|
||||||
return null
|
return null
|
||||||
return function
|
return function
|
||||||
}
|
}
|
||||||
@@ -105,28 +106,4 @@ class ArrayConstructorLowering(val context: CommonBackendContext) : IrElementTra
|
|||||||
it.patchDeclarationParents(scope.getLocalDeclarationParent())
|
it.patchDeclarationParents(scope.getLocalDeclarationParent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO use a generic inliner (e.g. JS/Native's FunctionInlining.Inliner)
|
|
||||||
private fun IrFunction.inline(arguments: List<IrValueDeclaration>): IrReturnableBlock {
|
|
||||||
val argumentMap = valueParameters.zip(arguments).toMap()
|
|
||||||
val blockSymbol = IrReturnableBlockSymbolImpl(descriptor)
|
|
||||||
val block = IrReturnableBlockImpl(startOffset, endOffset, returnType, blockSymbol, null, symbol)
|
|
||||||
val remapper = object : AbstractVariableRemapper() {
|
|
||||||
override fun remapVariable(value: IrValueDeclaration): IrValueDeclaration? =
|
|
||||||
argumentMap[value]
|
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn): IrExpression = super.visitReturn(
|
|
||||||
if (expression.returnTargetSymbol == symbol)
|
|
||||||
IrReturnImpl(expression.startOffset, expression.endOffset, expression.type, blockSymbol, expression.value)
|
|
||||||
else
|
|
||||||
expression
|
|
||||||
)
|
|
||||||
}
|
|
||||||
when (val transformed = body?.transform(remapper, null)) {
|
|
||||||
is IrBlockBody -> block.statements += transformed.statements
|
|
||||||
is IrExpressionBody -> block.statements += transformed.expression
|
|
||||||
else -> throw AssertionError("unexpected body type: $this")
|
|
||||||
}
|
|
||||||
return block
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -61,7 +61,7 @@ abstract class AbstractVariableRemapper : IrElementTransformerVoid() {
|
|||||||
} ?: expression
|
} ?: expression
|
||||||
}
|
}
|
||||||
|
|
||||||
class VariableRemapper(val mapping: Map<IrValueParameter, IrValueParameter>) : AbstractVariableRemapper() {
|
open class VariableRemapper(val mapping: Map<IrValueParameter, IrValueDeclaration>) : AbstractVariableRemapper() {
|
||||||
override fun remapVariable(value: IrValueDeclaration): IrValueDeclaration? =
|
override fun remapVariable(value: IrValueDeclaration): IrValueDeclaration? =
|
||||||
mapping[value]
|
mapping[value]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,8 +203,8 @@ val IrBody.statements: List<IrStatement>
|
|||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
is IrBlockBody -> statements
|
is IrBlockBody -> statements
|
||||||
is IrExpressionBody -> listOf(expression)
|
is IrExpressionBody -> listOf(expression)
|
||||||
is IrSyntheticBody -> error("Synthetic body contains no statements $this")
|
is IrSyntheticBody -> error("Synthetic body contains no statements: $this")
|
||||||
else -> error("Unknown subclass of IrBody")
|
else -> error("Unknown subclass of IrBody: $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
val IrClass.defaultType: IrSimpleType
|
val IrClass.defaultType: IrSimpleType
|
||||||
|
|||||||
Reference in New Issue
Block a user