[Native] Support evaluation of const intrinsics for K2

#KT-56023
#KT-55469 Fixed
This commit is contained in:
Ivan Kylchik
2023-02-03 14:53:15 +01:00
committed by Space Team
parent 5d5582d201
commit e981b1f958
34 changed files with 264 additions and 60 deletions
@@ -417,9 +417,14 @@ class Fir2IrConverter(
companion object {
private fun evaluateConstants(irModuleFragment: IrModuleFragment) {
val firModuleDescriptor = irModuleFragment.descriptor as? FirModuleDescriptor
val languageVersionSettings = firModuleDescriptor?.session?.languageVersionSettings
val intrinsicConstEvaluation = languageVersionSettings?.supportsFeature(LanguageFeature.IntrinsicConstEvaluation) == true
val interpreter = IrInterpreter(irModuleFragment.irBuiltins)
val mode = if (intrinsicConstEvaluation) EvaluationMode.ONLY_INTRINSIC_CONST else EvaluationMode.ONLY_BUILTINS
irModuleFragment.files.forEach {
it.transformChildren(IrConstTransformer(interpreter, it, mode = EvaluationMode.ONLY_BUILTINS), null)
it.transformChildren(IrConstTransformer(interpreter, it, mode = mode), null)
}
}
@@ -19,10 +19,7 @@ import org.jetbrains.kotlin.ir.interpreter.intrinsics.IntrinsicEvaluator
import org.jetbrains.kotlin.ir.interpreter.proxy.wrap
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
import org.jetbrains.kotlin.ir.interpreter.state.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.isArray
import org.jetbrains.kotlin.ir.types.isUnsignedType
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.name.FqName
@@ -91,7 +88,9 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
verify(handleIntrinsicMethods(irConstructor)) { "Unsupported intrinsic constructor: ${irConstructor.render()}" }
}
irClass.defaultType.isUnsignedType() -> {
val propertySymbol = irClass.declarations.single { it is IrProperty }.symbol
// Check for type is a hack needed for Native;
// in UInt, for example, we may have (after lowerings, I guess) additional property "$companion".
val propertySymbol = irClass.declarations.single { it is IrProperty && it.getter?.returnType?.isPrimitiveType() == true }.symbol
callStack.pushState(receiver.apply { this.setField(propertySymbol, args.single()) })
}
else -> defaultAction()
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.util.OperatorNameConventions
class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val bodyMap: Map<IdSignature, IrBody>) {
class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val bodyMap: Map<IdSignature, IrBody> = emptyMap()) {
val irBuiltIns: IrBuiltIns
get() = environment.irBuiltIns
private val callStack: CallStack
@@ -239,7 +239,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
constructor.valueParameters.forEachIndexed { i, param -> callStack.storeState(param.symbol, valueArguments[i]) }
callStack.storeState(constructor.symbol, KTypeState(returnType, environment.kTypeClass.owner))
val superReceiver = when (val irStatement = constructor.body?.statements?.get(0)) {
val superReceiver = when (val irStatement = constructor.body?.statements?.getOrNull(0)) {
null -> null // for jvm
is IrTypeOperatorCall -> (irStatement.argument as IrFunctionAccessExpression).getThisReceiver() // for enums
is IrFunctionAccessExpression -> irStatement.getThisReceiver()
@@ -255,14 +255,38 @@ internal fun interpretBinaryFunction(name: String, typeA: String, typeB: String,
"Comparable" -> if (typeB == "T") return (a as Comparable<Any?>).compareTo(b)
}
"equals" -> when (typeA) {
"Boolean" -> if (typeB == "Any?") return (a as Boolean).equals(b)
"Char" -> if (typeB == "Any?") return (a as Char).equals(b)
"Byte" -> if (typeB == "Any?") return (a as Byte).equals(b)
"Short" -> if (typeB == "Any?") return (a as Short).equals(b)
"Int" -> if (typeB == "Any?") return (a as Int).equals(b)
"Float" -> if (typeB == "Any?") return (a as Float).equals(b)
"Long" -> if (typeB == "Any?") return (a as Long).equals(b)
"Double" -> if (typeB == "Any?") return (a as Double).equals(b)
"Boolean" -> when (typeB) {
"Any?" -> return (a as Boolean).equals(b)
"Boolean" -> return (a as Boolean).equals(b as Boolean)
}
"Char" -> when (typeB) {
"Any?" -> return (a as Char).equals(b)
"Char" -> return (a as Char).equals(b as Char)
}
"Byte" -> when (typeB) {
"Any?" -> return (a as Byte).equals(b)
"Byte" -> return (a as Byte).equals(b as Byte)
}
"Short" -> when (typeB) {
"Any?" -> return (a as Short).equals(b)
"Short" -> return (a as Short).equals(b as Short)
}
"Int" -> when (typeB) {
"Any?" -> return (a as Int).equals(b)
"Int" -> return (a as Int).equals(b as Int)
}
"Float" -> when (typeB) {
"Any?" -> return (a as Float).equals(b)
"Float" -> return (a as Float).equals(b as Float)
}
"Long" -> when (typeB) {
"Any?" -> return (a as Long).equals(b)
"Long" -> return (a as Long).equals(b as Long)
}
"Double" -> when (typeB) {
"Any?" -> return (a as Double).equals(b)
"Double" -> return (a as Double).equals(b as Double)
}
"String" -> if (typeB == "Any?") return (a as String).equals(b)
"Any" -> if (typeB == "Any?") return (a as Any).equals(b)
}
@@ -50,7 +50,10 @@ enum class EvaluationMode(protected val mustCheckBody: Boolean) {
ONLY_BUILTINS(mustCheckBody = false) {
private val forbiddenMethodsOnPrimitives = setOf("inc", "dec", "rangeTo", "rangeUntil", "hashCode")
private val forbiddenMethodsOnStrings = setOf("subSequence", "hashCode", "<init>")
private val allowedExtensionFunctions = setOf("kotlin.floorDiv", "kotlin.mod", "kotlin.NumbersKt.floorDiv", "kotlin.NumbersKt.mod")
private val allowedExtensionFunctions = setOf(
"kotlin.floorDiv", "kotlin.mod", "kotlin.NumbersKt.floorDiv", "kotlin.NumbersKt.mod", "kotlin.<get-code>",
"kotlin.internal.ir.EQEQ",
)
override fun canEvaluateFunction(function: IrFunction, context: IrCall?): Boolean {
if ((function as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.isConst == true) return true
@@ -99,6 +99,13 @@ class IrCompileTimeChecker(
if (mode == EvaluationMode.ONLY_INTRINSIC_CONST && expression.origin == IrStatementOrigin.WHEN) {
return expression.statements.all { it.accept(this, null) }
}
// `IrReturnableBlock` will be created from IrCall after inline. We should do basically the same check as for IrCall.
if (expression is IrReturnableBlock) {
// TODO after JVM inline MR 8122 will be pushed check original IrCall.
TODO("Interpretation of `IrReturnableBlock` is not implemented")
}
return visitStatements(expression.statements)
}
@@ -1,6 +1,3 @@
// KT-55469
// IGNORE_BACKEND_K2: NATIVE
fun equals1(a: Double, b: Double) = a.equals(b)
fun box(): String {
@@ -1,5 +1,3 @@
// KT-55469
// IGNORE_BACKEND_K2: NATIVE
// WITH_STDLIB
fun foo(): Array<Boolean> {
return arrayOf(
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_K2: NATIVE
// WITH_STDLIB
const val a = "INT " + 0x8fffffffU
@@ -1,6 +1,3 @@
// KT-55469
// IGNORE_BACKEND_K2: NATIVE
fun equals1(a: Double, b: Double) = a.equals(b)
fun equals2(a: Double?, b: Double?) = a!!.equals(b!!)
@@ -1,4 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// `Boolean.equals(Boolean)` will not be evaluated in K1
// IGNORE_BACKEND_K1: NATIVE
const val trueVal = true
const val falseVal = false
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_K1: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
const val minusOneVal = (-1).toByte()
const val oneVal = 1.toByte()
@@ -1,4 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// `Char.equals(Char)` will not be evaluated in K1
// IGNORE_BACKEND_K1: NATIVE
// WITH_STDLIB
const val oneVal = '1'
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_K1: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
const val minusOneVal = -1.0
const val oneVal = 1.0
@@ -1,6 +1,6 @@
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_K1: JVM_IR
// IGNORE_FIR_DIAGNOSTICS
// IGNORE_BACKEND_K1: JVM_IR
// !DIAGNOSTICS: -UNINITIALIZED_ENUM_ENTRY
enum class TestEnum(val testNaming: String) {
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_K1: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
const val minusOneVal = -1.0f
const val oneVal = 1.0f
@@ -1,6 +1,7 @@
// !LANGUAGE: +IntrinsicConstEvaluation
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_K1: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
const val flag = true
const val value = 10
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_K1: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
const val minusOneVal = -1
const val oneVal = 1
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_K1: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
const val minusOneVal = -1L
const val oneVal = 1L
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_K1: JVM_IR
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND_K1: JVM_IR, NATIVE
const val minusOneVal = (-1).toShort()
const val oneVal = 1.toShort()
@@ -1,4 +1,5 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// WITH_STDLIB
const val code = '1'.code
@@ -1,4 +1,5 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
const val someStr = "123"
const val otherStr = "other"
@@ -1,4 +1,5 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// WITH_STDLIB
const val byteVal: UByte = 1u
@@ -1,4 +1,5 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
object K : Code("K")
@@ -1,4 +1,5 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// WITH_STDLIB
object Test {
@@ -1,6 +1,4 @@
// KT-3517 Can't call .equals() on a boolean
// KT-55469
// IGNORE_BACKEND_K2: NATIVE
fun box(): String {
val a = false
@@ -1,8 +1,3 @@
// KT-56023
// JS_IR: InterpreterError: Unsupported number of arguments for invocation as builtin function: four
// NATIVE: in mode -Pkotlin.internal.native.test.mode=TWO_STAGE_MULTI_MODULE (default test mode), test fails as below
// InterpreterError: Unsupported number of arguments for invocation as builtin function: four
// in mode -Pkotlin.internal.native.test.mode=ONE_STAGE_MULTI_MODULE, test passes
// IGNORE_BACKEND_K2: NATIVE, JS_IR
// MODULE: lib
@@ -1,7 +1,3 @@
// KT-56023
// JS_IR: IllegalStateException: CONST_VAL_WITH_NON_CONST_INITIALIZER: Const 'val' initializer should be a constant value at (7,18) in /lib.kt
// NATIVE: test fails as below in both modes -Pkotlin.internal.native.test.mode=TWO_STAGE_MULTI_MODULE, -Pkotlin.internal.native.test.mode=ONE_STAGE_MULTI_MODULE
// error: const 'val' initializer should be a constant value
// IGNORE_BACKEND_K2: NATIVE, JS_IR
// MODULE: lib
@@ -61,7 +61,10 @@ fun generateMap(): String {
this += Operation("toString", listOf("Unit"), customExpression = "Unit.toString()")
})
generateInterpretBinaryFunction(p, getOperationMap(2) + getBinaryIrOperationMap(irBuiltIns) + getExtensionOperationMap())
generateInterpretBinaryFunction(
p,
getOperationMap(2) + getBinaryIrOperationMap(irBuiltIns) + getExtensionOperationMap() + getAdditionalEqualsOperationMap()
)
generateInterpretTernaryFunction(p, getOperationMap(3))
@@ -274,6 +277,16 @@ private fun getExtensionOperationMap(): List<Operation> {
return operationMap
}
// We need this additional list to properly interpret functions like `Boolean.equals(Boolean) in Native`
// Probably can be dropped after KT-57344 fix
private fun getAdditionalEqualsOperationMap(): List<Operation> {
val builtIns = DefaultBuiltIns.Instance
return PrimitiveType.values().map { builtIns.getBuiltInClassByFqName(it.typeFqName) }.map {
val type = it.defaultType.constructor.toString()
Operation("equals", listOf(type, type), isFunction = true)
}
}
private fun getIrMethodSymbolByName(methodName: String): String {
return when (methodName) {
BuiltInOperatorNames.LESS -> "<"
@@ -1420,8 +1420,7 @@ task localClass_localHierarchy(type: KonanLocalTest) {
}
standaloneTest("objectDeclaration_globalConstants") {
disabled = (cacheTesting != null) || // Cache is not compatible with -opt.
isK2(project) // KT-56189
disabled = (cacheTesting != null) // Cache is not compatible with -opt.
flags = ["-opt", "-opt-in=kotlin.native.internal.InternalForKotlinNative", "-tr"]
source = "codegen/objectDeclaration/globalConstants.kt"
}
@@ -2846,7 +2845,6 @@ standaloneTest("runtime_math_exceptions") {
}
standaloneTest("runtime_math") {
disabled = isK2(project) // KT-56189
source = "stdlib_external/numbers/MathTest.kt"
flags = ['-tr']
}
@@ -3095,7 +3093,6 @@ task concatenation(type: KonanLocalTest) {
}
task const_infinity(type: KonanLocalTest) {
disabled = isK2(project) // KT-56189
source = "codegen/basics/const_infinity.kt"
}
@@ -3217,7 +3214,6 @@ task initializers3(type: KonanLocalTest) {
}
task initializers4(type: KonanLocalTest) {
disabled = isK2(project) // KT-56189
useGoldenData = true
source = "runtime/basic/initializers4.kt"
}
@@ -6147,10 +6143,6 @@ task buildKonanTests { t ->
// These tests should not be built into the TestRunner's test executable
def excludeList = [ "codegen/inline/returnLocalClassFromBlock.kt" ]
if (isK2(project)) {
excludeList += "codegen/basics/const_infinity.kt" // KT-56189
excludeList += "runtime/basic/initializers4.kt" // KT-56189
}
project.tasks
.withType(KonanStandaloneTest.class)
.each {
@@ -1,5 +1,3 @@
// KT-56189 -3.14 is not constant
// MUTED_WHEN: K2
package test
annotation class PrimitiveArrays(
@@ -1,6 +1,3 @@
// KT-56189 error: an annotation argument must be a compile-time constant
// -3.14 is not constant
// MUTED_WHEN: K2
package test
annotation class Primitives(
@@ -24247,6 +24247,18 @@ public class FirNativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTe
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")
@@ -24259,6 +24271,78 @@ public class FirNativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTe
public void testAllFilesPresentInDumpIrAndCheck() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, 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");
}
}
}
@@ -24013,6 +24013,18 @@ public class K1NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTes
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")
@@ -24024,6 +24036,78 @@ public class K1NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTes
public void testAllFilesPresentInDumpIrAndCheck() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/involvesIrInterpreter/dumpIrAndCheck"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, 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");
}
}
}