From 735013cc428eb5b699e408748c7b610f17d2e9dd Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Wed, 29 Jan 2020 17:35:43 +0300 Subject: [PATCH] Fix K/N for new linker (cherry picked from commit ea31937c010da2e0d3a1fb5d8b49625ffc31115e) --- .../jetbrains/kotlin/backend/konan/Context.kt | 2 +- .../kotlin/backend/konan/ObjCInterop.kt | 12 ++ .../kotlin/backend/konan/ToplevelPhases.kt | 19 ++- .../konan/descriptors/DescriptorUtils.kt | 8 + .../IrProviderForCEnumAndCStructStubs.kt | 3 +- .../ir/interop/IrProviderForInteropStubs.kt | 3 +- .../backend/konan/llvm/BinaryInterface.kt | 154 ++++++------------ .../backend/konan/optimizations/DataFlowIR.kt | 1 - .../serialization/KonanDeclarationTable.kt | 5 +- .../KonanDeserializeDescriptorReference.kt | 15 -- .../konan/serialization/KonanIdSignaturer.kt | 8 + .../serialization/KonanIrModuleSerializer.kt | 34 +--- .../konan/serialization/KonanIrlinker.kt | 95 ++++++++--- .../konan/serialization/KonanMangler.kt | 148 +++++++++++++++++ .../main/kotlin/org/jetbrains/build/Build.kt | 75 --------- 15 files changed, 323 insertions(+), 259 deletions(-) delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeserializeDescriptorReference.kt create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIdSignaturer.kt create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMangler.kt delete mode 100644 tools/performance-server/shared/src/main/kotlin/org/jetbrains/build/Build.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index 286b14e361b..3a3ec87c7d1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -58,7 +58,7 @@ import org.jetbrains.kotlin.library.SerializedIrModule * Offset for synthetic elements created by lowerings and not attributable to other places in the source code. */ -internal class SpecialDeclarationsFactory(val context: Context) : KotlinMangler by KonanManglerForBE { +internal class SpecialDeclarationsFactory(val context: Context) { private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) } private val outerThisFields = mutableMapOf() private val bridgesDescriptors = mutableMapOf, IrSimpleFunction>() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt index 3bab6a5bb71..40fca960114 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt @@ -259,6 +259,7 @@ fun ConstructorDescriptor.objCConstructorIsDesignated(): Boolean { val IrConstructor.isObjCConstructor get() = this.annotations.hasAnnotation(objCConstructorFqName) +val ConstructorDescriptor.isObjCConstructor get() = this.annotations.hasAnnotation(objCConstructorFqName) // TODO-DCE-OBJC-INIT: Selector should be preserved by DCE. fun IrConstructor.getObjCInitMethod(): IrSimpleFunction? { @@ -270,9 +271,20 @@ fun IrConstructor.getObjCInitMethod(): IrSimpleFunction? { } } +fun ConstructorDescriptor.getObjCInitMethod(): FunctionDescriptor? { + return this.annotations.findAnnotation(objCConstructorFqName)?.let { + val initSelector = it.getAnnotationStringValue("initSelector") + this.constructedClass.unsubstitutedMemberScope.getContributedDescriptors().asSequence() + .filterIsInstance() + .single { it.getExternalObjCMethodInfo()?.selector == initSelector } + } +} + val IrFunction.hasObjCFactoryAnnotation get() = this.annotations.hasAnnotation(objCFactoryFqName) +val FunctionDescriptor.hasObjCFactoryAnnotation get() = this.annotations.hasAnnotation(objCFactoryFqName) val IrFunction.hasObjCMethodAnnotation get() = this.annotations.hasAnnotation(objCMethodFqName) +val FunctionDescriptor.hasObjCMethodAnnotation get() = this.annotations.hasAnnotation(objCMethodFqName) fun FunctionDescriptor.getObjCFactoryInitMethodInfo(): ObjCMethodInfo? { val factoryAnnotation = this.annotations.findAnnotation(objCFactoryFqName) ?: return null diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index 38bae7c34c9..aadb7ee2588 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -4,7 +4,8 @@ import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.phaser.* -import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable +import org.jetbrains.kotlin.backend.common.serialization.mangle.ManglerChecker +import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.Ir2DescriptorManglerAdapter import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary @@ -29,6 +30,7 @@ import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.addChild import org.jetbrains.kotlin.ir.util.addFile import org.jetbrains.kotlin.ir.util.file +import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator @@ -107,7 +109,7 @@ private var Context.symbolTable: SymbolTable? by Context.nullValue() internal val createSymbolTablePhase = konanUnitPhase( op = { - this.symbolTable = SymbolTable() + this.symbolTable = SymbolTable(KonanIdSignaturer(KonanManglerDesc)) }, name = "CreateSymbolTable", description = "Create SymbolTable" @@ -143,7 +145,7 @@ internal val psiToIrPhase = konanUnitPhase( val symbolTable = symbolTable!! val translator = Psi2IrTranslator(config.configuration.languageVersionSettings, - Psi2IrConfiguration(false)) + Psi2IrConfiguration(false), KonanIdSignaturer(KonanManglerDesc)) val generatorContext = translator.createGeneratorContext(moduleDescriptor, bindingContext, symbolTable) translator.addPostprocessingStep { module -> @@ -240,6 +242,12 @@ internal val psiToIrPhase = konanUnitPhase( if (this.stdlibModule in modulesWithoutDCE) { functionIrClassFactory.buildAllClasses() } + modulesWithoutDCE + .filter(ModuleDescriptor::isFromInteropLibrary) + .forEach(irProviderForCEnumsAndCStructs::buildAllEnumsAndStructsFrom) + + module.acceptVoid(ManglerChecker(KonanManglerIr, Ir2DescriptorManglerAdapter(KonanManglerDesc))) + irModule = module irModules = deserializer.modules.filterValues { llvmModuleSpecification.containsModule(it) } ir.symbols = symbols @@ -279,18 +287,17 @@ internal val copyDefaultValuesToActualPhase = konanUnitPhase( internal val serializerPhase = konanUnitPhase( op = { val mppKlibs = config.configuration.get(CommonConfigurationKeys.KLIB_MPP)?:false - val descriptorTable = DescriptorTable.createDefault() serializedIr = irModule?.let { ir -> KonanIrModuleSerializer( - this, ir.irBuiltins, descriptorTable, expectDescriptorToSymbol, skipExpects = !mppKlibs + this, ir.irBuiltins, expectDescriptorToSymbol, skipExpects = !mppKlibs ).serializedIrModule(ir) } val serializer = KlibMetadataMonolithicSerializer( this.config.configuration.languageVersionSettings, config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!, - descriptorTable, !mppKlibs) + !mppKlibs) serializedMetadata = serializer.serializeModule(moduleDescriptor) }, name = "Serializer", diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index 9911eefd0c4..7cbedd16b2f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.isObjCClass import org.jetbrains.kotlin.backend.konan.llvm.longName import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.IrConst @@ -20,6 +21,9 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.resolve.annotations.argumentValue +import org.jetbrains.kotlin.resolve.constants.StringValue +import org.jetbrains.kotlin.utils.addToStdlib.safeAs /** * List of all implemented interfaces (including those which implemented by a super class) @@ -267,6 +271,10 @@ fun IrConstructorCall.getAnnotationStringValue(name: String): String { return (getValueArgument(parameter.index) as IrConst).value } +fun AnnotationDescriptor.getAnnotationStringValue(name: String): String { + return argumentValue(name)?.safeAs()?.value ?: error("Expected value $name at annotation $this") +} + fun IrConstructorCall.getAnnotationValueOrNull(name: String): T? { val parameter = symbol.owner.valueParameters.atMostOne { it.name.asString() == name } return parameter?.let { getValueArgument(it.index)?.let { (it as IrConst).value } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForCEnumAndCStructStubs.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForCEnumAndCStructStubs.kt index ad49a5314c1..33ee4817532 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForCEnumAndCStructStubs.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForCEnumAndCStructStubs.kt @@ -71,7 +71,8 @@ internal class IrProviderForCEnumAndCStructStubs( } fun canHandleSymbol(symbol: IrSymbol): Boolean { - if (!symbol.descriptor.module.isFromInteropLibrary()) return false + if (!symbol.isPublicApi) return false + if (symbol.signature.run { !IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.test() }) return false return symbol.findCEnumDescriptor(interopBuiltIns) != null || symbol.findCStructDescriptor(interopBuiltIns) != null } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForInteropStubs.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForInteropStubs.kt index 65101baa3d3..af45de1213c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForInteropStubs.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForInteropStubs.kt @@ -33,7 +33,8 @@ class IrProviderForInteropStubs( // So for now we relate on correct behavior of subsequent providers. symbol.isBound -> null isSpecialInteropCase(symbol) -> null - symbol.descriptor.module.isFromInteropLibrary() -> provideIrDeclaration(symbol) + symbol.isPublicApi && symbol.signature.run { IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.test() } -> + provideIrDeclaration(symbol) else -> null } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt index 912f4836f68..a1aad3cc151 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt @@ -6,21 +6,21 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.LLVMTypeRef -import org.jetbrains.kotlin.backend.common.serialization.KotlinManglerImpl -import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleConstant +import org.jetbrains.kotlin.backend.common.serialization.mangle.SpecialDeclarationType +import org.jetbrains.kotlin.backend.konan.RuntimeNames import org.jetbrains.kotlin.backend.konan.descriptors.externalSymbolOrThrow import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationStringValue import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract import org.jetbrains.kotlin.backend.konan.ir.allParameters -import org.jetbrains.kotlin.backend.konan.getObjCMethodInfo -import org.jetbrains.kotlin.backend.konan.isObjCClassMethod import org.jetbrains.kotlin.backend.konan.ir.isUnit -import org.jetbrains.kotlin.backend.konan.llvm.KonanMangler.isExported +import org.jetbrains.kotlin.backend.konan.isExternalObjCClass +import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.types.getClass -import org.jetbrains.kotlin.backend.konan.isInlinedNative -import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.findAnnotation +import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization +import org.jetbrains.kotlin.ir.util.isSuspend +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.library.uniqueName @@ -29,106 +29,52 @@ import org.jetbrains.kotlin.library.uniqueName // TODO: revise the naming scheme to ensure it produces unique names. // TODO: do not serialize descriptors of non-exported declarations. -abstract class AbstractKonanMangler : KotlinManglerImpl() { +object KonanBinaryInterface { + private val mangler = KonanManglerIr + private val exportChecker = mangler.getExportChecker() - override val IrType.isInlined - get() = this.isInlinedNative() + val IrFunction.functionName: String get() = mangler.run { signatureString } - /** - * Defines whether the declaration is exported, i.e. visible from other modules. - * - * Exported declarations must have predictable and stable ABI - * that doesn't depend on any internal transformations (e.g. IR lowering), - * and so should be computable from the descriptor itself without checking a backend state. - */ - override fun IrDeclaration.isPlatformSpecificExported(): Boolean { - // TODO: revise - if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) { - // Treat any `@SymbolName` declaration as exported. - return true - } - if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) { - // Treat any `@ExportForCppRuntime` declaration as exported. - return true - } - if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) { - // Treat `@CName` declaration as exported. - return true - } - if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) { - return true - } - - return false + val IrFunction.symbolName: String get() = funSymbolNameImpl() + val IrField.symbolName: String get() = + withPrefix(MangleConstant.FIELD_PREFIX, fieldSymbolNameImpl()) + val IrClass.typeInfoSymbolName: String get() = + withPrefix(MangleConstant.CLASS_PREFIX, typeInfoSymbolNameImpl()) + fun isExported(declaration: IrDeclaration) = exportChecker.run { + check(declaration, SpecialDeclarationType.REGULAR) || declaration.isPlatformSpecificExported() } - override fun IrFunction.valueParamsPart(typeParameterNamer: (IrTypeParameter) -> String): String { - return this.valueParameters.map { + private fun withPrefix(prefix: String, mangle: String) = "$prefix:$mangle" - // TODO: there are clashes originating from ObjectiveC interop. - // kotlinx.cinterop.ObjCClassOf.create(format: kotlin.String): T defined in platform.Foundation in file Foundation.kt - // and - // kotlinx.cinterop.ObjCClassOf.create(string: kotlin.String): T defined in platform.Foundation in file Foundation.kt + private fun IrFunction.funSymbolNameImpl(): String { + if (!isExported(this)) { + throw AssertionError(render()) + } - val argName = - if (this.hasObjCMethodAnnotation || this.hasObjCFactoryAnnotation || this.isObjCClassMethod()) "${it.name}:" else "" - "$argName${typeToHashString(it.type, typeParameterNamer)}${if (it.isVararg) "_VarArg" else ""}" - }.joinToString(";") + if (isExternal) { + this.externalSymbolOrThrow()?.let { + return it + } + } + + this.annotations.findAnnotation(RuntimeNames.exportForCppRuntime)?.let { + val name = it.getAnnotationStringValue() ?: this.name.asString() + return name // no wrapping currently required + } + + return withPrefix(MangleConstant.FUN_PREFIX, mangler.run { mangleString }) } - override val IrFunction.platformSpecificFunctionName: String? - get() { - (if (this is IrConstructor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo() - ?.let { - return buildString { - if (extensionReceiverParameter != null) { - append(extensionReceiverParameter!!.type.getClass()!!.name) - append(".") - } - - append("objc:") - append(it.selector) - if (this@platformSpecificFunctionName is IrConstructor && this@platformSpecificFunctionName.isObjCConstructor) append("#Constructor") - - if ((this@platformSpecificFunctionName as? IrSimpleFunction)?.correspondingPropertySymbol != null) { - append("#Accessor") - } - } - } - return null + private fun IrField.fieldSymbolNameImpl(): String { + val containingDeclarationPart = parent.fqNameForIrSerialization.let { + if (it.isRoot) "" else "$it." } + return "$containingDeclarationPart$name" + } - internal val IrFunction.symbolName: String - get() { - if (!this.isExported()) { - throw AssertionError(this.descriptor.toString()) - } - - if (isExternal) { - this.externalSymbolOrThrow()?.let { - return it - } - } - - this.annotations.findAnnotation(RuntimeNames.exportForCppRuntime)?.let { - val name = it.getAnnotationStringValue() ?: this.name.asString() - return name // no wrapping currently required - } - - val parent = this.parent - - val containingDeclarationPart = parent.fqNameForIrSerialization.let { - if (it.isRoot) "" else "$it." - } - return "kfun:$containingDeclarationPart$functionName" - } -} - -object KonanMangler : AbstractKonanMangler() - -object KonanManglerForBE : AbstractKonanMangler() { - override fun mangleTypeParameter(typeParameter: IrTypeParameter, typeParameterNamer: (IrTypeParameter) -> String): String = - typeParameter.name.asString() + private fun IrClass.typeInfoSymbolNameImpl(): String { + return this.fqNameForIrSerialization.toString() + } } internal val IrClass.writableTypeInfoSymbolName: String @@ -146,15 +92,15 @@ internal val IrClass.objectInstanceGetterSymbolName: String return "kobjget:$fqNameForIrSerialization" } -val IrFunction.functionName get() = with(KonanManglerForBE) { functionName } +val IrFunction.functionName get() = with(KonanBinaryInterface) { functionName } -val IrFunction.symbolName get() = with(KonanManglerForBE) { symbolName } +val IrFunction.symbolName get() = with(KonanBinaryInterface) { symbolName } -val IrField.symbolName get() = with(KonanManglerForBE) { symbolName } +val IrField.symbolName get() = with(KonanBinaryInterface) { symbolName } -val IrClass.typeInfoSymbolName get() = with(KonanManglerForBE) { typeInfoSymbolName } +val IrClass.typeInfoSymbolName get() = with(KonanBinaryInterface) { typeInfoSymbolName } -fun IrDeclaration.isExported() = with(KonanManglerForBE) { isExported() } +fun IrDeclaration.isExported() = KonanBinaryInterface.isExported(this) // TODO: bring here dependencies of this method? internal fun RuntimeAware.getLlvmFunctionType(function: IrFunction): LLVMTypeRef { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt index 22afb1feb93..448a6e488ce 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt @@ -11,7 +11,6 @@ import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract import org.jetbrains.kotlin.backend.konan.descriptors.target import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.llvm.* -import org.jetbrains.kotlin.backend.konan.llvm.KonanMangler.symbolName import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget import org.jetbrains.kotlin.descriptors.Modality diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeclarationTable.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeclarationTable.kt index 49a308a04ac..5a06de3a5a4 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeclarationTable.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeclarationTable.kt @@ -1,12 +1,11 @@ package org.jetbrains.kotlin.backend.konan.serialization -import org.jetbrains.kotlin.backend.konan.llvm.* - import org.jetbrains.kotlin.backend.common.serialization.GlobalDeclarationTable +import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns -class KonanGlobalDeclarationTable(builtIns: IrBuiltIns) : GlobalDeclarationTable(KonanMangler) { +class KonanGlobalDeclarationTable(signatureSerializer: IdSignatureSerializer, builtIns: IrBuiltIns) : GlobalDeclarationTable(signatureSerializer, KonanManglerIr) { init { loadKnownBuiltins(builtIns) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeserializeDescriptorReference.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeserializeDescriptorReference.kt deleted file mode 100644 index 5b765571a0a..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeserializeDescriptorReference.kt +++ /dev/null @@ -1,15 +0,0 @@ -package org.jetbrains.kotlin.backend.konan.serialization - -import org.jetbrains.kotlin.backend.common.serialization.* -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns -import org.jetbrains.kotlin.ir.util.KotlinMangler -import org.jetbrains.kotlin.ir.util.UniqId - -class KonanDescriptorReferenceDeserializer( - currentModule: ModuleDescriptor, - mangler: KotlinMangler, - builtIns: IrBuiltIns, - resolvedForwardDeclarations: MutableMap -): DescriptorReferenceDeserializer(currentModule, mangler, builtIns, resolvedForwardDeclarations), - DescriptorUniqIdAware by DeserializedDescriptorUniqIdAware diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIdSignaturer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIdSignaturer.kt new file mode 100644 index 00000000000..26ff9f8826b --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIdSignaturer.kt @@ -0,0 +1,8 @@ +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor +import org.jetbrains.kotlin.ir.util.KotlinMangler + +class KonanIdSignaturer(mangler: KotlinMangler.DescriptorMangler) : IdSignatureDescriptor(mangler) { + +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleSerializer.kt index 01267f553e5..fd73b981ca4 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleSerializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleSerializer.kt @@ -1,49 +1,23 @@ package org.jetbrains.kotlin.backend.konan.serialization import org.jetbrains.kotlin.backend.common.LoggingContext -import org.jetbrains.kotlin.backend.common.descriptors.propertyIfAccessor import org.jetbrains.kotlin.backend.common.serialization.* -import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary +import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.util.UniqId -import org.jetbrains.kotlin.resolve.descriptorUtil.module - -private class KonanDeclarationTable( - descriptorTable: DescriptorTable, - globalDeclarationTable: GlobalDeclarationTable, - startIndex: Long -) : DeclarationTable(descriptorTable, globalDeclarationTable, startIndex), - DescriptorUniqIdAware by DeserializedDescriptorUniqIdAware { - - /** - * It is incorrect to compute UniqId for declarations from metadata-based libraries. - * Instead we should get precomputed value from metadata. - */ - override fun tryComputeBackendSpecificUniqId(declaration: IrDeclaration): UniqId? { - return if (declaration.descriptor.module.isFromInteropLibrary()) { - // Property accessor doesn't provide UniqId so we need to get it from the property itself. - UniqId(declaration.descriptor.propertyIfAccessor.getUniqId() ?: error("No uniq id found for ${declaration.descriptor}")) - } else { - null - } - } -} class KonanIrModuleSerializer( logger: LoggingContext, irBuiltIns: IrBuiltIns, - private val descriptorTable: DescriptorTable, private val expectDescriptorToSymbol: MutableMap, val skipExpects: Boolean ) : IrModuleSerializer(logger) { - - private val globalDeclarationTable = KonanGlobalDeclarationTable(irBuiltIns) + private val signaturer = IdSignatureSerializer(KonanManglerIr) + private val globalDeclarationTable = KonanGlobalDeclarationTable(signaturer, irBuiltIns) override fun createSerializerForFile(file: IrFile): KonanIrFileSerializer = - KonanIrFileSerializer(logger, KonanDeclarationTable(descriptorTable, globalDeclarationTable, 0), expectDescriptorToSymbol, skipExpects = skipExpects) + KonanIrFileSerializer(logger, DeclarationTable(globalDeclarationTable), expectDescriptorToSymbol, skipExpects = skipExpects) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt index 0b9ed856f52..527a29014f5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt @@ -20,38 +20,43 @@ import org.jetbrains.kotlin.backend.common.LoggingContext import org.jetbrains.kotlin.backend.common.serialization.* import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary -import org.jetbrains.kotlin.backend.konan.llvm.KonanMangler +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl import org.jetbrains.kotlin.ir.util.SymbolTable -import org.jetbrains.kotlin.ir.util.UniqId - -import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe class KonanIrLinker( - currentModule: ModuleDescriptor, + private val currentModule: ModuleDescriptor, logger: LoggingContext, builtIns: IrBuiltIns, symbolTable: SymbolTable, - forwardModuleDescriptor: ModuleDescriptor?, + private val forwardModuleDescriptor: ModuleDescriptor?, exportedDependencies: List -) : KotlinIrLinker(logger, builtIns, symbolTable, exportedDependencies, forwardModuleDescriptor, KonanMangler), - DescriptorUniqIdAware by DeserializedDescriptorUniqIdAware { +) : KotlinIrLinker(logger, builtIns, symbolTable, exportedDependencies, forwardModuleDescriptor) { - override val descriptorReferenceDeserializer = - KonanDescriptorReferenceDeserializer(currentModule, KonanMangler, builtIns, resolvedForwardDeclarations) - - override fun reader(moduleDescriptor: ModuleDescriptor, fileIndex: Int, uniqId: UniqId) = - moduleDescriptor.konanLibrary!!.irDeclaration(uniqId.index, fileIndex) - - override fun readSymbol(moduleDescriptor: ModuleDescriptor, fileIndex: Int, symbolIndex: Int) = - moduleDescriptor.konanLibrary!!.symbol(symbolIndex, fileIndex) + override fun reader(moduleDescriptor: ModuleDescriptor, fileIndex: Int, idSigIndex: Int) = + moduleDescriptor.konanLibrary!!.irDeclaration(idSigIndex, fileIndex) override fun readType(moduleDescriptor: ModuleDescriptor, fileIndex: Int, typeIndex: Int) = moduleDescriptor.konanLibrary!!.type(typeIndex, fileIndex) + override fun readSignature(moduleDescriptor: ModuleDescriptor, fileIndex: Int, signatureIndex: Int) = + moduleDescriptor.konanLibrary!!.signature(signatureIndex, fileIndex) + override fun readString(moduleDescriptor: ModuleDescriptor, fileIndex: Int, stringIndex: Int) = moduleDescriptor.konanLibrary!!.string(stringIndex, fileIndex) @@ -62,19 +67,65 @@ class KonanIrLinker( moduleDescriptor.konanLibrary!!.file(fileIndex) override fun readFileCount(moduleDescriptor: ModuleDescriptor) = - moduleDescriptor.run { if (isForwardDeclarationModule || !shouldBeDeserialized()) 0 else konanLibrary!!.fileCount() } + moduleDescriptor.run { if (this === forwardModuleDescriptor || moduleDescriptor.isFromInteropLibrary()) 0 else konanLibrary!!.fileCount() } - private val ModuleDescriptor.userName get() = konanLibrary!!.libraryFile.absolutePath - - override fun handleNoModuleDeserializerFound(key: UniqId): DeserializationState<*> { + override fun handleNoModuleDeserializerFound(idSignature: IdSignature): DeserializationState<*> { return globalDeserializationState } + companion object { + private val C_NAMES_NAME = Name.identifier("cnames") + private val OBJC_NAMES_NAME = Name.identifier("objcnames") + } + + override fun isSpecialPlatformSignature(idSig: IdSignature): Boolean = idSig.isForwardDeclarationSignature() + + override fun postProcessPlatformSpecificDeclaration(idSig: IdSignature, descriptor: DeclarationDescriptor?, block: (IdSignature) -> Unit) { + if (descriptor == null) return + + if (!idSig.isForwardDeclarationSignature()) return + + val fqn = descriptor.fqNameSafe + if (!fqn.startsWith(C_NAMES_NAME) && !fqn.startsWith(OBJC_NAMES_NAME)) { + val signature = IdSignature.PublicSignature(fqn.parent(), FqName(fqn.shortName().asString()), null, 0) + block(signature) + } + } + + override fun resolvePlatformDescriptor(idSig: IdSignature): DeclarationDescriptor? { + if (!idSig.isForwardDeclarationSignature()) return null + + val fwdModule = forwardModuleDescriptor ?: error("Forward declaration module should not be null") + + return with(idSig as IdSignature.PublicSignature) { + val classId = ClassId(packageFqn, classFqn, false) + fwdModule.findClassAcrossModuleDependencies(classId) + } + } + + private fun IdSignature.isInteropSignature(): Boolean = IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.test() + + private fun IdSignature.isForwardDeclarationSignature(): Boolean { + if (isPublic) { + return packageFqName().run { + startsWith(C_NAMES_NAME) || startsWith(OBJC_NAMES_NAME) + } + } + + return false + } + + override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy): IrModuleDeserializer { + return KonanModuleDeserializer(moduleDescriptor, strategy) + } + + private inner class KonanModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy): + IrModuleDeserializer(moduleDescriptor, strategy) + /** * If declaration is from interop library then IR for it is generated by IrProviderForInteropStubs. */ - override fun DeclarationDescriptor.shouldBeDeserialized(): Boolean = - !module.isFromInteropLibrary() + override fun IdSignature.shouldBeDeserialized(): Boolean = !isInteropSignature() && !isForwardDeclarationSignature() val modules: Map get() = mutableMapOf().apply { deserializersForModules.filter { !it.key.isForwardDeclarationModule }.forEach { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMangler.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMangler.kt new file mode 100644 index 00000000000..adb3f0045bb --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMangler.kt @@ -0,0 +1,148 @@ +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode +import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorBasedKotlinManglerImpl +import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorExportCheckerVisitor +import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorMangleComputer +import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrBasedKotlinManglerImpl +import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrExportCheckerVisitor +import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrMangleComputer +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.util.hasAnnotation + +abstract class AbstractKonanIrMangler : IrBasedKotlinManglerImpl() { + override fun getExportChecker(): IrExportCheckerVisitor = KonanIrExportChecker() + + override fun getMangleComputer(mode: MangleMode): IrMangleComputer = KonanIrManglerComputer(StringBuilder(256), mode) + + private class KonanIrExportChecker : IrExportCheckerVisitor() { + override fun IrDeclaration.isPlatformSpecificExported(): Boolean { + if (this is IrSimpleFunction) if (isFakeOverride) return false + + // TODO: revise + if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) { + // Treat any `@SymbolName` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) { + // Treat any `@ExportForCppRuntime` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) { + // Treat `@CName` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) { + return true + } + + return false + } + + } + + private class KonanIrManglerComputer(builder: StringBuilder, mode: MangleMode) : IrMangleComputer(builder, mode) { + override fun copy(newMode: MangleMode): IrMangleComputer = KonanIrManglerComputer(builder, newMode) + + override fun IrFunction.platformSpecificFunctionName(): String? { + (if (this is IrConstructor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo() + ?.let { + return buildString { + if (extensionReceiverParameter != null) { + append(extensionReceiverParameter!!.type.getClass()!!.name) + append(".") + } + + append("objc:") + append(it.selector) + if (this@platformSpecificFunctionName is IrConstructor && this@platformSpecificFunctionName.isObjCConstructor) append("#Constructor") + + if ((this@platformSpecificFunctionName as? IrSimpleFunction)?.correspondingPropertySymbol != null) { + append("#Accessor") + } + } + } + return null + } + + override fun IrFunction.specialValueParamPrefix(param: IrValueParameter): String { + // TODO: there are clashes originating from ObjectiveC interop. + // kotlinx.cinterop.ObjCClassOf.create(format: kotlin.String): T defined in platform.Foundation in file Foundation.kt + // and + // kotlinx.cinterop.ObjCClassOf.create(string: kotlin.String): T defined in platform.Foundation in file Foundation.kt + + return if (this.hasObjCMethodAnnotation || this.hasObjCFactoryAnnotation || this.isObjCClassMethod()) "${param.name}:" else "" + } + + + } +} + +object KonanManglerIr : AbstractKonanIrMangler() + +abstract class AbstractKonanDescriptorMangler : DescriptorBasedKotlinManglerImpl() { + override fun getExportChecker(): DescriptorExportCheckerVisitor = KonanDescriptorExportChecker() + + override fun getMangleComputer(mode: MangleMode): DescriptorMangleComputer = + KonanDescriptorMangleComputer(StringBuilder(256), mode) + + private class KonanDescriptorExportChecker : DescriptorExportCheckerVisitor() { + override fun DeclarationDescriptor.isPlatformSpecificExported(): Boolean { + if (this is SimpleFunctionDescriptor) { + if (kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) return false + } + // TODO: revise + if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) { + // Treat any `@SymbolName` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) { + // Treat any `@ExportForCppRuntime` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) { + // Treat `@CName` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) { + return true + } + + return false + } + } + + private class KonanDescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) : DescriptorMangleComputer(builder, mode) { + override fun copy(newMode: MangleMode): DescriptorMangleComputer = KonanDescriptorMangleComputer(builder, newMode) + + override fun FunctionDescriptor.platformSpecificFunctionName(): String? { + (if (this is ConstructorDescriptor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo() + ?.let { + return buildString { + if (extensionReceiverParameter != null) { + append(extensionReceiverParameter!!.type.constructor.declarationDescriptor!!.name) + append(".") + } + + append("objc:") + append(it.selector) + if (this@platformSpecificFunctionName is ConstructorDescriptor && this@platformSpecificFunctionName.isObjCConstructor) append("#Constructor") + + if (this@platformSpecificFunctionName is PropertyAccessorDescriptor) { + append("#Accessor") + } + } + } + return null + } + + override fun FunctionDescriptor.specialValueParamPrefix(param: ValueParameterDescriptor): String { + return if (this.hasObjCMethodAnnotation || this.hasObjCFactoryAnnotation || this.isObjCClassMethod()) "${param.name}:" else "" + } + } +} + +object KonanManglerDesc : AbstractKonanDescriptorMangler() \ No newline at end of file diff --git a/tools/performance-server/shared/src/main/kotlin/org/jetbrains/build/Build.kt b/tools/performance-server/shared/src/main/kotlin/org/jetbrains/build/Build.kt deleted file mode 100644 index 3630710d801..00000000000 --- a/tools/performance-server/shared/src/main/kotlin/org/jetbrains/build/Build.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.jetbrains.build - -import org.jetbrains.report.* -import org.jetbrains.report.json.* - -data class Build(val buildNumber: String, val startTime: String, val finishTime: String, val branch: String, - val commits: String, val buildType: String, val failuresNumber: Int, val executionTime: String, - val compileTime: String, val codeSize: String, val bundleSize: String?) { - - companion object: EntityFromJsonFactory { - override fun create(data: JsonElement): Build { - if (data is JsonObject) { - val buildNumber = elementToString(data.getRequiredField("buildNumber"), "buildNumber") - val startTime = elementToString(data.getRequiredField("startTime"), "startTime") - val finishTime = elementToString(data.getRequiredField("finishTime"), "finishTime") - val branch = elementToString(data.getRequiredField("branch"), "branch") - val commits = elementToString(data.getRequiredField("commits"), "commits") - val buildType = elementToString(data.getRequiredField("buildType"), "buildType") - val failuresNumber = elementToInt(data.getRequiredField("failuresNumber"), "failuresNumber") - val executionTime = elementToString(data.getRequiredField("executionTime"), "executionTime") - val compileTime = elementToString(data.getRequiredField("compileTime"), "compileTime") - val codeSize = elementToString(data.getRequiredField("codeSize"), "codeSize") - val bundleSize = elementToStringOrNull(data.getRequiredField("bundleSize"), "bundleSize") - return Build(buildNumber, startTime, finishTime, branch, commits, buildType, failuresNumber, executionTime, - compileTime, codeSize, bundleSize) - } else { - error("Top level entity is expected to be an object. Please, check origin files.") - } - } - } - - private fun formatTime(time: String, targetZone: Int = 3): String { - val matchResult = "^\\d{8}T(\\d{2})(\\d{2})\\d{2}((\\+|-)\\d{2})".toRegex().find(time)?.groupValues - matchResult?.let { - val timeZone = matchResult[3].toInt() - val timeDifference = targetZone - timeZone - var hours = (matchResult[1].toInt() + timeDifference) - if (hours > 23) { - hours -= 24 - } - return "${if (hours < 10) "0$hours" else "$hours"}:${matchResult[2]}" - } ?: error { "Wrong format of time $startTime" } - } - - val date: String by lazy { - val matchResult = "^(\\d{4})(\\d{2})(\\d{2})".toRegex().find(startTime)?.groupValues - matchResult?.let { "${matchResult[3]}/${matchResult[2]}/${matchResult[1]}" } - ?: error { "Wrong format of time $startTime" } - } - - val formattedStartTime: String by lazy { - formatTime(startTime) - } - - val formattedFinishTime: String by lazy { - formatTime(finishTime) - } -} \ No newline at end of file