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).
This commit is contained in:
committed by
SvyatoslavScherbina
parent
011197c462
commit
610c9b5278
+5
-4
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+22
-9
@@ -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<ClassDescriptor, IrField>()
|
||||
private val bridgesDescriptors = mutableMapOf<Pair<FunctionDescriptor, BridgeDirections>, FunctionDescriptor>()
|
||||
private val bridgesDescriptors = mutableMapOf<Pair<IrSimpleFunction, BridgeDirections>, IrSimpleFunction>()
|
||||
private val loweredEnums = mutableMapOf<ClassDescriptor, LoweredEnum>()
|
||||
|
||||
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 = */ "<bridge-$bridgeDirections>${descriptor.functionName}".synthesizedName,
|
||||
/* name = */ "<bridge-$bridgeDirections>${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<ClassDescriptor, ClassVtablesBuilder>()
|
||||
private val vtableBuilders = mutableMapOf<IrClass, ClassVtablesBuilder>()
|
||||
|
||||
fun getVtableBuilder(classDescriptor: ClassDescriptor) = vtableBuilders.getOrPut(classDescriptor) {
|
||||
fun getVtableBuilder(classDescriptor: IrClass) = vtableBuilders.getOrPut(classDescriptor) {
|
||||
ClassVtablesBuilder(classDescriptor, this)
|
||||
}
|
||||
|
||||
|
||||
+7
-5
@@ -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<Name, Int>)
|
||||
|
||||
@@ -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<IrFunctionSymbol, FunctionDescriptor> {
|
||||
private fun getEnumItemGetter(enumClassDescriptor: ClassDescriptor): Pair<IrSimpleFunctionSymbol, FunctionDescriptor> {
|
||||
val getter = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||
|
||||
val typeParameterT = genericArrayType.declaredTypeParameters[0]
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
+21
-6
@@ -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) {
|
||||
|
||||
+5
@@ -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
|
||||
|
||||
+14
-19
@@ -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<OverriddenFunctionDescriptor>()
|
||||
|
||||
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())
|
||||
|
||||
+49
-171
@@ -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<ClassDescriptor>
|
||||
val superInterfacesImplementedInterfaces = superInterfaces.flatMap { it.implementedInterfaces }
|
||||
return (superClassImplementedInterfaces +
|
||||
superInterfacesImplementedInterfaces +
|
||||
superInterfaces).distinctBy { it.classId }
|
||||
superInterfaces).distinct()
|
||||
}
|
||||
|
||||
|
||||
@@ -57,21 +48,19 @@ internal val ClassDescriptor.implementedInterfaces: List<ClassDescriptor>
|
||||
*
|
||||
* TODO: this method is actually a part of resolve and probably duplicates another one
|
||||
*/
|
||||
internal fun <T : CallableMemberDescriptor> 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 : CallableMemberDescriptor> T.allOverriddenDescriptors: List<T>
|
||||
get() {
|
||||
val result = mutableListOf<T>()
|
||||
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<FunctionDescriptor>
|
||||
get () = unsubstitutedMemberScope.sortedContributedMethods
|
||||
|
||||
internal val ClassDescriptor.contributedMethods: List<FunctionDescriptor>
|
||||
get () = unsubstitutedMemberScope.contributedMethods
|
||||
|
||||
internal val MemberScope.sortedContributedMethods: List<FunctionDescriptor>
|
||||
internal val IrClass.sortedContributedMethods: List<SimpleFunctionDescriptor>
|
||||
get () = contributedMethods.sortedBy {
|
||||
it.functionName.localHash.value
|
||||
}
|
||||
|
||||
internal val MemberScope.contributedMethods: List<FunctionDescriptor>
|
||||
get () {
|
||||
val contributedDescriptors = this.getContributedDescriptors()
|
||||
|
||||
val functions = contributedDescriptors.filterIsInstance<FunctionDescriptor>()
|
||||
|
||||
val properties = contributedDescriptors.filterIsInstance<PropertyDescriptor>()
|
||||
val getters = properties.mapNotNull { it.getter }
|
||||
val setters = properties.mapNotNull { it.setter }
|
||||
|
||||
return functions + getters + setters
|
||||
}
|
||||
internal val IrClass.contributedMethods: List<SimpleFunctionDescriptor>
|
||||
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<BridgeDirection>) {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun FunctionDescriptor.bridgeDirectionsTo(overriddenDescriptor: FunctionDescriptor): BridgeDirections {
|
||||
val SimpleFunctionDescriptor.allOverriddenDescriptors: Set<SimpleFunctionDescriptor>
|
||||
get() {
|
||||
val result = mutableSetOf<SimpleFunctionDescriptor>()
|
||||
|
||||
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<DeclarationDescriptor> {
|
||||
var list = mutableListOf<DeclarationDescriptor>()
|
||||
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<FqName> {
|
||||
val result = mutableSetOf<FqName>()
|
||||
|
||||
fun getSubPackages(fqName: FqName) {
|
||||
result.add(fqName)
|
||||
module.getSubPackagesOf(fqName) { true }.forEach { getSubPackages(it) }
|
||||
}
|
||||
|
||||
getSubPackages(FqName.ROOT)
|
||||
return result
|
||||
}
|
||||
|
||||
fun ModuleDescriptor.getPackageFragments(): List<PackageFragmentDescriptor> =
|
||||
getPackagesFqNames(this).flatMap {
|
||||
getPackage(it).fragments.filter { it.module == this }
|
||||
}
|
||||
|
||||
val ClassDescriptor.enumEntries: List<ClassDescriptor>
|
||||
get() {
|
||||
assert(this.kind == ClassKind.ENUM_CLASS)
|
||||
return this.unsubstitutedMemberScope.getContributedDescriptors()
|
||||
.filterIsInstance<ClassDescriptor>()
|
||||
.filter { it.kind == ClassKind.ENUM_ENTRY }
|
||||
}
|
||||
|
||||
internal val DeclarationDescriptor.isExpectMember: Boolean
|
||||
get() = this is MemberDescriptor && this.isExpect
|
||||
|
||||
fun FunctionDescriptor.isComparisonDescriptor(map: Map<SimpleType, IrSimpleFunction>): Boolean =
|
||||
map.values.any { it.descriptor == this }
|
||||
this in map.values
|
||||
|
||||
+187
@@ -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 : CallableMemberDescriptor> 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 : CallableMemberDescriptor> T.allOverriddenDescriptors: List<T>
|
||||
get() {
|
||||
val result = mutableListOf<T>()
|
||||
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<FunctionDescriptor>
|
||||
get () = unsubstitutedMemberScope.contributedMethods
|
||||
|
||||
internal val MemberScope.contributedMethods: List<FunctionDescriptor>
|
||||
get () {
|
||||
val contributedDescriptors = this.getContributedDescriptors()
|
||||
|
||||
val functions = contributedDescriptors.filterIsInstance<FunctionDescriptor>()
|
||||
|
||||
val properties = contributedDescriptors.filterIsInstance<PropertyDescriptor>()
|
||||
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<DeclarationDescriptor> {
|
||||
var list = mutableListOf<DeclarationDescriptor>()
|
||||
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<FqName> {
|
||||
val result = mutableSetOf<FqName>()
|
||||
|
||||
fun getSubPackages(fqName: FqName) {
|
||||
result.add(fqName)
|
||||
module.getSubPackagesOf(fqName) { true }.forEach { getSubPackages(it) }
|
||||
}
|
||||
|
||||
getSubPackages(FqName.ROOT)
|
||||
return result
|
||||
}
|
||||
|
||||
fun ModuleDescriptor.getPackageFragments(): List<PackageFragmentDescriptor> =
|
||||
getPackagesFqNames(this).flatMap {
|
||||
getPackage(it).fragments.filter { it.module == this }
|
||||
}
|
||||
|
||||
val ClassDescriptor.enumEntries: List<ClassDescriptor>
|
||||
get() {
|
||||
assert(this.kind == ClassKind.ENUM_CLASS)
|
||||
return this.unsubstitutedMemberScope.getContributedDescriptors()
|
||||
.filterIsInstance<ClassDescriptor>()
|
||||
.filter { it.kind == ClassKind.ENUM_ENTRY }
|
||||
}
|
||||
|
||||
internal val DeclarationDescriptor.isExpectMember: Boolean
|
||||
get() = this is MemberDescriptor && this.isExpect
|
||||
+81
-9
@@ -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
|
||||
lateinit var moduleIndexForCodegen: ModuleIndex
|
||||
|
||||
override var symbols: KonanSymbols by Delegates.notNull()
|
||||
|
||||
fun getClass(type: KotlinType): IrClass? =
|
||||
(type.constructor.declarationDescriptor as? ClassDescriptor)?.let { get(it) }
|
||||
|
||||
fun get(descriptor: FunctionDescriptor): IrFunction {
|
||||
return moduleIndexForCodegen.functions[descriptor]
|
||||
?: symbols.symbolTable.referenceFunction(descriptor).owner as IrFunction
|
||||
}
|
||||
|
||||
fun get(descriptor: ClassDescriptor): IrClass {
|
||||
return moduleIndexForCodegen.classes[descriptor]
|
||||
?: symbols.symbolTable.referenceClass(descriptor)
|
||||
.also {
|
||||
if (!it.isBound)
|
||||
error(descriptor)
|
||||
}
|
||||
.owner
|
||||
}
|
||||
|
||||
fun getFromCurrentModule(descriptor: ClassDescriptor): IrClass = moduleIndexForCodegen.classes[descriptor]!!
|
||||
|
||||
fun getFromCurrentModule(descriptor: FunctionDescriptor): IrFunction = moduleIndexForCodegen.functions[descriptor]!!
|
||||
|
||||
fun getEnumEntryFromCurrentModule(descriptor: ClassDescriptor): IrEnumEntry =
|
||||
originalModuleIndex.enumEntries[descriptor] ?: error(descriptor)
|
||||
|
||||
fun getEnumEntry(descriptor: ClassDescriptor): IrEnumEntry {
|
||||
assert(descriptor.kind == ClassKind.ENUM_ENTRY)
|
||||
|
||||
return originalModuleIndex.enumEntries[descriptor]
|
||||
?: symbols.symbolTable.referenceEnumEntry(descriptor).owner
|
||||
}
|
||||
|
||||
fun getEnum(descriptor: ClassDescriptor): IrClass {
|
||||
assert(descriptor.kind == ClassKind.ENUM_CLASS)
|
||||
return originalModuleIndex.classes[descriptor]
|
||||
?: symbols.symbolTable.referenceClass(descriptor).owner
|
||||
}
|
||||
}
|
||||
|
||||
internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Symbols<Context>(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<TestProcessor.FunctionKind, IrEnumEntrySymbol>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
+9
@@ -33,6 +33,8 @@ class ModuleIndex(val module: IrModuleFragment) {
|
||||
*/
|
||||
val classes: Map<ClassDescriptor, IrClass>
|
||||
|
||||
val enumEntries: Map<ClassDescriptor, IrEnumEntry>
|
||||
|
||||
/**
|
||||
* Contains all functions declared in [module]
|
||||
*/
|
||||
@@ -41,6 +43,7 @@ class ModuleIndex(val module: IrModuleFragment) {
|
||||
|
||||
init {
|
||||
val map = mutableMapOf<ClassDescriptor, IrClass>()
|
||||
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
|
||||
|
||||
+60
@@ -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)
|
||||
+31
@@ -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<IrValueSymbol>
|
||||
internal typealias ParameterDescriptor = IrValueParameter
|
||||
+234
@@ -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 : IrDeclaration> 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("<init>")
|
||||
|
||||
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<IrValueParameter>
|
||||
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<IrValueParameter>
|
||||
get() {
|
||||
val result = ArrayList<IrValueParameter>(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<IrConstructor>()
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
-25
@@ -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)
|
||||
|
||||
+8
-15
@@ -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
|
||||
|
||||
+13
-18
@@ -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].
|
||||
*
|
||||
|
||||
+2
-2
@@ -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<KotlinType>
|
||||
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)
|
||||
|
||||
+1
-1
@@ -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.")
|
||||
|
||||
+120
-121
@@ -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<IrE
|
||||
private object TopLevelCodeContext : CodeContext {
|
||||
private fun unsupported(any: Any? = null): Nothing = throw UnsupportedOperationException(any?.toString() ?: "")
|
||||
|
||||
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) = unsupported(target)
|
||||
override fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) = unsupported(target)
|
||||
|
||||
override fun genBreak(destination: IrBreak) = unsupported()
|
||||
|
||||
@@ -347,7 +345,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
||||
appendLlvmUsed("llvm.compiler.used", context.llvm.compilerUsedGlobals)
|
||||
appendStaticInitializers()
|
||||
appendEntryPointSelector(findMainEntryPoint(context))
|
||||
appendEntryPointSelector(context.ir.symbols.entryPoint?.owner)
|
||||
if (context.isDynamicLibrary) {
|
||||
appendCAdapters()
|
||||
}
|
||||
@@ -371,7 +369,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
appendingTo(bbDeinit) {
|
||||
context.llvm.fileInitializers.forEach {
|
||||
val descriptor = it.descriptor
|
||||
val descriptor = it
|
||||
if (descriptor.type.isValueType())
|
||||
return@forEach // Is not a subject for memory management.
|
||||
val address = context.llvmDeclarations.forStaticField(descriptor).storage
|
||||
@@ -386,7 +384,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
.forEach {
|
||||
if (it.initializer?.expression !is IrConst<*>?) {
|
||||
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<IrE
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor) {
|
||||
context.log{"visitConstructor : ${ir2string(declaration)}"}
|
||||
if (declaration.descriptor.containingDeclaration.isIntrinsic) {
|
||||
if (declaration.constructedClass.isIntrinsic) {
|
||||
// Do not generate any ctors for intrinsic classes.
|
||||
return
|
||||
}
|
||||
@@ -489,18 +487,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
return
|
||||
}
|
||||
|
||||
val constructorDescriptor = declaration.descriptor
|
||||
val classDescriptor = constructorDescriptor.constructedClass
|
||||
if (constructorDescriptor.isPrimary) {
|
||||
if (DescriptorUtils.isObject(classDescriptor)) {
|
||||
if (!classDescriptor.isUnit()) {
|
||||
val objectPtr = codegen.getObjectInstanceStorage(classDescriptor)
|
||||
|
||||
LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitFunction(declaration)
|
||||
}
|
||||
|
||||
@@ -543,19 +529,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
function: IrFunction?,
|
||||
private val functionGenerationContext: FunctionGenerationContext): InnerScopeImpl() {
|
||||
|
||||
val parameters = bindParameters(function?.descriptor)
|
||||
val parameters = bindParameters(function)
|
||||
|
||||
init {
|
||||
if (function != null) {
|
||||
parameters.forEach{
|
||||
val descriptor = it.key
|
||||
val ir = when {
|
||||
descriptor is ValueParameterDescriptor -> 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<IrE
|
||||
}
|
||||
|
||||
var llvmFunction:LLVMValueRef? = declaration?.let{
|
||||
codegen.llvmFunction(declaration.descriptor)
|
||||
codegen.llvmFunction(it)
|
||||
}
|
||||
|
||||
private var name:String? = declaration?.descriptor?.name?.asString()
|
||||
|
||||
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
|
||||
if (declaration == null || target == declaration.descriptor) {
|
||||
if (target.returnsUnit()) {
|
||||
assert (value == null)
|
||||
override fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) {
|
||||
if (declaration == null || target == declaration) {
|
||||
if ((target as IrFunction).returnsUnit()) {
|
||||
functionGenerationContext.ret(null)
|
||||
} else {
|
||||
functionGenerationContext.ret(value!!)
|
||||
@@ -654,7 +633,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
if (declaration.descriptor.isExternal) return
|
||||
if (body == null) return
|
||||
|
||||
generateFunction(codegen, declaration.descriptor,
|
||||
generateFunction(codegen, declaration,
|
||||
declaration.location(declaration.startLine(), declaration.startColumn()),
|
||||
declaration.location(declaration.endLine(), declaration.endColumn())) {
|
||||
using(FunctionScope(declaration, it)) {
|
||||
@@ -674,7 +653,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
|
||||
if (declaration.descriptor.usedAnnotation) {
|
||||
context.llvm.usedFunctions.add(codegen.llvmFunction(declaration.descriptor))
|
||||
context.llvm.usedFunctions.add(codegen.llvmFunction(declaration))
|
||||
}
|
||||
|
||||
if (context.shouldVerifyBitCode())
|
||||
@@ -713,7 +692,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override fun visitProperty(declaration: IrProperty) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
declaration.getter?.acceptVoid(this)
|
||||
declaration.setter?.acceptVoid(this)
|
||||
declaration.backingField?.acceptVoid(this)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -721,7 +702,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
override fun visitField(declaration: IrField) {
|
||||
context.log{"visitField : ${ir2string(declaration)}"}
|
||||
debugFieldDeclaration(declaration)
|
||||
val descriptor = declaration.descriptor
|
||||
val descriptor = declaration
|
||||
if (context.needGlobalInit(declaration)) {
|
||||
val type = codegen.getLLVMType(descriptor.type)
|
||||
val globalProperty = context.llvmDeclarations.forStaticField(descriptor).storage
|
||||
@@ -791,7 +772,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun evaluateGetObjectValue(value: IrGetObjectValue): LLVMValueRef =
|
||||
functionGenerationContext.getObjectValue(
|
||||
value.descriptor,
|
||||
value.symbol.owner,
|
||||
currentCodeContext.exceptionHandler,
|
||||
value.startLocation
|
||||
)
|
||||
@@ -872,10 +853,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
throw IllegalStateException("IrVararg neither was lowered nor can be statically evaluated")
|
||||
}
|
||||
|
||||
val arrayClass = context.ir.getClass(value.type)!!
|
||||
|
||||
// Note: even if all elements are const, they aren't guaranteed to be statically initialized.
|
||||
// E.g. an element may be a pointer to lazy-initialized object (aka singleton).
|
||||
// However it is guaranteed that all elements are already initialized at this point.
|
||||
return codegen.staticData.createKotlinArray(value.type, elements)
|
||||
return codegen.staticData.createKotlinArray(arrayClass, elements)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -999,7 +982,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
for (catch in catches) {
|
||||
fun genCatchBlock() {
|
||||
using(VariableScope()) {
|
||||
currentCodeContext.genDeclareVariable(catch.parameter, exception, null)
|
||||
currentCodeContext.genDeclareVariable(catch.catchParameter, exception, null)
|
||||
evaluateExpressionAndJump(catch.result, success)
|
||||
}
|
||||
}
|
||||
@@ -1008,7 +991,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
genCatchBlock()
|
||||
return // Remaining catch clauses are unreachable.
|
||||
} else {
|
||||
val isInstance = genInstanceOf(exception, catch.parameter.type)
|
||||
val isInstance = genInstanceOf(exception, catch.getCatchParameterTypeClass(context)!!)
|
||||
val body = functionGenerationContext.basicBlock("catch", catch.startLocation)
|
||||
val nextCheck = functionGenerationContext.basicBlock("catchCheck", catch.endLocation)
|
||||
functionGenerationContext.condBr(isInstance, body, nextCheck)
|
||||
@@ -1143,7 +1126,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun evaluateGetValue(value: IrGetValue): LLVMValueRef {
|
||||
context.log{"evaluateGetValue : ${ir2string(value)}"}
|
||||
return currentCodeContext.genGetValue(value.descriptor)
|
||||
val symbol = value.symbol
|
||||
val ir: IrSymbolDeclaration<IrValueSymbol> = 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<IrE
|
||||
private fun evaluateSetVariable(value: IrSetVariable): LLVMValueRef {
|
||||
context.log{"evaluateSetVariable : ${ir2string(value)}"}
|
||||
val result = evaluateExpression(value.value)
|
||||
val variable = currentCodeContext.getDeclaredVariable(value.descriptor)
|
||||
val variable = currentCodeContext.getDeclaredVariable(value.symbol.owner)
|
||||
functionGenerationContext.vars.store(result, variable)
|
||||
assert(value.type.isUnit())
|
||||
return functionGenerationContext.theUnitInstanceRef.llvm
|
||||
@@ -1177,7 +1167,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
functionScope = locationInfo.scope,
|
||||
diType = element.descriptor.type.diType(context, codegen.llvmTargetData),
|
||||
name = element.descriptor.name,
|
||||
argNo = (element.descriptor as? ValueParameterDescriptor)?.index ?: 0,
|
||||
argNo = if (element.isValueParameter) element.index else 0,
|
||||
file = file,
|
||||
line = locationInfo.line,
|
||||
location = location)
|
||||
@@ -1189,7 +1179,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
context.log{"generateVariable : ${ir2string(variable)}"}
|
||||
val value = variable.initializer?.let { evaluateExpression(it) }
|
||||
currentCodeContext.genDeclareVariable(
|
||||
variable.descriptor, value, debugInfoIfNeeded(
|
||||
variable, value, debugInfoIfNeeded(
|
||||
(currentCodeContext.functionScope() as FunctionScope).declaration, variable))
|
||||
}
|
||||
|
||||
@@ -1251,11 +1241,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun evaluateCast(value: IrTypeOperatorCall): LLVMValueRef {
|
||||
context.log{"evaluateCast : ${ir2string(value)}"}
|
||||
val type = value.typeOperand
|
||||
assert(!KotlinBuiltIns.isPrimitiveType(type) && !KotlinBuiltIns.isPrimitiveType(value.argument.type))
|
||||
assert(!type.isTypeParameter())
|
||||
val dstDescriptor = TypeUtils.getClassDescriptor(type) // Get class descriptor for dst type.
|
||||
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor!!) // Get TypeInfo for dst type.
|
||||
val dstDescriptor = value.getTypeOperandClass(context)!!
|
||||
|
||||
assert(!KotlinBuiltIns.isPrimitiveType(dstDescriptor.defaultType) &&
|
||||
!KotlinBuiltIns.isPrimitiveType(value.argument.type))
|
||||
|
||||
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor) // Get TypeInfo for dst type.
|
||||
val srcArg = evaluateExpression(value.argument) // Evaluate src expression.
|
||||
val srcObjInfoPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, srcArg) // Cast src to ObjInfoPtr.
|
||||
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
|
||||
@@ -1283,7 +1274,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
functionGenerationContext.br(bbExit)
|
||||
|
||||
functionGenerationContext.positionAtEnd(bbInstanceOf)
|
||||
val resultInstanceOf = genInstanceOf(srcArg, type)
|
||||
val typeOperandClass = value.getTypeOperandClass(context)
|
||||
val resultInstanceOf = if (typeOperandClass != null) {
|
||||
genInstanceOf(srcArg, typeOperandClass)
|
||||
} else {
|
||||
// E.g. when generating type operation with reified type parameter in the original body of inline function.
|
||||
kTrue
|
||||
// TODO: these code should be unreachable, however [BridgesBuilding] generates IR with such type checks.
|
||||
}
|
||||
functionGenerationContext.br(bbExit)
|
||||
val bbInstanceOfResult = functionGenerationContext.currentBlock
|
||||
|
||||
@@ -1295,12 +1293,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun genInstanceOf(obj: LLVMValueRef, type: KotlinType): LLVMValueRef {
|
||||
val dstDescriptor = TypeUtils.getClassDescriptor(type) ?: return kTrue // Get class descriptor for dst type.
|
||||
// Reified parameters are not yet supported.
|
||||
// Workaround for reified parameters
|
||||
|
||||
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor) // Get TypeInfo for dst type.
|
||||
private fun genInstanceOf(obj: LLVMValueRef, dstClass: IrClass): LLVMValueRef {
|
||||
val dstTypeInfo = codegen.typeInfoValue(dstClass) // Get TypeInfo for dst type.
|
||||
val srcObjInfoPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, obj) // Cast src to ObjInfoPtr.
|
||||
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
|
||||
|
||||
@@ -1322,11 +1316,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
if (value.descriptor.dispatchReceiverParameter != null) {
|
||||
val thisPtr = evaluateExpression(value.receiver!!)
|
||||
return functionGenerationContext.loadSlot(
|
||||
fieldPtrOfClass(thisPtr, value.descriptor), value.descriptor.isVar())
|
||||
fieldPtrOfClass(thisPtr, value.symbol.owner), value.descriptor.isVar())
|
||||
}
|
||||
else {
|
||||
assert (value.receiver == null)
|
||||
val ptr = context.llvmDeclarations.forStaticField(value.descriptor).storage
|
||||
val ptr = context.llvmDeclarations.forStaticField(value.symbol.owner).storage
|
||||
return functionGenerationContext.loadSlot(ptr, value.descriptor.isVar())
|
||||
}
|
||||
}
|
||||
@@ -1339,11 +1333,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
if (value.descriptor.dispatchReceiverParameter != null) {
|
||||
val thisPtr = evaluateExpression(value.receiver!!)
|
||||
functionGenerationContext.storeAny(valueToAssign, fieldPtrOfClass(thisPtr, value.descriptor))
|
||||
functionGenerationContext.storeAny(valueToAssign, fieldPtrOfClass(thisPtr, value.symbol.owner))
|
||||
}
|
||||
else {
|
||||
assert (value.receiver == null)
|
||||
val globalValue = context.llvmDeclarations.forStaticField(value.descriptor).storage
|
||||
val globalValue = context.llvmDeclarations.forStaticField(value.symbol.owner).storage
|
||||
functionGenerationContext.storeAny(valueToAssign, globalValue)
|
||||
}
|
||||
|
||||
@@ -1385,7 +1379,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
|
||||
*/
|
||||
private fun fieldPtrOfClass(thisPtr: LLVMValueRef, value: PropertyDescriptor): LLVMValueRef {
|
||||
private fun fieldPtrOfClass(thisPtr: LLVMValueRef, value: IrField): LLVMValueRef {
|
||||
val fieldInfo = context.llvmDeclarations.forField(value)
|
||||
|
||||
val classDescriptor = value.containingDeclaration as ClassDescriptor
|
||||
@@ -1402,7 +1396,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
return if (classDescriptor.isObjCClass()) {
|
||||
assert(classDescriptor.isKotlinObjCClass())
|
||||
|
||||
val objCPtr = callDirect(context.interopBuiltIns.objCPointerHolderValue.getter!!,
|
||||
val objCPtr = callDirect(context.ir.symbols.objCPointerHolderValueGetter.owner,
|
||||
listOf(objectPtr), Lifetime.IRRELEVANT)
|
||||
|
||||
val objCDeclarations = context.llvmDeclarations.forClass(classDescriptor).objCDeclarations!!
|
||||
@@ -1448,14 +1442,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
val evaluated = evaluateExpression(value)
|
||||
|
||||
val target = expression.returnTarget
|
||||
val ret = if (target.returnsUnit()) {
|
||||
null
|
||||
} else {
|
||||
evaluated
|
||||
}
|
||||
val target = expression.returnTargetSymbol.owner
|
||||
|
||||
currentCodeContext.genReturn(target, ret)
|
||||
currentCodeContext.genReturn(target, evaluated)
|
||||
return codegen.kNothingFakeValue
|
||||
}
|
||||
|
||||
@@ -1487,15 +1476,15 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
return resultPhi!!
|
||||
}
|
||||
|
||||
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
|
||||
if (target != returnableBlock.descriptor) { // It is not our "local return".
|
||||
override fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) {
|
||||
if (target != returnableBlock) { // It is not our "local return".
|
||||
super.genReturn(target, value)
|
||||
return
|
||||
}
|
||||
// It is local return from current function.
|
||||
functionGenerationContext.br(getExit()) // Generate branch on exit block.
|
||||
|
||||
if (!target.returnsUnit()) { // If function returns more then "unit"
|
||||
if (!returnableBlock.type.isUnit()) { // If function returns more then "unit"
|
||||
functionGenerationContext.assignPhis(getResult() to value!!) // Assign return value to result PHI node.
|
||||
}
|
||||
}
|
||||
@@ -1538,7 +1527,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private inner class ClassScope(val clazz:IrClass) : InnerScopeImpl() {
|
||||
val isExported
|
||||
get() = clazz.descriptor.isExported()
|
||||
get() = clazz.isExported()
|
||||
var offsetInBits = 0L
|
||||
val members = mutableListOf<DIDerivedTypeRef>()
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -1547,7 +1536,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
tag = DwarfTag.DW_TAG_structure_type.value,
|
||||
refBuilder = context.debugInfo.builder,
|
||||
refScope = (currentCodeContext.fileScope() as FileScope).file.file() as DIScopeOpaqueRef,
|
||||
name = clazz.descriptor.typeInfoSymbolName,
|
||||
name = clazz.typeInfoSymbolName,
|
||||
refFile = file().file(),
|
||||
line = clazz.startLine()) as DITypeOpaqueRef
|
||||
else null
|
||||
@@ -1619,12 +1608,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateSpecialIntrinsicCall(expression: IrFunctionAccessExpression): LLVMValueRef? {
|
||||
if (expression.descriptor.isIntrinsic) {
|
||||
when (expression.descriptor.original) {
|
||||
val function = expression.symbol.owner as IrFunction
|
||||
|
||||
if (function.isIntrinsic) {
|
||||
when (function.descriptor) {
|
||||
context.interopBuiltIns.objCObjectInitBy -> {
|
||||
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<IrE
|
||||
val callee = expression as IrCall
|
||||
val initializer = callee.getValueArgument(1) as IrCall
|
||||
val thiz = evaluateExpression(callee.getValueArgument(0)!!)
|
||||
evaluateSimpleFunctionCall(initializer.descriptor, listOf(thiz) + evaluateExplicitArgs(initializer), resultLifetime(initializer))
|
||||
evaluateSimpleFunctionCall(
|
||||
initializer.symbol.owner as IrFunction,
|
||||
listOf(thiz) + evaluateExplicitArgs(initializer),
|
||||
resultLifetime(initializer)
|
||||
)
|
||||
return codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
}
|
||||
@@ -1661,7 +1656,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
updateBuilderDebugLocation(value)
|
||||
when {
|
||||
value is IrDelegatingConstructorCall ->
|
||||
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<IrE
|
||||
scope.members.add(DICreateMemberType(
|
||||
refBuilder = context.debugInfo.builder,
|
||||
refScope = scope.scope as DIScopeOpaqueRef,
|
||||
name = expression.descriptor.symbolName,
|
||||
name = expression.symbolName,
|
||||
file = irFile.file(),
|
||||
lineNum = expression.startLine(),
|
||||
sizeInBits = sizeInBits,
|
||||
@@ -1740,7 +1735,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun IrFunction.scope():DIScopeOpaqueRef? = descriptor.scope(startLine())
|
||||
private fun IrFunction.scope():DIScopeOpaqueRef? = this.scope(startLine())
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun FunctionDescriptor.scope(startLine:Int): DIScopeOpaqueRef? {
|
||||
@@ -1781,9 +1776,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private val coroutineImplDescriptor = context.getInternalClass("CoroutineImpl")
|
||||
private val doResumeFunctionDescriptor = coroutineImplDescriptor.unsubstitutedMemberScope
|
||||
.getContributedFunctions(Name.identifier("doResume"), NoLookupLocation.FROM_BACKEND).single()
|
||||
private val coroutineImplDescriptor = context.ir.symbols.coroutineImpl.owner
|
||||
private val doResumeFunctionDescriptor = coroutineImplDescriptor.declarations
|
||||
.filterIsInstance<IrSimpleFunction>().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<IrE
|
||||
codegen.param(caller, caller.allParameters.size) // The last argument.
|
||||
else {
|
||||
// Suspend call from non-suspend function - must be [CoroutineImpl].
|
||||
assert (doResumeFunctionDescriptor in caller.overriddenDescriptors,
|
||||
assert (doResumeFunctionDescriptor.symbol in (caller as IrSimpleFunction).overriddenSymbols,
|
||||
{ "Expected 'CoroutineImpl.doResume' but was '$caller'" })
|
||||
currentCodeContext.genGetValue(caller.dispatchReceiverParameter!!) // Coroutine itself is a continuation.
|
||||
}
|
||||
}
|
||||
|
||||
private fun CallableDescriptor.returnsUnit() = returnType == context.builtIns.unitType && !isSuspend
|
||||
private fun FunctionDescriptor.returnsUnit() = returnType == context.builtIns.unitType && !isSuspend
|
||||
|
||||
/**
|
||||
* Evaluates all arguments of [expression] that are explicitly represented in the IR.
|
||||
@@ -1824,7 +1819,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
assert (expression.getArguments().isEmpty())
|
||||
|
||||
val descriptor = expression.descriptor
|
||||
val descriptor = expression.symbol.owner as IrFunction
|
||||
assert (descriptor.dispatchReceiverParameter == null)
|
||||
|
||||
val entry = codegen.functionEntryPointAddress(descriptor)
|
||||
@@ -1887,7 +1882,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val bbResume = functionGenerationContext.basicBlock("resume", expression.resumeResult.startLocation)
|
||||
val id = currentCodeContext.addResumePoint(bbResume)
|
||||
|
||||
using (SuspensionPointScope(expression.suspensionPointIdParameter.descriptor, bbResume, id)) {
|
||||
using (SuspensionPointScope(expression.suspensionPointIdParameter, bbResume, id)) {
|
||||
continuationBlock(expression.type, expression.result.startLocation).run {
|
||||
val normalResult = evaluateExpression(expression.result)
|
||||
jump(this, normalResult)
|
||||
@@ -1906,7 +1901,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun evaluateFunctionCall(callee: IrCall, args: List<LLVMValueRef>,
|
||||
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<IrE
|
||||
if (callee is IrPrivateFunctionCall)
|
||||
return evaluatePrivateFunctionCall(callee, argsWithContinuationIfNeeded, resultLifetime)
|
||||
|
||||
when (descriptor) {
|
||||
is IrBuiltinOperatorDescriptorBase -> 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<IrE
|
||||
val functionPlacePtr = LLVMBuildGEP(functionGenerationContext.builder, functionsList, cValuesOf(kImmZero, functionIndex), 2, "")!!
|
||||
val functionPtr = functionGenerationContext.load(functionPlacePtr)
|
||||
|
||||
val functionPtrType = pointerType(codegen.getLlvmFunctionType(callee.descriptor))
|
||||
val target = callee.symbol.owner as IrFunction
|
||||
val functionPtrType = pointerType(codegen.getLlvmFunctionType(target))
|
||||
val function = functionGenerationContext.bitcast(functionPtrType, functionPtr)
|
||||
return call(callee.descriptor, function, args, resultLifetime)
|
||||
return call(target, function, args, resultLifetime)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -1966,7 +1965,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
descriptor: FunctionDescriptor, args: List<LLVMValueRef>,
|
||||
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<IrE
|
||||
private fun evaluateConstructorCall(callee: IrCall, args: List<LLVMValueRef>): 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<IrE
|
||||
functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), count = kImmZero,
|
||||
lifetime = resultLifetime(callee))
|
||||
} else if (constructedClass.isKotlinObjCClass()) {
|
||||
callDirect(context.interopBuiltIns.allocObjCObject, listOf(genGetObjCClass(constructedClass)),
|
||||
callDirect(context.ir.symbols.allocObjCObject.owner, listOf(genGetObjCClass(constructedClass)),
|
||||
resultLifetime(callee))
|
||||
} else {
|
||||
functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee))
|
||||
}
|
||||
evaluateSimpleFunctionCall(callee.descriptor,
|
||||
evaluateSimpleFunctionCall(callee.symbol.owner as IrFunction,
|
||||
listOf(thisValue) + args, Lifetime.IRRELEVANT /* constructor doesn't return anything */)
|
||||
thisValue
|
||||
}
|
||||
@@ -2074,8 +2073,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
interop.getObjCClass -> {
|
||||
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<IrE
|
||||
|
||||
context.ir.symbols.getClassTypeInfo.descriptor -> {
|
||||
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<IrE
|
||||
context.ir.symbols.createUninitializedInstance.descriptor -> {
|
||||
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<IrE
|
||||
}
|
||||
|
||||
private fun genObjCObjectInitFromPtr(args: List<LLVMValueRef>): 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<IrE
|
||||
|
||||
private fun evaluateOperatorCall(callee: IrCall, args: List<LLVMValueRef>): 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<IrE
|
||||
descriptor: ClassConstructorDescriptor, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
|
||||
val constructedClass = functionGenerationContext.constructedClass!!
|
||||
val thisPtr = currentCodeContext.genGetValue(constructedClass.thisAsReceiverParameter)
|
||||
val thisPtr = currentCodeContext.genGetValue(constructedClass.thisReceiver!!)
|
||||
|
||||
if (constructedClass.isObjCClass()) {
|
||||
return codegen.theUnitInstanceRef.llvm
|
||||
|
||||
+26
-32
@@ -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<IrClass>().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<ObjCMethodDesc> = mutableListOf<ObjCMethodDesc>().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<ObjCMethodDesc> =
|
||||
this.unsubstitutedMemberScope.contributedMethods.filter {
|
||||
it.kind.isReal && it !is ConstructorDescriptor
|
||||
}.mapNotNull { it.getObjCMethodInfo() }.map { generateMethodDesc(it) }
|
||||
private fun IrClass.generateOverridingMethodDescs(): List<ObjCMethodDesc> =
|
||||
this.simpleFunctions().filter { it.isReal }
|
||||
.mapNotNull { it.getObjCMethodInfo() }.map { generateMethodDesc(it) }
|
||||
|
||||
private fun IrClass.generateImpMethodDescs(): List<ObjCMethodDesc> = this.declarations
|
||||
.filterIsInstance<IrSimpleFunction>()
|
||||
.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
|
||||
)
|
||||
}
|
||||
}
|
||||
+39
-57
@@ -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<FunctionDescriptor, FunctionLlvmDeclarations>,
|
||||
private val classes: Map<ClassDescriptor, ClassLlvmDeclarations>,
|
||||
private val fields: Map<PropertyDescriptor, FieldLlvmDeclarations>,
|
||||
private val staticFields: Map<PropertyDescriptor, StaticFieldLlvmDeclarations>,
|
||||
private val fields: Map<IrField, FieldLlvmDeclarations>,
|
||||
private val staticFields: Map<IrField, StaticFieldLlvmDeclarations>,
|
||||
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<PropertyDescriptor>, // TODO: it is not an LLVM declaration.
|
||||
val fields: List<IrField>, // 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<PropertyDescriptor> {
|
||||
internal fun Context.getFields(classDescriptor: ClassDescriptor): List<IrField> {
|
||||
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<PropertyD
|
||||
/**
|
||||
* Fields declared in the class.
|
||||
*/
|
||||
private fun Context.getDeclaredFields(classDescriptor: ClassDescriptor): List<PropertyDescriptor> {
|
||||
private fun Context.getDeclaredFields(classDescriptor: ClassDescriptor): List<IrField> {
|
||||
// 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<Pr
|
||||
// In this function we check the presence of the backing field
|
||||
// two ways: first we check IR, then we check the protobuf extension.
|
||||
|
||||
val irClass = ir.moduleIndexForCodegen.classes[classDescriptor]
|
||||
val fields = if (irClass != null) {
|
||||
val declarations = irClass.declarations
|
||||
|
||||
declarations.mapNotNull {
|
||||
when (it) {
|
||||
is IrProperty -> 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<DeserializedPropertyDescriptor>()
|
||||
|
||||
properties.mapNotNull { it.backingField }
|
||||
}
|
||||
|
||||
return fields.sortedBy {
|
||||
it.fqNameSafe.localHash.value
|
||||
}
|
||||
}
|
||||
|
||||
private fun ContextUtils.createClassBodyType(name: String, fields: List<PropertyDescriptor>): LLVMTypeRef {
|
||||
private fun ContextUtils.createClassBodyType(name: String, fields: List<IrField>): 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<FunctionDescriptor, FunctionLlvmDeclarations>()
|
||||
val classes = mutableMapOf<ClassDescriptor, ClassLlvmDeclarations>()
|
||||
val fields = mutableMapOf<PropertyDescriptor, FieldLlvmDeclarations>()
|
||||
val staticFields = mutableMapOf<PropertyDescriptor, StaticFieldLlvmDeclarations>()
|
||||
val fields = mutableMapOf<IrField, FieldLlvmDeclarations>()
|
||||
val staticFields = mutableMapOf<IrField, StaticFieldLlvmDeclarations>()
|
||||
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.
|
||||
|
||||
+14
-17
@@ -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() }
|
||||
)
|
||||
}
|
||||
|
||||
+1
-1
@@ -186,5 +186,5 @@ internal class StaticData(override val context: Context): ContextUtils {
|
||||
*/
|
||||
internal fun StaticData.createImmutableBinaryBlob(value: IrConst<String>): 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)
|
||||
}
|
||||
+18
-29
@@ -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<LLVMValueRef>) =
|
||||
createKotlinArray(arrayType, elements.map { constValue(it) }).llvm
|
||||
internal fun StaticData.createKotlinArray(arrayClass: IrClass, elements: List<LLVMValueRef>) =
|
||||
createKotlinArray(arrayClass, elements.map { constValue(it) }).llvm
|
||||
|
||||
internal fun StaticData.createKotlinArray(arrayType: KotlinType, elements: List<ConstValue>): ConstPointer {
|
||||
val typeInfo = arrayType.typeInfoPtr!!
|
||||
internal fun StaticData.createKotlinArray(arrayClass: IrClass, elements: List<ConstValue>): 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<elementType>:
|
||||
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,
|
||||
|
||||
+8
-1
@@ -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)
|
||||
}
|
||||
|
||||
+7
-11
@@ -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<IrSimpleFunction>().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()
|
||||
|
||||
+42
-32
@@ -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<IrSimpleFunction>()
|
||||
.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<LLVMValueRef>()
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
+32
-40
@@ -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<FunctionDescriptor?>()
|
||||
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<IrSimpleFunction>()
|
||||
|
||||
irClass.descriptor.contributedMethods.forEach { functions.add(it) }
|
||||
|
||||
val builtBridges = mutableSetOf<FunctionDescriptor>()
|
||||
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<IrFunction>().map { it.symbol }
|
||||
val propertyAccessors = this.declarations
|
||||
.filterIsInstance<IrProperty>()
|
||||
.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)
|
||||
|
||||
+34
-36
@@ -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<IrElement>()
|
||||
|
||||
@@ -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<IrDeclarationParent>().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<KotlinType>? = 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<MemberScope>("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<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -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<DeclarationDescriptor, DeclarationDescriptor> = 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)
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
|
||||
+31
-22
@@ -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<IrVariableSymbol>()
|
||||
val variables = mutableMapOf<ValueDescriptor, IrValueSymbol>()
|
||||
|
||||
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<IrFunctionSymbol, List<Pair<ValueParameterDescriptor, IrExpression?>>> {
|
||||
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<IrFunctionSymbol, List<Pair<ValueParameterDescriptor, IrExpression?>>> {
|
||||
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" }
|
||||
|
||||
+9
-10
@@ -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))
|
||||
})
|
||||
|
||||
+12
-14
@@ -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<MemberScope>("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
|
||||
|
||||
|
||||
+5
-2
@@ -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<DeclarationDescriptor,
|
||||
typeSubstitutor = createTypeSubstitutor(callee) // Type parameters will be substituted with type arguments.
|
||||
) as IrFunction
|
||||
|
||||
val irReturnableBlockSymbol = IrReturnableBlockSymbolImpl(copyFunctionDeclaration.descriptor.original)
|
||||
|
||||
val evaluationStatements = evaluateArguments(callee, copyFunctionDeclaration) // And list of evaluation statements.
|
||||
|
||||
val statements = (copyFunctionDeclaration.body as IrBlockBody).statements // IR statements from function copy.
|
||||
@@ -142,7 +145,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
val descriptor = caller.descriptor.original
|
||||
if (descriptor.isInlineConstructor) {
|
||||
val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall
|
||||
val irBuilder = context.createIrBuilder(copyFunctionDeclaration.symbol, startOffset, endOffset)
|
||||
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
|
||||
irBuilder.run {
|
||||
val constructorDescriptor = delegatingConstructorCall.descriptor.original
|
||||
val constructorCall = irCall(delegatingConstructorCall.symbol,
|
||||
@@ -166,7 +169,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = returnType,
|
||||
descriptor = copyFunctionDeclaration.descriptor.original,
|
||||
symbol = irReturnableBlockSymbol,
|
||||
origin = null,
|
||||
statements = statements,
|
||||
sourceFileName = sourceFileName
|
||||
|
||||
+19
-5
@@ -28,12 +28,10 @@ import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
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.IrElementTransformerVoid
|
||||
@@ -118,7 +116,23 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
|
||||
initializer.createParameterDeclarations()
|
||||
|
||||
irClass.declarations.add(initializer)
|
||||
initializers.forEach {
|
||||
it.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
if (expression.symbol == irClass.thisReceiver!!.symbol) {
|
||||
return IrGetValueImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
initializer.dispatchReceiverParameter!!.symbol
|
||||
)
|
||||
} else {
|
||||
return expression
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
irClass.addChild(initializer)
|
||||
|
||||
return initializer.symbol
|
||||
}
|
||||
|
||||
+13
-2
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
@@ -31,6 +32,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.util.addChild
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -57,7 +59,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
private fun createOuterThisField() {
|
||||
val field = context.specialDeclarationsFactory.getOuterThisField(classDescriptor)
|
||||
outerThisFieldSymbol = field.symbol
|
||||
irClass.declarations.add(field)
|
||||
irClass.addChild(field)
|
||||
}
|
||||
|
||||
private fun lowerConstructors() {
|
||||
@@ -109,7 +111,16 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
var innerClass: ClassDescriptor
|
||||
if (constructorSymbol == null || constructorSymbol.descriptor.constructedClass != classDescriptor) {
|
||||
innerClass = classDescriptor
|
||||
irThis = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol, origin)
|
||||
val currentIrFunction = currentFunction!!.scope.scopeOwnerSymbol.owner as IrFunction
|
||||
|
||||
val currentFunctionReceiver = currentIrFunction.dispatchReceiverParameter
|
||||
val thisSymbol = if (currentFunctionReceiver?.descriptor == irClass.thisReceiver!!.descriptor) {
|
||||
currentFunctionReceiver
|
||||
} else {
|
||||
irClass.thisReceiver!!
|
||||
}.symbol
|
||||
|
||||
irThis = IrGetValueImpl(startOffset, endOffset, thisSymbol, origin)
|
||||
} else {
|
||||
// For constructor we have outer class as dispatchReceiverParameter.
|
||||
innerClass = DescriptorUtils.getContainingClass(classDescriptor) ?:
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
|
||||
else -> 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)
|
||||
|
||||
+23
-2
@@ -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<FunctionDescriptor, LocalFunctionContext> = LinkedHashMap()
|
||||
val localClasses: MutableMap<ClassDescriptor, LocalClassContext> = 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
|
||||
|
||||
+29
-24
@@ -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<KotlinType>(coroutineImplClassDescriptor.defaultType)
|
||||
val superClasses = mutableListOf<IrClass>(coroutineImplSymbol.owner)
|
||||
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
||||
var functionClassDescriptor: ClassDescriptor? = null
|
||||
var suspendFunctionClassTypeArguments: List<KotlinType>? = 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<CallableMemberDescriptor, CallableMemberDescriptor>()
|
||||
@@ -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<MemberScope>("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.
|
||||
|
||||
+3
-5
@@ -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())
|
||||
)
|
||||
|
||||
+2
-1
@@ -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<CallableMemberDescriptor>
|
||||
val maxFunctionTypeParameterCount get() = 22
|
||||
val maxFunctionTypeParameterCount get() = KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS
|
||||
fun isSpecialMapped(descriptor: ClassDescriptor): Boolean
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -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 }
|
||||
|
||||
+86
-80
@@ -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<ClassDescriptor>) {
|
||||
val descriptor = type.constructor.declarationDescriptor
|
||||
when (descriptor) {
|
||||
is ClassDescriptor -> erasure += descriptor
|
||||
is TypeParameterDescriptor -> {
|
||||
private fun computeErasure(type: KotlinType, context: Context, erasure: MutableList<ClassDescriptor>) {
|
||||
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<ClassDescriptor> {
|
||||
internal fun KotlinType.erasure(context: Context): List<ClassDescriptor> {
|
||||
val result = mutableListOf<ClassDescriptor>()
|
||||
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<IrReturnableBlock, List<IrExpression>>,
|
||||
private class ExpressionValuesExtractor(val context: Context,
|
||||
val returnableBlockValues: Map<IrReturnableBlock, List<IrExpression>>,
|
||||
val suspendableExpressionValues: Map<IrSuspendableExpression, List<IrSuspensionPoint>>) {
|
||||
|
||||
fun forEachValue(expression: IrExpression, block: (IrExpression) -> Unit) {
|
||||
@@ -187,11 +179,14 @@ private class ExpressionValuesExtractor(val returnableBlockValues: Map<IrReturna
|
||||
is IrSetField -> 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<IrSuspendableExpression, MutableList<IrSuspensionPoint>>()
|
||||
|
||||
private val expressionValuesExtractor = ExpressionValuesExtractor(returnableBlockValues, suspendableExpressionValues)
|
||||
private val expressionValuesExtractor = ExpressionValuesExtractor(context, returnableBlockValues, suspendableExpressionValues)
|
||||
|
||||
fun build(): ModuleDFG {
|
||||
val functions = mutableMapOf<DataFlowIR.FunctionSymbol, DataFlowIR.Function>()
|
||||
@@ -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<IrSimpleFunction>().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<IrExpression>,
|
||||
val returnValues: List<IrExpression>,
|
||||
val thrownValues: List<IrExpression>,
|
||||
@@ -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) // <this> 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) { // <this> 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>): 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()) // <Nothing> is not a singleton though its instance is get with <IrGetObject> 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
|
||||
)
|
||||
|
||||
+19
-33
@@ -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<ClassDescriptor, Type>()
|
||||
val functionMap = mutableMapOf<CallableDescriptor, FunctionSymbol>()
|
||||
val functionMap = mutableMapOf<DeclarationDescriptor, FunctionSymbol>()
|
||||
|
||||
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
|
||||
|
||||
+3
-3
@@ -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<DataFlowIR.Node.VirtualCall, Pair<DevirtualizedCallSite, DataFlowIR.FunctionSymbol>>()
|
||||
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) }
|
||||
|
||||
+1
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+214
-11
@@ -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<TypeParameterDescriptor>, 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<TypeParameterDescriptor>(), 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()
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -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)
|
||||
|
||||
+54
-40
@@ -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<DeclarationDescriptor, IrSymbol>
|
||||
) : IrElementTransformerVoid() {
|
||||
|
||||
private inline fun <D : DeclarationDescriptor, reified S : IrBindableSymbol<D, *>> S.replace(
|
||||
private val localDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, MutableList<IrSymbol>>()
|
||||
|
||||
private inline fun <R> 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 <reified D : DeclarationDescriptor, reified S : IrSymbol> 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 <D : DeclarationDescriptor, reified S : IrBindableSymbol<D, *>> S.replaceOrSame(
|
||||
private inline fun <reified D : DeclarationDescriptor, reified S : IrSymbol> 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 <reified S : IrSymbol> 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()
|
||||
}
|
||||
|
||||
+277
-8
@@ -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<CallableMemberDescriptor>()
|
||||
.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<IrSimpleFunction> = 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<IrClass>) {
|
||||
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<IrClass>) {
|
||||
val overriddenSuperMembers = this.declarations.map { it.descriptor }
|
||||
.filterIsInstance<CallableMemberDescriptor>().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 <reified T> 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<IrDeclaration>) {
|
||||
declarations.forEach { this.addChild(it) }
|
||||
}
|
||||
|
||||
fun IrDeclarationContainer.addChild(declaration: IrDeclaration) {
|
||||
this.declarations += declaration
|
||||
declaration.accept(SetDeclarationsParentVisitor, this)
|
||||
}
|
||||
|
||||
object SetDeclarationsParentVisitor : IrElementVisitor<Unit, IrDeclarationParent> {
|
||||
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<Unit, IrDeclarationParent?> {
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user