From 68a68b27636e3d004dace865d240da3ae323145b Mon Sep 17 00:00:00 2001 From: Pavel Kunyavskiy Date: Wed, 3 May 2023 16:49:00 +0200 Subject: [PATCH] [K/N] Refactor KonanSymbols to avoid descriptors when built over FIR ^KT-58437 --- .../jetbrains/kotlin/backend/common/ir/Ir.kt | 8 +- .../common/lower/loops/ProgressionType.kt | 4 +- .../jetbrains/kotlin/backend/konan/Fir2Ir.kt | 14 +- .../kotlin/backend/konan/InteropUtils.kt | 2 +- .../jetbrains/kotlin/backend/konan/PsiToIr.kt | 6 +- .../jetbrains/kotlin/backend/konan/ir/Ir.kt | 519 +++++++++--------- .../kotlin/backend/konan/llvm/EntryPoint.kt | 80 --- 7 files changed, 283 insertions(+), 350 deletions(-) delete mode 100644 kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt index 313d178cd8a..3763a1ea996 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt @@ -61,10 +61,10 @@ open class BuiltinSymbolsBase(val irBuiltIns: IrBuiltIns, private val symbolTabl // The "...OrNull" variants are used for the classes below because the minimal stdlib used in tests do not include those classes. // It was not feasible to add them to the JS reduced runtime because all its transitive dependencies also need to be // added, which would include a lot of the full stdlib. - open val uByte = irBuiltIns.findClass(Name.identifier("UByte"), "kotlin") - open val uShort = irBuiltIns.findClass(Name.identifier("UShort"), "kotlin") - open val uInt = irBuiltIns.findClass(Name.identifier("UInt"), "kotlin") - open val uLong = irBuiltIns.findClass(Name.identifier("ULong"), "kotlin") + val uByte = irBuiltIns.findClass(Name.identifier("UByte"), "kotlin") + val uShort = irBuiltIns.findClass(Name.identifier("UShort"), "kotlin") + val uInt = irBuiltIns.findClass(Name.identifier("UInt"), "kotlin") + val uLong = irBuiltIns.findClass(Name.identifier("ULong"), "kotlin") val uIntProgression = progressionOrNull("UIntProgression") val uLongProgression = progressionOrNull("ULongProgression") val uIntRange = progressionOrNull("UIntRange") diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionType.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionType.kt index a2ec5618a82..477d4d59de7 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionType.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionType.kt @@ -176,7 +176,7 @@ internal class UIntProgressionType(symbols: Symbols, allowUnsignedBounds: Boolea maxValueAsLong = UInt.MAX_VALUE.toLong(), // Uses `getProgressionLastElement(UInt, UInt, Int): UInt` getProgressionLastElementFunction = symbols.getProgressionLastElementByReturnType[symbols.uInt!!], - unsignedType = symbols.uInt!!.defaultType, + unsignedType = symbols.uInt.defaultType, unsignedConversionFunction = symbols.toUIntByExtensionReceiver.getValue(symbols.int) ) { @@ -192,7 +192,7 @@ internal class ULongProgressionType(symbols: Symbols, allowUnsignedBounds: Boole maxValueAsLong = ULong.MAX_VALUE.toLong(), // Uses `getProgressionLastElement(ULong, ULong, Long): ULong` getProgressionLastElementFunction = symbols.getProgressionLastElementByReturnType[symbols.uLong!!], - unsignedType = symbols.uLong!!.defaultType, + unsignedType = symbols.uLong.defaultType, unsignedConversionFunction = symbols.toULongByExtensionReceiver.getValue(symbols.long) ) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt index d0af8b21eb4..7f68458ae32 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt @@ -6,7 +6,8 @@ import org.jetbrains.kotlin.backend.common.serialization.metadata.DynamicTypeDes import org.jetbrains.kotlin.backend.konan.driver.PhaseContext import org.jetbrains.kotlin.backend.konan.driver.phases.Fir2IrOutput import org.jetbrains.kotlin.backend.konan.driver.phases.FirOutput -import org.jetbrains.kotlin.backend.konan.ir.KonanSymbolsOverFir +import org.jetbrains.kotlin.backend.konan.ir.SymbolOverIrLookupUtils +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols import org.jetbrains.kotlin.backend.konan.serialization.KonanIdSignaturer import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr @@ -28,10 +29,8 @@ import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize import org.jetbrains.kotlin.fir.signaturer.Ir2FirManglerAdapter import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories @@ -118,7 +117,7 @@ internal fun PhaseContext.fir2Ir( }.map { it.second }.toSet() - val symbols = createKonanSymbols(irModuleFragment, components, pluginContext) + val symbols = createKonanSymbols(components, pluginContext) val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames) @@ -131,13 +130,10 @@ internal fun PhaseContext.fir2Ir( } private fun PhaseContext.createKonanSymbols( - irModuleFragment: IrModuleFragment, components: Fir2IrComponents, pluginContext: Fir2IrPluginContext, -): KonanSymbolsOverFir { - val moduleDescriptor = irModuleFragment.descriptor +): KonanSymbols { val symbolTable = SymbolTable(KonanIdSignaturer(KonanManglerDesc), pluginContext.irFactory) - val descriptorsLookup = DescriptorsLookup(moduleDescriptor.builtIns as KonanBuiltIns) - return KonanSymbolsOverFir(this, descriptorsLookup, components.irBuiltIns, symbolTable, symbolTable.lazyWrapper) + return KonanSymbols(this, SymbolOverIrLookupUtils(), components.irBuiltIns, symbolTable.lazyWrapper) } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt index c8a1d99f401..b35602f4cf8 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt @@ -32,7 +32,7 @@ object InteropFqNames { const val cStructVarName = "CStructVar" const val cEnumVarName = "CEnumVar" const val cPrimitiveVarName = "CPrimitiveVar" - private const val cPointedName = "CPointed" + const val cPointedName = "CPointed" const val interopStubsName = "InteropStubs" const val managedTypeName = "ManagedType" 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 510e96bcfa1..e19a9570e9c 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 @@ -13,7 +13,8 @@ import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary import org.jetbrains.kotlin.backend.konan.driver.phases.PsiToIrContext import org.jetbrains.kotlin.backend.konan.driver.phases.PsiToIrInput import org.jetbrains.kotlin.backend.konan.driver.phases.PsiToIrOutput -import org.jetbrains.kotlin.backend.konan.ir.KonanSymbolsOverDescriptors +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.ir.SymbolOverDescriptorsLookupUtils import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs import org.jetbrains.kotlin.backend.konan.ir.konanLibrary import org.jetbrains.kotlin.backend.konan.serialization.* @@ -92,8 +93,7 @@ internal fun PsiToIrContext.psiToIr( else BuiltInFictitiousFunctionIrClassFactory(symbolTable, irBuiltInsOverDescriptors, reflectionTypes) irBuiltInsOverDescriptors.functionFactory = functionIrClassFactory - val descriptorsLookup = DescriptorsLookup(this.builtIns) - val symbols = KonanSymbolsOverDescriptors(this, descriptorsLookup, generatorContext.irBuiltIns, symbolTable, symbolTable.lazyWrapper) + val symbols = KonanSymbols(this, SymbolOverDescriptorsLookupUtils(generatorContext.symbolTable), generatorContext.irBuiltIns, symbolTable.lazyWrapper) val irDeserializer = if (isProducingLibrary && !useLinkerWhenProducingLibrary) { // Enable lazy IR generation for newly-created symbols inside BE diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index c9e7d0d30c4..23066600e67 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -10,32 +10,21 @@ import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Symbols import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.driver.PhaseContext -import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint import org.jetbrains.kotlin.backend.konan.lower.TestProcessor import org.jetbrains.kotlin.builtins.StandardNames -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.constructClassLikeType +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrBuiltIns +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol -import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable -import org.jetbrains.kotlin.ir.util.SymbolTable -import org.jetbrains.kotlin.ir.util.constructors -import org.jetbrains.kotlin.ir.util.findDeclaration -import org.jetbrains.kotlin.js.descriptorUtils.getKotlinTypeFqName -import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.name.StandardClassIds -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils object KonanNameConventions { @@ -43,28 +32,74 @@ object KonanNameConventions { val getWithoutBoundCheck = Name.special("") } +internal interface SymbolLookupUtils { + fun findMemberFunction(clazz: IrClassSymbol, name: Name): IrSimpleFunctionSymbol? + fun findMemberProperty(clazz: IrClassSymbol, name: Name): IrPropertySymbol? + fun findMemberPropertyGetter(clazz: IrClassSymbol, name: Name): IrSimpleFunctionSymbol? + fun findPrimaryConstructor(clazz: IrClassSymbol): IrConstructorSymbol? + fun findNoParametersConstructor(clazz: IrClassSymbol): IrConstructorSymbol? + fun findNestedClass(clazz: IrClassSymbol, name: Name): IrClassSymbol? + fun findGetter(property: IrPropertySymbol): IrSimpleFunctionSymbol? + + fun getName(clazz: IrClassSymbol): Name + fun isExtensionReceiverClass(property: IrPropertySymbol, expected: IrClassSymbol?): Boolean + fun isExtensionReceiverClass(function: IrFunctionSymbol, expected: IrClassSymbol?): Boolean + fun isExtensionReceiverNullable(function: IrFunctionSymbol): Boolean? + fun getValueParametersCount(function: IrFunctionSymbol): Int + fun getTypeParametersCount(function: IrFunctionSymbol): Int + fun isTypeParameterUpperBoundClass(property: IrPropertySymbol, index: Int, expected: IrClassSymbol): Boolean + fun isValueParameterClass(function: IrFunctionSymbol, index: Int, expected: IrClassSymbol?): Boolean + fun isReturnClass(function: IrFunctionSymbol, expected: IrClassSymbol): Boolean + fun isValueParameterTypeArgumentClass(function: IrFunctionSymbol, index: Int, argumentIndex: Int, expected: IrClassSymbol?): Boolean + fun isValueParameterNullable(function: IrFunctionSymbol, index: Int): Boolean? + fun isExpect(function: IrFunctionSymbol): Boolean + fun isSuspend(functionSymbol: IrFunctionSymbol): Boolean + fun getVisibility(function: IrFunctionSymbol): DescriptorVisibility + fun getValueParameterPrimitiveBinaryType(function: IrFunctionSymbol, index: Int): PrimitiveBinaryType? +} + // This is what Context collects about IR. internal class KonanIr(context: Context, override val symbols: KonanSymbols): Ir(context) -internal abstract class KonanSymbols( +internal class KonanSymbols( context: PhaseContext, - val descriptorsLookup: DescriptorsLookup, // Please don't add usages of `descriptorsLookup` and `descriptorsLookup.builtIns` to this class anymore. + val lookup: SymbolLookupUtils, irBuiltIns: IrBuiltIns, - internal val symbolTable: SymbolTable, // Please don't add usages of `symbolTable` to this class anymore. - lazySymbolTable: ReferenceSymbolTable + symbolTable: ReferenceSymbolTable, ): Symbols(irBuiltIns, symbolTable) { - protected abstract fun IrClassSymbol.findMemberSimpleFunction(name: Name): IrSimpleFunctionSymbol? - protected abstract fun IrClassSymbol.findMemberProperty(name: Name): IrPropertySymbol? - protected abstract fun IrClassSymbol.findMemberPropertyGetter(name: Name): IrSimpleFunctionSymbol? - protected abstract fun findDefaultConstructor(className: String): IrConstructorSymbol - protected abstract fun findDefaultConstructor(className: String, nestedClassName: String): IrConstructorSymbol - protected abstract fun findTopLevelExtensionPropertyGetter(packageName: FqName, name: Name, extensionParameterClassID: ClassId): IrSimpleFunctionSymbol? - private fun findInteropExtensionPropertyGetter(name: Name, extensionClassID: ClassId): IrSimpleFunctionSymbol? = - findTopLevelExtensionPropertyGetter(InteropFqNames.packageName, name, extensionClassID) + val entryPoint = run { + val config = context.config.configuration + if (config.get(KonanConfigKeys.PRODUCE) != CompilerOutputKind.PROGRAM) return@run null - val entryPoint = findMainEntryPoint(context, descriptorsLookup.builtIns)?.let { symbolTable.referenceSimpleFunction(it) } + val entryPoint = FqName(config.get(KonanConfigKeys.ENTRY) ?: when (config.get(KonanConfigKeys.GENERATE_TEST_RUNNER)) { + TestRunnerKind.MAIN_THREAD -> "kotlin.native.internal.test.main" + TestRunnerKind.WORKER -> "kotlin.native.internal.test.worker" + TestRunnerKind.MAIN_THREAD_NO_EXIT -> "kotlin.native.internal.test.mainNoExit" + else -> "main" + }) - override val externalSymbolTable = lazySymbolTable + val entryName = entryPoint.shortName() + val packageName = entryPoint.parent() + + fun IrSimpleFunctionSymbol.isArrayStringMain() = + lookup.getValueParametersCount(this) == 1 && + lookup.isValueParameterClass(this, 0, array) && + lookup.isValueParameterTypeArgumentClass(this, 0, 0, string) + + fun IrSimpleFunctionSymbol.isNoArgsMain() = lookup.getValueParametersCount(this) == 0 + + val candidates = irBuiltIns.findFunctions(entryName, packageName) + .filter { + lookup.isReturnClass(it, unit) && + lookup.getTypeParametersCount(it) == 0 && + lookup.getVisibility(it).isPublicAPI + } + + val main = candidates.singleOrNull { it.isArrayStringMain() } ?: candidates.singleOrNull { it.isNoArgsMain() } + if (main == null) context.reportCompilationError("Could not find '$entryName' in '$packageName' package.") + if (lookup.isSuspend(main)) context.reportCompilationError("Entry point can not be a suspend function.") + main + } val nothing get() = irBuiltIns.nothingClass val throwable get() = irBuiltIns.throwableClass @@ -80,8 +115,8 @@ internal abstract class KonanSymbols( val allIntegerClasses = signedIntegerClasses + unsignedIntegerClasses - val unsignedToSignedOfSameBitWidth = unsignedIntegerClasses.associate { - it to when (it) { + val unsignedToSignedOfSameBitWidth = unsignedIntegerClasses.associateWith { + when (it) { uByte -> byte uShort -> short uInt -> int @@ -92,11 +127,11 @@ internal abstract class KonanSymbols( val integerConversions = allIntegerClasses.flatMap { fromClass -> allIntegerClasses.map { toClass -> - val name = Name.identifier("to${toClass.descriptor.name.asString().replaceFirstChar(Char::uppercaseChar)}") + val name = Name.identifier("to${lookup.getName(toClass).asString().replaceFirstChar(Char::uppercaseChar)}") val symbol = if (fromClass in signedIntegerClasses && toClass in unsignedIntegerClasses) { irBuiltIns.getNonBuiltInFunctionsByExtensionReceiver(name, "kotlin")[fromClass]!! } else { - fromClass.findMemberSimpleFunction(name)!! + lookup.findMemberFunction(fromClass, name)!! } (fromClass to toClass) to symbol @@ -113,21 +148,32 @@ internal abstract class KonanSymbols( val processUnhandledException = irBuiltIns.findFunctions(Name.identifier("processUnhandledException"), "kotlin", "native").single() val terminateWithUnhandledException = irBuiltIns.findFunctions(Name.identifier("terminateWithUnhandledException"), "kotlin", "native").single() - abstract val interopNativePointedGetRawPointer: IrSimpleFunctionSymbol + val interopNativePointedGetRawPointer = interopFunctions(InteropFqNames.nativePointedGetRawPointerFunName).single { + lookup.isExtensionReceiverClass(it, nativePointed) + } val interopCPointer = interopClass(InteropFqNames.cPointerName) - val interopCstr = findInteropExtensionPropertyGetter(Name.identifier(InteropFqNames.cstrPropertyName), StandardClassIds.String)!! - val interopWcstr = findInteropExtensionPropertyGetter(Name.identifier(InteropFqNames.wcstrPropertyName), StandardClassIds.String)!! + val interopCPointed = interopClass(InteropFqNames.cPointedName) + val interopCstr = findTopLevelPropertyGetter(InteropFqNames.packageName, Name.identifier(InteropFqNames.cstrPropertyName), string) + val interopWcstr = findTopLevelPropertyGetter(InteropFqNames.packageName, Name.identifier(InteropFqNames.wcstrPropertyName), string) val interopMemScope = interopClass(InteropFqNames.memScopeName) val interopCValue = interopClass(InteropFqNames.cValueName) val interopCValuesRef = interopClass(InteropFqNames.cValuesRefName) - abstract val interopCValueWrite: IrSimpleFunctionSymbol - abstract val interopCValueRead: IrSimpleFunctionSymbol - abstract val interopAllocType: IrSimpleFunctionSymbol + val interopCValueWrite = interopFunctions(InteropFqNames.cValueWriteFunName).single { + lookup.isExtensionReceiverClass(it, interopCValue) + } + val interopCValueRead = interopFunctions(InteropFqNames.cValueReadFunName).single { + lookup.getValueParametersCount(it) == 1 + } + val interopAllocType = interopFunctions(InteropFqNames.allocTypeFunName).single { + lookup.getTypeParametersCount(it) == 0 + } val interopTypeOf = interopFunction(InteropFqNames.typeOfFunName) - abstract val interopCPointerGetRawValue: IrSimpleFunctionSymbol + val interopCPointerGetRawValue = interopFunctions(InteropFqNames.cPointerGetRawValueFunName).single { + lookup.isExtensionReceiverClass(it, interopCPointer) + } val interopAllocObjCObject = interopFunction(InteropFqNames.allocObjCObjectFunName) @@ -164,11 +210,9 @@ internal abstract class KonanSymbols( val interopObjCObjectInitBy = interopFunction(InteropFqNames.objCObjectInitByFunName) val interopObjCObjectRawValueGetter = interopFunction(InteropFqNames.objCObjectRawPtrFunName) - val interopNativePointedRawPtrGetter = interopClass(InteropFqNames.nativePointedName) - .findMemberPropertyGetter(Name.identifier(InteropFqNames.nativePointedRawPtrPropertyName))!! + val interopNativePointedRawPtrGetter = lookup.findMemberPropertyGetter(interopClass(InteropFqNames.nativePointedName), Name.identifier(InteropFqNames.nativePointedRawPtrPropertyName))!! - val interopCPointerRawValue: IrPropertySymbol = interopClass(InteropFqNames.cPointerName) - .findMemberProperty(Name.identifier(InteropFqNames.cPointerRawValuePropertyName))!! + val interopCPointerRawValue: IrPropertySymbol = lookup.findMemberProperty(interopClass(InteropFqNames.cPointerName), Name.identifier(InteropFqNames.cPointerRawValuePropertyName))!! val interopInterpretObjCPointer = interopFunction(InteropFqNames.interpretObjCPointerFunName) val interopInterpretObjCPointerOrNull = interopFunction(InteropFqNames.interpretObjCPointerOrNullFunName) @@ -182,10 +226,21 @@ internal abstract class KonanSymbols( val nativeMemUtils = interopClass(InteropFqNames.nativeMemUtilsName) val nativeHeap = interopClass(InteropFqNames.nativeHeapName) - abstract val interopGetPtr: IrSimpleFunctionSymbol - abstract val interopManagedGetPtr: IrSimpleFunctionSymbol + val cStuctVar = interopClass(InteropFqNames.cStructVarName) + val cStructVarConstructorSymbol = lookup.findPrimaryConstructor(cStuctVar)!! + val managedTypeConstructor = lookup.findPrimaryConstructor(interopClass(InteropFqNames.managedTypeName))!! + val structVarPrimaryConstructor = lookup.findPrimaryConstructor(lookup.findNestedClass(cStuctVar, Name.identifier(InteropFqNames.TypeName))!!)!! + + val interopGetPtr = findTopLevelPropertyGetter(InteropFqNames.packageName, Name.identifier("ptr")) { + lookup.isTypeParameterUpperBoundClass(it, 0, interopCPointed) + } val interopManagedType = interopClass(InteropFqNames.managedTypeName) + + val interopManagedGetPtr = findTopLevelPropertyGetter(InteropFqNames.packageName, Name.identifier("ptr")) { + lookup.isTypeParameterUpperBoundClass(it, 0, cStuctVar) && lookup.isExtensionReceiverClass(it, interopManagedType) + } + val interopCPlusPlusClass = interopClass(InteropFqNames.cPlusPlusClassName) val interopSkiaRefCnt = interopClass(InteropFqNames.skiaRefCntName) @@ -216,8 +271,9 @@ internal abstract class KonanSymbols( val createCleaner = irBuiltIns.findFunctions(Name.identifier("createCleaner"),"kotlin", "native", "ref").single() + // TODO: this is strange. It should be a map from IrClassSymbol val areEqualByValue = internalFunctions("areEqualByValue").associateBy { - it.descriptor.valueParameters[0].type.computePrimitiveBinaryTypeOrNull()!! + lookup.getValueParameterPrimitiveBinaryType(it, 0)!! } val reinterpret = internalFunction("reinterpret") @@ -226,7 +282,7 @@ internal abstract class KonanSymbols( val ieee754Equals = internalFunctions("ieee754Equals") - val equals = any.findMemberSimpleFunction(Name.identifier("equals"))!! + val equals = lookup.findMemberFunction(any, Name.identifier("equals"))!! val throwArithmeticException = internalFunction("ThrowArithmeticException") @@ -256,45 +312,41 @@ internal abstract class KonanSymbols( override val defaultConstructorMarker = internalClass("DefaultConstructorMarker") - private fun arrayToExtensionSymbolMap(name: String, filter: (FunctionDescriptor) -> Boolean = { true }) = + private fun arrayToExtensionSymbolMap(name: String, filter: (IrFunctionSymbol) -> Boolean = { true }) = arrays.associateWith { classSymbol -> irBuiltIns.findFunctions(Name.identifier(name), "kotlin", "collections") .singleOrNull { function -> - function.descriptor.let { - it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == classSymbol.descriptor - && !it.isExpect - && filter(it) - } - } ?: error(classSymbol.toString()) + lookup.isExtensionReceiverClass(function, classSymbol) && !lookup.isExpect(function) && filter(function) + } ?: error("No function $name for $classSymbol") } val arrayContentToString = arrayToExtensionSymbolMap("contentToString") { - it.extensionReceiverParameter?.type?.isMarkedNullable == false + lookup.isExtensionReceiverNullable(it) == false } val arrayContentHashCode = arrayToExtensionSymbolMap("contentHashCode") { - it.extensionReceiverParameter?.type?.isMarkedNullable == false + lookup.isExtensionReceiverNullable(it) == false } val arrayContentEquals = arrayToExtensionSymbolMap("contentEquals") { - it.extensionReceiverParameter?.type?.isMarkedNullable == false + lookup.isExtensionReceiverNullable(it) == false } override val arraysContentEquals by lazy { arrayContentEquals.mapKeys { it.key.defaultType } } val copyInto = arrayToExtensionSymbolMap("copyInto") - val copyOf = arrayToExtensionSymbolMap("copyOf") { it.valueParameters.isEmpty() } + val copyOf = arrayToExtensionSymbolMap("copyOf") { lookup.getValueParametersCount(it) == 0 } - val arrayGet = arrays.associateWith { it.findMemberSimpleFunction(Name.identifier("get"))!! } + val arrayGet = arrays.associateWith { lookup.findMemberFunction(it, Name.identifier("get"))!! } - val arraySet = arrays.associateWith { it.findMemberSimpleFunction(Name.identifier("set"))!! } + val arraySet = arrays.associateWith { lookup.findMemberFunction(it, Name.identifier("set"))!! } - val arraySize = arrays.associateWith { it.findMemberPropertyGetter(Name.identifier("size"))!! } + val arraySize = arrays.associateWith { lookup.findMemberPropertyGetter(it, Name.identifier("size"))!! } val valuesForEnum = internalFunction("valuesForEnum") val valueOfForEnum = internalFunction("valueOfForEnum") val createEnumEntries = irBuiltIns.findFunctions(Name.identifier("enumEntries"), "kotlin", "enums") - .single { it.descriptor.valueParameters.singleOrNull()?.type?.constructor?.declarationDescriptor == array.descriptor } + .single { lookup.getValueParametersCount(it) == 1 && lookup.isValueParameterClass(it, 0, array) } val enumEntriesInterface = irBuiltIns.findClass(Name.identifier("EnumEntries"), "kotlin", "enums")!! @@ -303,7 +355,7 @@ internal abstract class KonanSymbols( val initInstance = internalFunction("initInstance") val println = irBuiltIns.findFunctions(Name.identifier("println"), "kotlin", "io") - .single { it.descriptor.valueParameters.singleOrNull()?.type?.constructor?.declarationDescriptor == string.descriptor } + .single { lookup.getValueParametersCount(it) == 1 && lookup.isValueParameterClass(it, 0, string) } override val getContinuation = internalFunction("getContinuation") @@ -313,17 +365,8 @@ internal abstract class KonanSymbols( override val suspendCoroutineUninterceptedOrReturn = internalFunction("suspendCoroutineUninterceptedOrReturn") - private val coroutinesIntrinsicsPackage = - descriptorsLookup.builtIns.builtInsModule.getPackage(StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope - - private val coroutinesPackage = - descriptorsLookup.builtIns.builtInsModule.getPackage(StandardNames.COROUTINES_PACKAGE_FQ_NAME).memberScope - - override val coroutineContextGetter = symbolTable.referenceSimpleFunction( - coroutinesPackage - .getContributedVariables(Name.identifier("coroutineContext"), NoLookupLocation.FROM_BACKEND) - .single() - .getter!!) + override val coroutineContextGetter = + findTopLevelPropertyGetter(StandardNames.COROUTINES_PACKAGE_FQ_NAME, Name.identifier("coroutineContext"), null) override val coroutineGetContext = internalFunction("getCoroutineContext") @@ -335,23 +378,17 @@ internal abstract class KonanSymbols( val continuationImpl = internalCoroutinesClass("ContinuationImpl") - val invokeSuspendFunction = - baseContinuationImpl.findMemberSimpleFunction(Name.identifier("invokeSuspend"))!! + val invokeSuspendFunction = lookup.findMemberFunction(baseContinuationImpl, Name.identifier("invokeSuspend"))!! - override val coroutineSuspendedGetter = symbolTable.referenceSimpleFunction( - coroutinesIntrinsicsPackage - .getContributedVariables(COROUTINE_SUSPENDED_NAME, NoLookupLocation.FROM_BACKEND) - .filterNot { it.isExpect }.single().getter!! - ) + override val coroutineSuspendedGetter = + findTopLevelPropertyGetter(StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME, COROUTINE_SUSPENDED_NAME, null) val cancellationException = topLevelClass(KonanFqNames.cancellationException) val kotlinResult = irBuiltIns.findClass(Name.identifier("Result"))!! val kotlinResultGetOrThrow = irBuiltIns.findFunctions(Name.identifier("getOrThrow")) - .single { - it.descriptor.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == kotlinResult.descriptor - } + .single { lookup.isExtensionReceiverClass(it, kotlinResult) } override val functionAdapter = internalClass("FunctionAdapter") @@ -380,12 +417,12 @@ internal abstract class KonanSymbols( val kType = reflectionClass("KType") val getObjectTypeInfo = internalFunction("getObjectTypeInfo") val kClassImpl = internalClass("KClassImpl") - val kClassImplConstructor by lazy { kClassImpl.constructors.single { it.descriptor.isPrimary } } - val kClassImplIntrinsicConstructor by lazy { kClassImpl.constructors.single { it.descriptor.valueParameters.isEmpty() } } + val kClassImplConstructor = lookup.findPrimaryConstructor(kClassImpl)!! + val kClassImplIntrinsicConstructor = lookup.findNoParametersConstructor(kClassImpl)!! val kClassUnsupportedImpl = internalClass("KClassUnsupportedImpl") val kTypeParameterImpl = internalClass("KTypeParameterImpl") val kTypeImpl = internalClass("KTypeImpl") - val kTypeImplIntrinsicConstructor by lazy { kTypeImpl.constructors.single { it.descriptor.valueParameters.isEmpty() } } + val kTypeImplIntrinsicConstructor = lookup.findNoParametersConstructor(kTypeImpl)!! val kTypeImplForTypeParametersWithRecursiveBounds = internalClass("KTypeImplForTypeParametersWithRecursiveBounds") val kTypeProjectionList = internalClass("KTypeProjectionList") @@ -395,14 +432,17 @@ internal abstract class KonanSymbols( val eagerInitialization = topLevelClass(KonanFqNames.eagerInitialization) - val cStructVarConstructorSymbol = findDefaultConstructor(InteropFqNames.cStructVarName) - val managedTypeConstructor = findDefaultConstructor(InteropFqNames.managedTypeName) - val enumVarConstructorSymbol = findDefaultConstructor(InteropFqNames.cEnumVarName) - val primitiveVarPrimaryConstructor = findDefaultConstructor(InteropFqNames.cPrimitiveVarName, InteropFqNames.TypeName) - val structVarPrimaryConstructor = findDefaultConstructor(InteropFqNames.cStructVarName, InteropFqNames.TypeName) + val enumVarConstructorSymbol = lookup.findPrimaryConstructor(interopClass(InteropFqNames.cEnumVarName))!! + val primitiveVarPrimaryConstructor = lookup.findPrimaryConstructor(lookup.findNestedClass(interopClass(InteropFqNames.cPrimitiveVarName), Name.identifier(InteropFqNames.TypeName))!!)!! private fun topLevelClass(fqName: FqName): IrClassSymbol = irBuiltIns.findClass(fqName.shortName(), fqName.parent())!! + private fun findTopLevelPropertyGetter(packageName: FqName, name: Name, extensionReceiverClass: IrClassSymbol?) = + findTopLevelPropertyGetter(packageName, name) { lookup.isExtensionReceiverClass(it, extensionReceiverClass) } + + private fun findTopLevelPropertyGetter(packageName: FqName, name: Name, predicate: (IrPropertySymbol) -> Boolean) = + lookup.findGetter(irBuiltIns.findProperties(name, packageName).single(predicate))!! + private fun nativeFunction(name: String) = irBuiltIns.findFunctions(Name.identifier(name), KonanFqNames.packageName).single() @@ -421,10 +461,12 @@ internal abstract class KonanSymbols( private fun getKonanTestClass(className: String) = irBuiltIns.findClass(Name.identifier(className), "kotlin", "native", "internal", "test")!! - private fun interopFunction(name: String) = - irBuiltIns.findFunctions(Name.identifier(name), InteropFqNames.packageName).single() + private fun interopFunctions(name: String) = + irBuiltIns.findFunctions(Name.identifier(name), InteropFqNames.packageName) - protected fun interopClass(name: String) = + private fun interopFunction(name: String) = interopFunctions(name).single() + + private fun interopClass(name: String) = irBuiltIns.findClass(Name.identifier(name), InteropFqNames.packageName)!! fun kFunctionN(n: Int) = irBuiltIns.kFunctionN(n).symbol @@ -457,180 +499,155 @@ internal abstract class KonanSymbols( fun getTestFunctionKind(kind: TestProcessor.FunctionKind) = testFunctionKindCache[kind]!! } -// WARNING: override protected functions are called from base class(`KonanSymbols`) constructor, -// so its functionality must be independent of the derived object(`KonanSymbolsOverDescriptors`)'s state, which is uninitialized at the invocation moment -internal class KonanSymbolsOverDescriptors( - context: PhaseContext, - descriptorsLookup: DescriptorsLookup, - irBuiltIns: IrBuiltIns, - symbolTable: SymbolTable, - lazySymbolTable: ReferenceSymbolTable -) : KonanSymbols(context, descriptorsLookup, irBuiltIns, symbolTable, lazySymbolTable) { - override fun IrClassSymbol.findMemberSimpleFunction(name: Name): IrSimpleFunctionSymbol? = +@OptIn(ObsoleteDescriptorBasedAPI::class) +internal class SymbolOverDescriptorsLookupUtils(val symbolTable: SymbolTable) : SymbolLookupUtils { + override fun findMemberFunction(clazz: IrClassSymbol, name: Name): IrSimpleFunctionSymbol? = // inspired by: irBuiltIns.findBuiltInClassMemberFunctions(this, name).singleOrNull() - descriptor.unsubstitutedMemberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + clazz.descriptor.unsubstitutedMemberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) .singleOrNull() ?.let { symbolTable.referenceSimpleFunction(it) } - override fun IrClassSymbol.findMemberProperty(name: Name): IrPropertySymbol? = - descriptor.unsubstitutedMemberScope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND) + override fun findMemberProperty(clazz: IrClassSymbol, name: Name): IrPropertySymbol? = + clazz.descriptor.unsubstitutedMemberScope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND) .singleOrNull() ?.let { symbolTable.referenceProperty(it) } - override fun IrClassSymbol.findMemberPropertyGetter(name: Name): IrSimpleFunctionSymbol? = - descriptor.unsubstitutedMemberScope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND) + override fun findMemberPropertyGetter(clazz: IrClassSymbol, name: Name): IrSimpleFunctionSymbol? = + clazz.descriptor.unsubstitutedMemberScope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND) .singleOrNull() ?.getter ?.let { symbolTable.referenceSimpleFunction(it) } - override fun findTopLevelExtensionPropertyGetter(packageName: FqName, name: Name, extensionParameterClassID: ClassId): IrSimpleFunctionSymbol? { - val extensionParameterFqNameString = extensionParameterClassID.asFqNameString() - return descriptorsLookup.builtIns.builtInsModule.getPackage(InteropFqNames.packageName).memberScope - .getContributedVariables(name, NoLookupLocation.FROM_BACKEND) - .singleOrNull { - it.extensionReceiverParameter?.type?.getKotlinTypeFqName(true) == extensionParameterFqNameString - }?.getter - ?.let { symbolTable.referenceSimpleFunction(it) } + override fun getName(clazz: IrClassSymbol) = clazz.descriptor.name + override fun isExtensionReceiverClass(property: IrPropertySymbol, expected: IrClassSymbol?): Boolean { + return property.descriptor.extensionReceiverParameter?.type?.let { TypeUtils.getClassDescriptor(it) } == expected?.descriptor } - override val interopNativePointedGetRawPointer = symbolTable.referenceSimpleFunction( - descriptorsLookup.interopBuiltIns.getContributedFunctions(InteropFqNames.nativePointedGetRawPointerFunName).single { - val extensionReceiverParameter = it.extensionReceiverParameter - extensionReceiverParameter != null && - TypeUtils.getClassDescriptor(extensionReceiverParameter.type)?.fqNameUnsafe == InteropFqNames.nativePointed - }) - override val interopCValueWrite = symbolTable.referenceSimpleFunction( - descriptorsLookup.interopBuiltIns.getContributedFunctions(InteropFqNames.cValueWriteFunName).single { - it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor?.fqNameSafe == InteropFqNames.cValue - }) - override val interopCValueRead = symbolTable.referenceSimpleFunction( - descriptorsLookup.interopBuiltIns.getContributedFunctions(InteropFqNames.cValueReadFunName).single { - it.valueParameters.size == 1 - }) - override val interopAllocType = symbolTable.referenceSimpleFunction( - descriptorsLookup.interopBuiltIns.getContributedFunctions(InteropFqNames.allocTypeFunName).single { - it.extensionReceiverParameter != null && it.valueParameters.singleOrNull()?.name?.toString() == "type" - }) - override val interopCPointerGetRawValue = symbolTable.referenceSimpleFunction( - descriptorsLookup.interopBuiltIns.getContributedFunctions(InteropFqNames.cPointerGetRawValueFunName).single { - val extensionReceiverParameter = it.extensionReceiverParameter - extensionReceiverParameter != null && - TypeUtils.getClassDescriptor(extensionReceiverParameter.type)?.fqNameUnsafe == InteropFqNames.cPointer - }) - - override fun findDefaultConstructor(className: String): IrConstructorSymbol = symbolTable.referenceConstructor( - descriptorsLookup.interopBuiltIns.getContributedClass(className) - .unsubstitutedPrimaryConstructor!! - ) - - override fun findDefaultConstructor(className: String, nestedClassName: String): IrConstructorSymbol = symbolTable.referenceConstructor( - descriptorsLookup.interopBuiltIns.getContributedClass(className) - .defaultType.memberScope.getContributedClass(nestedClassName) - .unsubstitutedPrimaryConstructor!! - ) - - override val interopGetPtr = descriptorsLookup.interopBuiltIns.getContributedVariables("ptr").single { - val singleTypeParameter = it.typeParameters.singleOrNull() - val singleTypeParameterUpperBound = singleTypeParameter?.upperBounds?.singleOrNull() - val extensionReceiverParameter = it.extensionReceiverParameter - - singleTypeParameterUpperBound != null && - extensionReceiverParameter != null && - TypeUtils.getClassDescriptor(singleTypeParameterUpperBound)?.fqNameSafe == InteropFqNames.cPointed && - extensionReceiverParameter.type == singleTypeParameter.defaultType - }.getter!!.let { symbolTable.referenceSimpleFunction(it) } - - override val interopManagedGetPtr = descriptorsLookup.interopBuiltIns.getContributedVariables("ptr").single { - val singleTypeParameter = it.typeParameters.singleOrNull() - val singleTypeParameterUpperBound = singleTypeParameter?.upperBounds?.singleOrNull() - val extensionReceiverParameter = it.extensionReceiverParameter - - singleTypeParameterUpperBound != null && - extensionReceiverParameter != null && - TypeUtils.getClassDescriptor(singleTypeParameterUpperBound)?.fqNameSafe == InteropFqNames.cStructVar && - TypeUtils.getClassDescriptor(extensionReceiverParameter.type)?.fqNameSafe == InteropFqNames.managedType - }.getter!!.let { symbolTable.referenceSimpleFunction(it) } -} - -// WARNING: override protected functions are called from base class(`KonanSymbols`) constructor, -// so its functionality must be independent of the derived object(`KonanSymbolsOverFir`)'s state, which is uninitialized at the invocation moment -internal class KonanSymbolsOverFir( - context: PhaseContext, - descriptorsLookup: DescriptorsLookup, - irBuiltIns: IrBuiltIns, - symbolTable: SymbolTable, - lazySymbolTable: ReferenceSymbolTable -) : KonanSymbols(context, descriptorsLookup, irBuiltIns, symbolTable, lazySymbolTable) { - override fun IrClassSymbol.findMemberSimpleFunction(name: Name): IrSimpleFunctionSymbol? = - owner.findDeclaration { it.name == name }?.symbol - - override fun IrClassSymbol.findMemberProperty(name: Name): IrPropertySymbol? = - owner.findDeclaration { it.name == name }?.symbol - - override fun IrClassSymbol.findMemberPropertyGetter(name: Name): IrSimpleFunctionSymbol? = - owner.findDeclaration { it.name == name }?.getter?.symbol - - override fun findTopLevelExtensionPropertyGetter(packageName: FqName, name: Name, extensionParameterClassID: ClassId): IrSimpleFunctionSymbol? { - val extensionParameterConeKotlinType = extensionParameterClassID.constructClassLikeType(arrayOf(), false).type - return irBuiltIns.findProperties(name, packageName).singleOrNull { - ((it.owner as Fir2IrLazyProperty).fir.receiverParameter?.typeRef as FirResolvedTypeRef).type == extensionParameterConeKotlinType - }?.owner?.getter?.symbol + override fun isExtensionReceiverClass(function: IrFunctionSymbol, expected: IrClassSymbol?): Boolean { + return function.descriptor.extensionReceiverParameter?.type?.let { TypeUtils.getClassDescriptor(it) } == expected?.descriptor } - override val interopNativePointedGetRawPointer = findSingleInteropFunction(InteropFqNames.nativePointedGetRawPointerFunName) { - val extensionReceiverParameter = it.owner.extensionReceiverParameter - extensionReceiverParameter != null && - extensionReceiverParameter.type.classFqName?.toUnsafe() == InteropFqNames.nativePointed - } - override val interopCValueWrite = findSingleInteropFunction(InteropFqNames.cValueWriteFunName) { - it.owner.extensionReceiverParameter?.type?.classFqName == InteropFqNames.cValue - } - override val interopCValueRead = findSingleInteropFunction(InteropFqNames.cValueReadFunName) { - it.owner.valueParameters.size == 1 - } - override val interopAllocType = findSingleInteropFunction(InteropFqNames.allocTypeFunName) { - it.owner.extensionReceiverParameter != null && it.owner.valueParameters.singleOrNull()?.name?.toString() == "type" - } - override val interopCPointerGetRawValue = findSingleInteropFunction(InteropFqNames.cPointerGetRawValueFunName) { - it.owner.extensionReceiverParameter?.type?.classFqName?.toUnsafe() == InteropFqNames.cPointer + override fun findGetter(property: IrPropertySymbol): IrSimpleFunctionSymbol = symbolTable.referenceSimpleFunction(property.descriptor.getter!!) + + override fun isExtensionReceiverNullable(function: IrFunctionSymbol): Boolean? { + return function.descriptor.extensionReceiverParameter?.type?.isMarkedNullable } - override val interopGetPtr = irBuiltIns.findProperties(Name.identifier("ptr"), InteropFqNames.packageName).single { - val singleTypeParameter = it.owner.getter?.typeParameters?.singleOrNull() - val singleTypeParameterUpperBound = singleTypeParameter?.symbol?.superTypes()?.singleOrNull() - val extensionReceiverParameter = it.owner.getter?.extensionReceiverParameter + override fun getValueParametersCount(function: IrFunctionSymbol): Int = function.descriptor.valueParameters.size - singleTypeParameterUpperBound != null && - extensionReceiverParameter != null && - singleTypeParameterUpperBound.classFqName == InteropFqNames.cPointed && - extensionReceiverParameter.type.classFqName == singleTypeParameter.defaultType.classFqName - }.owner.getter!!.symbol + override fun getTypeParametersCount(function: IrFunctionSymbol): Int = function.descriptor.typeParameters.size - override val interopManagedGetPtr = irBuiltIns.findProperties(Name.identifier("ptr"), InteropFqNames.packageName).single { - val singleTypeParameter = it.owner.getter?.typeParameters?.singleOrNull() - val singleTypeParameterUpperBound = singleTypeParameter?.symbol?.superTypes()?.singleOrNull() - val extensionReceiverParameter = it.owner.getter?.extensionReceiverParameter + private fun match(type: KotlinType?, symbol: IrClassSymbol?) = + if (type == null) + symbol == null + else + TypeUtils.getClassDescriptor(type) == symbol?.descriptor - singleTypeParameterUpperBound != null && - extensionReceiverParameter != null && - singleTypeParameterUpperBound.classFqName == InteropFqNames.cStructVar && - extensionReceiverParameter.type.classFqName == InteropFqNames.managedType - }.owner.getter!!.symbol + override fun isTypeParameterUpperBoundClass(property: IrPropertySymbol, index: Int, expected: IrClassSymbol): Boolean { + return property.descriptor.typeParameters.getOrNull(index)?.upperBounds?.any { match(it, expected) } ?: false + } - private fun findSingleInteropFunction(name: String, predicate: (IrSimpleFunctionSymbol) -> Boolean) = - irBuiltIns.findFunctions(Name.identifier(name), InteropFqNames.packageName).single(predicate) + override fun isValueParameterClass(function: IrFunctionSymbol, index: Int, expected: IrClassSymbol?): Boolean { + return match(function.descriptor.valueParameters.getOrNull(index)?.type, expected) + } - override fun findDefaultConstructor(className: String): IrConstructorSymbol = - interopClass(className).owner.declarations.single { - it is IrConstructor && it.isPrimary - }.symbol as IrConstructorSymbol + override fun isReturnClass(function: IrFunctionSymbol, expected: IrClassSymbol): Boolean { + return match(function.descriptor.returnType, expected) + } - override fun findDefaultConstructor(className: String, nestedClassName: String): IrConstructorSymbol { - val nested = interopClass(className).owner.declarations.single { - it is IrClass && it.name == Name.identifier(nestedClassName) - }.symbol as IrClassSymbol - return nested.owner.declarations.single { - it is IrConstructor && it.isPrimary - }.symbol as IrConstructorSymbol + override fun isValueParameterTypeArgumentClass(function: IrFunctionSymbol, index: Int, argumentIndex: Int, expected: IrClassSymbol?): Boolean { + return match(function.descriptor.valueParameters.getOrNull(index)?.type?.arguments?.getOrNull(argumentIndex)?.type, expected) + } + + override fun isValueParameterNullable(function: IrFunctionSymbol, index: Int): Boolean? { + return function.descriptor.valueParameters.getOrNull(index)?.type?.isMarkedNullable + } + + override fun isExpect(function: IrFunctionSymbol): Boolean = function.descriptor.isExpect + + override fun isSuspend(functionSymbol: IrFunctionSymbol): Boolean = functionSymbol.descriptor.isSuspend + override fun getVisibility(function: IrFunctionSymbol): DescriptorVisibility = function.descriptor.visibility + + override fun findPrimaryConstructor(clazz: IrClassSymbol) = clazz.descriptor.unsubstitutedPrimaryConstructor?.let { symbolTable.referenceConstructor(it) } + override fun findNoParametersConstructor(clazz: IrClassSymbol) = clazz.descriptor.constructors.singleOrNull { it.valueParameters.size == 0 }?.let { symbolTable.referenceConstructor(it) } + + override fun findNestedClass(clazz: IrClassSymbol, name: Name): IrClassSymbol? { + val classDescriptor = clazz.descriptor.defaultType.memberScope.getContributedClassifier(name, NoLookupLocation.FROM_BUILTINS) as? ClassDescriptor + return classDescriptor?.let { + symbolTable.referenceClass(it) + } + } + + override fun getValueParameterPrimitiveBinaryType(function: IrFunctionSymbol, index: Int): PrimitiveBinaryType? { + return function.descriptor.valueParameters[0].type.computePrimitiveBinaryTypeOrNull() + } +} + +internal class SymbolOverIrLookupUtils() : SymbolLookupUtils { + override fun findMemberFunction(clazz: IrClassSymbol, name: Name): IrSimpleFunctionSymbol? = + clazz.owner.findDeclaration { it.name == name }?.symbol + + override fun findMemberProperty(clazz: IrClassSymbol, name: Name): IrPropertySymbol? = + clazz.owner.findDeclaration { it.name == name }?.symbol + + override fun findMemberPropertyGetter(clazz: IrClassSymbol, name: Name): IrSimpleFunctionSymbol? = + clazz.owner.findDeclaration { it.name == name }?.getter?.symbol + + override fun findPrimaryConstructor(clazz: IrClassSymbol): IrConstructorSymbol? = clazz.owner.primaryConstructor?.symbol + override fun findNoParametersConstructor(clazz: IrClassSymbol): IrConstructorSymbol? = clazz.owner.constructors.singleOrNull { it.valueParameters.isEmpty() }?.symbol + + override fun findNestedClass(clazz: IrClassSymbol, name: Name): IrClassSymbol? { + return clazz.owner.declarations.filterIsInstance().singleOrNull { it.name == name }?.symbol + } + + override fun getName(clazz: IrClassSymbol): Name = clazz.owner.name + + override fun isExtensionReceiverClass(property: IrPropertySymbol, expected: IrClassSymbol?): Boolean { + return property.owner.getter?.extensionReceiverParameter?.type?.classOrNull == expected + } + + override fun isExtensionReceiverClass(function: IrFunctionSymbol, expected: IrClassSymbol?): Boolean { + return function.owner.extensionReceiverParameter?.type?.classOrNull == expected + } + + override fun findGetter(property: IrPropertySymbol): IrSimpleFunctionSymbol? = property.owner.getter?.symbol + + override fun isExtensionReceiverNullable(function: IrFunctionSymbol): Boolean? { + return function.owner.extensionReceiverParameter?.type?.isMarkedNullable() + } + + override fun getValueParametersCount(function: IrFunctionSymbol): Int = function.owner.valueParameters.size + + override fun getTypeParametersCount(function: IrFunctionSymbol): Int = function.owner.typeParameters.size + + override fun isTypeParameterUpperBoundClass(property: IrPropertySymbol, index: Int, expected: IrClassSymbol): Boolean { + return property.owner.getter?.typeParameters?.getOrNull(index)?.superTypes?.any { it.classOrNull == expected } ?: false + } + + override fun isValueParameterClass(function: IrFunctionSymbol, index: Int, expected: IrClassSymbol?): Boolean { + return function.owner.valueParameters.getOrNull(index)?.type?.classOrNull == expected + } + + override fun isReturnClass(function: IrFunctionSymbol, expected: IrClassSymbol): Boolean { + return function.owner.returnType.classOrNull == expected + } + + override fun isValueParameterTypeArgumentClass(function: IrFunctionSymbol, index: Int, argumentIndex: Int, expected: IrClassSymbol?): Boolean { + val type = function.owner.valueParameters.getOrNull(index)?.type as? IrSimpleType ?: return false + val argumentType = type.arguments.getOrNull(argumentIndex) as? IrSimpleType ?: return false + return argumentType.classOrNull == expected + } + + override fun isValueParameterNullable(function: IrFunctionSymbol, index: Int): Boolean? { + return function.owner.valueParameters.getOrNull(index)?.type?.isMarkedNullable() + } + + override fun isExpect(function: IrFunctionSymbol): Boolean = function.owner.isExpect + + override fun isSuspend(functionSymbol: IrFunctionSymbol): Boolean = functionSymbol.owner.isSuspend + override fun getVisibility(function: IrFunctionSymbol): DescriptorVisibility = function.owner.visibility + + override fun getValueParameterPrimitiveBinaryType(function: IrFunctionSymbol, index: Int): PrimitiveBinaryType? { + return function.owner.valueParameters[0].type.computePrimitiveBinaryTypeOrNull() } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt deleted file mode 100644 index b95f6428de6..00000000000 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2010-2018 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.llvm - -import org.jetbrains.kotlin.backend.konan.* -import org.jetbrains.kotlin.backend.konan.descriptors.isArray -import org.jetbrains.kotlin.backend.konan.driver.PhaseContext -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.konan.target.CompilerOutputKind.* -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.isUnit - -internal fun findMainEntryPoint(context: PhaseContext, builtIns: KotlinBuiltIns): FunctionDescriptor? { - - val config = context.config.configuration - if (config.get(KonanConfigKeys.PRODUCE) != PROGRAM) return null - - val entryPoint = FqName(config.get(KonanConfigKeys.ENTRY) ?: defaultEntryName(config)) - - val entryName = entryPoint.shortName() - val packageName = entryPoint.parent() - - val packageScope = builtIns.builtInsModule.getPackage(packageName).memberScope - - val candidates = packageScope.getContributedFunctions(entryName, - NoLookupLocation.FROM_BACKEND).filter { - it.returnType?.isUnit() == true && - it.typeParameters.isEmpty() && - it.visibility.isPublicAPI - } - - val main = - candidates.singleOrNull { it.hasSingleArrayOfStringParameter } ?: - candidates.singleOrNull { it.hasNoParameters } ?: - context.reportCompilationError("Could not find '$entryName' in '$packageName' package.") - - if (main.isSuspend) - context.reportCompilationError("Entry point can not be a suspend function.") - - return main -} - -private fun defaultEntryName(config: CompilerConfiguration): String = - when (config.get(KonanConfigKeys.GENERATE_TEST_RUNNER)) { - TestRunnerKind.MAIN_THREAD -> "kotlin.native.internal.test.main" - TestRunnerKind.WORKER -> "kotlin.native.internal.test.worker" - TestRunnerKind.MAIN_THREAD_NO_EXIT -> "kotlin.native.internal.test.mainNoExit" - else -> "main" - } - -private val KotlinType.filterClass: ClassDescriptor? - get() { - val constr = constructor.declarationDescriptor - return constr as? ClassDescriptor - } - -private val ClassDescriptor.isString - get() = fqNameSafe.asString() == "kotlin.String" - -private val KotlinType.isString - get() = filterClass?.isString ?: false - -private val KotlinType.isArrayOfString: Boolean - get() = (filterClass?.isArray ?: false) && - (arguments.singleOrNull()?.type?.isString ?: false) - -private val FunctionDescriptor.hasSingleArrayOfStringParameter: Boolean - get() = valueParameters.singleOrNull()?.type?.isArrayOfString ?: false - -private val FunctionDescriptor.hasNoParameters: Boolean - get() = valueParameters.isEmpty()