From 73adcd7b6240d3e751e628f0a6b32bd4c9864b53 Mon Sep 17 00:00:00 2001 From: pyos Date: Tue, 28 Sep 2021 13:23:33 +0200 Subject: [PATCH] JVM_IR: copy code from JvmDefaultParameterInjector to JvmTailrecLowering Some weird edge case for inline classes wrapping primitives? --- .../backend/common/lower/TailrecLowering.kt | 52 +++++++------------ .../backend/jvm/lower/JvmTailrecLowering.kt | 8 ++- 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt index c9cc42f604d..02e56b2065a 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt @@ -28,7 +28,7 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol 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.getArgumentsWithIr 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 { override fun lower(irBody: IrBody, container: IrDeclaration) { if (container is IrFunction) { - // TODO Shouldn't this be done after local declarations lowering? // Lower local declarations irBody.acceptChildrenVoid(object : IrElementVisitorVoid { override fun visitElement(element: IrElement) { @@ -62,26 +61,22 @@ open class TailrecLowering(val context: BackendContext) : BodyLoweringPass { } } - private fun lowerTailRecursionCalls(function: IrFunction) = - lowerTailRecursionCalls(context, function, useProperComputationOrderOfTailrecDefaultParameters(), ::followFunctionReference) - - open fun useProperComputationOrderOfTailrecDefaultParameters() = true + open val useProperComputationOrderOfTailrecDefaultParameters: Boolean + get() = true 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( - context: BackendContext, - irFunction: IrFunction, - properComputationOrderOfTailrecDefaultParameters: Boolean, - followFunctionReference: (IrFunctionReference) -> Boolean -) { - val tailRecursionCalls = collectTailRecursionCalls(irFunction, followFunctionReference) +private fun TailrecLowering.lowerTailRecursionCalls(irFunction: IrFunction) { + val tailRecursionCalls = collectTailRecursionCalls(irFunction, ::followFunctionReference) if (tailRecursionCalls.isEmpty()) { return } - val oldBody = irFunction.body as IrBlockBody + val oldBody = irFunction.body as? IrBlockBody ?: return val oldBodyStatements = ArrayList(oldBody.statements) val builder = context.createIrBuilder(irFunction.symbol).at(oldBody) @@ -104,14 +99,9 @@ private fun lowerTailRecursionCalls( val parameterToNew = parameters.associateWith { createTmpVariable(irGet(parameterToVariable[it]!!), nameHint = it.symbol.suggestVariableName()) } - val transformer = BodyTransformer( - builder, irFunction, loop, - parameterToNew, parameterToVariable, tailRecursionCalls, - properComputationOrderOfTailrecDefaultParameters, - followFunctionReference + this@lowerTailRecursionCalls, builder, irFunction, loop, parameterToNew, parameterToVariable, tailRecursionCalls ) - oldBodyStatements.forEach { +it.transformStatement(transformer) } @@ -123,14 +113,13 @@ private fun lowerTailRecursionCalls( } private class BodyTransformer( - val builder: IrBuilderWithScope, - val irFunction: IrFunction, - val loop: IrLoop, - val parameterToNew: Map, - val parameterToVariable: Map, - val tailRecursionCalls: Set, - val properComputationOrderOfTailrecDefaultParameters: Boolean, - val followFunctionReference: (IrFunctionReference) -> Boolean + private val lowering: TailrecLowering, + private val builder: IrBuilderWithScope, + irFunction: IrFunction, + private val loop: IrLoop, + parameterToNew: Map, + private val parameterToVariable: Map, + private val tailRecursionCalls: Set, ) : VariableRemapper(parameterToNew) { val parameters = irFunction.explicitParameters @@ -144,7 +133,7 @@ private class BodyTransformer( } override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { - if (followFunctionReference(expression)) { + if (lowering.followFunctionReference(expression)) { expression.symbol.owner.body?.transformChildrenVoid(this) } return super.visitFunctionReference(expression) @@ -163,13 +152,12 @@ private class BodyTransformer( defaultValuedParameters.associateWithTo(parameterToArgument) { // 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`. - // TODO: on the JVM, this might not be correct for inline classes - copy code from JvmDefaultParameterInjector? - irTemporary(IrConstImpl.defaultValueForType(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type.makeNullable()), irType = it.type) + irTemporary(lowering.nullConst(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type)) } // Now replace those variables with ones containing actual default values. Unused null-valued temporaries will hopefully // be optimized out later. val remapper = VariableRemapper(parameterToArgument) - defaultValuedParameters.let { if (properComputationOrderOfTailrecDefaultParameters) it else it.asReversed() } + defaultValuedParameters.let { if (lowering.useProperComputationOrderOfTailrecDefaultParameters) it else it.asReversed() } .associateWithTo(parameterToArgument) { parameter -> val originalDefaultValue = parameter.defaultValue?.expression ?: throw Error("no argument specified for $parameter") irTemporary(originalDefaultValue.deepCopyWithVariables().patchDeclarationParents(parent).transform(remapper, null)) diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmTailrecLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmTailrecLowering.kt index 38c4aa9ab8a..0a9874131a5 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmTailrecLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmTailrecLowering.kt @@ -8,14 +8,20 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.lower.TailrecLowering import org.jetbrains.kotlin.backend.jvm.JvmBackendContext 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.languageVersionSettings +import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrFunctionReference +import org.jetbrains.kotlin.ir.types.IrType class JvmTailrecLowering(context: JvmBackendContext) : TailrecLowering(context) { - override fun useProperComputationOrderOfTailrecDefaultParameters(): Boolean = + override val useProperComputationOrderOfTailrecDefaultParameters: Boolean = context.ir.context.configuration.languageVersionSettings.supportsFeature(LanguageFeature.ProperComputationOrderOfTailrecDefaultParameters) override fun followFunctionReference(reference: IrFunctionReference): Boolean = reference.origin == JvmLoweredStatementOrigin.INLINE_LAMBDA + + override fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression = + type.defaultValue(startOffset, endOffset, context as JvmBackendContext) }