diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 545af58654b..2f61d66db4e 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -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(), IrGeneratorContextInterface { - companion object { - private val NEGATED_OPERATIONS: Set = EnumSet.of(FirOperation.NOT_EQ, FirOperation.NOT_IDENTITY) - - private val UNARY_OPERATIONS: Set = 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 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 { - 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 - ): 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 -> diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/PrimitiveComparison.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/PrimitiveComparison.kt index 648508605d1..a880716c225 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/PrimitiveComparison.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/PrimitiveComparison.kt @@ -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() ?: return null val rightType = right.typeRef.coneTypeSafe() ?: 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 } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index b50457e4111..7768005e3cf 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -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()?.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 + ) } } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/OperatorExpressionGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/OperatorExpressionGenerator.kt new file mode 100644 index 00000000000..c56e35f44e7 --- /dev/null +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/OperatorExpressionGenerator.kt @@ -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 = EnumSet.of(FirOperation.NOT_EQ, FirOperation.NOT_IDENTITY) + + private val UNARY_OPERATIONS: Set = 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 { + 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 + ): 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 + } + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt b/compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt index 10684f1c621..8c00f604620 100644 --- a/compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt +++ b/compiler/testData/codegen/box/binaryOp/compareWithBoxedDouble.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM //FILE: Holder.java diff --git a/compiler/testData/codegen/box/binaryOp/compareWithBoxedLong.kt b/compiler/testData/codegen/box/binaryOp/compareWithBoxedLong.kt index 4ea96bca7ac..fb90b33fa9d 100644 --- a/compiler/testData/codegen/box/binaryOp/compareWithBoxedLong.kt +++ b/compiler/testData/codegen/box/binaryOp/compareWithBoxedLong.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM //FILE: JavaClass.java diff --git a/compiler/testData/codegen/box/ieee754/lessDouble_properIeeeAndNewInference.kt b/compiler/testData/codegen/box/ieee754/lessDouble_properIeeeAndNewInference.kt index 249851377b8..d5f0f13e4ba 100644 --- a/compiler/testData/codegen/box/ieee754/lessDouble_properIeeeAndNewInference.kt +++ b/compiler/testData/codegen/box/ieee754/lessDouble_properIeeeAndNewInference.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // !LANGUAGE: +ProperIeee754Comparisons +NewInference fun box(): String { diff --git a/compiler/testData/codegen/box/ir/primitiveNumberComparisons/mixedNumberTypes.kt b/compiler/testData/codegen/box/ir/primitiveNumberComparisons/mixedNumberTypes.kt index 8c545129cc9..103bf360ed7 100644 --- a/compiler/testData/codegen/box/ir/primitiveNumberComparisons/mixedNumberTypes.kt +++ b/compiler/testData/codegen/box/ir/primitiveNumberComparisons/mixedNumberTypes.kt @@ -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 diff --git a/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointEqeq.fir.txt b/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointEqeq.fir.txt index 952dc49121e..883f885fd26 100644 --- a/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointEqeq.fir.txt +++ b/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointEqeq.fir.txt @@ -160,8 +160,9 @@ FILE fqName: 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 .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 .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 .testFD' type=kotlin.Any origin=null BRANCH @@ -186,8 +187,9 @@ FILE fqName: 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 .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 .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 .testDF' type=kotlin.Any origin=null BRANCH if: CONST Boolean type=kotlin.Boolean value=true then: CONST Boolean type=kotlin.Boolean value=false diff --git a/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointExcleq.fir.txt b/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointExcleq.fir.txt index b1de33c5e5a..98b6b01fa00 100644 --- a/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointExcleq.fir.txt +++ b/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointExcleq.fir.txt @@ -173,8 +173,9 @@ FILE fqName: 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 .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 .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 .testFD' type=kotlin.Any origin=null BRANCH @@ -200,8 +201,9 @@ FILE fqName: 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 .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 .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 .testDF' type=kotlin.Any origin=null BRANCH if: CONST Boolean type=kotlin.Boolean value=true then: CONST Boolean type=kotlin.Boolean value=false diff --git a/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointLess.fir.txt b/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointLess.fir.txt deleted file mode 100644 index 95a5c8de757..00000000000 --- a/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointLess.fir.txt +++ /dev/null @@ -1,149 +0,0 @@ -FILE fqName: 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 ' - 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 .test1d' type=kotlin.Double origin=null - arg1: GET_VAR 'y: kotlin.Double declared in .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 ' - 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 .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 .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 .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 ' - 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 .test3d' type=kotlin.Any origin=null - then: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Double - GET_VAR 'y: kotlin.Any declared in .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 .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 .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 ' - 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 .test1f' type=kotlin.Float origin=null - arg1: GET_VAR 'y: kotlin.Float declared in .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 ' - 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 .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 .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 .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 ' - 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 .test3f' type=kotlin.Any origin=null - then: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Float - GET_VAR 'y: kotlin.Any declared in .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 .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 .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 ' - 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 .testFD' type=kotlin.Any origin=null - then: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Double - GET_VAR 'y: kotlin.Any declared in .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 .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 .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 ' - 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 .testDF' type=kotlin.Any origin=null - then: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Float - GET_VAR 'y: kotlin.Any declared in .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 .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 .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 diff --git a/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointLess.kt b/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointLess.kt index 0024bfe4846..a35ca688b83 100644 --- a/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointLess.kt +++ b/compiler/testData/ir/irText/expressions/floatingPointComparisons/floatingPointLess.kt @@ -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 diff --git a/compiler/testData/ir/irText/expressions/floatingPointComparisons/nullableAnyAsIntToDouble.fir.txt b/compiler/testData/ir/irText/expressions/floatingPointComparisons/nullableAnyAsIntToDouble.fir.txt index 6feca7245cc..c9b9b99b311 100644 --- a/compiler/testData/ir/irText/expressions/floatingPointComparisons/nullableAnyAsIntToDouble.fir.txt +++ b/compiler/testData/ir/irText/expressions/floatingPointComparisons/nullableAnyAsIntToDouble.fir.txt @@ -8,12 +8,11 @@ FILE fqName: fileName:/nullableAnyAsIntToDouble.kt BRANCH if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int GET_VAR 'x: kotlin.Any? declared in .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 .test' type=kotlin.Any? origin=null - other: GET_VAR 'y: kotlin.Double declared in .test' type=kotlin.Double origin=null - arg1: CONST Int type=kotlin.Int value=0 + arg1: GET_VAR 'y: kotlin.Double declared in .test' type=kotlin.Double origin=null BRANCH if: CONST Boolean type=kotlin.Boolean value=true then: CONST Boolean type=kotlin.Boolean value=false diff --git a/compiler/testData/ir/irText/expressions/floatingPointComparisons/nullableFloatingPointEqeq.fir.txt b/compiler/testData/ir/irText/expressions/floatingPointComparisons/nullableFloatingPointEqeq.fir.txt index 5d357bf9016..8257b14fb59 100644 --- a/compiler/testData/ir/irText/expressions/floatingPointComparisons/nullableFloatingPointEqeq.fir.txt +++ b/compiler/testData/ir/irText/expressions/floatingPointComparisons/nullableFloatingPointEqeq.fir.txt @@ -18,8 +18,20 @@ FILE fqName: fileName:/nullableFloatingPointEqeq.kt GET_VAR 'y: kotlin.Any? declared in .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 .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 .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 .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 .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 .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: fileName:/nullableFloatingPointEqeq.kt GET_VAR 'y: kotlin.Any? declared in .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 .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 .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 .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 .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 .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: 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 .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 .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 .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 .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 .testDI2' type=kotlin.Any? origin=null BRANCH diff --git a/compiler/testData/ir/irText/expressions/floatingPointComparisons/typeParameterWithPrimitiveNumericSupertype.fir.txt b/compiler/testData/ir/irText/expressions/floatingPointComparisons/typeParameterWithPrimitiveNumericSupertype.fir.txt index a6c3321c37a..501d7424ae1 100644 --- a/compiler/testData/ir/irText/expressions/floatingPointComparisons/typeParameterWithPrimitiveNumericSupertype.fir.txt +++ b/compiler/testData/ir/irText/expressions/floatingPointComparisons/typeParameterWithPrimitiveNumericSupertype.fir.txt @@ -44,8 +44,9 @@ FILE fqName: fileName:/typeParameterWithPrimitiveNumericSupertype.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Float GET_VAR 'x: kotlin.Any declared in .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 .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 .test2' type=kotlin.Any origin=null arg1: GET_VAR 'y: T of .test2 declared in .test2' type=T of .test2 origin=null BRANCH if: CONST Boolean type=kotlin.Boolean value=true @@ -61,8 +62,9 @@ FILE fqName: fileName:/typeParameterWithPrimitiveNumericSupertype.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int GET_VAR 'x: kotlin.Any declared in .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 .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 .test3' type=kotlin.Any origin=null arg1: GET_VAR 'y: T of .test3 declared in .test3' type=T of .test3 origin=null BRANCH if: CONST Boolean type=kotlin.Boolean value=true @@ -78,8 +80,9 @@ FILE fqName: fileName:/typeParameterWithPrimitiveNumericSupertype.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int GET_VAR 'x: kotlin.Any declared in .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 .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 .test4' type=kotlin.Any origin=null arg1: GET_VAR 'y: T of .test4 declared in .test4' type=T of .test4 origin=null BRANCH if: CONST Boolean type=kotlin.Boolean value=true @@ -96,8 +99,9 @@ FILE fqName: fileName:/typeParameterWithPrimitiveNumericSupertype.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int GET_VAR 'x: kotlin.Any declared in .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 .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 .test5' type=kotlin.Any origin=null arg1: GET_VAR 'y: R of .test5 declared in .test5' type=R of .test5 origin=null BRANCH if: CONST Boolean type=kotlin.Boolean value=true @@ -137,7 +141,8 @@ FILE fqName: fileName:/typeParameterWithPrimitiveNumericSupertype.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Double GET_VAR 'y: kotlin.Any declared in .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 .F declared in .F.testCapturedType' type=T of .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 .F declared in .F.testCapturedType' type=T of .F origin=null arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double GET_VAR 'y: kotlin.Any declared in .F.testCapturedType' type=kotlin.Any origin=null BRANCH diff --git a/compiler/testData/ir/irText/expressions/floatingPointComparisons/whenByFloatingPoint.fir.txt b/compiler/testData/ir/irText/expressions/floatingPointComparisons/whenByFloatingPoint.fir.txt index 19826ac79be..9e3014995a7 100644 --- a/compiler/testData/ir/irText/expressions/floatingPointComparisons/whenByFloatingPoint.fir.txt +++ b/compiler/testData/ir/irText/expressions/floatingPointComparisons/whenByFloatingPoint.fir.txt @@ -112,8 +112,9 @@ FILE fqName: 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 .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 .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 .testSmartCastToDifferentTypes' type=kotlin.Any origin=null then: CONST Int type=kotlin.Int value=0 BRANCH if: CONST Boolean type=kotlin.Boolean value=true diff --git a/compiler/testData/ir/irText/expressions/primitiveComparisons.fir.txt b/compiler/testData/ir/irText/expressions/primitiveComparisons.fir.txt deleted file mode 100644 index 4b3b441d206..00000000000 --- a/compiler/testData/ir/irText/expressions/primitiveComparisons.fir.txt +++ /dev/null @@ -1,209 +0,0 @@ -FILE fqName: 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 ' - 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 .btest1' type=kotlin.Byte origin=null - other: GET_VAR 'b: kotlin.Byte declared in .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 ' - 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 .btest2' type=kotlin.Byte origin=null - other: GET_VAR 'b: kotlin.Byte declared in .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 ' - 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 .btest3' type=kotlin.Byte origin=null - other: GET_VAR 'b: kotlin.Byte declared in .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 ' - 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 .btest4' type=kotlin.Byte origin=null - other: GET_VAR 'b: kotlin.Byte declared in .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 ' - 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 .stest1' type=kotlin.Short origin=null - other: GET_VAR 'b: kotlin.Short declared in .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 ' - 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 .stest2' type=kotlin.Short origin=null - other: GET_VAR 'b: kotlin.Short declared in .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 ' - 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 .stest3' type=kotlin.Short origin=null - other: GET_VAR 'b: kotlin.Short declared in .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 ' - 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 .stest4' type=kotlin.Short origin=null - other: GET_VAR 'b: kotlin.Short declared in .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 ' - 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 .itest1' type=kotlin.Int origin=null - arg1: GET_VAR 'b: kotlin.Int declared in .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 ' - 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 .itest2' type=kotlin.Int origin=null - arg1: GET_VAR 'b: kotlin.Int declared in .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 ' - 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 .itest3' type=kotlin.Int origin=null - arg1: GET_VAR 'b: kotlin.Int declared in .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 ' - 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 .itest4' type=kotlin.Int origin=null - arg1: GET_VAR 'b: kotlin.Int declared in .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 ' - 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 .ltest1' type=kotlin.Long origin=null - arg1: GET_VAR 'b: kotlin.Long declared in .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 ' - 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 .ltest2' type=kotlin.Long origin=null - arg1: GET_VAR 'b: kotlin.Long declared in .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 ' - 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 .ltest3' type=kotlin.Long origin=null - arg1: GET_VAR 'b: kotlin.Long declared in .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 ' - 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 .ltest4' type=kotlin.Long origin=null - arg1: GET_VAR 'b: kotlin.Long declared in .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 ' - 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 .ftest1' type=kotlin.Float origin=null - arg1: GET_VAR 'b: kotlin.Float declared in .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 ' - 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 .ftest2' type=kotlin.Float origin=null - arg1: GET_VAR 'b: kotlin.Float declared in .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 ' - 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 .ftest3' type=kotlin.Float origin=null - arg1: GET_VAR 'b: kotlin.Float declared in .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 ' - 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 .ftest4' type=kotlin.Float origin=null - arg1: GET_VAR 'b: kotlin.Float declared in .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 ' - 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 .dtest1' type=kotlin.Double origin=null - arg1: GET_VAR 'b: kotlin.Double declared in .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 ' - 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 .dtest2' type=kotlin.Double origin=null - arg1: GET_VAR 'b: kotlin.Double declared in .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 ' - 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 .dtest3' type=kotlin.Double origin=null - arg1: GET_VAR 'b: kotlin.Double declared in .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 ' - 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 .dtest4' type=kotlin.Double origin=null - arg1: GET_VAR 'b: kotlin.Double declared in .dtest4' type=kotlin.Double origin=null diff --git a/compiler/testData/ir/irText/expressions/primitiveComparisons.kt b/compiler/testData/ir/irText/expressions/primitiveComparisons.kt index 3d208a2fc8d..00f6a3d5457 100644 --- a/compiler/testData/ir/irText/expressions/primitiveComparisons.kt +++ b/compiler/testData/ir/irText/expressions/primitiveComparisons.kt @@ -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