diff --git a/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Utils.kt b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Utils.kt index 7c59b6c054d..ab3dea147b9 100644 --- a/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Utils.kt +++ b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Utils.kt @@ -390,11 +390,29 @@ private class CString(val bytes: ByteArray): CValues() { } } +private object EmptyCString: CValues() { + override val size get() = 1 + override val align get() = 1 + + private val placement = + interpretCPointer(nativeMemUtils.alloc(1, 1).rawPtr)!!.also { + it[0] = 0.toByte() + } + + override fun getPointer(scope: AutofreeScope): CPointer { + return placement + } + override fun place(placement: CPointer): CPointer { + placement[0] = 0.toByte() + return placement + } +} + /** * @return the value of zero-terminated UTF-8-encoded C string constructed from given [kotlin.String]. */ public val String.cstr: CValues - get() = CString(encodeToUtf8(this)) + get() = if (isEmpty()) EmptyCString else CString(encodeToUtf8(this)) /** * @return the value of zero-terminated UTF-8-encoded C string constructed from given [kotlin.String]. 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 9d8cae222b5..919504184cf 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 @@ -40,6 +40,7 @@ import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyToWithoutSuperTypes import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager +import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl @@ -47,6 +48,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.konan.library.KonanLibraryLayout import org.jetbrains.kotlin.library.SerializedIrModule import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal +import org.jetbrains.kotlin.utils.addToStdlib.getOrPut /** * Offset for synthetic elements created by lowerings and not attributable to other places in the source code. @@ -254,10 +256,20 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { KonanReflectionTypes(moduleDescriptor, KonanFqNames.internalPackageName) } - val layoutBuilders = mutableMapOf() + // TODO: Remove after adding special property to IrDeclaration. + private val layoutBuilders = mutableMapOf() - fun getLayoutBuilder(irClass: IrClass) = layoutBuilders.getOrPut(irClass) { - ClassLayoutBuilder(irClass, this, isLowered = shouldLower(this, irClass)) + fun getLayoutBuilder(irClass: IrClass): ClassLayoutBuilder { + if (irClass is IrLazyClass) + return layoutBuilders.getOrPut(irClass) { + ClassLayoutBuilder(irClass, this, isLowered = shouldLower(this, irClass)) + } + val metadata = irClass.metadata as? CodegenClassMetadata + ?: CodegenClassMetadata(irClass).also { irClass.metadata = it } + metadata.layoutBuilder?.let { return it } + val layoutBuilder = ClassLayoutBuilder(irClass, this, isLowered = shouldLower(this, irClass)) + metadata.layoutBuilder = layoutBuilder + return layoutBuilder } lateinit var globalHierarchyAnalysisResult: GlobalHierarchyAnalysisResult diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LlvmModuleSpecificationImpl.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LlvmModuleSpecificationImpl.kt index 5e3ce5256ca..c17084ffb3c 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LlvmModuleSpecificationImpl.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LlvmModuleSpecificationImpl.kt @@ -5,11 +5,10 @@ package org.jetbrains.kotlin.backend.konan -import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary +import org.jetbrains.kotlin.backend.konan.ir.konanLibrary import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.util.module import org.jetbrains.kotlin.library.KotlinLibrary internal abstract class LlvmModuleSpecificationBase(protected val cachedLibraries: CachedLibraries) : LlvmModuleSpecification { @@ -26,7 +25,7 @@ internal abstract class LlvmModuleSpecificationBase(protected val cachedLibrarie module.konanLibrary.let { it == null || containsLibrary(it) } override fun containsDeclaration(declaration: IrDeclaration): Boolean = - declaration.module.konanLibrary.let { it == null || containsLibrary(it) } + declaration.konanLibrary.let { it == null || containsLibrary(it) } } internal class DefaultLlvmModuleSpecification(cachedLibraries: CachedLibraries) 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 b26382d6b73..0a158b1a33f 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 @@ -8,12 +8,11 @@ import org.jetbrains.kotlin.backend.common.serialization.mangle.ManglerChecker import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.Ir2DescriptorManglerAdapter import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary -import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary +import org.jetbrains.kotlin.backend.konan.ir.konanLibrary import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs +import org.jetbrains.kotlin.backend.konan.serialization.* import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker -import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc -import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -154,7 +153,7 @@ internal fun Context.psiToIr( } expectDescriptorToSymbol = mutableMapOf() - val module = translator.generateModuleFragment( + val mainModule = translator.generateModuleFragment( generatorContext, environment.getSourceFiles(), irProviders = listOf(irDeserializer), @@ -164,7 +163,7 @@ internal fun Context.psiToIr( // how ExpectedActualResolver is implemented. // Need to fix ExpectActualResolver to either cache expects or somehow reduce the member scope searches. expectDescriptorToSymbol = if (expectActualLinker) expectDescriptorToSymbol else null - ) + ).toKonanModule() irDeserializer.postProcess() @@ -173,7 +172,7 @@ internal fun Context.psiToIr( symbolTable.noUnboundLeft("Unbound symbols left after linker") - module.acceptVoid(ManglerChecker(KonanManglerIr, Ir2DescriptorManglerAdapter(KonanManglerDesc))) + mainModule.acceptVoid(ManglerChecker(KonanManglerIr, Ir2DescriptorManglerAdapter(KonanManglerDesc))) val modules = if (isProducingLibrary) emptyMap() else (irDeserializer as KonanIrLinker).modules @@ -182,7 +181,7 @@ internal fun Context.psiToIr( modules.values.forEach { fakeOverrideChecker.check(it) } } - irModule = module + irModule = mainModule // Note: coupled with [shouldLower] below. irModules = modules.filterValues { llvmModuleSpecification.containsModule(it) } @@ -196,6 +195,11 @@ internal fun Context.psiToIr( functionIrClassFactory.module = (modules.values + irModule!!).single { it.descriptor.isNativeStdlib() } } + mainModule.files.forEach { it.metadata = KonanFileMetadataSource(mainModule) } + modules.values.forEach { module -> + module.files.forEach { it.metadata = KonanFileMetadataSource(module as KonanIrModuleFragmentImpl) } + } + val originalBindingContext = bindingContext as? CleanableBindingContext ?: error("BindingContext should be cleanable in K/N IR to avoid leaking memory: $bindingContext") originalBindingContext.clear() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt index a39fefa269f..7c0c6563e02 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt @@ -8,7 +8,7 @@ import org.jetbrains.kotlin.backend.common.lower.at import org.jetbrains.kotlin.backend.common.lower.irNot import org.jetbrains.kotlin.backend.konan.PrimitiveBinaryType import org.jetbrains.kotlin.backend.konan.RuntimeNames -import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary +import org.jetbrains.kotlin.backend.konan.ir.konanLibrary import org.jetbrains.kotlin.backend.konan.getObjCMethodInfo import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation @@ -303,7 +303,7 @@ internal fun KotlinStubs.generateObjCCall( ) = builder.irBlock { val resolved = method.resolveFakeOverride(allowAbstract = true)?: method val exceptionMode = ForeignExceptionMode.byValue( - resolved.module.konanLibrary?.manifestProperties + resolved.konanLibrary?.manifestProperties ?.getProperty(ForeignExceptionMode.manifestKey) ) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt index 51b8249f9a9..7a9a2f33a92 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt @@ -10,8 +10,6 @@ import org.jetbrains.kotlin.backend.konan.RuntimeNames import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor -import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin -import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker @@ -156,5 +154,3 @@ internal val DeclarationDescriptor.isExpectMember: Boolean internal val DeclarationDescriptor.isSerializableExpectClass: Boolean get() = this is ClassDescriptor && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(this) - -val ModuleDescriptor.konanLibrary get() = (this.klibModuleOrigin as? DeserializedKlibModuleOrigin)?.library diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/NewIrUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/NewIrUtils.kt index 606317321b0..1706ff71686 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/NewIrUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/NewIrUtils.kt @@ -7,9 +7,17 @@ package org.jetbrains.kotlin.backend.konan.ir import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION +import org.jetbrains.kotlin.backend.konan.descriptors.isInteropLibrary +import org.jetbrains.kotlin.backend.konan.llvm.KonanMetadata +import org.jetbrains.kotlin.backend.konan.serialization.KonanFileMetadataSource +import org.jetbrains.kotlin.backend.konan.serialization.KonanIrModuleFragmentImpl import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyDeclarationBase import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrConst @@ -23,6 +31,7 @@ import org.jetbrains.kotlin.ir.types.IdSignatureValues import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.isMarkedNullable import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -101,3 +110,23 @@ fun buildSimpleAnnotation(irBuiltIns: IrBuiltIns, startOffset: Int, endOffset: I internal fun IrExpression.isBoxOrUnboxCall() = (this is IrCall && symbol.owner.origin == DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION) + +val ModuleDescriptor.konanLibrary get() = (this.klibModuleOrigin as? DeserializedKlibModuleOrigin)?.library +val IrModuleFragment.konanLibrary get() = + (this as? KonanIrModuleFragmentImpl)?.konanLibrary ?: descriptor.konanLibrary +val IrFile.konanLibrary get() = + (metadata as? KonanFileMetadataSource)?.module?.konanLibrary ?: packageFragmentDescriptor.containingDeclaration.konanLibrary +val IrDeclaration.konanLibrary: KotlinLibrary? get() { + ((this as? IrMetadataSourceOwner)?.metadata as? KonanMetadata)?.let { return it.konanLibrary } + val result = when (val parent = parent) { + is IrFile -> parent.konanLibrary + is IrPackageFragment -> parent.packageFragmentDescriptor.containingDeclaration.konanLibrary + is IrDeclaration -> parent.konanLibrary + else -> TODO("Unexpected declaration parent: $parent") + } + if (this is IrMetadataSourceOwner && this !is IrLazyDeclarationBase) + metadata = KonanMetadata(metadata?.name, result) + return result +} + +fun IrDeclaration.isFromInteropLibrary() = konanLibrary?.isInteropLibrary() == true diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index 15317a1c59c..394e29ff712 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -636,4 +636,4 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { val llvmVector128 = vector128Type } -class IrStaticInitializer(val module: ModuleDescriptor, val initializer: LLVMValueRef) +class IrStaticInitializer(val konanLibrary: KotlinLibrary?, val initializer: LLVMValueRef) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 0832299a239..b6eeb3a3cc5 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.llvm.coverage.LLVMCoverageInstrumentation +import org.jetbrains.kotlin.backend.konan.serialization.KonanIrModuleFragmentImpl import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -32,6 +33,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.konan.ForeignExceptionMode import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.classId @@ -323,7 +325,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map Unit) { + private fun runAndProcessInitializers(konanLibrary: KotlinLibrary?, f: () -> Unit) { // TODO: collect those two in one place. context.llvm.fileInitializers.clear() context.llvm.fileUsesThreadLocalObjects = false @@ -337,7 +339,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map, - private val classes: Map, - private val fields: Map, - private val staticFields: Map, - private val unique: Map) { +internal class LlvmDeclarations(private val unique: Map) { fun forFunction(function: IrFunction) = forFunctionOrNull(function) ?: with(function){error("$name in $file/${parent.fqNameForIrSerialization}")} - fun forFunctionOrNull(function: IrFunction) = functions[function] + fun forFunctionOrNull(function: IrFunction) = (function.metadata as? CodegenFunctionMetadata)?.llvm - fun forClass(irClass: IrClass) = classes[irClass] ?: + fun forClass(irClass: IrClass) = (irClass.metadata as? CodegenClassMetadata)?.llvm ?: error(irClass.descriptor.toString()) - fun forField(field: IrField) = fields[field] ?: + fun forField(field: IrField) = (field.metadata as? CodegenInstanceFieldMetadata)?.llvm ?: error(field.descriptor.toString()) - fun forStaticField(field: IrField) = staticFields[field] ?: + fun forStaticField(field: IrField) = (field.metadata as? CodegenStaticFieldMetadata)?.llvm ?: error(field.descriptor.toString()) fun forSingleton(irClass: IrClass) = forClass(irClass).singletonDeclarations ?: @@ -100,10 +92,6 @@ private fun ContextUtils.createClassBodyType(name: String, fields: List private class DeclarationsGeneratorVisitor(override val context: Context) : IrElementVisitorVoid, ContextUtils { - val functions = mutableMapOf() - val classes = mutableMapOf() - val fields = mutableMapOf() - val staticFields = mutableMapOf() val uniques = mutableMapOf() private class Namer(val prefix: String) { @@ -157,7 +145,10 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : override fun visitClass(declaration: IrClass) { if (declaration.requiresRtti()) { - this.classes[declaration] = createClassDeclarations(declaration) + val classLlvmDeclarations = createClassDeclarations(declaration) + val metadata = declaration.metadata as? CodegenClassMetadata + ?: CodegenClassMetadata(declaration).also { declaration.metadata = it } + metadata.llvm = classLlvmDeclarations } super.visitClass(declaration) } @@ -311,12 +302,16 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : val containingClass = declaration.parent as? IrClass if (containingClass != null) { if (!containingClass.requiresRtti()) return - val classDeclarations = this.classes[containingClass] ?: - error(containingClass.descriptor.toString()) + val classDeclarations = (containingClass.metadata as? CodegenClassMetadata)?.llvm + ?: error(containingClass.descriptor.toString()) val allFields = context.getLayoutBuilder(containingClass).fields - this.fields[declaration] = FieldLlvmDeclarations( - allFields.indexOf(declaration) + 1, // First field is ObjHeader. - classDeclarations.bodyType + declaration.metadata = CodegenInstanceFieldMetadata( + declaration.metadata?.name, + containingClass.konanLibrary, + FieldLlvmDeclarations( + allFields.indexOf(declaration) + 1, // First field is ObjHeader. + classDeclarations.bodyType + ) ) } else { // Fields are module-private, so we use internal name: @@ -327,7 +322,11 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : addKotlinGlobal(name, getLLVMType(declaration.type), isExported = false) } - this.staticFields[declaration] = StaticFieldLlvmDeclarations(storage) + declaration.metadata = CodegenStaticFieldMetadata( + declaration.metadata?.name, + declaration.konanLibrary, + StaticFieldLlvmDeclarations(storage) + ) } } @@ -346,7 +345,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : if (declaration.isTypedIntrinsic || declaration.isObjCBridgeBased() // All call-sites to external accessors to interop properties // are lowered by InteropLowering. - || (declaration.isAccessor && declaration.isFromMetadataInteropLibrary()) + || (declaration.isAccessor && declaration.isFromInteropLibrary()) || declaration.annotations.hasAnnotation(RuntimeNames.cCall)) return context.llvm.externalFunction(declaration.symbolName, llvmFunctionType, @@ -374,6 +373,36 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : function } - this.functions[declaration] = FunctionLlvmDeclarations(llvmFunction) + declaration.metadata = CodegenFunctionMetadata( + declaration.metadata?.name, + declaration.konanLibrary, + FunctionLlvmDeclarations(llvmFunction) + ) } } + +internal open class KonanMetadata(override val name: Name?, val konanLibrary: KotlinLibrary?) : MetadataSource + +internal class CodegenClassMetadata(irClass: IrClass) + : KonanMetadata(irClass.metadata?.name, irClass.konanLibrary), MetadataSource.Class { + var layoutBuilder: ClassLayoutBuilder? = null + var llvm: ClassLlvmDeclarations? = null +} + +private class CodegenFunctionMetadata( + name: Name?, + konanLibrary: KotlinLibrary?, + val llvm: FunctionLlvmDeclarations +) : KonanMetadata(name, konanLibrary), MetadataSource.Function + +private class CodegenInstanceFieldMetadata( + name: Name?, + konanLibrary: KotlinLibrary?, + val llvm: FieldLlvmDeclarations +) : KonanMetadata(name, konanLibrary), MetadataSource.Property + +private class CodegenStaticFieldMetadata( + name: Name?, + konanLibrary: KotlinLibrary?, + val llvm: StaticFieldLlvmDeclarations +) : KonanMetadata(name, konanLibrary), MetadataSource.Property \ No newline at end of file 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 be643ec4c34..a5bee8d2929 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 @@ -53,6 +53,10 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain private fun buildWorkerBridges(declaration: IrDeclaration): List { val bridges = mutableListOf() declaration.transformChildrenVoid(object: IrElementTransformerVoid() { + override fun visitClass(declaration: IrClass): IrStatement { + // Skip nested. + return declaration + } override fun visitCall(expression: IrCall): IrExpression { expression.transformChildrenVoid(this) @@ -133,20 +137,24 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass { override fun lower(irClass: IrClass) { val builtBridges = mutableSetOf() - irClass.simpleFunctions() - .forEach { function -> - function.allOverriddenFunctions - .map { OverriddenFunctionInfo(function, it) } - .filter { !it.bridgeDirections.allNotNeeded() } - .filter { it.canBeCalledVirtually } - .filter { !it.inheritsBridge } - .distinctBy { it.bridgeDirections } - .forEach { - buildBridge(it, irClass) - builtBridges += it.function - } + for (function in irClass.simpleFunctions()) { + val set = mutableSetOf() + for (overriddenFunction in function.allOverriddenFunctions) { + val overriddenFunctionInfo = OverriddenFunctionInfo(function, overriddenFunction) + val bridgeDirections = overriddenFunctionInfo.bridgeDirections + if (!bridgeDirections.allNotNeeded() && overriddenFunctionInfo.canBeCalledVirtually + && !overriddenFunctionInfo.inheritsBridge && set.add(bridgeDirections)) { + buildBridge(overriddenFunctionInfo, irClass) + builtBridges += function } + } + } irClass.transformChildrenVoid(object: IrElementTransformerVoid() { + override fun visitClass(declaration: IrClass): IrStatement { + // Skip nested. + return declaration + } + override fun visitFunction(declaration: IrFunction): IrStatement { declaration.transformChildrenVoid(this) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt index ad89024f187..21f6779a58c 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl @@ -124,19 +125,25 @@ internal class EnumUsageLowering(val context: Context) } } -internal class EnumClassLowering(val context: Context) : ClassLoweringPass { +internal class EnumClassLowering(val context: Context) : FileLoweringPass { fun run(irFile: IrFile) { // EnumWhenLowering should be performed before EnumUsageLowering because // the latter performs lowering of IrGetEnumValue EnumWhenLowering(context).lower(irFile) - runOnFilePostfix(irFile) + lower(irFile) EnumUsageLowering(context).lower(irFile) } - override fun lower(irClass: IrClass) { - if (irClass.kind != ClassKind.ENUM_CLASS) return - EnumClassTransformer(irClass).run() + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitClass(declaration: IrClass): IrStatement { + declaration.transformChildrenVoid() + if (declaration.kind == ClassKind.ENUM_CLASS) + EnumClassTransformer(declaration).run() + return declaration + } + }) } private inner class EnumClassTransformer(val irClass: IrClass) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt index ff1022f50d5..9af0994cdee 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.lower.callsSuper import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -87,6 +88,11 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { private fun lowerOuterThisReferences() { irClass.transformChildrenVoid(object : IrElementTransformerVoidWithContext() { + override fun visitClassNew(declaration: IrClass): IrStatement { + // Skip nested. + return declaration + } + override fun visitGetValue(expression: IrGetValue): IrExpression { expression.transformChildrenVoid(this) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt index 062f8353be9..791d47dee94 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt @@ -14,8 +14,6 @@ import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.cgen.* import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions -import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary -import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.ir.companionObject @@ -811,7 +809,7 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi private fun tryGenerateInteropConstantRead(expression: IrCall): IrExpression? { val function = expression.symbol.owner - if (!function.descriptor.module.isFromInteropLibrary()) return null + if (!function.isFromInteropLibrary()) return null if (!function.isGetter) return null val constantProperty = (function as? IrSimpleFunction) @@ -870,7 +868,7 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi if (function.annotations.hasAnnotation(RuntimeNames.cCall)) { context.llvmImports.add(function.llvmSymbolOrigin) val exceptionMode = ForeignExceptionMode.byValue( - function.module.konanLibrary?.manifestProperties?.getProperty(ForeignExceptionMode.manifestKey) + function.konanLibrary?.manifestProperties?.getProperty(ForeignExceptionMode.manifestKey) ) return generateWithStubs { generateCCall(expression, builder, isInvoke = false, exceptionMode) } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt index 0652aea9149..98d96ad83a3 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.backend.konan.KonanBackendContext import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* @@ -61,6 +62,11 @@ internal class VarargInjectionLowering constructor(val context: KonanBackendCont private fun lower(owner: IrSymbol, element: IrElement?) { element?.transformChildrenVoid(object: IrElementTransformerVoid() { + override fun visitClass(declaration: IrClass): IrStatement { + // Skip nested. + return declaration + } + val transformer = this private fun replaceEmptyParameterWithEmptyArray(expression: IrFunctionAccessExpression) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt index 803dce00605..2c6676b3da1 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt @@ -24,22 +24,24 @@ import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolD import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer import org.jetbrains.kotlin.backend.konan.CachedLibraries import org.jetbrains.kotlin.backend.konan.descriptors.isInteropLibrary -import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs +import org.jetbrains.kotlin.backend.konan.ir.konanLibrary import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib +import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary import org.jetbrains.kotlin.ir.builders.TranslationPluginContext import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrPublicSymbolBase import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.library.IrLibrary import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.name.ClassId @@ -107,8 +109,13 @@ internal class KonanIrLinker( return KonanModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy) } - private inner class KonanModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy): - KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy) + private inner class KonanModuleDeserializer( + moduleDescriptor: ModuleDescriptor, + klib: IrLibrary, + strategy: DeserializationStrategy + ): KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy) { + override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns, emptyList()) + } private inner class KonanInteropModuleDeserializer( moduleDescriptor: ModuleDescriptor, @@ -160,7 +167,7 @@ internal class KonanIrLinker( return symbolOwner.symbol } - override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns) + override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns) override val moduleDependencies: Collection = listOfNotNull(forwardDeclarationDeserializer) } @@ -208,7 +215,7 @@ internal class KonanIrLinker( return declaredDeclaration.getOrPut(idSig) { buildForwardDeclarationStub(descriptor) }.symbol } - override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns) + override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns) override val moduleDependencies: Collection = emptyList() } @@ -226,3 +233,34 @@ internal class KonanIrLinker( override val irBuiltIns: IrBuiltIns ):TranslationPluginContext } + +class KonanIrModuleFragmentImpl( + override val descriptor: ModuleDescriptor, + override val irBuiltins: IrBuiltIns, + files: List = emptyList(), +) : IrModuleFragment() { + override val name: Name get() = descriptor.name // TODO + + override val files: MutableList = files.toMutableList() + + val konanLibrary = (descriptor.klibModuleOrigin as? DeserializedKlibModuleOrigin)?.library + + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitModuleFragment(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + files.forEach { it.accept(visitor, data) } + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + files.forEachIndexed { i, irFile -> + files[i] = irFile.transform(transformer, data) + } + } +} + +fun IrModuleFragment.toKonanModule() = KonanIrModuleFragmentImpl(descriptor, irBuiltins, files) + +class KonanFileMetadataSource(val module: KonanIrModuleFragmentImpl) : MetadataSource.File { + override val name: Name? = null +} \ No newline at end of file