[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.descriptors.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
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.expressions.impl.*
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
@@ -695,10 +692,4 @@ fun IrExpression?.isPure(
}
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.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.ir.builders.createTmpVariable
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.declarations.*
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.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isNullable
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.transformChildrenVoid
@@ -195,10 +193,7 @@ class IfNullExpressionsFusionLowering(val context: CommonBackendContext) : FileL
private fun IrExpression.copyIfTrivial() =
if (isTrivial()) {
require(this is IrExpressionWithCopy) {
"Not a copyable expression: ${render()}"
}
copy()
shallowCopy()
} else this
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.functions
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.name.FqName
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -262,20 +263,20 @@ private class Transformer(
additionalStatements.addIfNotNull(lowerVar)
additionalStatements.addIfNotNull(upperVar)
}
lowerExpression = tmpLowerExpression.copy()
upperExpression = tmpUpperExpression.copy()
lowerExpression = tmpLowerExpression.shallowCopy()
upperExpression = tmpUpperExpression.shallowCopy()
useLowerClauseOnLeftSide = true
} else if (lower.canHaveSideEffects && upper.canHaveSideEffects) {
if (shouldUpperComeFirst) {
val (upperVar, tmpUpperExpression) = createTemporaryVariableIfNecessary(upper, "containsUpper")
additionalStatements.add(upperVar!!)
lowerExpression = lower
upperExpression = tmpUpperExpression.copy()
upperExpression = tmpUpperExpression.shallowCopy()
useLowerClauseOnLeftSide = true
} else {
val (lowerVar, tmpLowerExpression) = createTemporaryVariableIfNecessary(lower, "containsLower")
additionalStatements.add(lowerVar!!)
lowerExpression = tmpLowerExpression.copy()
lowerExpression = tmpLowerExpression.shallowCopy()
upperExpression = upper
useLowerClauseOnLeftSide = false
}
@@ -311,27 +312,27 @@ private class Transformer(
irCall(lowerCompFun).apply {
putValueArgument(0, irInt(0))
putValueArgument(1, irCall(compareToFun).apply {
dispatchReceiver = argExpression.copy()
dispatchReceiver = argExpression.shallowCopy()
putValueArgument(0, lowerExpression)
})
}
} else {
irCall(lowerCompFun).apply {
putValueArgument(0, lowerExpression)
putValueArgument(1, argExpression.copy())
putValueArgument(1, argExpression.shallowCopy())
}
}
val upperClause = if (useCompareTo) {
irCall(upperCompFun).apply {
putValueArgument(0, irCall(compareToFun).apply {
dispatchReceiver = argExpression.copy()
dispatchReceiver = argExpression.shallowCopy()
putValueArgument(0, upperExpression)
})
putValueArgument(1, irInt(0))
}
} else {
irCall(upperCompFun).apply {
putValueArgument(0, argExpression.copy())
putValueArgument(0, argExpression.shallowCopy())
putValueArgument(1, upperExpression)
}
}
@@ -592,10 +592,6 @@ class FunctionInlining(
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D) =
visitor.visitGetValue(this, data)
override fun copy(): IrGetValue {
TODO("not implemented")
}
fun withLocation(startOffset: Int, endOffset: Int) =
IrGetValueImpl(startOffset, endOffset, type, symbol, origin)
}
@@ -66,13 +66,13 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
val inductionVariable: IrVariable
protected val stepVariable: IrVariable?
val stepExpression: IrExpressionWithCopy
val stepExpression: IrExpression
protected val lastVariableIfCanCacheLast: IrVariable?
protected val lastExpression: IrExpression
// 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.
get() = if (field is IrExpressionWithCopy) field.copy() else field.deepCopyWithSymbols()
get() = field.shallowCopyOrNull() ?: field.deepCopyWithSymbols()
protected val symbols = context.ir.symbols
@@ -105,7 +105,7 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
if (headerInfo.canCacheLast) {
val (variable, expression) = createTemporaryVariableIfNecessary(last, nameHint = "last")
lastVariableIfCanCacheLast = variable
lastExpression = expression.copy()
lastExpression = expression.shallowCopy()
} else {
lastVariableIfCanCacheLast = null
lastExpression = last
@@ -146,7 +146,7 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
inductionVariable.symbol, irCallOp(
plusFun.symbol, plusFun.returnType,
irGet(inductionVariable),
stepExpression.copy(), IrStatementOrigin.PLUSEQ
stepExpression.shallowCopy(), IrStatementOrigin.PLUSEQ
), IrStatementOrigin.PLUSEQ
)
}
@@ -225,14 +225,14 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
context.oror(
context.andand(
irCall(builtIns.greaterFunByOperandType.getValue(stepClass.symbol)).apply {
putValueArgument(0, stepExpression.copy())
putValueArgument(0, stepExpression.shallowCopy())
putValueArgument(1, zeroStepExpression())
},
conditionForIncreasing()
),
context.andand(
irCall(builtIns.lessFunByOperandType.getValue(stepClass.symbol)).apply {
putValueArgument(0, stepExpression.copy())
putValueArgument(0, stepExpression.shallowCopy())
putValueArgument(1, zeroStepExpression())
},
conditionForDecreasing()
@@ -5,7 +5,6 @@
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.ir.builders.createTmpVariable
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.impl.IrCallImpl
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.getClass
import org.jetbrains.kotlin.ir.types.isNothing
import org.jetbrains.kotlin.ir.util.defaultType
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.util.OperatorNameConventions
@@ -82,9 +80,6 @@ private fun Any?.toLong(): Long? =
else -> null
}
internal val IrExpressionWithCopy.constLongValue: Long?
get() = if (this is IrConst<*>) value.toLong() else null
internal val IrExpression.constLongValue: Long?
get() = if (this is IrConst<*>) value.toLong() else null
@@ -97,13 +92,10 @@ internal val IrExpression.constLongValue: Long?
internal fun DeclarationIrBuilder.createTemporaryVariableIfNecessary(
expression: IrExpression, nameHint: String? = null,
irType: IrType? = null, isMutable: Boolean = false
): Pair<IrVariable?, IrExpressionWithCopy> =
): Pair<IrVariable?, IrExpression> =
if (expression.canHaveSideEffects) {
scope.createTmpVariable(expression, nameHint = nameHint, irType = irType, isMutable = isMutable).let { Pair(it, irGet(it)) }
} else {
require(expression is IrExpressionWithCopy) {
"Not a copyable expression: ${expression.render()}"
}
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.getClass
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. */
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 progressionClass = expression.type.getClass()!!
val first = irCall(progressionClass.symbol.getPropertyGetter("first")!!).apply {
dispatchReceiver = progressionExpression.copy()
dispatchReceiver = progressionExpression.shallowCopy()
}
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.
@@ -47,7 +48,7 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte
irInt(1)
} else {
irCall(progressionClass.symbol.getPropertyGetter("step")!!).apply {
dispatchReceiver = progressionExpression.copy()
dispatchReceiver = progressionExpression.shallowCopy()
}
}
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.expressions.IrCall
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.types.defaultType
import org.jetbrains.kotlin.ir.types.isInt
import org.jetbrains.kotlin.ir.types.isLong
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.shallowCopy
import org.jetbrains.kotlin.name.FqName
import kotlin.math.absoluteValue
@@ -79,7 +79,7 @@ internal class StepHandler(
irCall(context.irBuiltIns.illegalArgumentExceptionSymbol).apply {
val exceptionMessage = irConcat()
exceptionMessage.addArgument(irString("Step must be positive, was: "))
exceptionMessage.addArgument(stepArgExpression.copy())
exceptionMessage.addArgument(stepArgExpression.shallowCopy())
exceptionMessage.addArgument(irString("."))
putValueArgument(0, exceptionMessage)
}
@@ -89,7 +89,7 @@ internal class StepHandler(
stepArgValueAsLong == null -> {
// Step argument is not a constant. In this case, we check if step <= 0.
val stepNonPositiveCheck = irCall(stepCompFun).apply {
putValueArgument(0, stepArgExpression.copy())
putValueArgument(0, stepArgExpression.shallowCopy())
putValueArgument(1, data.run { zeroStepExpression() })
}
irIfThen(
@@ -118,7 +118,7 @@ internal class StepHandler(
ProgressionDirection.INCREASING -> stepArgExpression
ProgressionDirection.DECREASING -> {
if (stepArgVar == null) {
stepNegation = scope.createTmpVariable(stepArgExpression.copy().negate())
stepNegation = scope.createTmpVariable(stepArgExpression.shallowCopy().negate())
irGet(stepNegation)
} else {
// Step is already stored in a variable, just negate it.
@@ -133,7 +133,7 @@ internal class StepHandler(
val (tmpNestedStepVar, nestedStepExpression) = createTemporaryVariableIfNecessary(nestedStep, "nestedStep")
nestedStepVar = tmpNestedStepVar
val nestedStepNonPositiveCheck = irCall(stepCompFun).apply {
putValueArgument(0, nestedStepExpression.copy())
putValueArgument(0, nestedStepExpression.shallowCopy())
putValueArgument(1, data.run { zeroStepExpression() })
}
if (stepArgVar == null) {
@@ -142,8 +142,8 @@ internal class StepHandler(
irIfThenElse(
stepType,
nestedStepNonPositiveCheck,
stepArgExpression.copy().negate(),
stepArgExpression.copy()
stepArgExpression.shallowCopy().negate(),
stepArgExpression.shallowCopy()
),
nameHint = "maybeNegatedStep"
)
@@ -272,9 +272,9 @@ internal class StepHandler(
return ProgressionHeaderInfo(
data,
first = nestedFirstExpression.copy(),
first = nestedFirstExpression.shallowCopy(),
last = recalculatedLast,
step = finalStepExpression.copy(),
step = finalStepExpression.shallowCopy(),
isReversed = nestedInfo.isReversed,
additionalStatements = additionalStatements,
direction = nestedInfo.direction
@@ -283,13 +283,13 @@ internal class StepHandler(
private fun DeclarationIrBuilder.callGetProgressionLastElementIfNecessary(
progressionType: ProgressionType,
first: IrExpressionWithCopy,
last: IrExpressionWithCopy,
step: IrExpressionWithCopy
first: IrExpression,
last: IrExpression,
step: IrExpression
): IrExpression {
// Calling getProgressionLastElement() is not needed if step == 1 or -1; the "last" value is unchanged in such cases.
if (step.constLongValue?.absoluteValue == 1L) {
return last.copy()
return last.shallowCopy()
}
// 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.
// The return value is finally converted back to signed since it will be assigned back to `last`.
irCall(getProgressionLastElementFun).apply {
putValueArgument(0, first.copy().asElementType().asUnsigned())
putValueArgument(1, last.copy().asElementType().asUnsigned())
putValueArgument(2, step.copy().asStepType())
putValueArgument(0, first.shallowCopy().asElementType().asUnsigned())
putValueArgument(1, last.shallowCopy().asElementType().asUnsigned())
putValueArgument(2, step.shallowCopy().asStepType())
}.asSigned()
} else {
irCall(getProgressionLastElementFun).apply {
// 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.
putValueArgument(0, first.copy().asStepType())
putValueArgument(1, last.copy().asStepType())
putValueArgument(2, step.copy().asStepType())
putValueArgument(0, first.shallowCopy().asStepType())
putValueArgument(1, last.shallowCopy().asStepType())
putValueArgument(2, step.shallowCopy().asStepType())
}
}
}
@@ -6,15 +6,15 @@
package org.jetbrains.kotlin.ir.backend.js.lower
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.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder
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.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
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.impl.IrCompositeImpl
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 isArraySymbol get() = context.intrinsics.isArraySymbol
private val isSuspendFunctionSymbol = context.intrinsics.isSuspendFunctionSymbol
// private val isCharSymbol get() = context.intrinsics.isCharSymbol
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" }
return typeParameter.superTypes.fold<IrType, IrExpression?>(null) { r, t ->
val copy = if (argument is IrExpressionWithCopy) {
argument.copy()
} else {
argument.deepCopyWithSymbols()
}
val copy = argument.shallowCopyOrNull()
?: argument.deepCopyWithSymbols()
val check = generateTypeCheckNonNull(copy, t.makeNotNull())
if (r == null) {
@@ -361,7 +359,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass {
val toType = expression.typeOperand
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>()
@@ -122,7 +122,7 @@ private class MoveOrCopyCompanionObjectFieldsLowering(val context: JvmBackendCon
correspondingPropertySymbol = property.symbol
annotations += oldField.annotations
initializer = with(oldField.initializer!!) {
IrExpressionBodyImpl(startOffset, endOffset, (expression as IrConst<*>).copy())
IrExpressionBodyImpl(startOffset, endOffset, (expression as IrConst<*>).shallowCopy())
}
if (oldProperty.parentAsClass.visibility == DescriptorVisibilities.PRIVATE) {
@@ -69,8 +69,8 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
}
}
private fun IrBlockBuilder.cacheValue(value: IrExpression): () -> IrExpressionWithCopy {
if (value.isPure(true) && value is IrExpressionWithCopy) {
private fun IrBlockBuilder.cacheValue(value: IrExpression): () -> IrExpression {
if (value.isPure(true) && value.isTrivial()) {
return { value.deepCopyWithSymbols() }
}
val tmpVal = createTmpVariable(value)
@@ -84,12 +84,12 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
get() = this.erasedUpperBound?.defaultType ?: builtIns.anyType
private fun generateTypeCheck(
valueProvider: () -> IrExpressionWithCopy,
valueProvider: () -> IrExpression,
toType: IrType
): IrExpression {
val toNotNullable = toType.makeNotNull()
val valueInstance: IrExpressionWithCopy = valueProvider()
val fromType = (valueInstance as IrExpression).type
val valueInstance: IrExpression = valueProvider()
val fromType = valueInstance.type
// Inlined values have no type information on runtime.
// But since they are final we can compute type checks on compile time.
@@ -108,7 +108,7 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
else ->
builder.irIfThenElse(
type = builtIns.booleanType,
condition = builder.irEqualsNull(valueProvider() as IrExpression),
condition = builder.irEqualsNull(valueProvider()),
thenPart = builder.irBoolean(isToNullable),
elsePart = instanceCheck
)
@@ -129,16 +129,16 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
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())
return when {
toType.isNothing() -> builder.irComposite(resultType = builtIns.booleanType) {
+(argument as IrExpression)
+(argument)
+builder.irFalse()
}
toType.isTypeParameter() -> generateTypeCheckWithTypeParameter(argument, toType)
toType.isInterface() -> generateIsInterface(argument as IrExpression, toType)
else -> generateIsSubClass(argument as IrExpression, toType)
toType.isInterface() -> generateIsInterface(argument, toType)
else -> generateIsSubClass(argument, toType)
}
}
@@ -188,12 +188,12 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
val cachedValue = cacheValue(value)
+builder.irIfNull(
type = toType,
subject = cachedValue() as IrExpression,
subject = cachedValue(),
thenPart = builder.irNull(toType),
elsePart = builder.irCall(symbols.wasmRefCast, type = toType).apply {
putTypeArgument(0, fromType)
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) {
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)
if (check is IrConst<*>) {
val value = check.value as Boolean
@@ -252,12 +252,12 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
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
?: error("expected type parameter, but got $toType")
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 {
putValueArgument(0, r)
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.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.isTrivial
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
@@ -109,7 +110,7 @@ fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffse
TODO("Receiver: ${receiver::class.java.simpleName}")
}
if (receiverExpression is IrExpressionWithCopy)
if (receiverExpression.isTrivial())
RematerializableValue(receiverExpression.type, receiverExpression)
else
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.Scope
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.types.IrType
import org.jetbrains.kotlin.ir.util.shallowCopy
class RematerializableValue(override val type: IrType, val irExpression: IrExpressionWithCopy) : IntermediateValue {
override fun load(): IrExpression = irExpression.copy()
class RematerializableValue(override val type: IrType, val irExpression: IrExpression) : IntermediateValue {
override fun load(): IrExpression = irExpression.shallowCopy()
}
fun Scope.createTemporaryVariableInBlock(
@@ -16,11 +16,10 @@
package org.jetbrains.kotlin.ir.expressions
abstract class IrConst<T> : IrExpression(), IrExpressionWithCopy {
abstract class IrConst<T> : IrExpression() {
abstract val kind: IrConstKind<T>
abstract val value: T
abstract override fun copy(): 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 IrGetObjectValue : IrGetSingletonValue(), IrExpressionWithCopy {
abstract class IrGetObjectValue : IrGetSingletonValue() {
abstract override val symbol: IrClassSymbol
}
@@ -39,8 +39,4 @@ abstract class IrExpression : IrElementBase(), IrStatement, IrVarargElement, IrA
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
// No children by default
}
}
interface IrExpressionWithCopy {
fun copy(): IrExpression
}
}
@@ -25,9 +25,7 @@ abstract class IrValueAccessExpression : IrDeclarationReference() {
abstract val origin: IrStatementOrigin?
}
abstract class IrGetValue : IrValueAccessExpression(), IrExpressionWithCopy {
abstract override fun copy(): IrGetValue
}
abstract class IrGetValue : IrValueAccessExpression()
abstract class IrSetValue : IrValueAccessExpression() {
abstract override val symbol: IrValueSymbol
@@ -32,9 +32,6 @@ class IrConstImpl<T>(
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitConst(this, data)
override fun copy(): IrConst<T> =
IrConstImpl(startOffset, endOffset, type, kind, value)
override fun copyWithOffsets(startOffset: Int, endOffset: Int) =
IrConstImpl(startOffset, endOffset, type, kind, value)
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.ir.expressions.impl
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.visitors.IrElementVisitor
@@ -26,10 +25,7 @@ class IrErrorExpressionImpl(
override val endOffset: Int,
override var type: IrType,
override val description: String
) : IrErrorExpression(), IrExpressionWithCopy {
) : IrErrorExpression() {
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitErrorExpression(this, data)
override fun copy(): IrErrorExpressionImpl =
IrErrorExpressionImpl(startOffset, endOffset, type, description)
}
@@ -30,8 +30,4 @@ class IrGetObjectValueImpl(
) : IrGetObjectValue() {
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
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 =
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")
override fun <T> visitConst(expression: IrConst<T>): IrConst<T> =
expression.copy().copyAttributes(expression)
expression.shallowCopy().copyAttributes(expression)
override fun visitVararg(expression: IrVararg): IrVararg =
IrVarargImpl(
@@ -12,9 +12,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.name.FqName
@@ -558,4 +556,50 @@ val IrFunction.originalFunction: IrFunction
get() = (this as? IrAttributeContainer)?.attributeOwnerId as? IrFunction ?: this
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
)