From 610c9b52787adca51c48995f3a1e32fcea85d7e6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Tue, 6 Mar 2018 12:19:23 +0300 Subject: [PATCH] Reduce usage of descriptors in latest stages of compiler Initialize properly new required IR data. Also update kotlin compiler to 1.2.40-dev-837 (d3ab86db). --- .../kotlin/backend/konan/CAdapterGenerator.kt | 9 +- .../jetbrains/kotlin/backend/konan/Context.kt | 31 +- .../konan/EnumSpecialDescriptorsFactory.kt | 12 +- .../kotlin/backend/konan/KonanDriver.kt | 2 +- .../kotlin/backend/konan/KonanLower.kt | 27 +- .../kotlin/backend/konan/KonanPlatform.kt | 5 + .../konan/descriptors/ClassVtablesBuilder.kt | 33 +- .../konan/descriptors/DescriptorUtils.kt | 220 +++----------- .../descriptors/LegacyDescriptorUtils.kt | 187 ++++++++++++ .../jetbrains/kotlin/backend/konan/ir/Ir.kt | 90 +++++- .../kotlin/backend/konan/ir/ModuleIndex.kt | 9 + .../konan/irasdescriptors/FakeIrUtils.kt | 60 ++++ .../konan/irasdescriptors/IrAsDescriptors.kt | 31 ++ .../konan/irasdescriptors/NewIrUtils.kt | 234 ++++++++++++++ .../backend/konan/llvm/BinaryInterface.kt | 63 ++-- .../backend/konan/llvm/CodeGenerator.kt | 23 +- .../kotlin/backend/konan/llvm/ContextUtils.kt | 31 +- .../kotlin/backend/konan/llvm/DebugUtils.kt | 4 +- .../kotlin/backend/konan/llvm/EntryPoint.kt | 2 +- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 241 ++++++++------- .../llvm/KotlinObjCClassInfoGenerator.kt | 58 ++-- .../backend/konan/llvm/LlvmDeclarations.kt | 96 +++--- .../backend/konan/llvm/RTTIGenerator.kt | 31 +- .../kotlin/backend/konan/llvm/StaticData.kt | 2 +- .../backend/konan/llvm/StaticObjects.kt | 47 ++- .../backend/konan/llvm/VariableManager.kt | 9 +- .../llvm/objcexport/BlockPointerSupport.kt | 18 +- .../objcexport/ObjCExportCodeGenerator.kt | 74 +++-- .../backend/konan/lower/BridgesBuilding.kt | 72 ++--- .../konan/lower/CallableReferenceLowering.kt | 70 +++-- .../lower/DeepCopyIrTreeWithDescriptors.kt | 10 +- .../lower/DefaultArgumentsStubGenerator.kt | 53 ++-- .../backend/konan/lower/DelegationLowering.kt | 19 +- .../backend/konan/lower/EnumClassLowering.kt | 26 +- .../backend/konan/lower/FunctionInlining.kt | 7 +- .../konan/lower/InitializersLowering.kt | 24 +- .../backend/konan/lower/InnerClassLowering.kt | 15 +- .../backend/konan/lower/InteropLowering.kt | 2 +- .../konan/lower/LocalDeclarationsLowering.kt | 25 +- .../konan/lower/SuspendFunctionsLowering.kt | 53 ++-- .../backend/konan/lower/TestProcessor.kt | 8 +- .../konan/objcexport/ObjCExportMapper.kt | 3 +- .../konan/optimizations/CallGraphBuilder.kt | 3 +- .../backend/konan/optimizations/DFGBuilder.kt | 166 +++++----- .../backend/konan/optimizations/DataFlowIR.kt | 52 ++-- .../konan/optimizations/Devirtualization.kt | 6 +- .../konan/optimizations/EscapeAnalysis.kt | 3 +- .../konan/serialization/DescriptorTable.kt | 225 +++++++++++++- .../konan/serialization/SerializeIr.kt | 4 + .../kotlin/ir/util/IrUnboundSymbolReplacer.kt | 94 +++--- .../org/jetbrains/kotlin/ir/util/IrUtils2.kt | 285 +++++++++++++++++- gradle.properties | 14 +- 52 files changed, 1948 insertions(+), 940 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/FakeIrUtils.kt create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrAsDescriptors.kt create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt index 3acfd3e36e2..69fd6e4b9a4 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt @@ -198,7 +198,7 @@ private class ExportedElement(val kind: ElementKind, isFunction -> { val function = declaration as FunctionDescriptor cname = "_konan_function_${owner.nextFunctionIndex()}" - val llvmFunction = owner.codegen.llvmFunction(function) + val llvmFunction = owner.codegen.llvmFunction(context.ir.getFromCurrentModule(function)) // If function is virtual, we need to resolve receiver properly. val bridge = if (!DescriptorUtils.isTopLevelDeclaration(function) && !function.isExtension && function.isOverridable) { @@ -207,7 +207,7 @@ private class ExportedElement(val kind: ElementKind, val receiver = param(0) val numParams = LLVMCountParams(llvmFunction) val args = (0..numParams - 1).map { index -> param(index) } - val callee = lookupVirtualImpl(receiver, function) + val callee = lookupVirtualImpl(receiver, context.ir.getFromCurrentModule(function)) val result = call(callee, args, exceptionHandler = ExceptionHandler.Caller, verbatim = true) ret(result) } @@ -223,14 +223,15 @@ private class ExportedElement(val kind: ElementKind, val builder = LLVMCreateBuilder()!! val bb = LLVMAppendBasicBlock(getTypeFunction, "")!! LLVMPositionBuilderAtEnd(builder, bb) - LLVMBuildRet(builder, (declaration as ClassDescriptor).typeInfoPtr.llvm) + LLVMBuildRet(builder, context.ir.getFromCurrentModule(declaration as ClassDescriptor).typeInfoPtr.llvm) LLVMDisposeBuilder(builder) } isEnumEntry -> { // Produce entry getter. cname = "_konan_function_${owner.nextFunctionIndex()}" generateFunction(owner.codegen, owner.kGetObjectFuncType, cname) { - val value = getEnumEntry(declaration as ClassDescriptor, ExceptionHandler.Caller) + val irEnumEntry = context.ir.getEnumEntryFromCurrentModule(declaration as ClassDescriptor) + val value = getEnumEntry(irEnumEntry, ExceptionHandler.Caller) ret(value) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index cd6a8f60d15..03f08b8b102 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.backend.konan.ir.KonanIr import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter import org.jetbrains.kotlin.backend.konan.library.LinkData import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl @@ -37,7 +38,9 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.SourceManager import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor +import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.endOffsetOrUndefined import org.jetbrains.kotlin.ir.util.startOffsetOrUndefined import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -48,7 +51,6 @@ import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import java.lang.System.out import kotlin.LazyThreadSafetyMode.PUBLICATION @@ -56,7 +58,7 @@ import kotlin.LazyThreadSafetyMode.PUBLICATION internal class SpecialDeclarationsFactory(val context: Context) { private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) } private val outerThisFields = mutableMapOf() - private val bridgesDescriptors = mutableMapOf, FunctionDescriptor>() + private val bridgesDescriptors = mutableMapOf, IrSimpleFunction>() private val loweredEnums = mutableMapOf() object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS : @@ -83,20 +85,31 @@ internal class SpecialDeclarationsFactory(val context: Context) { ) } - fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): FunctionDescriptor { - val descriptor = overriddenFunctionDescriptor.descriptor.original + fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): IrSimpleFunction { + val irFunction = overriddenFunctionDescriptor.descriptor + val descriptor = irFunction.descriptor assert(overriddenFunctionDescriptor.needBridge, { "Function $descriptor is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor}" }) val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections - return bridgesDescriptors.getOrPut(descriptor to bridgeDirections) { - SimpleFunctionDescriptorImpl.create( + return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) { + val newDescriptor = SimpleFunctionDescriptorImpl.create( /* containingDeclaration = */ descriptor.containingDeclaration, /* annotations = */ Annotations.EMPTY, - /* name = */ "${descriptor.functionName}".synthesizedName, + /* name = */ "${irFunction.functionName}".synthesizedName, /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, /* source = */ SourceElement.NO_SOURCE).apply { initializeBridgeDescriptor(this, descriptor, bridgeDirections.array) } + + IrFunctionImpl( + irFunction.startOffset, + irFunction.endOffset, + DECLARATION_ORIGIN_BRIDGE_METHOD, + newDescriptor + ).apply { + createParameterDeclarations() + this.parent = overriddenFunctionDescriptor.descriptor.parent + } } } @@ -169,9 +182,9 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { override val reflectionTypes: ReflectionTypes by lazy(PUBLICATION) { ReflectionTypes(moduleDescriptor, FqName("konan.internal")) } - private val vtableBuilders = mutableMapOf() + private val vtableBuilders = mutableMapOf() - fun getVtableBuilder(classDescriptor: ClassDescriptor) = vtableBuilders.getOrPut(classDescriptor) { + fun getVtableBuilder(classDescriptor: IrClass) = vtableBuilders.getOrPut(classDescriptor) { ClassVtablesBuilder(classDescriptor, this) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt index 24e638c225f..27889c008f6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt @@ -25,9 +25,8 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.* -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver @@ -43,7 +42,7 @@ internal object DECLARATION_ORIGIN_ENUM : internal data class LoweredEnum(val implObject: IrClass, val valuesField: IrField, val valuesGetter: IrSimpleFunction, - val itemGetterSymbol: IrFunctionSymbol, + val itemGetterSymbol: IrSimpleFunctionSymbol, val itemGetterDescriptor: FunctionDescriptor, val entriesMap: Map) @@ -74,7 +73,11 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) { val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor).apply { createParameterDeclarations() addFakeOverrides() + setSuperSymbols(listOf(context.ir.symbols.any.owner)) } + implObject.parent = context.ir.getEnum(enumClassDescriptor) + valuesGetter.parent = implObject + valuesField.parent = implObject val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor) @@ -114,10 +117,9 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) { false, false, false, false, false, false).initialize(valuesArrayType, dispatchReceiverParameter = receiver) } - private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin")) private val genericArrayType = context.ir.symbols.array.descriptor - private fun getEnumItemGetter(enumClassDescriptor: ClassDescriptor): Pair { + private fun getEnumItemGetter(enumClassDescriptor: ClassDescriptor): Pair { val getter = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") } val typeParameterT = genericArrayType.declaredTypeParameters[0] diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt index 3e75f86d85b..04904d66a5c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt @@ -90,7 +90,7 @@ fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironme phaser.phase(KonanPhase.BACKEND) { phaser.phase(KonanPhase.LOWER) { KonanLower(context).lower() - validateIrModule(context, context.ir.irModule) +// validateIrModule(context, context.ir.irModule) // Temporarily disabled until moving to new IR finished. context.ir.moduleIndexForCodegen = ModuleIndex(context.ir.irModule) } phaser.phase(KonanPhase.BITCODE) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt index 79d9d80af94..8e4b38fdacb 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt @@ -18,8 +18,8 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.common.lower.* -import org.jetbrains.kotlin.backend.common.validateIrFile import org.jetbrains.kotlin.backend.common.validateIrModule +import org.jetbrains.kotlin.backend.konan.irasdescriptors.referenceAllTypeExternalClassifiers import org.jetbrains.kotlin.backend.konan.lower.* import org.jetbrains.kotlin.backend.konan.lower.DefaultArgumentStubGenerator import org.jetbrains.kotlin.backend.konan.lower.DefaultParameterInjector @@ -27,18 +27,24 @@ import org.jetbrains.kotlin.backend.konan.lower.LateinitLowering import org.jetbrains.kotlin.backend.konan.lower.LocalDeclarationsLowering import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.util.checkDeclarationParents +import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.ir.util.replaceUnboundSymbols internal class KonanLower(val context: Context) { fun lower() { + val irModule = context.irModule!! + // Phases to run against whole module. - lowerModule(context.irModule!!) + lowerModule(irModule) // Phases to run against a file. - context.irModule!!.files.forEach { + irModule.files.forEach { lowerFile(it) } + + irModule.checkDeclarationParents() } private fun lowerModule(irModule: IrModuleFragment) { @@ -73,8 +79,17 @@ internal class KonanLower(val context: Context) { irModule.files.forEach(LateinitLowering(context)::lower) } - @Suppress("DEPRECATION") - irModule.replaceUnboundSymbols(context) + val symbolTable = context.ir.symbols.symbolTable + irModule.referenceAllTypeExternalClassifiers(symbolTable) + + do { + @Suppress("DEPRECATION") + irModule.replaceUnboundSymbols(context) + irModule.referenceAllTypeExternalClassifiers(symbolTable) + } while (symbolTable.unboundClasses.isNotEmpty()) + + irModule.patchDeclarationParents() + validateIrModule(context, irModule) } @@ -144,7 +159,7 @@ internal class KonanLower(val context: Context) { WorkersBridgesBuilding(context).lower(irFile) } phaser.phase(KonanPhase.AUTOBOX) { - validateIrFile(context, irFile) + // validateIrFile(context, irFile) // Temporarily disabled until moving to new IR finished. Autoboxing(context).lower(irFile) } phaser.phase(KonanPhase.RETURNS_INSERTION) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPlatform.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPlatform.kt index e6a6046b541..ed58e9db013 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPlatform.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPlatform.kt @@ -80,3 +80,8 @@ object KonanPlatform : TargetPlatform("Konan") { override val platformConfigurator: PlatformConfigurator = KonanPlatformConfigurator } + +/** + * Maximum number of parameters supported in function types (e.g. `FunctionXX`, `KFunctionXX`, `SuspendFunctionXX`). + */ +internal const val KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS = 22 diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt index b780264bfa6..ed0d18753fd 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt @@ -17,19 +17,14 @@ package org.jetbrains.kotlin.backend.konan.descriptors import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.localHash -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.OverridingUtil -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny -internal val FunctionDescriptor.canBeCalledVirtually: Boolean - // We check that either method is open, or one of declarations it overrides is open. - get() = isOverridable || DescriptorUtils.getAllOverriddenDeclarations(this).any { it.isOverridable } - -internal class OverriddenFunctionDescriptor(val descriptor: FunctionDescriptor, overriddenDescriptor: FunctionDescriptor) { +internal class OverriddenFunctionDescriptor( + val descriptor: SimpleFunctionDescriptor, + overriddenDescriptor: SimpleFunctionDescriptor +) { val overriddenDescriptor = overriddenDescriptor.original val needBridge: Boolean @@ -44,16 +39,15 @@ internal class OverriddenFunctionDescriptor(val descriptor: FunctionDescriptor, return descriptor.canObjCClassMethodBeCalledVirtually(this.overriddenDescriptor) } - // We check that either method is open, or one of declarations it overrides is open. - return overriddenDescriptor.canBeCalledVirtually + return overriddenDescriptor.isOverridable } val inheritsBridge: Boolean - get() = !descriptor.kind.isReal - && OverridingUtil.overrides(descriptor.target, overriddenDescriptor) + get() = !descriptor.isReal + && descriptor.target.overrides(overriddenDescriptor) && descriptor.bridgeDirectionsTo(overriddenDescriptor).allNotNeeded() - fun getImplementation(context: Context): FunctionDescriptor { + fun getImplementation(context: Context): SimpleFunctionDescriptor { val target = descriptor.target if (!needBridge) return target val bridgeOwner = if (inheritsBridge) { @@ -90,17 +84,18 @@ internal class ClassVtablesBuilder(val classDescriptor: ClassDescriptor, val con assert(!classDescriptor.isInterface) - val superVtableEntries = if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(classDescriptor)) { + val superVtableEntries = if (classDescriptor.isSpecialClassWithNoSupertypes()) { emptyList() } else { - context.getVtableBuilder(classDescriptor.getSuperClassOrAny()).vtableEntries + val superClass = classDescriptor.getSuperClassNotAny() ?: context.ir.symbols.any.owner + context.getVtableBuilder(superClass).vtableEntries } val methods = classDescriptor.sortedContributedMethods val newVtableSlots = mutableListOf() val inheritedVtableSlots = superVtableEntries.map { superMethod -> - val overridingMethod = methods.singleOrNull { OverridingUtil.overrides(it, superMethod.descriptor) } + val overridingMethod = methods.singleOrNull { it.overrides(superMethod.descriptor) } if (overridingMethod == null) { superMethod } else { @@ -122,7 +117,7 @@ internal class ClassVtablesBuilder(val classDescriptor: ClassDescriptor, val con inheritedVtableSlots + filteredNewVtableSlots.sortedBy { it.overriddenDescriptor.functionName.localHash.value } } - fun vtableIndex(function: FunctionDescriptor): Int { + fun vtableIndex(function: SimpleFunctionDescriptor): Int { val bridgeDirections = function.target.bridgeDirectionsTo(function.original) val index = vtableEntries.indexOfFirst { it.descriptor == function.original && it.bridgeDirections == bridgeDirections } if (index < 0) throw Error(function.toString() + " not in vtable of " + classDescriptor.toString()) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index 08753c89b15..c7616a1c1d8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -16,27 +16,18 @@ package org.jetbrains.kotlin.backend.konan.descriptors -import org.jetbrains.kotlin.backend.common.atMostOne -import org.jetbrains.kotlin.backend.konan.KonanBuiltIns +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.isValueType import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.localHash -import org.jetbrains.kotlin.backend.konan.llvm.isExported -import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor -import org.jetbrains.kotlin.builtins.getFunctionalClassKind -import org.jetbrains.kotlin.builtins.isFunctionType -import org.jetbrains.kotlin.builtins.isSuspendFunctionType -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.util.simpleFunctions import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.OverridingUtil -import org.jetbrains.kotlin.resolve.descriptorUtil.* -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.SimpleType import org.jetbrains.kotlin.types.typeUtil.isUnit -import org.jetbrains.kotlin.util.OperatorNameConventions /** * List of all implemented interfaces (including those which implemented by a super class) @@ -48,7 +39,7 @@ internal val ClassDescriptor.implementedInterfaces: List val superInterfacesImplementedInterfaces = superInterfaces.flatMap { it.implementedInterfaces } return (superClassImplementedInterfaces + superInterfacesImplementedInterfaces + - superInterfaces).distinctBy { it.classId } + superInterfaces).distinct() } @@ -57,21 +48,19 @@ internal val ClassDescriptor.implementedInterfaces: List * * TODO: this method is actually a part of resolve and probably duplicates another one */ -internal fun T.resolveFakeOverride(): T { - if (this.kind.isReal) { +internal tailrec fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction { + if (this.isReal) { return this } else { - val overridden = OverridingUtil.getOverriddenDeclarations(this) - val filtered = OverridingUtil.filterOutOverridden(overridden) - // TODO: is it correct to take first? - @Suppress("UNCHECKED_CAST") - return filtered.first { it.modality != Modality.ABSTRACT } as T + return overriddenSymbols + .firstOrNull { it.owner.modality != Modality.ABSTRACT }!! + .owner.resolveFakeOverride() } } private val intrinsicAnnotation = FqName("konan.internal.Intrinsic") -internal val CallableDescriptor.isIntrinsic: Boolean +internal val FunctionDescriptor.isIntrinsic: Boolean get() = this.annotations.hasAnnotation(intrinsicAnnotation) private val intrinsicTypes = setOf( @@ -81,7 +70,7 @@ private val intrinsicTypes = setOf( "kotlin.Float", "kotlin.Double" ) -private val arrayTypes = setOf( +internal val arrayTypes = setOf( "kotlin.Array", "kotlin.ByteArray", "kotlin.CharArray", @@ -105,82 +94,20 @@ internal val ClassDescriptor.isArray: Boolean internal val ClassDescriptor.isInterface: Boolean get() = (this.kind == ClassKind.INTERFACE) -private val konanInternalPackageName = FqName.fromSegments(listOf("konan", "internal")) - -/** - * @return `konan.internal` member scope - */ -internal val KonanBuiltIns.konanInternal: MemberScope - get() = this.builtInsModule.getPackage(konanInternalPackageName).memberScope - -internal val KotlinType.isKFunctionType: Boolean - get() { - val kind = constructor.declarationDescriptor?.getFunctionalClassKind() - return kind == FunctionClassDescriptor.Kind.KFunction - } - -internal val FunctionDescriptor.isFunctionInvoke: Boolean - get() { - val dispatchReceiver = dispatchReceiverParameter ?: return false - assert(!dispatchReceiver.type.isKFunctionType) - - return dispatchReceiver.type.isFunctionType && - this.isOperator && this.name == OperatorNameConventions.INVOKE - } - -internal val FunctionDescriptor.isSuspendFunctionInvoke: Boolean - get() { - val dispatchReceiver = dispatchReceiverParameter - ?: return false - - return dispatchReceiver.type.isSuspendFunctionType && - this.isOperator && this.name == OperatorNameConventions.INVOKE - } - -internal fun ClassDescriptor.isUnit() = this.defaultType.isUnit() - -internal val T.allOverriddenDescriptors: List - get() { - val result = mutableListOf() - fun traverse(descriptor: T) { - result.add(descriptor) - @Suppress("UNCHECKED_CAST") - descriptor.overriddenDescriptors.forEach { traverse(it as T) } - } - traverse(this) - return result - } - -internal val ClassDescriptor.sortedContributedMethods: List - get () = unsubstitutedMemberScope.sortedContributedMethods - -internal val ClassDescriptor.contributedMethods: List - get () = unsubstitutedMemberScope.contributedMethods - -internal val MemberScope.sortedContributedMethods: List +internal val IrClass.sortedContributedMethods: List get () = contributedMethods.sortedBy { it.functionName.localHash.value } -internal val MemberScope.contributedMethods: List - get () { - val contributedDescriptors = this.getContributedDescriptors() - - val functions = contributedDescriptors.filterIsInstance() - - val properties = contributedDescriptors.filterIsInstance() - val getters = properties.mapNotNull { it.getter } - val setters = properties.mapNotNull { it.setter } - - return functions + getters + setters - } +internal val IrClass.contributedMethods: List + get () = this.simpleFunctions() fun ClassDescriptor.isAbstract() = this.modality == Modality.SEALED || this.modality == Modality.ABSTRACT || this.kind == ClassKind.ENUM_CLASS internal fun FunctionDescriptor.hasValueTypeAt(index: Int): Boolean { when (index) { - 0 -> return !isSuspend && returnType.let { it != null && (it.isValueType() || it.isUnit()) } + 0 -> return !isSuspend && returnType.let { (it.isValueType() || it.isUnit()) } 1 -> return extensionReceiverParameter.let { it != null && it.type.isValueType() } else -> return this.valueParameters[index - 2].type.isValueType() } @@ -188,7 +115,7 @@ internal fun FunctionDescriptor.hasValueTypeAt(index: Int): Boolean { internal fun FunctionDescriptor.hasReferenceAt(index: Int): Boolean { when (index) { - 0 -> return isSuspend || returnType.let { it != null && !it.isValueType() && !it.isUnit() } + 0 -> return isSuspend || returnType.let { !it.isValueType() && !it.isUnit() } 1 -> return extensionReceiverParameter.let { it != null && !it.type.isValueType() } else -> return !this.valueParameters[index - 2].type.isValueType() } @@ -200,9 +127,15 @@ private fun FunctionDescriptor.needBridgeToAt(target: FunctionDescriptor, index: internal fun FunctionDescriptor.needBridgeTo(target: FunctionDescriptor) = (0..this.valueParameters.size + 1).any { needBridgeToAt(target, it) } -internal val FunctionDescriptor.target: FunctionDescriptor +internal val SimpleFunctionDescriptor.target: SimpleFunctionDescriptor get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride()).original +internal val FunctionDescriptor.target: FunctionDescriptor get() = when (this) { + is SimpleFunctionDescriptor -> this.target + is ConstructorDescriptor -> this + else -> error(this) +} + internal enum class BridgeDirection { NOT_NEEDED, FROM_VALUE_TYPE, @@ -248,14 +181,31 @@ internal class BridgeDirections(val array: Array) { } } -internal fun FunctionDescriptor.bridgeDirectionsTo(overriddenDescriptor: FunctionDescriptor): BridgeDirections { +val SimpleFunctionDescriptor.allOverriddenDescriptors: Set + get() { + val result = mutableSetOf() + + fun traverse(function: SimpleFunctionDescriptor) { + if (function in result) return + result += function + function.overriddenSymbols.forEach { traverse(it.owner) } + } + + traverse(this) + + return result + } + +internal fun SimpleFunctionDescriptor.bridgeDirectionsTo( + overriddenDescriptor: SimpleFunctionDescriptor +): BridgeDirections { val ourDirections = BridgeDirections(this.valueParameters.size) for (index in ourDirections.array.indices) ourDirections.array[index] = this.bridgeDirectionToAt(overriddenDescriptor, index) val target = this.target - if (!kind.isReal && modality != Modality.ABSTRACT - && OverridingUtil.overrides(target, overriddenDescriptor) + if (!this.isReal && modality != Modality.ABSTRACT + && target.overrides(overriddenDescriptor) && ourDirections == target.bridgeDirectionsTo(overriddenDescriptor)) { // Bridge is inherited from superclass. return BridgeDirections(this.valueParameters.size) @@ -265,82 +215,10 @@ internal fun FunctionDescriptor.bridgeDirectionsTo(overriddenDescriptor: Functio } tailrec internal fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor { - return if (this is PackageFragmentDescriptor) this - else this.containingDeclaration!!.findPackage() + val parent = this.parent + return parent as? PackageFragmentDescriptor + ?: (parent as DeclarationDescriptor).findPackage() } -internal fun DeclarationDescriptor.allContainingDeclarations(): List { - var list = mutableListOf() - var current = this.containingDeclaration - while (current != null) { - list.add(current) - current = current.containingDeclaration - } - return list -} - -internal fun DeclarationDescriptor.getMemberScope(): MemberScope { - val containingScope = when (this) { - is ClassDescriptor -> this.unsubstitutedMemberScope - is PackageViewDescriptor -> this.memberScope - else -> error("Unexpected member scope: $containingDeclaration") - } - return containingScope -} - -// It is possible to declare "external inline fun", -// but it doesn't have much sense for native, -// since externals don't have IR bodies. -// Enforce inlining of constructors annotated with @InlineConstructor. - -private val inlineConstructor = FqName("konan.internal.InlineConstructor") - -internal val FunctionDescriptor.needsInlining: Boolean - get() { - val inlineConstructor = annotations.hasAnnotation(inlineConstructor) - if (inlineConstructor) return true - return (this.isInline && !this.isExternal && !this.propertyIfAccessor.isIntrinsic) - } - -internal val FunctionDescriptor.needsSerializedIr: Boolean - get() = (this.needsInlining && this.isExported()) - -fun AnnotationDescriptor.getStringValueOrNull(name: String): String? { - val constantValue = this.allValueArguments.entries.atMostOne { - it.key.asString() == name - }?.value - return constantValue?.value as String? -} - -fun AnnotationDescriptor.getStringValue(name: String): String = this.getStringValueOrNull(name)!! - -private fun getPackagesFqNames(module: ModuleDescriptor): Set { - val result = mutableSetOf() - - fun getSubPackages(fqName: FqName) { - result.add(fqName) - module.getSubPackagesOf(fqName) { true }.forEach { getSubPackages(it) } - } - - getSubPackages(FqName.ROOT) - return result -} - -fun ModuleDescriptor.getPackageFragments(): List = - getPackagesFqNames(this).flatMap { - getPackage(it).fragments.filter { it.module == this } - } - -val ClassDescriptor.enumEntries: List - get() { - assert(this.kind == ClassKind.ENUM_CLASS) - return this.unsubstitutedMemberScope.getContributedDescriptors() - .filterIsInstance() - .filter { it.kind == ClassKind.ENUM_ENTRY } - } - -internal val DeclarationDescriptor.isExpectMember: Boolean - get() = this is MemberDescriptor && this.isExpect - fun FunctionDescriptor.isComparisonDescriptor(map: Map): Boolean = - map.values.any { it.descriptor == this } \ No newline at end of file + this in map.values diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt new file mode 100644 index 00000000000..4f2ca5ee218 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt @@ -0,0 +1,187 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan.descriptors + +import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.konan.KonanBuiltIns +import org.jetbrains.kotlin.backend.konan.serialization.isExported +import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor +import org.jetbrains.kotlin.builtins.getFunctionalClassKind +import org.jetbrains.kotlin.builtins.isFunctionType +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.OverridingUtil +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.typeUtil.isUnit +import org.jetbrains.kotlin.util.OperatorNameConventions + + +/** + * Implementation of given method. + * + * TODO: this method is actually a part of resolve and probably duplicates another one + */ +internal fun T.resolveFakeOverride(): T { + if (this.kind.isReal) { + return this + } else { + val overridden = OverridingUtil.getOverriddenDeclarations(this) + val filtered = OverridingUtil.filterOutOverridden(overridden) + // TODO: is it correct to take first? + @Suppress("UNCHECKED_CAST") + return filtered.first { it.modality != Modality.ABSTRACT } as T + } +} + +internal val ClassDescriptor.isArray: Boolean + get() = this.fqNameSafe.asString() in arrayTypes + + +internal val ClassDescriptor.isInterface: Boolean + get() = (this.kind == ClassKind.INTERFACE) + +private val konanInternalPackageName = FqName.fromSegments(listOf("konan", "internal")) + +/** + * @return `konan.internal` member scope + */ +internal val KonanBuiltIns.konanInternal: MemberScope + get() = this.builtInsModule.getPackage(konanInternalPackageName).memberScope + +internal val KotlinType.isKFunctionType: Boolean + get() { + val kind = constructor.declarationDescriptor?.getFunctionalClassKind() + return kind == FunctionClassDescriptor.Kind.KFunction + } + +internal val FunctionDescriptor.isFunctionInvoke: Boolean + get() { + val dispatchReceiver = dispatchReceiverParameter ?: return false + assert(!dispatchReceiver.type.isKFunctionType) + + return dispatchReceiver.type.isFunctionType && + this.isOperator && this.name == OperatorNameConventions.INVOKE + } + +internal fun ClassDescriptor.isUnit() = this.defaultType.isUnit() + +internal val T.allOverriddenDescriptors: List + get() { + val result = mutableListOf() + fun traverse(descriptor: T) { + result.add(descriptor) + @Suppress("UNCHECKED_CAST") + descriptor.overriddenDescriptors.forEach { traverse(it as T) } + } + traverse(this) + return result + } + +internal val ClassDescriptor.contributedMethods: List + get () = unsubstitutedMemberScope.contributedMethods + +internal val MemberScope.contributedMethods: List + get () { + val contributedDescriptors = this.getContributedDescriptors() + + val functions = contributedDescriptors.filterIsInstance() + + val properties = contributedDescriptors.filterIsInstance() + val getters = properties.mapNotNull { it.getter } + val setters = properties.mapNotNull { it.setter } + + return functions + getters + setters + } + +fun ClassDescriptor.isAbstract() = this.modality == Modality.SEALED || this.modality == Modality.ABSTRACT + || this.kind == ClassKind.ENUM_CLASS + +internal val FunctionDescriptor.target: FunctionDescriptor + get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride()).original + +tailrec internal fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor { + return if (this is PackageFragmentDescriptor) this + else this.containingDeclaration!!.findPackage() +} + +internal fun DeclarationDescriptor.allContainingDeclarations(): List { + var list = mutableListOf() + var current = this.containingDeclaration + while (current != null) { + list.add(current) + current = current.containingDeclaration + } + return list +} + +// It is possible to declare "external inline fun", +// but it doesn't have much sense for native, +// since externals don't have IR bodies. +// Enforce inlining of constructors annotated with @InlineConstructor. + +private val inlineConstructor = FqName("konan.internal.InlineConstructor") + +internal val FunctionDescriptor.needsInlining: Boolean + get() { + val inlineConstructor = annotations.hasAnnotation(inlineConstructor) + if (inlineConstructor) return true + return (this.isInline && !this.isExternal) + } + +internal val FunctionDescriptor.needsSerializedIr: Boolean + get() = (this.needsInlining && this.isExported()) + +fun AnnotationDescriptor.getStringValueOrNull(name: String): String? { + val constantValue = this.allValueArguments.entries.atMostOne { + it.key.asString() == name + }?.value + return constantValue?.value as String? +} + +fun AnnotationDescriptor.getStringValue(name: String): String = this.getStringValueOrNull(name)!! + +private fun getPackagesFqNames(module: ModuleDescriptor): Set { + val result = mutableSetOf() + + fun getSubPackages(fqName: FqName) { + result.add(fqName) + module.getSubPackagesOf(fqName) { true }.forEach { getSubPackages(it) } + } + + getSubPackages(FqName.ROOT) + return result +} + +fun ModuleDescriptor.getPackageFragments(): List = + getPackagesFqNames(this).flatMap { + getPackage(it).fragments.filter { it.module == this } + } + +val ClassDescriptor.enumEntries: List + get() { + assert(this.kind == ClassKind.ENUM_CLASS) + return this.unsubstitutedMemberScope.getContributedDescriptors() + .filterIsInstance() + .filter { it.kind == ClassKind.ENUM_ENTRY } + } + +internal val DeclarationDescriptor.isExpectMember: Boolean + get() = this is MemberDescriptor && this.isExpect diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index 971d9bdbadb..46faebdd3c1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -20,23 +20,22 @@ import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Symbols import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS import org.jetbrains.kotlin.backend.konan.ValueType -import org.jetbrains.kotlin.backend.konan.descriptors.getMemberScope +import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint import org.jetbrains.kotlin.backend.konan.lower.TestProcessor import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.isFunctionType -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType import kotlin.properties.Delegates @@ -51,10 +50,56 @@ internal class KonanIr(context: Context, irModule: IrModuleFragment): Ir(context, symbolTable) { + val entryPoint = findMainEntryPoint(context)?.let { symbolTable.referenceSimpleFunction(it) } + + val nothing = symbolTable.referenceClass(builtIns.nothing) + val throwable = symbolTable.referenceClass(builtIns.throwable) + val string = symbolTable.referenceClass(builtIns.string) + + val arrayList = symbolTable.referenceClass(getArrayListClassDescriptor(context)) + val interopNativePointedGetRawPointer = symbolTable.referenceSimpleFunction(context.interopBuiltIns.nativePointedGetRawPointer) @@ -83,6 +128,15 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym val interopInterpretObjCPointerOrNull = symbolTable.referenceSimpleFunction(context.interopBuiltIns.interpretObjCPointerOrNull) + val interopCreateNSStringFromKString = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.CreateNSStringFromKString) + + val objCPointerHolder = symbolTable.referenceClass(context.interopBuiltIns.objCPointerHolder) + val objCPointerHolderValueGetter = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.objCPointerHolderValue.getter!!) + + val allocObjCObject = symbolTable.referenceSimpleFunction(context.interopBuiltIns.allocObjCObject) + val getNativeNullPtr = symbolTable.referenceSimpleFunction(context.builtIns.getNativeNullPtr) val boxFunctions = ValueType.values().associate { @@ -97,7 +151,7 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym val valueClassToBox = ValueType.values().associate { val valueClassId = ClassId.topLevel(it.classFqName.toSafe()) val valueClassDescriptor = context.builtIns.builtInsModule.findClassAcrossModuleDependencies(valueClassId)!! - valueClassDescriptor to boxClasses[it]!! + symbolTable.referenceClass(valueClassDescriptor) to boxClasses[it]!! } val unboxFunctions = ValueType.values().mapNotNull { @@ -235,6 +289,15 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym .getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).single(predicate) ) + val functions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS) + .map { symbolTable.referenceClass(builtIns.getFunction(it)) } + + val kFunctions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS) + .map { symbolTable.referenceClass(context.reflectionTypes.getKFunction(it)) } + + val suspendFunctions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS) + .map { symbolTable.referenceClass(builtIns.getSuspendFunction(it)) } + val baseClassSuite = getKonanTestClass("BaseClassSuite") val topLevelSuite = getKonanTestClass("TopLevelSuite") val testFunctionKind = getKonanTestClass("TestFunctionKind") @@ -267,8 +330,17 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym private val testFunctionKindCache = mutableMapOf() fun getTestFunctionKind(kind: TestProcessor.FunctionKind): IrEnumEntrySymbol = testFunctionKindCache.getOrPut(kind) { - symbolTable.referenceEnumEntry(testFunctionKind.descriptor.getMemberScope().getContributedClassifier( + symbolTable.referenceEnumEntry(testFunctionKind.descriptor.unsubstitutedMemberScope.getContributedClassifier( kind.runtimeKindName, NoLookupLocation.FROM_BACKEND ) as ClassDescriptor) } -} \ No newline at end of file +} + +private fun getArrayListClassDescriptor(context: Context): ClassDescriptor { + val module = context.builtIns.builtInsModule + val pkg = module.getPackage(FqName.fromSegments(listOf("kotlin", "collections"))) + val classifier = pkg.memberScope.getContributedClassifier(Name.identifier("ArrayList"), + NoLookupLocation.FROM_BACKEND) + + return classifier as ClassDescriptor +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/ModuleIndex.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/ModuleIndex.kt index f21fd9c1717..30bdf5d8b9b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/ModuleIndex.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/ModuleIndex.kt @@ -33,6 +33,8 @@ class ModuleIndex(val module: IrModuleFragment) { */ val classes: Map + val enumEntries: Map + /** * Contains all functions declared in [module] */ @@ -41,6 +43,7 @@ class ModuleIndex(val module: IrModuleFragment) { init { val map = mutableMapOf() + enumEntries = mutableMapOf() module.acceptVoid(object : IrElementVisitorVoid { override fun visitElement(element: IrElement) { @@ -58,6 +61,12 @@ class ModuleIndex(val module: IrModuleFragment) { map[declaration.descriptor] = declaration } + override fun visitEnumEntry(declaration: IrEnumEntry) { + super.visitEnumEntry(declaration) + + enumEntries[declaration.descriptor] = declaration + } + override fun visitFunction(declaration: IrFunction) { super.visitFunction(declaration) functions[declaration.descriptor] = declaration diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/FakeIrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/FakeIrUtils.kt new file mode 100644 index 00000000000..fc0027c9b98 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/FakeIrUtils.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan.irasdescriptors + +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.llvm.llvmSymbolOrigin +import org.jetbrains.kotlin.idea.MainFunctionDetector +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrCatch +import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.module + +// This file contains some IR utilities which actually use descriptors. +// TODO: port this code to IR. + +internal val IrDeclaration.annotations get() = this.descriptor.annotations +internal val IrDeclaration.isAnonymousObject get() = DescriptorUtils.isAnonymousObject(this.descriptor) +internal val IrFunction.isExternal get() = this.descriptor.isExternal +internal val IrDeclaration.isLocal get() = DescriptorUtils.isLocal(this.descriptor) + +internal val IrDeclaration.module get() = this.descriptor.module + +@Deprecated("Do not call this method in the compiler front-end.") +internal val IrField.isDelegate get() = @Suppress("DEPRECATION") this.descriptor.isDelegated + +internal fun IrFunction.getObjCMethodInfo() = this.descriptor.getObjCMethodInfo() +internal fun IrClass.isExternalObjCClass() = this.descriptor.isExternalObjCClass() +internal fun IrClass.isKotlinObjCClass() = this.descriptor.isKotlinObjCClass() +internal fun IrConstructor.getObjCInitMethod() = this.descriptor.getObjCInitMethod() +internal fun IrFunction.getExternalObjCMethodInfo() = this.descriptor.getExternalObjCMethodInfo() +internal fun IrFunction.isObjCClassMethod() = this.descriptor.isObjCClassMethod() +internal fun IrFunction.canObjCClassMethodBeCalledVirtually(overridden: IrFunction) = + this.descriptor.canObjCClassMethodBeCalledVirtually(overridden.descriptor) +internal fun IrClass.isObjCClass() = this.descriptor.isObjCClass() +internal fun IrFunction.isExternalObjCClassMethod() = this.descriptor.isExternalObjCClassMethod() + +internal val IrDeclaration.llvmSymbolOrigin get() = this.descriptor.llvmSymbolOrigin + +internal fun IrFunction.isMain() = MainFunctionDetector.isMain(this.descriptor) + +internal fun IrTypeOperatorCall.getTypeOperandClass(context: Context): IrClass? = + context.ir.getClass(this.typeOperand) + +internal fun IrCatch.getCatchParameterTypeClass(context: Context): IrClass? = + context.ir.getClass(this.catchParameter.type) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrAsDescriptors.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrAsDescriptors.kt new file mode 100644 index 00000000000..b982e51befe --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/IrAsDescriptors.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan.irasdescriptors + +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol + +internal typealias DeclarationDescriptor = IrDeclaration +internal typealias FunctionDescriptor = IrFunction +internal typealias SimpleFunctionDescriptor = IrSimpleFunction +internal typealias ClassDescriptor = IrClass +internal typealias ConstructorDescriptor = IrConstructor +internal typealias ClassConstructorDescriptor = IrConstructor +internal typealias PackageFragmentDescriptor = IrPackageFragment +internal typealias VariableDescriptor = IrVariable +internal typealias ValueDescriptor = IrSymbolDeclaration +internal typealias ParameterDescriptor = IrValueParameter diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt new file mode 100644 index 00000000000..d14dd535db6 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt @@ -0,0 +1,234 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan.irasdescriptors + +import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.konan.descriptors.backingField +import org.jetbrains.kotlin.backend.konan.descriptors.isInterface +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression +import org.jetbrains.kotlin.ir.expressions.getTypeArgumentOrDefault +import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils + +val IrConstructor.constructedClass get() = this.parent as IrClass + +val T.original get() = this +val IrDeclaration.containingDeclaration get() = this.parent + +val IrDeclarationParent.fqNameSafe: FqName get() = when (this) { + is IrPackageFragment -> this.fqName + is IrDeclaration -> this.parent.fqNameSafe.child(this.name) + + else -> error(this) +} + +val IrDeclaration.name: Name + get() = when (this) { + is IrSimpleFunction -> this.name + is IrClass -> this.name + is IrEnumEntry -> this.name + is IrProperty -> this.name + is IrLocalDelegatedProperty -> this.name + is IrField -> this.name + is IrVariable -> this.name + is IrConstructor -> SPECIAL_INIT_NAME + is IrValueParameter -> this.name + else -> error(this) + } + +private val SPECIAL_INIT_NAME = Name.special("") + +val IrField.fqNameSafe: FqName get() = this.parent.fqNameSafe.child(this.name) + +/** + * @return naturally-ordered list of all parameters available inside the function body. + */ +val IrFunction.allParameters: List + get() = if (this is IrConstructor) { + listOf(this.constructedClass.thisReceiver + ?: error(this.descriptor) + ) + explicitParameters + } else { + explicitParameters + } + +/** + * @return naturally-ordered list of the parameters that can have values specified at call site. + */ +val IrFunction.explicitParameters: List + get() { + val result = ArrayList(valueParameters.size + 2) + + this.dispatchReceiverParameter?.let { + result.add(it) + } + + this.extensionReceiverParameter?.let { + result.add(it) + } + + result.addAll(valueParameters) + + return result + } + +val IrValueParameter.isVararg get() = this.varargElementType != null + +val IrFunction.isSuspend get() = this is IrSimpleFunction && this.isSuspend + +fun IrClass.isUnit() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.unit.toSafe() + +fun IrClass.getSuperClassNotAny() = this.superClasses.map { it.owner }.atMostOne { !it.isInterface && !it.isAny() } + +fun IrClass.isAny() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.any.toSafe() +fun IrClass.isNothing() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.nothing.toSafe() + +fun IrClass.getSuperInterfaces() = this.superClasses.map { it.owner }.filter { it.isInterface } + +val IrProperty.konanBackingField: IrField? + get() { + this.backingField?.let { return it } + + (this.descriptor as? DeserializedPropertyDescriptor)?.backingField?.let { backingFieldDescriptor -> + val result = IrFieldImpl( + this.startOffset, + this.endOffset, + IrDeclarationOrigin.PROPERTY_BACKING_FIELD, + backingFieldDescriptor + ).also { + it.parent = this.parent + } + this.backingField = result + return result + } + + return null + } + +val IrClass.defaultType: KotlinType + get() = this.thisReceiver!!.type + +val IrField.containingClass get() = this.parent as? IrClass + +val IrFunction.isReal get() = this.origin != IrDeclarationOrigin.FAKE_OVERRIDE + +val IrSimpleFunction.isOverridable: Boolean + get() = visibility != Visibilities.PRIVATE + && modality != Modality.FINAL + && (parent as? IrClass)?.isFinalClass != true + +val IrFunction.isOverridable get() = this is IrSimpleFunction && this.isOverridable + +val IrFunction.isOverridableOrOverrides + get() = this is IrSimpleFunction && (this.isOverridable || this.overriddenSymbols.isNotEmpty()) + +val IrClass.isFinalClass: Boolean + get() = modality == Modality.FINAL && kind != ClassKind.ENUM_CLASS + +fun IrSimpleFunction.overrides(other: IrSimpleFunction): Boolean { + if (this == other) return true + + this.overriddenSymbols.forEach { + if (it.owner.overrides(other)) { + return true + } + } + + return false +} + +fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing() + +val IrClass.constructors get() = this.declarations.filterIsInstance() + +internal val IrValueParameter.isValueParameter get() = this.index >= 0 + +fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTable) { + val moduleDescriptor = this.descriptor + + fun KotlinType.referenceAllClassifiers() { + TypeUtils.getClassDescriptor(this)?.let { + if (it.module != moduleDescriptor) { + if (it.kind == ClassKind.ENUM_ENTRY) { + symbolTable.referenceEnumEntry(it) + } else { + symbolTable.referenceClass(it) + } + } + } + + this.constructor.supertypes.forEach { + it.referenceAllClassifiers() + } + } + + val visitor = object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitValueParameter(declaration: IrValueParameter) { + super.visitValueParameter(declaration) + declaration.type.referenceAllClassifiers() + } + + override fun visitVariable(declaration: IrVariable) { + super.visitVariable(declaration) + declaration.type.referenceAllClassifiers() + } + + override fun visitExpression(expression: IrExpression) { + super.visitExpression(expression) + expression.type.referenceAllClassifiers() + } + + override fun visitFunction(declaration: IrFunction) { + super.visitFunction(declaration) + declaration.returnType.referenceAllClassifiers() + } + + override fun visitFunctionAccess(expression: IrFunctionAccessExpression) { + super.visitFunctionAccess(expression) + expression.descriptor.original.typeParameters.forEach { + expression.getTypeArgumentOrDefault(it).referenceAllClassifiers() + } + } + } + + this.acceptVoid(visitor) + this.dependencyModules.forEach { module -> + module.externalPackageFragments.forEach { + it.acceptVoid(visitor) + } + } +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt index 93d40747f8f..0840084bf3c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt @@ -17,26 +17,24 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.LLVMTypeRef -import org.jetbrains.kotlin.backend.common.descriptors.allParameters import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract -import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember -import org.jetbrains.kotlin.backend.konan.descriptors.isUnit -import org.jetbrains.kotlin.backend.konan.getObjCMethodInfo -import org.jetbrains.kotlin.backend.konan.isExternalObjCClass +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.isValueType import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.calls.components.isVararg import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty + // This file describes the ABI for Kotlin descriptors of exported declarations. // TODO: revise the naming scheme to ensure it produces unique names. // TODO: do not serialize descriptors of non-exported declarations. @@ -49,7 +47,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty * and so should be computable from the descriptor itself without checking a backend state. */ internal tailrec fun DeclarationDescriptor.isExported(): Boolean { - assert(!this.isExpectMember) { this } + // TODO: revise if (this.annotations.findAnnotation(symbolNameAnnotation) != null) { // Treat any `@SymbolName` declaration as exported. @@ -73,7 +71,7 @@ internal tailrec fun DeclarationDescriptor.isExported(): Boolean { return true } - if (DescriptorUtils.isAnonymousObject(this)) + if (this.isAnonymousObject) return false if (this is ConstructorDescriptor && constructedClass.kind.isSingleton) { @@ -82,19 +80,33 @@ internal tailrec fun DeclarationDescriptor.isExported(): Boolean { return constructedClass.isExported() } - if (this is PropertyAccessorDescriptor) { - return this.correspondingProperty.isExported() + if (this is IrFunction) { + val descriptor = this.descriptor + // TODO: this code is required because accessor doesn't have a reference to property. + if (descriptor is PropertyAccessorDescriptor) { + val property = descriptor.correspondingProperty + if (property.annotations.hasAnnotation(inlineExposedAnnotation) || + property.annotations.hasAnnotation(publishedApiAnnotation)) return true + } } - if (this is DeclarationDescriptorWithVisibility && !this.visibility.isPublicAPI) { + val visibility = when (this) { + is IrClass -> this.visibility + is IrFunction -> this.visibility + is IrProperty -> this.visibility + is IrField -> this.visibility + else -> null + } + + if (visibility != null && !visibility.isPublicAPI) { // If the declaration is explicitly marked as non-public, // then it must not be accessible from other modules. return false } - if (this is DeclarationDescriptorNonRoot) { - // If the declaration is not root, then check its container too. - return containingDeclaration.isExported() + val parent = this.parent + if (parent is IrDeclaration) { + return parent.isExported() } return true @@ -158,8 +170,8 @@ private val FunctionDescriptor.signature: String val signatureSuffix = when { this.typeParameters.isNotEmpty() -> "Generic" - returnType.let { it != null && it.isValueType() } -> "ValueType" - returnType.let { it != null && !KotlinBuiltIns.isUnitOrNullableUnit(it) } -> typeToHashString(returnType!!) + returnType.isValueType() -> "ValueType" + !KotlinBuiltIns.isUnitOrNullableUnit(returnType) -> typeToHashString(returnType) else -> "" } return "$extensionReceiverPart($argsPart)$signatureSuffix" @@ -188,7 +200,7 @@ internal val FunctionDescriptor.functionName: String internal val FunctionDescriptor.symbolName: String get() { if (!this.isExported()) { - throw AssertionError(this.toString()) + throw AssertionError(this.descriptor.toString()) } this.annotations.findAnnotation(symbolNameAnnotation)?.let { @@ -204,19 +216,20 @@ internal val FunctionDescriptor.symbolName: String return name // no wrapping currently required } - val containingDeclarationPart = containingDeclaration.fqNameSafe.let { + val parent = this.parent + + val containingDeclarationPart = parent.fqNameSafe.let { if (it.isRoot) "" else "$it." } return "kfun:$containingDeclarationPart$functionName" } -internal val PropertyDescriptor.symbolName: String +internal val IrField.symbolName: String get() { - val containingDeclarationPart = containingDeclaration.fqNameSafe.let { + val containingDeclarationPart = parent.fqNameSafe.let { if (it.isRoot) "" else "$it." } - val extensionReceiverPart = this.extensionReceiverParameter?.let { "${it.type}." } ?: "" - return "kprop:$containingDeclarationPart$extensionReceiverPart$name" + return "kprop:$containingDeclarationPart$name" } @@ -235,7 +248,7 @@ internal fun RuntimeAware.getLlvmFunctionType(function: FunctionDescriptor): LLV val returnType = when { original is ConstructorDescriptor -> voidType original.isSuspend -> kObjHeaderPtr // Suspend functions return Any?. - else -> getLLVMReturnType(original.returnType!!) + else -> getLLVMReturnType(original.returnType) } val paramTypes = ArrayList(original.allParameters.map { getLLVMType(it.type) }) if (original.isSuspend) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index 6ec55119464..7fff720874e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -21,14 +21,9 @@ import kotlinx.cinterop.* import llvm.* import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.isInterface -import org.jetbrains.kotlin.backend.konan.descriptors.isUnit import org.jetbrains.kotlin.backend.konan.descriptors.stdlibModule -import org.jetbrains.kotlin.backend.konan.isObjCClass -import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor -import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* internal class CodeGenerator(override val context: Context) : ContextUtils { @@ -70,7 +65,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { fun typeInfoForAllocation(constructedClass: ClassDescriptor): LLVMValueRef { val descriptorForTypeInfo = if (constructedClass.isObjCClass()) { - context.interopBuiltIns.objCPointerHolder + context.ir.symbols.objCPointerHolder.owner } else { constructedClass } @@ -549,7 +544,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, assert (typeInfoPtr.type == codegen.kTypeInfoPtr) { LLVMPrintTypeToString(typeInfoPtr.type)!!.toKString() } val llvmMethod = if (!owner.isInterface) { // If this is a virtual method of the class - we can call via vtable. - val index = context.getVtableBuilder(owner).vtableIndex(descriptor) + val index = context.getVtableBuilder(owner).vtableIndex(descriptor as SimpleFunctionDescriptor) val vtablePlace = gep(typeInfoPtr, Int32(1).llvm) // typeInfoPtr + 1 val vtable = bitcast(kInt8PtrPtr, vtablePlace) @@ -606,22 +601,20 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, /** * Note: the same code is generated as IR in [org.jetbrains.kotlin.backend.konan.lower.EnumUsageLowering]. */ - fun getEnumEntry(descriptor: ClassDescriptor, exceptionHandler: ExceptionHandler): LLVMValueRef { - assert(descriptor.kind == ClassKind.ENUM_ENTRY) - + fun getEnumEntry(descriptor: IrEnumEntry, exceptionHandler: ExceptionHandler): LLVMValueRef { val enumClassDescriptor = descriptor.containingDeclaration as ClassDescriptor - val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor) + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor.descriptor) val ordinal = loweredEnum.entriesMap[descriptor.name]!! val values = call( - loweredEnum.valuesGetter.descriptor.original.llvmFunction, + loweredEnum.valuesGetter.llvmFunction, emptyList(), Lifetime.ARGUMENT, exceptionHandler ) return call( - loweredEnum.itemGetterDescriptor.original.llvmFunction, + loweredEnum.itemGetterSymbol.owner.llvmFunction, listOf(values, Int32(ordinal).llvm), Lifetime.GLOBAL, exceptionHandler diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index 7f653f16a7d..885b7e7d19e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -22,22 +22,19 @@ import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.CurrentKonanModule import org.jetbrains.kotlin.backend.konan.descriptors.DeserializedKonanModule import org.jetbrains.kotlin.backend.konan.descriptors.LlvmSymbolOrigin +import org.jetbrains.kotlin.backend.konan.descriptors.findPackage import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.backend.konan.hash.GlobalHash +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.isNativeBinary import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl import org.jetbrains.kotlin.backend.konan.library.withResolvedDependencies -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor +import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.module -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty @@ -162,7 +159,14 @@ internal interface ContextUtils : RuntimeAware { val staticData: StaticData get() = context.llvm.staticData - fun isExternal(descriptor: DeclarationDescriptor) = descriptor.module != context.ir.irModule.descriptor + fun isExternal(descriptor: DeclarationDescriptor): Boolean { + val pkg = descriptor.findPackage() + return when (pkg) { + is IrFile -> false + is IrExternalPackageFragment -> true + else -> error(pkg) + } + } /** * LLVM function generated from the Kotlin function. @@ -170,10 +174,7 @@ internal interface ContextUtils : RuntimeAware { */ val FunctionDescriptor.llvmFunction: LLVMValueRef get() { - assert (this.kind.isReal) - if (this is TypeAliasConstructorDescriptor) { - return this.underlyingConstructorDescriptor.llvmFunction - } + assert (this.isReal) return if (isExternal(this)) { context.llvm.externalFunction(this.symbolName, getLlvmFunctionType(this), @@ -209,12 +210,6 @@ internal interface ContextUtils : RuntimeAware { val ClassDescriptor.llvmTypeInfoPtr: LLVMValueRef get() = typeInfoPtr.llvm - /** - * Pointer to type info for this type, or `null` if the type doesn't have corresponding type info. - */ - val KotlinType.typeInfoPtr: ConstPointer? - get() = TypeUtils.getClassDescriptor(this)?.typeInfoPtr - /** * Returns contents of this [GlobalHash]. * diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt index 173f36a9c2c..566931c3549 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt @@ -21,8 +21,8 @@ import kotlinx.cinterop.memScoped import llvm.* import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.KonanVersion +import org.jetbrains.kotlin.backend.konan.irasdescriptors.FunctionDescriptor import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.SourceManager.FileEntry import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName @@ -185,7 +185,7 @@ private fun debugInfoBaseType(context:Context, targetData:LLVMTargetDataRef, typ internal val FunctionDescriptor.types:List get() { val parameters = valueParameters.map{it.type} - return if (returnType != null) listOf(returnType!!, *parameters.toTypedArray()) else parameters + return listOf(returnType, *parameters.toTypedArray()) } internal fun KotlinType.size(context:Context) = context.debugInfo.llvmTypeSizes.getOrDefault(this, context.debugInfo.otherTypeSize) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt index db9f064e34c..1b3ff97ee7f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt @@ -52,7 +52,7 @@ internal fun findMainEntryPoint(context: Context): FunctionDescriptor? { it.returnType?.isUnit() == true && it.hasSingleArrayOfStringParameter && it.typeParameters.isEmpty() && - it.isExported() + it.visibility.isPublicAPI } if (main == null) { context.reportCompilationError("Could not find '$entryName' in '$packageName' package.") diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 0c46d8b4efa..4708624a179 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -19,39 +19,37 @@ package org.jetbrains.kotlin.backend.konan.llvm import kotlinx.cinterop.* import llvm.* import org.jetbrains.kotlin.backend.common.descriptors.allParameters -import org.jetbrains.kotlin.backend.common.descriptors.isSuspend import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport import org.jetbrains.kotlin.backend.konan.optimizations.* import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.config.CommonConfigurationKeys -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.SourceManager import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl -import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptorBase import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol +import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.util.getArguments import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType -import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.isUnit internal fun emitLLVM(context: Context) { @@ -153,7 +151,7 @@ internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid { override fun visitClass(declaration: IrClass) { super.visitClass(declaration) - val descriptor = declaration.descriptor + val descriptor = declaration if (descriptor.isIntrinsic) { // do not generate any code for intrinsic classes as they require special handling return @@ -181,7 +179,7 @@ internal interface CodeContext { * * @param value may be null iff target type is `Unit`. */ - fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) + fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) fun genBreak(destination: IrBreak) @@ -270,7 +268,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map?) { val initialization = evaluateExpression(it.initializer!!.expression) - val address = context.llvmDeclarations.forStaticField(it.descriptor).storage + val address = context.llvmDeclarations.forStaticField(it).storage storeAny(initialization, address) } } @@ -479,7 +477,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map function.getIrValueParameter(descriptor) - descriptor is ReceiverParameterDescriptor && function.extensionReceiverParameter?.descriptor == descriptor -> function.extensionReceiverParameter!! - descriptor is ReceiverParameterDescriptor && function.dispatchReceiverParameter?.descriptor == descriptor-> function.dispatchReceiverParameter!! - function.descriptor is ClassConstructorDescriptor && (function.descriptor as ClassConstructorDescriptor).constructedClass.thisAsReceiverParameter == descriptor-> IrValueParameterImpl(function.startOffset, function.startOffset, object: IrDeclarationOriginImpl("THIS"){}, descriptor) - else -> TODO() - } + val ir = descriptor val local = functionGenerationContext.vars.createParameter(descriptor, debugInfoIfNeeded(function, ir)) @@ -587,15 +567,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map = when (symbol) { + is IrVariableSymbol -> symbol.owner + is IrValueParameterSymbol -> symbol.owner + else -> error(symbol) + } + + return currentCodeContext.genGetValue(ir) } //-------------------------------------------------------------------------// @@ -1151,7 +1141,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map() @Suppress("UNCHECKED_CAST") @@ -1547,7 +1536,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map { val receiver = evaluateExpression(expression.extensionReceiver!!) val irConstructorCall = expression.getValueArgument(0) as IrCall - val constructorDescriptor = irConstructorCall.descriptor as ClassConstructorDescriptor + val constructorDescriptor = irConstructorCall.symbol.owner as ClassConstructorDescriptor val constructorArgs = evaluateExplicitArgs(irConstructorCall) val args = listOf(receiver) + constructorArgs callDirect(constructorDescriptor, args, Lifetime.IRRELEVANT) @@ -1641,7 +1632,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map - return delegatingConstructorCall(value.descriptor, args) + return delegatingConstructorCall(value.symbol.owner, args) else -> return evaluateFunctionCall(value as IrCall, args, resultLifetime(value)) @@ -1709,7 +1704,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map().single { it.name.asString() == "doResume" } private fun getContinuation(): LLVMValueRef { val caller = functionGenerationContext.functionDescriptor!! @@ -1791,13 +1786,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map, resultLifetime: Lifetime): LLVMValueRef { - val descriptor = callee.descriptor + val descriptor = callee.symbol.owner as IrFunction val argsWithContinuationIfNeeded = if (descriptor.isSuspend) args + getContinuation() @@ -1918,11 +1913,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map return evaluateOperatorCall (callee, argsWithContinuationIfNeeded) - is ConstructorDescriptor -> return evaluateConstructorCall (callee, argsWithContinuationIfNeeded) - else -> return evaluateSimpleFunctionCall( - descriptor, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifier) + when { + descriptor.origin == IrDeclarationOrigin.IR_BUILTINS_STUB -> + return evaluateOperatorCall(callee, argsWithContinuationIfNeeded) + + descriptor is ConstructorDescriptor -> return evaluateConstructorCall(callee, argsWithContinuationIfNeeded) + + else -> return evaluateSimpleFunctionCall( + descriptor, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifierSymbol?.owner) } } @@ -1940,9 +1938,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map, resultLifetime: Lifetime, superClass: ClassDescriptor? = null): LLVMValueRef { //context.log{"evaluateSimpleFunctionCall : $tmpVariableName = ${ir2string(value)}"} - if (descriptor.isOverridable && superClass == null) + if (superClass == null && descriptor is SimpleFunctionDescriptor && descriptor.isOverridable) return callVirtual(descriptor, args, resultLifetime) else return callDirect(descriptor, args, resultLifetime) @@ -1980,7 +1979,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map): LLVMValueRef { context.log{"evaluateConstructorCall : ${ir2string(callee)}"} return memScoped { - val constructedClass = (callee.descriptor as ConstructorDescriptor).constructedClass + val constructedClass = (callee.symbol as IrConstructorSymbol).owner.constructedClass val thisValue = if (constructedClass.isArray) { assert(args.isNotEmpty() && args[0].type == int32Type) functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), args[0], @@ -1991,12 +1990,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map { val typeArgument = callee.getTypeArgument(descriptor.typeParameters.single()) - val classDescriptor = TypeUtils.getClassDescriptor(typeArgument!!)!! - genGetObjCClass(classDescriptor) + val irClass = context.ir.getClass(typeArgument!!)!! + genGetObjCClass(irClass) } interop.getObjCMessenger -> { @@ -2090,16 +2089,16 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map { val typeArgument = callee.getTypeArgumentOrDefault(descriptor.typeParameters.single()) - val typeArgumentClass = TypeUtils.getClassDescriptor(typeArgument) + val typeArgumentClass = context.ir.getClass(typeArgument) if (typeArgumentClass == null) { // E.g. for `T::class` in a body of an inline function itself. functionGenerationContext.unreachable() kNullInt8Ptr } else { - val classDescriptor = context.ir.symbols.valueClassToBox[typeArgumentClass]?.descriptor + val irClass = context.ir.symbols.valueClassToBox[typeArgumentClass.symbol]?.owner ?: typeArgumentClass - val typeInfo = codegen.typeInfoValue(classDescriptor) + val typeInfo = codegen.typeInfoValue(irClass) LLVMConstBitCast(typeInfo, kInt8Ptr)!! } } @@ -2107,8 +2106,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map { val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0] val enumClass = callee.getTypeArgument(typeParameterT)!! - val enumClassDescriptor = enumClass.constructor.declarationDescriptor as ClassDescriptor - functionGenerationContext.allocInstance(enumClassDescriptor, resultLifetime(callee)) + val enumIrClass = context.ir.getClass(enumClass)!! + functionGenerationContext.allocInstance(enumIrClass, resultLifetime(callee)) } context.ir.symbols.listOfInternal.descriptor -> { @@ -2301,7 +2300,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map): LLVMValueRef { - return callDirect(context.interopBuiltIns.objCPointerHolder.unsubstitutedPrimaryConstructor!!, + return callDirect(context.ir.symbols.objCPointerHolder.owner.constructors.single(), args, Lifetime.IRRELEVANT) } @@ -2335,13 +2334,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map): LLVMValueRef { context.log{"evaluateOperatorCall : origin:${ir2string(callee)}"} - val descriptor = callee.descriptor + val descriptor = callee.symbol.owner as IrFunction val ib = context.irModule!!.irBuiltins with(functionGenerationContext) { return when { - descriptor == ib.eqeqeq -> icmpEq(args[0], args[1]) - descriptor == ib.booleanNot -> icmpNe(args[0], kTrue) + descriptor == ib.eqeqeqFun -> icmpEq(args[0], args[1]) + descriptor == ib.booleanNotFun -> icmpNe(args[0], kTrue) descriptor.isComparisonDescriptor(ib.greaterFunByOperandType) -> { if (args[0].type.isFloatingPoint()) fcmpGt(args[0], args[1]) @@ -2447,7 +2446,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map): LLVMValueRef { val constructedClass = functionGenerationContext.constructedClass!! - val thisPtr = currentCodeContext.genGetValue(constructedClass.thisAsReceiverParameter) + val thisPtr = currentCodeContext.genGetValue(constructedClass.thisReceiver!!) if (constructedClass.isObjCClass()) { return codegen.theUnitInstanceRef.llvm diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/KotlinObjCClassInfoGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/KotlinObjCClassInfoGenerator.kt index 862cf14e600..980c80a6a35 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/KotlinObjCClassInfoGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/KotlinObjCClassInfoGenerator.kt @@ -18,44 +18,40 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.LLVMStoreSizeOfType import llvm.LLVMValueRef +import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.konan.* -import org.jetbrains.kotlin.backend.konan.descriptors.contributedMethods import org.jetbrains.kotlin.backend.konan.descriptors.getStringValue import org.jetbrains.kotlin.backend.konan.descriptors.getStringValueOrNull -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.descriptors.isFinalClass +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.util.simpleFunctions import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces internal class KotlinObjCClassInfoGenerator(override val context: Context) : ContextUtils { fun generate(irClass: IrClass) { - val descriptor = irClass.descriptor - assert(descriptor.isFinalClass) + assert(irClass.isFinalClass) - val objCLLvmDeclarations = context.llvmDeclarations.forClass(descriptor).objCDeclarations!! + val objCLLvmDeclarations = context.llvmDeclarations.forClass(irClass).objCDeclarations!! val instanceMethods = generateInstanceMethodDescs(irClass) - val companionObjectDescriptor = descriptor.companionObjectDescriptor - val classMethods = companionObjectDescriptor?.generateOverridingMethodDescs() ?: emptyList() + val companionObject = irClass.declarations.filterIsInstance().atMostOne { it.isCompanion } + val classMethods = companionObject?.generateOverridingMethodDescs() ?: emptyList() - val superclassName = descriptor.getSuperClassNotAny()!!.let { + val superclassName = irClass.getSuperClassNotAny()!!.let { context.llvm.imports.add(it.llvmSymbolOrigin) it.name.asString() } - val protocolNames = descriptor.getSuperInterfaces().map { + val protocolNames = irClass.getSuperInterfaces().map { context.llvm.imports.add(it.llvmSymbolOrigin) it.name.asString().removeSuffix("Protocol") } val bodySize = - LLVMStoreSizeOfType(llvmTargetData, context.llvmDeclarations.forClass(descriptor).bodyType).toInt() + LLVMStoreSizeOfType(llvmTargetData, context.llvmDeclarations.forClass(irClass).bodyType).toInt() - val className = selectClassName(descriptor)?.let { staticData.cStringLiteral(it) } ?: NullPointer(int8Type) + val className = selectClassName(irClass)?.let { staticData.cStringLiteral(it) } ?: NullPointer(int8Type) val info = Struct(runtime.kotlinObjCClassInfo, className, @@ -73,8 +69,8 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con Int32(bodySize), objCLLvmDeclarations.bodyOffsetGlobal.pointer, - descriptor.typeInfoPtr, - companionObjectDescriptor?.typeInfoPtr ?: NullPointer(runtime.typeInfoType), + irClass.typeInfoPtr, + companionObject?.typeInfoPtr ?: NullPointer(runtime.typeInfoType), objCLLvmDeclarations.classPointerGlobal.pointer ) @@ -88,13 +84,12 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con private fun generateInstanceMethodDescs( irClass: IrClass ): List = mutableListOf().apply { - val descriptor = irClass.descriptor - addAll(descriptor.generateOverridingMethodDescs()) + addAll(irClass.generateOverridingMethodDescs()) addAll(irClass.generateImpMethodDescs()) val allImplementedSelectors = this.map { it.selector }.toSet() - assert(descriptor.getSuperClassNotAny()!!.isExternalObjCClass()) - val allInitMethodsInfo = descriptor.getSuperClassNotAny()!!.constructors + assert(irClass.getSuperClassNotAny()!!.isExternalObjCClass()) + val allInitMethodsInfo = irClass.getSuperClassNotAny()!!.constructors .mapNotNull { it.getObjCInitMethod()?.getExternalObjCMethodInfo() } .filter { it.selector !in allImplementedSelectors } .distinctBy { it.selector } @@ -104,14 +99,14 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con } } - private fun selectClassName(descriptor: ClassDescriptor): String? { + private fun selectClassName(irClass: IrClass): String? { val exportObjCClassAnnotation = - descriptor.annotations.findAnnotation(context.interopBuiltIns.exportObjCClass.fqNameSafe) + irClass.annotations.findAnnotation(context.interopBuiltIns.exportObjCClass.fqNameSafe) return if (exportObjCClassAnnotation != null) { - exportObjCClassAnnotation.getStringValueOrNull("name") ?: descriptor.name.asString() - } else if (descriptor.isExported()) { - descriptor.fqNameSafe.asString() + exportObjCClassAnnotation.getStringValueOrNull("name") ?: irClass.name.asString() + } else if (irClass.isExported()) { + irClass.fqNameSafe.asString() } else { null // Generate as anonymous. } @@ -138,22 +133,21 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con ) ) - private fun ClassDescriptor.generateOverridingMethodDescs(): List = - this.unsubstitutedMemberScope.contributedMethods.filter { - it.kind.isReal && it !is ConstructorDescriptor - }.mapNotNull { it.getObjCMethodInfo() }.map { generateMethodDesc(it) } + private fun IrClass.generateOverridingMethodDescs(): List = + this.simpleFunctions().filter { it.isReal } + .mapNotNull { it.getObjCMethodInfo() }.map { generateMethodDesc(it) } private fun IrClass.generateImpMethodDescs(): List = this.declarations .filterIsInstance() .mapNotNull { val annotation = - it.descriptor.annotations.findAnnotation(context.interopBuiltIns.objCMethodImp.fqNameSafe) ?: + it.annotations.findAnnotation(context.interopBuiltIns.objCMethodImp.fqNameSafe) ?: return@mapNotNull null ObjCMethodDesc( annotation.getStringValue("selector"), annotation.getStringValue("encoding"), - it.descriptor.llvmFunction + it.llvmFunction ) } } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt index 4b6b3956caa..e2a98dc7038 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt @@ -20,18 +20,13 @@ import kotlinx.cinterop.* import llvm.* import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.descriptors.* -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.idea.MainFunctionDetector -import org.jetbrains.kotlin.serialization.deserialization.descriptors.* +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe internal fun createLlvmDeclarations(context: Context): LlvmDeclarations { val generator = DeclarationsGeneratorVisitor(context) @@ -47,8 +42,8 @@ internal fun createLlvmDeclarations(context: Context): LlvmDeclarations { internal class LlvmDeclarations( private val functions: Map, private val classes: Map, - private val fields: Map, - private val staticFields: Map, + private val fields: Map, + private val staticFields: Map, private val theUnitInstanceRef: ConstPointer? ) { fun forFunction(descriptor: FunctionDescriptor) = functions[descriptor] ?: @@ -57,10 +52,10 @@ internal class LlvmDeclarations( fun forClass(descriptor: ClassDescriptor) = classes[descriptor] ?: error(descriptor.toString()) - fun forField(descriptor: PropertyDescriptor) = fields[descriptor] ?: + fun forField(descriptor: IrField) = fields[descriptor] ?: error(descriptor.toString()) - fun forStaticField(descriptor: PropertyDescriptor) = staticFields[descriptor] ?: + fun forStaticField(descriptor: IrField) = staticFields[descriptor] ?: error(descriptor.toString()) fun forSingleton(descriptor: ClassDescriptor) = forClass(descriptor).singletonDeclarations ?: @@ -72,7 +67,7 @@ internal class LlvmDeclarations( internal class ClassLlvmDeclarations( val bodyType: LLVMTypeRef, - val fields: List, // TODO: it is not an LLVM declaration. + val fields: List, // TODO: it is not an LLVM declaration. val typeInfoGlobal: StaticData.Global, val writableTypeInfoGlobal: StaticData.Global?, val typeInfo: ConstPointer, @@ -101,7 +96,7 @@ internal class StaticFieldLlvmDeclarations(val storage: LLVMValueRef) */ internal fun ContextUtils.getFields(classDescriptor: ClassDescriptor) = context.getFields(classDescriptor) -internal fun Context.getFields(classDescriptor: ClassDescriptor): List { +internal fun Context.getFields(classDescriptor: ClassDescriptor): List { val superClass = classDescriptor.getSuperClassNotAny() // TODO: what if Any has fields? val superFields = if (superClass != null) getFields(superClass) else emptyList() @@ -111,7 +106,7 @@ internal fun Context.getFields(classDescriptor: ClassDescriptor): List { +private fun Context.getDeclaredFields(classDescriptor: ClassDescriptor): List { // TODO: Here's what is going on here: // The existence of a backing field for a property is only described in the IR, // but not in the PropertyDescriptor. @@ -122,33 +117,24 @@ private fun Context.getDeclaredFields(classDescriptor: ClassDescriptor): List it.backingField?.descriptor - is IrField -> it.descriptor - else -> null - } + val irClass = classDescriptor + val fields = irClass.declarations.mapNotNull { + when (it) { + is IrField -> it + is IrProperty -> it.konanBackingField + else -> null } - } else { - val properties = classDescriptor.unsubstitutedMemberScope. - getContributedDescriptors(). - filterIsInstance() - - properties.mapNotNull { it.backingField } } + return fields.sortedBy { it.fqNameSafe.localHash.value } } -private fun ContextUtils.createClassBodyType(name: String, fields: List): LLVMTypeRef { +private fun ContextUtils.createClassBodyType(name: String, fields: List): LLVMTypeRef { val fieldTypes = fields.map { @Suppress("DEPRECATION") - getLLVMType(if (it.isDelegated) context.builtIns.nullableAnyType else it.type) + getLLVMType(if (it.isDelegate) context.builtIns.nullableAnyType else it.type) } val classType = LLVMStructCreateNamed(LLVMGetModuleContext(context.llvmModule), name)!! @@ -163,8 +149,8 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : val functions = mutableMapOf() val classes = mutableMapOf() - val fields = mutableMapOf() - val staticFields = mutableMapOf() + val fields = mutableMapOf() + val staticFields = mutableMapOf() var theUnitInstanceRef: ConstPointer? = null private class Namer(val prefix: String) { @@ -183,7 +169,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : val objectNamer = Namer("object-") private fun getLocalName(parent: FqName, descriptor: DeclarationDescriptor): Name { - if (DescriptorUtils.isAnonymousObject(descriptor)) { + if (descriptor.isAnonymousObject) { return objectNamer.getName(parent, descriptor) } @@ -191,20 +177,15 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : } private fun getFqName(descriptor: DeclarationDescriptor): FqName { - if (descriptor is PackageFragmentDescriptor) { - return descriptor.fqName + val parent = descriptor.parent + val parentFqName = when (parent) { + is IrPackageFragment -> parent.fqName + is IrDeclaration -> getFqName(parent) + else -> error(parent) } - - val containingDeclaration = descriptor.containingDeclaration - val parent = if (containingDeclaration != null) { - getFqName(containingDeclaration) - } else { - FqName.ROOT - } - - val localName = getLocalName(parent, descriptor) - return parent.child(localName) + val localName = getLocalName(parentFqName, descriptor) + return parentFqName.child(localName) } /** @@ -223,17 +204,17 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : override fun visitClass(declaration: IrClass) { - if (declaration.descriptor.isIntrinsic) { + if (declaration.isIntrinsic) { // do not generate any declarations for intrinsic classes as they require special handling } else { - this.classes[declaration.descriptor] = createClassDeclarations(declaration) + this.classes[declaration] = createClassDeclarations(declaration) } super.visitClass(declaration) } private fun createClassDeclarations(declaration: IrClass): ClassLlvmDeclarations { - val descriptor = declaration.descriptor + val descriptor = declaration val internalName = qualifyInternalName(descriptor) @@ -317,7 +298,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : ): SingletonLlvmDeclarations? { if (descriptor.isUnit()) { - this.theUnitInstanceRef = staticData.createUnitInstance(descriptor, bodyType, typeInfoPtr) + this.theUnitInstanceRef = staticData.createUnitInstance(bodyType, typeInfoPtr) return null } @@ -330,6 +311,8 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : val instanceFieldRef = addGlobal( symbolName, getLLVMType(descriptor.defaultType), isExported = isExported, threadLocal = true) + LLVMSetInitializer(instanceFieldRef, kNullObjHeaderPtr) + return SingletonLlvmDeclarations(instanceFieldRef) } @@ -353,11 +336,10 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : override fun visitField(declaration: IrField) { super.visitField(declaration) - val descriptor = declaration.descriptor + val descriptor = declaration - val dispatchReceiverParameter = descriptor.dispatchReceiverParameter - if (dispatchReceiverParameter != null) { - val containingClass = dispatchReceiverParameter.containingDeclaration + val containingClass = descriptor.containingClass + if (containingClass != null) { val classDeclarations = this.classes[containingClass] ?: error(containingClass.toString()) val allFields = classDeclarations.fields @@ -381,9 +363,9 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : override fun visitFunction(declaration: IrFunction) { super.visitFunction(declaration) - if (!declaration.descriptor.kind.isReal) return + if (!declaration.isReal) return - val descriptor = declaration.descriptor + val descriptor = declaration val llvmFunctionType = getLlvmFunctionType(descriptor) if ((descriptor is ConstructorDescriptor && descriptor.getObjCInitMethod() != null)) { @@ -402,7 +384,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : } else { val symbolName = if (descriptor.isExported()) { descriptor.symbolName.also { - if (!MainFunctionDetector.isMain(descriptor)) { + if (!descriptor.isMain()) { assert(LLVMGetNamedFunction(context.llvm.llvmModule, it) == null) { it } } else { // As a workaround, allow `main` functions to clash because frontend accepts this. diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt index e5190c61399..462ae6f8360 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt @@ -19,15 +19,12 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.* import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.* -import org.jetbrains.kotlin.backend.konan.isExternalObjCClassMethod -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.constants.StringValue -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny -import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf internal class RTTIGenerator(override val context: Context) : ContextUtils { @@ -125,8 +122,8 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { val size = getInstanceSize(bodyType, className) - val superTypeOrAny = classDesc.getSuperClassOrAny() - val superType = if (KotlinBuiltIns.isAny(classDesc)) NullPointer(runtime.typeInfoType) + val superTypeOrAny = classDesc.getSuperClassNotAny() ?: context.ir.symbols.any.owner + val superType = if (classDesc.isAny()) NullPointer(runtime.typeInfoType) else superTypeOrAny.typeInfoPtr val interfaces = classDesc.implementedInterfaces.map { it.typeInfoPtr } @@ -236,14 +233,14 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { val size = 0 - val superClass = context.builtIns.any + val superClass = context.ir.symbols.any.owner assert(superClass.implementedInterfaces.isEmpty()) val interfaces = listOf(descriptor.typeInfoPtr) val interfacesPtr = staticData.placeGlobalConstArray("", pointerType(runtime.typeInfoType), interfaces) - assert(superClass.getMemberScope().getVariableNames().isEmpty()) + assert(superClass.declarations.all { it !is IrProperty && it !is IrField }) val objOffsetsPtr = NullPointer(int32Type) val objOffsetsCount = 0 val fieldsPtr = NullPointer(runtime.fieldTableRecordType) @@ -295,18 +292,18 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { private fun getReflectionInfo(descriptor: ClassDescriptor): ReflectionInfo { // Use data from value class in type info for box class: val descriptorForReflection = context.ir.symbols.valueClassToBox.entries - .firstOrNull { it.value.descriptor == descriptor } - ?.key ?: descriptor + .firstOrNull { it.value.owner == descriptor } + ?.key?.owner ?: descriptor - return if (DescriptorUtils.isAnonymousObject(descriptorForReflection)) { + return if (descriptorForReflection.isAnonymousObject) { ReflectionInfo(packageName = null, relativeName = null) - } else if (DescriptorUtils.isLocal(descriptorForReflection)) { + } else if (descriptorForReflection.isLocal) { ReflectionInfo(packageName = null, relativeName = descriptorForReflection.name.asString()) } else { ReflectionInfo( packageName = descriptorForReflection.findPackage().fqName.asString(), - relativeName = descriptorForReflection.parentsWithSelf - .takeWhile { it is ClassDescriptor }.toList().reversed() + relativeName = generateSequence(descriptorForReflection, { it.parent as? ClassDescriptor }) + .toList().reversed() .joinToString(".") { it.name.asString() } ) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticData.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticData.kt index 85239e253cd..3cfa999c3a7 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticData.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticData.kt @@ -186,5 +186,5 @@ internal class StaticData(override val context: Context): ContextUtils { */ internal fun StaticData.createImmutableBinaryBlob(value: IrConst): LLVMValueRef { val args = value.value.map { Int8(it.toByte()).llvm } - return createKotlinArray(context.ir.symbols.immutableBinaryBlob.descriptor.defaultType, args) + return createKotlinArray(context.ir.symbols.immutableBinaryBlob.owner, args) } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt index e95acf2e972..f9e794589b2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt @@ -20,14 +20,14 @@ import llvm.LLVMLinkage import llvm.LLVMSetLinkage import llvm.LLVMTypeRef import llvm.LLVMValueRef -import org.jetbrains.kotlin.backend.konan.descriptors.isUnit +import org.jetbrains.kotlin.backend.konan.irasdescriptors.defaultType +import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe +import org.jetbrains.kotlin.backend.konan.irasdescriptors.llvmSymbolOrigin import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.ir.expressions.IrConst +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeProjection import org.jetbrains.kotlin.types.replace @@ -43,12 +43,10 @@ private fun StaticData.arrayHeader(typeInfo: ConstPointer, length: Int): Struct } internal fun StaticData.createKotlinStringLiteral(value: String): ConstPointer { - val type = context.builtIns.stringType - val name = "kstr:" + value.globalHashBase64 val elements = value.toCharArray().map(::Char16) - val objRef = createKotlinArray(type, elements) + val objRef = createKotlinArray(context.ir.symbols.string.owner, elements) val res = createAlias(name, objRef) LLVMSetLinkage(res.llvm, LLVMLinkage.LLVMWeakAnyLinkage) @@ -56,20 +54,13 @@ internal fun StaticData.createKotlinStringLiteral(value: String): ConstPointer { return res } -private fun StaticData.createRef(type: KotlinType, objHeaderPtr: ConstPointer): ConstPointer { - val llvmType = getLLVMType(type) - return if (llvmType != objHeaderPtr.llvmType) { - objHeaderPtr.bitcast(llvmType) - } else { - objHeaderPtr - } -} +private fun StaticData.createRef(objHeaderPtr: ConstPointer) = objHeaderPtr.bitcast(kObjHeaderPtr) -internal fun StaticData.createKotlinArray(arrayType: KotlinType, elements: List) = - createKotlinArray(arrayType, elements.map { constValue(it) }).llvm +internal fun StaticData.createKotlinArray(arrayClass: IrClass, elements: List) = + createKotlinArray(arrayClass, elements.map { constValue(it) }).llvm -internal fun StaticData.createKotlinArray(arrayType: KotlinType, elements: List): ConstPointer { - val typeInfo = arrayType.typeInfoPtr!! +internal fun StaticData.createKotlinArray(arrayClass: IrClass, elements: List): ConstPointer { + val typeInfo = arrayClass.typeInfoPtr val bodyElementType: LLVMTypeRef = elements.firstOrNull()?.llvmType ?: int8Type // (use [0 x i8] as body if there are no elements) @@ -84,11 +75,11 @@ internal fun StaticData.createKotlinArray(arrayType: KotlinType, elements: List< global.setInitializer(Struct(compositeType, arrayHeader, arrayBody)) - return createRef(arrayType, objHeaderPtr) + return createRef(objHeaderPtr) } -internal fun StaticData.createKotlinObject(type: KotlinType, body: ConstValue): ConstPointer { - val typeInfo = type.typeInfoPtr!! +internal fun StaticData.createKotlinObject(type: IrClass, body: ConstValue): ConstPointer { + val typeInfo = type.typeInfoPtr val compositeType = structType(runtime.objHeaderType, body.llvmType) @@ -99,7 +90,7 @@ internal fun StaticData.createKotlinObject(type: KotlinType, body: ConstValue): global.setInitializer(Struct(compositeType, objHeader, body)) - return createRef(type, objHeaderPtr) + return createRef(objHeaderPtr) } private fun StaticData.getArrayListClass(): ClassDescriptor { @@ -118,7 +109,7 @@ private fun StaticData.getArrayListClass(): ClassDescriptor { * @param length value for `length: Int` field. */ internal fun StaticData.createArrayList(elementType: TypeProjection, array: ConstPointer, length: Int): ConstPointer { - val arrayListClass = getArrayListClass() + val arrayListClass = context.ir.symbols.arrayList.owner // type is ArrayList: val type = arrayListClass.defaultType.replace(listOf(elementType)) @@ -140,15 +131,13 @@ internal fun StaticData.createArrayList(elementType: TypeProjection, array: Cons val body = Struct(*(sorted.values.toTypedArray())) - return createKotlinObject(type, body) + return createKotlinObject(arrayListClass, body) } -internal fun StaticData.createUnitInstance(descriptor: ClassDescriptor, - bodyType: LLVMTypeRef, +internal fun StaticData.createUnitInstance(bodyType: LLVMTypeRef, typeInfo: ConstPointer ): ConstPointer { - assert (descriptor.isUnit()) assert (getStructElements(bodyType).isEmpty()) val objHeader = objHeader(typeInfo) val global = this.placeGlobal(theUnitInstanceName, objHeader, isExported = true) @@ -157,7 +146,7 @@ internal fun StaticData.createUnitInstance(descriptor: ClassDescriptor, internal val ContextUtils.theUnitInstanceRef: ConstPointer get() { - val unitDescriptor = context.builtIns.unit + val unitDescriptor = context.ir.symbols.unit.owner return if (isExternal(unitDescriptor)) { constPointer(importGlobal( theUnitInstanceName, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VariableManager.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VariableManager.kt index 004d4ab62fa..d1b2875adca 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VariableManager.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VariableManager.kt @@ -18,8 +18,9 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.* import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.name.Name @@ -175,3 +176,9 @@ internal fun debugInfoParameterLocation(builder: DIBuilderRef?, return VariableDebugLocation(localVariable = variableDeclaration!!, location = location, file = file, line = line) } + +private val ValueDescriptor.type get() = when (this) { + is IrVariable -> this.type + is IrValueParameter -> this.type + else -> error(this) +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt index 14a6ecbc8b3..0fb18284c3d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt @@ -19,10 +19,9 @@ package org.jetbrains.kotlin.backend.konan.llvm.objcexport import llvm.* import org.jetbrains.kotlin.backend.konan.descriptors.CurrentKonanModule import org.jetbrains.kotlin.backend.konan.llvm.* -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.util.OperatorNameConventions internal fun ObjCExportCodeGenerator.generateKotlinFunctionImpl(invokeMethod: FunctionDescriptor): ConstPointer { // TODO: consider also overriding methods of `Any`. @@ -31,7 +30,7 @@ internal fun ObjCExportCodeGenerator.generateKotlinFunctionImpl(invokeMethod: Fu val function = generateFunction( codegen, - codegen.getLlvmFunctionType(invokeMethod), + codegen.getLlvmFunctionType(context.ir.get(invokeMethod)), "invokeFunction$numberOfParameters" ) { val args = (0 until numberOfParameters).map { index -> kotlinReferenceToObjC(param(index + 1)) } @@ -154,7 +153,10 @@ internal class BlockAdapterToFunctionGenerator(val objCExportCodeGenerator: ObjC objCReferenceToKotlin(param(index), Lifetime.ARGUMENT) } - val callee = lookupVirtualImpl(kotlinFunction, context.builtIns.getInvokeDescriptor(numberOfParameters)) + val invokeMethod = context.ir.symbols.functions[numberOfParameters].owner.declarations + .filterIsInstance().single { it.name == OperatorNameConventions.INVOKE } + + val callee = lookupVirtualImpl(kotlinFunction, invokeMethod) val result = callFromBridge(callee, listOf(kotlinFunction) + args, Lifetime.ARGUMENT) @@ -221,9 +223,3 @@ internal class BlockAdapterToFunctionGenerator(val objCExportCodeGenerator: ObjC } } } - -private fun KotlinBuiltIns.getInvokeDescriptor(numberOfParameters: Int): FunctionDescriptor = - getFunction(numberOfParameters).unsubstitutedMemberScope.getContributedFunctions( - Name.identifier("invoke"), - NoLookupLocation.FROM_BACKEND - ).single() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index a9f38bd07fd..f960dbfd15f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -21,15 +21,17 @@ import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.descriptors.allParameters import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.descriptors.* +import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass import org.jetbrains.kotlin.backend.konan.llvm.* import org.jetbrains.kotlin.backend.konan.llvm.objc.ObjCCodeGenerator import org.jetbrains.kotlin.backend.konan.objcexport.* import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.util.OperatorNameConventions internal class ObjCExportCodeGenerator( codegen: CodeGenerator, @@ -153,7 +155,7 @@ internal class ObjCExportCodeGenerator( val value = genValue(Lifetime.ARGUMENT) - return callFromBridge(conversion.descriptor.llvmFunction, listOf(value), resultLifetime) + return callFromBridge(conversion.owner.llvmFunction, listOf(value), resultLifetime) } internal fun emitRtti( @@ -329,15 +331,16 @@ private fun ObjCExportCodeGenerator.setObjCExportTypeInfo( val writableTypeInfoType = runtime.writableTypeInfoType!! val writableTypeInfoValue = Struct(writableTypeInfoType, objCExportAddition) - val global = if (codegen.isExternal(descriptor)) { + val irClass = context.ir.get(descriptor) + val global = if (codegen.isExternal(irClass)) { // Note: this global replaces the external one with common linkage. staticData.createGlobal( writableTypeInfoType, - descriptor.writableTypeInfoSymbolName, + irClass.writableTypeInfoSymbolName, isExported = true ) } else { - context.llvmDeclarations.forClass(descriptor).writableTypeInfoGlobal!!.also { + context.llvmDeclarations.forClass(irClass).writableTypeInfoGlobal!!.also { it.setLinkage(LLVMLinkage.LLVMExternalLinkage) } } @@ -356,7 +359,7 @@ private fun ObjCExportCodeGenerator.emitBoxConverter(objCValueType: ObjCValueTyp val name = "${valueType.classFqName.shortName()}To${objCValueType.nsNumberName}" val converter = generateFunction(codegen, kotlinToObjCFunctionType, name) { - val unboxFunction = symbols.getUnboxFunction(valueType).descriptor.llvmFunction + val unboxFunction = symbols.getUnboxFunction(valueType).owner.llvmFunction val kotlinValue = callFromBridge( unboxFunction, listOf(param(0)), @@ -385,15 +388,14 @@ private fun ObjCExportCodeGenerator.emitFunctionConverters() { } private fun ObjCExportCodeGenerator.generateKotlinFunctionAdapterToBlock(numberOfParameters: Int): ConstPointer { - val interfaceDescriptor = codegen.context.builtIns.getFunction(numberOfParameters) - val invokeMethod = interfaceDescriptor.unsubstitutedMemberScope.getContributedFunctions( - Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND - ).single() + val irInterface = context.ir.symbols.functions[numberOfParameters].owner + val invokeMethod = irInterface.declarations.filterIsInstance() + .single { it.name == OperatorNameConventions.INVOKE } - val invokeImpl = generateKotlinFunctionImpl(invokeMethod) + val invokeImpl = generateKotlinFunctionImpl(invokeMethod.descriptor) return rttiGenerator.generateSyntheticInterfaceImpl( - interfaceDescriptor, + irInterface, mapOf(invokeMethod to invokeImpl) ) } @@ -414,7 +416,7 @@ private fun ObjCExportCodeGenerator.emitKotlinFunctionAdaptersToBlock() { private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() { setObjCExportTypeInfo( context.builtIns.string, - constPointer(codegen.llvmFunction(context.interopBuiltIns.CreateNSStringFromKString)) + constPointer(codegen.llvmFunction(context.ir.symbols.interopCreateNSStringFromKString.owner)) ) setObjCExportTypeInfo( @@ -495,10 +497,11 @@ private fun ObjCExportCodeGenerator.generateObjCImp( } } + val targetIr = context.ir.get(target) val llvmTarget = if (!isVirtual) { - codegen.llvmFunction(target) + codegen.llvmFunction(targetIr) } else { - lookupVirtualImpl(args.first(), target) + lookupVirtualImpl(args.first(), targetIr) } val targetResult = callFromBridge(llvmTarget, args, Lifetime.ARGUMENT) @@ -533,13 +536,15 @@ private fun ObjCExportCodeGenerator.generateObjCImpForArrayConstructor( objCToKotlin(param(index + 2), typeBridge, Lifetime.ARGUMENT) } + val targetIr = context.ir.get(target) + val arrayInstance = callFromBridge( context.llvm.allocArrayFunction, - listOf(target.constructedClass.llvmTypeInfoPtr, kotlinValueArgs.first()), + listOf((targetIr as IrConstructor).constructedClass.llvmTypeInfoPtr, kotlinValueArgs.first()), resultLifetime = Lifetime.ARGUMENT ) callFromBridge( - target.llvmFunction, + targetIr.llvmFunction, listOf(arrayInstance) + kotlinValueArgs ) @@ -564,7 +569,7 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge( val objcMsgSend = msgSender(objCFunctionType(methodBridge)) - val functionType = codegen.getLlvmFunctionType(descriptor) + val functionType = codegen.getLlvmFunctionType(context.ir.get(descriptor)) val result = generateFunction(codegen, functionType, "") { val args = mutableListOf() @@ -689,7 +694,8 @@ private fun ObjCExportCodeGenerator.vtableIndex(descriptor: FunctionDescriptor): return if (classDescriptor.isInterface) { null } else { - context.getVtableBuilder(classDescriptor).vtableIndex(descriptor) + context.getVtableBuilder(context.ir.get(classDescriptor)) + .vtableIndex(context.ir.get(descriptor) as IrSimpleFunction) } } @@ -761,12 +767,12 @@ private fun ObjCExportCodeGenerator.createTypeAdapter( inherited.forEach { presentVtableBridges += vtableIndex(it) - presentMethodTableBridges += it.functionName + presentMethodTableBridges += context.ir.get(it).functionName } uninherited.forEach { val vtableIndex = vtableIndex(it) - val functionName = it.functionName + val functionName = context.ir.get(it).functionName if (vtableIndex !in presentVtableBridges || functionName !in presentMethodTableBridges) { presentVtableBridges += vtableIndex @@ -794,17 +800,18 @@ private fun ObjCExportCodeGenerator.createTypeAdapter( .filter { mapper.isBaseMethod(it) && it.isOverridable } .map { createMethodVirtualAdapter(it) } - val typeInfo = constPointer(codegen.typeInfoValue(descriptor)) + val irClass = context.ir.get(descriptor) + val typeInfo = constPointer(codegen.typeInfoValue(irClass)) val objCName = namer.getClassOrProtocolName(descriptor) val vtableSize = if (descriptor.kind == ClassKind.INTERFACE) { -1 } else { - context.getVtableBuilder(descriptor).vtableEntries.size + context.getVtableBuilder(irClass).vtableEntries.size } - val vtable = if (!descriptor.isInterface && !descriptor.typeInfoHasVtableAttached) { - staticData.placeGlobal("", rttiGenerator.vtable(descriptor)).also { + val vtable = if (!descriptor.isInterface && !irClass.typeInfoHasVtableAttached) { + staticData.placeGlobal("", rttiGenerator.vtable(irClass)).also { it.setConstant(true) }.pointer.getElementPtr(0) } else { @@ -812,7 +819,7 @@ private fun ObjCExportCodeGenerator.createTypeAdapter( } val methodTable = if (!descriptor.isInterface && descriptor.isAbstract()) { - rttiGenerator.methodTableRecords(descriptor) + rttiGenerator.methodTableRecords(irClass) } else { emptyList() } @@ -859,13 +866,16 @@ private fun ObjCExportCodeGenerator.createDirectAdapters( val implementation = if (this.modality == Modality.ABSTRACT) { null } else { - OverriddenFunctionDescriptor(this, base).getImplementation(context) + OverriddenFunctionDescriptor( + context.ir.get(this) as IrSimpleFunction, + context.ir.get(base) as IrSimpleFunction + ).getImplementation(context) } - DirectAdapterRequest(implementation, base) + DirectAdapterRequest(implementation?.descriptor, base) } val superClassMethod = method.overriddenDescriptors - .atMostOne { !(it.containingDeclaration as ClassDescriptor).isInterface } + .atMostOne { !(it.containingDeclaration as ClassDescriptor).isInterface }?.original val inheritedAdapters = superClassMethod?.getAllRequiredDirectAdapters().orEmpty() val requiredAdapters = method.getAllRequiredDirectAdapters() @@ -914,7 +924,7 @@ private fun ObjCExportCodeGenerator.createObjectInstanceAdapter( return generateObjCToKotlinMethodAdapter(methodBridge, selector) { initRuntimeIfNeeded() // For instance methods it gets called when allocating. - val value = getObjectValue(descriptor, ExceptionHandler.Caller, locationInfo = null) + val value = getObjectValue(context.ir.get(descriptor), ExceptionHandler.Caller, locationInfo = null) ret(kotlinToObjC(value, ReferenceBridge)) } } @@ -930,7 +940,7 @@ private fun ObjCExportCodeGenerator.createEnumEntryAdapter( return generateObjCToKotlinMethodAdapter(methodBridge, selector) { initRuntimeIfNeeded() // For instance methods it gets called when allocating. - val value = getEnumEntry(descriptor, ExceptionHandler.Caller) + val value = getEnumEntry(context.ir.getEnumEntry(descriptor), ExceptionHandler.Caller) ret(kotlinToObjC(value, ReferenceBridge)) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt index b0a8b80e2cc..472a526f7c1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt @@ -35,9 +35,10 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.util.createParameterDeclarations +import org.jetbrains.kotlin.ir.util.simpleFunctions import org.jetbrains.kotlin.ir.util.transformFlat -import org.jetbrains.kotlin.ir.util.type import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature @@ -48,7 +49,7 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain val interop = context.interopBuiltIns val symbols = context.ir.symbols val nullableAnyType = context.builtIns.nullableAnyType - var runtimeJobDescriptor: FunctionDescriptor? = null + lateinit var runtimeJobFunction: IrSimpleFunction override fun lower(irDeclarationContainer: IrDeclarationContainer) { irDeclarationContainer.declarations.transformFlat { @@ -68,10 +69,11 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain return expression val job = expression.getValueArgument(3) as IrFunctionReference + val jobFunction = (job.symbol as IrSimpleFunctionSymbol).owner val jobDescriptor = job.descriptor val arg = jobDescriptor.valueParameters[0] - if (runtimeJobDescriptor == null) { - runtimeJobDescriptor = jobDescriptor.newCopyBuilder() + if (!::runtimeJobFunction.isInitialized) { + val runtimeJobDescriptor = jobDescriptor.newCopyBuilder() .setReturnType(nullableAnyType) .setValueParameters(listOf(ValueParameterDescriptorImpl( containingDeclaration = jobDescriptor, @@ -87,8 +89,17 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain source = arg.source ))) .build()!! + + runtimeJobFunction = IrFunctionImpl( + jobFunction.startOffset, + jobFunction.endOffset, + IrDeclarationOrigin.DEFINED, + runtimeJobDescriptor + ).also { + it.createParameterDeclarations() + } } - val overriddenJobDescriptor = OverriddenFunctionDescriptor(jobDescriptor, runtimeJobDescriptor!!) + val overriddenJobDescriptor = OverriddenFunctionDescriptor(jobFunction, runtimeJobFunction) if (!overriddenJobDescriptor.needBridge) return expression val bridge = context.buildBridge( @@ -115,22 +126,9 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain internal class BridgesBuilding(val context: Context) : ClassLoweringPass { override fun lower(irClass: IrClass) { - val functions = mutableSetOf() - irClass.declarations.forEach { - when (it) { - is IrFunction -> functions.add(it.descriptor) - is IrProperty -> { - functions.add(it.getter?.descriptor) - functions.add(it.setter?.descriptor) - } - } - } + val builtBridges = mutableSetOf() - irClass.descriptor.contributedMethods.forEach { functions.add(it) } - - val builtBridges = mutableSetOf() - functions.filterNotNull() - .filterNot { it.modality == Modality.ABSTRACT } + irClass.simpleFunctions() .forEach { function -> function.allOverriddenDescriptors .map { OverriddenFunctionDescriptor(function, it) } @@ -151,7 +149,7 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass { ?: return declaration val descriptor = declaration.descriptor val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor) - if (typeSafeBarrierDescription == null || builtBridges.contains(descriptor)) + if (typeSafeBarrierDescription == null || builtBridges.contains(declaration)) return declaration val irBuilder = context.createIrBuilder(declaration.symbol, declaration.startOffset, declaration.endOffset) @@ -169,22 +167,13 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass { startOffset = irClass.startOffset, endOffset = irClass.endOffset, descriptor = descriptor, - targetSymbol = irClass.findMember(descriptor.descriptor), // TODO: optimize. + targetSymbol = descriptor.descriptor.symbol, superQualifierSymbol = irClass.symbol) ) } } -private fun IrClass.findMember(descriptor: FunctionDescriptor): IrFunctionSymbol { - val functions = this.declarations.filterIsInstance().map { it.symbol } - val propertyAccessors = this.declarations - .filterIsInstance() - .flatMap { listOfNotNull(it.getter?.symbol, it.setter?.symbol) } - - return (functions + propertyAccessors).single { it.descriptor == descriptor } -} - -private object DECLARATION_ORIGIN_BRIDGE_METHOD : +internal object DECLARATION_ORIGIN_BRIDGE_METHOD : IrDeclarationOriginImpl("BRIDGE_METHOD") private fun IrBuilderWithScope.returnIfBadType(value: IrExpression, @@ -220,17 +209,20 @@ private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction, private fun Context.buildBridge(startOffset: Int, endOffset: Int, descriptor: OverriddenFunctionDescriptor, targetSymbol: IrFunctionSymbol, - superQualifierSymbol: IrClassSymbol? = null): IrFunctionImpl { - val bridgeDescriptor = specialDeclarationsFactory.getBridgeDescriptor(descriptor) - val bridge = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_BRIDGE_METHOD, - bridgeDescriptor).apply { createParameterDeclarations() } + superQualifierSymbol: IrClassSymbol? = null): IrFunction { + + val bridge = specialDeclarationsFactory.getBridgeDescriptor(descriptor) + + if (bridge.modality == Modality.ABSTRACT) { + return bridge + } val irBuilder = createIrBuilder(bridge.symbol, startOffset, endOffset) bridge.body = irBuilder.irBlockBody(bridge) { - val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor) - typeSafeBarrierDescription?.let { buildTypeSafeBarrier(bridge, descriptor.descriptor, it) } + val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor.descriptor) + typeSafeBarrierDescription?.let { buildTypeSafeBarrier(bridge, descriptor.descriptor.descriptor, it) } - val delegatingCall = IrCallImpl(startOffset, endOffset, targetSymbol, descriptor.descriptor, + val delegatingCall = IrCallImpl(startOffset, endOffset, targetSymbol, targetSymbol.descriptor, superQualifierSymbol = superQualifierSymbol /* Call non-virtually */ ).apply { bridge.dispatchReceiverParameter?.let { @@ -244,7 +236,7 @@ private fun Context.buildBridge(startOffset: Int, endOffset: Int, } } - if (KotlinBuiltIns.isUnitOrNullableUnit(bridgeDescriptor.returnType!!)) + if (KotlinBuiltIns.isUnitOrNullableUnit(bridge.returnType)) +delegatingCall else +irReturn(delegatingCall) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt index 5f18583fb41..ac228deb7a0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt @@ -25,10 +25,9 @@ import org.jetbrains.kotlin.backend.common.descriptors.replace import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName -import org.jetbrains.kotlin.backend.common.ir.createFakeOverrideDescriptor -import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations @@ -54,11 +53,10 @@ import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils @@ -69,7 +67,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass private var functionReferenceCount = 0 override fun lower(irFile: IrFile) { - irFile.transformChildrenVoid(object: IrElementTransformerVoidWithContext() { + irFile.transform(object: IrElementTransformerVoidWithContext() { private val stack = mutableListOf() @@ -126,7 +124,12 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass return expression } - val loweredFunctionReference = FunctionReferenceBuilder(currentScope!!.scope.scopeOwner, expression).build() + val parent = allScopes.map { it.irElement }.filterIsInstance().last() + val loweredFunctionReference = FunctionReferenceBuilder( + currentScope!!.scope.scopeOwner, + parent, + expression + ).build() val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset) return irBuilder.irBlock(expression) { +loweredFunctionReference.functionReferenceClass @@ -137,7 +140,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass } } } - }) + }, null) } private class BuiltFunctionReference(val functionReferenceClass: IrClass, @@ -154,6 +157,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass private val getContinuationSymbol = context.ir.symbols.getContinuation private inner class FunctionReferenceBuilder(val containingDeclaration: DeclarationDescriptor, + val parent: IrDeclarationParent, val functionReference: IrFunctionReference) { private val functionDescriptor = functionReference.descriptor @@ -176,12 +180,14 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass val superTypes = mutableListOf( kFunctionImplSymbol.owner.defaultType.replace(listOf(returnType)) ) + val superClasses = mutableListOf(kFunctionImplSymbol.owner) val numberOfParameters = unboundFunctionParameters.size val functionClassDescriptor = context.reflectionTypes.getKFunction(numberOfParameters) val functionParameterTypes = unboundFunctionParameters.map { it.type } val functionClassTypeParameters = functionParameterTypes + returnType superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeParameters) + superClasses += context.ir.symbols.kFunctions[numberOfParameters].owner var suspendFunctionClassDescriptor: ClassDescriptor? = null var suspendFunctionClassTypeParameters: List? = null @@ -192,9 +198,10 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass Name.identifier("SuspendFunction${numberOfParameters - 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) + lastParameterType.arguments.single().type superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeParameters) + superClasses += context.ir.symbols.suspendFunctions[numberOfParameters - 1].owner } - functionReferenceClassDescriptor = ClassDescriptorImpl( + functionReferenceClassDescriptor = object : ClassDescriptorImpl( /* containingDeclaration = */ containingDeclaration, /* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName, /* modality = */ Modality.FINAL, @@ -202,13 +209,16 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass /* superTypes = */ superTypes, /* source = */ SourceElement.NO_SOURCE, /* isExternal = */ false - ) + ) { + override fun getVisibility() = Visibilities.PRIVATE + } functionReferenceClass = IrClassImpl( startOffset = startOffset, endOffset = endOffset, origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, descriptor = functionReferenceClassDescriptor ) + functionReferenceClass.parent = this.parent val constructorBuilder = createConstructorBuilder() @@ -222,33 +232,27 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionDescriptor) } - val inheritedKFunctionImpl = kFunctionImplSymbol.descriptor.unsubstitutedMemberScope - .getContributedDescriptors() - .map { it.createFakeOverrideDescriptor(functionReferenceClassDescriptor) } - .filterNotNull() - val contributedDescriptors = ( - inheritedKFunctionImpl + invokeMethodBuilder.symbol.descriptor + suspendInvokeMethodBuilder?.symbol?.descriptor - ).filterNotNull().toList() + val memberScope = stub("callable reference class") functionReferenceClassDescriptor.initialize( - SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.symbol.descriptor), null) + memberScope, setOf(constructorBuilder.symbol.descriptor), null) functionReferenceClass.createParameterDeclarations() functionReferenceThis = functionReferenceClass.thisReceiver!!.symbol - functionReferenceClass.addFakeOverrides() - constructorBuilder.initialize() - functionReferenceClass.declarations.add(constructorBuilder.ir) + functionReferenceClass.addChild(constructorBuilder.ir) invokeMethodBuilder.initialize() - functionReferenceClass.declarations.add(invokeMethodBuilder.ir) + functionReferenceClass.addChild(invokeMethodBuilder.ir) suspendInvokeMethodBuilder?.let { it.initialize() - functionReferenceClass.declarations.add(it.ir) + functionReferenceClass.addChild(it.ir) } + functionReferenceClass.setSuperSymbolsAndAddFakeOverrides(superClasses) + return BuiltFunctionReference(functionReferenceClass, constructorBuilder.ir) } @@ -299,7 +303,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass IrConstKind.String, functionDescriptor.name.asString()) putValueArgument(0, name) val fqName = IrConstImpl(startOffset, endOffset, context.builtIns.stringType, IrConstKind.String, - functionDescriptor.fullName) + (functionReference.symbol.owner as IrFunction).fullName) putValueArgument(1, fqName) val bound = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType, boundFunctionParameters.isNotEmpty()) @@ -318,17 +322,8 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass } } - // TODO: what about private package level functions? - private val DeclarationDescriptor.fullName: String - get() { - return when (this) { - is PackageFragmentDescriptor -> fqNameSafe.asString() - is ClassDescriptor -> containingDeclaration.fullName + "." + fqNameSafe - is FunctionDescriptor -> containingDeclaration.fullName + "." + functionName - is PropertyDescriptor -> containingDeclaration.fullName + "." + fqNameSafe - else -> TODO("$this") - } - } + private val IrFunction.fullName: String + get() = parent.fqNameSafe.child(Name.identifier(functionName)).asString() private fun createInvokeMethodBuilder(superFunctionDescriptor: FunctionDescriptor) = object : SymbolWithIrBuilder() { @@ -385,7 +380,10 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass val argument = if (!unboundArgsSet.contains(it)) // Bound parameter - read from field. - irGetField(irGet(functionReferenceThis), argumentToPropertiesMap[it]!!) + irGetField( + irGet(function.dispatchReceiverParameter!!.symbol), + argumentToPropertiesMap[it]!! + ) else { if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size) // For suspend functions the last argument is continuation and it is implicit. @@ -420,7 +418,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass initialize() } - functionReferenceClass.declarations.add(propertyBuilder.ir) + functionReferenceClass.addChild(propertyBuilder.ir) return propertyBuilder.ir.backingField!!.symbol } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt index eed31f727e2..72efe99c91b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt @@ -16,10 +16,10 @@ package org.jetbrains.kotlin.backend.konan.lower -import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope +import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.ir.IrElement @@ -46,9 +46,9 @@ import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.typeUtil.makeNullable -class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor, +internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor, val parentDescriptor: DeclarationDescriptor, - val context: CommonBackendContext) { + val context: Context) { private val descriptorSubstituteMap: MutableMap = mutableMapOf() private var typeSubstitutor: TypeSubstitutor? = null @@ -503,7 +503,9 @@ class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor, origin = mapDeclarationOrigin(declaration.origin), descriptor = mapFunctionDeclaration(declaration.descriptor), body = declaration.body?.transform(this, null) - ).transformParameters(declaration) + ).also { + it.setOverrides(context.ir.symbols.symbolTable) + }.transformParameters(declaration) //---------------------------------------------------------------------// diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentsStubGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentsStubGenerator.kt index 5bc14f4dbfa..9be7a43b331 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentsStubGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentsStubGenerator.kt @@ -55,7 +55,11 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo override fun lower(irDeclarationContainer: IrDeclarationContainer) { irDeclarationContainer.declarations.transformFlat { memberDeclaration -> if (memberDeclaration is IrFunction) - lower(memberDeclaration) + lower(memberDeclaration).also { functions -> + functions.forEach { + it.parent = irDeclarationContainer + } + } else null } @@ -78,12 +82,18 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo functionDescriptor.overriddenDescriptors.forEach { context.log{"DEFAULT-REPLACER: $it"} } if (bodies.isNotEmpty()) { val newIrFunction = functionDescriptor.generateDefaultsFunction(context) + newIrFunction.parent = irFunction.parent val descriptor = newIrFunction.descriptor log { "$functionDescriptor -> $descriptor" } val builder = context.createIrBuilder(newIrFunction.symbol) - val body = builder.irBlockBody(irFunction) { + newIrFunction.body = builder.irBlockBody(newIrFunction) { val params = mutableListOf() val variables = mutableMapOf() + + irFunction.dispatchReceiverParameter?.let { + variables[it.descriptor] = newIrFunction.dispatchReceiverParameter!!.symbol + } + if (descriptor.extensionReceiverParameter != null) { variables[functionDescriptor.extensionReceiverParameter!!] = newIrFunction.extensionReceiverParameter!!.symbol @@ -157,20 +167,8 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo irFunction.valueParameters.forEach { it.defaultValue = null } - return if (functionDescriptor is ClassConstructorDescriptor) - listOf(irFunction, IrConstructorImpl( - startOffset = irFunction.startOffset, - endOffset = irFunction.endOffset, - descriptor = descriptor as ClassConstructorDescriptor, - origin = DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, - body = body).apply { createParameterDeclarations() }) - else - listOf(irFunction, IrFunctionImpl( - startOffset = irFunction.startOffset, - endOffset = irFunction.endOffset, - descriptor = descriptor, - origin = DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, - body = body).apply { createParameterDeclarations() }) + + return listOf(irFunction, newIrFunction) } return listOf(irFunction) } @@ -283,13 +281,24 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext): B } } - private fun parametersForCall(expression: IrMemberAccessExpression): Pair>> { - val descriptor = expression.descriptor as FunctionDescriptor - val keyDescriptor = if (DescriptorUtils.isOverride(descriptor)) - DescriptorUtils.getAllOverriddenDescriptors(descriptor).first { it.needsDefaultArgumentsLowering } - else - descriptor.original + private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? { + if (!this.descriptor.needsDefaultArgumentsLowering) return null + + if (this !is IrSimpleFunction) return this + + this.overriddenSymbols.forEach { + it.owner.findSuperMethodWithDefaultArguments()?.let { return it } + } + + return this + } + + private fun parametersForCall(expression: IrFunctionAccessExpression): Pair>> { + val descriptor = expression.descriptor + val keyFunction = (expression.symbol.owner as IrFunction).findSuperMethodWithDefaultArguments()!! + val keyDescriptor = keyFunction.descriptor val realFunction = keyDescriptor.generateDefaultsFunction(context) + realFunction.parent = keyFunction.parent val realDescriptor = realFunction.descriptor log { "$descriptor -> $realDescriptor" } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt index 8c22a056215..bad80626b76 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt @@ -41,6 +41,7 @@ import org.jetbrains.kotlin.ir.expressions.IrLocalDelegatedPropertyReference import org.jetbrains.kotlin.ir.expressions.IrPropertyReference import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.util.addChild import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid @@ -120,16 +121,14 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi declaration.transformChildrenVoid(this) val initializer = declaration.delegate.initializer!! - return IrVariableImpl(declaration.startOffset, declaration.endOffset, - declaration.origin, declaration.delegate.descriptor, - IrBlockImpl(initializer.startOffset, initializer.endOffset, initializer.type, null, - listOf( - declaration.getter, - declaration.setter, - initializer - ).filterNotNull()) - ) + declaration.delegate.initializer = IrBlockImpl(initializer.startOffset, initializer.endOffset, initializer.type, null, + listOf( + declaration.getter, + declaration.setter, + initializer + ).filterNotNull()) + return declaration.delegate } override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { @@ -191,7 +190,7 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi if (kProperties.isNotEmpty()) { val initializers = kProperties.values.sortedBy { it.second }.map { it.first } // TODO: move to object for lazy initialization. - irFile.declarations.add(0, kPropertiesField.apply { + irFile.addChild(kPropertiesField.apply { initializer = IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.createArrayOfExpression(kPropertyImplType, initializers, UNDEFINED_OFFSET, UNDEFINED_OFFSET)) }) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt index 37c07d23627..4b835d0051d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt @@ -19,13 +19,11 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.deepCopyWithVariables -import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName -import org.jetbrains.kotlin.backend.common.ir.createFakeOverrideDescriptor import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor import org.jetbrains.kotlin.backend.common.ir.createArrayOfExpression import org.jetbrains.kotlin.backend.common.ir.createSimpleDelegatingConstructorDescriptor @@ -43,6 +41,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeSubstitutor @@ -187,7 +186,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val defaultClass = createDefaultClassForEnumEntries() lowerEnumClassBody() if (defaultClass != null) - irClass.declarations.add(defaultClass) + irClass.addChild(defaultClass) createImplObject() } @@ -275,15 +274,11 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { } } - val contributedDescriptors = irClass.descriptor.unsubstitutedMemberScope - .getContributedDescriptors() - .map { it.createFakeOverrideDescriptor(defaultClassDescriptor) } - .filterNotNull() - .toList() - defaultClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null) + val memberScope = stub("enum default class") + defaultClassDescriptor.initialize(memberScope, constructors, null) defaultClass.createParameterDeclarations() - defaultClass.addFakeOverrides() + defaultClass.setSuperSymbolsAndAddFakeOverrides(listOf(irClass)) return defaultClass } @@ -325,10 +320,10 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { constructorOfAny, implObject.descriptor.constructors.single(), DECLARATION_ORIGIN_ENUM) - implObject.declarations.add(createSyntheticValuesPropertyDeclaration(enumEntries)) - implObject.declarations.add(createValuesPropertyInitializer(enumEntries)) + implObject.addChild(createSyntheticValuesPropertyDeclaration(enumEntries)) + implObject.addChild(createValuesPropertyInitializer(enumEntries)) - irClass.declarations.add(implObject) + irClass.addChild(implObject) } private val genericCreateUninitializedInstanceSymbol = context.ir.symbols.createUninitializedInstance @@ -363,7 +358,9 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { getter.body = IrBlockBodyImpl(startOffset, endOffset, listOf(returnStatement)) return IrPropertyImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, - false, loweredEnum.valuesField.descriptor, irField, getter, null) + false, loweredEnum.valuesField.descriptor, irField, getter, null).also { + it.parent = loweredEnum.implObject + } } private val initInstanceSymbol = context.ir.symbols.initInstance @@ -432,6 +429,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { loweredConstructorDescriptor, enumConstructor.body!! // will be transformed later ) + loweredEnumConstructor.parent = enumConstructor.parent loweredEnumConstructors[constructorDescriptor] = loweredEnumConstructor diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt index 552cc430ddb..60aabc9410c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt @@ -39,6 +39,7 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.getDefault import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid @@ -133,6 +134,8 @@ private class Inliner(val globalSubstituteMap: MutableMap null } - }.let { irClass.declarations.addAll(it) } + }.let { irClass.addChildren(it) } if (irClass.descriptor.annotations.hasAnnotation(interop.exportObjCClass.fqNameSafe)) { val irBuilder = context.createIrBuilder(currentFile.symbol).at(irClass) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LocalDeclarationsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LocalDeclarationsLowering.kt index 9674168c34e..d7f4589cc1c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LocalDeclarationsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LocalDeclarationsLowering.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.util.addChild import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.* @@ -144,6 +145,17 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai "LocalClassContext for ${descriptor}" } + private class LocalClassMemberContext(val member: IrFunction, val classContext: LocalClassContext) : LocalContext() { + override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { + val field = classContext.capturedValueToField[descriptor] ?: return null + + return IrGetFieldImpl(startOffset, endOffset, field.symbol, + receiver = IrGetValueImpl(startOffset, endOffset, member.dispatchReceiverParameter!!.symbol) + ) + } + + } + private inner class LocalDeclarationsTransformer(val memberDeclaration: IrDeclaration) { val localFunctions: MutableMap = LinkedHashMap() val localClasses: MutableMap = LinkedHashMap() @@ -169,6 +181,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai rewriteDeclarations() val result = collectRewrittenDeclarations() + result.forEach { it.parent = memberDeclaration.parent } return result } @@ -209,7 +222,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai // Replace local function definition with an empty composite. return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType) } else { - return super.visitFunction(declaration) + if (localContext is LocalClassContext && declaration.parent == localContext.declaration) { + return declaration.apply { + val classMemberLocalContext = LocalClassMemberContext(declaration, localContext) + transformChildrenVoid(FunctionBodiesRewriter(classMemberLocalContext)) + } + } else { + return super.visitFunction(declaration) + } } } @@ -219,6 +239,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai val constructorContext = localClassConstructors[declaration.descriptor] if (constructorContext != null) { return constructorContext.transformedDeclaration.apply { + this.parent = declaration.parent this.body = declaration.body!! declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> @@ -361,7 +382,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai localClassContext.capturedValueToField.forEach { capturedValue, field -> val startOffset = irClass.startOffset val endOffset = irClass.endOffset - irClass.declarations.add(field) + irClass.addChild(field) for (constructorContext in constructorsCallingSuper) { val blockBody = constructorContext.declaration.body as? IrBlockBody diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt index 3ca1a8d99e7..db248e8a384 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters import org.jetbrains.kotlin.backend.common.descriptors.getFunction import org.jetbrains.kotlin.backend.common.descriptors.replace -import org.jetbrains.kotlin.backend.common.ir.createFakeOverrideDescriptor import org.jetbrains.kotlin.backend.common.ir.createOverriddenDescriptor import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.konan.Context @@ -56,6 +55,7 @@ import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.makeNotNullable @@ -301,6 +301,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai fun build(): BuiltCoroutine { val superTypes = mutableListOf(coroutineImplClassDescriptor.defaultType) + val superClasses = mutableListOf(coroutineImplSymbol.owner) var suspendFunctionClassDescriptor: ClassDescriptor? = null var functionClassDescriptor: ClassDescriptor? = null var suspendFunctionClassTypeArguments: List? = null @@ -313,12 +314,14 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai val unboundParameterTypes = unboundFunctionParameters.map { it.type } suspendFunctionClassTypeArguments = unboundParameterTypes + irFunction.descriptor.returnType!! superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeArguments) + superClasses += context.ir.symbols.suspendFunctions[numberOfParameters].owner functionClassDescriptor = kotlinPackageScope.getContributedClassifier( Name.identifier("Function${numberOfParameters + 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor val continuationType = continuationClassDescriptor.defaultType.replace(listOf(irFunction.descriptor.returnType!!)) functionClassTypeArguments = unboundParameterTypes + continuationType + context.builtIns.nullableAnyType superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeArguments) + superClasses += context.ir.symbols.functions[numberOfParameters + 1].owner } coroutineClassDescriptor = ClassDescriptorImpl( @@ -336,6 +339,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai origin = DECLARATION_ORIGIN_COROUTINE_IMPL, descriptor = coroutineClassDescriptor ) + coroutineClass.parent = irFunction.parent val overriddenMap = mutableMapOf() @@ -375,40 +379,35 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai doResumeFunctionSymbol = doResumeMethodBuilder.symbol) } - val inheritedFromCoroutineImpl = coroutineImplClassDescriptor.unsubstitutedMemberScope - .getContributedDescriptors() - .map { overriddenMap[it] ?: it.createFakeOverrideDescriptor(coroutineClassDescriptor) } - val contributedDescriptors = ( - inheritedFromCoroutineImpl + invokeMethodBuilder?.symbol?.descriptor - ).filterNotNull().toList() - coroutineClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null) + val memberScope = stub("coroutine class") + coroutineClassDescriptor.initialize(memberScope, constructors, null) coroutineClass.createParameterDeclarations() coroutineClassThis = coroutineClass.thisReceiver!!.symbol - coroutineClass.addFakeOverrides() - coroutineConstructorBuilder.initialize() - coroutineClass.declarations.add(coroutineConstructorBuilder.ir) + coroutineClass.addChild(coroutineConstructorBuilder.ir) coroutineFactoryConstructorBuilder?.let { it.initialize() - coroutineClass.declarations.add(it.ir) + coroutineClass.addChild(it.ir) } createMethodBuilder?.let { it.initialize() - coroutineClass.declarations.add(it.ir) + coroutineClass.addChild(it.ir) } invokeMethodBuilder?.let { it.initialize() - coroutineClass.declarations.add(it.ir) + coroutineClass.addChild(it.ir) } doResumeMethodBuilder.initialize() - coroutineClass.declarations.add(doResumeMethodBuilder.ir) + coroutineClass.addChild(doResumeMethodBuilder.ir) + + coroutineClass.setSuperSymbolsAndAddFakeOverrides(superClasses) return BuiltCoroutine( coroutineClass = coroutineClass, @@ -569,6 +568,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai createParameterDeclarations() + val thisReceiver = this.dispatchReceiverParameter!!.symbol + val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) body = irBuilder.irBlockBody(startOffset, endOffset) { +irReturn( @@ -579,7 +580,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai if (unboundArgsSet.contains(it)) irGet(valueParameters[unboundIndex++].symbol) else - irGetField(irGet(coroutineClassThis), argumentToPropertiesMap[it]!!) + irGetField(irGet(thisReceiver), argumentToPropertiesMap[it]!!) }.forEachIndexed { index, argument -> putValueArgument(index, argument) } @@ -640,12 +641,14 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai createParameterDeclarations() + val thisReceiver = this.dispatchReceiverParameter!!.symbol + val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) body = irBuilder.irBlockBody(startOffset, endOffset) { +irReturn( irCall(doResumeFunctionSymbol).apply { dispatchReceiver = irCall(createFunctionSymbol).apply { - dispatchReceiver = irGet(coroutineClassThis) + dispatchReceiver = irGet(thisReceiver) valueParameters.forEachIndexed { index, parameter -> putValueArgument(index, irGet(parameter.symbol)) } @@ -673,7 +676,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai initialize() } - coroutineClass.declarations.add(propertyBuilder.ir) + coroutineClass.addChild(propertyBuilder.ir) return propertyBuilder.symbol } @@ -709,7 +712,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai outType = context.builtIns.nullableAnyType, isMutable = true) ) - val label = coroutineClassDescriptor.unsubstitutedMemberScope + val label = coroutineImplClassDescriptor.unsubstitutedMemberScope .getContributedVariables(Name.identifier("label"), NoLookupLocation.FROM_BACKEND).single() val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) @@ -747,6 +750,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai originalBody.transformChildrenVoid(object : IrElementTransformerVoid() { + private val thisReceiver = function.dispatchReceiverParameter!!.symbol + // Replace returns to refer to the new function. override fun visitReturn(expression: IrReturn): IrExpression { expression.transformChildrenVoid(this) @@ -763,7 +768,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai val capturedValue = argumentToPropertiesMap[expression.descriptor] ?: return expression - return irGetField(irGet(coroutineClassThis), capturedValue) + return irGetField(irGet(thisReceiver), capturedValue) } // Save/restore state at suspension points. @@ -782,10 +787,10 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai val scope = liveLocals[suspensionPoint]!! return irBlock(expression) { scope.forEach { - +irSetField(irGet(coroutineClassThis), localToPropertyMap[it]!!, irGet(localsMap[it.descriptor] ?: it)) + +irSetField(irGet(thisReceiver), localToPropertyMap[it]!!, irGet(localsMap[it.descriptor] ?: it)) } +irCall(coroutineImplLabelSetterSymbol).apply { - dispatchReceiver = irGet(coroutineClassThis) + dispatchReceiver = irGet(thisReceiver) putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter.symbol)) } } @@ -794,7 +799,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai val scope = liveLocals[suspensionPoint]!! return irBlock(expression) { scope.forEach { - +irSetVar(localsMap[it.descriptor] ?: it, irGetField(irGet(coroutineClassThis), localToPropertyMap[it]!!)) + +irSetVar(localsMap[it.descriptor] ?: it, irGetField(irGet(thisReceiver), localToPropertyMap[it]!!)) } } } @@ -813,7 +818,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai endOffset = endOffset, type = context.builtIns.unitType, suspensionPointId = irCall(coroutineImplLabelGetterSymbol).apply { - dispatchReceiver = irGet(coroutineClassThis) + dispatchReceiver = irGet(function.dispatchReceiverParameter!!.symbol) }, result = irBlock(startOffset, endOffset) { +irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception. diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TestProcessor.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TestProcessor.kt index f8d01641d76..44cf45e7af7 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TestProcessor.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TestProcessor.kt @@ -46,10 +46,7 @@ import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl -import org.jetbrains.kotlin.ir.util.addFakeOverrides -import org.jetbrains.kotlin.ir.util.addTopLevelInitializer -import org.jetbrains.kotlin.ir.util.constructors -import org.jetbrains.kotlin.ir.util.createParameterDeclarations +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils @@ -499,6 +496,7 @@ internal class TestProcessor (val context: KonanBackendContext) { addMember(instanceGetterBuilder.ir) companionGetterBuilder?.let { addMember(it.ir) } addFakeOverrides() + setSuperSymbols(context.ir.symbols.symbolTable) } override fun doInitialize() { @@ -546,7 +544,7 @@ internal class TestProcessor (val context: KonanBackendContext) { irFile.packageFragmentDescriptor, testClass.functions)) { initialize() - irFile.declarations.add(ir) + irFile.addChild(ir) irFile.addTopLevelInitializer( IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, ir.symbol.constructors.single()) ) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt index 86b04487d1b..6ad856dea71 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.konan.objcexport import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters import org.jetbrains.kotlin.backend.common.descriptors.isSuspend +import org.jetbrains.kotlin.backend.konan.KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS import org.jetbrains.kotlin.backend.konan.ValueType import org.jetbrains.kotlin.backend.konan.correspondingValueType import org.jetbrains.kotlin.backend.konan.descriptors.isArray @@ -33,7 +34,7 @@ import org.jetbrains.kotlin.types.typeUtil.isUnit internal interface ObjCExportMapper { fun getCategoryMembersFor(descriptor: ClassDescriptor): List - val maxFunctionTypeParameterCount get() = 22 + val maxFunctionTypeParameterCount get() = KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS fun isSpecialMapped(descriptor: ClassDescriptor): Boolean } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/CallGraphBuilder.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/CallGraphBuilder.kt index c5b927ddd63..a7d43c5dc5d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/CallGraphBuilder.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/CallGraphBuilder.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.backend.konan.DirectedGraph import org.jetbrains.kotlin.backend.konan.DirectedGraphNode import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.KonanConfigKeys -import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint import org.jetbrains.kotlin.konan.target.CompilerOutputKind internal class CallGraphNode(val graph: CallGraph, val symbol: DataFlowIR.FunctionSymbol) @@ -94,7 +93,7 @@ internal class CallGraphBuilder(val context: Context, fun build(): CallGraph { val rootSet = if (hasMain) { - listOf(symbolTable.mapFunction(findMainEntryPoint(context)!!).resolved()) + + listOf(symbolTable.mapFunction(context.ir.symbols.entryPoint!!.owner).resolved()) + moduleDFG.functions .map { it.key } .filter { it.isGlobalInitializer } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt index 4b474ed2aa9..9cf73f17075 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt @@ -16,69 +16,60 @@ package org.jetbrains.kotlin.backend.konan.optimizations -import org.jetbrains.kotlin.backend.common.descriptors.allParameters -import org.jetbrains.kotlin.backend.common.descriptors.isSuspend +import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole import org.jetbrains.kotlin.backend.common.peek import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors import org.jetbrains.kotlin.backend.konan.descriptors.isInterface import org.jetbrains.kotlin.backend.konan.descriptors.target import org.jetbrains.kotlin.backend.konan.ir.IrSuspendableExpression import org.jetbrains.kotlin.backend.konan.ir.IrSuspensionPoint +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.localHash -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.util.getArguments +import org.jetbrains.kotlin.ir.util.simpleFunctions import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.OverridingUtil -import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isUnit +import org.jetbrains.kotlin.util.OperatorNameConventions -private fun computeErasure(type: KotlinType, erasure: MutableList) { - val descriptor = type.constructor.declarationDescriptor - when (descriptor) { - is ClassDescriptor -> erasure += descriptor - is TypeParameterDescriptor -> { +private fun computeErasure(type: KotlinType, context: Context, erasure: MutableList) { + val irClass = context.ir.getClass(type) + if (irClass != null) { + erasure += irClass + } else { + val descriptor = type.constructor.declarationDescriptor + if (descriptor is TypeParameterDescriptor) { descriptor.upperBounds.forEach { - computeErasure(it, erasure) + computeErasure(it, context, erasure) } + } else { + TODO(descriptor.toString()) } - else -> TODO(descriptor.toString()) } } -internal fun KotlinType.erasure(): List { +internal fun KotlinType.erasure(context: Context): List { val result = mutableListOf() - computeErasure(this, result) + computeErasure(this, context, result) return result } -private fun MemberScope.getOverridingOf(function: FunctionDescriptor) = when (function) { - is PropertyGetterDescriptor -> - this.getContributedVariables(function.correspondingProperty.name, NoLookupLocation.FROM_BACKEND) - .firstOrNull { OverridingUtil.overrides(it, function.correspondingProperty) }?.getter - - is PropertySetterDescriptor -> - this.getContributedVariables(function.correspondingProperty.name, NoLookupLocation.FROM_BACKEND) - .firstOrNull { OverridingUtil.overrides(it, function.correspondingProperty) }?.setter - - else -> this.getContributedFunctions(function.name, NoLookupLocation.FROM_BACKEND) - .firstOrNull { OverridingUtil.overrides(it, function) } +private fun IrClass.getOverridingOf(function: FunctionDescriptor) = (function as? SimpleFunctionDescriptor)?.let { + it.allOverriddenDescriptors.atMostOne { it.parent == this } } private fun IrTypeOperator.isCast() = @@ -122,7 +113,7 @@ private class VariableValues { if (element !is IrGetValue) result += element else { - val descriptor = element.descriptor + val descriptor = element.symbol.owner if (descriptor is VariableDescriptor && !seen.contains(descriptor)) dfs(descriptor, seen, result) } @@ -130,7 +121,8 @@ private class VariableValues { } } -private class ExpressionValuesExtractor(val returnableBlockValues: Map>, +private class ExpressionValuesExtractor(val context: Context, + val returnableBlockValues: Map>, val suspendableExpressionValues: Map>) { fun forEachValue(expression: IrExpression, block: (IrExpression) -> Unit) { @@ -187,11 +179,14 @@ private class ExpressionValuesExtractor(val returnableBlockValues: Map block(expression) else -> { - if ((expression.type.isUnit() || expression.type.isNothing())) { - block(IrGetObjectValueImpl(expression.startOffset, expression.endOffset, - expression.type, IrClassSymbolImpl(expression.type.constructor.declarationDescriptor as ClassDescriptor))) + val classSymbol = when { + expression.type.isUnit() -> context.ir.symbols.unit + expression.type.isNothing() -> context.ir.symbols.nothing + else -> TODO(ir2stringWhole(expression)) } - else TODO(ir2stringWhole(expression)) + + block(IrGetObjectValueImpl(expression.startOffset, expression.endOffset, + expression.type, classSymbol)) } } } @@ -221,7 +216,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag // All suspension points within specified suspendable expression. private val suspendableExpressionValues = mutableMapOf>() - private val expressionValuesExtractor = ExpressionValuesExtractor(returnableBlockValues, suspendableExpressionValues) + private val expressionValuesExtractor = ExpressionValuesExtractor(context, returnableBlockValues, suspendableExpressionValues) fun build(): ModuleDFG { val functions = mutableMapOf() @@ -237,7 +232,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag println("Analysing function ${declaration.descriptor}") println("IR: ${ir2stringWhole(declaration)}") } - analyze(declaration.descriptor, it) + analyze(declaration, it) } } @@ -247,11 +242,11 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag println("Analysing global field ${declaration.descriptor}") println("IR: ${ir2stringWhole(declaration)}") } - analyze(declaration.descriptor, IrSetFieldImpl(it.startOffset, it.endOffset, declaration.symbol, null, it.expression)) + analyze(declaration, IrSetFieldImpl(it.startOffset, it.endOffset, declaration.symbol, null, it.expression)) } } - private fun analyze(descriptor: CallableDescriptor, body: IrElement) { + private fun analyze(descriptor: DeclarationDescriptor, body: IrElement) { // Find all interesting expressions, variables and functions. val visitor = ElementFinderVisitor() body.acceptVoid(visitor) @@ -346,14 +341,13 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag if (expression is IrCall && expression.symbol == scheduleImplSymbol) { // Producer of scheduleImpl is called externally, we need to reflect this somehow. - @Suppress("DEPRECATION") - val producerInvocation = IrCallImpl(expression.startOffset, expression.endOffset, scheduleImplProducerInvokeDescriptor) + val producerInvocation = IrCallImpl(expression.startOffset, expression.endOffset, + scheduleImplProducerInvoke.symbol, scheduleImplProducerInvoke.descriptor) producerInvocation.dispatchReceiver = expression.getValueArgument(2) expressions += producerInvocation } if (expression is IrReturnableBlock) { - returnableBlocks.put(expression.descriptor, expression) returnableBlockValues.put(expression, mutableListOf()) } if (expression is IrSuspendableExpression) { @@ -363,8 +357,6 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag if (expression is IrSuspensionPoint) suspendableExpressionValues[suspendableExpressionStack.peek()!!]!!.add(expression) super.visitExpression(expression) - if (expression is IrReturnableBlock) - returnableBlocks.remove(expression.descriptor) if (expression is IrSuspendableExpression) suspendableExpressionStack.pop() } @@ -375,7 +367,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag } override fun visitReturn(expression: IrReturn) { - val returnableBlock = returnableBlocks[expression.returnTarget] + val returnableBlock = expression.returnTargetSymbol.owner as? IrReturnableBlock if (returnableBlock != null) { returnableBlockValues[returnableBlock]!!.add(expression.value) } else { // Non-local return. @@ -391,39 +383,43 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag } override fun visitCatch(aCatch: IrCatch) { - catchParameters.add(aCatch.parameter) + catchParameters.add(aCatch.catchParameter) super.visitCatch(aCatch) } override fun visitSetVariable(expression: IrSetVariable) { super.visitSetVariable(expression) - assignVariable(expression.descriptor, expression.value) + assignVariable(expression.symbol.owner, expression.value) } override fun visitVariable(declaration: IrVariable) { - variableValues.addEmpty(declaration.descriptor) + variableValues.addEmpty(declaration) super.visitVariable(declaration) - declaration.initializer?.let { assignVariable(declaration.descriptor, it) } + declaration.initializer?.let { assignVariable(declaration, it) } } } - private val doResumeFunctionDescriptor = context.getInternalClass("CoroutineImpl").unsubstitutedMemberScope - .getContributedFunctions(Name.identifier("doResume"), NoLookupLocation.FROM_BACKEND).single() + private val doResumeFunctionSymbol = + context.ir.symbols.coroutineImpl.owner.declarations + .filterIsInstance().single { it.name.asString() == "doResume" }.symbol + private val getContinuationSymbol = context.ir.symbols.getContinuation private val continuationType = getContinuationSymbol.descriptor.returnType!! private val arrayGetSymbol = context.ir.symbols.arrayGet private val arraySetSymbol = context.ir.symbols.arraySet private val scheduleImplSymbol = context.ir.symbols.scheduleImpl + private val scheduleImplProducerClassSymbol = context.ir.symbols.functions[0] private val scheduleImplProducerParam = scheduleImplSymbol.descriptor.valueParameters[2].also { assert(it.name.asString() == "producer") + assert(it.type.constructor.declarationDescriptor == scheduleImplProducerClassSymbol.descriptor) } - private val scheduleImplProducerInvokeDescriptor = scheduleImplProducerParam.type.memberScope - .getContributedFunctions(Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND).single() + private val scheduleImplProducerInvoke = scheduleImplProducerClassSymbol.owner.simpleFunctions() + .single { it.name == OperatorNameConventions.INVOKE } private inner class FunctionDFGBuilder(val expressionValuesExtractor: ExpressionValuesExtractor, val variableValues: VariableValues, - val descriptor: CallableDescriptor, + val descriptor: DeclarationDescriptor, val expressions: List, val returnValues: List, val thrownValues: List, @@ -432,14 +428,15 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag private val allParameters = (descriptor as? FunctionDescriptor)?.allParameters ?: emptyList() private val templateParameters = allParameters.withIndex().associateBy({ it.value }, { DataFlowIR.Node.Parameter(it.index) }) - private val continuationParameter = - if (descriptor.isSuspend) - DataFlowIR.Node.Parameter(allParameters.size) - else { - if (doResumeFunctionDescriptor in descriptor.overriddenDescriptors) // is a CoroutineImpl inheritor. - templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation. - else null - } + private val continuationParameter = if (descriptor !is IrSimpleFunction) { + null + } else if (descriptor.isSuspend) { + DataFlowIR.Node.Parameter(allParameters.size) + } else if (doResumeFunctionSymbol in descriptor.overriddenSymbols) { // is a CoroutineImpl inheritor. + templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation. + } else { + null + } private fun getContinuation() = continuationParameter ?: error("Function $descriptor has no continuation parameter") @@ -457,19 +454,28 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag private fun choosePrimary(erasure: List): ClassDescriptor { if (erasure.size == 1) return erasure[0] // A parameter with constraints - choose class if exists. - return erasure.singleOrNull { !it.isInterface } ?: context.builtIns.any + return erasure.singleOrNull { !it.isInterface } ?: context.ir.symbols.any.owner } fun build(): DataFlowIR.Function { + val isSuspend = descriptor is IrSimpleFunction && descriptor.isSuspend + expressions.forEach { getNode(it) } + + val returnNodeType = when (descriptor) { + is IrField -> descriptor.type + is IrFunction -> descriptor.returnType + else -> error(descriptor) + } + val returnsNode = DataFlowIR.Node.Variable( values = returnValues.map { expressionToEdge(it) }, - type = symbolTable.mapType(descriptor.returnType ?: context.builtIns.unitType), + type = symbolTable.mapType(returnNodeType), kind = DataFlowIR.VariableKind.Temporary ) val throwsNode = DataFlowIR.Node.Variable( values = thrownValues.map { expressionToEdge(it) }, - type = symbolTable.mapClass(context.builtIns.throwable), + type = symbolTable.mapClass(context.ir.symbols.throwable.owner), kind = DataFlowIR.VariableKind.Temporary ) variables.forEach { descriptor, node -> @@ -478,12 +484,12 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag } } val allNodes = nodes.values + variables.values + templateParameters.values + returnsNode + throwsNode + - (if (descriptor.isSuspend) listOf(continuationParameter!!) else emptyList()) + (if (isSuspend) listOf(continuationParameter!!) else emptyList()) - val parameterTypes = (allParameters.map { it.type } + (if (descriptor.isSuspend) listOf(continuationType) else emptyList())) - .map { symbolTable.mapClass(choosePrimary(it.erasure())) } + val parameterTypes = (allParameters.map { it.type } + (if (isSuspend) listOf(continuationType) else emptyList())) + .map { symbolTable.mapClass(choosePrimary(it.erasure(context))) } .toTypedArray() - val returnType = if (descriptor.isSuspend) context.builtIns.anyType else (descriptor.returnType ?: context.builtIns.unitType) + val returnType = if (isSuspend) context.builtIns.anyType else returnNodeType return DataFlowIR.Function( symbol = symbolTable.mapFunction(descriptor), parameterTypes = parameterTypes, @@ -499,10 +505,10 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag private fun getNode(expression: IrExpression): DataFlowIR.Node { if (expression is IrGetValue) { - val descriptor = expression.descriptor - if (descriptor is ParameterDescriptor) + val descriptor = expression.symbol.owner + if (descriptor is IrValueParameter) return templateParameters[descriptor]!! - return variables[descriptor as VariableDescriptor]!! + return variables[descriptor]!! } return nodes.getOrPut(expression) { DEBUG_OUTPUT(0) { @@ -541,7 +547,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag symbolTable.mapType(value.type), if (value.type.isNothing()) // is not a singleton though its instance is get with operation. null - else symbolTable.mapFunction(value.descriptor.constructors.single()) + else symbolTable.mapFunction(value.symbol.owner.constructors.single()) ) is IrCall -> when (value.symbol) { @@ -554,7 +560,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag expressionToEdge(value.getValueArgument(0)!!), expressionToEdge(value.getValueArgument(1)!!)) else -> { - val callee = value.descriptor + val callee = value.symbol.owner as IrFunction val arguments = value.getArguments() .map { expressionToEdge(it.second) } .let { @@ -580,11 +586,11 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag symbolTable.mapClass(owner), callee.functionName.localHash.value, arguments, - symbolTable.mapType(callee.returnType!!), + symbolTable.mapType(callee.returnType), value ) } else { - val vtableIndex = vTableBuilder.vtableIndex(callee) + val vtableIndex = vTableBuilder.vtableIndex(callee as IrSimpleFunction) assert(vtableIndex >= 0, { "Unable to find function $callee in vtable of $owner" }) DataFlowIR.Node.VtableCall( symbolTable.mapFunction(callee.target), @@ -596,7 +602,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag ) } } else { - val actualCallee = (value.superQualifier?.unsubstitutedMemberScope?.getOverridingOf(callee) ?: callee).target + val actualCallee = (value.superQualifierSymbol?.owner?.getOverridingOf(callee) ?: callee).target DataFlowIR.Node.StaticCall( symbolTable.mapFunction(actualCallee), arguments, @@ -611,12 +617,12 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag is IrDelegatingConstructorCall -> { val thiz = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, - createValueSymbol((descriptor as ConstructorDescriptor).constructedClass.thisAsReceiverParameter)) + (descriptor as ConstructorDescriptor).constructedClass.thisReceiver!!.symbol) val arguments = listOf(thiz) + value.getArguments().map { it.second } DataFlowIR.Node.StaticCall( - symbolTable.mapFunction(value.descriptor), + symbolTable.mapFunction(value.symbol.owner), arguments.map { expressionToEdge(it) }, - symbolTable.mapClass(context.builtIns.unit), + symbolTable.mapClass(context.ir.symbols.unit.owner), symbolTable.mapType(thiz.type), value ) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt index 325bee1bf5c..86fb5380ab9 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt @@ -20,20 +20,19 @@ import org.jetbrains.kotlin.backend.common.descriptors.allParameters import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract import org.jetbrains.kotlin.backend.konan.descriptors.isInterface +import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.isObjCClass import org.jetbrains.kotlin.backend.konan.isValueType import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.isExported import org.jetbrains.kotlin.backend.konan.llvm.localHash import org.jetbrains.kotlin.backend.konan.llvm.symbolName -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrField -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptorBase +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid @@ -421,7 +420,7 @@ internal object DataFlowIR { private inline fun takeName(block: () -> String) = if (TAKE_NAMES) block() else null val classMap = mutableMapOf() - val functionMap = mutableMapOf() + val functionMap = mutableMapOf() private val NAME_ESCAPES = Name.identifier("Escapes") private val NAME_POINTS_TO = Name.identifier("PointsTo") @@ -432,10 +431,10 @@ internal object DataFlowIR { private val konanPackage = context.builtIns.builtInsModule.getPackage(FQ_NAME_KONAN).memberScope private val escapesAnnotationDescriptor = konanPackage.getContributedClassifier( - NAME_ESCAPES, NoLookupLocation.FROM_BACKEND) as ClassDescriptor + NAME_ESCAPES, NoLookupLocation.FROM_BACKEND) as org.jetbrains.kotlin.descriptors.ClassDescriptor private val escapesWhoDescriptor = escapesAnnotationDescriptor.unsubstitutedPrimaryConstructor!!.valueParameters.single() private val pointsToAnnotationDescriptor = konanPackage.getContributedClassifier( - NAME_POINTS_TO, NoLookupLocation.FROM_BACKEND) as ClassDescriptor + NAME_POINTS_TO, NoLookupLocation.FROM_BACKEND) as org.jetbrains.kotlin.descriptors.ClassDescriptor private val pointsToOnWhomDescriptor = pointsToAnnotationDescriptor.unsubstitutedPrimaryConstructor!!.valueParameters.single() var privateTypeIndex = 0 @@ -448,17 +447,17 @@ internal object DataFlowIR { } override fun visitFunction(declaration: IrFunction) { - declaration.body?.let { mapFunction(declaration.descriptor) } + declaration.body?.let { mapFunction(declaration) } } override fun visitField(declaration: IrField) { - declaration.initializer?.let { mapFunction(declaration.descriptor) } + declaration.initializer?.let { mapFunction(declaration) } } override fun visitClass(declaration: IrClass) { declaration.acceptChildrenVoid(this) - mapClass(declaration.descriptor) + mapClass(declaration) } }, data = null) } @@ -501,40 +500,27 @@ internal object DataFlowIR { return type } - fun mapType(type: KotlinType) = mapClass(type.erasure().single()) + fun mapType(type: KotlinType) = mapClass(type.erasure(context).single()) // TODO: use from LlvmDeclarations. - private fun getFqName(descriptor: DeclarationDescriptor): FqName { - if (descriptor is PackageFragmentDescriptor) { - return descriptor.fqName - } - - val containingDeclaration = descriptor.containingDeclaration - val parent = if (containingDeclaration != null) { - getFqName(containingDeclaration) - } else { - FqName.ROOT - } - - val localName = descriptor.name - return parent.child(localName) - } + private fun getFqName(descriptor: DeclarationDescriptor): FqName = + descriptor.parent.fqNameSafe.child(descriptor.name) private val FunctionDescriptor.internalName get() = getFqName(this).asString() + "#internal" - fun mapFunction(descriptor: CallableDescriptor) = descriptor.original.let { + fun mapFunction(descriptor: DeclarationDescriptor) = descriptor.original.let { functionMap.getOrPut(it) { when (it) { - is PropertyDescriptor -> { + is IrField -> { // A global property initializer. - assert (it.dispatchReceiverParameter == null) { "All local properties initializers should've been lowered" } + assert (it.parent !is IrClass) { "All local properties initializers should've been lowered" } FunctionSymbol.Private(privateFunIndex++, 0, module, -1, true, takeName { "${it.symbolName}_init" }) } is FunctionDescriptor -> { val name = if (it.isExported()) it.symbolName else it.internalName val numberOfParameters = it.allParameters.size + if (it.isSuspend) 1 else 0 - if (it.module != irModule.descriptor || it.isExternal || (it is IrBuiltinOperatorDescriptorBase)) { + if (it.module != irModule.descriptor || it.isExternal || (it.origin == IrDeclarationOrigin.IR_BUILTINS_STUB)) { val escapesAnnotation = it.annotations.findAnnotation(FQ_NAME_ESCAPES) val pointsToAnnotation = it.annotations.findAnnotation(FQ_NAME_POINTS_TO) @Suppress("UNCHECKED_CAST") @@ -544,7 +530,7 @@ internal object DataFlowIR { FunctionSymbol.External(name.localHash.value, numberOfParameters, false, escapesBitMask, pointsToBitMask?.let { it.map { it.value }.toIntArray() }, takeName { name }) } else { - val isAbstract = it.modality == Modality.ABSTRACT + val isAbstract = it is SimpleFunctionDescriptor && it.modality == Modality.ABSTRACT val classDescriptor = it.containingDeclaration as? ClassDescriptor val placeToFunctionsTable = !isAbstract && it !is ConstructorDescriptor && classDescriptor != null && classDescriptor.kind != ClassKind.ANNOTATION_CLASS diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt index 98c2a125065..5a31af09afc 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt @@ -66,7 +66,7 @@ internal object Devirtualization { return this } - val entryPoint = findMainEntryPoint(context) + val entryPoint = context.ir.symbols.entryPoint?.owner val exportedFunctions = if (entryPoint != null) listOf(moduleDFG.symbolTable.mapFunction(entryPoint).resolved()) @@ -97,7 +97,7 @@ internal object Devirtualization { val moduleDFG: ModuleDFG, val externalModulesDFG: ExternalModulesDFG) { - private val entryPoint = findMainEntryPoint(context) + private val entryPoint = context.ir.symbols.entryPoint?.owner private val symbolTable = moduleDFG.symbolTable @@ -506,7 +506,7 @@ internal object Devirtualization { } val result = mutableMapOf>() - val nothing = symbolTable.mapClass(context.builtIns.nothing) + val nothing = symbolTable.mapClass(context.ir.symbols.nothing.owner) functions.values .asSequence() .filter { constraintGraph.functions.containsKey(it.symbol) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt index f36886d7c89..ca46d51f4ba 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt @@ -19,7 +19,6 @@ package org.jetbrains.kotlin.backend.konan.optimizations import org.jetbrains.kotlin.backend.konan.DirectedGraphCondensationBuilder import org.jetbrains.kotlin.backend.konan.DirectedGraphMultiNode import org.jetbrains.kotlin.backend.konan.llvm.Lifetime -import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.ir.IrElement internal object EscapeAnalysis { @@ -605,7 +604,7 @@ internal object EscapeAnalysis { reachable += parameters.size reachabilities.add(reachable.toIntArray()) visited.forEach { node -> - if (node !is ParameterDescriptor) + if (node !is DataFlowIR.Node.Parameter) nodes[node]!!.addIncomingParameter(it.index) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DescriptorTable.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DescriptorTable.kt index 6dff766a674..cc37fd2eab8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DescriptorTable.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/DescriptorTable.kt @@ -16,27 +16,30 @@ package org.jetbrains.kotlin.backend.konan.serialization -import kotlin.properties.Delegates +import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember +import org.jetbrains.kotlin.backend.konan.getObjCMethodInfo +import org.jetbrains.kotlin.backend.konan.isValueType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns -import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.serialization.deserialization.NameResolver -import org.jetbrains.kotlin.serialization.ProtoBuf -import org.jetbrains.kotlin.serialization.ProtoBuf.QualifiedNameTable.QualifiedName -import org.jetbrains.kotlin.backend.konan.llvm.isExported -import org.jetbrains.kotlin.backend.konan.llvm.typeInfoSymbolName -import org.jetbrains.kotlin.backend.konan.llvm.symbolName import org.jetbrains.kotlin.backend.konan.llvm.localHash +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.constants.StringValue +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty internal fun DeclarationDescriptor.symbolName(): String = when (this) { is FunctionDescriptor - -> this.symbolName + -> this.uniqueName is PropertyDescriptor - -> this.symbolName + -> this.uniqueName is ClassDescriptor - -> this.typeInfoSymbolName + -> this.uniqueName else -> error("Unexpected exported descriptor: $this") } @@ -91,3 +94,203 @@ val IrBuiltIns.irBuiltInDescriptors .map(IrSimpleFunction::descriptor) +// The declarations below are copied from `BinaryInterface.kt` when it was based on descriptors. +// TODO: do not serialize descriptors of non-exported declarations. + +/** + * Defines whether the declaration is exported, i.e. visible from other modules. + * + * Exported declarations must have predictable and stable ABI + * that doesn't depend on any internal transformations (e.g. IR lowering), + * and so should be computable from the descriptor itself without checking a backend state. + */ +internal tailrec fun DeclarationDescriptor.isExported(): Boolean { + assert(!this.isExpectMember) { this } + + if (this.annotations.findAnnotation(symbolNameAnnotation) != null) { + // Treat any `@SymbolName` declaration as exported. + return true + } + if (this.annotations.findAnnotation(exportForCppRuntimeAnnotation) != null) { + // Treat any `@ExportForCppRuntime` declaration as exported. + return true + } + if (this.annotations.findAnnotation(cnameAnnotation) != null) { + // Treat `@CName` declaration as exported. + return true + } + if (this.annotations.hasAnnotation(exportForCompilerAnnotation)) { + return true + } + if (this.annotations.hasAnnotation(publishedApiAnnotation)){ + return true + } + if (this.annotations.hasAnnotation(inlineExposedAnnotation)){ + return true + } + + if (DescriptorUtils.isAnonymousObject(this)) + return false + + if (this is ConstructorDescriptor && constructedClass.kind.isSingleton) { + // Currently code generator can access the constructor of the singleton, + // so ignore visibility of the constructor itself. + return constructedClass.isExported() + } + + if (this is PropertyAccessorDescriptor) { + return this.correspondingProperty.isExported() + } + + if (this is DeclarationDescriptorWithVisibility && !this.visibility.isPublicAPI) { + // If the declaration is explicitly marked as non-public, + // then it must not be accessible from other modules. + return false + } + + if (this is DeclarationDescriptorNonRoot) { + // If the declaration is not root, then check its container too. + return containingDeclaration.isExported() + } + + return true +} + +private val symbolNameAnnotation = FqName("konan.SymbolName") + +private val exportForCppRuntimeAnnotation = FqName("konan.internal.ExportForCppRuntime") + +private val cnameAnnotation = FqName("konan.internal.CName") + +private val exportForCompilerAnnotation = FqName("konan.internal.ExportForCompiler") + +private val publishedApiAnnotation = FqName("kotlin.PublishedApi") + +private val inlineExposedAnnotation = FqName("kotlin.internal.InlineExposed") + +private fun acyclicTypeMangler(visited: MutableSet, type: KotlinType): String { + val descriptor = TypeUtils.getTypeParameterDescriptorOrNull(type) + if (descriptor != null) { + val upperBounds = if (visited.contains(descriptor)) "" else { + + visited.add(descriptor) + + descriptor.upperBounds.map { + val bound = acyclicTypeMangler(visited, it) + if (bound == "kotlin.Any?") "" else "_$bound" + }.joinToString("") + } + return "#GENERIC" + upperBounds + } + + var hashString = TypeUtils.getClassDescriptor(type)!!.fqNameSafe.asString() + if (!type.arguments.isEmpty()) { + hashString += "<${type.arguments.map { + if (it.isStarProjection()) { + "#STAR" + } else { + val variance = it.projectionKind.label + val projection = if (variance == "") "" else "${variance}_" + projection + acyclicTypeMangler(visited, it.type) + } + }.joinToString(",")}>" + } + + if (type.isMarkedNullable) hashString += "?" + return hashString +} + +private fun typeToHashString(type: KotlinType) + = acyclicTypeMangler(mutableSetOf(), type) + +private val FunctionDescriptor.signature: String + get() { + val extensionReceiverPart = this.extensionReceiverParameter?.let { "@${typeToHashString(it.type)}." } ?: "" + + val argsPart = this.valueParameters.map { + typeToHashString(it.type) + }.joinToString(";") + + // Distinguish value types and references - it's needed for calling virtual methods through bridges. + // Also is function has type arguments - frontend allows exactly matching overrides. + val signatureSuffix = + when { + this.typeParameters.isNotEmpty() -> "Generic" + returnType.let { it != null && it.isValueType() } -> "ValueType" + returnType.let { it != null && !KotlinBuiltIns.isUnitOrNullableUnit(it) } -> typeToHashString(returnType!!) + else -> "" + } + + return "$extensionReceiverPart($argsPart)$signatureSuffix" + } + +// TODO: rename to indicate that it has signature included +private val FunctionDescriptor.uniqueLocalName: String + get() { + with(this.original) { // basic support for generics + this.getObjCMethodInfo()?.let { + return buildString { + if (extensionReceiverParameter != null) { + append(TypeUtils.getClassDescriptor(extensionReceiverParameter!!.type)!!.name) + append(".") + } + + append("objc:") + append(it.selector) + } + } + + return "$name$signature" + } + } + +private val FunctionDescriptor.uniqueName: String + get() { + if (!this.isExported()) { + throw AssertionError(this.toString()) + } + + this.annotations.findAnnotation(symbolNameAnnotation)?.let { + if (this.isExternal) { + return getStringValue(it)!! + } else { + // ignore; TODO: report compile error + } + } + + this.annotations.findAnnotation(exportForCppRuntimeAnnotation)?.let { + val name = getStringValue(it) ?: this.name.asString() + return name // no wrapping currently required + } + + val containingDeclarationPart = containingDeclaration.fqNameSafe.let { + if (it.isRoot) "" else "$it." + } + return "kfun:$containingDeclarationPart$uniqueLocalName" + } + +private val PropertyDescriptor.uniqueName: String + get() { + val containingDeclarationPart = containingDeclaration.fqNameSafe.let { + if (it.isRoot) "" else "$it." + } + val extensionReceiverPart = this.extensionReceiverParameter?.let { "${it.type}." } ?: "" + return "kprop:$containingDeclarationPart$extensionReceiverPart$name" + + } + +private fun getStringValue(annotation: AnnotationDescriptor): String? { + annotation.allValueArguments.values.ifNotEmpty { + val stringValue = this.single() as StringValue + return stringValue.value + } + + return null +} + +private val ClassDescriptor.uniqueName: String + get() { + assert (this.isExported()) + return "ktype:" + this.fqNameSafe.toString() + } + diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt index 8fd5a2e8ed3..d5015c0491b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt @@ -39,6 +39,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.impl.* import org.jetbrains.kotlin.ir.util.addFakeOverrides import org.jetbrains.kotlin.ir.util.createParameterDeclarations +import org.jetbrains.kotlin.ir.util.setOverrides +import org.jetbrains.kotlin.ir.util.setSuperSymbols import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer import org.jetbrains.kotlin.serialization.KonanIr import org.jetbrains.kotlin.serialization.KonanIr.IrConst.ValueCase.* @@ -1209,6 +1211,7 @@ internal class IrDeserializer(val context: Context, clazz.createParameterDeclarations() clazz.addFakeOverrides() + clazz.setSuperSymbols(context.ir.symbols.symbolTable) return clazz @@ -1222,6 +1225,7 @@ internal class IrDeserializer(val context: Context, descriptor, body as IrBody) function.createParameterDeclarations() + function.setOverrides(context.ir.symbols.symbolTable) proto.defaultArgumentList.forEach { val expr = deserializeExpression(it.value) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt index c0480b54c0a..af5d330f1e1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt @@ -20,19 +20,12 @@ import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol -import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.visitors.* @Deprecated("") @@ -93,7 +86,7 @@ private fun IrModuleFragment.mergeFrom(other: IrModuleFragment): Unit { if (thisPackage == null) { this.externalPackageFragments.add(it) } else { - thisPackage.declarations.addAll(it.declarations) + thisPackage.addChildren(it.declarations) } } } @@ -120,42 +113,47 @@ private class IrUnboundSymbolReplacer( val descriptorToSymbol: Map ) : IrElementTransformerVoid() { - private inline fun > S.replace( + private val localDescriptorToSymbol = mutableMapOf>() + + private inline fun withLocal(symbol: IrSymbol?, block: () -> R): R { + if (symbol == null) return block() + + val locals = localDescriptorToSymbol.getOrPut(symbol.descriptor) { mutableListOf() } + locals.add(symbol) + return try { + block() + } finally { + locals.removeAt(locals.lastIndex) + } + } + + private inline fun S.replace( referenceSymbol: (SymbolTable, D) -> S): S? { if (this.isBound) { return null } + localDescriptorToSymbol[this.descriptor]?.lastOrNull()?.let { + return it as S + } + + descriptorToSymbol[this.descriptor]?.let { return it as S } - return referenceSymbol(symbolTable, this.descriptor) + return referenceSymbol(symbolTable, this.descriptor as D) } - private inline fun > S.replaceOrSame( + private inline fun S.replaceOrSame( referenceSymbol: (SymbolTable, D) -> S): S = this.replace(referenceSymbol) ?: this - private fun IrFunctionSymbol.replace( - referenceSymbol: (SymbolTable, FunctionDescriptor) -> IrFunctionSymbol): IrFunctionSymbol? { - - if (this.isBound) { - return null - } - - descriptorToSymbol[this.descriptor]?.let { - return it as IrFunctionSymbol - } - - return referenceSymbol(symbolTable, this.descriptor) - } - private inline fun S.replaceLocal(): S? { return if (this.isBound) { null } else { - descriptorToSymbol[this.descriptor] as S + (localDescriptorToSymbol[this.descriptor]?.lastOrNull() ?: descriptorToSymbol[this.descriptor]) as S } } @@ -198,17 +196,8 @@ private class IrUnboundSymbolReplacer( } override fun visitClassReference(expression: IrClassReference): IrExpression { - val symbol = expression.symbol.let { - if (it.isBound) { - return super.visitClassReference(expression) - } - - descriptorToSymbol[it.descriptor]?.let { - it as IrClassifierSymbol - } - - symbolTable.referenceClassifier(it.descriptor) - } + val symbol = expression.symbol.replace(SymbolTable::referenceClassifier) + ?: return super.visitClassReference(expression) expression.transformChildrenVoid(this) return with(expression) { @@ -216,6 +205,18 @@ private class IrUnboundSymbolReplacer( } } + override fun visitClass(declaration: IrClass): IrStatement { + declaration.superClasses.forEachIndexed { index, symbol -> + val newSymbol = symbol.replace(SymbolTable::referenceClass) + if (newSymbol != null) { + declaration.superClasses[index] = newSymbol + } + } + withLocal(declaration.thisReceiver?.symbol) { + return super.visitClass(declaration) + } + } + override fun visitGetField(expression: IrGetField): IrExpression { val symbol = expression.symbol.replaceOrSame(SymbolTable::referenceField) @@ -358,7 +359,20 @@ private class IrUnboundSymbolReplacer( override fun visitFunction(declaration: IrFunction): IrStatement { returnTargetStack.push(declaration.symbol) try { - return super.visitFunction(declaration) + if (declaration is IrSimpleFunction) { + declaration.overriddenSymbols.forEachIndexed { index, symbol -> + val newSymbol = symbol.replace(SymbolTable::referenceSimpleFunction) + if (newSymbol != null) { + declaration.overriddenSymbols[index] = newSymbol + } + } + } + + withLocal(declaration.dispatchReceiverParameter?.symbol) { + withLocal(declaration.extensionReceiverParameter?.symbol) { + return super.visitFunction(declaration) + } + } } finally { returnTargetStack.pop() } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt index 60391057228..74862c87041 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt @@ -17,23 +17,25 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.resolve.OverridingStrategy +import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.types.KotlinType +import java.lang.reflect.Proxy //TODO: delete file on next kotlin dependency update internal fun IrExpression.isNullConst() = this is IrConst<*> && this.kind == IrConstKind.Null @@ -74,5 +76,272 @@ internal fun IrFile.addTopLevelInitializer(expression: IrExpression) { irField.initializer = IrExpressionBodyImpl(expression.startOffset, expression.endOffset, initializer) - this.declarations.add(irField) + this.addChild(irField) +} + +fun IrClass.addFakeOverrides() { + + val startOffset = this.startOffset + val endOffset = this.endOffset + + descriptor.unsubstitutedMemberScope.getContributedDescriptors() + .filterIsInstance() + .filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE } + .forEach { + this.addChild(createFakeOverride(it, startOffset, endOffset)) + } +} + +private fun createFakeOverride(descriptor: CallableMemberDescriptor, startOffset: Int, endOffset: Int): IrDeclaration { + + fun FunctionDescriptor.createFunction(): IrFunction = IrFunctionImpl( + startOffset, endOffset, + IrDeclarationOrigin.FAKE_OVERRIDE, this + ).apply { + createParameterDeclarations() + } + + return when (descriptor) { + is FunctionDescriptor -> descriptor.createFunction() + is PropertyDescriptor -> + IrPropertyImpl(startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, descriptor).apply { + // TODO: add field if getter is missing? + getter = descriptor.getter?.createFunction() + setter = descriptor.setter?.createFunction() + } + else -> TODO(descriptor.toString()) + } +} + +fun IrFunction.createParameterDeclarations() { + fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl( + innerStartOffset(this), innerEndOffset(this), + IrDeclarationOrigin.DEFINED, + this + ).also { + it.parent = this@createParameterDeclarations + } + + dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.irValueParameter() + extensionReceiverParameter = descriptor.extensionReceiverParameter?.irValueParameter() + + assert(valueParameters.isEmpty()) + descriptor.valueParameters.mapTo(valueParameters) { it.irValueParameter() } + + assert(typeParameters.isEmpty()) + descriptor.typeParameters.mapTo(typeParameters) { + IrTypeParameterImpl( + innerStartOffset(it), innerEndOffset(it), + IrDeclarationOrigin.DEFINED, + it + ).also { typeParameter -> + typeParameter.parent = this + } + } +} + +fun IrSimpleFunction.setOverrides(symbolTable: SymbolTable) { + assert(this.overriddenSymbols.isEmpty()) + + this.descriptor.overriddenDescriptors.mapTo(this.overriddenSymbols) { + symbolTable.referenceSimpleFunction(it.original) + } + + this.typeParameters.forEach { it.setSupers(symbolTable) } +} + +fun IrClass.simpleFunctions(): List = this.declarations.flatMap { + when (it) { + is IrSimpleFunction -> listOf(it) + is IrProperty -> listOfNotNull(it.getter as IrSimpleFunction?, it.setter as IrSimpleFunction?) + else -> emptyList() + } +} + +fun IrClass.createParameterDeclarations() { + descriptor.thisAsReceiverParameter.let { + thisReceiver = IrValueParameterImpl( + innerStartOffset(it), innerEndOffset(it), + IrDeclarationOrigin.INSTANCE_RECEIVER, + it + ).also { valueParameter -> + valueParameter.parent = this + } + } + + assert(typeParameters.isEmpty()) + descriptor.declaredTypeParameters.mapTo(typeParameters) { + IrTypeParameterImpl( + innerStartOffset(it), innerEndOffset(it), + IrDeclarationOrigin.DEFINED, + it + ).also { typeParameter -> + typeParameter.parent = this + } + } +} + +fun IrClass.setSuperSymbols(supers: List) { + assert(this.superDescriptors().toSet() == supers.map { it.descriptor }.toSet()) + assert(this.superClasses.isEmpty()) + supers.mapTo(this.superClasses) { it.symbol } + + val superMembers = supers.flatMap { + it.simpleFunctions() + }.associateBy { it.descriptor } + + this.simpleFunctions().forEach { + assert(it.overriddenSymbols.isEmpty()) + + it.descriptor.overriddenDescriptors.mapTo(it.overriddenSymbols) { + val superMember = superMembers[it.original] ?: error(it.original) + superMember.symbol + } + } +} + +private fun IrClass.superDescriptors() = + this.descriptor.typeConstructor.supertypes.map { it.constructor.declarationDescriptor as ClassDescriptor } + +fun IrClass.setSuperSymbols(symbolTable: SymbolTable) { + assert(this.superClasses.isEmpty()) + this.superDescriptors().mapTo(this.superClasses) { symbolTable.referenceClass(it) } + this.simpleFunctions().forEach { + it.setOverrides(symbolTable) + } + this.typeParameters.forEach { + it.setSupers(symbolTable) + } +} + +fun IrTypeParameter.setSupers(symbolTable: SymbolTable) { + assert(this.superClassifiers.isEmpty()) + this.descriptor.upperBounds.mapNotNullTo(this.superClassifiers) { + it.constructor.declarationDescriptor?.let { + if (it is TypeParameterDescriptor) { + IrTypeParameterSymbolImpl(it) // Workaround for deserialized inline functions + } else { + symbolTable.referenceClassifier(it) + } + } + } +} + +fun IrClass.setSuperSymbolsAndAddFakeOverrides(supers: List) { + val overriddenSuperMembers = this.declarations.map { it.descriptor } + .filterIsInstance().flatMap { it.overriddenDescriptors.map { it.original } } + + val unoverriddenSuperMembers = supers.flatMap { + it.declarations.mapNotNull { + when (it) { + is IrSimpleFunction -> it.descriptor + is IrProperty -> it.descriptor + else -> null + } + } + } - overriddenSuperMembers + + val irClass = this + + val overridingStrategy = object : OverridingStrategy() { + override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) { + irClass.addChild(createFakeOverride(fakeOverride, startOffset, endOffset)) + } + + override fun inheritanceConflict(first: CallableMemberDescriptor, second: CallableMemberDescriptor) { + error("inheritance conflict in synthesized class ${irClass.descriptor}:\n $first\n $second") + } + + override fun overrideConflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) { + error("override conflict in synthesized class ${irClass.descriptor}:\n $fromSuper\n $fromCurrent") + } + } + + unoverriddenSuperMembers.groupBy { it.name }.forEach { (name, members) -> + OverridingUtil.generateOverridesInFunctionGroup( + name, + members, + emptyList(), + this.descriptor, + overridingStrategy + ) + } + + this.setSuperSymbols(supers) +} + +private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int = + descriptor.startOffset ?: this.startOffset + +private fun IrElement.innerEndOffset(descriptor: DeclarationDescriptorWithSource): Int = + descriptor.endOffset ?: this.endOffset + +inline fun stub(name: String): T { + return Proxy.newProxyInstance(T::class.java.classLoader, arrayOf(T::class.java)) { proxy, method, methodArgs -> + if (method.name == "toString" && method.parameterCount == 0) { + "${T::class.simpleName} stub for $name" + } else { + error("${T::class.simpleName}.${method.name} is not supported for $name") + } + } as T +} + +fun IrDeclarationContainer.addChildren(declarations: List) { + declarations.forEach { this.addChild(it) } +} + +fun IrDeclarationContainer.addChild(declaration: IrDeclaration) { + this.declarations += declaration + declaration.accept(SetDeclarationsParentVisitor, this) +} + +object SetDeclarationsParentVisitor : IrElementVisitor { + override fun visitElement(element: IrElement, data: IrDeclarationParent) { + if (element !is IrDeclarationParent) { + element.acceptChildren(this, data) + } + } + + override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclarationParent) { + declaration.parent = data + super.visitDeclaration(declaration, data) + } +} + +fun IrModuleFragment.checkDeclarationParents() { + this.accept(CheckDeclarationParentsVisitor, null) + this.dependencyModules.forEach { dependencyModule -> + dependencyModule.externalPackageFragments.forEach { + it.accept(CheckDeclarationParentsVisitor, null) + } + } +} + +object CheckDeclarationParentsVisitor : IrElementVisitor { + + override fun visitElement(element: IrElement, data: IrDeclarationParent?) { + element.acceptChildren(this, element as? IrDeclarationParent ?: data) + } + + override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclarationParent?) { + if (declaration !is IrVariable) { + checkParent(declaration, data) + } else { + // Don't check IrVariable parent. + } + + super.visitDeclaration(declaration, data) + } + + private fun checkParent(declaration: IrDeclaration, expectedParent: IrDeclarationParent?) { + val parent = try { + declaration.parent + } catch (e: Throwable) { + error("$declaration for ${declaration.descriptor} has no parent") + } + + if (parent != expectedParent) { + error("$declaration for ${declaration.descriptor} has unexpected parent $parent") + } + } } diff --git a/gradle.properties b/gradle.properties index 82aab666d0c..5fa6087181a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,16 +20,16 @@ remoteRoot=konan_tests #kotlinCompilerModule=org.jetbrains.kotlin:kotlin-compiler:1.1-SNAPSHOT # Download artifacts of https://teamcity.jetbrains.com/viewType.html?buildTypeId=Kotlin_120_Compiler testDataVersion=1226829:id -kotlinCompilerRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_dev_CompilerAllPlugins),number:1.2.40-dev-610/artifacts/content/maven -kotlinCompilerVersion=1.2.40-dev-610 -kotlinScriptRuntimeVersion=1.2.40-dev-610 -kotlinStdLibVersion=1.2.40-dev-610 -kotlinReflectVersion=1.2.40-dev-610 +kotlinCompilerRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_dev_CompilerAllPlugins),number:1.2.40-dev-837/artifacts/content/maven +kotlinCompilerVersion=1.2.40-dev-837 +kotlinScriptRuntimeVersion=1.2.40-dev-837 +kotlinStdLibVersion=1.2.40-dev-837 +kotlinReflectVersion=1.2.40-dev-837 konanVersion=0.6.1 org.gradle.jvmargs='-Dfile.encoding=UTF-8' ## # required for performance mesuarement tasks -kotlinStdLibJdk8Version=1.2.40-dev-610 -kotlinGradlePluginVersion=1.2.40-dev-610 +kotlinStdLibJdk8Version=1.2.40-dev-837 +kotlinGradlePluginVersion=1.2.40-dev-837