From c545481db968ca1f185f39757fa0cee52d71ba70 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Fri, 12 Apr 2019 18:29:44 +0300 Subject: [PATCH] Fix JS_IR IrConstructorCall support --- .../lower/DefaultArgumentStubGenerator.kt | 119 +++++++++--------- .../lower/InlineClassDeclarationLowering.kt | 12 +- .../ir/backend/js/JsSharedVariablesManager.kt | 3 +- .../lower/ArrayInlineConstructorLowering.kt | 12 +- .../backend/js/lower/AutoboxingTransformer.kt | 4 +- .../js/lower/CallableReferenceLowering.kt | 10 +- .../ir/backend/js/lower/ConstLowering.kt | 4 +- .../backend/js/lower/SecondaryCtorLowering.kt | 13 +- .../ir/backend/js/lower/TestGenerator.kt | 3 +- .../js/lower/ThrowableSuccessorsLowering.kt | 4 +- .../ir/backend/js/lower/VarargLowering.kt | 13 +- .../backend/js/lower/calls/CallsLowering.kt | 12 +- .../js/lower/calls/CallsLoweringUtils.kt | 19 +-- .../lower/calls/EnumIntrinsicsTransformer.kt | 9 +- .../EqualityAndComparisonCallsTransformer.kt | 15 +-- .../calls/ExceptionHelperCallsTransformer.kt | 3 +- .../calls/MethodsOfAnyCallsTransformer.kt | 11 +- .../calls/NumberConversionCallsTransformer.kt | 5 +- .../calls/NumberOperatorCallsTransformer.kt | 29 ++--- ...PrimitiveContainerMemberCallTransformer.kt | 11 +- .../lower/calls/ReflectionCallsTransformer.kt | 5 +- .../js/lower/inline/FunctionInlining.kt | 53 +++++--- .../IrElementToJsExpressionTransformer.kt | 28 +++++ .../irToJs/JsIntrinsicTransformers.kt | 21 ++-- .../org/jetbrains/kotlin/ir/util/IrUtils.kt | 38 +++++- 25 files changed, 295 insertions(+), 161 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt index 47f15d91c79..4cebe2fe104 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.descriptors.Modality 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.declarations.* @@ -216,40 +217,10 @@ open class DefaultParameterInjector( override fun lower(irFile: IrFile) { irFile.transformChildrenVoid(object : IrElementTransformerVoid() { - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { - super.visitDelegatingConstructorCall(expression) - - val declaration = expression.symbol.owner as IrFunction - - if (!declaration.needsDefaultArgumentsLowering(skipInline, skipExternalMethods)) - return expression - - val argumentsCount = argumentCount(expression) - - if (argumentsCount == declaration.valueParameters.size) - return expression - - val (symbolForCall, params) = parametersForCall(expression) - return IrDelegatingConstructorCallImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - type = context.irBuiltIns.unitType, - symbol = symbolForCall as IrConstructorSymbol, - descriptor = symbolForCall.descriptor, - typeArgumentsCount = expression.typeArgumentsCount - ) - .apply { - copyTypeArgumentsFrom(expression) - params.forEach { - log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" } - putValueArgument(it.first.index, it.second) - } - dispatchReceiver = expression.dispatchReceiver - } - } - - override fun visitCall(expression: IrCall): IrExpression { - super.visitCall(expression) + private fun visitFunctionAccessExpression( + expression: IrFunctionAccessExpression, + builder: (IrFunctionSymbol) -> IrFunctionAccessExpression + ): IrExpression { val functionDeclaration = expression.symbol.owner if (!functionDeclaration.needsDefaultArgumentsLowering(skipInline, skipExternalMethods)) @@ -268,30 +239,66 @@ open class DefaultParameterInjector( } declaration.typeParameters.forEach { log { "$declaration[${it.index}] : $it" } } - return IrCallImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - type = symbol.owner.returnType, - symbol = symbol, - descriptor = descriptor, - typeArgumentsCount = expression.typeArgumentsCount, - origin = DEFAULT_DISPATCH_CALL, - superQualifierSymbol = expression.superQualifierSymbol - ) - .apply { - this.copyTypeArgumentsFrom(expression) + return builder(symbol).apply { + this.copyTypeArgumentsFrom(expression) - params.forEach { - log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" } - putValueArgument(it.first.index, it.second) - } - - dispatchReceiver = expression.dispatchReceiver - extensionReceiver = expression.extensionReceiver - - log { "call::extension@: ${ir2string(expression.extensionReceiver)}" } - log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" } + params.forEach { + log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" } + putValueArgument(it.first.index, it.second) } + + dispatchReceiver = expression.dispatchReceiver + extensionReceiver = expression.extensionReceiver + + log { "call::extension@: ${ir2string(expression.extensionReceiver)}" } + log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" } + } + } + + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { + super.visitDelegatingConstructorCall(expression) + + return visitFunctionAccessExpression(expression) { + IrDelegatingConstructorCallImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + type = context.irBuiltIns.unitType, + symbol = it as IrConstructorSymbol, + descriptor = it.descriptor, + typeArgumentsCount = expression.typeArgumentsCount + ) + } + } + + override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { + super.visitConstructorCall(expression) + + return visitFunctionAccessExpression(expression) { + IrConstructorCallImpl.fromSymbolOwner( + expression.startOffset, + expression.endOffset, + it.owner.returnType, + it as IrConstructorSymbol, + DEFAULT_DISPATCH_CALL + ) + } + } + + override fun visitCall(expression: IrCall): IrExpression { + super.visitCall(expression) + + return visitFunctionAccessExpression(expression) { + IrCallImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + type = it.owner.returnType, + symbol = it, + descriptor = it.descriptor, + typeArgumentsCount = expression.typeArgumentsCount, + origin = DEFAULT_DISPATCH_CALL, + superQualifierSymbol = expression.superQualifierSymbol + ) + } } private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt index aee56f8c8e7..fcbb7f679d5 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt @@ -183,6 +183,16 @@ class InlineClassLowering(val context: BackendContext) { override fun lower(irFile: IrFile) { irFile.transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { + expression.transformChildrenVoid(this) + val function = expression.symbol.owner + if (!function.parentAsClass.isInline || function.isPrimary) { + return expression + } + + return irCall(expression, getOrCreateStaticMethod(function), dispatchReceiverAsFirstArgument = false) + } + override fun visitCall(expression: IrCall): IrExpression { expression.transformChildrenVoid(this) val function = expression.symbol.owner @@ -208,7 +218,7 @@ class InlineClassLowering(val context: BackendContext) { val klass = function.parentAsClass return when { !klass.isInline -> expression - function.isPrimary -> irCall(expression, function) + function.isPrimary -> irConstructorCall(expression, function) else -> irCall(expression, getOrCreateStaticMethod(function)).apply { (0 until expression.valueArgumentsCount).forEach { putValueArgument(it, expression.getValueArgument(it)!!) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt index 28f9e9485ef..bc4a8336495 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt @@ -48,7 +48,7 @@ class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclaration val constructorSymbol = closureBoxConstructorDeclaration.symbol - val irCall = IrCallImpl(initializer.startOffset, initializer.endOffset, closureBoxType, constructorSymbol).apply { + val irCall = IrConstructorCallImpl.fromSymbolDescriptor(initializer.startOffset, initializer.endOffset, closureBoxType, constructorSymbol).apply { putValueArgument(0, initializer) } @@ -132,6 +132,7 @@ class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclaration descriptor.bind(declaration) declaration.parent = implicitDeclarationsFile + // TODO: substitute closureBoxType = IrSimpleTypeImpl(declaration.symbol, false, emptyList(), emptyList()) declaration.thisReceiver = JsIrBuilder.buildValueParameter(Name.special(""), -1, closureBoxType, IrDeclarationOrigin.INSTANCE_RECEIVER).apply { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ArrayInlineConstructorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ArrayInlineConstructorLowering.kt index 9dfb2cb7a84..028fdb3a94f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ArrayInlineConstructorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ArrayInlineConstructorLowering.kt @@ -9,7 +9,11 @@ import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression +import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.util.irCall @@ -23,9 +27,11 @@ class ArrayConstructorTransformer( it.inlineConstructor to it.sizeConstructor } - fun transformCall(expression: IrCall): IrCall { + fun transformConstructorCall(expression: IrConstructorCall): IrFunctionAccessExpression { if (expression.symbol == context.intrinsics.array.inlineConstructor) { - return irCall(expression, context.intrinsics.jsArray) + return irCall(expression, context.intrinsics.jsArray).apply { + copyTypeArgumentsFrom(expression) + } } else { primitiveArrayInlineToSizeConstructorMap[expression.symbol]?.let { sizeConstructor -> return IrCallImpl( @@ -34,7 +40,7 @@ class ArrayConstructorTransformer( expression.type, context.intrinsics.jsFillArray ).apply { - putValueArgument(0, IrCallImpl( + putValueArgument(0, IrConstructorCallImpl.fromSymbolOwner( expression.startOffset, expression.endOffset, expression.type, diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt index f1f676c96c0..6ef79433c83 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt @@ -29,6 +29,7 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag override fun IrExpression.useAs(type: IrType): IrExpression { val actualType = when (this) { + is IrConstructorCall -> symbol.owner.returnType is IrCall -> { val function = this.symbol.owner if (function.let { it is IrSimpleFunction && it.isSuspend }) { @@ -127,8 +128,9 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag private val IrFunctionAccessExpression.target: IrFunction get() = when (this) { - is IrCall -> this.callTarget + is IrConstructorCall -> this.symbol.owner is IrDelegatingConstructorCall -> this.symbol.owner + is IrCall -> this.callTarget else -> TODO(this.render()) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt index b2d8e319d2f..69b480a3660 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt @@ -21,7 +21,9 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl @@ -517,7 +519,13 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP val callTarget = context.ir.defaultParameterDeclarationsCache[declaration] ?: declaration - val irCall = JsIrBuilder.buildCall(callTarget.symbol, type = returnType) + val target = callTarget.symbol + + val irCall = + if (target is IrConstructorSymbol) IrConstructorCallImpl.fromSymbolOwner(returnType, target) else JsIrBuilder.buildCall( + callTarget.symbol, + type = returnType + ) var cp = 0 var gp = 0 diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ConstLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ConstLowering.kt index 918eccab060..b3408b7d8b1 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ConstLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ConstLowering.kt @@ -14,10 +14,12 @@ import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.isUnsigned import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid @@ -31,7 +33,7 @@ class ConstTransformer(private val context: JsIrBackendContext) : IrElementTrans ): IrExpression { val constructor = irClass.constructors.single() val argType = constructor.owner.valueParameters.first().type - return JsIrBuilder.buildCall(constructor).apply { + return IrConstructorCallImpl.fromSymbolOwner(irClass.owner.defaultType, constructor).apply { for (i in args.indices) { putValueArgument(i, carrierFactory(UNDEFINED_OFFSET, UNDEFINED_OFFSET, argType, args[i])) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt index 69757d618ba..65ac8959f5c 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt @@ -192,20 +192,19 @@ private class CallsiteRedirectionTransformer(context: JsIrBackendContext) : IrEl private val oldCtorToNewMap = context.secondaryConstructorToFactoryCache private val defaultThrowableConstructor = context.defaultThrowableCtor - private val IrFunction.isSecondaryConstructorCall + private val IrConstructor.isSecondaryConstructorCall get() = - this is IrConstructor && !isPrimary && this != defaultThrowableConstructor && !isExternal && !parentAsClass.isInline + !isPrimary && this != defaultThrowableConstructor && !isExternal && !parentAsClass.isInline override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = super.visitFunction(declaration, declaration) - override fun visitCall(expression: IrCall, data: IrFunction?): IrElement { - super.visitCall(expression, data) + override fun visitConstructorCall(expression: IrConstructorCall, data: IrFunction?): IrElement { + super.visitConstructorCall(expression, data) val target = expression.symbol.owner return if (target.isSecondaryConstructorCall) { - val constructor = target as IrConstructor - val ctor = oldCtorToNewMap.getOrPut(constructor) { - buildConstructorStubDeclarations(constructor, constructor.parentAsClass) + val ctor = oldCtorToNewMap.getOrPut(target) { + buildConstructorStubDeclarations(target, target.parentAsClass) } replaceSecondaryConstructorWithFactoryFunction(expression, ctor.stub.symbol) } else expression diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TestGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TestGenerator.kt index 9f9749488e8..8b5c3561387 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TestGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TestGenerator.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.util.defaultType @@ -135,7 +136,7 @@ class TestGenerator(val context: JsIrBackendContext) : FileLoweringPass { JsIrBuilder.buildGetObjectValue(defaultType, symbol) } else { declarations.asSequence().filterIsInstance().single { it.isPrimary }.let { constructor -> - JsIrBuilder.buildCall(constructor.symbol).also { + IrConstructorCallImpl.fromSymbolOwner(defaultType, constructor.symbol).also { if (isInner) { it.dispatchReceiver = (parent as IrClass).instance() } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableSuccessorsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableSuccessorsLowering.kt index f8cc4e75301..b9ad294f05b 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableSuccessorsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableSuccessorsLowering.kt @@ -108,8 +108,8 @@ class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLowerin } inner class ThrowableInstanceCreationLowering : IrElementTransformerVoid() { - override fun visitCall(expression: IrCall): IrExpression { - if (expression.symbol !in throwableConstructors) return super.visitCall(expression) + override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { + if (expression.symbol !in throwableConstructors) return super.visitConstructorCall(expression) expression.transformChildrenVoid(this) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/VarargLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/VarargLowering.kt index fb27dec9836..dae61b82471 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/VarargLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/VarargLowering.kt @@ -10,11 +10,9 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.expressions.IrCall -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrSpreadElement -import org.jetbrains.kotlin.ir.expressions.IrVararg +import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl import org.jetbrains.kotlin.ir.types.IrType @@ -67,7 +65,7 @@ private class VarargTransformer( if (inlineClass == null) this else - IrCallImpl(startOffset, endOffset, inlineClass.defaultType, inlineClass.constructors.single { it.isPrimary }.symbol).also { + IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, inlineClass.defaultType, inlineClass.constructors.single { it.isPrimary }.symbol).also { it.putValueArgument(0, this) } @@ -165,7 +163,7 @@ private class VarargTransformer( res } - override fun visitCall(expression: IrCall): IrExpression { + private fun transformFunctionAccessExpression(expression: IrFunctionAccessExpression): IrExpression { expression.transformChildrenVoid() val size = expression.valueArgumentsCount @@ -179,4 +177,7 @@ private class VarargTransformer( return expression } + + override fun visitCall(expression: IrCall) = transformFunctionAccessExpression(expression) + override fun visitConstructorCall(expression: IrConstructorCall) = transformFunctionAccessExpression(expression) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLowering.kt index 231a9c86428..3906575d3a8 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLowering.kt @@ -10,8 +10,8 @@ import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid @@ -36,11 +36,11 @@ class CallsLowering(val context: JsIrBackendContext) : FileLoweringPass { return super.visitFunction(declaration) } - override fun visitCall(expression: IrCall): IrExpression { - val call = super.visitCall(expression) - if (call is IrCall) { + override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression { + val call = super.visitFunctionAccess(expression) + if (call is IrFunctionAccessExpression) { for (transformer in transformers) { - val newCall = transformer.transformCall(call) + val newCall = transformer.transformFunctionAccess(call) if (newCall !== call) { return newCall } @@ -53,5 +53,5 @@ class CallsLowering(val context: JsIrBackendContext) : FileLoweringPass { } interface CallsTransformer { - fun transformCall(call: IrCall): IrExpression + fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt index e3f308b9c6d..e91dbd8a4a5 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt @@ -8,13 +8,14 @@ package org.jetbrains.kotlin.ir.backend.js.lower.calls import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.SimpleType -typealias SymbolToTransformer = MutableMap IrExpression> +typealias SymbolToTransformer = MutableMap IrExpression> internal fun SymbolToTransformer.add(from: Map, to: IrFunctionSymbol) { from.forEach { _, func -> @@ -22,13 +23,13 @@ internal fun SymbolToTransformer.add(from: Map, to } } -internal fun SymbolToTransformer.add(from: Map, to: (IrCall) -> IrExpression) { +internal fun SymbolToTransformer.add(from: Map, to: (IrFunctionAccessExpression) -> IrExpression) { from.forEach { _, func -> add(func, to) } } -internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: (IrCall) -> IrExpression) { +internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: (IrFunctionAccessExpression) -> IrExpression) { put(from, to) } @@ -36,15 +37,15 @@ internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: IrFunctionSymbo put(from) { call -> irCall(call, to, dispatchReceiverAsFirstArgument) } } -internal fun MutableMap IrExpression>.addWithPredicate( +internal fun MutableMap IrExpression>.addWithPredicate( from: K, - predicate: (IrCall) -> Boolean, - action: (IrCall) -> IrExpression + predicate: (IrFunctionAccessExpression) -> Boolean, + action: (IrFunctionAccessExpression) -> IrExpression ) { - put(from) { call: IrCall -> if (predicate(call)) action(call) else call } + put(from) { call: IrFunctionAccessExpression -> if (predicate(call)) action(call) else call } } -internal typealias MemberToTransformer = HashMap IrExpression> +internal typealias MemberToTransformer = HashMap IrExpression> internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunctionSymbol) { add(type, name) { irCall(it, v, dispatchReceiverAsFirstArgument = true) } @@ -54,7 +55,7 @@ internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunction) { add(type, name, v.symbol) } -internal fun MemberToTransformer.add(type: IrType, name: Name, v: (IrCall) -> IrExpression) { +internal fun MemberToTransformer.add(type: IrType, name: Name, v: (IrFunctionAccessExpression) -> IrExpression) { put(SimpleMemberKey(type, name), v) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EnumIntrinsicsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EnumIntrinsicsTransformer.kt index f464474d116..7862408ed2e 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EnumIntrinsicsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EnumIntrinsicsTransformer.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.isStaticMethodOfClass import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.isString import org.jetbrains.kotlin.ir.util.findDeclaration @@ -20,7 +21,7 @@ import org.jetbrains.kotlin.name.Name class EnumIntrinsicsTransformer(private val context: JsIrBackendContext) : CallsTransformer { private fun transformEnumTopLevelIntrinsic( - call: IrCall, + call: IrFunctionAccessExpression, staticMethodPredicate: (IrSimpleFunction) -> Boolean ): IrExpression { val enum = call.getTypeArgument(0)?.getClass() ?: return call @@ -32,17 +33,17 @@ class EnumIntrinsicsTransformer(private val context: JsIrBackendContext) : Calls return irCall(call, staticMethod.symbol) } - private fun transformEnumValueOfIntrinsic(call: IrCall) = transformEnumTopLevelIntrinsic(call) { + private fun transformEnumValueOfIntrinsic(call: IrFunctionAccessExpression) = transformEnumTopLevelIntrinsic(call) { it.name == Name.identifier("valueOf") && it.valueParameters.count() == 1 && it.valueParameters[0].type.isString() } - private fun transformEnumValuesIntrinsic(call: IrCall) = transformEnumTopLevelIntrinsic(call) { + private fun transformEnumValuesIntrinsic(call: IrFunctionAccessExpression) = transformEnumTopLevelIntrinsic(call) { it.name == Name.identifier("values") && it.valueParameters.count() == 0 } - override fun transformCall(call: IrCall) = when (call.symbol) { + override fun transformFunctionAccess(call: IrFunctionAccessExpression) = when (call.symbol) { context.intrinsics.enumValueOfIntrinsic -> transformEnumValueOfIntrinsic(call) context.intrinsics.enumValuesIntrinsic -> transformEnumValuesIntrinsic(call) else -> call diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EqualityAndComparisonCallsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EqualityAndComparisonCallsTransformer.kt index 824a8a8cce4..3421e4c3ba5 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EqualityAndComparisonCallsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/EqualityAndComparisonCallsTransformer.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.isEqualsInheritedFromAny import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.* @@ -45,7 +46,7 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls } } - private fun transformLongComparison(comparator: IrSimpleFunctionSymbol): (IrCall) -> IrExpression = { call -> + private fun transformLongComparison(comparator: IrSimpleFunctionSymbol): (IrFunctionAccessExpression) -> IrExpression = { call -> IrCallImpl( call.startOffset, call.endOffset, @@ -57,7 +58,7 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls } } - override fun transformCall(call: IrCall): IrExpression { + override fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression { val symbol = call.symbol symbolToTransformer[symbol]?.let { return it(call) @@ -65,12 +66,12 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls return when (symbol.owner.name) { Name.identifier("compareTo") -> transformCompareToMethodCall(call) - Name.identifier("equals") -> transformEqualsMethodCall(call) + Name.identifier("equals") -> transformEqualsMethodCall(call as IrCall) else -> call } } - private fun transformEqeqOperator(call: IrCall): IrExpression { + private fun transformEqeqOperator(call: IrFunctionAccessExpression): IrExpression { val lhs = call.getValueArgument(0)!! val rhs = call.getValueArgument(1)!! @@ -101,17 +102,17 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls } } - private fun chooseEqualityOperatorForPrimitiveTypes(call: IrCall): IrExpression = when { + private fun chooseEqualityOperatorForPrimitiveTypes(call: IrFunctionAccessExpression): IrExpression = when { call.allValueArgumentsAreNullable() -> irCall(call, intrinsics.jsEqeq) else -> irCall(call, intrinsics.jsEqeqeq) } - private fun IrCall.allValueArgumentsAreNullable() = + private fun IrFunctionAccessExpression.allValueArgumentsAreNullable() = (0 until valueArgumentsCount).all { getValueArgument(it)!!.type.isNullable() } - private fun transformCompareToMethodCall(call: IrCall): IrExpression { + private fun transformCompareToMethodCall(call: IrFunctionAccessExpression): IrExpression { val function = call.symbol.owner as IrSimpleFunction if (function.parent !is IrClass) return call diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/ExceptionHelperCallsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/ExceptionHelperCallsTransformer.kt index 4fecf942428..266dd6d4bea 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/ExceptionHelperCallsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/ExceptionHelperCallsTransformer.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower.calls import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.util.kotlinPackageFqn import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -26,5 +27,5 @@ class ExceptionHelperCallsTransformer(private val context: JsIrBackendContext) : ) - override fun transformCall(call: IrCall) = helperMapping[call.symbol]?.let { irCall(call, it) } ?: call + override fun transformFunctionAccess(call: IrFunctionAccessExpression) = helperMapping[call.symbol]?.let { irCall(call, it) } ?: call } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt index 2d425d7a6c7..0c7515609c3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.types.IrDynamicType import org.jetbrains.kotlin.ir.types.isAny import org.jetbrains.kotlin.ir.types.isArray @@ -21,14 +22,14 @@ import org.jetbrains.kotlin.name.Name class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransformer { private val intrinsics = context.intrinsics - private val nameToTransformer: Map IrExpression> + private val nameToTransformer: Map IrExpression> init { nameToTransformer = mutableMapOf() nameToTransformer.run { put(Name.identifier("toString")) { call -> if (shouldReplaceToStringWithRuntimeCall(call)) { - if (call.isSuperToAny()) { + if ((call as IrCall).isSuperToAny()) { irCall(call, intrinsics.jsAnyToString, dispatchReceiverAsFirstArgument = true) } else { irCall(call, intrinsics.jsToString, dispatchReceiverAsFirstArgument = true) @@ -40,7 +41,7 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform put(Name.identifier("hashCode")) { call -> if (call.symbol.owner.isFakeOverriddenFromAny()) { - if (call.isSuperToAny()) { + if ((call as IrCall).isSuperToAny()) { irCall(call, intrinsics.jsGetObjectHashCode, dispatchReceiverAsFirstArgument = true) } else { irCall(call, intrinsics.jsHashCode, dispatchReceiverAsFirstArgument = true) @@ -53,7 +54,7 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform } - override fun transformCall(call: IrCall): IrExpression { + override fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression { val symbol = call.symbol nameToTransformer[symbol.owner.name]?.let { return it(call) @@ -62,7 +63,7 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform return call } - private fun shouldReplaceToStringWithRuntimeCall(call: IrCall): Boolean { + private fun shouldReplaceToStringWithRuntimeCall(call: IrFunctionAccessExpression): Boolean { // TODO: (KOTLIN-CR-2079) // - User defined extension functions Any?.toString() call can be lost during lowering. // - Use direct method call for dynamic types??? diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberConversionCallsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberConversionCallsTransformer.kt index 25e6d1da8e0..a286e7303a3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberConversionCallsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberConversionCallsTransformer.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.utils.ConversionNames import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTransformer { private val intrinsics = context.intrinsics @@ -74,7 +75,7 @@ class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTrans } } - override fun transformCall(call: IrCall): IrExpression { + override fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression { val function = call.symbol.owner function.dispatchReceiverParameter?.also { val key = SimpleMemberKey(it.type, function.name) @@ -85,7 +86,7 @@ class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTrans return call } - private fun useDispatchReceiver(call: IrCall): IrExpression { + private fun useDispatchReceiver(call: IrFunctionAccessExpression): IrExpression { return JsIrBuilder.buildImplicitCast(call.dispatchReceiver!!, call.type) } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberOperatorCallsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberOperatorCallsTransformer.kt index f0fe277a662..11c18844433 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberOperatorCallsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberOperatorCallsTransformer.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.types.* @@ -71,7 +72,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo } } - override fun transformCall(call: IrCall): IrExpression { + override fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression { val function = call.symbol.owner function.dispatchReceiverParameter?.also { val key = SimpleMemberKey(it.type, function.name) @@ -82,7 +83,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo return call } - private fun transformRangeTo(call: IrCall): IrExpression { + private fun transformRangeTo(call: IrFunctionAccessExpression): IrExpression { if (call.valueArgumentsCount != 1) return call return with(call.symbol.owner.valueParameters[0].type) { when { @@ -96,7 +97,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo } private fun irBinaryOp( - call: IrCall, + call: IrFunctionAccessExpression, intrinsic: IrFunctionSymbol, toInt32: Boolean = false ): IrExpression { @@ -106,7 +107,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo return newCall } - class BinaryOp(call: IrCall) { + class BinaryOp(call: IrFunctionAccessExpression) { val function = call.symbol.owner val name = function.name val lhs = function.dispatchReceiverParameter!!.type @@ -117,13 +118,13 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo result.isInt() && (lhs.isInt() || rhs.isInt()) } - private fun transformAdd(call: IrCall) = + private fun transformAdd(call: IrFunctionAccessExpression) = irBinaryOp(call, intrinsics.jsPlus, toInt32 = BinaryOp(call).canAddOrSubOverflow()) - private fun transformSub(call: IrCall) = + private fun transformSub(call: IrFunctionAccessExpression) = irBinaryOp(call, intrinsics.jsMinus, toInt32 = BinaryOp(call).canAddOrSubOverflow()) - private fun transformMul(call: IrCall) = BinaryOp(call).run { + private fun transformMul(call: IrFunctionAccessExpression) = BinaryOp(call).run { when { result.isInt() -> when { @@ -138,19 +139,19 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo } } - private fun transformDiv(call: IrCall) = + private fun transformDiv(call: IrFunctionAccessExpression) = irBinaryOp(call, intrinsics.jsDiv, toInt32 = BinaryOp(call).result.isInt()) - private fun transformRem(call: IrCall) = + private fun transformRem(call: IrFunctionAccessExpression) = irBinaryOp(call, intrinsics.jsMod) - private fun transformIncrement(call: IrCall) = + private fun transformIncrement(call: IrFunctionAccessExpression) = transformCrement(call, intrinsics.jsPlus) - private fun transformDecrement(call: IrCall) = + private fun transformDecrement(call: IrFunctionAccessExpression) = transformCrement(call, intrinsics.jsMinus) - private fun transformCrement(call: IrCall, correspondingBinaryOp: IrFunctionSymbol): IrExpression { + private fun transformCrement(call: IrFunctionAccessExpression, correspondingBinaryOp: IrFunctionSymbol): IrExpression { val operation = irCall(call, correspondingBinaryOp, dispatchReceiverAsFirstArgument = true).apply { putValueArgument(1, buildInt(1)) } @@ -158,7 +159,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo return convertResultToPrimitiveType(operation, call.type) } - private fun transformUnaryMinus(call: IrCall) = + private fun transformUnaryMinus(call: IrFunctionAccessExpression) = convertResultToPrimitiveType( irCall(call, intrinsics.jsUnaryMinus, dispatchReceiverAsFirstArgument = true), call.type @@ -171,7 +172,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo else -> e } - private fun withLongCoercion(default: (IrCall) -> IrExpression): (IrCall) -> IrExpression = { call -> + private fun withLongCoercion(default: (IrFunctionAccessExpression) -> IrExpression): (IrFunctionAccessExpression) -> IrExpression = { call -> assert(call.valueArgumentsCount == 1) val arg = call.getValueArgument(0)!! diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/PrimitiveContainerMemberCallTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/PrimitiveContainerMemberCallTransformer.kt index 393f1677063..35b9fd177b2 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/PrimitiveContainerMemberCallTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/PrimitiveContainerMemberCallTransformer.kt @@ -8,9 +8,12 @@ package org.jetbrains.kotlin.ir.backend.js.lower.calls import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.util.getSimpleFunction import org.jetbrains.kotlin.ir.util.getPropertyGetter @@ -56,13 +59,13 @@ class PrimitiveContainerMemberCallTransformer(private val context: JsIrBackendCo } } - override fun transformCall(call: IrCall): IrExpression { - val symbol = call.symbol + override fun transformFunctionAccess(expression: IrFunctionAccessExpression): IrExpression { + val symbol = expression.symbol symbolToTransformer[symbol]?.let { - return it(call) + return it(expression) } - return call + return expression } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/ReflectionCallsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/ReflectionCallsTransformer.kt index 026535054c6..ece9aefb78f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/ReflectionCallsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/ReflectionCallsTransformer.kt @@ -10,12 +10,13 @@ import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.types.isSubtypeOfClass import org.jetbrains.kotlin.name.Name class ReflectionCallsTransformer(private val context: JsIrBackendContext) : CallsTransformer { - private val nameToTransformer: Map IrExpression> + private val nameToTransformer: Map IrExpression> init { nameToTransformer = mutableMapOf() @@ -45,7 +46,7 @@ class ReflectionCallsTransformer(private val context: JsIrBackendContext) : Call } } - override fun transformCall(call: IrCall): IrExpression { + override fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression { val symbol = call.symbol nameToTransformer[symbol.owner.name]?.let { return it(call) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt index e72928d319a..c1e0f8ec06a 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt @@ -24,10 +24,7 @@ import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.builders.irReturn import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl import org.jetbrains.kotlin.ir.util.* @@ -48,8 +45,22 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW private val arrayConstructorTransformer = ArrayConstructorTransformer(context) + override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { + val callSite = arrayConstructorTransformer.transformConstructorCall(super.visitConstructorCall(expression) as IrConstructorCall) + + if (!callSite.symbol.owner.needsInlining) + return callSite + + val callee = getFunctionDeclaration(callSite.symbol) // Get declaration of the function to be inlined. + callee.transformChildrenVoid(this) // Process recursive inline. + + val parent = allScopes.map { it.irElement }.filterIsInstance().lastOrNull() + val inliner = Inliner(callSite, callee, currentScope!!, parent, context) + return inliner.inline() + } + override fun visitCall(expression: IrCall): IrExpression { - val callSite = arrayConstructorTransformer.transformCall(super.visitCall(expression) as IrCall) + val callSite = super.visitCall(expression) as IrCall if (!callSite.symbol.owner.needsInlining) return callSite @@ -102,7 +113,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW private val IrFunction.needsInlining get() = isInlineConstructor || (this.isInline && !this.isExternal) - private inner class Inliner(val callSite: IrCall, + private inner class Inliner(val callSite: IrFunctionAccessExpression, val callee: IrFunction, val currentScope: ScopeWithIr, val parent: IrDeclarationParent?, @@ -135,7 +146,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW } } - private fun inlineFunction(callSite: IrCall, callee: IrFunction): IrReturnableBlock { + private fun inlineFunction(callSite: IrFunctionAccessExpression, callee: IrFunction): IrReturnableBlock { val copiedCallee = copyIrElement.copy(callee) as IrFunction val evaluationStatements = evaluateArguments(callSite, copiedCallee) @@ -240,11 +251,15 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW val unboundArgsSet = unboundFunctionParameters.toSet() val valueParameters = expression.getArgumentsWithIr().drop(1) // Skip dispatch receiver. - val immediateCall = IrCallImpl( - expression.startOffset, expression.endOffset, - expression.type, - functionArgument.symbol - ).apply { + val newCall = expression.run { + if (function is IrConstructor) { + IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, type, function.symbol) + } else { + IrCallImpl(startOffset, endOffset, type, functionArgument.symbol) + } + } + + val immediateCall = newCall.apply { functionParameters.forEach { val argument = if (it !in unboundArgsSet) @@ -261,7 +276,13 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW for (index in 0 until functionArgument.typeArgumentsCount) putTypeArgument(index, functionArgument.getTypeArgument(index)) } - return this@FunctionInlining.visitCall(super.visitCall(immediateCall) as IrCall) + + return if (immediateCall is IrCall) { + this@FunctionInlining.visitCall(super.visitCall(immediateCall) as IrCall) + } else { + require(immediateCall is IrConstructorCall) + this@FunctionInlining.visitConstructorCall(super.visitConstructorCall(immediateCall) as IrConstructorCall) + } } if (functionArgument !is IrBlock) return super.visitCall(expression) @@ -276,7 +297,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW override fun visitElement(element: IrElement) = element.accept(this, null) } - private fun isLambdaCall(irCall: IrCall): Boolean { + private fun isLambdaCall(irCall: IrFunctionAccessExpression): Boolean { val callee = irCall.symbol.owner val dispatchReceiver = callee.dispatchReceiverParameter ?: return false assert(!dispatchReceiver.type.isKFunction()) @@ -319,7 +340,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW //-------------------------------------------------------------------------// - private fun buildParameterToArgument(callSite: IrCall, callee: IrFunction): List { + private fun buildParameterToArgument(callSite: IrFunctionAccessExpression, callee: IrFunction): List { val parameterToArgument = mutableListOf() @@ -394,7 +415,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW //-------------------------------------------------------------------------// - private fun evaluateArguments(callSite: IrCall, callee: IrFunction): List { + private fun evaluateArguments(callSite: IrFunctionAccessExpression, callee: IrFunction): List { val parameterToArgumentOld = buildParameterToArgument(callSite, callee) val evaluationStatements = mutableListOf() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt index d11a5165994..3b27e0b9c48 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt @@ -133,6 +133,34 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer + context.getRefForExternalClass(klass) + + else -> + context.getNameForClass(klass).makeRef() + } + JsNew(ref, arguments) + } + } + override fun visitCall(expression: IrCall, context: JsGenerationContext): JsExpression { val function = expression.symbol.owner.realOverrideTarget val symbol = function.symbol diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt index 92f0b774c9f..db9ac92f582 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol @@ -20,7 +21,7 @@ import org.jetbrains.kotlin.ir.util.getInlinedClass import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.js.backend.ast.* -typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression +typealias IrCallTransformer = (IrFunctionAccessExpression, context: JsGenerationContext) -> JsExpression class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { private val transformers: Map @@ -120,7 +121,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { } addIfNotNull(intrinsics.jsCode) { call, context -> - val jsCode = translateJsCode(call, context.currentScope) + val jsCode = translateJsCode(call as IrCall, context.currentScope) when (jsCode) { is JsExpression -> jsCode @@ -129,20 +130,20 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { } } - add(intrinsics.jsName) { call: IrCall, context -> + add(intrinsics.jsName) { call, context -> val args = translateCallArguments(call, context) val receiver = args[0] JsNameRef(Namer.KCALLABLE_NAME, receiver) } - add(intrinsics.jsPropertyGet) { call: IrCall, context -> + add(intrinsics.jsPropertyGet) { call, context -> val args = translateCallArguments(call, context) val reference = args[0] val receiver = args[1] JsInvocation(JsNameRef(Namer.KPROPERTY_GET, reference), listOf(receiver)) } - add(intrinsics.jsPropertySet) { call: IrCall, context -> + add(intrinsics.jsPropertySet) { call, context -> val args = translateCallArguments(call, context) val reference = args[0] val receiver = args[1] @@ -198,14 +199,14 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { } } - add(intrinsics.jsBoxIntrinsic) { call: IrCall, context -> - val arg = translateCallArguments(call, context).single() + add(intrinsics.jsBoxIntrinsic) { call, context -> + val arg = translateCallArguments(call as IrCall, context).single() val inlineClass = call.getTypeArgument(0)!!.getInlinedClass()!! val constructor = inlineClass.declarations.filterIsInstance().single { it.isPrimary } JsNew(context.getNameForConstructor(constructor).makeRef(), listOf(arg)) } - add(intrinsics.jsUnboxIntrinsic) { call: IrCall, context -> + add(intrinsics.jsUnboxIntrinsic) { call, context -> val arg = translateCallArguments(call, context).single() val inlineClass = call.getTypeArgument(1)!!.getInlinedClass()!! val field = getInlineClassBackingField(inlineClass) @@ -213,10 +214,10 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { JsNameRef(fieldName, arg) } - add(intrinsics.jsBind) { call: IrCall, context: JsGenerationContext -> + add(intrinsics.jsBind) { call, context: JsGenerationContext -> val receiver = call.getValueArgument(0)!! val reference = call.getValueArgument(1) as IrFunctionReference - val superClass = call.superQualifierSymbol!! + val superClass = (call as IrCall).superQualifierSymbol!! val jsReceiver = receiver.accept(IrElementToJsExpressionTransformer(), context) val functionName = context.getNameForMemberFunction(reference.symbol.owner as IrSimpleFunction) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index 6182fda43b5..e6c4a6cd31f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.IrSimpleType @@ -395,6 +396,41 @@ fun ReferenceSymbolTable.referenceFunction(callable: CallableDescriptor): IrFunc * [dispatchReceiverAsFirstArgument]: optionally convert call with dispatch receiver to static call * [firstArgumentAsDispatchReceiver]: optionally convert static call to call with dispatch receiver */ + +fun irConstructorCall( + call: IrMemberAccessExpression, + newFunction: IrConstructor, + dispatchReceiverAsFirstArgument: Boolean = false, + firstArgumentAsDispatchReceiver: Boolean = false +): IrConstructorCall = + irConstructorCall(call, newFunction.symbol, dispatchReceiverAsFirstArgument, firstArgumentAsDispatchReceiver) + +fun irConstructorCall( + call: IrMemberAccessExpression, + newSymbol: IrConstructorSymbol, + dispatchReceiverAsFirstArgument: Boolean = false, + firstArgumentAsDispatchReceiver: Boolean = false +): IrConstructorCall = + call.run { + IrConstructorCallImpl( + startOffset, + endOffset, + type, + newSymbol, + newSymbol.descriptor, + typeArgumentsCount, + 0, + call.valueArgumentsCount, + origin + ).apply { + copyTypeAndValueArgumentsFrom( + call, + dispatchReceiverAsFirstArgument, + firstArgumentAsDispatchReceiver + ) + } + } + fun irCall( call: IrMemberAccessExpression, newFunction: IrFunction, @@ -427,7 +463,7 @@ fun irCall( } } -private fun IrCall.copyTypeAndValueArgumentsFrom( +private fun IrMemberAccessExpression.copyTypeAndValueArgumentsFrom( call: IrMemberAccessExpression, dispatchReceiverAsFirstArgument: Boolean = false, firstArgumentAsDispatchReceiver: Boolean = false