[IR] Remove IrExpressionWithCopy and replace with shallowCopy method

This commit is contained in:
Ilya Goncharov
2021-03-29 12:51:27 +03:00
committed by TeamCityServer
parent 084d824984
commit 368ac36204
23 changed files with 126 additions and 128 deletions
@@ -18,10 +18,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildTypeParameter
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.* import org.jetbrains.kotlin.ir.descriptors.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
@@ -696,9 +693,3 @@ fun IrExpression?.isPure(
return false return false
} }
fun IrExpression.isTrivial() =
this is IrConst<*> ||
this is IrGetValue ||
this is IrGetObjectValue ||
this is IrErrorExpressionImpl
@@ -7,8 +7,6 @@ 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.ir.isTrivial
import org.jetbrains.kotlin.backend.common.lower.loops.canHaveSideEffects
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.ir.builders.createTmpVariable import org.jetbrains.kotlin.ir.builders.createTmpVariable
import org.jetbrains.kotlin.ir.builders.irBlock import org.jetbrains.kotlin.ir.builders.irBlock
@@ -16,13 +14,13 @@ import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irIfNull import org.jetbrains.kotlin.ir.builders.irIfNull
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isNullable import org.jetbrains.kotlin.ir.types.isNullable
import org.jetbrains.kotlin.ir.util.fileOrNull import org.jetbrains.kotlin.ir.util.fileOrNull
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.isTrivial
import org.jetbrains.kotlin.ir.util.shallowCopy
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
@@ -195,10 +193,7 @@ class IfNullExpressionsFusionLowering(val context: CommonBackendContext) : FileL
private fun IrExpression.copyIfTrivial() = private fun IrExpression.copyIfTrivial() =
if (isTrivial()) { if (isTrivial()) {
require(this is IrExpressionWithCopy) { shallowCopy()
"Not a copyable expression: ${render()}"
}
copy()
} else this } else this
private fun IrExpression.remap(from: IrVariable, to: Lazy<IrVariable>): IrExpression = private fun IrExpression.remap(from: IrVariable, to: Lazy<IrVariable>): IrExpression =
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.util.shallowCopy
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.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -262,20 +263,20 @@ private class Transformer(
additionalStatements.addIfNotNull(lowerVar) additionalStatements.addIfNotNull(lowerVar)
additionalStatements.addIfNotNull(upperVar) additionalStatements.addIfNotNull(upperVar)
} }
lowerExpression = tmpLowerExpression.copy() lowerExpression = tmpLowerExpression.shallowCopy()
upperExpression = tmpUpperExpression.copy() upperExpression = tmpUpperExpression.shallowCopy()
useLowerClauseOnLeftSide = true useLowerClauseOnLeftSide = true
} else if (lower.canHaveSideEffects && upper.canHaveSideEffects) { } else if (lower.canHaveSideEffects && upper.canHaveSideEffects) {
if (shouldUpperComeFirst) { if (shouldUpperComeFirst) {
val (upperVar, tmpUpperExpression) = createTemporaryVariableIfNecessary(upper, "containsUpper") val (upperVar, tmpUpperExpression) = createTemporaryVariableIfNecessary(upper, "containsUpper")
additionalStatements.add(upperVar!!) additionalStatements.add(upperVar!!)
lowerExpression = lower lowerExpression = lower
upperExpression = tmpUpperExpression.copy() upperExpression = tmpUpperExpression.shallowCopy()
useLowerClauseOnLeftSide = true useLowerClauseOnLeftSide = true
} else { } else {
val (lowerVar, tmpLowerExpression) = createTemporaryVariableIfNecessary(lower, "containsLower") val (lowerVar, tmpLowerExpression) = createTemporaryVariableIfNecessary(lower, "containsLower")
additionalStatements.add(lowerVar!!) additionalStatements.add(lowerVar!!)
lowerExpression = tmpLowerExpression.copy() lowerExpression = tmpLowerExpression.shallowCopy()
upperExpression = upper upperExpression = upper
useLowerClauseOnLeftSide = false useLowerClauseOnLeftSide = false
} }
@@ -311,27 +312,27 @@ private class Transformer(
irCall(lowerCompFun).apply { irCall(lowerCompFun).apply {
putValueArgument(0, irInt(0)) putValueArgument(0, irInt(0))
putValueArgument(1, irCall(compareToFun).apply { putValueArgument(1, irCall(compareToFun).apply {
dispatchReceiver = argExpression.copy() dispatchReceiver = argExpression.shallowCopy()
putValueArgument(0, lowerExpression) putValueArgument(0, lowerExpression)
}) })
} }
} else { } else {
irCall(lowerCompFun).apply { irCall(lowerCompFun).apply {
putValueArgument(0, lowerExpression) putValueArgument(0, lowerExpression)
putValueArgument(1, argExpression.copy()) putValueArgument(1, argExpression.shallowCopy())
} }
} }
val upperClause = if (useCompareTo) { val upperClause = if (useCompareTo) {
irCall(upperCompFun).apply { irCall(upperCompFun).apply {
putValueArgument(0, irCall(compareToFun).apply { putValueArgument(0, irCall(compareToFun).apply {
dispatchReceiver = argExpression.copy() dispatchReceiver = argExpression.shallowCopy()
putValueArgument(0, upperExpression) putValueArgument(0, upperExpression)
}) })
putValueArgument(1, irInt(0)) putValueArgument(1, irInt(0))
} }
} else { } else {
irCall(upperCompFun).apply { irCall(upperCompFun).apply {
putValueArgument(0, argExpression.copy()) putValueArgument(0, argExpression.shallowCopy())
putValueArgument(1, upperExpression) putValueArgument(1, upperExpression)
} }
} }
@@ -592,10 +592,6 @@ class FunctionInlining(
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D) = override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D) =
visitor.visitGetValue(this, data) visitor.visitGetValue(this, data)
override fun copy(): IrGetValue {
TODO("not implemented")
}
fun withLocation(startOffset: Int, endOffset: Int) = fun withLocation(startOffset: Int, endOffset: Int) =
IrGetValueImpl(startOffset, endOffset, type, symbol, origin) IrGetValueImpl(startOffset, endOffset, type, symbol, origin)
} }
@@ -66,13 +66,13 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
val inductionVariable: IrVariable val inductionVariable: IrVariable
protected val stepVariable: IrVariable? protected val stepVariable: IrVariable?
val stepExpression: IrExpressionWithCopy val stepExpression: IrExpression
protected val lastVariableIfCanCacheLast: IrVariable? protected val lastVariableIfCanCacheLast: IrVariable?
protected val lastExpression: IrExpression protected val lastExpression: IrExpression
// If this is not `IrExpressionWithCopy`, then it is `<IrGetValue>.getSize()` built in `IndexedGetIterationHandler`. // If this is not `IrExpressionWithCopy`, then it is `<IrGetValue>.getSize()` built in `IndexedGetIterationHandler`.
// It is therefore safe to deep-copy as it does not contain any functions or classes. // It is therefore safe to deep-copy as it does not contain any functions or classes.
get() = if (field is IrExpressionWithCopy) field.copy() else field.deepCopyWithSymbols() get() = field.shallowCopyOrNull() ?: field.deepCopyWithSymbols()
protected val symbols = context.ir.symbols protected val symbols = context.ir.symbols
@@ -105,7 +105,7 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
if (headerInfo.canCacheLast) { if (headerInfo.canCacheLast) {
val (variable, expression) = createTemporaryVariableIfNecessary(last, nameHint = "last") val (variable, expression) = createTemporaryVariableIfNecessary(last, nameHint = "last")
lastVariableIfCanCacheLast = variable lastVariableIfCanCacheLast = variable
lastExpression = expression.copy() lastExpression = expression.shallowCopy()
} else { } else {
lastVariableIfCanCacheLast = null lastVariableIfCanCacheLast = null
lastExpression = last lastExpression = last
@@ -146,7 +146,7 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
inductionVariable.symbol, irCallOp( inductionVariable.symbol, irCallOp(
plusFun.symbol, plusFun.returnType, plusFun.symbol, plusFun.returnType,
irGet(inductionVariable), irGet(inductionVariable),
stepExpression.copy(), IrStatementOrigin.PLUSEQ stepExpression.shallowCopy(), IrStatementOrigin.PLUSEQ
), IrStatementOrigin.PLUSEQ ), IrStatementOrigin.PLUSEQ
) )
} }
@@ -225,14 +225,14 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
context.oror( context.oror(
context.andand( context.andand(
irCall(builtIns.greaterFunByOperandType.getValue(stepClass.symbol)).apply { irCall(builtIns.greaterFunByOperandType.getValue(stepClass.symbol)).apply {
putValueArgument(0, stepExpression.copy()) putValueArgument(0, stepExpression.shallowCopy())
putValueArgument(1, zeroStepExpression()) putValueArgument(1, zeroStepExpression())
}, },
conditionForIncreasing() conditionForIncreasing()
), ),
context.andand( context.andand(
irCall(builtIns.lessFunByOperandType.getValue(stepClass.symbol)).apply { irCall(builtIns.lessFunByOperandType.getValue(stepClass.symbol)).apply {
putValueArgument(0, stepExpression.copy()) putValueArgument(0, stepExpression.shallowCopy())
putValueArgument(1, zeroStepExpression()) putValueArgument(1, zeroStepExpression())
}, },
conditionForDecreasing() conditionForDecreasing()
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.backend.common.lower.loops package org.jetbrains.kotlin.backend.common.lower.loops
import org.jetbrains.kotlin.backend.common.ir.isTrivial
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.ir.builders.createTmpVariable import org.jetbrains.kotlin.ir.builders.createTmpVariable
import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.builders.irGet
@@ -14,13 +13,12 @@ import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.isNothing import org.jetbrains.kotlin.ir.types.isNothing
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.isTrivial
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -82,9 +80,6 @@ private fun Any?.toLong(): Long? =
else -> null else -> null
} }
internal val IrExpressionWithCopy.constLongValue: Long?
get() = if (this is IrConst<*>) value.toLong() else null
internal val IrExpression.constLongValue: Long? internal val IrExpression.constLongValue: Long?
get() = if (this is IrConst<*>) value.toLong() else null get() = if (this is IrConst<*>) value.toLong() else null
@@ -97,13 +92,10 @@ internal val IrExpression.constLongValue: Long?
internal fun DeclarationIrBuilder.createTemporaryVariableIfNecessary( internal fun DeclarationIrBuilder.createTemporaryVariableIfNecessary(
expression: IrExpression, nameHint: String? = null, expression: IrExpression, nameHint: String? = null,
irType: IrType? = null, isMutable: Boolean = false irType: IrType? = null, isMutable: Boolean = false
): Pair<IrVariable?, IrExpressionWithCopy> = ): Pair<IrVariable?, IrExpression> =
if (expression.canHaveSideEffects) { if (expression.canHaveSideEffects) {
scope.createTmpVariable(expression, nameHint = nameHint, irType = irType, isMutable = isMutable).let { Pair(it, irGet(it)) } scope.createTmpVariable(expression, nameHint = nameHint, irType = irType, isMutable = isMutable).let { Pair(it, irGet(it)) }
} else { } else {
require(expression is IrExpressionWithCopy) {
"Not a copyable expression: ${expression.render()}"
}
Pair(null, expression) Pair(null, expression)
} }
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.getPropertyGetter import org.jetbrains.kotlin.ir.util.getPropertyGetter
import org.jetbrains.kotlin.ir.util.shallowCopy
/** Builds a [HeaderInfo] for progressions not handled by more specialized handlers. */ /** Builds a [HeaderInfo] for progressions not handled by more specialized handlers. */
internal class DefaultProgressionHandler(private val context: CommonBackendContext, private val allowUnsignedBounds: Boolean = false) : internal class DefaultProgressionHandler(private val context: CommonBackendContext, private val allowUnsignedBounds: Boolean = false) :
@@ -35,10 +36,10 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte
val (progressionVar, progressionExpression) = createTemporaryVariableIfNecessary(expression, nameHint = "progression") val (progressionVar, progressionExpression) = createTemporaryVariableIfNecessary(expression, nameHint = "progression")
val progressionClass = expression.type.getClass()!! val progressionClass = expression.type.getClass()!!
val first = irCall(progressionClass.symbol.getPropertyGetter("first")!!).apply { val first = irCall(progressionClass.symbol.getPropertyGetter("first")!!).apply {
dispatchReceiver = progressionExpression.copy() dispatchReceiver = progressionExpression.shallowCopy()
} }
val last = irCall(progressionClass.symbol.getPropertyGetter("last")!!).apply { val last = irCall(progressionClass.symbol.getPropertyGetter("last")!!).apply {
dispatchReceiver = progressionExpression.copy() dispatchReceiver = progressionExpression.shallowCopy()
} }
// *Ranges (e.g., IntRange) have step == 1 and is always increasing. // *Ranges (e.g., IntRange) have step == 1 and is always increasing.
@@ -47,7 +48,7 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte
irInt(1) irInt(1)
} else { } else {
irCall(progressionClass.symbol.getPropertyGetter("step")!!).apply { irCall(progressionClass.symbol.getPropertyGetter("step")!!).apply {
dispatchReceiver = progressionExpression.copy() dispatchReceiver = progressionExpression.shallowCopy()
} }
} }
val direction = if (isRange) ProgressionDirection.INCREASING else ProgressionDirection.UNKNOWN val direction = if (isRange) ProgressionDirection.INCREASING else ProgressionDirection.UNKNOWN
@@ -16,12 +16,12 @@ import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.types.isInt import org.jetbrains.kotlin.ir.types.isInt
import org.jetbrains.kotlin.ir.types.isLong import org.jetbrains.kotlin.ir.types.isLong
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.shallowCopy
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
@@ -79,7 +79,7 @@ internal class StepHandler(
irCall(context.irBuiltIns.illegalArgumentExceptionSymbol).apply { irCall(context.irBuiltIns.illegalArgumentExceptionSymbol).apply {
val exceptionMessage = irConcat() val exceptionMessage = irConcat()
exceptionMessage.addArgument(irString("Step must be positive, was: ")) exceptionMessage.addArgument(irString("Step must be positive, was: "))
exceptionMessage.addArgument(stepArgExpression.copy()) exceptionMessage.addArgument(stepArgExpression.shallowCopy())
exceptionMessage.addArgument(irString(".")) exceptionMessage.addArgument(irString("."))
putValueArgument(0, exceptionMessage) putValueArgument(0, exceptionMessage)
} }
@@ -89,7 +89,7 @@ internal class StepHandler(
stepArgValueAsLong == null -> { stepArgValueAsLong == null -> {
// Step argument is not a constant. In this case, we check if step <= 0. // Step argument is not a constant. In this case, we check if step <= 0.
val stepNonPositiveCheck = irCall(stepCompFun).apply { val stepNonPositiveCheck = irCall(stepCompFun).apply {
putValueArgument(0, stepArgExpression.copy()) putValueArgument(0, stepArgExpression.shallowCopy())
putValueArgument(1, data.run { zeroStepExpression() }) putValueArgument(1, data.run { zeroStepExpression() })
} }
irIfThen( irIfThen(
@@ -118,7 +118,7 @@ internal class StepHandler(
ProgressionDirection.INCREASING -> stepArgExpression ProgressionDirection.INCREASING -> stepArgExpression
ProgressionDirection.DECREASING -> { ProgressionDirection.DECREASING -> {
if (stepArgVar == null) { if (stepArgVar == null) {
stepNegation = scope.createTmpVariable(stepArgExpression.copy().negate()) stepNegation = scope.createTmpVariable(stepArgExpression.shallowCopy().negate())
irGet(stepNegation) irGet(stepNegation)
} else { } else {
// Step is already stored in a variable, just negate it. // Step is already stored in a variable, just negate it.
@@ -133,7 +133,7 @@ internal class StepHandler(
val (tmpNestedStepVar, nestedStepExpression) = createTemporaryVariableIfNecessary(nestedStep, "nestedStep") val (tmpNestedStepVar, nestedStepExpression) = createTemporaryVariableIfNecessary(nestedStep, "nestedStep")
nestedStepVar = tmpNestedStepVar nestedStepVar = tmpNestedStepVar
val nestedStepNonPositiveCheck = irCall(stepCompFun).apply { val nestedStepNonPositiveCheck = irCall(stepCompFun).apply {
putValueArgument(0, nestedStepExpression.copy()) putValueArgument(0, nestedStepExpression.shallowCopy())
putValueArgument(1, data.run { zeroStepExpression() }) putValueArgument(1, data.run { zeroStepExpression() })
} }
if (stepArgVar == null) { if (stepArgVar == null) {
@@ -142,8 +142,8 @@ internal class StepHandler(
irIfThenElse( irIfThenElse(
stepType, stepType,
nestedStepNonPositiveCheck, nestedStepNonPositiveCheck,
stepArgExpression.copy().negate(), stepArgExpression.shallowCopy().negate(),
stepArgExpression.copy() stepArgExpression.shallowCopy()
), ),
nameHint = "maybeNegatedStep" nameHint = "maybeNegatedStep"
) )
@@ -272,9 +272,9 @@ internal class StepHandler(
return ProgressionHeaderInfo( return ProgressionHeaderInfo(
data, data,
first = nestedFirstExpression.copy(), first = nestedFirstExpression.shallowCopy(),
last = recalculatedLast, last = recalculatedLast,
step = finalStepExpression.copy(), step = finalStepExpression.shallowCopy(),
isReversed = nestedInfo.isReversed, isReversed = nestedInfo.isReversed,
additionalStatements = additionalStatements, additionalStatements = additionalStatements,
direction = nestedInfo.direction direction = nestedInfo.direction
@@ -283,13 +283,13 @@ internal class StepHandler(
private fun DeclarationIrBuilder.callGetProgressionLastElementIfNecessary( private fun DeclarationIrBuilder.callGetProgressionLastElementIfNecessary(
progressionType: ProgressionType, progressionType: ProgressionType,
first: IrExpressionWithCopy, first: IrExpression,
last: IrExpressionWithCopy, last: IrExpression,
step: IrExpressionWithCopy step: IrExpression
): IrExpression { ): IrExpression {
// Calling getProgressionLastElement() is not needed if step == 1 or -1; the "last" value is unchanged in such cases. // Calling getProgressionLastElement() is not needed if step == 1 or -1; the "last" value is unchanged in such cases.
if (step.constLongValue?.absoluteValue == 1L) { if (step.constLongValue?.absoluteValue == 1L) {
return last.copy() return last.shallowCopy()
} }
// Call `getProgressionLastElement(first, last, step)`. The following overloads are present in the stdlib: // Call `getProgressionLastElement(first, last, step)`. The following overloads are present in the stdlib:
@@ -304,17 +304,17 @@ internal class StepHandler(
// Bounds are signed for unsigned progressions but `getProgressionLastElement` expects unsigned. // Bounds are signed for unsigned progressions but `getProgressionLastElement` expects unsigned.
// The return value is finally converted back to signed since it will be assigned back to `last`. // The return value is finally converted back to signed since it will be assigned back to `last`.
irCall(getProgressionLastElementFun).apply { irCall(getProgressionLastElementFun).apply {
putValueArgument(0, first.copy().asElementType().asUnsigned()) putValueArgument(0, first.shallowCopy().asElementType().asUnsigned())
putValueArgument(1, last.copy().asElementType().asUnsigned()) putValueArgument(1, last.shallowCopy().asElementType().asUnsigned())
putValueArgument(2, step.copy().asStepType()) putValueArgument(2, step.shallowCopy().asStepType())
}.asSigned() }.asSigned()
} else { } else {
irCall(getProgressionLastElementFun).apply { irCall(getProgressionLastElementFun).apply {
// Step type is used for casting because it works for all signed progressions. In particular, // Step type is used for casting because it works for all signed progressions. In particular,
// getProgressionLastElement(Int, Int, Int) is called for CharProgression, which uses an Int step. // getProgressionLastElement(Int, Int, Int) is called for CharProgression, which uses an Int step.
putValueArgument(0, first.copy().asStepType()) putValueArgument(0, first.shallowCopy().asStepType())
putValueArgument(1, last.copy().asStepType()) putValueArgument(1, last.shallowCopy().asStepType())
putValueArgument(2, step.copy().asStepType()) putValueArgument(2, step.shallowCopy().asStepType())
} }
} }
} }
@@ -6,15 +6,15 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.ir.isPure
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.backend.common.ir.isPure
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
@@ -47,6 +47,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass {
private val isInterfaceSymbol get() = context.intrinsics.isInterfaceSymbol private val isInterfaceSymbol get() = context.intrinsics.isInterfaceSymbol
private val isArraySymbol get() = context.intrinsics.isArraySymbol private val isArraySymbol get() = context.intrinsics.isArraySymbol
private val isSuspendFunctionSymbol = context.intrinsics.isSuspendFunctionSymbol private val isSuspendFunctionSymbol = context.intrinsics.isSuspendFunctionSymbol
// private val isCharSymbol get() = context.intrinsics.isCharSymbol // private val isCharSymbol get() = context.intrinsics.isCharSymbol
private val isObjectSymbol get() = context.intrinsics.isObjectSymbol private val isObjectSymbol get() = context.intrinsics.isObjectSymbol
@@ -269,11 +270,8 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass {
// assert(!typeParameter.isReified) { "reified parameters have to be lowered before" } // assert(!typeParameter.isReified) { "reified parameters have to be lowered before" }
return typeParameter.superTypes.fold<IrType, IrExpression?>(null) { r, t -> return typeParameter.superTypes.fold<IrType, IrExpression?>(null) { r, t ->
val copy = if (argument is IrExpressionWithCopy) { val copy = argument.shallowCopyOrNull()
argument.copy() ?: argument.deepCopyWithSymbols()
} else {
argument.deepCopyWithSymbols()
}
val check = generateTypeCheckNonNull(copy, t.makeNotNull()) val check = generateTypeCheckNonNull(copy, t.makeNotNull())
if (r == null) { if (r == null) {
@@ -361,7 +359,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass {
val toType = expression.typeOperand val toType = expression.typeOperand
fun maskOp(arg: IrExpression, mask: IrExpression, shift: IrConst<*>) = calculator.run { fun maskOp(arg: IrExpression, mask: IrExpression, shift: IrConst<*>) = calculator.run {
shr(shl(and(arg, mask), shift), shift.copy()) shr(shl(and(arg, mask), shift), shift.shallowCopy())
} }
val newStatements = mutableListOf<IrStatement>() val newStatements = mutableListOf<IrStatement>()
@@ -122,7 +122,7 @@ private class MoveOrCopyCompanionObjectFieldsLowering(val context: JvmBackendCon
correspondingPropertySymbol = property.symbol correspondingPropertySymbol = property.symbol
annotations += oldField.annotations annotations += oldField.annotations
initializer = with(oldField.initializer!!) { initializer = with(oldField.initializer!!) {
IrExpressionBodyImpl(startOffset, endOffset, (expression as IrConst<*>).copy()) IrExpressionBodyImpl(startOffset, endOffset, (expression as IrConst<*>).shallowCopy())
} }
if (oldProperty.parentAsClass.visibility == DescriptorVisibilities.PRIVATE) { if (oldProperty.parentAsClass.visibility == DescriptorVisibilities.PRIVATE) {
@@ -69,8 +69,8 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
} }
} }
private fun IrBlockBuilder.cacheValue(value: IrExpression): () -> IrExpressionWithCopy { private fun IrBlockBuilder.cacheValue(value: IrExpression): () -> IrExpression {
if (value.isPure(true) && value is IrExpressionWithCopy) { if (value.isPure(true) && value.isTrivial()) {
return { value.deepCopyWithSymbols() } return { value.deepCopyWithSymbols() }
} }
val tmpVal = createTmpVariable(value) val tmpVal = createTmpVariable(value)
@@ -84,12 +84,12 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
get() = this.erasedUpperBound?.defaultType ?: builtIns.anyType get() = this.erasedUpperBound?.defaultType ?: builtIns.anyType
private fun generateTypeCheck( private fun generateTypeCheck(
valueProvider: () -> IrExpressionWithCopy, valueProvider: () -> IrExpression,
toType: IrType toType: IrType
): IrExpression { ): IrExpression {
val toNotNullable = toType.makeNotNull() val toNotNullable = toType.makeNotNull()
val valueInstance: IrExpressionWithCopy = valueProvider() val valueInstance: IrExpression = valueProvider()
val fromType = (valueInstance as IrExpression).type val fromType = valueInstance.type
// Inlined values have no type information on runtime. // Inlined values have no type information on runtime.
// But since they are final we can compute type checks on compile time. // But since they are final we can compute type checks on compile time.
@@ -108,7 +108,7 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
else -> else ->
builder.irIfThenElse( builder.irIfThenElse(
type = builtIns.booleanType, type = builtIns.booleanType,
condition = builder.irEqualsNull(valueProvider() as IrExpression), condition = builder.irEqualsNull(valueProvider()),
thenPart = builder.irBoolean(isToNullable), thenPart = builder.irBoolean(isToNullable),
elsePart = instanceCheck elsePart = instanceCheck
) )
@@ -129,16 +129,16 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
else -> error("Unreachable execution (coercion to non-Integer type") else -> error("Unreachable execution (coercion to non-Integer type")
} }
private fun generateTypeCheckNonNull(argument: IrExpressionWithCopy, toType: IrType): IrExpression { private fun generateTypeCheckNonNull(argument: IrExpression, toType: IrType): IrExpression {
assert(!toType.isMarkedNullable()) assert(!toType.isMarkedNullable())
return when { return when {
toType.isNothing() -> builder.irComposite(resultType = builtIns.booleanType) { toType.isNothing() -> builder.irComposite(resultType = builtIns.booleanType) {
+(argument as IrExpression) +(argument)
+builder.irFalse() +builder.irFalse()
} }
toType.isTypeParameter() -> generateTypeCheckWithTypeParameter(argument, toType) toType.isTypeParameter() -> generateTypeCheckWithTypeParameter(argument, toType)
toType.isInterface() -> generateIsInterface(argument as IrExpression, toType) toType.isInterface() -> generateIsInterface(argument, toType)
else -> generateIsSubClass(argument as IrExpression, toType) else -> generateIsSubClass(argument, toType)
} }
} }
@@ -188,12 +188,12 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
val cachedValue = cacheValue(value) val cachedValue = cacheValue(value)
+builder.irIfNull( +builder.irIfNull(
type = toType, type = toType,
subject = cachedValue() as IrExpression, subject = cachedValue(),
thenPart = builder.irNull(toType), thenPart = builder.irNull(toType),
elsePart = builder.irCall(symbols.wasmRefCast, type = toType).apply { elsePart = builder.irCall(symbols.wasmRefCast, type = toType).apply {
putTypeArgument(0, fromType) putTypeArgument(0, fromType)
putTypeArgument(1, toType) putTypeArgument(1, toType)
putValueArgument(0, cachedValue() as IrExpression) putValueArgument(0, cachedValue())
} }
) )
} }
@@ -225,7 +225,7 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
return builder.irComposite(resultType = expression.type) { return builder.irComposite(resultType = expression.type) {
val argument = cacheValue(expression.argument) val argument = cacheValue(expression.argument)
val narrowArg = narrowType(fromType, expression.type, argument() as IrExpression) val narrowArg = narrowType(fromType, expression.type, argument())
val check = generateTypeCheck(argument, toType) val check = generateTypeCheck(argument, toType)
if (check is IrConst<*>) { if (check is IrConst<*>) {
val value = check.value as Boolean val value = check.value as Boolean
@@ -252,12 +252,12 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
value = expression.argument value = expression.argument
) )
private fun generateTypeCheckWithTypeParameter(argument: IrExpressionWithCopy, toType: IrType): IrExpression { private fun generateTypeCheckWithTypeParameter(argument: IrExpression, toType: IrType): IrExpression {
val typeParameter = toType.classifierOrNull?.owner as? IrTypeParameter val typeParameter = toType.classifierOrNull?.owner as? IrTypeParameter
?: error("expected type parameter, but got $toType") ?: error("expected type parameter, but got $toType")
return typeParameter.superTypes.fold(builder.irTrue() as IrExpression) { r, t -> return typeParameter.superTypes.fold(builder.irTrue() as IrExpression) { r, t ->
val check = generateTypeCheckNonNull(argument.copy() as IrExpressionWithCopy, t.makeNotNull()) val check = generateTypeCheckNonNull(argument.shallowCopy(), t.makeNotNull())
builder.irCall(symbols.booleanAnd).apply { builder.irCall(symbols.booleanAnd).apply {
putValueArgument(0, r) putValueArgument(0, r)
putValueArgument(1, check) putValueArgument(1, check)
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.isTrivial
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
@@ -109,7 +110,7 @@ fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffse
TODO("Receiver: ${receiver::class.java.simpleName}") TODO("Receiver: ${receiver::class.java.simpleName}")
} }
if (receiverExpression is IrExpressionWithCopy) if (receiverExpression.isTrivial())
RematerializableValue(receiverExpression.type, receiverExpression) RematerializableValue(receiverExpression.type, receiverExpression)
else else
OnceExpressionValue(receiverExpression) OnceExpressionValue(receiverExpression)
@@ -19,12 +19,12 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.builders.Scope import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy
import org.jetbrains.kotlin.ir.expressions.IrStatementContainer import org.jetbrains.kotlin.ir.expressions.IrStatementContainer
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.shallowCopy
class RematerializableValue(override val type: IrType, val irExpression: IrExpressionWithCopy) : IntermediateValue { class RematerializableValue(override val type: IrType, val irExpression: IrExpression) : IntermediateValue {
override fun load(): IrExpression = irExpression.copy() override fun load(): IrExpression = irExpression.shallowCopy()
} }
fun Scope.createTemporaryVariableInBlock( fun Scope.createTemporaryVariableInBlock(
@@ -16,11 +16,10 @@
package org.jetbrains.kotlin.ir.expressions package org.jetbrains.kotlin.ir.expressions
abstract class IrConst<T> : IrExpression(), IrExpressionWithCopy { abstract class IrConst<T> : IrExpression() {
abstract val kind: IrConstKind<T> abstract val kind: IrConstKind<T>
abstract val value: T abstract val value: T
abstract override fun copy(): IrConst<T>
abstract fun copyWithOffsets(startOffset: Int, endOffset: Int): IrConst<T> abstract fun copyWithOffsets(startOffset: Int, endOffset: Int): IrConst<T>
} }
@@ -27,7 +27,7 @@ abstract class IrDeclarationReference : IrExpression() {
abstract class IrGetSingletonValue : IrDeclarationReference() abstract class IrGetSingletonValue : IrDeclarationReference()
abstract class IrGetObjectValue : IrGetSingletonValue(), IrExpressionWithCopy { abstract class IrGetObjectValue : IrGetSingletonValue() {
abstract override val symbol: IrClassSymbol abstract override val symbol: IrClassSymbol
} }
@@ -40,7 +40,3 @@ abstract class IrExpression : IrElementBase(), IrStatement, IrVarargElement, IrA
// No children by default // No children by default
} }
} }
interface IrExpressionWithCopy {
fun copy(): IrExpression
}
@@ -25,9 +25,7 @@ abstract class IrValueAccessExpression : IrDeclarationReference() {
abstract val origin: IrStatementOrigin? abstract val origin: IrStatementOrigin?
} }
abstract class IrGetValue : IrValueAccessExpression(), IrExpressionWithCopy { abstract class IrGetValue : IrValueAccessExpression()
abstract override fun copy(): IrGetValue
}
abstract class IrSetValue : IrValueAccessExpression() { abstract class IrSetValue : IrValueAccessExpression() {
abstract override val symbol: IrValueSymbol abstract override val symbol: IrValueSymbol
@@ -32,9 +32,6 @@ class IrConstImpl<T>(
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R = override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitConst(this, data) visitor.visitConst(this, data)
override fun copy(): IrConst<T> =
IrConstImpl(startOffset, endOffset, type, kind, value)
override fun copyWithOffsets(startOffset: Int, endOffset: Int) = override fun copyWithOffsets(startOffset: Int, endOffset: Int) =
IrConstImpl(startOffset, endOffset, type, kind, value) IrConstImpl(startOffset, endOffset, type, kind, value)
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.ir.expressions.impl package org.jetbrains.kotlin.ir.expressions.impl
import org.jetbrains.kotlin.ir.expressions.IrErrorExpression import org.jetbrains.kotlin.ir.expressions.IrErrorExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
@@ -26,10 +25,7 @@ class IrErrorExpressionImpl(
override val endOffset: Int, override val endOffset: Int,
override var type: IrType, override var type: IrType,
override val description: String override val description: String
) : IrErrorExpression(), IrExpressionWithCopy { ) : IrErrorExpression() {
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R = override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitErrorExpression(this, data) visitor.visitErrorExpression(this, data)
override fun copy(): IrErrorExpressionImpl =
IrErrorExpressionImpl(startOffset, endOffset, type, description)
} }
@@ -30,8 +30,4 @@ class IrGetObjectValueImpl(
) : IrGetObjectValue() { ) : IrGetObjectValue() {
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R = override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitGetObjectValue(this, data) visitor.visitGetObjectValue(this, data)
override fun copy(): IrExpression {
return IrGetObjectValueImpl(startOffset, endOffset, type, symbol)
}
} }
@@ -27,7 +27,4 @@ class IrGetValueImpl(
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R = override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitGetValue(this, data) visitor.visitGetValue(this, data)
override fun copy(): IrGetValue =
IrGetValueImpl(startOffset, endOffset, type, symbol, origin)
} }
@@ -392,7 +392,7 @@ open class DeepCopyIrTreeWithSymbols(
throw IllegalArgumentException("Unsupported expression type: $expression") throw IllegalArgumentException("Unsupported expression type: $expression")
override fun <T> visitConst(expression: IrConst<T>): IrConst<T> = override fun <T> visitConst(expression: IrConst<T>): IrConst<T> =
expression.copy().copyAttributes(expression) expression.shallowCopy().copyAttributes(expression)
override fun visitVararg(expression: IrVararg): IrVararg = override fun visitVararg(expression: IrVararg): IrVararg =
IrVarargImpl( IrVarargImpl(
@@ -12,9 +12,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -559,3 +557,49 @@ val IrFunction.originalFunction: IrFunction
val IrProperty.originalProperty: IrProperty val IrProperty.originalProperty: IrProperty
get() = attributeOwnerId as? IrProperty ?: this get() = attributeOwnerId as? IrProperty ?: this
fun IrExpression.isTrivial() =
this is IrConst<*> ||
this is IrGetValue ||
this is IrGetObjectValue ||
this is IrErrorExpressionImpl
fun IrExpression.shallowCopy(): IrExpression =
shallowCopyOrNull()
?: error("Not a copyable expression: ${render()}")
fun IrExpression.shallowCopyOrNull(): IrExpression? =
when (this) {
is IrConst<*> -> shallowCopy()
is IrGetObjectValue ->
IrGetObjectValueImpl(
startOffset,
endOffset,
type,
symbol
)
is IrGetValueImpl ->
IrGetValueImpl(
startOffset,
endOffset,
type,
symbol,
origin
)
is IrErrorExpressionImpl ->
IrErrorExpressionImpl(
startOffset,
endOffset,
type,
description
)
else -> null
}
internal fun <T> IrConst<T>.shallowCopy() = IrConstImpl(
startOffset,
endOffset,
type,
kind,
value
)