[K/N] Refactor KonanSymbols to avoid descriptors when built over FIR

^KT-58437
This commit is contained in:
Pavel Kunyavskiy
2023-05-03 16:49:00 +02:00
committed by Space Team
parent 7f9118d0f2
commit 68a68b2763
7 changed files with 283 additions and 350 deletions
@@ -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")
@@ -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)
) {
@@ -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)
}
@@ -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"
@@ -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
@@ -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("<getWithoutBoundCheck>")
}
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>(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<IrSimpleFunction> { it.name == name }?.symbol
override fun IrClassSymbol.findMemberProperty(name: Name): IrPropertySymbol? =
owner.findDeclaration<IrProperty> { it.name == name }?.symbol
override fun IrClassSymbol.findMemberPropertyGetter(name: Name): IrSimpleFunctionSymbol? =
owner.findDeclaration<IrProperty> { 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<IrSimpleFunction> { it.name == name }?.symbol
override fun findMemberProperty(clazz: IrClassSymbol, name: Name): IrPropertySymbol? =
clazz.owner.findDeclaration<IrProperty> { it.name == name }?.symbol
override fun findMemberPropertyGetter(clazz: IrClassSymbol, name: Name): IrSimpleFunctionSymbol? =
clazz.owner.findDeclaration<IrProperty> { 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<IrClass>().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()
}
}
@@ -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()