diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index 844b0de81f2..cad9a89467b 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.ir.KonanIr import org.jetbrains.kotlin.backend.konan.llvm.* import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager -import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD +import org.jetbrains.kotlin.backend.konan.lower.BridgesSupport import org.jetbrains.kotlin.backend.konan.lower.InnerClassesSupport import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport import org.jetbrains.kotlin.backend.konan.optimizations.DevirtualizationAnalysis @@ -28,12 +28,10 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass import org.jetbrains.kotlin.ir.deepCopyWithVariables import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.types.IrTypeSystemContext import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl import org.jetbrains.kotlin.ir.util.* @@ -54,7 +52,10 @@ import kotlin.LazyThreadSafetyMode.PUBLICATION import kotlin.reflect.KProperty internal class NativeMapping : DefaultMapping() { + data class BridgeKey(val target: IrSimpleFunction, val bridgeDirections: BridgeDirections) + val outerThisFields = DefaultDelegateFactory.newDeclarationToDeclarationMapping() + val bridges = mutableMapOf() } internal class InlineFunctionOriginInfo(val irFunction: IrFunction, val irFile: IrFile, val startOffset: Int, val endOffset: Int) @@ -68,10 +69,6 @@ internal class SpecialDeclarationsFactory(val context: Context) { private val internalLoweredEnums = mutableMapOf() private val externalLoweredEnums = mutableMapOf() - private data class BridgeKey(val target: IrSimpleFunction, val bridgeDirections: BridgeDirections) - - private val bridges = mutableMapOf() - private val notLoweredInlineFunctions = mutableMapOf() val loweredInlineFunctions = mutableMapOf() fun getNonLoweredInlineFunction(function: IrFunction): IrFunction { @@ -112,61 +109,6 @@ internal class SpecialDeclarationsFactory(val context: Context) { fun getEnumEntryOrdinal(enumEntry: IrEnumEntry) = enumEntry.parentAsClass.declarations.filterIsInstance().indexOf(enumEntry) - - fun getBridge(overriddenFunction: OverriddenFunctionInfo): IrSimpleFunction { - val irFunction = overriddenFunction.function - assert(overriddenFunction.needBridge) { - "Function ${irFunction.descriptor} is not needed in a bridge to call overridden function ${overriddenFunction.overriddenFunction.descriptor}" - } - val key = BridgeKey(irFunction, overriddenFunction.bridgeDirections) - return bridges.getOrPut(key) { createBridge(key) } - } - - private fun createBridge(key: BridgeKey): IrSimpleFunction { - val (function, bridgeDirections) = key - val startOffset = function.startOffset - val endOffset = function.endOffset - - fun BridgeDirection.type() = - if (this.kind == BridgeDirectionKind.NONE) - null - else this.irClass?.defaultType ?: context.irBuiltIns.anyNType - - return IrFunctionImpl( - startOffset, endOffset, - DECLARATION_ORIGIN_BRIDGE_METHOD(function), - IrSimpleFunctionSymbolImpl(), - "${function.computeFunctionName()}".synthesizedName, - function.visibility, - function.modality, - isInline = false, - isExternal = false, - isTailrec = false, - isSuspend = function.isSuspend, - returnType = bridgeDirections.returnDirection.type() ?: function.returnType, - isExpect = false, - isFakeOverride = false, - isOperator = false, - isInfix = false - ).apply { - val bridge = this - parent = function.parent - - dispatchReceiverParameter = function.dispatchReceiverParameter?.let { - it.copyTo(bridge, type = bridgeDirections.dispatchReceiverDirection.type() ?: it.type) - } - extensionReceiverParameter = function.extensionReceiverParameter?.let { - it.copyTo(bridge, type = bridgeDirections.extensionReceiverDirection.type() ?: it.type) - } - valueParameters += function.valueParameters.map { - it.copyTo(bridge, type = bridgeDirections.parameterDirectionAt(it.index).type() ?: it.type) - } - - typeParameters += function.typeParameters.map { parameter -> - parameter.copyToWithoutSuperTypes(bridge).also { it.superTypes += parameter.superTypes } - } - } - } } internal class Context(config: KonanConfig) : KonanBackendContext(config) { @@ -205,6 +147,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { val specialDeclarationsFactory = SpecialDeclarationsFactory(this) val innerClassesSupport by lazy { InnerClassesSupport(mapping, irFactory) } + val bridgesSupport by lazy { BridgesSupport(mapping, irBuiltIns, irFactory) } open class LazyMember(val initializer: Context.() -> T) { operator fun getValue(thisRef: Context, property: KProperty<*>): T = thisRef.getValue(this) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt index 0fac59efb07..5e46c631ec8 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt @@ -57,7 +57,7 @@ internal class OverriddenFunctionInfo( } else { function } - context.specialDeclarationsFactory.getBridge(OverriddenFunctionInfo(bridgeOwner, overriddenFunction)) + context.bridgesSupport.getBridge(OverriddenFunctionInfo(bridgeOwner, overriddenFunction)) } return if (implementation.modality == Modality.ABSTRACT) null else implementation } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt index 13cad522916..2d61f97aba8 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt @@ -11,10 +11,14 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.NativeMapping import org.jetbrains.kotlin.backend.konan.descriptors.* +import org.jetbrains.kotlin.backend.konan.llvm.computeFunctionName import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl @@ -26,13 +30,61 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.isNullableAny -import org.jetbrains.kotlin.ir.util.simpleFunctions -import org.jetbrains.kotlin.ir.util.transformFlat +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature import org.jetbrains.kotlin.load.java.SpecialGenericSignatures +internal class BridgesSupport(mapping: NativeMapping, val irBuiltIns: IrBuiltIns, val irFactory: IrFactory) { + private val bridges = mapping.bridges + + fun getBridge(overriddenFunction: OverriddenFunctionInfo): IrSimpleFunction { + val irFunction = overriddenFunction.function + assert(overriddenFunction.needBridge) { + "Function ${irFunction.render()} doesn't need a bridge to call overridden function ${overriddenFunction.overriddenFunction.render()}" + } + val key = NativeMapping.BridgeKey(irFunction, overriddenFunction.bridgeDirections) + return bridges.getOrPut(key) { createBridge(key) } + } + + private fun BridgeDirection.type() = + if (this.kind == BridgeDirectionKind.NONE) + null + else this.irClass?.defaultType ?: irBuiltIns.anyNType + + private fun createBridge(key: NativeMapping.BridgeKey): IrSimpleFunction { + val (function, bridgeDirections) = key + + return irFactory.buildFun { + startOffset = function.startOffset + endOffset = function.endOffset + origin = DECLARATION_ORIGIN_BRIDGE_METHOD(function) + name = "${function.computeFunctionName()}".synthesizedName + visibility = function.visibility + modality = function.modality + returnType = bridgeDirections.returnDirection.type() ?: function.returnType + isSuspend = function.isSuspend + }.apply { + parent = function.parent + val bridge = this + + dispatchReceiverParameter = function.dispatchReceiverParameter?.let { + it.copyTo(bridge, type = bridgeDirections.dispatchReceiverDirection.type() ?: it.type) + } + extensionReceiverParameter = function.extensionReceiverParameter?.let { + it.copyTo(bridge, type = bridgeDirections.extensionReceiverDirection.type() ?: it.type) + } + valueParameters = function.valueParameters.map { + it.copyTo(bridge, type = bridgeDirections.parameterDirectionAt(it.index).type() ?: it.type) + } + + typeParameters = function.typeParameters.map { parameter -> + parameter.copyToWithoutSuperTypes(bridge).also { it.superTypes += parameter.superTypes } + } + } + } +} internal class WorkersBridgesBuilding(val context: Context) : DeclarationContainerLoweringPass, IrElementTransformerVoid() { val symbols = context.ir.symbols @@ -230,7 +282,7 @@ private fun Context.buildBridge(startOffset: Int, endOffset: Int, overriddenFunction: OverriddenFunctionInfo, targetSymbol: IrSimpleFunctionSymbol, superQualifierSymbol: IrClassSymbol? = null): IrFunction { - val bridge = specialDeclarationsFactory.getBridge(overriddenFunction) + val bridge = bridgesSupport.getBridge(overriddenFunction) if (bridge.modality == Modality.ABSTRACT) { return bridge