From 78b4024ccbdbd765789ee9ea7ef6dae69303cac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Sch=C3=A4fer?= Date: Fri, 4 Oct 2019 13:39:47 +0200 Subject: [PATCH] JVM IR: Unify the handling of IrStringConcatenation and toString --- .../FlattenStringConcatenationLowering.kt | 61 +++++++++++++------ .../jvm/intrinsics/IrIntrinsicMethods.kt | 7 --- .../kotlin/backend/jvm/intrinsics/ToString.kt | 32 ---------- 3 files changed, 41 insertions(+), 59 deletions(-) delete mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ToString.kt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/FlattenStringConcatenationLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/FlattenStringConcatenationLowering.kt index b49bb153d2f..48aadf53dc6 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/FlattenStringConcatenationLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/FlattenStringConcatenationLowering.kt @@ -11,18 +11,20 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation import org.jetbrains.kotlin.ir.expressions.impl.IrStringConcatenationImpl +import org.jetbrains.kotlin.ir.types.isAny +import org.jetbrains.kotlin.ir.types.isNullableAny +import org.jetbrains.kotlin.ir.types.isString import org.jetbrains.kotlin.ir.types.isStringClassType -import org.jetbrains.kotlin.ir.util.fqNameSafe import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.name.Name val flattenStringConcatenationPhase = makeIrFilePhase( ::FlattenStringConcatenationLowering, @@ -76,26 +78,45 @@ class FlattenStringConcatenationLowering(val context: CommonBackendContext) : Fi KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME, KotlinBuiltIns.FQ_NAMES.string.toSafe() ) - private val PLUS_NAME = Name.identifier("plus") - /** @return true if the given expression is a [IrStringConcatenation] or [String.plus] [IrCall]. */ - private fun isStringConcatenationExpression(expression: IrExpression): Boolean { - return when (expression) { - is IrStringConcatenation -> true - is IrCall -> { - val function = expression.symbol.owner - val receiver = expression.dispatchReceiver ?: expression.extensionReceiver - receiver != null && - receiver.type.isStringClassType() && - expression.type.isStringClassType() && - expression.valueArgumentsCount == 1 && - function.name == PLUS_NAME && - function.fqNameWhenAvailable?.parent() in PARENT_NAMES - } - else -> false - } + /** @return true if the given expression is a call to [String.plus] */ + private fun isStringPlusCall(expression: IrCall): Boolean { + val function = expression.symbol.owner + val receiver = expression.dispatchReceiver ?: expression.extensionReceiver + + return receiver != null + && receiver.type.isStringClassType() + && function.returnType.isStringClassType() + && function.valueParameters.size == 1 + && function.name.asString() == "plus" + && function.fqNameWhenAvailable?.parent() in PARENT_NAMES } + /** @return true if the given expression is a call to [toString] */ + private fun isToStringCall(expression: IrCall): Boolean { + if (expression.superQualifierSymbol != null) + return false + + val function = expression.symbol.owner + if (function.name.asString() != "toString" || function.valueParameters.size != 0 || !function.returnType.isString()) + return false + + // Check for Any?.toString, which is an extension method defined in the kotlin package. + if (function.dispatchReceiverParameter == null + && function.extensionReceiverParameter?.type?.isNullableAny() == true + && function.fqNameWhenAvailable?.parent() == KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME) + return true + + // Check for Any.toString or an override. + return (function.dispatchReceiverParameter != null && function.extensionReceiverParameter == null + && (function.dispatchReceiverParameter?.type?.isAny() == true + || (function as? IrSimpleFunction)?.overriddenSymbols?.isNotEmpty() == true)) + } + + /** @return true if the given expression is a [IrStringConcatenation], or an [IrCall] to [toString] or [String.plus]. */ + private fun isStringConcatenationExpression(expression: IrExpression): Boolean = + (expression is IrStringConcatenation) || (expression is IrCall) && (isStringPlusCall(expression) || isToStringCall(expression)) + /** Recursively collects string concatenation arguments from the given expression. */ private fun collectStringConcatenationArguments(expression: IrExpression): List { val arguments = mutableListOf() @@ -152,4 +173,4 @@ class FlattenStringConcatenationLowering(val context: CommonBackendContext) : Fi transformedExpression.transformChildrenVoid(this) return transformedExpression } -} \ No newline at end of file +} 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 42542672376..88915f3fa44 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 @@ -67,12 +67,6 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { "isArrayOf", emptyList() ) to IsArrayOf, - Key( - KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME, - KotlinBuiltIns.FQ_NAMES.any.toSafe(), - "toString", - emptyList() - ) to ToString, Key( KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME, null, @@ -108,7 +102,6 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { unaryFunForPrimitives("inc", INC) + unaryFunForPrimitives("dec", DEC) + unaryFunForPrimitives("hashCode", HashCode) + - unaryFunForPrimitives("toString", ToString) + binaryFunForPrimitives("equals", EQUALS, irBuiltIns.anyClass) + binaryFunForPrimitivesAcrossPrimitives("rangeTo", RangeTo) + binaryOp("plus", IADD) + diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ToString.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ToString.kt deleted file mode 100644 index 216202ecf14..00000000000 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ToString.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.jvm.intrinsics - -import org.jetbrains.kotlin.backend.jvm.JvmBackendContext -import org.jetbrains.kotlin.codegen.AsmUtil -import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression -import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression -import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature - -object ToString : IntrinsicMethod() { - override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { - val type = AsmUtil.stringValueOfType(calcReceiverType(expression, context)) - return IrIntrinsicFunction.create(expression, signature, context, type) { - it.invokestatic("java/lang/String", "valueOf", "(${type.descriptor})Ljava/lang/String;", false) - } - } -}