[FIR] Promote numeric types during comparisons

Added support for comparing platform types. Extracted logic to convert
operator expressions to OperatorExpressionGenerator.
This commit is contained in:
Mark Punzalan
2020-04-14 00:51:19 -07:00
committed by Mikhail Glukhikh
parent 1d9967013b
commit d4cbfcb79e
18 changed files with 310 additions and 547 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator
import org.jetbrains.kotlin.fir.backend.generators.ClassMemberGenerator
import org.jetbrains.kotlin.fir.backend.generators.OperatorExpressionGenerator
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
@@ -21,42 +22,36 @@ import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.resolve.isIteratorNext
import org.jetbrains.kotlin.fir.resolve.transformers.IntegerLiteralTypeApproximationTransformer
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperator
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.IrGeneratorContextInterface
import org.jetbrains.kotlin.ir.builders.constFalse
import org.jetbrains.kotlin.ir.builders.constTrue
import org.jetbrains.kotlin.ir.builders.elseBranch
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import java.util.*
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtForExpression
class Fir2IrVisitor(
private val converter: Fir2IrConverter,
private val components: Fir2IrComponents,
fakeOverrideMode: FakeOverrideMode
) : Fir2IrComponents by components, FirDefaultVisitor<IrElement, Any?>(), IrGeneratorContextInterface {
companion object {
private val NEGATED_OPERATIONS: Set<FirOperation> = EnumSet.of(FirOperation.NOT_EQ, FirOperation.NOT_IDENTITY)
private val UNARY_OPERATIONS: Set<FirOperation> = EnumSet.of(FirOperation.EXCL)
}
private val integerApproximator = IntegerLiteralTypeApproximationTransformer(session.firSymbolProvider, session.inferenceContext)
@@ -66,6 +61,8 @@ class Fir2IrVisitor(
private val memberGenerator = ClassMemberGenerator(components, this, conversionScope, callGenerator, fakeOverrideMode)
private val operatorGenerator = OperatorExpressionGenerator(components, this, callGenerator)
private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() }
private fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T = conversionScope.applyParentFromStackTo(declaration)
@@ -611,106 +608,11 @@ class Fir2IrVisitor(
}
}
override fun visitComparisonExpression(comparisonExpression: FirComparisonExpression, data: Any?): IrElement {
return comparisonExpression.convertWithOffsets { startOffset, endOffset ->
generateComparisonCall(startOffset, endOffset, comparisonExpression)
}
}
override fun visitComparisonExpression(comparisonExpression: FirComparisonExpression, data: Any?): IrElement =
operatorGenerator.convertComparisonExpression(comparisonExpression)
private fun generateComparisonCall(
startOffset: Int, endOffset: Int,
comparisonExpression: FirComparisonExpression
): IrExpression {
val operation = comparisonExpression.operation
fun fallbackToRealCall(): IrExpression {
val (symbol, origin) = getSymbolAndOriginForComparison(operation, irBuiltIns.intType.classifierOrFail)
return primitiveOp2(
startOffset, endOffset,
symbol!!,
irBuiltIns.booleanType,
origin,
visitFunctionCall(comparisonExpression.compareToCall, null),
IrConstImpl.int(startOffset, endOffset, irBuiltIns.intType, 0)
)
}
val comparisonInfo = comparisonExpression.inferPrimitiveNumericComparisonInfo() ?: return fallbackToRealCall()
val comparisonType = comparisonInfo.comparisonType
// Currently inferPrimitiveNumericComparisonInfo returns null for different primitive values
// TODO: Support different primitive types as well and fix inferPrimitiveNumericComparisonInfo
require(comparisonInfo.leftPrimitiveType == comparisonInfo.rightPrimitiveType && comparisonInfo.leftType == comparisonInfo.rightType) {
"Contract for inferPrimitiveNumericComparisonInfo is violated"
}
val simpleType = when ((comparisonType.type as? ConeClassLikeType)?.lookupTag?.classId) {
StandardClassIds.Long -> irBuiltIns.longType
StandardClassIds.Int -> irBuiltIns.intType
StandardClassIds.Float -> irBuiltIns.floatType
StandardClassIds.Double -> irBuiltIns.doubleType
StandardClassIds.Char -> irBuiltIns.charType
else -> return fallbackToRealCall()
}
val (symbol, origin) = getSymbolAndOriginForComparison(operation, simpleType.classifierOrFail)
return primitiveOp2(
startOffset, endOffset, symbol!!, irBuiltIns.booleanType, origin,
convertToIrExpression(comparisonExpression.left), convertToIrExpression(comparisonExpression.right)
)
}
private fun getSymbolAndOriginForComparison(
operation: FirOperation,
classifier: IrClassifierSymbol
): Pair<IrSimpleFunctionSymbol?, IrStatementOriginImpl> {
return when (operation) {
FirOperation.LT -> irBuiltIns.lessFunByOperandType[classifier] to IrStatementOrigin.LT
FirOperation.GT -> irBuiltIns.greaterFunByOperandType[classifier] to IrStatementOrigin.GT
FirOperation.LT_EQ -> irBuiltIns.lessOrEqualFunByOperandType[classifier] to IrStatementOrigin.LTEQ
FirOperation.GT_EQ -> irBuiltIns.greaterOrEqualFunByOperandType[classifier] to IrStatementOrigin.GTEQ
else -> error("Unexpected comparison operation: $operation")
}
}
private fun generateOperatorCall(
startOffset: Int, endOffset: Int, operation: FirOperation, arguments: List<FirExpression>
): IrExpression {
val (type, symbol, origin) = when (operation) {
FirOperation.EQ -> Triple(irBuiltIns.booleanType, irBuiltIns.eqeqSymbol, IrStatementOrigin.EQEQ)
FirOperation.NOT_EQ -> Triple(irBuiltIns.booleanType, irBuiltIns.eqeqSymbol, IrStatementOrigin.EXCLEQ)
FirOperation.IDENTITY -> Triple(irBuiltIns.booleanType, irBuiltIns.eqeqeqSymbol, IrStatementOrigin.EQEQEQ)
FirOperation.NOT_IDENTITY -> Triple(irBuiltIns.booleanType, irBuiltIns.eqeqeqSymbol, IrStatementOrigin.EXCLEQEQ)
FirOperation.EXCL -> Triple(irBuiltIns.booleanType, irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL)
FirOperation.LT, FirOperation.GT,
FirOperation.LT_EQ, FirOperation.GT_EQ,
FirOperation.OTHER, FirOperation.ASSIGN, FirOperation.PLUS_ASSIGN,
FirOperation.MINUS_ASSIGN, FirOperation.TIMES_ASSIGN,
FirOperation.DIV_ASSIGN, FirOperation.REM_ASSIGN,
FirOperation.IS, FirOperation.NOT_IS,
FirOperation.AS, FirOperation.SAFE_AS
-> {
TODO("Should not be here: incompatible operation in FirOperatorCall: $operation")
}
}
val result = if (operation in UNARY_OPERATIONS) {
primitiveOp1(startOffset, endOffset, symbol, type, origin, convertToIrExpression(arguments[0]))
} else {
primitiveOp2(
startOffset, endOffset, symbol, type, origin,
convertToIrExpression(arguments[0]), convertToIrExpression(arguments[1])
)
}
if (operation !in NEGATED_OPERATIONS) return result
return primitiveOp1(startOffset, endOffset, irBuiltIns.booleanNotSymbol, irBuiltIns.booleanType, origin, result)
}
override fun visitOperatorCall(operatorCall: FirOperatorCall, data: Any?): IrElement {
return operatorCall.convertWithOffsets { startOffset, endOffset ->
generateOperatorCall(startOffset, endOffset, operatorCall.operation, operatorCall.arguments)
}
}
override fun visitOperatorCall(operatorCall: FirOperatorCall, data: Any?): IrElement =
operatorGenerator.convertOperatorCall(operatorCall)
override fun visitStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall, data: Any?): IrElement {
return stringConcatenationCall.convertWithOffsets { startOffset, endOffset ->
@@ -9,15 +9,14 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.arguments
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
class PrimitiveConeNumericComparisonInfo(
val comparisonType: ConeKotlinType,
val leftPrimitiveType: ConeClassLikeType,
val rightPrimitiveType: ConeClassLikeType,
val leftType: ConeKotlinType,
val rightType: ConeKotlinType
val comparisonType: ConeClassLikeType,
val leftType: ConeClassLikeType,
val rightType: ConeClassLikeType
)
val FirComparisonExpression.left: FirExpression
@@ -26,25 +25,39 @@ val FirComparisonExpression.left: FirExpression
val FirComparisonExpression.right: FirExpression
get() = compareToCall.arguments.getOrNull(0) ?: error("There should be a first arg for ${compareToCall.render()}")
fun FirComparisonExpression.inferPrimitiveNumericComparisonInfo(): PrimitiveConeNumericComparisonInfo? {
fun FirComparisonExpression.inferPrimitiveNumericComparisonInfo(): PrimitiveConeNumericComparisonInfo? =
inferPrimitiveNumericComparisonInfo(left, right)
fun inferPrimitiveNumericComparisonInfo(left: FirExpression, right: FirExpression): PrimitiveConeNumericComparisonInfo? {
val leftType = left.typeRef.coneTypeSafe<ConeKotlinType>() ?: return null
val rightType = right.typeRef.coneTypeSafe<ConeKotlinType>() ?: return null
val leftPrimitiveOrNullableType = leftType.getPrimitiveTypeOrSupertype() ?: return null
val rightPrimitiveOrNullableType = rightType.getPrimitiveTypeOrSupertype() ?: return null
val leftPrimitiveType = leftPrimitiveOrNullableType.withNullability(ConeNullability.NOT_NULL)
val rightPrimitiveType = rightPrimitiveOrNullableType.withNullability(ConeNullability.NOT_NULL)
val leastCommonType = leastCommonPrimitiveNumericType(leftPrimitiveOrNullableType, rightPrimitiveOrNullableType)
// TODO: Support different types with coercion
if (leftPrimitiveType != rightPrimitiveType) return null
val leastCommonType = rightPrimitiveType
return PrimitiveConeNumericComparisonInfo(
leastCommonType,
leftPrimitiveType, rightPrimitiveType,
leftPrimitiveOrNullableType, rightPrimitiveOrNullableType
)
return PrimitiveConeNumericComparisonInfo(leastCommonType, leftPrimitiveOrNullableType, rightPrimitiveOrNullableType)
}
private fun leastCommonPrimitiveNumericType(t1: ConeClassLikeType, t2: ConeClassLikeType): ConeClassLikeType {
val pt1 = t1.promoteIntegerTypeToIntIfRequired()
val pt2 = t2.promoteIntegerTypeToIntIfRequired()
return when {
pt1.isDouble() || pt2.isDouble() -> PrimitiveTypes.Double
pt1.isFloat() || pt2.isFloat() -> PrimitiveTypes.Float
pt1.isLong() || pt2.isLong() -> PrimitiveTypes.Long
pt1.isInt() || pt2.isInt() -> PrimitiveTypes.Int
else -> throw AssertionError("Unexpected types: t1=$t1, t2=$t2")
}
}
private fun ConeClassLikeType.promoteIntegerTypeToIntIfRequired(): ConeClassLikeType =
when (lookupTag.classId) {
StandardClassIds.Byte, StandardClassIds.Short -> PrimitiveTypes.Int
StandardClassIds.Long, StandardClassIds.Int, StandardClassIds.Float, StandardClassIds.Double, StandardClassIds.Char -> this
else -> throw AssertionError("Primitive number type expected: $this")
}
private fun ConeKotlinType.getPrimitiveTypeOrSupertype(): ConeClassLikeType? =
when {
this is ConeTypeParameterType ->
@@ -53,6 +66,8 @@ private fun ConeKotlinType.getPrimitiveTypeOrSupertype(): ConeClassLikeType? =
}
this is ConeClassLikeType && isPrimitiveNumberType() ->
this
this is ConeFlexibleType ->
this.lowerBound.getPrimitiveTypeOrSupertype()
else ->
null
}
@@ -33,9 +33,9 @@ import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
import java.lang.IllegalArgumentException
internal class CallAndReferenceGenerator(
private val components: Fir2IrComponents,
@@ -110,37 +110,46 @@ internal class CallAndReferenceGenerator(
return convertToUnsafeIrCall(qualifiedAccess, typeRef, explicitReceiverExpression)
}
return qualifiedAccess.convertWithOffsets { startOffset, endOffset ->
val type = typeRef.toIrType()
val callableSymbol = (qualifiedAccess.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirCallableSymbol<*>
val typeShouldBeNotNull = callableSymbol?.fir?.returnTypeRef?.coneTypeSafe<ConeKotlinType>()?.isNullable == false
val unsafeIrCall = convertToUnsafeIrCall(
qualifiedAccess, typeRef, explicitReceiverExpression, makeNotNull = typeShouldBeNotNull
val unsafeIrCall =
convertToUnsafeIrCall(qualifiedAccess, typeRef, explicitReceiverExpression, makeNotNull = typeShouldBeNotNull)
convertToSafeIrCall(
unsafeIrCall,
explicitReceiverExpression!!,
isDispatch = explicitReceiver == qualifiedAccess.dispatchReceiver
)
IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.SAFE_CALL).apply {
val receiverVariable = declarationStorage.declareTemporaryVariable(explicitReceiverExpression!!).apply {
parent = conversionScope.parentFromStack()
}
statements += receiverVariable
statements += IrWhenImpl(startOffset, endOffset, type).apply {
val variableSymbol = symbolTable.referenceValue(receiverVariable.descriptor)
val condition = IrCallImpl(
startOffset, endOffset, irBuiltIns.booleanType, irBuiltIns.eqeqSymbol, origin = IrStatementOrigin.EQEQ
).apply {
putValueArgument(0, IrGetValueImpl(startOffset, endOffset, variableSymbol))
putValueArgument(1, IrConstImpl.constNull(startOffset, endOffset, irBuiltIns.nothingNType))
}
branches += IrBranchImpl(
condition, IrConstImpl.constNull(startOffset, endOffset, irBuiltIns.nothingNType)
)
val newReceiver = IrGetValueImpl(startOffset, endOffset, variableSymbol)
val replacedCall = unsafeIrCall.replaceReceiver(
newReceiver, isDispatch = explicitReceiver == qualifiedAccess.dispatchReceiver
)
branches += IrElseBranchImpl(
IrConstImpl.boolean(startOffset, endOffset, irBuiltIns.booleanType, true),
replacedCall
)
}
}
internal fun convertToSafeIrCall(call: IrExpression, explicitReceiverExpression: IrExpression, isDispatch: Boolean): IrExpression {
val startOffset = call.startOffset
val endOffset = call.endOffset
val receiverVariable = declarationStorage.declareTemporaryVariable(explicitReceiverExpression, "safe_receiver").apply {
parent = conversionScope.parentFromStack()
}
val variableSymbol = symbolTable.referenceValue(receiverVariable.descriptor)
val resultType = call.type.makeNullable()
return IrBlockImpl(startOffset, endOffset, resultType, IrStatementOrigin.SAFE_CALL).apply {
statements += receiverVariable
statements += IrWhenImpl(startOffset, endOffset, resultType).apply {
val condition = IrCallImpl(
startOffset, endOffset, irBuiltIns.booleanType, irBuiltIns.eqeqSymbol, origin = IrStatementOrigin.EQEQ
).apply {
putValueArgument(0, IrGetValueImpl(startOffset, endOffset, variableSymbol))
putValueArgument(1, IrConstImpl.constNull(startOffset, endOffset, irBuiltIns.nothingNType))
}
branches += IrBranchImpl(
condition, IrConstImpl.constNull(startOffset, endOffset, irBuiltIns.nothingNType)
)
val newReceiver = IrGetValueImpl(startOffset, endOffset, variableSymbol)
val replacedCall = call.replaceReceiver(newReceiver, isDispatch)
branches += IrElseBranchImpl(
IrConstImpl.boolean(startOffset, endOffset, irBuiltIns.booleanType, true),
replacedCall
)
}
}
}
@@ -0,0 +1,152 @@
/*
* 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.fir.backend.generators
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.isNullable
import org.jetbrains.kotlin.ir.builders.primitiveOp1
import org.jetbrains.kotlin.ir.builders.primitiveOp2
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.getSimpleFunction
import java.util.*
internal class OperatorExpressionGenerator(
private val components: Fir2IrComponents,
private val visitor: Fir2IrVisitor,
private val callGenerator: CallAndReferenceGenerator
) : Fir2IrComponents by components {
companion object {
private val NEGATED_OPERATIONS: Set<FirOperation> = EnumSet.of(FirOperation.NOT_EQ, FirOperation.NOT_IDENTITY)
private val UNARY_OPERATIONS: Set<FirOperation> = EnumSet.of(FirOperation.EXCL)
}
fun convertComparisonExpression(comparisonExpression: FirComparisonExpression): IrExpression {
return comparisonExpression.convertWithOffsets { startOffset, endOffset ->
generateComparisonCall(startOffset, endOffset, comparisonExpression)
}
}
fun convertOperatorCall(operatorCall: FirOperatorCall): IrExpression {
return operatorCall.convertWithOffsets { startOffset, endOffset ->
generateOperatorCall(startOffset, endOffset, operatorCall.operation, operatorCall.arguments)
}
}
private fun generateComparisonCall(
startOffset: Int, endOffset: Int,
comparisonExpression: FirComparisonExpression
): IrExpression {
val operation = comparisonExpression.operation
fun fallbackToRealCall(): IrExpression {
val (symbol, origin) = getSymbolAndOriginForComparison(operation, irBuiltIns.intType.classifierOrFail)
return primitiveOp2(
startOffset, endOffset,
symbol!!,
irBuiltIns.booleanType,
origin,
comparisonExpression.compareToCall.accept(visitor, null) as IrExpression,
IrConstImpl.int(startOffset, endOffset, irBuiltIns.intType, 0)
)
}
val comparisonInfo = comparisonExpression.inferPrimitiveNumericComparisonInfo() ?: return fallbackToRealCall()
val comparisonType = comparisonInfo.comparisonType
val comparisonIrType = typeConverter.classIdToTypeMap[comparisonType.lookupTag.classId] ?: return fallbackToRealCall()
val (symbol, origin) = getSymbolAndOriginForComparison(operation, comparisonIrType.classifierOrFail)
return primitiveOp2(
startOffset, endOffset, symbol!!, irBuiltIns.booleanType, origin,
visitor.convertToIrExpression(comparisonExpression.left).asComparisonOperand(comparisonInfo.leftType, comparisonType),
visitor.convertToIrExpression(comparisonExpression.right).asComparisonOperand(comparisonInfo.rightType, comparisonType),
)
}
private fun getSymbolAndOriginForComparison(
operation: FirOperation,
classifier: IrClassifierSymbol
): Pair<IrSimpleFunctionSymbol?, IrStatementOriginImpl> {
return when (operation) {
FirOperation.LT -> irBuiltIns.lessFunByOperandType[classifier] to IrStatementOrigin.LT
FirOperation.GT -> irBuiltIns.greaterFunByOperandType[classifier] to IrStatementOrigin.GT
FirOperation.LT_EQ -> irBuiltIns.lessOrEqualFunByOperandType[classifier] to IrStatementOrigin.LTEQ
FirOperation.GT_EQ -> irBuiltIns.greaterOrEqualFunByOperandType[classifier] to IrStatementOrigin.GTEQ
else -> error("Unexpected comparison operation: $operation")
}
}
private fun generateOperatorCall(
startOffset: Int, endOffset: Int, operation: FirOperation, arguments: List<FirExpression>
): IrExpression {
val (type, symbol, origin) = when (operation) {
FirOperation.EQ -> Triple(irBuiltIns.booleanType, irBuiltIns.eqeqSymbol, IrStatementOrigin.EQEQ)
FirOperation.NOT_EQ -> Triple(irBuiltIns.booleanType, irBuiltIns.eqeqSymbol, IrStatementOrigin.EXCLEQ)
FirOperation.IDENTITY -> Triple(irBuiltIns.booleanType, irBuiltIns.eqeqeqSymbol, IrStatementOrigin.EQEQEQ)
FirOperation.NOT_IDENTITY -> Triple(irBuiltIns.booleanType, irBuiltIns.eqeqeqSymbol, IrStatementOrigin.EXCLEQEQ)
FirOperation.EXCL -> Triple(irBuiltIns.booleanType, irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL)
FirOperation.LT, FirOperation.GT,
FirOperation.LT_EQ, FirOperation.GT_EQ,
FirOperation.OTHER, FirOperation.ASSIGN, FirOperation.PLUS_ASSIGN,
FirOperation.MINUS_ASSIGN, FirOperation.TIMES_ASSIGN,
FirOperation.DIV_ASSIGN, FirOperation.REM_ASSIGN,
FirOperation.IS, FirOperation.NOT_IS,
FirOperation.AS, FirOperation.SAFE_AS
-> {
TODO("Should not be here: incompatible operation in FirOperatorCall: $operation")
}
}
val result = if (operation in UNARY_OPERATIONS) {
primitiveOp1(startOffset, endOffset, symbol, type, origin, visitor.convertToIrExpression(arguments[0]))
} else {
val comparisonInfo = inferPrimitiveNumericComparisonInfo(arguments[0], arguments[1])
val comparisonType = comparisonInfo?.comparisonType
primitiveOp2(
startOffset, endOffset, symbol, type, origin,
visitor.convertToIrExpression(arguments[0]).asComparisonOperand(comparisonInfo?.leftType, comparisonType),
visitor.convertToIrExpression(arguments[1]).asComparisonOperand(comparisonInfo?.rightType, comparisonType)
)
}
if (operation !in NEGATED_OPERATIONS) return result
return primitiveOp1(startOffset, endOffset, irBuiltIns.booleanNotSymbol, irBuiltIns.booleanType, origin, result)
}
private fun IrExpression.asComparisonOperand(
operandType: ConeClassLikeType?,
targetType: ConeClassLikeType?
): IrExpression {
if (targetType == null) return this
if (operandType == null) throw AssertionError("operandType should be non-null")
val operandClassId = operandType.lookupTag.classId
val targetClassId = targetType.lookupTag.classId
if (operandClassId == targetClassId) return this
val conversionFunction =
typeConverter.classIdToSymbolMap[operandClassId]?.getSimpleFunction("to${targetType.lookupTag.classId.shortClassName.asString()}")
?: throw AssertionError("No conversion function for $operandType ~> $targetType")
val dispatchReceiver = this@asComparisonOperand
val unsafeIrCall = IrCallImpl(startOffset, endOffset, conversionFunction.owner.returnType, conversionFunction).also {
it.dispatchReceiver = dispatchReceiver
}
return if (operandType.isNullable) {
callGenerator.convertToSafeIrCall(unsafeIrCall, dispatchReceiver, isDispatch = true)
} else {
unsafeIrCall
}
}
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
//FILE: Holder.java
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
//FILE: JavaClass.java
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// !LANGUAGE: +ProperIeee754Comparisons +NewInference
fun box(): String {
@@ -1,5 +1,4 @@
// !LANGUAGE: +ProperIeee754Comparisons
// IGNORE_BACKEND_FIR: JVM_IR
fun ltDI(x: Any, y: Any) =
x is Double && y is Int && x < y
@@ -160,8 +160,9 @@ FILE fqName:<root> fileName:/floatingPointEqeq.kt
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'x: kotlin.Any declared in <root>.testFD' type=kotlin.Any origin=null
arg0: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Float' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'x: kotlin.Any declared in <root>.testFD' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'y: kotlin.Any declared in <root>.testFD' type=kotlin.Any origin=null
BRANCH
@@ -186,8 +187,9 @@ FILE fqName:<root> fileName:/floatingPointEqeq.kt
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'x: kotlin.Any declared in <root>.testDF' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.testDF' type=kotlin.Any origin=null
arg1: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Float' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.testDF' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
@@ -173,8 +173,9 @@ FILE fqName:<root> fileName:/floatingPointExcleq.kt
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
arg0: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'x: kotlin.Any declared in <root>.testFD' type=kotlin.Any origin=null
arg0: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Float' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'x: kotlin.Any declared in <root>.testFD' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'y: kotlin.Any declared in <root>.testFD' type=kotlin.Any origin=null
BRANCH
@@ -200,8 +201,9 @@ FILE fqName:<root> fileName:/floatingPointExcleq.kt
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
arg0: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'x: kotlin.Any declared in <root>.testDF' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.testDF' type=kotlin.Any origin=null
arg1: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Float' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.testDF' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
@@ -1,149 +0,0 @@
FILE fqName:<root> fileName:/floatingPointLess.kt
FUN name:test1d visibility:public modality:FINAL <> (x:kotlin.Double, y:kotlin.Double) returnType:kotlin.Boolean
VALUE_PARAMETER name:x index:0 type:kotlin.Double
VALUE_PARAMETER name:y index:1 type:kotlin.Double
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test1d (x: kotlin.Double, y: kotlin.Double): kotlin.Boolean declared in <root>'
CALL 'public final fun less (arg0: kotlin.Double, arg1: kotlin.Double): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: GET_VAR 'x: kotlin.Double declared in <root>.test1d' type=kotlin.Double origin=null
arg1: GET_VAR 'y: kotlin.Double declared in <root>.test1d' type=kotlin.Double origin=null
FUN name:test2d visibility:public modality:FINAL <> (x:kotlin.Double, y:kotlin.Any) returnType:kotlin.Boolean
VALUE_PARAMETER name:x index:0 type:kotlin.Double
VALUE_PARAMETER name:y index:1 type:kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test2d (x: kotlin.Double, y: kotlin.Any): kotlin.Boolean declared in <root>'
WHEN type=kotlin.Boolean origin=ANDAND
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Double
GET_VAR 'y: kotlin.Any declared in <root>.test2d' type=kotlin.Any origin=null
then: CALL 'public final fun less (arg0: kotlin.Double, arg1: kotlin.Double): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: GET_VAR 'x: kotlin.Double declared in <root>.test2d' type=kotlin.Double origin=null
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'y: kotlin.Any declared in <root>.test2d' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
FUN name:test3d visibility:public modality:FINAL <> (x:kotlin.Any, y:kotlin.Any) returnType:kotlin.Boolean
VALUE_PARAMETER name:x index:0 type:kotlin.Any
VALUE_PARAMETER name:y index:1 type:kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test3d (x: kotlin.Any, y: kotlin.Any): kotlin.Boolean declared in <root>'
WHEN type=kotlin.Boolean origin=ANDAND
BRANCH
if: WHEN type=kotlin.Boolean origin=ANDAND
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Double
GET_VAR 'x: kotlin.Any declared in <root>.test3d' type=kotlin.Any origin=null
then: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Double
GET_VAR 'y: kotlin.Any declared in <root>.test3d' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'public final fun less (arg0: kotlin.Double, arg1: kotlin.Double): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'x: kotlin.Any declared in <root>.test3d' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'y: kotlin.Any declared in <root>.test3d' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
FUN name:test1f visibility:public modality:FINAL <> (x:kotlin.Float, y:kotlin.Float) returnType:kotlin.Boolean
VALUE_PARAMETER name:x index:0 type:kotlin.Float
VALUE_PARAMETER name:y index:1 type:kotlin.Float
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test1f (x: kotlin.Float, y: kotlin.Float): kotlin.Boolean declared in <root>'
CALL 'public final fun less (arg0: kotlin.Float, arg1: kotlin.Float): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: GET_VAR 'x: kotlin.Float declared in <root>.test1f' type=kotlin.Float origin=null
arg1: GET_VAR 'y: kotlin.Float declared in <root>.test1f' type=kotlin.Float origin=null
FUN name:test2f visibility:public modality:FINAL <> (x:kotlin.Float, y:kotlin.Any) returnType:kotlin.Boolean
VALUE_PARAMETER name:x index:0 type:kotlin.Float
VALUE_PARAMETER name:y index:1 type:kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test2f (x: kotlin.Float, y: kotlin.Any): kotlin.Boolean declared in <root>'
WHEN type=kotlin.Boolean origin=ANDAND
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.test2f' type=kotlin.Any origin=null
then: CALL 'public final fun less (arg0: kotlin.Float, arg1: kotlin.Float): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: GET_VAR 'x: kotlin.Float declared in <root>.test2f' type=kotlin.Float origin=null
arg1: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.test2f' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
FUN name:test3f visibility:public modality:FINAL <> (x:kotlin.Any, y:kotlin.Any) returnType:kotlin.Boolean
VALUE_PARAMETER name:x index:0 type:kotlin.Any
VALUE_PARAMETER name:y index:1 type:kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test3f (x: kotlin.Any, y: kotlin.Any): kotlin.Boolean declared in <root>'
WHEN type=kotlin.Boolean origin=ANDAND
BRANCH
if: WHEN type=kotlin.Boolean origin=ANDAND
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Float
GET_VAR 'x: kotlin.Any declared in <root>.test3f' type=kotlin.Any origin=null
then: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.test3f' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'public final fun less (arg0: kotlin.Float, arg1: kotlin.Float): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'x: kotlin.Any declared in <root>.test3f' type=kotlin.Any origin=null
arg1: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.test3f' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
FUN name:testFD visibility:public modality:FINAL <> (x:kotlin.Any, y:kotlin.Any) returnType:kotlin.Boolean
VALUE_PARAMETER name:x index:0 type:kotlin.Any
VALUE_PARAMETER name:y index:1 type:kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testFD (x: kotlin.Any, y: kotlin.Any): kotlin.Boolean declared in <root>'
WHEN type=kotlin.Boolean origin=ANDAND
BRANCH
if: WHEN type=kotlin.Boolean origin=ANDAND
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Float
GET_VAR 'x: kotlin.Any declared in <root>.testFD' type=kotlin.Any origin=null
then: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Double
GET_VAR 'y: kotlin.Any declared in <root>.testFD' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: CALL 'public final fun compareTo (other: kotlin.Double): kotlin.Int [operator] declared in kotlin.Float' type=kotlin.Int origin=null
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'x: kotlin.Any declared in <root>.testFD' type=kotlin.Any origin=null
other: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'y: kotlin.Any declared in <root>.testFD' type=kotlin.Any origin=null
arg1: CONST Int type=kotlin.Int value=0
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
FUN name:testDF visibility:public modality:FINAL <> (x:kotlin.Any, y:kotlin.Any) returnType:kotlin.Boolean
VALUE_PARAMETER name:x index:0 type:kotlin.Any
VALUE_PARAMETER name:y index:1 type:kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testDF (x: kotlin.Any, y: kotlin.Any): kotlin.Boolean declared in <root>'
WHEN type=kotlin.Boolean origin=ANDAND
BRANCH
if: WHEN type=kotlin.Boolean origin=ANDAND
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Double
GET_VAR 'x: kotlin.Any declared in <root>.testDF' type=kotlin.Any origin=null
then: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.testDF' type=kotlin.Any origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: CALL 'public final fun compareTo (other: kotlin.Float): kotlin.Int [operator] declared in kotlin.Double' type=kotlin.Int origin=null
$this: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'x: kotlin.Any declared in <root>.testDF' type=kotlin.Any origin=null
other: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.testDF' type=kotlin.Any origin=null
arg1: CONST Int type=kotlin.Int value=0
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
fun test1d(x: Double, y: Double) = x < y
fun test2d(x: Double, y: Any) = y is Double && x < y
fun test3d(x: Any, y: Any) = x is Double && y is Double && x < y
@@ -8,12 +8,11 @@ FILE fqName:<root> fileName:/nullableAnyAsIntToDouble.kt
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any? declared in <root>.test' type=kotlin.Any? origin=null
then: CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: CALL 'public final fun compareTo (other: kotlin.Double): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
then: CALL 'public final fun less (arg0: kotlin.Double, arg1: kotlin.Double): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Int' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any? declared in <root>.test' type=kotlin.Any? origin=null
other: GET_VAR 'y: kotlin.Double declared in <root>.test' type=kotlin.Double origin=null
arg1: CONST Int type=kotlin.Int value=0
arg1: GET_VAR 'y: kotlin.Double declared in <root>.test' type=kotlin.Double origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
@@ -18,8 +18,20 @@ FILE fqName:<root> fileName:/nullableFloatingPointEqeq.kt
GET_VAR 'y: kotlin.Any? declared in <root>.testDF' type=kotlin.Any? origin=null
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'x: kotlin.Double? declared in <root>.testDF' type=kotlin.Double? origin=null
arg1: TYPE_OP type=kotlin.Float? origin=IMPLICIT_CAST typeOperand=kotlin.Float?
GET_VAR 'y: kotlin.Any? declared in <root>.testDF' type=kotlin.Any? origin=null
arg1: BLOCK type=kotlin.Double? origin=SAFE_CALL
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Float? [val]
TYPE_OP type=kotlin.Float? origin=IMPLICIT_CAST typeOperand=kotlin.Float?
GET_VAR 'y: kotlin.Any? declared in <root>.testDF' type=kotlin.Any? origin=null
WHEN type=kotlin.Double? origin=null
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_0: kotlin.Float? [val] declared in <root>.testDF' type=kotlin.Float? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST Null type=kotlin.Nothing? value=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Float' type=kotlin.Double origin=null
$this: GET_VAR 'val tmp_0: kotlin.Float? [val] declared in <root>.testDF' type=kotlin.Float? origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
@@ -34,8 +46,20 @@ FILE fqName:<root> fileName:/nullableFloatingPointEqeq.kt
GET_VAR 'y: kotlin.Any? declared in <root>.testDI' type=kotlin.Any? origin=null
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'x: kotlin.Double? declared in <root>.testDI' type=kotlin.Double? origin=null
arg1: TYPE_OP type=kotlin.Int? origin=IMPLICIT_CAST typeOperand=kotlin.Int?
GET_VAR 'y: kotlin.Any? declared in <root>.testDI' type=kotlin.Any? origin=null
arg1: BLOCK type=kotlin.Double? origin=SAFE_CALL
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int? [val]
TYPE_OP type=kotlin.Int? origin=IMPLICIT_CAST typeOperand=kotlin.Int?
GET_VAR 'y: kotlin.Any? declared in <root>.testDI' type=kotlin.Any? origin=null
WHEN type=kotlin.Double? origin=null
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_1: kotlin.Int? [val] declared in <root>.testDI' type=kotlin.Int? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST Null type=kotlin.Nothing? value=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Int' type=kotlin.Double origin=null
$this: GET_VAR 'val tmp_1: kotlin.Int? [val] declared in <root>.testDI' type=kotlin.Int? origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
@@ -56,8 +80,20 @@ FILE fqName:<root> fileName:/nullableFloatingPointEqeq.kt
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Boolean type=kotlin.Boolean value=false
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: TYPE_OP type=kotlin.Int? origin=IMPLICIT_CAST typeOperand=kotlin.Int?
GET_VAR 'x: kotlin.Any? declared in <root>.testDI2' type=kotlin.Any? origin=null
arg0: BLOCK type=kotlin.Double? origin=SAFE_CALL
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.Int? [val]
TYPE_OP type=kotlin.Int? origin=IMPLICIT_CAST typeOperand=kotlin.Int?
GET_VAR 'x: kotlin.Any? declared in <root>.testDI2' type=kotlin.Any? origin=null
WHEN type=kotlin.Double? origin=null
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_2: kotlin.Int? [val] declared in <root>.testDI2' type=kotlin.Int? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST Null type=kotlin.Nothing? value=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Int' type=kotlin.Double origin=null
$this: GET_VAR 'val tmp_2: kotlin.Int? [val] declared in <root>.testDI2' type=kotlin.Int? origin=null
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'y: kotlin.Any? declared in <root>.testDI2' type=kotlin.Any? origin=null
BRANCH
@@ -44,8 +44,9 @@ FILE fqName:<root> fileName:/typeParameterWithPrimitiveNumericSupertype.kt
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Float
GET_VAR 'x: kotlin.Any declared in <root>.test2' type=kotlin.Any origin=null
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'x: kotlin.Any declared in <root>.test2' type=kotlin.Any origin=null
arg0: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Float' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'x: kotlin.Any declared in <root>.test2' type=kotlin.Any origin=null
arg1: GET_VAR 'y: T of <root>.test2 declared in <root>.test2' type=T of <root>.test2 origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -61,8 +62,9 @@ FILE fqName:<root> fileName:/typeParameterWithPrimitiveNumericSupertype.kt
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any declared in <root>.test3' type=kotlin.Any origin=null
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any declared in <root>.test3' type=kotlin.Any origin=null
arg0: CALL 'public open fun toFloat (): kotlin.Float declared in kotlin.Int' type=kotlin.Float origin=null
$this: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any declared in <root>.test3' type=kotlin.Any origin=null
arg1: GET_VAR 'y: T of <root>.test3 declared in <root>.test3' type=T of <root>.test3 origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -78,8 +80,9 @@ FILE fqName:<root> fileName:/typeParameterWithPrimitiveNumericSupertype.kt
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any declared in <root>.test4' type=kotlin.Any origin=null
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any declared in <root>.test4' type=kotlin.Any origin=null
arg0: CALL 'public open fun toFloat (): kotlin.Float declared in kotlin.Int' type=kotlin.Float origin=null
$this: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any declared in <root>.test4' type=kotlin.Any origin=null
arg1: GET_VAR 'y: T of <root>.test4 declared in <root>.test4' type=T of <root>.test4 origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -96,8 +99,9 @@ FILE fqName:<root> fileName:/typeParameterWithPrimitiveNumericSupertype.kt
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any declared in <root>.test5' type=kotlin.Any origin=null
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any declared in <root>.test5' type=kotlin.Any origin=null
arg0: CALL 'public open fun toFloat (): kotlin.Float declared in kotlin.Int' type=kotlin.Float origin=null
$this: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
GET_VAR 'x: kotlin.Any declared in <root>.test5' type=kotlin.Any origin=null
arg1: GET_VAR 'y: R of <root>.test5 declared in <root>.test5' type=R of <root>.test5 origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -137,7 +141,8 @@ FILE fqName:<root> fileName:/typeParameterWithPrimitiveNumericSupertype.kt
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Double
GET_VAR 'y: kotlin.Any declared in <root>.F.testCapturedType' type=kotlin.Any origin=null
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'x: T of <root>.F declared in <root>.F.testCapturedType' type=T of <root>.F origin=null
arg0: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Float' type=kotlin.Double origin=null
$this: GET_VAR 'x: T of <root>.F declared in <root>.F.testCapturedType' type=T of <root>.F origin=null
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
GET_VAR 'y: kotlin.Any declared in <root>.F.testCapturedType' type=kotlin.Any origin=null
BRANCH
@@ -112,8 +112,9 @@ FILE fqName:<root> fileName:/whenByFloatingPoint.kt
BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'val tmp_4: kotlin.Double [val] declared in <root>.testSmartCastToDifferentTypes' type=kotlin.Double origin=null
arg1: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.testSmartCastToDifferentTypes' type=kotlin.Any origin=null
arg1: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Float' type=kotlin.Double origin=null
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
GET_VAR 'y: kotlin.Any declared in <root>.testSmartCastToDifferentTypes' type=kotlin.Any origin=null
then: CONST Int type=kotlin.Int value=0
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
@@ -1,209 +0,0 @@
FILE fqName:<root> fileName:/primitiveComparisons.kt
FUN name:btest1 visibility:public modality:FINAL <> (a:kotlin.Byte, b:kotlin.Byte) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Byte
VALUE_PARAMETER name:b index:1 type:kotlin.Byte
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun btest1 (a: kotlin.Byte, b: kotlin.Byte): kotlin.Boolean declared in <root>'
CALL 'public final fun greater (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GT
arg0: CALL 'public open fun compareTo (other: kotlin.Byte): kotlin.Int [operator] declared in kotlin.Byte' type=kotlin.Int origin=null
$this: GET_VAR 'a: kotlin.Byte declared in <root>.btest1' type=kotlin.Byte origin=null
other: GET_VAR 'b: kotlin.Byte declared in <root>.btest1' type=kotlin.Byte origin=null
arg1: CONST Int type=kotlin.Int value=0
FUN name:btest2 visibility:public modality:FINAL <> (a:kotlin.Byte, b:kotlin.Byte) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Byte
VALUE_PARAMETER name:b index:1 type:kotlin.Byte
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun btest2 (a: kotlin.Byte, b: kotlin.Byte): kotlin.Boolean declared in <root>'
CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: CALL 'public open fun compareTo (other: kotlin.Byte): kotlin.Int [operator] declared in kotlin.Byte' type=kotlin.Int origin=null
$this: GET_VAR 'a: kotlin.Byte declared in <root>.btest2' type=kotlin.Byte origin=null
other: GET_VAR 'b: kotlin.Byte declared in <root>.btest2' type=kotlin.Byte origin=null
arg1: CONST Int type=kotlin.Int value=0
FUN name:btest3 visibility:public modality:FINAL <> (a:kotlin.Byte, b:kotlin.Byte) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Byte
VALUE_PARAMETER name:b index:1 type:kotlin.Byte
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun btest3 (a: kotlin.Byte, b: kotlin.Byte): kotlin.Boolean declared in <root>'
CALL 'public final fun greaterOrEqual (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GTEQ
arg0: CALL 'public open fun compareTo (other: kotlin.Byte): kotlin.Int [operator] declared in kotlin.Byte' type=kotlin.Int origin=null
$this: GET_VAR 'a: kotlin.Byte declared in <root>.btest3' type=kotlin.Byte origin=null
other: GET_VAR 'b: kotlin.Byte declared in <root>.btest3' type=kotlin.Byte origin=null
arg1: CONST Int type=kotlin.Int value=0
FUN name:btest4 visibility:public modality:FINAL <> (a:kotlin.Byte, b:kotlin.Byte) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Byte
VALUE_PARAMETER name:b index:1 type:kotlin.Byte
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun btest4 (a: kotlin.Byte, b: kotlin.Byte): kotlin.Boolean declared in <root>'
CALL 'public final fun lessOrEqual (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LTEQ
arg0: CALL 'public open fun compareTo (other: kotlin.Byte): kotlin.Int [operator] declared in kotlin.Byte' type=kotlin.Int origin=null
$this: GET_VAR 'a: kotlin.Byte declared in <root>.btest4' type=kotlin.Byte origin=null
other: GET_VAR 'b: kotlin.Byte declared in <root>.btest4' type=kotlin.Byte origin=null
arg1: CONST Int type=kotlin.Int value=0
FUN name:stest1 visibility:public modality:FINAL <> (a:kotlin.Short, b:kotlin.Short) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Short
VALUE_PARAMETER name:b index:1 type:kotlin.Short
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun stest1 (a: kotlin.Short, b: kotlin.Short): kotlin.Boolean declared in <root>'
CALL 'public final fun greater (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GT
arg0: CALL 'public open fun compareTo (other: kotlin.Short): kotlin.Int [operator] declared in kotlin.Short' type=kotlin.Int origin=null
$this: GET_VAR 'a: kotlin.Short declared in <root>.stest1' type=kotlin.Short origin=null
other: GET_VAR 'b: kotlin.Short declared in <root>.stest1' type=kotlin.Short origin=null
arg1: CONST Int type=kotlin.Int value=0
FUN name:stest2 visibility:public modality:FINAL <> (a:kotlin.Short, b:kotlin.Short) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Short
VALUE_PARAMETER name:b index:1 type:kotlin.Short
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun stest2 (a: kotlin.Short, b: kotlin.Short): kotlin.Boolean declared in <root>'
CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: CALL 'public open fun compareTo (other: kotlin.Short): kotlin.Int [operator] declared in kotlin.Short' type=kotlin.Int origin=null
$this: GET_VAR 'a: kotlin.Short declared in <root>.stest2' type=kotlin.Short origin=null
other: GET_VAR 'b: kotlin.Short declared in <root>.stest2' type=kotlin.Short origin=null
arg1: CONST Int type=kotlin.Int value=0
FUN name:stest3 visibility:public modality:FINAL <> (a:kotlin.Short, b:kotlin.Short) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Short
VALUE_PARAMETER name:b index:1 type:kotlin.Short
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun stest3 (a: kotlin.Short, b: kotlin.Short): kotlin.Boolean declared in <root>'
CALL 'public final fun greaterOrEqual (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GTEQ
arg0: CALL 'public open fun compareTo (other: kotlin.Short): kotlin.Int [operator] declared in kotlin.Short' type=kotlin.Int origin=null
$this: GET_VAR 'a: kotlin.Short declared in <root>.stest3' type=kotlin.Short origin=null
other: GET_VAR 'b: kotlin.Short declared in <root>.stest3' type=kotlin.Short origin=null
arg1: CONST Int type=kotlin.Int value=0
FUN name:stest4 visibility:public modality:FINAL <> (a:kotlin.Short, b:kotlin.Short) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Short
VALUE_PARAMETER name:b index:1 type:kotlin.Short
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun stest4 (a: kotlin.Short, b: kotlin.Short): kotlin.Boolean declared in <root>'
CALL 'public final fun lessOrEqual (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LTEQ
arg0: CALL 'public open fun compareTo (other: kotlin.Short): kotlin.Int [operator] declared in kotlin.Short' type=kotlin.Int origin=null
$this: GET_VAR 'a: kotlin.Short declared in <root>.stest4' type=kotlin.Short origin=null
other: GET_VAR 'b: kotlin.Short declared in <root>.stest4' type=kotlin.Short origin=null
arg1: CONST Int type=kotlin.Int value=0
FUN name:itest1 visibility:public modality:FINAL <> (a:kotlin.Int, b:kotlin.Int) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Int
VALUE_PARAMETER name:b index:1 type:kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun itest1 (a: kotlin.Int, b: kotlin.Int): kotlin.Boolean declared in <root>'
CALL 'public final fun greater (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GT
arg0: GET_VAR 'a: kotlin.Int declared in <root>.itest1' type=kotlin.Int origin=null
arg1: GET_VAR 'b: kotlin.Int declared in <root>.itest1' type=kotlin.Int origin=null
FUN name:itest2 visibility:public modality:FINAL <> (a:kotlin.Int, b:kotlin.Int) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Int
VALUE_PARAMETER name:b index:1 type:kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun itest2 (a: kotlin.Int, b: kotlin.Int): kotlin.Boolean declared in <root>'
CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: GET_VAR 'a: kotlin.Int declared in <root>.itest2' type=kotlin.Int origin=null
arg1: GET_VAR 'b: kotlin.Int declared in <root>.itest2' type=kotlin.Int origin=null
FUN name:itest3 visibility:public modality:FINAL <> (a:kotlin.Int, b:kotlin.Int) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Int
VALUE_PARAMETER name:b index:1 type:kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun itest3 (a: kotlin.Int, b: kotlin.Int): kotlin.Boolean declared in <root>'
CALL 'public final fun greaterOrEqual (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GTEQ
arg0: GET_VAR 'a: kotlin.Int declared in <root>.itest3' type=kotlin.Int origin=null
arg1: GET_VAR 'b: kotlin.Int declared in <root>.itest3' type=kotlin.Int origin=null
FUN name:itest4 visibility:public modality:FINAL <> (a:kotlin.Int, b:kotlin.Int) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Int
VALUE_PARAMETER name:b index:1 type:kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun itest4 (a: kotlin.Int, b: kotlin.Int): kotlin.Boolean declared in <root>'
CALL 'public final fun lessOrEqual (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LTEQ
arg0: GET_VAR 'a: kotlin.Int declared in <root>.itest4' type=kotlin.Int origin=null
arg1: GET_VAR 'b: kotlin.Int declared in <root>.itest4' type=kotlin.Int origin=null
FUN name:ltest1 visibility:public modality:FINAL <> (a:kotlin.Long, b:kotlin.Long) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Long
VALUE_PARAMETER name:b index:1 type:kotlin.Long
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun ltest1 (a: kotlin.Long, b: kotlin.Long): kotlin.Boolean declared in <root>'
CALL 'public final fun greater (arg0: kotlin.Long, arg1: kotlin.Long): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GT
arg0: GET_VAR 'a: kotlin.Long declared in <root>.ltest1' type=kotlin.Long origin=null
arg1: GET_VAR 'b: kotlin.Long declared in <root>.ltest1' type=kotlin.Long origin=null
FUN name:ltest2 visibility:public modality:FINAL <> (a:kotlin.Long, b:kotlin.Long) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Long
VALUE_PARAMETER name:b index:1 type:kotlin.Long
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun ltest2 (a: kotlin.Long, b: kotlin.Long): kotlin.Boolean declared in <root>'
CALL 'public final fun less (arg0: kotlin.Long, arg1: kotlin.Long): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: GET_VAR 'a: kotlin.Long declared in <root>.ltest2' type=kotlin.Long origin=null
arg1: GET_VAR 'b: kotlin.Long declared in <root>.ltest2' type=kotlin.Long origin=null
FUN name:ltest3 visibility:public modality:FINAL <> (a:kotlin.Long, b:kotlin.Long) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Long
VALUE_PARAMETER name:b index:1 type:kotlin.Long
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun ltest3 (a: kotlin.Long, b: kotlin.Long): kotlin.Boolean declared in <root>'
CALL 'public final fun greaterOrEqual (arg0: kotlin.Long, arg1: kotlin.Long): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GTEQ
arg0: GET_VAR 'a: kotlin.Long declared in <root>.ltest3' type=kotlin.Long origin=null
arg1: GET_VAR 'b: kotlin.Long declared in <root>.ltest3' type=kotlin.Long origin=null
FUN name:ltest4 visibility:public modality:FINAL <> (a:kotlin.Long, b:kotlin.Long) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Long
VALUE_PARAMETER name:b index:1 type:kotlin.Long
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun ltest4 (a: kotlin.Long, b: kotlin.Long): kotlin.Boolean declared in <root>'
CALL 'public final fun lessOrEqual (arg0: kotlin.Long, arg1: kotlin.Long): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LTEQ
arg0: GET_VAR 'a: kotlin.Long declared in <root>.ltest4' type=kotlin.Long origin=null
arg1: GET_VAR 'b: kotlin.Long declared in <root>.ltest4' type=kotlin.Long origin=null
FUN name:ftest1 visibility:public modality:FINAL <> (a:kotlin.Float, b:kotlin.Float) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Float
VALUE_PARAMETER name:b index:1 type:kotlin.Float
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun ftest1 (a: kotlin.Float, b: kotlin.Float): kotlin.Boolean declared in <root>'
CALL 'public final fun greater (arg0: kotlin.Float, arg1: kotlin.Float): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GT
arg0: GET_VAR 'a: kotlin.Float declared in <root>.ftest1' type=kotlin.Float origin=null
arg1: GET_VAR 'b: kotlin.Float declared in <root>.ftest1' type=kotlin.Float origin=null
FUN name:ftest2 visibility:public modality:FINAL <> (a:kotlin.Float, b:kotlin.Float) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Float
VALUE_PARAMETER name:b index:1 type:kotlin.Float
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun ftest2 (a: kotlin.Float, b: kotlin.Float): kotlin.Boolean declared in <root>'
CALL 'public final fun less (arg0: kotlin.Float, arg1: kotlin.Float): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: GET_VAR 'a: kotlin.Float declared in <root>.ftest2' type=kotlin.Float origin=null
arg1: GET_VAR 'b: kotlin.Float declared in <root>.ftest2' type=kotlin.Float origin=null
FUN name:ftest3 visibility:public modality:FINAL <> (a:kotlin.Float, b:kotlin.Float) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Float
VALUE_PARAMETER name:b index:1 type:kotlin.Float
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun ftest3 (a: kotlin.Float, b: kotlin.Float): kotlin.Boolean declared in <root>'
CALL 'public final fun greaterOrEqual (arg0: kotlin.Float, arg1: kotlin.Float): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GTEQ
arg0: GET_VAR 'a: kotlin.Float declared in <root>.ftest3' type=kotlin.Float origin=null
arg1: GET_VAR 'b: kotlin.Float declared in <root>.ftest3' type=kotlin.Float origin=null
FUN name:ftest4 visibility:public modality:FINAL <> (a:kotlin.Float, b:kotlin.Float) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Float
VALUE_PARAMETER name:b index:1 type:kotlin.Float
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun ftest4 (a: kotlin.Float, b: kotlin.Float): kotlin.Boolean declared in <root>'
CALL 'public final fun lessOrEqual (arg0: kotlin.Float, arg1: kotlin.Float): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LTEQ
arg0: GET_VAR 'a: kotlin.Float declared in <root>.ftest4' type=kotlin.Float origin=null
arg1: GET_VAR 'b: kotlin.Float declared in <root>.ftest4' type=kotlin.Float origin=null
FUN name:dtest1 visibility:public modality:FINAL <> (a:kotlin.Double, b:kotlin.Double) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Double
VALUE_PARAMETER name:b index:1 type:kotlin.Double
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun dtest1 (a: kotlin.Double, b: kotlin.Double): kotlin.Boolean declared in <root>'
CALL 'public final fun greater (arg0: kotlin.Double, arg1: kotlin.Double): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GT
arg0: GET_VAR 'a: kotlin.Double declared in <root>.dtest1' type=kotlin.Double origin=null
arg1: GET_VAR 'b: kotlin.Double declared in <root>.dtest1' type=kotlin.Double origin=null
FUN name:dtest2 visibility:public modality:FINAL <> (a:kotlin.Double, b:kotlin.Double) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Double
VALUE_PARAMETER name:b index:1 type:kotlin.Double
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun dtest2 (a: kotlin.Double, b: kotlin.Double): kotlin.Boolean declared in <root>'
CALL 'public final fun less (arg0: kotlin.Double, arg1: kotlin.Double): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: GET_VAR 'a: kotlin.Double declared in <root>.dtest2' type=kotlin.Double origin=null
arg1: GET_VAR 'b: kotlin.Double declared in <root>.dtest2' type=kotlin.Double origin=null
FUN name:dtest3 visibility:public modality:FINAL <> (a:kotlin.Double, b:kotlin.Double) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Double
VALUE_PARAMETER name:b index:1 type:kotlin.Double
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun dtest3 (a: kotlin.Double, b: kotlin.Double): kotlin.Boolean declared in <root>'
CALL 'public final fun greaterOrEqual (arg0: kotlin.Double, arg1: kotlin.Double): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GTEQ
arg0: GET_VAR 'a: kotlin.Double declared in <root>.dtest3' type=kotlin.Double origin=null
arg1: GET_VAR 'b: kotlin.Double declared in <root>.dtest3' type=kotlin.Double origin=null
FUN name:dtest4 visibility:public modality:FINAL <> (a:kotlin.Double, b:kotlin.Double) returnType:kotlin.Boolean
VALUE_PARAMETER name:a index:0 type:kotlin.Double
VALUE_PARAMETER name:b index:1 type:kotlin.Double
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun dtest4 (a: kotlin.Double, b: kotlin.Double): kotlin.Boolean declared in <root>'
CALL 'public final fun lessOrEqual (arg0: kotlin.Double, arg1: kotlin.Double): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LTEQ
arg0: GET_VAR 'a: kotlin.Double declared in <root>.dtest4' type=kotlin.Double origin=null
arg1: GET_VAR 'b: kotlin.Double declared in <root>.dtest4' type=kotlin.Double origin=null
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
fun btest1(a: Byte, b: Byte) = a > b
fun btest2(a: Byte, b: Byte) = a < b
fun btest3(a: Byte, b: Byte) = a >= b