KT-43286 use JVM 1.8 intrinsics for coercible unsigned values only

This commit is contained in:
Dmitry Petrov
2020-11-25 12:56:47 +03:00
parent 498047e64e
commit f6abc5c3cf
11 changed files with 140 additions and 18 deletions
@@ -32036,6 +32036,16 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/unsignedTypes/kt25784.kt");
}
@TestMetadata("kt43286.kt")
public void testKt43286() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286.kt");
}
@TestMetadata("kt43286a.kt")
public void testKt43286a() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/literalEqualsNullableUnsigned.kt");
@@ -35,8 +35,8 @@ class JvmStandardLibraryBuiltInsLowering(val context: JvmBackendContext) : FileL
val parentClass = expression.symbol.owner.parent.fqNameForIrSerialization.asString()
val functionName = expression.symbol.owner.name.asString()
Jvm8builtInReplacements[parentClass to functionName]?.let {
return expression.replaceWithCallTo(it)
jvm8builtInReplacements[parentClass to functionName]?.let { replacement ->
return expression.replaceWithCallTo(replacement)
}
return expression
@@ -46,7 +46,7 @@ class JvmStandardLibraryBuiltInsLowering(val context: JvmBackendContext) : FileL
irFile.transformChildren(transformer, null)
}
private val Jvm8builtInReplacements = mapOf(
private val jvm8builtInReplacements = mapOf(
("kotlin.UInt" to "compareTo") to context.ir.symbols.compareUnsignedInt,
("kotlin.UInt" to "div") to context.ir.symbols.divideUnsignedInt,
("kotlin.UInt" to "rem") to context.ir.symbols.remainderUnsignedInt,
@@ -59,7 +59,8 @@ 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.
private fun IrCall.replaceWithCallTo(replacement: IrSimpleFunctionSymbol) =
// If we can't coerce arguments to required types, keep original expression (see below).
private fun IrCall.replaceWithCallTo(replacement: IrSimpleFunctionSymbol): IrCall =
IrCallImpl.fromSymbolOwner(
startOffset,
endOffset,
@@ -68,23 +69,30 @@ class JvmStandardLibraryBuiltInsLowering(val context: JvmBackendContext) : FileL
).also { newCall ->
var valueArgumentOffset = 0
this.dispatchReceiver?.let {
newCall.putValueArgument(valueArgumentOffset, it.coerceTo(replacement.owner.valueParameters[valueArgumentOffset].type))
val coercedDispatchReceiver = it.coerceIfPossible(replacement.owner.valueParameters[valueArgumentOffset].type)
?: return this@replaceWithCallTo
newCall.putValueArgument(valueArgumentOffset, coercedDispatchReceiver)
valueArgumentOffset++
}
(0 until valueArgumentsCount).forEach {
newCall.putValueArgument(it + valueArgumentOffset, getValueArgument(it)!!.coerceTo(replacement.owner.valueParameters[it].type))
for (index in 0 until valueArgumentsCount) {
val coercedValueArgument = getValueArgument(index)!!.coerceIfPossible(replacement.owner.valueParameters[index].type)
?: return this@replaceWithCallTo
newCall.putValueArgument(index + valueArgumentOffset, coercedValueArgument)
}
}
private fun IrExpression.coerceTo(target: IrType): IrExpression =
IrCallImpl.fromSymbolOwner(
startOffset,
endOffset,
target,
context.ir.symbols.unsafeCoerceIntrinsic
).also { call ->
call.putTypeArgument(0, type)
call.putTypeArgument(1, target)
call.putValueArgument(0, this)
}
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.
val fromJvmType = context.typeMapper.mapType(type)
val toJvmType = context.typeMapper.mapType(toType)
return if (fromJvmType != toJvmType)
null
else
IrCallImpl.fromSymbolOwner(startOffset, endOffset, toType, context.ir.symbols.unsafeCoerceIntrinsic).also { call ->
call.putTypeArgument(0, type)
call.putTypeArgument(1, toType)
call.putValueArgument(0, this)
}
}
}
+26
View File
@@ -0,0 +1,26 @@
// JVM_TARGET: 1.8
// WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME
class D(val x: UInt?)
class E(val x: Any)
fun f(d: D): String {
return d.x?.let { d.x.toString() } ?: ""
}
fun g(e: E): String {
if (e.x is UInt) return e.x.toString()
return ""
}
fun box(): String {
val test1 = f(D(42u))
if (test1 != "42") throw Exception(test1)
val test2 = g(E(42u))
if (test2 != "42") throw Exception(test2)
return "OK"
}
@@ -0,0 +1,8 @@
// JVM_TARGET: 1.8
// WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME
fun box(): String {
val x = 3UL % 2U
return if (x == 1UL) "OK" else "Fail: $x"
}
@@ -33807,6 +33807,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/unsignedTypes/kt25784.kt");
}
@TestMetadata("kt43286.kt")
public void testKt43286() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286.kt");
}
@TestMetadata("kt43286a.kt")
public void testKt43286a() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/literalEqualsNullableUnsigned.kt");
@@ -31441,6 +31441,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/unsignedTypes/kt25784.kt");
}
@TestMetadata("kt43286.kt")
public void testKt43286() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286.kt");
}
@TestMetadata("kt43286a.kt")
public void testKt43286a() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/literalEqualsNullableUnsigned.kt");
@@ -32036,6 +32036,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/unsignedTypes/kt25784.kt");
}
@TestMetadata("kt43286.kt")
public void testKt43286() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286.kt");
}
@TestMetadata("kt43286a.kt")
public void testKt43286a() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/literalEqualsNullableUnsigned.kt");
@@ -26002,6 +26002,16 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/unsignedTypes/kt25784.kt");
}
@TestMetadata("kt43286.kt")
public void testKt43286() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286.kt");
}
@TestMetadata("kt43286a.kt")
public void testKt43286a() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/literalEqualsNullableUnsigned.kt");
@@ -26002,6 +26002,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/unsignedTypes/kt25784.kt");
}
@TestMetadata("kt43286.kt")
public void testKt43286() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286.kt");
}
@TestMetadata("kt43286a.kt")
public void testKt43286a() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/literalEqualsNullableUnsigned.kt");
@@ -26017,6 +26017,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/unsignedTypes/kt25784.kt");
}
@TestMetadata("kt43286.kt")
public void testKt43286() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286.kt");
}
@TestMetadata("kt43286a.kt")
public void testKt43286a() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/literalEqualsNullableUnsigned.kt");
@@ -14305,6 +14305,16 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverListOfBoxedUnsignedValues.kt");
}
@TestMetadata("kt43286.kt")
public void testKt43286() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286.kt");
}
@TestMetadata("kt43286a.kt")
public void testKt43286a() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/literalEqualsNullableUnsigned.kt");