diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/SharedVariablesManager.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/SharedVariablesManager.kt index 0afaafc53e8..f773afdbc4c 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/SharedVariablesManager.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/SharedVariablesManager.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.IrSetValue +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol interface SharedVariablesManager { @@ -17,7 +18,7 @@ interface SharedVariablesManager { fun defineSharedValue(originalDeclaration: IrVariable, sharedVariableDeclaration: IrVariable): IrStatement - fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue): IrExpression + fun getSharedValue(sharedVariableSymbol: IrValueSymbol, originalGet: IrGetValue): IrExpression - fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetValue): IrExpression + fun setSharedValue(sharedVariableSymbol: IrValueSymbol, originalSet: IrSetValue): IrExpression } \ No newline at end of file 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 928a7d99bcd..c67b16f7d5c 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 @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol class JsSharedVariablesManager(context: JsIrBackendContext) : SharedVariablesManager { @@ -59,7 +60,7 @@ class JsSharedVariablesManager(context: JsIrBackendContext) : SharedVariablesMan override fun defineSharedValue(originalDeclaration: IrVariable, sharedVariableDeclaration: IrVariable) = sharedVariableDeclaration - override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue): IrExpression { + override fun getSharedValue(sharedVariableSymbol: IrValueSymbol, originalGet: IrGetValue): IrExpression { return IrCallImpl( originalGet.startOffset, @@ -83,7 +84,7 @@ class JsSharedVariablesManager(context: JsIrBackendContext) : SharedVariablesMan } } - override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetValue): IrExpression { + override fun setSharedValue(sharedVariableSymbol: IrValueSymbol, originalSet: IrSetValue): IrExpression { return IrCallImpl( originalSet.startOffset, originalSet.endOffset, diff --git a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index c8e771453ba..e47b42438bd 100644 --- a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -8,10 +8,7 @@ package org.jetbrains.kotlin.backend.jvm import org.jetbrains.kotlin.analyzer.hasJdkCapability import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl -import org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase -import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig -import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel -import org.jetbrains.kotlin.backend.common.phaser.then +import org.jetbrains.kotlin.backend.common.phaser.* import org.jetbrains.kotlin.backend.jvm.ir.getKtFile import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor import org.jetbrains.kotlin.codegen.CodegenFactory @@ -50,7 +47,7 @@ open class JvmIrCodegenFactory( private val externalMangler: JvmDescriptorMangler? = null, private val externalSymbolTable: SymbolTable? = null, private val jvmGeneratorExtensions: JvmGeneratorExtensionsImpl = JvmGeneratorExtensionsImpl(configuration), - private val prefixPhases: NamedCompilerPhase? = null, + private val prefixPhases: CompilerPhase? = null, private val evaluatorFragmentInfoForPsi2Ir: EvaluatorFragmentInfo? = null, ) : CodegenFactory { data class JvmIrBackendInput( diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FragmentSharedVariablesLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FragmentSharedVariablesLowering.kt new file mode 100644 index 00000000000..f9d803da6fa --- /dev/null +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FragmentSharedVariablesLowering.kt @@ -0,0 +1,119 @@ +/* + * Copyright 2010-2021 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.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrGetValue +import org.jetbrains.kotlin.ir.expressions.IrSetValue +import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +// Used from the IntelliJ IDEA Kotlin Debugger Plug-In +@Suppress("unused") +val fragmentSharedVariablesLowering = makeIrModulePhase( + ::FragmentSharedVariablesLowering, + name = "FragmentSharedVariablesLowering", + description = "Promotes captured variables that are modified by the fragment to shared variables" +) + +// This lowering is a preprocessor for IR in order to support the compilation +// scheme used by the "Evaluate Expression..." mechanism of the IntelliJ plug-in +// for Kotlin debugging. +// +// Fragments are compiled as the body of an enclosing function that close the free +// variables of the fragment as parameters. The values of these are then extracted +// from the stack at the current breakpoint, and the fragment code is invoked with +// these values to evaluate the expression. +// +// If the parameter is a shared variable, e.g. `IntRef` (the same mechanism used to +// implement captures of lambdas) the value extracted from the stack is +// automatically boxed in a `Ref` before being passed to the fragment. +// +// Upon return, all `Ref`s are written back into the stack, thus allowing fragments +// to modify the state of the program being debugged. +// +// This lowering promotes these parameters to `Ref`s, as deemed appropriate by +// psi2ir's Fragment generation. +// +// The reason for this "phasing" is that the JVM specific infrastructure (e.g. +// symbols for `Ref`s) have not been loaded when psi2ir runs, as psi2ir is designed +// to be backend agnostic. So, we "tag" the appropriate parameters with a new +// JvmIrDeclarationOrigin that we can then detect in this lowering. +// +// See `FragmentDeclarationGenerator.kt:declareParameter` for the front half +// of this logic. +class FragmentSharedVariablesLowering( + val context: JvmBackendContext +) : IrElementTransformerVoidWithContext(), FileLoweringPass { + + companion object { + // Echo of GENERATED_FUNCTION_NAME in the JVM Debugger plug-in. + // TODO: Find a good common dependency of JVM Debugger and IR Compiler and deduplicate this + const val GENERATED_FUNCTION_NAME = "generated_for_debugger_fun" + } + + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(this) + } + + override fun visitFunctionNew(declaration: IrFunction): IrStatement { + if (declaration.name.asString() != GENERATED_FUNCTION_NAME) { + return super.visitFunctionNew(declaration) + } + + val promotedParameters = promoteParametersForCapturesToRefs(declaration) + replaceUseOfPromotedParametersWithRefs(declaration, promotedParameters) + return declaration + } + + private fun promoteParametersForCapturesToRefs(declaration: IrFunction): Map { + val promotedParameters = mutableMapOf() + declaration.valueParameters = declaration.valueParameters.map { + if (it.origin == IrDeclarationOrigin.SHARED_VARIABLE_IN_EVALUATOR_FRAGMENT) { + val newParameter = + it.copyTo( + declaration, + type = context.sharedVariablesManager.getIrType(it.type), + origin = IrDeclarationOrigin.DEFINED + ) + promotedParameters[it.symbol] = newParameter.symbol + newParameter + } else { + it + } + } + return promotedParameters + } + + private fun replaceUseOfPromotedParametersWithRefs( + declaration: IrFunction, + promotedParameters: Map + ) { + declaration.body!!.transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitGetValue(expression: IrGetValue): IrExpression { + expression.transformChildrenVoid(this) + val newDeclaration = promotedParameters[expression.symbol] ?: return expression + return context.sharedVariablesManager.getSharedValue(newDeclaration, expression) + } + + override fun visitSetValue(expression: IrSetValue): IrExpression { + expression.transformChildrenVoid(this) + val newDeclaration = promotedParameters[expression.symbol] ?: return expression + return context.sharedVariablesManager.setSharedValue(newDeclaration, expression) + } + }) + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSharedVariablesManager.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSharedVariablesManager.kt index 167991a1c22..4e7458a4c11 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSharedVariablesManager.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSharedVariablesManager.kt @@ -19,7 +19,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.IrSetValue import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.name.FqName @@ -39,7 +39,7 @@ class JvmSharedVariablesManager( name = Name.identifier("Ref") } - private class RefProvider(val refClass: IrClass, elementType: IrType) { + class RefProvider(val refClass: IrClass, elementType: IrType) { val refConstructor = refClass.addConstructor { origin = IrDeclarationOrigin.IR_BUILTINS_STUB } @@ -75,7 +75,7 @@ class JvmSharedVariablesManager( RefProvider(refClass, refClass.typeParameters[0].defaultType) } - private fun getProvider(valueType: IrType): RefProvider = + fun getProvider(valueType: IrType): RefProvider = if (valueType.isPrimitiveType()) primitiveRefProviders.getValue(valueType.classifierOrFail) else @@ -129,7 +129,7 @@ class JvmSharedVariablesManager( putValueArgument(0, value) } - override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue): IrExpression = + override fun getSharedValue(sharedVariableSymbol: IrValueSymbol, originalGet: IrGetValue): IrExpression = with(originalGet) { val unboxedType = InlineClassAbi.unboxType(symbol.owner.type) val provider = getProvider(unboxedType ?: symbol.owner.type) @@ -138,7 +138,7 @@ class JvmSharedVariablesManager( unboxedType?.let { unsafeCoerce(unboxedRead, it, symbol.owner.type) } ?: unboxedRead } - override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetValue): IrExpression = + override fun setSharedValue(sharedVariableSymbol: IrValueSymbol, originalSet: IrSetValue): IrExpression = with(originalSet) { val unboxedType = InlineClassAbi.unboxType(symbol.owner.type) val unboxedValue = unboxedType?.let { unsafeCoerce(value, symbol.owner.type, it) } ?: value @@ -146,6 +146,13 @@ class JvmSharedVariablesManager( val receiver = IrGetValueImpl(startOffset, endOffset, sharedVariableSymbol) IrSetFieldImpl(startOffset, endOffset, provider.elementField.symbol, receiver, unboxedValue, type, origin) } + + @Suppress("MemberVisibilityCanBePrivate") // Used by FragmentSharedVariablesLowering + fun getIrType(originalType: IrType): IrType { + val provider = getProvider(InlineClassAbi.unboxType(originalType) ?: originalType) + val typeArguments = provider.refClass.typeParameters.map { originalType } + return provider.refClass.typeWith(typeArguments) + } } private inline fun IrFactory.addClass( diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmSharedVariablesManager.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmSharedVariablesManager.kt index 0c6772b3476..589a4766f33 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmSharedVariablesManager.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmSharedVariablesManager.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.IrSetValue import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl @@ -78,7 +79,7 @@ class WasmSharedVariablesManager(val context: JsCommonBackendContext, val builtI override fun defineSharedValue(originalDeclaration: IrVariable, sharedVariableDeclaration: IrVariable) = sharedVariableDeclaration - override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue): IrExpression { + override fun getSharedValue(sharedVariableSymbol: IrValueSymbol, originalGet: IrGetValue): IrExpression { val getField = IrGetFieldImpl( originalGet.startOffset, originalGet.endOffset, closureBoxFieldDeclaration.symbol, @@ -103,7 +104,7 @@ class WasmSharedVariablesManager(val context: JsCommonBackendContext, val builtI ) } - override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetValue): IrExpression = + override fun setSharedValue(sharedVariableSymbol: IrValueSymbol, originalSet: IrSetValue): IrExpression = IrSetFieldImpl( originalSet.startOffset, originalSet.endOffset, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/EvaluatorFragmentInfo.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/EvaluatorFragmentInfo.kt index fd941e67415..59f85cf08c8 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/EvaluatorFragmentInfo.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/EvaluatorFragmentInfo.kt @@ -22,5 +22,27 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor class EvaluatorFragmentInfo( val classDescriptor: ClassDescriptor, val methodDescriptor: FunctionDescriptor, - val parameters: List + parameterDescriptors: List, +) { + var parameters: List = parameterDescriptors.map { EvaluatorFragmentParameterInfo(it, false) } + + companion object { + // Used in the IntelliJ Kotlin JVM Debugger Plug-In (CodeFragmentCompiler) + // TODO: Remove once intellij-community#1839 has landed. + @Suppress("unused") + fun createWithFragmentParameterInfo( + classDescriptor: ClassDescriptor, + methodDescriptor: FunctionDescriptor, + parametersWithInfo: List + ) = + EvaluatorFragmentInfo(classDescriptor, methodDescriptor, listOf()).apply { + parameters = parametersWithInfo + } + } +} + + +data class EvaluatorFragmentParameterInfo( + val descriptor: DeclarationDescriptor, + val isLValue: Boolean, ) \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentCompilerSymbolTableDecorator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentCompilerSymbolTableDecorator.kt index afd6791d944..02341613221 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentCompilerSymbolTableDecorator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentCompilerSymbolTableDecorator.kt @@ -31,10 +31,10 @@ class FragmentCompilerSymbolTableDecorator( if (descriptor !is ReceiverParameterDescriptor) return super.referenceValueParameter(descriptor) val finderPredicate = when (val receiverValue = descriptor.value) { - is ExtensionReceiver -> { targetDescriptor: DeclarationDescriptor -> + is ExtensionReceiver -> { (targetDescriptor, _): EvaluatorFragmentParameterInfo -> receiverValue == (targetDescriptor as? ReceiverParameterDescriptor)?.value } - is ThisClassReceiver -> { targetDescriptor: DeclarationDescriptor -> + is ThisClassReceiver -> { (targetDescriptor, _): EvaluatorFragmentParameterInfo -> receiverValue.classDescriptor == targetDescriptor.original } else -> TODO("Unimplemented") @@ -50,7 +50,7 @@ class FragmentCompilerSymbolTableDecorator( override fun referenceValue(value: ValueDescriptor): IrValueSymbol { val parameterPosition = - fragmentInfo.parameters.indexOf(value) + fragmentInfo.parameters.indexOfFirst { it.descriptor == value } if (parameterPosition > -1) { return super.referenceValueParameter(fragmentInfo.methodDescriptor.valueParameters[parameterPosition]) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentDeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentDeclarationGenerator.kt index 38ef2764339..f6bf48046f7 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentDeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/fragments/FragmentDeclarationGenerator.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.psi.KtBlockCodeFragment import org.jetbrains.kotlin.psi2ir.generators.Generator import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext import org.jetbrains.kotlin.psi2ir.generators.createBodyGenerator +import org.jetbrains.kotlin.resolve.BindingContextUtils import org.jetbrains.kotlin.types.KotlinType open class FragmentDeclarationGenerator( @@ -91,32 +92,51 @@ open class FragmentDeclarationGenerator( private fun generateFragmentValueParameterDeclarations(irFunction: IrSimpleFunction) { val functionDescriptor = irFunction.descriptor functionDescriptor.valueParameters.forEachIndexed { index, valueParameterDescriptor -> - irFunction.valueParameters += declareParameter(valueParameterDescriptor).apply { - context.fragmentContext!!.capturedDescriptorToFragmentParameterMap[fragmentInfo.parameters[index]] = this.symbol + val parameterInfo = fragmentInfo.parameters[index] + irFunction.valueParameters += declareParameter(valueParameterDescriptor, parameterInfo).apply { + context.fragmentContext!!.capturedDescriptorToFragmentParameterMap[parameterInfo.descriptor] = this.symbol } } } - private fun declareParameter(descriptor: ValueParameterDescriptor): IrValueParameter { - // Parameter must be _assignable_: - // These parameters model the captured variables of the fragment. The captured - // _values_ are extracted from the call stack of the JVM being debugged, and supplied - // to the fragment evaluator via these parameters. Any modifications by the fragment - // are written directly to the parameter, and then extracted from the stack frame - // of the interpreter/JVM evaluating the fragment and written back into the call - // stack of the JVM being debugged. + private fun declareParameter(descriptor: ValueParameterDescriptor, parameterInfo: EvaluatorFragmentParameterInfo): IrValueParameter { + // Parameter must be _assignable_ if written by the fragment: + // These parameters model the captured variables of the fragment. The + // captured _values_ are extracted from the call stack of the JVM being + // debugged, and supplied to the fragment evaluator via these + // parameters. + // + // If the parameter is modified by the fragment, the parameter is boxed + // in a `Ref`, and the value extracted from that box upon return from + // the fragment, then written back into the stack frame of the JVM + // being debugged. + // + // The promotion to `Ref` and the replacement of loads/stores with the + // appropriate getfield/putfield API of the `Ref` is done _after_ + // psi2ir, so for now we must mark the parameter as assignable for the + // of IR generation. The replacement is delayed because the JVM + // specific infrastructure (i.e. "SharedVariableContext") is not yet + // instantiated: PSI2IR is kept backend agnostic. return context.symbolTable.declareValueParameter( UNDEFINED_OFFSET, UNDEFINED_OFFSET, - IrDeclarationOrigin.DEFINED, + if (shouldPromoteToSharedVariable(parameterInfo)) IrDeclarationOrigin.SHARED_VARIABLE_IN_EVALUATOR_FRAGMENT else IrDeclarationOrigin.DEFINED, descriptor, descriptor.type.toIrType(), - (descriptor as? ValueParameterDescriptor)?.varargElementType?.toIrType(), + descriptor.varargElementType?.toIrType(), null, - isAssignable = true + isAssignable = parameterInfo.isLValue ) } + private fun shouldPromoteToSharedVariable(parameterInfo: EvaluatorFragmentParameterInfo) = + parameterInfo.isLValue || + BindingContextUtils.isBoxedLocalCapturedInClosure( + context.bindingContext, + parameterInfo.descriptor + ) + + private fun KotlinType.toIrType() = context.typeTranslator.translateType(this) private inline fun T.buildWithScope(builder: (T) -> Unit): T = diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt index e40bd869562..e204debb29c 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationOrigin.kt @@ -83,6 +83,8 @@ interface IrDeclarationOrigin { object CONTINUATION : IrDeclarationOriginImpl("CONTINUATION", isSynthetic = true) object LOWERED_SUSPEND_FUNCTION : IrDeclarationOriginImpl("LOWERED_SUSPEND_FUNCTION", isSynthetic = true) + object SHARED_VARIABLE_IN_EVALUATOR_FRAGMENT : IrDeclarationOriginImpl("SHARED_VARIABLE_IN_EVALUATOR_FRAGMENT", isSynthetic = true) + val isSynthetic: Boolean get() = false } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt index b52879b237c..7074a954423 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl -import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.util.constructors @@ -74,7 +74,7 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S ) } - override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue) = + override fun getSharedValue(sharedVariableSymbol: IrValueSymbol, originalGet: IrGetValue) = IrCallImpl(originalGet.startOffset, originalGet.endOffset, originalGet.type, elementProperty.getter!!.symbol, elementProperty.getter!!.typeParameters.size, elementProperty.getter!!.valueParameters.size).apply { @@ -84,7 +84,7 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S ) } - override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetValue) = + override fun setSharedValue(sharedVariableSymbol: IrValueSymbol, originalSet: IrSetValue) = IrCallImpl(originalSet.startOffset, originalSet.endOffset, context.irBuiltIns.unitType, elementProperty.setter!!.symbol, elementProperty.setter!!.typeParameters.size, elementProperty.setter!!.valueParameters.size).apply {