[JVM IR] Use JVM8 support for unsigned int operations
- unmute tests - add test to ensure JVM target is respected - add test to cover smart-casted cases - implement function matching and replacement - Switching on uint constants - introduce lowering for standard library replacements
This commit is contained in:
committed by
Dmitry Petrov
parent
c95216dc5d
commit
f0ff8f202c
@@ -300,6 +300,8 @@ private val jvmFilePhases =
|
||||
anonymousObjectSuperConstructorPhase then
|
||||
tailrecPhase then
|
||||
|
||||
jvmStandardLibraryBuiltInsPhase then
|
||||
|
||||
forLoopsPhase then
|
||||
jvmInlineClassPhase then
|
||||
|
||||
|
||||
@@ -616,6 +616,52 @@ class JvmSymbols(
|
||||
}
|
||||
}
|
||||
|
||||
private val javaLangInteger: IrClassSymbol = createClass(FqName("java.lang.Integer")) { klass ->
|
||||
klass.addFunction("compareUnsigned", irBuiltIns.intType, isStatic = true).apply {
|
||||
addValueParameter("x", irBuiltIns.intType)
|
||||
addValueParameter("y", irBuiltIns.intType)
|
||||
}
|
||||
klass.addFunction("divideUnsigned", irBuiltIns.intType, isStatic = true).apply {
|
||||
addValueParameter("dividend", irBuiltIns.intType)
|
||||
addValueParameter("divisor", irBuiltIns.intType)
|
||||
}
|
||||
klass.addFunction("remainderUnsigned", irBuiltIns.intType, isStatic = true).apply {
|
||||
addValueParameter("dividend", irBuiltIns.intType)
|
||||
addValueParameter("divisor", irBuiltIns.intType)
|
||||
}
|
||||
klass.addFunction("toUnsignedString", irBuiltIns.stringType, isStatic = true).apply {
|
||||
addValueParameter("i", irBuiltIns.intType)
|
||||
}
|
||||
}
|
||||
|
||||
val compareUnsignedInt: IrSimpleFunctionSymbol = javaLangInteger.functionByName("compareUnsigned")
|
||||
val divideUnsignedInt: IrSimpleFunctionSymbol = javaLangInteger.functionByName("divideUnsigned")
|
||||
val remainderUnsignedInt: IrSimpleFunctionSymbol = javaLangInteger.functionByName("remainderUnsigned")
|
||||
val toUnsignedStringInt: IrSimpleFunctionSymbol = javaLangInteger.functionByName("toUnsignedString")
|
||||
|
||||
private val javaLangLong: IrClassSymbol = createClass(FqName("java.lang.Long")) { klass ->
|
||||
klass.addFunction("compareUnsigned", irBuiltIns.intType, isStatic = true).apply {
|
||||
addValueParameter("x", irBuiltIns.longType)
|
||||
addValueParameter("y", irBuiltIns.longType)
|
||||
}
|
||||
klass.addFunction("divideUnsigned", irBuiltIns.longType, isStatic = true).apply {
|
||||
addValueParameter("dividend", irBuiltIns.longType)
|
||||
addValueParameter("divisor", irBuiltIns.longType)
|
||||
}
|
||||
klass.addFunction("remainderUnsigned", irBuiltIns.longType, isStatic = true).apply {
|
||||
addValueParameter("dividend", irBuiltIns.longType)
|
||||
addValueParameter("divisor", irBuiltIns.longType)
|
||||
}
|
||||
klass.addFunction("toUnsignedString", irBuiltIns.stringType, isStatic = true).apply {
|
||||
addValueParameter("i", irBuiltIns.longType)
|
||||
}
|
||||
}
|
||||
|
||||
val compareUnsignedLong: IrSimpleFunctionSymbol = javaLangLong.functionByName("compareUnsigned")
|
||||
val divideUnsignedLong: IrSimpleFunctionSymbol = javaLangLong.functionByName("divideUnsigned")
|
||||
val remainderUnsignedLong: IrSimpleFunctionSymbol = javaLangLong.functionByName("remainderUnsigned")
|
||||
val toUnsignedStringLong: IrSimpleFunctionSymbol = javaLangLong.functionByName("toUnsignedString")
|
||||
|
||||
val systemArraycopy: IrSimpleFunctionSymbol = systemClass.functionByName("arraycopy")
|
||||
|
||||
val signatureStringIntrinsic: IrSimpleFunctionSymbol =
|
||||
|
||||
+118
-22
@@ -43,48 +43,125 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
|
||||
|
||||
val calls = callToLabels.map { it.call }
|
||||
|
||||
// Checks if all conditions are CALL EQEQ(tmp_variable, some_constant)
|
||||
if (!areConstComparisons(calls))
|
||||
return null
|
||||
// To generate a switch from a when it must be a comparison of a single
|
||||
// variable, the "subject", against a series of constants. We assume the
|
||||
// subject is the left hand side of the first condition, provided the
|
||||
// first condition is a comparison. If the first condition is of the form:
|
||||
//
|
||||
// CALL EQEQ(<unsafe-coerce><UInt, Int>(var),_)
|
||||
//
|
||||
// we must be trying to generate an _unsigned_ int switch, and need to
|
||||
// account for unsafe-coerce in all comparisons that arise from the
|
||||
// wrapping and unwrapping of the UInt inline class wrapper. Otherwise,
|
||||
// this is a primitive Int or String switch, with a condition of the form
|
||||
//
|
||||
// CALL EQEQ(var,_)
|
||||
|
||||
// Subject should be the same for all conditions. Let's pick the first.
|
||||
val subject = callToLabels[0].call.getValueArgument(0)!! as IrGetValue
|
||||
val firstCondition = callToLabels[0].call
|
||||
if (firstCondition.symbol != codegen.classCodegen.context.irBuiltIns.eqeqSymbol) return null
|
||||
val subject = firstCondition.getValueArgument(0)
|
||||
return when {
|
||||
subject is IrCall && subject.isCoerceFromUIntToInt() ->
|
||||
generateUIntSwitch(subject.getValueArgument(0)!! as? IrGetValue, calls, callToLabels, expressionToLabels, elseExpression)
|
||||
subject is IrGetValue ->
|
||||
generatePrimitiveSwitch(subject, calls, callToLabels, expressionToLabels, elseExpression)
|
||||
else ->
|
||||
null
|
||||
}?.genOptimizedIfEnoughCases()
|
||||
}
|
||||
|
||||
// Don't generate repeated cases, which are unreachable but allowed in Kotlin.
|
||||
// Only keep the first encountered case:
|
||||
val cases =
|
||||
callToLabels.map { ValueToLabel((it.call.getValueArgument(1) as IrConst<*>).value, it.label) }.distinctBy { it.value }
|
||||
fun IrCall.isCoerceFromUIntToInt(): Boolean =
|
||||
symbol == codegen.classCodegen.context.ir.symbols.unsafeCoerceIntrinsic
|
||||
&& getTypeArgument(0)?.isUInt() == true
|
||||
&& getTypeArgument(1)?.isInt() == true
|
||||
|
||||
// Remove labels and "then expressions" that are not reachable.
|
||||
val reachableLabels = HashSet(cases.map { it.label })
|
||||
expressionToLabels.removeIf { it.label !in reachableLabels }
|
||||
private fun generateUIntSwitch(
|
||||
subject: IrGetValue?,
|
||||
conditions: List<IrCall>,
|
||||
callToLabels: ArrayList<CallToLabel>,
|
||||
expressionToLabels: ArrayList<ExpressionToLabel>,
|
||||
elseExpression: IrExpression?
|
||||
): Switch? {
|
||||
if (subject == null) return null
|
||||
// We check that all conditions are of the form
|
||||
// CALL EQEQ (<unsafe-coerce><UInt,Int>(subject),
|
||||
// <unsafe-coerce><UInt,Int>( Constant ))
|
||||
if (!areConstUIntComparisons(conditions)) return null
|
||||
|
||||
// Filter repeated cases. Allowed in Kotlin but unreachable.
|
||||
val cases = callToLabels.map {
|
||||
val constCoercion = it.call.getValueArgument(1)!! as IrCall
|
||||
val constValue = (constCoercion.getValueArgument(0) as IrConst<*>).value
|
||||
ValueToLabel(
|
||||
constValue,
|
||||
it.label
|
||||
)
|
||||
}.distinctBy { it.value }
|
||||
|
||||
expressionToLabels.removeUnreachableLabels(cases)
|
||||
|
||||
return IntSwitch(
|
||||
subject,
|
||||
elseExpression,
|
||||
expressionToLabels,
|
||||
cases
|
||||
)
|
||||
}
|
||||
|
||||
private fun generatePrimitiveSwitch(
|
||||
subject: IrGetValue,
|
||||
conditions: List<IrCall>,
|
||||
callToLabels: ArrayList<CallToLabel>,
|
||||
expressionToLabels: ArrayList<ExpressionToLabel>,
|
||||
elseExpression: IrExpression?
|
||||
): Switch? {
|
||||
// Checks if all conditions are CALL EQEQ(var,constant)
|
||||
if (!areConstantComparisons(conditions)) return null
|
||||
|
||||
return when {
|
||||
areConstIntComparisons(calls) ->
|
||||
areConstIntComparisons(conditions) -> {
|
||||
val cases = extractSwitchCasesAndFilterUnreachableLabels(callToLabels, expressionToLabels)
|
||||
IntSwitch(
|
||||
subject,
|
||||
elseExpression,
|
||||
expressionToLabels,
|
||||
cases
|
||||
)
|
||||
areConstStringComparisons(calls) ->
|
||||
}
|
||||
areConstStringComparisons(conditions) -> {
|
||||
val cases = extractSwitchCasesAndFilterUnreachableLabels(callToLabels, expressionToLabels)
|
||||
StringSwitch(
|
||||
subject,
|
||||
elseExpression,
|
||||
expressionToLabels,
|
||||
cases
|
||||
)
|
||||
else -> null // TODO: Enum, etc.
|
||||
}?.genOptimizedIfEnoughCases()
|
||||
}
|
||||
else ->
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun areConstComparisons(conditions: List<IrCall>): Boolean {
|
||||
// All branches must be CALL 'EQEQ(Any?, Any?)': Boolean
|
||||
if (conditions.any { it.symbol != codegen.classCodegen.context.irBuiltIns.eqeqSymbol })
|
||||
return false
|
||||
// Check that all conditions are of the form
|
||||
//
|
||||
// CALL EQEQ (<unsafe-coerce><UInt,Int>(subject), <unsafe-coerce><UInt,Int>( Constant ))
|
||||
//
|
||||
// where subject is taken to be the first variable compared on the left hand side, if any.
|
||||
private fun areConstUIntComparisons(conditions: List<IrCall>): Boolean {
|
||||
val lhs = conditions.map { it.takeIf { it.symbol == codegen.context.irBuiltIns.eqeqSymbol }?.getValueArgument(0) as? IrCall }
|
||||
if (lhs.any { it == null || !it.isCoerceFromUIntToInt() }) return false
|
||||
val lhsVariableAccesses = lhs.map { it!!.getValueArgument(0) as? IrGetValue }
|
||||
if (lhsVariableAccesses.any { it == null || it.symbol != lhsVariableAccesses[0]!!.symbol }) return false
|
||||
|
||||
// All LHS refer to the same tmp variable.
|
||||
val lhs = conditions.map { it.getValueArgument(0) as? IrGetValue }
|
||||
val rhs = conditions.map { it.getValueArgument(1) as? IrCall }
|
||||
if (rhs.any { it == null || !it.isCoerceFromUIntToInt() || it.getValueArgument(0) !is IrConst<*> }) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun areConstantComparisons(conditions: List<IrCall>): Boolean {
|
||||
// All conditions are equality checks && all LHS refer to the same tmp variable.
|
||||
val lhs = conditions.map { it.takeIf { it.symbol == codegen.context.irBuiltIns.eqeqSymbol }?.getValueArgument(0) as? IrGetValue }
|
||||
if (lhs.any { it == null || it.symbol != lhs[0]!!.symbol })
|
||||
return false
|
||||
|
||||
@@ -122,6 +199,25 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
|
||||
return true
|
||||
}
|
||||
|
||||
private fun extractSwitchCasesAndFilterUnreachableLabels(
|
||||
callToLabels: List<CallToLabel>,
|
||||
expressionToLabels: ArrayList<ExpressionToLabel>
|
||||
): List<ValueToLabel> {
|
||||
// Don't generate repeated cases, which are unreachable but allowed in Kotlin.
|
||||
// Only keep the first encountered case:
|
||||
val cases =
|
||||
callToLabels.map { ValueToLabel((it.call.getValueArgument(1) as IrConst<*>).value, it.label) }.distinctBy { it.value }
|
||||
|
||||
expressionToLabels.removeUnreachableLabels(cases)
|
||||
|
||||
return cases
|
||||
}
|
||||
|
||||
private fun ArrayList<ExpressionToLabel>.removeUnreachableLabels(cases: List<ValueToLabel>) {
|
||||
val reachableLabels = HashSet(cases.map { it.label })
|
||||
removeIf { it.label !in reachableLabels }
|
||||
}
|
||||
|
||||
// psi2ir lowers multiple cases to nested conditions. For example,
|
||||
//
|
||||
// when (subject) {
|
||||
|
||||
+2
-1
@@ -53,7 +53,8 @@ val jvmInlineClassPhase = makeIrFilePhase(
|
||||
name = "Inline Classes",
|
||||
description = "Lower inline classes",
|
||||
// forLoopsPhase may produce UInt and ULong which are inline classes.
|
||||
prerequisite = setOf(forLoopsPhase)
|
||||
// standard library replacements are done on the unmangled names for UInt and ULong classes.
|
||||
prerequisite = setOf(forLoopsPhase, jvmStandardLibraryBuiltInsPhase)
|
||||
)
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -46,7 +46,7 @@ class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass
|
||||
dispatchReceiverParameter != null
|
||||
|
||||
|
||||
private fun getOperandsIfCallToEqeqOrEquals(call: IrCall): Pair<IrExpression, IrExpression>? =
|
||||
private fun getOperandsIfCallToEQEQOrEquals(call: IrCall): Pair<IrExpression, IrExpression>? =
|
||||
when {
|
||||
call.symbol == context.irBuiltIns.eqeqSymbol -> {
|
||||
val left = call.getValueArgument(0)!!
|
||||
@@ -103,7 +103,7 @@ class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass
|
||||
return (expression.dispatchReceiver as IrCall).dispatchReceiver!!
|
||||
}
|
||||
|
||||
getOperandsIfCallToEqeqOrEquals(expression)?.let { (left, right) ->
|
||||
getOperandsIfCallToEQEQOrEquals(expression)?.let { (left, right) ->
|
||||
return when {
|
||||
left.isNullConst() && right.isNullConst() ->
|
||||
IrConstImpl.constTrue(expression.startOffset, expression.endOffset, context.irBuiltIns.booleanType)
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
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.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
|
||||
internal val jvmStandardLibraryBuiltInsPhase = makeIrFilePhase(
|
||||
::JvmStandardLibraryBuiltInsLowering,
|
||||
name = "JvmStandardLibraryBuiltInsLowering",
|
||||
description = "Use Java Standard Library implementations of built-ins"
|
||||
)
|
||||
|
||||
class JvmStandardLibraryBuiltInsLowering(val context: JvmBackendContext) : FileLoweringPass {
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
if (context.state.target < JvmTarget.JVM_1_8) return
|
||||
|
||||
val transformer = object : IrElementTransformerVoid() {
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.transformChildren(this, null)
|
||||
|
||||
val parentClass = expression.symbol.owner.parent.fqNameForIrSerialization.asString()
|
||||
val functionName = expression.symbol.owner.name.asString()
|
||||
Jvm8builtInReplacements[parentClass to functionName]?.let {
|
||||
return expression.replaceWithCallTo(it)
|
||||
}
|
||||
|
||||
return expression
|
||||
}
|
||||
}
|
||||
|
||||
irFile.transformChildren(transformer, null)
|
||||
}
|
||||
|
||||
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,
|
||||
("kotlin.UInt" to "toString") to context.ir.symbols.toUnsignedStringInt,
|
||||
("kotlin.ULong" to "compareTo") to context.ir.symbols.compareUnsignedLong,
|
||||
("kotlin.ULong" to "div") to context.ir.symbols.divideUnsignedLong,
|
||||
("kotlin.ULong" to "rem") to context.ir.symbols.remainderUnsignedLong,
|
||||
("kotlin.ULong" to "toString") to context.ir.symbols.toUnsignedStringLong
|
||||
)
|
||||
|
||||
// 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: IrFunctionSymbol) =
|
||||
IrCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
type,
|
||||
replacement
|
||||
).also { newCall ->
|
||||
var valueArgumentOffset = 0
|
||||
this.dispatchReceiver?.let {
|
||||
newCall.putValueArgument(valueArgumentOffset, it.coerceTo(replacement.owner.valueParameters[valueArgumentOffset].type))
|
||||
valueArgumentOffset++
|
||||
}
|
||||
(0 until valueArgumentsCount).forEach {
|
||||
newCall.putValueArgument(it + valueArgumentOffset, getValueArgument(it)!!.coerceTo(replacement.owner.valueParameters[it].type))
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrExpression.coerceTo(target: IrType): IrExpression =
|
||||
IrCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
target,
|
||||
context.ir.symbols.unsafeCoerceIntrinsic
|
||||
).also { call ->
|
||||
call.putTypeArgument(0, type)
|
||||
call.putTypeArgument(1, target)
|
||||
call.putValueArgument(0, this)
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
val ua = 1234U
|
||||
val ub = 5678U
|
||||
|
||||
fun box(): String {
|
||||
if (ua.compareTo(ub) > 0) {
|
||||
throw AssertionError()
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// 1 kotlin/UnsignedKt.uintCompare
|
||||
// 0 INVOKESTATIC java/lang/Integer.compareUnsigned \(II\)I
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR
|
||||
|
||||
val ua = 1234U
|
||||
val ub = 5678U
|
||||
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR
|
||||
|
||||
val ua = 1234U
|
||||
val ub = 5678U
|
||||
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR
|
||||
|
||||
val ua = 1234U
|
||||
val ub = 5678U
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun both(a: Any?, b: Any?) = if (a is UInt && b is UInt) a < b else null!!
|
||||
|
||||
// 1 compareUnsigned
|
||||
// 0 uintCompare
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR
|
||||
|
||||
fun box(): String {
|
||||
val min = 0U.toString()
|
||||
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR
|
||||
|
||||
val ua = 1234UL
|
||||
val ub = 5678UL
|
||||
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR
|
||||
|
||||
val ua = 1234UL
|
||||
val ub = 5678UL
|
||||
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR
|
||||
|
||||
val ua = 1234UL
|
||||
val ub = 5678UL
|
||||
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR
|
||||
|
||||
fun box(): String {
|
||||
val min = 0UL.toString()
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36839 Generate 'when' with unsigned subject using TABLESWITCH/LOOKUPSWITCH in JVM_IR
|
||||
|
||||
const val M1: UInt = 2147483648u
|
||||
|
||||
|
||||
@@ -4483,6 +4483,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/unsignedTypes"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntCompare_before.kt")
|
||||
public void testUnsignedIntCompare_before() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_before.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntCompare_jvm18.kt")
|
||||
public void testUnsignedIntCompare_jvm18() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_jvm18.kt");
|
||||
@@ -4498,6 +4503,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntRemainder_jvm18.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntSmartCasts_jvm18.kt")
|
||||
public void testUnsignedIntSmartCasts_jvm18() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntSmartCasts_jvm18.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntToString_jvm18.kt")
|
||||
public void testUnsignedIntToString_jvm18() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntToString_jvm18.kt");
|
||||
|
||||
+10
@@ -4441,6 +4441,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/unsignedTypes"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntCompare_before.kt")
|
||||
public void testUnsignedIntCompare_before() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_before.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntCompare_jvm18.kt")
|
||||
public void testUnsignedIntCompare_jvm18() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_jvm18.kt");
|
||||
@@ -4456,6 +4461,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
||||
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntRemainder_jvm18.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntSmartCasts_jvm18.kt")
|
||||
public void testUnsignedIntSmartCasts_jvm18() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntSmartCasts_jvm18.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedIntToString_jvm18.kt")
|
||||
public void testUnsignedIntToString_jvm18() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntToString_jvm18.kt");
|
||||
|
||||
Reference in New Issue
Block a user