diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt index 59fc63c1161..ecdcec88448 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt @@ -48,8 +48,6 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { private val KOTLIN_JVM = FqName("kotlin.jvm") private val KOTLIN_JVM_INTERNAL_UNSAFE = FqName("kotlin.jvm.internal.unsafe") - val andandSymbol = irBuiltIns.run { defineOperator(OperatorNames.ANDAND, bool, listOf(bool, bool)) } - private val intrinsicsMap = ( listOf( Key(KOTLIN_JVM, FqName("T"),"", emptyList()) to JavaClassProperty, @@ -96,12 +94,6 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { "clone", emptyList() ) to Clone, - Key( - KOTLIN_INTERNAL_IR, - null, - OperatorNames.ANDAND, - listOf(KotlinBuiltIns.FQ_NAMES._boolean.toSafe(), KotlinBuiltIns.FQ_NAMES._boolean.toSafe()) - ) to AndAnd, irBuiltIns.eqeqSymbol.toKey()!! to Equals(KtTokens.EQEQ), irBuiltIns.eqeqeqSymbol.toKey()!! to Equals(KtTokens.EQEQEQ), irBuiltIns.ieee754equalsFunByOperandType[irBuiltIns.float]!!.toKey()!! to Ieee754Equals(Type.FLOAT_TYPE), @@ -110,7 +102,9 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { irBuiltIns.enumValueOfSymbol.toKey()!! to IrEnumValueOf, irBuiltIns.noWhenBranchMatchedExceptionSymbol.toKey()!! to IrNoWhenBranchMatchedException, irBuiltIns.illegalArgumentExceptionSymbol.toKey()!! to IrIllegalArgumentException, - irBuiltIns.throwNpeSymbol.toKey()!! to ThrowNPE + irBuiltIns.throwNpeSymbol.toKey()!! to ThrowNPE, + irBuiltIns.andandSymbol.toKey()!! to AndAnd, + irBuiltIns.ororSymbol.toKey()!! to OrOr ) + numberConversionMethods() + unaryFunForPrimitives("plus", UnaryPlus) + @@ -226,8 +220,4 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { irFunSymbol.toKey()!! to PrimitiveComparison(type, operator) } } - - private object OperatorNames { - const val ANDAND = "ANDAND" - } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/OrOr.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/OrOr.kt new file mode 100644 index 00000000000..caca8ffc378 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/OrOr.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.codegen.* +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression +import org.jetbrains.org.objectweb.asm.Label + +object OrOr : IntrinsicMethod() { + + private class BooleanDisjunction( + val arg0: IrExpression, val arg1: IrExpression, val codegen: ExpressionCodegen, val data: BlockInfo) : BooleanValue(codegen.mv) { + + override fun jumpIfFalse(target: Label) { + val stayLabel = Label() + arg0.accept(codegen, data).coerceToBoolean().jumpIfTrue(stayLabel) + arg1.accept(codegen, data).coerceToBoolean().jumpIfFalse(target) + mv.visitLabel(stayLabel) + } + + override fun jumpIfTrue(target: Label) { + arg0.accept(codegen, data).coerceToBoolean().jumpIfTrue(target) + arg1.accept(codegen, data).coerceToBoolean().jumpIfTrue(target) + } + } + + override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? { + val (left, right) = expression.receiverAndArgs() + return BooleanDisjunction(left, right, codegen, data) + } +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt index 518b2b74c33..bd96faff0e1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt @@ -114,10 +114,30 @@ class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLower expression.startOffset, expression.endOffset, context.irBuiltIns.booleanType, - context.irIntrinsics.andandSymbol + context.irBuiltIns.andandSymbol ).apply { - dispatchReceiver = expression.branches[0].condition - putValueArgument(0, expression.branches[0].result) + putValueArgument(0, expression.branches[0].condition) + putValueArgument(1, expression.branches[0].result) + } + } + if (expression.origin == IrStatementOrigin.OROR) { + assert( + expression.type.isBoolean() + && expression.branches.size == 2 + && expression.branches[0].result.isTrueConst() + && expression.branches[1].condition.isTrueConst()) { + "OROR condition should have an 'if a then true' body on its first branch, " + + "and an 'if true then b' body on its second branch. " + + "Failing expression: ${expression.dump()}" + } + return IrCallImpl( + expression.startOffset, + expression.endOffset, + context.irBuiltIns.booleanType, + context.irBuiltIns.ororSymbol + ).apply { + putValueArgument(0, expression.branches[0].condition) + putValueArgument(1, expression.branches[1].result) } } // If the only condition that is left has a constant true condition remove the diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt index 7db180a7613..e5d816f544d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt @@ -216,6 +216,8 @@ class IrBuiltIns( val throwNpeSymbol = defineOperator(OperatorNames.THROW_NPE, nothing, listOf()) val throwCceSymbol = defineOperator(OperatorNames.THROW_CCE, nothing, listOf()) val throwIseSymbol = defineOperator(OperatorNames.THROW_ISE, nothing, listOf()) + val andandSymbol = defineOperator(OperatorNames.ANDAND, bool, listOf(bool, bool)) + val ororSymbol = defineOperator(OperatorNames.OROR, bool, listOf(bool, bool)) val noWhenBranchMatchedExceptionSymbol = defineOperator(OperatorNames.NO_WHEN_BRANCH_MATCHED_EXCEPTION, nothing, listOf()) val illegalArgumentExceptionSymbol = defineOperator(OperatorNames.ILLEGAL_ARGUMENT_EXCEPTION, nothing, listOf(string)) @@ -274,5 +276,7 @@ class IrBuiltIns( const val THROW_ISE = "THROW_ISE" const val NO_WHEN_BRANCH_MATCHED_EXCEPTION = "noWhenBranchMatchedException" const val ILLEGAL_ARGUMENT_EXCEPTION = "illegalArgumentException" + const val ANDAND = "ANDAND" + const val OROR = "OROR" } } diff --git a/compiler/testData/codegen/bytecodeText/conditions/disjunction.kt b/compiler/testData/codegen/bytecodeText/conditions/disjunction.kt index c1707e4befa..e0f873a74d4 100644 --- a/compiler/testData/codegen/bytecodeText/conditions/disjunction.kt +++ b/compiler/testData/codegen/bytecodeText/conditions/disjunction.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR val a = false val b = false val c = false diff --git a/compiler/testData/codegen/bytecodeText/conditions/negatedDisjunction.kt b/compiler/testData/codegen/bytecodeText/conditions/negatedDisjunction.kt index 8fba0996790..0278b2e0dfb 100644 --- a/compiler/testData/codegen/bytecodeText/conditions/negatedDisjunction.kt +++ b/compiler/testData/codegen/bytecodeText/conditions/negatedDisjunction.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR val a = false val b = false val c = false