[JS IR] Move isPure check to backend.common and add platform-specific check on calls with side effects

This commit is contained in:
Ilya Goncharov
2021-03-03 15:29:43 +03:00
parent 7bbb5b77db
commit 120b5b9e05
11 changed files with 79 additions and 48 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irString
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
@@ -45,4 +46,8 @@ interface CommonBackendContext : BackendContext, LoggingContext {
classSymbolMap: MutableMap<IrClassSymbol, IrClassSymbol>,
functionSymbolMap: MutableMap<IrSimpleFunctionSymbol, IrSimpleFunctionSymbol>
) {}
fun isSideEffectFree(call: IrCall): Boolean {
return false
}
}
@@ -644,3 +644,42 @@ private fun computeAllOverridden(function: IrSimpleFunction, result: MutableSet<
}
}
}
// TODO: support more cases like built-in operator call and so on
fun IrExpression?.isPure(
anyVariable: Boolean,
checkFields: Boolean = true,
context: CommonBackendContext? = null
): Boolean {
if (this == null) return true
fun IrExpression.isPureImpl(): Boolean {
return when (this) {
is IrConst<*> -> true
is IrGetValue -> {
if (anyVariable) return true
val valueDeclaration = symbol.owner
if (valueDeclaration is IrVariable) !valueDeclaration.isVar
else true
}
is IrCall -> context?.isSideEffectFree(this) ?: false
is IrGetObjectValue -> type.isUnit()
else -> false
}
}
if (isPureImpl()) return true
if (!checkFields) return false
if (this is IrGetField) {
if (!symbol.owner.isFinal) {
if (!anyVariable) {
return false
}
}
return receiver.isPure(anyVariable)
}
return false
}
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.util.isPure
import org.jetbrains.kotlin.backend.common.ir.isPure
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid