[JS] Support evaluation of const intrinsics for K2

#KT-56023 Fixed
#KT-51582 Fixed
This commit is contained in:
Ivan Kylchik
2023-02-08 14:40:58 +01:00
committed by Space Team
parent e981b1f958
commit 7cf9dda8dc
36 changed files with 413 additions and 40 deletions
@@ -30,11 +30,14 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
import org.jetbrains.kotlin.ir.interpreter.checker.IrConstTransformer
import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.platform.isJs
import org.jetbrains.kotlin.psi.KtFile
class Fir2IrConverter(
@@ -418,10 +421,15 @@ class Fir2IrConverter(
companion object {
private fun evaluateConstants(irModuleFragment: IrModuleFragment) {
val firModuleDescriptor = irModuleFragment.descriptor as? FirModuleDescriptor
val targetPlatform = firModuleDescriptor?.platform
val languageVersionSettings = firModuleDescriptor?.session?.languageVersionSettings
val intrinsicConstEvaluation = languageVersionSettings?.supportsFeature(LanguageFeature.IntrinsicConstEvaluation) == true
val interpreter = IrInterpreter(irModuleFragment.irBuiltins)
val configuration = IrInterpreterConfiguration(
printOnlyExceptionMessage = targetPlatform.isJs(),
treatFloatInSpecialWay = targetPlatform.isJs()
)
val interpreter = IrInterpreter(IrInterpreterEnvironment(irModuleFragment.irBuiltins, configuration))
val mode = if (intrinsicConstEvaluation) EvaluationMode.ONLY_INTRINSIC_CONST else EvaluationMode.ONLY_BUILTINS
irModuleFragment.files.forEach {
it.transformChildren(IrConstTransformer(interpreter, it, mode = mode), null)
@@ -20,10 +20,10 @@ import org.jetbrains.kotlin.ir.interpreter.checker.IrConstTransformer
class ConstEvaluationLowering(
val context: CommonBackendContext,
private val suppressErrors: Boolean = context.configuration.getBoolean(CommonConfigurationKeys.IGNORE_CONST_OPTIMIZATION_ERRORS),
configuration: IrInterpreterConfiguration = IrInterpreterConfiguration(printOnlyExceptionMessage = true),
private val onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
private val onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
) : FileLoweringPass {
val configuration = IrInterpreterConfiguration(printOnlyExceptionMessage = true)
val interpreter = IrInterpreter(IrInterpreterEnvironment(context.irBuiltIns, configuration), emptyMap())
override fun lower(irFile: IrFile) {
@@ -151,13 +151,21 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
}
val receiverType = irFunction.dispatchReceiverParameter?.type ?: irFunction.extensionReceiverParameter?.type
val argsType = listOfNotNull(receiverType) + irFunction.valueParameters.map { it.type }
val argsType = (listOfNotNull(receiverType) + irFunction.valueParameters.map { it.type }).map {
// TODO: for consistency with current K/JS implementation Float constant should be treated as a Double (KT-35422)
if (environment.configuration.treatFloatInSpecialWay && it.isFloat()) irBuiltIns.doubleType else it
}
val argsValues = args.wrap(this, irFunction)
// TODO replace unary, binary, ternary functions with vararg
withExceptionHandler(environment) {
val result = when (argsType.size) {
1 -> interpretUnaryFunction(methodName, argsType[0].getOnlyName(), argsValues[0])
1 -> when {
methodName == "toString" && environment.configuration.treatFloatInSpecialWay && (argsValues[0] is Double || argsValues[0] is Float) -> {
argsValues[0].specialToStringForJs()
}
else -> interpretUnaryFunction(methodName, argsType[0].getOnlyName(), argsValues[0])
}
2 -> when (methodName) {
"rangeTo" -> return calculateRangeTo(irFunction.returnType, args)
else -> interpretBinaryFunction(
@@ -8,8 +8,10 @@ package org.jetbrains.kotlin.ir.interpreter
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterError
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
import org.jetbrains.kotlin.ir.interpreter.exceptions.verify
@@ -112,6 +114,19 @@ private fun unfoldConstructor(constructor: IrConstructor, callStack: CallStack)
private fun unfoldValueParameters(expression: IrFunctionAccessExpression, environment: IrInterpreterEnvironment) {
val callStack = environment.callStack
val irFunction = expression.symbol.owner
if (irFunction.name.asString() == "<get-name>" && expression.dispatchReceiver is IrGetEnumValue) {
// this optimization allow us to avoid creation of enum object when we try to interpret simple `name` call; see KT-53480
callStack.pushSimpleInstruction(expression)
callStack.pushSimpleInstruction(irFunction.dispatchReceiverParameter!!)
val enumEntry = (expression.dispatchReceiver as IrGetEnumValue).symbol.owner
callStack.pushState(enumEntry.toState(environment.irBuiltIns))
return
}
// TODO do the same thing but for "KCallable.name" with "this" as receiver
val hasDefaults = (0 until expression.valueArgumentsCount).any { expression.getValueArgument(it) == null }
if (hasDefaults) {
environment.getCachedFunction(expression.symbol, fromDelegatingCall = expression is IrDelegatingConstructorCall)?.let {
@@ -166,7 +181,6 @@ private fun unfoldValueParameters(expression: IrFunctionAccessExpression, enviro
).owner.createCall().apply { environment.irBuiltIns.copyArgs(expression, this) }
callStack.pushCompoundInstruction(callToDefault)
} else {
val irFunction = expression.symbol.owner
callStack.pushSimpleInstruction(expression)
fun IrValueParameter.schedule(arg: IrExpression?) {
@@ -277,14 +291,6 @@ private fun unfoldGetEnumValue(expression: IrGetEnumValue, environment: IrInterp
val callStack = environment.callStack
environment.mapOfEnums[expression.symbol]?.let { return callStack.pushState(it) }
val frameOwner = callStack.currentFrameOwner
if (frameOwner is IrCall && frameOwner.dispatchReceiver is IrGetEnumValue && frameOwner.symbol.owner.name.asString() == "<get-name>") {
// this optimization allow us to avoid creation of enum object when we try to interpret simple `name` call; see KT-53480
val enumEntry = (frameOwner.dispatchReceiver as IrGetEnumValue).symbol.owner
callStack.pushState(enumEntry.toState(environment.irBuiltIns))
return
}
callStack.pushSimpleInstruction(expression)
val enumEntry = expression.symbol.owner
val enumClass = enumEntry.symbol.owner.parentAsClass
@@ -389,6 +395,13 @@ private fun unfoldStringConcatenation(expression: IrStringConcatenation, environ
// this callback is used to check the need for an explicit toString call
val explicitToStringCheck = fun() {
when (val state = callStack.peekState()) {
is Primitive<*> -> {
// This block is not really needed, but this way it is easier to handle `toString` with `treatFloatInSpecialWay` enabled.
callStack.popState()
val toStringCall = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, environment.irBuiltIns.memberToString)
callStack.pushSimpleInstruction(toStringCall)
callStack.pushState(state)
}
is Common -> {
callStack.popState()
// TODO this check can be dropped after serialization introduction
@@ -293,6 +293,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
return callStack.pushCompoundInstruction(constructorCall)
}
callStack.pushState(expression.toPrimitive())
}
@@ -11,12 +11,14 @@ package org.jetbrains.kotlin.ir.interpreter
* @param createNonCompileTimeObjects
* 'true' - interpreter will construct object and initialize its properties despite the fact it is not marked as compile time;
* 'false' - interpreter will create a representation of empty object, that can be used to get const properties
* @param treatFloatInSpecialWay interpret float const as if it was a double and avoid `toFloat` evaluation if possible
*/
// TODO maybe create some sort of builder
class IrInterpreterConfiguration(
data class IrInterpreterConfiguration(
val maxStack: Int = 10_000,
val maxCommands: Int = 1_000_000,
val createNonCompileTimeObjects: Boolean = false,
val printOnlyExceptionMessage: Boolean = false,
val collapseStackTraceFromJDK: Boolean = true,
val treatFloatInSpecialWay: Boolean = false,
)
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
@@ -118,8 +119,9 @@ class IrInterpreterEnvironment(
return when (state) {
is Primitive<*> ->
when {
state.value == null -> state.value.toIrConst(type, start, end)
type.isPrimitiveType() || type.isString() -> state.value.toIrConst(type, start, end)
configuration.treatFloatInSpecialWay && state.value is Float -> IrConstImpl.float(start, end, type, state.value)
configuration.treatFloatInSpecialWay && state.value is Double -> IrConstImpl.double(start, end, type, state.value)
state.value == null || type.isPrimitiveType() || type.isString() -> state.value.toIrConst(type, start, end)
else -> original // TODO support for arrays
}
is ExceptionState -> {
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
import org.jetbrains.kotlin.utils.keysToMap
import java.lang.invoke.MethodType
import kotlin.math.floor
val intrinsicConstEvaluationAnnotation = FqName("kotlin.internal.IntrinsicConstEvaluation")
val compileTimeAnnotation = FqName("kotlin.CompileTimeCalculation")
@@ -131,7 +132,9 @@ fun IrFunctionAccessExpression.getVarargType(index: Int): IrType? {
}
}
internal fun IrFunction.getCapitalizedFileName() = this.file.name.replace(".kt", "Kt").capitalizeAsciiOnly()
internal fun IrFunction.getCapitalizedFileName(): String {
return this.fileOrNull?.name?.replace(".kt", "Kt")?.capitalizeAsciiOnly() ?: "<UNKNOWN>"
}
internal fun IrClass.isSubclassOfThrowable(): Boolean {
return generateSequence(this) { irClass ->
@@ -314,6 +317,14 @@ internal fun State.unsignedToString(): String {
}
}
internal fun Any?.specialToStringForJs(): String {
return when {
this is Float && !this.isInfinite() && floor(this) == this -> this.toInt().toString()
this is Double && !this.isInfinite() && floor(this) == this -> this.toLong().toString()
else -> this.toString()
}
}
internal fun IrEnumEntry.toState(irBuiltIns: IrBuiltIns): Common {
val enumClass = this.symbol.owner.parentAsClass
val enumEntries = enumClass.declarations.filterIsInstance<IrEnumEntry>()
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
import org.jetbrains.kotlin.ir.interpreter.accessesTopLevelOrObjectField
import org.jetbrains.kotlin.ir.interpreter.fqName
import org.jetbrains.kotlin.ir.interpreter.isAccessToNotNullableObject
@@ -18,7 +19,9 @@ import org.jetbrains.kotlin.ir.util.statements
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
class IrCompileTimeChecker(
containingDeclaration: IrElement? = null, private val mode: EvaluationMode = EvaluationMode.WITH_ANNOTATIONS
containingDeclaration: IrElement? = null,
private val mode: EvaluationMode = EvaluationMode.WITH_ANNOTATIONS,
private val interpreterConfiguration: IrInterpreterConfiguration,
) : IrElementVisitor<Boolean, Nothing?> {
private var contextExpression: IrCall? = null
private val visitedStack = mutableListOf<IrElement>().apply { if (containingDeclaration != null) add(containingDeclaration) }
@@ -67,6 +70,13 @@ class IrCompileTimeChecker(
val owner = expression.symbol.owner
if (!mode.canEvaluateFunction(owner, expression)) return false
// We disable `toFloat` folding on K/JS till `toFloat` is fixed (KT-35422)
// This check must be placed here instead of CallInterceptor because we still
// want to evaluate (1) `const val` expressions and (2) values in annotations.
if (owner.name.asString() == "toFloat" && interpreterConfiguration.treatFloatInSpecialWay) {
return super.visitCall(expression, data)
}
return expression.saveContext {
val dispatchReceiverComputable = expression.dispatchReceiver?.accept(this, null) ?: true
val extensionReceiverComputable = expression.extensionReceiver?.accept(this, null) ?: true
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
import org.jetbrains.kotlin.ir.interpreter.isPrimitiveArray
import org.jetbrains.kotlin.ir.interpreter.toIrConst
import org.jetbrains.kotlin.ir.types.*
@@ -49,9 +50,12 @@ class IrConstTransformer(
return this
}
private fun IrExpression.canBeInterpreted(containingDeclaration: IrElement? = null): Boolean {
private fun IrExpression.canBeInterpreted(
containingDeclaration: IrElement? = null,
configuration: IrInterpreterConfiguration = interpreter.environment.configuration
): Boolean {
return try {
this.accept(IrCompileTimeChecker(containingDeclaration, mode = mode), null)
this.accept(IrCompileTimeChecker(containingDeclaration, mode, configuration), null)
} catch (e: Throwable) {
if (suppressExceptions) {
return false
@@ -87,7 +91,9 @@ class IrConstTransformer(
val expression = initializer?.expression ?: return declaration
if (expression is IrConst<*>) return declaration
val isConst = declaration.correspondingPropertySymbol?.owner?.isConst == true
if (isConst && expression.canBeInterpreted(declaration)) {
if (!isConst) return super.visitField(declaration)
if (expression.canBeInterpreted(declaration, interpreter.environment.configuration.copy(treatFloatInSpecialWay = false))) {
initializer.expression = expression.interpret(failAsError = true)
}
@@ -129,7 +135,7 @@ class IrConstTransformer(
}
private fun IrExpression.transformSingleArg(expectedType: IrType): IrExpression {
if (this.canBeInterpreted()) {
if (this.canBeInterpreted(configuration = interpreter.environment.configuration.copy(treatFloatInSpecialWay = false))) {
return this.interpret(failAsError = true).convertToConstIfPossible(expectedType)
} else if (this is IrConstructorCall) {
transformAnnotation(this)
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.ReflectionProxy.Comp
import org.jetbrains.kotlin.ir.interpreter.state.*
import org.jetbrains.kotlin.ir.interpreter.state.reflection.ReflectionState
import org.jetbrains.kotlin.ir.types.isArray
import org.jetbrains.kotlin.ir.types.isFloat
import java.lang.invoke.MethodType
internal interface Proxy {
@@ -34,6 +35,8 @@ internal fun State.wrap(callInterceptor: CallInterceptor, remainArraysAsIs: Bool
is Primitive<*> -> when {
this.isNull() -> null
this.type.isArray() || this.type.isPrimitiveArray() -> if (remainArraysAsIs) this else this.value
// TODO: for consistency with current K/JS implementation Float constant should be treated as a Double (KT-35422)
this.type.isFloat() && callInterceptor.environment.configuration.treatFloatInSpecialWay -> this.value.toString().toDouble()
else -> this.value
}
is Common -> this.asProxy(callInterceptor, extendFrom)
+2 -2
View File
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// IGNORE_BACKEND_K1: JS_IR
// IGNORE_BACKEND_K1: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_K2: JS_IR, NATIVE
// WITH_STDLIB
import kotlin.math.*
-1
View File
@@ -1,6 +1,5 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K2: JS_IR
fun box(): String {
if (239.toByte().toString() != (239.toByte() as Byte?).toString()) return "byte failed"
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
// `Boolean.equals(Boolean)` will not be evaluated in K1
// IGNORE_BACKEND_K1: NATIVE
@@ -1,6 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
const val minusOneVal = (-1).toByte()
const val oneVal = 1.toByte()
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
// `Char.equals(Char)` will not be evaluated in K1
// IGNORE_BACKEND_K1: NATIVE
// WITH_STDLIB
@@ -1,12 +1,14 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
const val minusOneVal = -1.0
const val oneVal = 1.0
const val twoVal = 2.0
const val threeVal = 3.0
const val fourVal = 4.0
const val oneAndAHalf = 1.5
const val byteVal = 2.toByte()
const val shortVal = 2.toShort()
@@ -87,6 +89,7 @@ const val equals4 = fourVal == twoVal
const val toString1 = oneVal.toString()
const val toString2 = twoVal.toString()
const val toString3 = oneAndAHalf.toString()
fun box(): String {
if (compareTo1 != -1) return "Fail 1.1"
@@ -159,8 +162,9 @@ fun box(): String {
if (equals3 != false) return "Fail 9.3"
if (equals4 != false) return "Fail 9.4"
if (toString1 != "1.0") return "Fail 10.1"
if (toString2 != "2.0") return "Fail 10.2"
if (toString1 != "1.0" && toString1 != "1" /* JS */) return "Fail 10.1"
if (toString2 != "2.0" && toString2 != "2" /* JS */) return "Fail 10.2"
if (toString3 != "1.5") return "Fail 10.3"
return "OK"
}
@@ -12,8 +12,9 @@ const val name3 = EnumClass.anotherValue.name
const val name4 = EnumClass.WITH_UNDERSCORE.name
fun box(): String {
if (name2 != "VALUE") return "Fail 1"
if (name3 != "anotherValue") return "Fail 2"
if (name4 != "WITH_UNDERSCORE") return "Fail 3"
if (EnumClass.OK.name != "OK") return "Fail 1"
if (name2 != "VALUE") return "Fail 2"
if (name3 != "anotherValue") return "Fail 3"
if (name4 != "WITH_UNDERSCORE") return "Fail 4"
return name1
}
@@ -1,12 +1,14 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
const val minusOneVal = -1.0f
const val oneVal = 1.0f
const val twoVal = 2.0f
const val threeVal = 3.0f
const val fourVal = 4.0f
const val oneAndAHalf = 1.5f
const val byteVal = 2.toByte()
const val shortVal = 2.toShort()
@@ -87,6 +89,7 @@ const val equals4 = fourVal == twoVal
const val toString1 = oneVal.toString()
const val toString2 = twoVal.toString()
const val toString3 = oneAndAHalf.toString()
fun box(): String {
if (compareTo1 != -1) return "Fail 1.1"
@@ -159,8 +162,9 @@ fun box(): String {
if (equals3 != false) return "Fail 9.3"
if (equals4 != false) return "Fail 9.4"
if (toString1 != "1.0") return "Fail 10.1"
if (toString2 != "2.0") return "Fail 10.2"
if (toString1 != "1.0" && toString1 != "1" /* JS */) return "Fail 10.1"
if (toString2 != "2.0" && toString2 != "2" /* JS */) return "Fail 10.2"
if (toString3 != "1.5") return "Fail 10.3"
return "OK"
}
@@ -1,7 +1,8 @@
// !LANGUAGE: +IntrinsicConstEvaluation
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
const val flag = true
const val value = 10
@@ -1,6 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
const val minusOneVal = -1
const val oneVal = 1
@@ -1,6 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
const val minusOneVal = -1L
const val oneVal = 1L
@@ -1,6 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
const val minusOneVal = (-1).toShort()
const val oneVal = 1.toShort()
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
// WITH_STDLIB
const val code = '1'.code
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
const val someStr = "123"
const val otherStr = "other"
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
// WITH_STDLIB
const val byteVal: UByte = 1u
@@ -0,0 +1,10 @@
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JS_IR, JS_IR_ES6
const val toStringInConst = 1.0.toString()
fun box(): String {
if (toStringInConst != "1") return "Fail 1"
if (1.0.toString() != toStringInConst) return "Fail 2"
return "OK"
}
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
object K : Code("K")
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
// WITH_STDLIB
object Test {
+8
View File
@@ -23,3 +23,11 @@ const val f1 = <!EVALUATED: `2`!>enumValues<EnumClass>().size<!>
const val f2 = <!EVALUATED: `VALUE1`!>enumValueOf<EnumClass>("VALUE1").name<!>
const val j1 = <!EVALUATED: `VALUE1, VALUE2`!>enumValues<EnumClass>().joinToString { it.name }<!>
@CompileTimeCalculation
fun getEnumValue(flag: Boolean): EnumClass {
return if (flag) EnumClass.VALUE1 else EnumClass.VALUE2
}
const val conditional1 = <!EVALUATED: `VALUE1`!>getEnumValue(true).name<!>
const val conditional2 = <!EVALUATED: `VALUE2`!>getEnumValue(false).name<!>
+1
View File
@@ -1,4 +1,5 @@
// FIR_IDENTICAL
// IGNORE_BACKEND_K2: JS_IR
val test1 = 1
val test2 = -1
val test3 = true
@@ -21043,6 +21043,12 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@Test
@TestMetadata("jsIrToConst.kt")
public void testJsIrToConst() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/jsIrToConst.kt");
}
@Test
@TestMetadata("kt55912.kt")
public void testKt55912() throws Exception {
@@ -21055,6 +21061,18 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt56215.kt");
}
@Test
@TestMetadata("stringConcatenationWithObject.kt")
public void testStringConcatenationWithObject() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/stringConcatenationWithObject.kt");
}
@Test
@TestMetadata("thisPlusString.kt")
public void testThisPlusString() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/thisPlusString.kt");
}
@Nested
@TestMetadata("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck")
@TestDataPath("$PROJECT_ROOT")
@@ -21063,6 +21081,78 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
public void testAllFilesPresentInDumpIrAndCheck() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@Test
@TestMetadata("booleanOperations.kt")
public void testBooleanOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/booleanOperations.kt");
}
@Test
@TestMetadata("byteOperations.kt")
public void testByteOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/byteOperations.kt");
}
@Test
@TestMetadata("charOperations.kt")
public void testCharOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/charOperations.kt");
}
@Test
@TestMetadata("doubleOperations.kt")
public void testDoubleOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/doubleOperations.kt");
}
@Test
@TestMetadata("floatOperations.kt")
public void testFloatOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/floatOperations.kt");
}
@Test
@TestMetadata("ifConstVal.kt")
public void testIfConstVal() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/ifConstVal.kt");
}
@Test
@TestMetadata("intOperations.kt")
public void testIntOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/intOperations.kt");
}
@Test
@TestMetadata("longOperations.kt")
public void testLongOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/longOperations.kt");
}
@Test
@TestMetadata("shortOperations.kt")
public void testShortOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/shortOperations.kt");
}
@Test
@TestMetadata("stdlibConst.kt")
public void testStdlibConst() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/stdlibConst.kt");
}
@Test
@TestMetadata("stringOperations.kt")
public void testStringOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/stringOperations.kt");
}
@Test
@TestMetadata("unsignedConst.kt")
public void testUnsignedConst() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/unsignedConst.kt");
}
}
}
@@ -21043,6 +21043,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@Test
@TestMetadata("jsIrToConst.kt")
public void testJsIrToConst() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/jsIrToConst.kt");
}
@Test
@TestMetadata("kt55912.kt")
public void testKt55912() throws Exception {
@@ -21055,6 +21061,18 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt56215.kt");
}
@Test
@TestMetadata("stringConcatenationWithObject.kt")
public void testStringConcatenationWithObject() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/stringConcatenationWithObject.kt");
}
@Test
@TestMetadata("thisPlusString.kt")
public void testThisPlusString() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/thisPlusString.kt");
}
@Nested
@TestMetadata("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck")
@TestDataPath("$PROJECT_ROOT")
@@ -21063,6 +21081,78 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
public void testAllFilesPresentInDumpIrAndCheck() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@Test
@TestMetadata("booleanOperations.kt")
public void testBooleanOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/booleanOperations.kt");
}
@Test
@TestMetadata("byteOperations.kt")
public void testByteOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/byteOperations.kt");
}
@Test
@TestMetadata("charOperations.kt")
public void testCharOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/charOperations.kt");
}
@Test
@TestMetadata("doubleOperations.kt")
public void testDoubleOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/doubleOperations.kt");
}
@Test
@TestMetadata("floatOperations.kt")
public void testFloatOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/floatOperations.kt");
}
@Test
@TestMetadata("ifConstVal.kt")
public void testIfConstVal() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/ifConstVal.kt");
}
@Test
@TestMetadata("intOperations.kt")
public void testIntOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/intOperations.kt");
}
@Test
@TestMetadata("longOperations.kt")
public void testLongOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/longOperations.kt");
}
@Test
@TestMetadata("shortOperations.kt")
public void testShortOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/shortOperations.kt");
}
@Test
@TestMetadata("stdlibConst.kt")
public void testStdlibConst() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/stdlibConst.kt");
}
@Test
@TestMetadata("stringOperations.kt")
public void testStringOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/stringOperations.kt");
}
@Test
@TestMetadata("unsignedConst.kt")
public void testUnsignedConst() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/unsignedConst.kt");
}
}
}
@@ -21043,6 +21043,12 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
@Test
@TestMetadata("jsIrToConst.kt")
public void testJsIrToConst() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/jsIrToConst.kt");
}
@Test
@TestMetadata("kt55912.kt")
public void testKt55912() throws Exception {
@@ -21055,6 +21061,18 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt56215.kt");
}
@Test
@TestMetadata("stringConcatenationWithObject.kt")
public void testStringConcatenationWithObject() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/stringConcatenationWithObject.kt");
}
@Test
@TestMetadata("thisPlusString.kt")
public void testThisPlusString() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/thisPlusString.kt");
}
@Nested
@TestMetadata("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck")
@TestDataPath("$PROJECT_ROOT")
@@ -21063,6 +21081,78 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
public void testAllFilesPresentInDumpIrAndCheck() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
@Test
@TestMetadata("booleanOperations.kt")
public void testBooleanOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/booleanOperations.kt");
}
@Test
@TestMetadata("byteOperations.kt")
public void testByteOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/byteOperations.kt");
}
@Test
@TestMetadata("charOperations.kt")
public void testCharOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/charOperations.kt");
}
@Test
@TestMetadata("doubleOperations.kt")
public void testDoubleOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/doubleOperations.kt");
}
@Test
@TestMetadata("floatOperations.kt")
public void testFloatOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/floatOperations.kt");
}
@Test
@TestMetadata("ifConstVal.kt")
public void testIfConstVal() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/ifConstVal.kt");
}
@Test
@TestMetadata("intOperations.kt")
public void testIntOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/intOperations.kt");
}
@Test
@TestMetadata("longOperations.kt")
public void testLongOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/longOperations.kt");
}
@Test
@TestMetadata("shortOperations.kt")
public void testShortOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/shortOperations.kt");
}
@Test
@TestMetadata("stdlibConst.kt")
public void testStdlibConst() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/stdlibConst.kt");
}
@Test
@TestMetadata("stringOperations.kt")
public void testStringOperations() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/stringOperations.kt");
}
@Test
@TestMetadata("unsignedConst.kt")
public void testUnsignedConst() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck/unsignedConst.kt");
}
}
}
+1
View File
@@ -1,3 +1,4 @@
// IGNORE_BACKEND_K2: JS_IR
// KJS_WITH_FULL_RUNTIME
// EXPECTED_REACHABLE_NODES: 1378
package foo