IR: remove unnecessary calls to deepCopyWithSymbols

to make it harder to hide incorrect uses.
This commit is contained in:
pyos
2020-10-13 14:33:24 +02:00
committed by Alexander Udalov
parent 45a0850d95
commit 13def12731
14 changed files with 94 additions and 108 deletions
@@ -149,7 +149,7 @@ fun IrValueParameter.copyTo(
descriptor.bind(it) descriptor.bind(it)
it.parent = irFunction it.parent = irFunction
it.defaultValue = defaultValueCopy it.defaultValue = defaultValueCopy
it.annotations = annotations.map { it.deepCopyWithSymbols() } it.copyAnnotationsFrom(this)
} }
} }
@@ -229,6 +229,10 @@ private fun IrTypeParameter.copySuperTypesFrom(source: IrTypeParameter, srcToDst
} }
} }
fun IrMutableAnnotationContainer.copyAnnotationsFrom(source: IrAnnotationContainer) {
annotations += source.annotations.map { it.deepCopyWithSymbols(this as? IrDeclarationParent) }
}
// Copy value parameters, dispatch receiver, and extension receiver from source to value parameters of this function. // Copy value parameters, dispatch receiver, and extension receiver from source to value parameters of this function.
// Type of dispatch receiver defaults to source's dispatch receiver. It is overridable in case the new function and the old one are used in // Type of dispatch receiver defaults to source's dispatch receiver. It is overridable in case the new function and the old one are used in
// different contexts and expect different type of dispatch receivers. The overriding type should be assign compatible to the old type. // different contexts and expect different type of dispatch receivers. The overriding type should be assign compatible to the old type.
@@ -606,7 +606,7 @@ private fun IrFunction.generateDefaultsFunctionImpl(
} }
// TODO some annotations are needed (e.g. @JvmStatic), others need different values (e.g. @JvmName), the rest are redundant. // TODO some annotations are needed (e.g. @JvmStatic), others need different values (e.g. @JvmName), the rest are redundant.
newFunction.annotations = annotations.map { it.deepCopyWithSymbols() } newFunction.copyAnnotationsFrom(this)
return newFunction return newFunction
} }
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
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.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -260,20 +259,20 @@ private class Transformer(
additionalStatements.addIfNotNull(lowerVar) additionalStatements.addIfNotNull(lowerVar)
additionalStatements.addIfNotNull(upperVar) additionalStatements.addIfNotNull(upperVar)
} }
lowerExpression = tmpLowerExpression lowerExpression = tmpLowerExpression.copy()
upperExpression = tmpUpperExpression upperExpression = tmpUpperExpression.copy()
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 upperExpression = tmpUpperExpression.copy()
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 lowerExpression = tmpLowerExpression.copy()
upperExpression = upper upperExpression = upper
useLowerClauseOnLeftSide = false useLowerClauseOnLeftSide = false
} }
@@ -309,27 +308,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 dispatchReceiver = argExpression.copy()
putValueArgument(0, lowerExpression) putValueArgument(0, lowerExpression)
}) })
} }
} else { } else {
irCall(lowerCompFun).apply { irCall(lowerCompFun).apply {
putValueArgument(0, lowerExpression) putValueArgument(0, lowerExpression)
putValueArgument(1, argExpression) putValueArgument(1, argExpression.copy())
} }
} }
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.deepCopyWithSymbols() dispatchReceiver = argExpression.copy()
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.deepCopyWithSymbols()) putValueArgument(0, argExpression.copy())
putValueArgument(1, upperExpression) putValueArgument(1, upperExpression)
} }
} }
@@ -13,15 +13,13 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
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.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrDoWhileLoopImpl import org.jetbrains.kotlin.ir.expressions.impl.IrDoWhileLoopImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrWhileLoopImpl import org.jetbrains.kotlin.ir.expressions.impl.IrWhileLoopImpl
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
/** /**
@@ -68,14 +66,13 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
val inductionVariable: IrVariable val inductionVariable: IrVariable
protected val stepVariable: IrVariable? protected val stepVariable: IrVariable?
val stepExpression: IrExpression val stepExpression: IrExpressionWithCopy
// Always copy `stepExpression` is it may be used multiple times.
get() = field.deepCopyWithSymbols()
protected val lastVariableIfCanCacheLast: IrVariable? protected val lastVariableIfCanCacheLast: IrVariable?
protected val lastExpression: IrExpression protected val lastExpression: IrExpression
// Always copy `lastExpression` is it may be used in multiple conditions. // If this is not `IrExpressionWithCopy`, then it is `<IrGetValue>.getSize()` built in `IndexedGetIterationHandler`.
get() = field.deepCopyWithSymbols() // 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()
protected val symbols = context.ir.symbols protected val symbols = context.ir.symbols
@@ -105,11 +102,14 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
// TODO: Confirm if casting to non-nullable is still necessary // TODO: Confirm if casting to non-nullable is still necessary
val last = headerInfo.last.asElementType() val last = headerInfo.last.asElementType()
lastVariableIfCanCacheLast = if (headerInfo.canCacheLast) { if (headerInfo.canCacheLast) {
scope.createTmpVariable(last, nameHint = "last") val (variable, expression) = createTemporaryVariableIfNecessary(last, nameHint = "last")
} else null lastVariableIfCanCacheLast = variable
lastExpression = expression.copy()
lastExpression = if (headerInfo.canCacheLast) irGet(lastVariableIfCanCacheLast!!) else last } else {
lastVariableIfCanCacheLast = null
lastExpression = last
}
val (tmpStepVar, tmpStepExpression) = val (tmpStepVar, tmpStepExpression) =
createTemporaryVariableIfNecessary( createTemporaryVariableIfNecessary(
@@ -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, IrStatementOrigin.PLUSEQ stepExpression.copy(), 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) putValueArgument(0, stepExpression.copy())
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) putValueArgument(0, stepExpression.copy())
putValueArgument(1, zeroStepExpression()) putValueArgument(1, zeroStepExpression())
}, },
conditionForDecreasing() conditionForDecreasing()
@@ -351,19 +351,17 @@ internal class ProgressionLoopHeader(
} }
} }
private class InitializerCallReplacer(symbolRemapper: SymbolRemapper, typeRemapper: TypeRemapper, val replacementCall: IrCall) : private class InitializerCallReplacer(val replacementCall: IrCall) : IrElementTransformerVoid() {
DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper) {
var initializerCall: IrCall? = null var initializerCall: IrCall? = null
override fun visitCall(expression: IrCall): IrCall { override fun visitCall(expression: IrCall): IrCall {
if (initializerCall == null) { if (initializerCall != null) {
initializerCall = expression
return replacementCall
} else {
throw IllegalStateException( throw IllegalStateException(
"Multiple initializer calls found. First: ${initializerCall!!.render()}\nSecond: ${expression.render()}" "Multiple initializer calls found. First: ${initializerCall!!.render()}\nSecond: ${expression.render()}"
) )
} }
initializerCall = expression
return replacementCall
} }
} }
@@ -390,9 +388,7 @@ internal class IndexedGetLoopHeader(
} }
// The call could be wrapped in an IMPLICIT_NOTNULL type-cast (see comment in ForLoopsLowering.gatherLoopVariableInfo()). // The call could be wrapped in an IMPLICIT_NOTNULL type-cast (see comment in ForLoopsLowering.gatherLoopVariableInfo()).
// Find and replace the call to preserve any type-casts. // Find and replace the call to preserve any type-casts.
loopVariable?.initializer = loopVariable?.initializer?.deepCopyWithSymbols { symbolRemapper, typeRemapper -> loopVariable?.initializer = loopVariable?.initializer?.transform(InitializerCallReplacer(get), null)
InitializerCallReplacer(symbolRemapper, typeRemapper, get)
}
// Even if there is no loop variable, we always want to call `get()` as it may have side-effects. // Even if there is no loop variable, we always want to call `get()` as it may have side-effects.
// The un-lowered loop always calls `get()` on each iteration. // The un-lowered loop always calls `get()` on each iteration.
listOf(loopVariable ?: get) + incrementInductionVariable(this) listOf(loopVariable ?: get) + incrementInductionVariable(this)
@@ -589,9 +585,7 @@ internal class IterableLoopHeader(
} }
// The call could be wrapped in an IMPLICIT_NOTNULL type-cast (see comment in ForLoopsLowering.gatherLoopVariableInfo()). // The call could be wrapped in an IMPLICIT_NOTNULL type-cast (see comment in ForLoopsLowering.gatherLoopVariableInfo()).
// Find and replace the call to preserve any type-casts. // Find and replace the call to preserve any type-casts.
loopVariable?.initializer = loopVariable?.initializer?.deepCopyWithSymbols { symbolRemapper, typeRemapper -> loopVariable?.initializer = loopVariable?.initializer?.transform(InitializerCallReplacer(next), null)
InitializerCallReplacer(symbolRemapper, typeRemapper, next)
}
// Even if there is no loop variable, we always want to call `next()` for iterables and sequences. // Even if there is no loop variable, we always want to call `next()` for iterables and sequences.
listOf(loopVariable ?: next.coerceToUnitIfNeeded(next.type, context.irBuiltIns)) listOf(loopVariable ?: next.coerceToUnitIfNeeded(next.type, context.irBuiltIns))
} }
@@ -31,8 +31,6 @@ internal sealed class ProgressionType(
val maxValueAsLong: Long, val maxValueAsLong: Long,
val getProgressionLastElementFunction: IrSimpleFunctionSymbol? val getProgressionLastElementFunction: IrSimpleFunctionSymbol?
) { ) {
abstract fun DeclarationIrBuilder.minValueExpression(): IrExpression
abstract fun DeclarationIrBuilder.zeroStepExpression(): IrExpression abstract fun DeclarationIrBuilder.zeroStepExpression(): IrExpression
fun IrExpression.asElementType() = castIfNecessary(elementClass) fun IrExpression.asElementType() = castIfNecessary(elementClass)
@@ -63,7 +61,6 @@ internal class IntProgressionType(symbols: Symbols<CommonBackendContext>) :
// Uses `getProgressionLastElement(Int, Int, Int): Int` // Uses `getProgressionLastElement(Int, Int, Int): Int`
getProgressionLastElementFunction = symbols.getProgressionLastElementByReturnType[symbols.int] getProgressionLastElementFunction = symbols.getProgressionLastElementByReturnType[symbols.int]
) { ) {
override fun DeclarationIrBuilder.minValueExpression() = irInt(Int.MIN_VALUE)
override fun DeclarationIrBuilder.zeroStepExpression() = irInt(0) override fun DeclarationIrBuilder.zeroStepExpression() = irInt(0)
} }
@@ -77,7 +74,6 @@ internal class LongProgressionType(symbols: Symbols<CommonBackendContext>) :
// Uses `getProgressionLastElement(Long, Long, Long): Long` // Uses `getProgressionLastElement(Long, Long, Long): Long`
getProgressionLastElementFunction = symbols.getProgressionLastElementByReturnType[symbols.long] getProgressionLastElementFunction = symbols.getProgressionLastElementByReturnType[symbols.long]
) { ) {
override fun DeclarationIrBuilder.minValueExpression() = irLong(Long.MIN_VALUE)
override fun DeclarationIrBuilder.zeroStepExpression() = irLong(0) override fun DeclarationIrBuilder.zeroStepExpression() = irLong(0)
} }
@@ -91,7 +87,6 @@ internal class CharProgressionType(symbols: Symbols<CommonBackendContext>) :
// Uses `getProgressionLastElement(Int, Int, Int): Int` // Uses `getProgressionLastElement(Int, Int, Int): Int`
getProgressionLastElementFunction = symbols.getProgressionLastElementByReturnType[symbols.int] getProgressionLastElementFunction = symbols.getProgressionLastElementByReturnType[symbols.int]
) { ) {
override fun DeclarationIrBuilder.minValueExpression() = irChar(Char.MIN_VALUE)
override fun DeclarationIrBuilder.zeroStepExpression() = irInt(0) override fun DeclarationIrBuilder.zeroStepExpression() = irInt(0)
} }
@@ -175,7 +170,7 @@ internal abstract class UnsignedProgressionType(
} }
} }
internal class UIntProgressionType(symbols: Symbols<CommonBackendContext>, allowUnsignedBounds: Boolean) : internal class UIntProgressionType(symbols: Symbols<CommonBackendContext>, allowUnsignedBounds: Boolean) :
UnsignedProgressionType( UnsignedProgressionType(
symbols, symbols,
elementClass = if (allowUnsignedBounds) symbols.uInt!!.owner else symbols.int.owner, elementClass = if (allowUnsignedBounds) symbols.uInt!!.owner else symbols.int.owner,
@@ -187,13 +182,11 @@ internal class UIntProgressionType(symbols: Symbols<CommonBackendContext>, allo
unsignedType = symbols.uInt!!.defaultType, unsignedType = symbols.uInt!!.defaultType,
unsignedConversionFunction = symbols.toUIntByExtensionReceiver.getValue(symbols.int) unsignedConversionFunction = symbols.toUIntByExtensionReceiver.getValue(symbols.int)
) { ) {
@OptIn(ExperimentalUnsignedTypes::class)
override fun DeclarationIrBuilder.minValueExpression() = irInt(UInt.MIN_VALUE.toInt(), elementClass.defaultType)
override fun DeclarationIrBuilder.zeroStepExpression() = irInt(0) override fun DeclarationIrBuilder.zeroStepExpression() = irInt(0)
} }
internal class ULongProgressionType(symbols: Symbols<CommonBackendContext>, private val allowUnsignedBounds: Boolean) : internal class ULongProgressionType(symbols: Symbols<CommonBackendContext>, allowUnsignedBounds: Boolean) :
UnsignedProgressionType( UnsignedProgressionType(
symbols, symbols,
elementClass = if (allowUnsignedBounds) symbols.uLong!!.owner else symbols.long.owner, elementClass = if (allowUnsignedBounds) symbols.uLong!!.owner else symbols.long.owner,
@@ -205,8 +198,6 @@ internal class ULongProgressionType(symbols: Symbols<CommonBackendContext>, priv
unsignedType = symbols.uLong!!.defaultType, unsignedType = symbols.uLong!!.defaultType,
unsignedConversionFunction = symbols.toULongByExtensionReceiver.getValue(symbols.long) unsignedConversionFunction = symbols.toULongByExtensionReceiver.getValue(symbols.long)
) { ) {
@OptIn(ExperimentalUnsignedTypes::class)
override fun DeclarationIrBuilder.minValueExpression() = irLong(ULong.MIN_VALUE.toLong(), elementClass.defaultType)
override fun DeclarationIrBuilder.zeroStepExpression() = irLong(0) override fun DeclarationIrBuilder.zeroStepExpression() = irLong(0)
} }
@@ -10,10 +10,7 @@ import org.jetbrains.kotlin.ir.builders.createTmpVariable
import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
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.types.IrType import org.jetbrains.kotlin.ir.types.IrType
@@ -73,16 +70,20 @@ internal fun IrExpression.decrement(): IrExpression {
} }
internal val IrExpression.canHaveSideEffects: Boolean internal val IrExpression.canHaveSideEffects: Boolean
get() = this !is IrConst<*> && this !is IrGetValue get() = this !is IrExpressionWithCopy
private fun Any?.toLong(): Long? =
when (this) {
is Number -> toLong()
is Char -> toLong()
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<*>) { get() = if (this is IrConst<*>) value.toLong() else null
when (val value = this.value) {
is Number -> value.toLong()
is Char -> value.toLong()
else -> null
}
} else null
/** /**
* If [expression] can have side effects ([IrExpression.canHaveSideEffects]), this function creates a temporary local variable for that * If [expression] can have side effects ([IrExpression.canHaveSideEffects]), this function creates a temporary local variable for that
@@ -93,8 +94,8 @@ 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?, IrExpression> = ): Pair<IrVariable?, IrExpressionWithCopy> =
if (expression.canHaveSideEffects) { if (expression !is IrExpressionWithCopy) {
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 {
Pair(null, expression) Pair(null, expression)
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
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.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.getPropertyGetter import org.jetbrains.kotlin.ir.util.getPropertyGetter
/** Builds a [HeaderInfo] for progressions not handled by more specialized handlers. */ /** Builds a [HeaderInfo] for progressions not handled by more specialized handlers. */
@@ -34,27 +33,27 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
// Directly use the `first/last/step` properties of the progression. // Directly use the `first/last/step` properties of the progression.
val (progressionVar, progressionExpression) = createTemporaryVariableIfNecessary(expression, nameHint = "progression") val (progressionVar, progressionExpression) = createTemporaryVariableIfNecessary(expression, nameHint = "progression")
val progressionClass = progressionExpression.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 dispatchReceiver = progressionExpression.copy()
} }
val last = irCall(progressionClass.symbol.getPropertyGetter("last")!!).apply { val last = irCall(progressionClass.symbol.getPropertyGetter("last")!!).apply {
dispatchReceiver = progressionExpression.deepCopyWithSymbols() dispatchReceiver = progressionExpression.copy()
} }
// *Ranges (e.g., IntRange) have step == 1 and is always increasing. // *Ranges (e.g., IntRange) have step == 1 and is always increasing.
val isRange = progressionExpression.type in rangeClassesTypes val isRange = expression.type in rangeClassesTypes
val step = if (isRange) { val step = if (isRange) {
irInt(1) irInt(1)
} else { } else {
irCall(progressionClass.symbol.getPropertyGetter("step")!!).apply { irCall(progressionClass.symbol.getPropertyGetter("step")!!).apply {
dispatchReceiver = progressionExpression.deepCopyWithSymbols() dispatchReceiver = progressionExpression.copy()
} }
} }
val direction = if (isRange) ProgressionDirection.INCREASING else ProgressionDirection.UNKNOWN val direction = if (isRange) ProgressionDirection.INCREASING else ProgressionDirection.UNKNOWN
ProgressionHeaderInfo( ProgressionHeaderInfo(
ProgressionType.fromIrType(progressionExpression.type, symbols, allowUnsignedBounds)!!, ProgressionType.fromIrType(expression.type, symbols, allowUnsignedBounds)!!,
first, first,
last, last,
step, step,
@@ -16,11 +16,11 @@ 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.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
@@ -75,12 +75,11 @@ internal class StepHandler(
// We insert a similar check in the lowered form only if necessary. // We insert a similar check in the lowered form only if necessary.
val stepType = data.stepClass.defaultType val stepType = data.stepClass.defaultType
val stepCompFun = context.irBuiltIns.lessOrEqualFunByOperandType.getValue(data.stepClass.symbol) val stepCompFun = context.irBuiltIns.lessOrEqualFunByOperandType.getValue(data.stepClass.symbol)
val zeroStep = data.run { zeroStepExpression() }
val throwIllegalStepExceptionCall = { val throwIllegalStepExceptionCall = {
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.deepCopyWithSymbols()) exceptionMessage.addArgument(stepArgExpression.copy())
exceptionMessage.addArgument(irString(".")) exceptionMessage.addArgument(irString("."))
putValueArgument(0, exceptionMessage) putValueArgument(0, exceptionMessage)
} }
@@ -90,8 +89,8 @@ 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.deepCopyWithSymbols()) putValueArgument(0, stepArgExpression.copy())
putValueArgument(1, zeroStep.deepCopyWithSymbols()) putValueArgument(1, data.run { zeroStepExpression() })
} }
irIfThen( irIfThen(
context.irBuiltIns.unitType, context.irBuiltIns.unitType,
@@ -119,7 +118,8 @@ internal class StepHandler(
ProgressionDirection.INCREASING -> stepArgExpression ProgressionDirection.INCREASING -> stepArgExpression
ProgressionDirection.DECREASING -> { ProgressionDirection.DECREASING -> {
if (stepArgVar == null) { if (stepArgVar == null) {
stepArgExpression.negate() stepNegation = scope.createTmpVariable(stepArgExpression.copy().negate())
irGet(stepNegation)
} else { } else {
// Step is already stored in a variable, just negate it. // Step is already stored in a variable, just negate it.
stepNegation = irSet(stepArgVar.symbol, irGet(stepArgVar).negate()) stepNegation = irSet(stepArgVar.symbol, irGet(stepArgVar).negate())
@@ -133,8 +133,8 @@ 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) putValueArgument(0, nestedStepExpression.copy())
putValueArgument(1, zeroStep.deepCopyWithSymbols()) putValueArgument(1, data.run { zeroStepExpression() })
} }
if (stepArgVar == null) { if (stepArgVar == null) {
// Create a temporary variable for the possibly-negated step, so we don't have to re-check every time step is used. // Create a temporary variable for the possibly-negated step, so we don't have to re-check every time step is used.
@@ -142,8 +142,8 @@ internal class StepHandler(
irIfThenElse( irIfThenElse(
stepType, stepType,
nestedStepNonPositiveCheck, nestedStepNonPositiveCheck,
stepArgExpression.deepCopyWithSymbols().negate(), stepArgExpression.copy().negate(),
stepArgExpression.deepCopyWithSymbols() stepArgExpression.copy()
), ),
nameHint = "maybeNegatedStep" nameHint = "maybeNegatedStep"
) )
@@ -272,9 +272,9 @@ internal class StepHandler(
return ProgressionHeaderInfo( return ProgressionHeaderInfo(
data, data,
first = nestedFirstExpression, first = nestedFirstExpression.copy(),
last = recalculatedLast, last = recalculatedLast,
step = finalStepExpression, step = finalStepExpression.copy(),
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: IrExpression, first: IrExpressionWithCopy,
last: IrExpression, last: IrExpressionWithCopy,
step: IrExpression step: IrExpressionWithCopy
): 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 return last.copy()
} }
// 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.deepCopyWithSymbols().asElementType().asUnsigned()) putValueArgument(0, first.copy().asElementType().asUnsigned())
putValueArgument(1, last.deepCopyWithSymbols().asElementType().asUnsigned()) putValueArgument(1, last.copy().asElementType().asUnsigned())
putValueArgument(2, step.deepCopyWithSymbols().asStepType()) putValueArgument(2, step.copy().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.deepCopyWithSymbols().asStepType()) putValueArgument(0, first.copy().asStepType())
putValueArgument(1, last.deepCopyWithSymbols().asStepType()) putValueArgument(1, last.copy().asStepType())
putValueArgument(2, step.deepCopyWithSymbols().asStepType()) putValueArgument(2, step.copy().asStepType())
} }
} }
} }
@@ -291,7 +291,7 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
if (view.isInline) JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE if (view.isInline) JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE
else JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE else JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE
}.apply { }.apply {
annotations += view.annotations.map { it.deepCopyWithSymbols(this) } copyAnnotationsFrom(view)
copyParameterDeclarationsFrom(view) copyParameterDeclarationsFrom(view)
copyAttributes(view) copyAttributes(view)
generateErrorForInlineBody() generateErrorForInlineBody()
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.ir.copyAnnotationsFrom
import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
@@ -219,10 +220,10 @@ private fun IrSimpleFunction.createMultifileDelegateIfNeeded(
} }
} }
function.copyAnnotationsFrom(target)
function.copyParameterDeclarationsFrom(target) function.copyParameterDeclarationsFrom(target)
function.returnType = target.returnType.substitute(target.typeParameters, function.typeParameters.map { it.defaultType }) function.returnType = target.returnType.substitute(target.typeParameters, function.typeParameters.map { it.defaultType })
function.parent = facadeClass function.parent = facadeClass
function.annotations = target.annotations.map { it.deepCopyWithSymbols() }
if (shouldGeneratePartHierarchy) { if (shouldGeneratePartHierarchy) {
function.origin = IrDeclarationOrigin.FAKE_OVERRIDE function.origin = IrDeclarationOrigin.FAKE_OVERRIDE
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.ir.copyAnnotationsFrom
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
@@ -17,7 +18,6 @@ import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.builders.irDelegatingConstructorCall import org.jetbrains.kotlin.ir.builders.irDelegatingConstructorCall
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.hasDefaultValue import org.jetbrains.kotlin.ir.util.hasDefaultValue
internal val jvmDefaultConstructorPhase = makeIrFilePhase( internal val jvmDefaultConstructorPhase = makeIrFilePhase(
@@ -53,7 +53,7 @@ private class JvmDefaultConstructorLowering(val context: JvmBackendContext) : Cl
visibility = primaryConstructor.visibility visibility = primaryConstructor.visibility
}.apply { }.apply {
val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset) val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset)
annotations += primaryConstructor.annotations.map { it.deepCopyWithSymbols(this) } copyAnnotationsFrom(primaryConstructor)
body = irBuilder.irBlockBody { body = irBuilder.irBlockBody {
+irDelegatingConstructorCall(primaryConstructor).apply { +irDelegatingConstructorCall(primaryConstructor).apply {
passTypeArgumentsFrom(irClass) passTypeArgumentsFrom(irClass)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ir.copyAnnotationsFrom
import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport
@@ -17,7 +18,6 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.util.parentAsClass
@@ -67,9 +67,9 @@ class JvmInnerClassesSupport(private val irFactory: IrFactory) : InnerClassesSup
updateFrom(oldConstructor) updateFrom(oldConstructor)
returnType = oldConstructor.returnType returnType = oldConstructor.returnType
}.apply { }.apply {
annotations = oldConstructor.annotations.map { it.deepCopyWithSymbols(this) }
parent = oldConstructor.parent parent = oldConstructor.parent
returnType = oldConstructor.returnType returnType = oldConstructor.returnType
copyAnnotationsFrom(oldConstructor)
copyTypeParametersFrom(oldConstructor) copyTypeParametersFrom(oldConstructor)
val outerThisValueParameter = buildValueParameter(this) { val outerThisValueParameter = buildValueParameter(this) {
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.ir.copyAnnotationsFrom
import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
@@ -20,7 +21,6 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.allTypeParameters import org.jetbrains.kotlin.ir.util.allTypeParameters
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_OVERLOADS_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_OVERLOADS_FQ_NAME
@@ -145,7 +145,7 @@ private class JvmOverloadsAnnotationLowering(val context: JvmBackendContext) : C
} }
res.parent = oldFunction.parent res.parent = oldFunction.parent
res.annotations += oldFunction.annotations.map { it.deepCopyWithSymbols(res) } res.copyAnnotationsFrom(oldFunction)
res.copyTypeParametersFrom(oldFunction) res.copyTypeParametersFrom(oldFunction)
res.dispatchReceiverParameter = oldFunction.dispatchReceiverParameter?.copyTo(res) res.dispatchReceiverParameter = oldFunction.dispatchReceiverParameter?.copyTo(res)
res.extensionReceiverParameter = oldFunction.extensionReceiverParameter?.copyTo(res) res.extensionReceiverParameter = oldFunction.extensionReceiverParameter?.copyTo(res)
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlock import org.jetbrains.kotlin.backend.common.lower.irBlock
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
@@ -79,9 +76,9 @@ private class CompanionObjectJvmStaticLowering(val context: JvmBackendContext) :
returnType = jvmStaticFunction.returnType returnType = jvmStaticFunction.returnType
}.apply { }.apply {
copyTypeParametersFrom(jvmStaticFunction) copyTypeParametersFrom(jvmStaticFunction)
copyAnnotationsFrom(jvmStaticFunction)
extensionReceiverParameter = jvmStaticFunction.extensionReceiverParameter?.copyTo(this) extensionReceiverParameter = jvmStaticFunction.extensionReceiverParameter?.copyTo(this)
valueParameters = jvmStaticFunction.valueParameters.map { it.copyTo(this) } valueParameters = jvmStaticFunction.valueParameters.map { it.copyTo(this) }
annotations = jvmStaticFunction.annotations.map { it.deepCopyWithSymbols() }
} }
companion.declarations.remove(jvmStaticFunction) companion.declarations.remove(jvmStaticFunction)
companion.addProxy(staticExternal, companion, isStatic = false) companion.addProxy(staticExternal, companion, isStatic = false)
@@ -106,12 +103,12 @@ private class CompanionObjectJvmStaticLowering(val context: JvmBackendContext) :
isSuspend = target.isSuspend isSuspend = target.isSuspend
}.apply { }.apply {
copyTypeParametersFrom(target) copyTypeParametersFrom(target)
copyAnnotationsFrom(target)
if (!isStatic) { if (!isStatic) {
dispatchReceiverParameter = thisReceiver?.copyTo(this, type = defaultType) dispatchReceiverParameter = thisReceiver?.copyTo(this, type = defaultType)
} }
extensionReceiverParameter = target.extensionReceiverParameter?.copyTo(this) extensionReceiverParameter = target.extensionReceiverParameter?.copyTo(this)
valueParameters = target.valueParameters.map { it.copyTo(this) } valueParameters = target.valueParameters.map { it.copyTo(this) }
annotations = target.annotations.map { it.deepCopyWithSymbols() }
val proxy = this val proxy = this
val companionInstanceField = context.cachedDeclarations.getFieldForObjectInstance(companion) val companionInstanceField = context.cachedDeclarations.getFieldForObjectInstance(companion)