diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt index 3fd26b4c47a..0cbd136338d 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.psi2ir.generators +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.lexer.KtTokens @@ -24,6 +25,7 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.makeNullable import java.lang.AssertionError @@ -234,6 +236,16 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression { val resolvedCall = getResolvedCall(expression)!! + + if (expression.baseExpression is KtConstantExpression) { + ConstantExpressionEvaluator.getConstant(expression, context.bindingContext)?.let { constant -> + val receiverType = resolvedCall.dispatchReceiver?.type + if (receiverType != null && KotlinBuiltIns.isPrimitiveType(receiverType)) { + return statementGenerator.generateConstantExpression(expression, constant) + } + } + } + return CallGenerator(statementGenerator).generateCall(expression, statementGenerator.pregenerateCall(resolvedCall), irOperator) } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt index f44508521ca..de24ae299c2 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt @@ -35,10 +35,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject -import org.jetbrains.kotlin.resolve.constants.BooleanValue -import org.jetbrains.kotlin.resolve.constants.IntValue -import org.jetbrains.kotlin.resolve.constants.NullValue -import org.jetbrains.kotlin.resolve.constants.StringValue +import org.jetbrains.kotlin.resolve.constants.* import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils @@ -151,10 +148,13 @@ class StatementGenerator( return IrThrowImpl(expression.startOffset, expression.endOffset, context.builtIns.nothingType, expression.thrownExpression!!.genExpr()) } - override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression { - val compileTimeConstant = ConstantExpressionEvaluator.getConstant(expression, context.bindingContext) - ?: error("KtConstantExpression was not evaluated: ${expression.text}") - val constantValue = compileTimeConstant.toConstantValue(getInferredTypeWithImplicitCastsOrFail(expression)) + override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression = + generateConstantExpression(expression, + ConstantExpressionEvaluator.getConstant(expression, context.bindingContext) ?: + error("KtConstantExpression was not evaluated: ${expression.text}")) + + fun generateConstantExpression(expression: KtExpression, constant: CompileTimeConstant<*>): IrExpression { + val constantValue = constant.toConstantValue(getInferredTypeWithImplicitCastsOrFail(expression)) val constantType = constantValue.type return when (constantValue) { @@ -166,6 +166,12 @@ class StatementGenerator( IrConstImpl.constNull(expression.startOffset, expression.endOffset, constantType) is BooleanValue -> IrConstImpl.boolean(expression.startOffset, expression.endOffset, constantType, constantValue.value) + is LongValue -> + IrConstImpl.long(expression.startOffset, expression.endOffset, constantType, constantValue.value) + is DoubleValue -> + IrConstImpl.double(expression.startOffset, expression.endOffset, constantType, constantValue.value) + is FloatValue -> + IrConstImpl.float(expression.startOffset, expression.endOffset, constantType, constantValue.value) else -> TODO("handle other literal types: ${constantValue.type}") } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConst.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConst.kt index ad78857f4c4..d51ab6eba40 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConst.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConst.kt @@ -75,6 +75,15 @@ class IrConstImpl ( fun constFalse(startOffset: Int, endOffset: Int, type: KotlinType): IrConstImpl = boolean(startOffset, endOffset, type, false) + + fun long(startOffset: Int, endOffset: Int, type: KotlinType, value: Long): IrExpression = + IrConstImpl(startOffset, endOffset, type, IrConstKind.Long, value) + + fun float(startOffset: Int, endOffset: Int, type: KotlinType, value: Float): IrExpression = + IrConstImpl(startOffset, endOffset, type, IrConstKind.Float, value) + + fun double(startOffset: Int, endOffset: Int, type: KotlinType, value: Double): IrExpression = + IrConstImpl(startOffset, endOffset, type, IrConstKind.Double, value) } } diff --git a/compiler/testData/ir/irText/expressions/ifElseIf.txt b/compiler/testData/ir/irText/expressions/ifElseIf.txt index 220ee5eb691..7f1637601c3 100644 --- a/compiler/testData/ir/irText/expressions/ifElseIf.txt +++ b/compiler/testData/ir/irText/expressions/ifElseIf.txt @@ -12,6 +12,5 @@ FILE /ifElseIf.kt arg0: CALL .compareTo type=kotlin.Int operator=LT $this: GET_VAR i type=kotlin.Int operator=null other: CONST Int type=kotlin.Int value='0' - then: CALL .unaryMinus type=kotlin.Int operator=UMINUS - $this: CONST Int type=kotlin.Int value='1' + then: CONST Int type=kotlin.Int value='-1' else: CONST Int type=kotlin.Int value='0' diff --git a/compiler/testData/ir/irText/expressions/literals.kt b/compiler/testData/ir/irText/expressions/literals.kt index be88ac88d0d..1b80a5cb441 100644 --- a/compiler/testData/ir/irText/expressions/literals.kt +++ b/compiler/testData/ir/irText/expressions/literals.kt @@ -3,4 +3,10 @@ val test2 = -1 val test3 = true val test4 = false val test5 = "abc" -val test6 = null \ No newline at end of file +val test6 = null +val test7 = 1L +val test8 = -1L +val test9 = 1.0 +val test10 = -1.0 +val test11 = 1.0f +val test12 = -1.0f \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/literals.txt b/compiler/testData/ir/irText/expressions/literals.txt index 71ceae9b1c5..ebf22f44f89 100644 --- a/compiler/testData/ir/irText/expressions/literals.txt +++ b/compiler/testData/ir/irText/expressions/literals.txt @@ -4,8 +4,7 @@ FILE /literals.kt CONST Int type=kotlin.Int value='1' PROPERTY public val test2: kotlin.Int = -1 getter=null setter=null EXPRESSION_BODY - CALL .unaryMinus type=kotlin.Int operator=UMINUS - $this: CONST Int type=kotlin.Int value='1' + CONST Int type=kotlin.Int value='-1' PROPERTY public val test3: kotlin.Boolean = true getter=null setter=null EXPRESSION_BODY CONST Boolean type=kotlin.Boolean value='true' @@ -18,3 +17,21 @@ FILE /literals.kt PROPERTY public val test6: kotlin.Nothing? = null getter=null setter=null EXPRESSION_BODY CONST Null type=kotlin.Nothing? value='null' + PROPERTY public val test7: kotlin.Long = 1.toLong() getter=null setter=null + EXPRESSION_BODY + CONST Long type=kotlin.Long value='1' + PROPERTY public val test8: kotlin.Long = -1.toLong() getter=null setter=null + EXPRESSION_BODY + CONST Long type=kotlin.Long value='-1' + PROPERTY public val test9: kotlin.Double = 1.0.toDouble() getter=null setter=null + EXPRESSION_BODY + CONST Double type=kotlin.Double value='1.0' + PROPERTY public val test10: kotlin.Double = -1.0.toDouble() getter=null setter=null + EXPRESSION_BODY + CONST Double type=kotlin.Double value='-1.0' + PROPERTY public val test11: kotlin.Float = 1.0.toFloat() getter=null setter=null + EXPRESSION_BODY + CONST Float type=kotlin.Float value='1.0' + PROPERTY public val test12: kotlin.Float = -1.0.toFloat() getter=null setter=null + EXPRESSION_BODY + CONST Float type=kotlin.Float value='-1.0' diff --git a/compiler/testData/ir/irText/expressions/simpleUnaryOperators.txt b/compiler/testData/ir/irText/expressions/simpleUnaryOperators.txt index b0919f86471..2d8b4efd037 100644 --- a/compiler/testData/ir/irText/expressions/simpleUnaryOperators.txt +++ b/compiler/testData/ir/irText/expressions/simpleUnaryOperators.txt @@ -7,8 +7,7 @@ FILE /simpleUnaryOperators.kt FUN public fun test2(): kotlin.Int BLOCK_BODY RETURN type=kotlin.Nothing from=test2 - CALL .unaryMinus type=kotlin.Int operator=UMINUS - $this: CONST Int type=kotlin.Int value='42' + CONST Int type=kotlin.Int value='-42' FUN public fun test3(/*0*/ x: kotlin.Int): kotlin.Int BLOCK_BODY RETURN type=kotlin.Nothing from=test3 @@ -17,8 +16,7 @@ FILE /simpleUnaryOperators.kt FUN public fun test4(): kotlin.Int BLOCK_BODY RETURN type=kotlin.Nothing from=test4 - CALL .unaryPlus type=kotlin.Int operator=UPLUS - $this: CONST Int type=kotlin.Int value='42' + CONST Int type=kotlin.Int value='42' FUN public fun test5(/*0*/ x: kotlin.Boolean): kotlin.Boolean BLOCK_BODY RETURN type=kotlin.Nothing from=test5 @@ -27,5 +25,4 @@ FILE /simpleUnaryOperators.kt FUN public fun test6(): kotlin.Boolean BLOCK_BODY RETURN type=kotlin.Nothing from=test6 - CALL .not type=kotlin.Boolean operator=EXCL - $this: CONST Boolean type=kotlin.Boolean value='true' + CONST Boolean type=kotlin.Boolean value='false'