JVM_IR: copy code from JvmDefaultParameterInjector to JvmTailrecLowering
Some weird edge case for inline classes wrapping primitives?
This commit is contained in:
+20
-32
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.transformStatement
|
import org.jetbrains.kotlin.ir.transformStatement
|
||||||
import org.jetbrains.kotlin.ir.types.makeNullable
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.util.explicitParameters
|
import org.jetbrains.kotlin.ir.util.explicitParameters
|
||||||
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
|
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
|
||||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||||
@@ -45,7 +45,6 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|||||||
open class TailrecLowering(val context: BackendContext) : BodyLoweringPass {
|
open class TailrecLowering(val context: BackendContext) : BodyLoweringPass {
|
||||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||||
if (container is IrFunction) {
|
if (container is IrFunction) {
|
||||||
// TODO Shouldn't this be done after local declarations lowering?
|
|
||||||
// Lower local declarations
|
// Lower local declarations
|
||||||
irBody.acceptChildrenVoid(object : IrElementVisitorVoid {
|
irBody.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) {
|
||||||
@@ -62,26 +61,22 @@ open class TailrecLowering(val context: BackendContext) : BodyLoweringPass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lowerTailRecursionCalls(function: IrFunction) =
|
open val useProperComputationOrderOfTailrecDefaultParameters: Boolean
|
||||||
lowerTailRecursionCalls(context, function, useProperComputationOrderOfTailrecDefaultParameters(), ::followFunctionReference)
|
get() = true
|
||||||
|
|
||||||
open fun useProperComputationOrderOfTailrecDefaultParameters() = true
|
|
||||||
|
|
||||||
open fun followFunctionReference(reference: IrFunctionReference): Boolean = false
|
open fun followFunctionReference(reference: IrFunctionReference): Boolean = false
|
||||||
|
|
||||||
|
open fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression =
|
||||||
|
IrConstImpl.defaultValueForType(startOffset, endOffset, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lowerTailRecursionCalls(
|
private fun TailrecLowering.lowerTailRecursionCalls(irFunction: IrFunction) {
|
||||||
context: BackendContext,
|
val tailRecursionCalls = collectTailRecursionCalls(irFunction, ::followFunctionReference)
|
||||||
irFunction: IrFunction,
|
|
||||||
properComputationOrderOfTailrecDefaultParameters: Boolean,
|
|
||||||
followFunctionReference: (IrFunctionReference) -> Boolean
|
|
||||||
) {
|
|
||||||
val tailRecursionCalls = collectTailRecursionCalls(irFunction, followFunctionReference)
|
|
||||||
if (tailRecursionCalls.isEmpty()) {
|
if (tailRecursionCalls.isEmpty()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val oldBody = irFunction.body as IrBlockBody
|
val oldBody = irFunction.body as? IrBlockBody ?: return
|
||||||
val oldBodyStatements = ArrayList(oldBody.statements)
|
val oldBodyStatements = ArrayList(oldBody.statements)
|
||||||
val builder = context.createIrBuilder(irFunction.symbol).at(oldBody)
|
val builder = context.createIrBuilder(irFunction.symbol).at(oldBody)
|
||||||
|
|
||||||
@@ -104,14 +99,9 @@ private fun lowerTailRecursionCalls(
|
|||||||
val parameterToNew = parameters.associateWith {
|
val parameterToNew = parameters.associateWith {
|
||||||
createTmpVariable(irGet(parameterToVariable[it]!!), nameHint = it.symbol.suggestVariableName())
|
createTmpVariable(irGet(parameterToVariable[it]!!), nameHint = it.symbol.suggestVariableName())
|
||||||
}
|
}
|
||||||
|
|
||||||
val transformer = BodyTransformer(
|
val transformer = BodyTransformer(
|
||||||
builder, irFunction, loop,
|
this@lowerTailRecursionCalls, builder, irFunction, loop, parameterToNew, parameterToVariable, tailRecursionCalls
|
||||||
parameterToNew, parameterToVariable, tailRecursionCalls,
|
|
||||||
properComputationOrderOfTailrecDefaultParameters,
|
|
||||||
followFunctionReference
|
|
||||||
)
|
)
|
||||||
|
|
||||||
oldBodyStatements.forEach {
|
oldBodyStatements.forEach {
|
||||||
+it.transformStatement(transformer)
|
+it.transformStatement(transformer)
|
||||||
}
|
}
|
||||||
@@ -123,14 +113,13 @@ private fun lowerTailRecursionCalls(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class BodyTransformer(
|
private class BodyTransformer(
|
||||||
val builder: IrBuilderWithScope,
|
private val lowering: TailrecLowering,
|
||||||
val irFunction: IrFunction,
|
private val builder: IrBuilderWithScope,
|
||||||
val loop: IrLoop,
|
irFunction: IrFunction,
|
||||||
val parameterToNew: Map<IrValueParameter, IrValueDeclaration>,
|
private val loop: IrLoop,
|
||||||
val parameterToVariable: Map<IrValueParameter, IrVariable>,
|
parameterToNew: Map<IrValueParameter, IrValueDeclaration>,
|
||||||
val tailRecursionCalls: Set<IrCall>,
|
private val parameterToVariable: Map<IrValueParameter, IrVariable>,
|
||||||
val properComputationOrderOfTailrecDefaultParameters: Boolean,
|
private val tailRecursionCalls: Set<IrCall>,
|
||||||
val followFunctionReference: (IrFunctionReference) -> Boolean
|
|
||||||
) : VariableRemapper(parameterToNew) {
|
) : VariableRemapper(parameterToNew) {
|
||||||
|
|
||||||
val parameters = irFunction.explicitParameters
|
val parameters = irFunction.explicitParameters
|
||||||
@@ -144,7 +133,7 @@ private class BodyTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||||
if (followFunctionReference(expression)) {
|
if (lowering.followFunctionReference(expression)) {
|
||||||
expression.symbol.owner.body?.transformChildrenVoid(this)
|
expression.symbol.owner.body?.transformChildrenVoid(this)
|
||||||
}
|
}
|
||||||
return super.visitFunctionReference(expression)
|
return super.visitFunctionReference(expression)
|
||||||
@@ -163,13 +152,12 @@ private class BodyTransformer(
|
|||||||
defaultValuedParameters.associateWithTo(parameterToArgument) {
|
defaultValuedParameters.associateWithTo(parameterToArgument) {
|
||||||
// Note that we intentionally keep the original type of the parameter for the variable even though that violates type safety
|
// Note that we intentionally keep the original type of the parameter for the variable even though that violates type safety
|
||||||
// if it's non-null. This ensures that capture parameters have the same types for all copies of `x`.
|
// if it's non-null. This ensures that capture parameters have the same types for all copies of `x`.
|
||||||
// TODO: on the JVM, this might not be correct for inline classes - copy code from JvmDefaultParameterInjector?
|
irTemporary(lowering.nullConst(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type))
|
||||||
irTemporary(IrConstImpl.defaultValueForType(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type.makeNullable()), irType = it.type)
|
|
||||||
}
|
}
|
||||||
// Now replace those variables with ones containing actual default values. Unused null-valued temporaries will hopefully
|
// Now replace those variables with ones containing actual default values. Unused null-valued temporaries will hopefully
|
||||||
// be optimized out later.
|
// be optimized out later.
|
||||||
val remapper = VariableRemapper(parameterToArgument)
|
val remapper = VariableRemapper(parameterToArgument)
|
||||||
defaultValuedParameters.let { if (properComputationOrderOfTailrecDefaultParameters) it else it.asReversed() }
|
defaultValuedParameters.let { if (lowering.useProperComputationOrderOfTailrecDefaultParameters) it else it.asReversed() }
|
||||||
.associateWithTo(parameterToArgument) { parameter ->
|
.associateWithTo(parameterToArgument) { parameter ->
|
||||||
val originalDefaultValue = parameter.defaultValue?.expression ?: throw Error("no argument specified for $parameter")
|
val originalDefaultValue = parameter.defaultValue?.expression ?: throw Error("no argument specified for $parameter")
|
||||||
irTemporary(originalDefaultValue.deepCopyWithVariables().patchDeclarationParents(parent).transform(remapper, null))
|
irTemporary(originalDefaultValue.deepCopyWithVariables().patchDeclarationParents(parent).transform(remapper, null))
|
||||||
|
|||||||
+7
-1
@@ -8,14 +8,20 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
|||||||
import org.jetbrains.kotlin.backend.common.lower.TailrecLowering
|
import org.jetbrains.kotlin.backend.common.lower.TailrecLowering
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.ir.defaultValue
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
|
||||||
class JvmTailrecLowering(context: JvmBackendContext) : TailrecLowering(context) {
|
class JvmTailrecLowering(context: JvmBackendContext) : TailrecLowering(context) {
|
||||||
override fun useProperComputationOrderOfTailrecDefaultParameters(): Boolean =
|
override val useProperComputationOrderOfTailrecDefaultParameters: Boolean =
|
||||||
context.ir.context.configuration.languageVersionSettings.supportsFeature(LanguageFeature.ProperComputationOrderOfTailrecDefaultParameters)
|
context.ir.context.configuration.languageVersionSettings.supportsFeature(LanguageFeature.ProperComputationOrderOfTailrecDefaultParameters)
|
||||||
|
|
||||||
override fun followFunctionReference(reference: IrFunctionReference): Boolean =
|
override fun followFunctionReference(reference: IrFunctionReference): Boolean =
|
||||||
reference.origin == JvmLoweredStatementOrigin.INLINE_LAMBDA
|
reference.origin == JvmLoweredStatementOrigin.INLINE_LAMBDA
|
||||||
|
|
||||||
|
override fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression =
|
||||||
|
type.defaultValue(startOffset, endOffset, context as JvmBackendContext)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user