JVM_IR KT-43721 coerce intrinsic result to corresponding unsigned type

This commit is contained in:
Dmitry Petrov
2020-12-03 14:15:04 +03:00
parent c776fcbd00
commit caea0a9df0
17 changed files with 403 additions and 4 deletions
@@ -32308,6 +32308,59 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
@TestMetadata("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Jvm8Intrinsics extends AbstractFirBlackBoxCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTestWithCustomIgnoreDirective(this::doTest, TargetBackend.JVM_IR, testDataFilePath, "// IGNORE_BACKEND_FIR: ");
}
public void testAllFilesPresentInJvm8Intrinsics() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("unsignedIntCompare_jvm8.kt")
public void testUnsignedIntCompare_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntCompare_jvm8.kt");
}
@TestMetadata("unsignedIntDivide_jvm8.kt")
public void testUnsignedIntDivide_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntDivide_jvm8.kt");
}
@TestMetadata("unsignedIntRemainder_jvm8.kt")
public void testUnsignedIntRemainder_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntRemainder_jvm8.kt");
}
@TestMetadata("unsignedIntToString_jvm8.kt")
public void testUnsignedIntToString_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntToString_jvm8.kt");
}
@TestMetadata("unsignedLongCompare_jvm8.kt")
public void testUnsignedLongCompare_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongCompare_jvm8.kt");
}
@TestMetadata("unsignedLongDivide_jvm8.kt")
public void testUnsignedLongDivide_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongDivide_jvm8.kt");
}
@TestMetadata("unsignedLongRemainder_jvm8.kt")
public void testUnsignedLongRemainder_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongRemainder_jvm8.kt");
}
@TestMetadata("unsignedLongToString_jvm8.kt")
public void testUnsignedLongToString_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongToString_jvm8.kt");
}
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")
@@ -14,8 +14,9 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
internal val jvmStandardLibraryBuiltInsPhase = makeIrFilePhase(
@@ -60,11 +61,14 @@ class JvmStandardLibraryBuiltInsLowering(val context: JvmBackendContext) : FileL
// Originals are so far only instance methods, and the replacements are
// statics, so we copy dispatch receivers to a value argument if needed.
// If we can't coerce arguments to required types, keep original expression (see below).
private fun IrCall.replaceWithCallTo(replacement: IrSimpleFunctionSymbol): IrCall =
IrCallImpl.fromSymbolOwner(
private fun IrCall.replaceWithCallTo(replacement: IrSimpleFunctionSymbol): IrExpression {
val expectedType = this.type
val intrinsicCallType = replacement.owner.returnType
val intrinsicCall = IrCallImpl.fromSymbolOwner(
startOffset,
endOffset,
type,
intrinsicCallType,
replacement
).also { newCall ->
var valueArgumentOffset = 0
@@ -81,6 +85,15 @@ class JvmStandardLibraryBuiltInsLowering(val context: JvmBackendContext) : FileL
}
}
// Coerce intrinsic call result from JVM 'int' or 'long' to corresponding unsigned type if required.
return if (intrinsicCallType.isInt() || intrinsicCallType.isLong()) {
intrinsicCall.coerceIfPossible(expectedType)
?: throw AssertionError("Can't coerce '${intrinsicCallType.render()}' to '${expectedType.render()}'")
} else {
intrinsicCall
}
}
private fun IrExpression.coerceIfPossible(toType: IrType): IrExpression? {
// TODO maybe UnsafeCoerce could handle types with different, but coercible underlying representations.
// See KT-43286 and related tests for details.
@@ -0,0 +1,14 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// JVM_TARGET: 1.8
val ua = 1234U
val ub = 5678U
fun box(): String {
if (ua.compareTo(ub) > 0) {
throw AssertionError()
}
return "OK"
}
@@ -0,0 +1,14 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// JVM_TARGET: 1.8
val ua = 1234U
val ub = 5678U
val u = ua * ub
fun box(): String {
val div = u / ua
if (div != ub) throw AssertionError("$div")
return "OK"
}
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// JVM_TARGET: 1.8
val ua = 1234U
val ub = 5678U
val uc = 3456U
val u = ua * ub + uc
fun box(): String {
val rem = u % ub
if (rem != uc) throw AssertionError("$rem")
return "OK"
}
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// JVM_TARGET: 1.8
fun box(): String {
val min = 0U.toString()
if ("0" != min) throw AssertionError(min)
val middle = 2_147_483_647U.toString()
if ("2147483647" != middle) throw AssertionError(middle)
val max = 4_294_967_295U.toString()
if ("4294967295" != max) throw AssertionError(max)
return "OK"
}
@@ -0,0 +1,14 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// JVM_TARGET: 1.8
val ua = 1234UL
val ub = 5678UL
fun box(): String {
if (ua.compareTo(ub) > 0) {
throw AssertionError()
}
return "OK"
}
@@ -0,0 +1,18 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// JVM_TARGET: 1.8
val ua = 1234UL
val ub = 5678UL
val uai = ua.toUInt()
val u = ua * ub
fun box(): String {
val div = u / ua
if (div != ub) throw AssertionError("$div")
val divInt = u / uai
if (div != ub) throw AssertionError("$div")
return "OK"
}
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// JVM_TARGET: 1.8
val ua = 1234UL
val ub = 5678UL
val uc = 3456UL
val u = ua * ub + uc
fun box(): String {
val rem = u % ub
if (rem != uc) throw AssertionError("$rem")
return "OK"
}
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// JVM_TARGET: 1.8
fun box(): String {
val min = 0UL.toString()
if ("0" != min) throw AssertionError(min)
val middle = 9_223_372_036_854_775_807UL.toString()
if ("9223372036854775807" != middle) throw AssertionError(middle)
val max = 18_446_744_073_709_551_615UL.toString()
if ("18446744073709551615" != max) throw AssertionError(max)
return "OK"
}
@@ -34079,6 +34079,59 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
@TestMetadata("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Jvm8Intrinsics extends AbstractBlackBoxCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInJvm8Intrinsics() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("unsignedIntCompare_jvm8.kt")
public void testUnsignedIntCompare_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntCompare_jvm8.kt");
}
@TestMetadata("unsignedIntDivide_jvm8.kt")
public void testUnsignedIntDivide_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntDivide_jvm8.kt");
}
@TestMetadata("unsignedIntRemainder_jvm8.kt")
public void testUnsignedIntRemainder_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntRemainder_jvm8.kt");
}
@TestMetadata("unsignedIntToString_jvm8.kt")
public void testUnsignedIntToString_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntToString_jvm8.kt");
}
@TestMetadata("unsignedLongCompare_jvm8.kt")
public void testUnsignedLongCompare_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongCompare_jvm8.kt");
}
@TestMetadata("unsignedLongDivide_jvm8.kt")
public void testUnsignedLongDivide_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongDivide_jvm8.kt");
}
@TestMetadata("unsignedLongRemainder_jvm8.kt")
public void testUnsignedLongRemainder_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongRemainder_jvm8.kt");
}
@TestMetadata("unsignedLongToString_jvm8.kt")
public void testUnsignedLongToString_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongToString_jvm8.kt");
}
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")
@@ -31713,6 +31713,59 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
@TestMetadata("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Jvm8Intrinsics extends AbstractLightAnalysisModeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInJvm8Intrinsics() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("unsignedIntCompare_jvm8.kt")
public void testUnsignedIntCompare_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntCompare_jvm8.kt");
}
@TestMetadata("unsignedIntDivide_jvm8.kt")
public void testUnsignedIntDivide_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntDivide_jvm8.kt");
}
@TestMetadata("unsignedIntRemainder_jvm8.kt")
public void testUnsignedIntRemainder_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntRemainder_jvm8.kt");
}
@TestMetadata("unsignedIntToString_jvm8.kt")
public void testUnsignedIntToString_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntToString_jvm8.kt");
}
@TestMetadata("unsignedLongCompare_jvm8.kt")
public void testUnsignedLongCompare_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongCompare_jvm8.kt");
}
@TestMetadata("unsignedLongDivide_jvm8.kt")
public void testUnsignedLongDivide_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongDivide_jvm8.kt");
}
@TestMetadata("unsignedLongRemainder_jvm8.kt")
public void testUnsignedLongRemainder_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongRemainder_jvm8.kt");
}
@TestMetadata("unsignedLongToString_jvm8.kt")
public void testUnsignedLongToString_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongToString_jvm8.kt");
}
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")
@@ -32308,6 +32308,59 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
@TestMetadata("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Jvm8Intrinsics extends AbstractIrBlackBoxCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
public void testAllFilesPresentInJvm8Intrinsics() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("unsignedIntCompare_jvm8.kt")
public void testUnsignedIntCompare_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntCompare_jvm8.kt");
}
@TestMetadata("unsignedIntDivide_jvm8.kt")
public void testUnsignedIntDivide_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntDivide_jvm8.kt");
}
@TestMetadata("unsignedIntRemainder_jvm8.kt")
public void testUnsignedIntRemainder_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntRemainder_jvm8.kt");
}
@TestMetadata("unsignedIntToString_jvm8.kt")
public void testUnsignedIntToString_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedIntToString_jvm8.kt");
}
@TestMetadata("unsignedLongCompare_jvm8.kt")
public void testUnsignedLongCompare_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongCompare_jvm8.kt");
}
@TestMetadata("unsignedLongDivide_jvm8.kt")
public void testUnsignedLongDivide_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongDivide_jvm8.kt");
}
@TestMetadata("unsignedLongRemainder_jvm8.kt")
public void testUnsignedLongRemainder_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongRemainder_jvm8.kt");
}
@TestMetadata("unsignedLongToString_jvm8.kt")
public void testUnsignedLongToString_jvm8() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics/unsignedLongToString_jvm8.kt");
}
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")
@@ -26239,6 +26239,19 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
@TestMetadata("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Jvm8Intrinsics extends AbstractIrJsCodegenBoxES6Test {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath);
}
public void testAllFilesPresentInJvm8Intrinsics() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")
@@ -26239,6 +26239,19 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
@TestMetadata("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Jvm8Intrinsics extends AbstractIrJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInJvm8Intrinsics() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")
@@ -26239,6 +26239,19 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
@TestMetadata("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Jvm8Intrinsics extends AbstractJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
}
public void testAllFilesPresentInJvm8Intrinsics() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")
@@ -14402,6 +14402,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
public void testUnsignedToSignedConversion() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedToSignedConversion.kt");
}
@TestMetadata("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Jvm8Intrinsics extends AbstractIrCodegenBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInJvm8Intrinsics() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/unsignedTypes/jvm8Intrinsics"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")