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 3df422002bd..07154ef4e1a 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 @@ -66,6 +66,10 @@ internal class NativeMapping : DefaultMapping() { val bridges = mutableMapOf() val notLoweredInlineFunctions = mutableMapOf() val loweredInlineFunctions = mutableMapOf() + val companionObjectCacheAccessors = DefaultDelegateFactory.newDeclarationToDeclarationMapping() + val outerThisCacheAccessors = DefaultDelegateFactory.newDeclarationToDeclarationMapping() + val lateinitPropertyCacheAccessors = DefaultDelegateFactory.newDeclarationToDeclarationMapping() + val enumValuesCacheAccessors = DefaultDelegateFactory.newDeclarationToDeclarationMapping() } internal class Context(config: KonanConfig) : KonanBackendContext(config) { @@ -106,6 +110,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { val bridgesSupport by lazy { BridgesSupport(mapping, irBuiltIns, irFactory) } val inlineFunctionsSupport by lazy { InlineFunctionsSupport(mapping) } val enumsSupport by lazy { EnumsSupport(mapping, ir.symbols, irBuiltIns, irFactory) } + val cachesAbiSupport by lazy { CachesAbiSupport(mapping, ir.symbols, irFactory) } open class LazyMember(val initializer: Context.() -> T) { operator fun getValue(thisRef: Context, property: KProperty<*>): T = thisRef.getValue(this) @@ -361,11 +366,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { val declaredLocalArrays: MutableMap = HashMap() - /** - * Manages internal ABI references and declarations. - */ - val internalAbi = InternalAbi(this) - lateinit var irLinker: KonanIrLinker val inlineFunctionBodies = mutableListOf() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EntryPoint.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EntryPoint.kt index 079c40bad20..bfb5ae28945 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EntryPoint.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EntryPoint.kt @@ -8,21 +8,20 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation -import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.builders.declarations.buildFun +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl -import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET import org.jetbrains.kotlin.ir.util.irCatch import org.jetbrains.kotlin.name.Name +internal object DECLARATION_ORIGIN_ENTRY_POINT : IrDeclarationOriginImpl("ENTRY_POINT") + internal fun makeEntryPoint(context: Context): IrFunction { val actualMain = context.ir.symbols.entryPoint!!.owner // TODO: Do we need to do something with the offsets if
is in a cached library? @@ -34,46 +33,27 @@ internal fun makeEntryPoint(context: Context): IrFunction { actualMain.endOffset else SYNTHETIC_OFFSET - val entryPoint = IrFunctionImpl( - startOffset, - endOffset, - IrDeclarationOrigin.DEFINED, - IrSimpleFunctionSymbolImpl(), - Name.identifier("Konan_start"), - DescriptorVisibilities.PRIVATE, - Modality.FINAL, - context.irBuiltIns.intType, - isInline = false, - isExternal = false, - isTailrec = false, - isSuspend = false, - isExpect = false, - isFakeOverride = false, - isOperator = false, - isInfix = false - ).also { function -> - function.valueParameters = listOf( - IrValueParameterImpl( - startOffset, endOffset, - IrDeclarationOrigin.DEFINED, - IrValueParameterSymbolImpl(), - Name.identifier("args"), - index = 0, - varargElementType = null, - isCrossinline = false, - type = context.irBuiltIns.arrayClass.typeWith(context.irBuiltIns.stringType), - isNoinline = false, - isHidden = false, - isAssignable = false - ).apply { - parent = function - }) + val entryPoint = context.irFactory.buildFun { + this.startOffset = startOffset + this.endOffset = endOffset + origin = DECLARATION_ORIGIN_ENTRY_POINT + name = Name.identifier("Konan_start") + visibility = DescriptorVisibilities.PRIVATE + returnType = context.irBuiltIns.intType + }.apply { + addValueParameter { + this.startOffset = startOffset + this.endOffset = endOffset + origin = DECLARATION_ORIGIN_ENTRY_POINT + name = Name.identifier("args") + type = context.irBuiltIns.arrayClass.typeWith(context.irBuiltIns.stringType) + } } entryPoint.annotations += buildSimpleAnnotation(context.irBuiltIns, startOffset, endOffset, context.ir.symbols.exportForCppRuntime.owner, "Konan_start") - val builder = context.createIrBuilder(entryPoint.symbol) + val builder = context.createIrBuilder(entryPoint.symbol, startOffset, endOffset) entryPoint.body = builder.irBlockBody(entryPoint) { +IrTryImpl(startOffset, endOffset, context.irBuiltIns.nothingType).apply { tryResult = irBlock { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InternalAbi.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InternalAbi.kt deleted file mode 100644 index 3f160e67b5a..00000000000 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InternalAbi.kt +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the LICENSE file. - */ -package org.jetbrains.kotlin.backend.konan - -import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName -import org.jetbrains.kotlin.backend.konan.llvm.llvmSymbolOrigin -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl -import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl -import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl -import org.jetbrains.kotlin.ir.util.addChild -import org.jetbrains.kotlin.ir.util.addFile -import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.scopes.MemberScope - -/** - * Sometimes we need to reference symbols that are not declared in metadata. - * For example, symbol might be declared during lowering. - * In case of compiler caches, this means that it is not accessible as Lazy IR - * and we have to explicitly add an external declaration. - */ -internal class InternalAbi(private val context: Context) { - /** - * Files that stores all internal ABI declarations. - * We use per-module files so that global initializer will be stored - * in the appropriate modules. - * - * We have to store such declarations in top-level to avoid mangling that - * makes referencing harder. - * A bit better solution is to add files with proper packages, but it is impossible - * during FileLowering (hello, ConcurrentModificationException). - */ - private lateinit var internalAbiFiles: Map - - /** - * Representation of ABI files from external modules. - */ - private val externalAbiFiles = mutableMapOf() - - fun init(modules: List) { - internalAbiFiles = modules.associate { it.descriptor to createAbiFile(it) } - } - - private fun createAbiFile(module: IrModuleFragment): IrFile = - module.addFile(NaiveSourceBasedFileEntryImpl("internal"), KonanFqNames.cachesInternalAbi) - - private fun createExternalAbiFile(module: ModuleDescriptor, fqName: FqName): IrExternalPackageFragment { - val packageFragmentDescriptor = object : PackageFragmentDescriptorImpl(module, fqName) { - override fun getMemberScope(): MemberScope = MemberScope.Empty - } - return IrExternalPackageFragmentImpl(IrExternalPackageFragmentSymbolImpl(packageFragmentDescriptor), fqName) - } - - /** - * Adds external [function] from [module] to a list of external references. - */ - fun reference(function: IrFunction, module: ModuleDescriptor) { - assert(function.isExternal) { "Function that represents external ABI should be marked as external" } - context.llvmImports.add(module.llvmSymbolOrigin) - val externalAbiFile = externalAbiFiles.getOrPut(module) { createExternalAbiFile(module, KonanFqNames.cachesInternalAbi) } - externalAbiFile.addChild(function) - } - - /** - * Adds [function] to a list of [module]'s publicly available symbols. - */ - fun declare(function: IrFunction, module: ModuleDescriptor) { - internalAbiFiles.getValue(module).addChild(function) - } - - companion object { - /** - * Allows to distinguish external declarations to internal ABI. - */ - val INTERNAL_ABI_ORIGIN = object : IrDeclarationOriginImpl("INTERNAL_ABI") {} - - fun getCompanionObjectAccessorName(companion: IrClass): Name = - getMangledNameFor("globalAccessor", companion) - - fun getEnumValuesAccessorName(enum: IrClass): Name = - getMangledNameFor("getValues", enum) - - fun getInnerClassOuterThisAccessorName(innerClass: IrClass): Name = - getMangledNameFor("outerThis", innerClass) - - fun getLateinitPropertyFieldAccessorName(property: IrProperty): Name = - getMangledNameFor("${property.name}_field", property.parent) - - /** - * Generate name for declaration that will be a part of internal ABI. - */ - private fun getMangledNameFor(declarationName: String, parent: IrDeclarationParent): Name { - val prefix = parent.fqNameForIrSerialization - return "$prefix.$declarationName".synthesizedName - } - } -} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt index 0cf6064275b..68e970389da 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt @@ -39,5 +39,4 @@ object KonanFqNames { val noReorderFields = FqName("kotlin.native.internal.NoReorderFields") val objCName = FqName("kotlin.native.ObjCName") val reflectionPackageName = FqName("kotlin.native.internal.ReflectionPackageName") - val cachesInternalAbi = FqName("kotlin.native.caches.abi") } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt index 7804d2e4974..8a736cb016b 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt @@ -242,7 +242,6 @@ internal fun Context.psiToIr( if (this.stdlibModule in modulesWithoutDCE) { (functionIrClassFactory as? BuiltInFictitiousFunctionIrClassFactory)?.buildAllClasses() } - internalAbi.init(irModules.values + irModule!!) (functionIrClassFactory as? BuiltInFictitiousFunctionIrClassFactory)?.module = (modules.values + irModule!!).single { it.descriptor.isNativeStdlib() } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index 29f8aa16c05..b6169940569 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -363,7 +363,7 @@ internal val entryPointPhase = makeCustomPhase( } else { // `main` function is compiled to other LLVM module. // For example, test running support uses `main` defined in stdlib. - context.irModule!!.addFile(NaiveSourceBasedFileEntryImpl("entryPointOwner"), FqName("kotlin.native.caches.abi")) + context.irModule!!.addFile(NaiveSourceBasedFileEntryImpl("entryPointOwner"), FqName("kotlin.native.internal.abi")) } file.addChild(makeEntryPoint(context)) @@ -425,12 +425,12 @@ private val backendCodegen = namedUnitPhase( name = "Backend codegen", description = "Backend code generation", lower = takeFromContext { it.irModule!! } then + entryPointPhase then functionsWithoutBoundCheck then allLoweringsPhase then // Lower current module first. dependenciesLowerPhase then // Then lower all libraries in topological order. // With that we guarantee that inline functions are unlowered while being inlined. dumpTestsPhase then - entryPointPhase then exportInternalAbiPhase then useInternalAbiPhase then bitcodePhase then diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index faa7b55cae8..ad3d47aefa1 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -298,8 +298,6 @@ fun IrFunction.externalSymbolOrThrow(): String? { if (annotations.hasAnnotation(RuntimeNames.cCall)) return null - if (origin == InternalAbi.INTERNAL_ABI_ORIGIN) return null - throw Error("external function ${this.longName} must have @TypedIntrinsic, @SymbolName, @GCUnsafeCall or @ObjCMethod annotation") } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CachesAbiLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CachesAbiLowering.kt index ed7da65c300..7b83061af92 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CachesAbiLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CachesAbiLowering.kt @@ -5,22 +5,23 @@ package org.jetbrains.kotlin.backend.konan.lower +import org.jetbrains.kotlin.backend.common.getOrPut import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.InternalAbi +import org.jetbrains.kotlin.backend.konan.NativeMapping +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.ir.llvmSymbolOrigin import org.jetbrains.kotlin.backend.konan.isObjCClass import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter import org.jetbrains.kotlin.ir.builders.declarations.buildFun -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrProperty -import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrGetField import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -29,42 +30,135 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name +/** + * Allows to distinguish external declarations to internal ABI. + */ +internal object INTERNAL_ABI_ORIGIN : IrDeclarationOriginImpl("INTERNAL_ABI") + +/** + * Sometimes we need to reference symbols that are not declared in metadata. + * For example, symbol might be declared during lowering. + * In case of compiler caches, this means that it is not accessible as Lazy IR + * and we have to explicitly add an external declaration. + */ +internal class CachesAbiSupport(mapping: NativeMapping, symbols: KonanSymbols, private val irFactory: IrFactory) { + private val companionObjectAccessors = mapping.companionObjectCacheAccessors + private val outerThisAccessors = mapping.outerThisCacheAccessors + private val lateinitPropertyAccessors = mapping.lateinitPropertyCacheAccessors + private val enumValuesAccessors = mapping.enumValuesCacheAccessors + private val lateInitFieldToNullableField = mapping.lateInitFieldToNullableField + private val array = symbols.array + + fun getCompanionObjectAccessor(irClass: IrClass): IrSimpleFunction { + require(irClass.isCompanion) { "Expected a companion object but was: ${irClass.render()}" } + return companionObjectAccessors.getOrPut(irClass) { + irFactory.buildFun { + name = getMangledNameFor("globalAccessor", irClass) + origin = INTERNAL_ABI_ORIGIN + returnType = irClass.defaultType + }.apply { + parent = irClass.getPackageFragment() + } + } + } + + fun getOuterThisAccessor(irClass: IrClass): IrSimpleFunction { + require(irClass.isInner) { "Expected an inner class but was: ${irClass.render()}" } + return outerThisAccessors.getOrPut(irClass) { + irFactory.buildFun { + name = getMangledNameFor("outerThis", irClass) + origin = INTERNAL_ABI_ORIGIN + returnType = irClass.parentAsClass.defaultType + }.apply { + parent = irClass.getPackageFragment() + + addValueParameter { + name = Name.identifier("innerClass") + origin = INTERNAL_ABI_ORIGIN + type = irClass.defaultType + } + } + } + } + + fun getLateinitPropertyAccessor(irProperty: IrProperty): IrSimpleFunction { + require(irProperty.isLateinit) { "Expected a lateinit property but was: ${irProperty.render()}" } + return lateinitPropertyAccessors.getOrPut(irProperty) { + val backingField = irProperty.backingField ?: error("Lateinit property ${irProperty.render()} should have a backing field") + val actualField = lateInitFieldToNullableField[backingField] ?: backingField + val owner = irProperty.parent + irFactory.buildFun { + name = getMangledNameFor("${irProperty.name}_field", owner) + origin = INTERNAL_ABI_ORIGIN + returnType = actualField.type + }.apply { + parent = irProperty.getPackageFragment() + + (owner as? IrClass)?.let { + addValueParameter { + name = Name.identifier("owner") + origin = INTERNAL_ABI_ORIGIN + type = it.defaultType + } + } + } + } + } + + fun getEnumValuesAccessor(irClass: IrClass): IrSimpleFunction { + require(irClass.isEnumClass) { "Expected a enum class but was: ${irClass.render()}" } + return enumValuesAccessors.getOrPut(irClass) { + irFactory.buildFun { + name = getMangledNameFor("getValues", irClass) + returnType = array.typeWith(irClass.defaultType) + origin = INTERNAL_ABI_ORIGIN + }.apply { + parent = irClass.getPackageFragment() + } + } + } + + /** + * Generate name for declaration that will be a part of internal ABI. + */ + private fun getMangledNameFor(declarationName: String, parent: IrDeclarationParent): Name { + val prefix = parent.fqNameForIrSerialization + return "$prefix.$declarationName".synthesizedName + } +} + internal class ExportCachesAbiVisitor(val context: Context) : IrElementVisitorVoid { + private val cachesAbiSupport = context.cachesAbiSupport + private val addedFunctions = mutableListOf() + override fun visitElement(element: IrElement) { element.acceptChildrenVoid(this) } + override fun visitFile(declaration: IrFile) { + declaration.acceptChildrenVoid(this) + + declaration.addChildren(addedFunctions) + addedFunctions.clear() + } + override fun visitClass(declaration: IrClass) { declaration.acceptChildrenVoid(this) if (declaration.isLocal) return if (declaration.isCompanion) { - val function = context.irFactory.buildFun { - name = InternalAbi.getCompanionObjectAccessorName(declaration) - origin = InternalAbi.INTERNAL_ABI_ORIGIN - returnType = declaration.defaultType - } + val function = cachesAbiSupport.getCompanionObjectAccessor(declaration) context.createIrBuilder(function.symbol).apply { function.body = irBlockBody { +irReturn(irGetObjectValue(declaration.defaultType, declaration.symbol)) } } - context.internalAbi.declare(function, declaration.module) + addedFunctions.add(function) } if (declaration.isInner) { - val function = context.irFactory.buildFun { - name = InternalAbi.getInnerClassOuterThisAccessorName(declaration) - origin = InternalAbi.INTERNAL_ABI_ORIGIN - returnType = declaration.parentAsClass.defaultType - } - function.addValueParameter { - name = Name.identifier("innerClass") - origin = InternalAbi.INTERNAL_ABI_ORIGIN - type = declaration.defaultType - } - + val function = cachesAbiSupport.getOuterThisAccessor(declaration) context.createIrBuilder(function.symbol).apply { function.body = irBlockBody { +irReturn(irGetField( @@ -73,22 +167,17 @@ internal class ExportCachesAbiVisitor(val context: Context) : IrElementVisitorVo ) } } - context.internalAbi.declare(function, declaration.module) + addedFunctions.add(function) } if (declaration.isEnumClass) { - val function = context.irFactory.buildFun { - name = InternalAbi.getEnumValuesAccessorName(declaration) - returnType = context.ir.symbols.array.typeWith(declaration.defaultType) - origin = InternalAbi.INTERNAL_ABI_ORIGIN - } - + val function = cachesAbiSupport.getEnumValuesAccessor(declaration) context.createIrBuilder(function.symbol).run { function.body = irBlockBody { +irReturn(with(this@ExportCachesAbiVisitor.context.enumsSupport) { irGetValuesField(declaration) }) } } - context.internalAbi.declare(function, declaration.module) + addedFunctions.add(function) } } @@ -100,33 +189,20 @@ internal class ExportCachesAbiVisitor(val context: Context) : IrElementVisitorVo return val backingField = declaration.backingField ?: error("Lateinit property ${declaration.render()} should have a backing field") - val function = context.irFactory.buildFun { - name = InternalAbi.getLateinitPropertyFieldAccessorName(declaration) - origin = InternalAbi.INTERNAL_ABI_ORIGIN - returnType = backingField.type - } val ownerClass = declaration.parentClassOrNull - if (ownerClass != null) - function.addValueParameter { - name = Name.identifier("owner") - origin = InternalAbi.INTERNAL_ABI_ORIGIN - type = ownerClass.defaultType - } - + val function = cachesAbiSupport.getLateinitPropertyAccessor(declaration) context.createIrBuilder(function.symbol).apply { function.body = irBlockBody { +irReturn(irGetField(ownerClass?.let { irGet(function.valueParameters[0]) }, backingField)) } } - context.internalAbi.declare(function, declaration.module) + addedFunctions.add(function) } } internal class ImportCachesAbiTransformer(val context: Context) : IrElementTransformerVoid() { - private val companionObjectAccessors = mutableMapOf() - private val outerThisAccessors = mutableMapOf() - private val lateinitPropertyAccessors = mutableMapOf() - private val enumValuesAccessors = mutableMapOf() + private val cachesAbiSupport = context.cachesAbiSupport + private val enumsSupport = context.enumsSupport override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression { expression.transformChildrenVoid(this) @@ -140,17 +216,9 @@ internal class ImportCachesAbiTransformer(val context: Context) : IrElementTrans // Access to Obj-C metaclass is done via intrinsic. return expression } - val accessor = companionObjectAccessors.getOrPut(irClass) { - context.irFactory.buildFun { - name = InternalAbi.getCompanionObjectAccessorName(irClass) - returnType = irClass.defaultType - origin = InternalAbi.INTERNAL_ABI_ORIGIN - isExternal = true - }.also { - context.internalAbi.reference(it, irClass.module) - } - } - return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size) + val accessor = cachesAbiSupport.getCompanionObjectAccessor(irClass) + context.llvmImports.add(irClass.llvmSymbolOrigin) + return irCall(expression.startOffset, expression.endOffset, accessor, emptyList()) } override fun visitGetField(expression: IrGetField): IrExpression { @@ -164,54 +232,17 @@ internal class ImportCachesAbiTransformer(val context: Context) : IrElementTrans context.llvmModuleSpecification.containsDeclaration(field) -> expression irClass?.isInner == true && context.innerClassesSupport.getOuterThisField(irClass) == field -> { - val accessor = outerThisAccessors.getOrPut(irClass) { - context.irFactory.buildFun { - name = InternalAbi.getInnerClassOuterThisAccessorName(irClass) - returnType = irClass.parentAsClass.defaultType - origin = InternalAbi.INTERNAL_ABI_ORIGIN - isExternal = true - }.also { function -> - context.internalAbi.reference(function, irClass.module) - - function.addValueParameter { - name = Name.identifier("innerClass") - origin = InternalAbi.INTERNAL_ABI_ORIGIN - type = irClass.defaultType - } - } - } - return IrCallImpl( - expression.startOffset, expression.endOffset, - expression.type, accessor.symbol, - accessor.typeParameters.size, accessor.valueParameters.size - ).apply { + val accessor = cachesAbiSupport.getOuterThisAccessor(irClass) + context.llvmImports.add(irClass.llvmSymbolOrigin) + return irCall(expression.startOffset, expression.endOffset, accessor, emptyList()).apply { putValueArgument(0, expression.receiver) } } property?.isLateinit == true -> { - val accessor = lateinitPropertyAccessors.getOrPut(property) { - context.irFactory.buildFun { - name = InternalAbi.getLateinitPropertyFieldAccessorName(property) - returnType = field.type - origin = InternalAbi.INTERNAL_ABI_ORIGIN - isExternal = true - }.also { function -> - context.internalAbi.reference(function, property.module) - - if (irClass != null) - function.addValueParameter { - name = Name.identifier("owner") - origin = InternalAbi.INTERNAL_ABI_ORIGIN - type = irClass.defaultType - } - } - } - return IrCallImpl( - expression.startOffset, expression.endOffset, - expression.type, accessor.symbol, - accessor.typeParameters.size, accessor.valueParameters.size - ).apply { + val accessor = cachesAbiSupport.getLateinitPropertyAccessor(property) + context.llvmImports.add(property.llvmSymbolOrigin) + return irCall(expression.startOffset, expression.endOffset, accessor, emptyList()).apply { if (irClass != null) putValueArgument(0, expression.receiver) } @@ -221,17 +252,11 @@ internal class ImportCachesAbiTransformer(val context: Context) : IrElementTrans val enumClass = irClass?.parentClassOrNull require(enumClass != null) { "Unexpected usage of enum VALUES field" } require(enumClass.isEnumClass) { "Expected a enum class: ${enumClass.render()}" } - val accessor = enumValuesAccessors.getOrPut(enumClass) { - context.irFactory.buildFun { - name = InternalAbi.getEnumValuesAccessorName(enumClass) - returnType = context.ir.symbols.array.typeWith(enumClass.defaultType) - origin = InternalAbi.INTERNAL_ABI_ORIGIN - isExternal = true - }.also { - context.internalAbi.reference(it, enumClass.module) - } - } - return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size) + require(enumsSupport.getImplObject(enumClass) == irClass) { "Expected a enum's impl object: ${irClass.render()}" } + require(field == enumsSupport.getValuesField(irClass)) { "Expected VALUES field: ${field.render()}" } + val accessor = cachesAbiSupport.getEnumValuesAccessor(enumClass) + context.llvmImports.add(enumClass.llvmSymbolOrigin) + return irCall(expression.startOffset, expression.endOffset, accessor, emptyList()) } else -> expression diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FileInitializersLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FileInitializersLowering.kt index 771db1e9f4c..780a6e7e9db 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FileInitializersLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FileInitializersLowering.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENTRY_POINT import org.jetbrains.kotlin.backend.konan.KonanFqNames import org.jetbrains.kotlin.backend.konan.llvm.FieldStorageKind import org.jetbrains.kotlin.backend.konan.llvm.needsGCRegistration @@ -81,7 +82,7 @@ internal class FileInitializersLowering(val context: Context) : FileLoweringPass else null irFile.simpleFunctions() - .filterNot { it.isModuleInitializer } + .filterNot { it.isModuleInitializer || it.origin == DECLARATION_ORIGIN_ENTRY_POINT } .forEach { val body = it.body ?: return@forEach val statements = (body as IrBlockBody).statements