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 -> {
|
isFunction -> {
|
||||||
val function = declaration as FunctionDescriptor
|
val function = declaration as FunctionDescriptor
|
||||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
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.
|
// If function is virtual, we need to resolve receiver properly.
|
||||||
val bridge = if (!DescriptorUtils.isTopLevelDeclaration(function) && !function.isExtension &&
|
val bridge = if (!DescriptorUtils.isTopLevelDeclaration(function) && !function.isExtension &&
|
||||||
function.isOverridable) {
|
function.isOverridable) {
|
||||||
@@ -207,7 +207,7 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
val receiver = param(0)
|
val receiver = param(0)
|
||||||
val numParams = LLVMCountParams(llvmFunction)
|
val numParams = LLVMCountParams(llvmFunction)
|
||||||
val args = (0..numParams - 1).map { index -> param(index) }
|
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)
|
val result = call(callee, args, exceptionHandler = ExceptionHandler.Caller, verbatim = true)
|
||||||
ret(result)
|
ret(result)
|
||||||
}
|
}
|
||||||
@@ -223,14 +223,15 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
val builder = LLVMCreateBuilder()!!
|
val builder = LLVMCreateBuilder()!!
|
||||||
val bb = LLVMAppendBasicBlock(getTypeFunction, "")!!
|
val bb = LLVMAppendBasicBlock(getTypeFunction, "")!!
|
||||||
LLVMPositionBuilderAtEnd(builder, bb)
|
LLVMPositionBuilderAtEnd(builder, bb)
|
||||||
LLVMBuildRet(builder, (declaration as ClassDescriptor).typeInfoPtr.llvm)
|
LLVMBuildRet(builder, context.ir.getFromCurrentModule(declaration as ClassDescriptor).typeInfoPtr.llvm)
|
||||||
LLVMDisposeBuilder(builder)
|
LLVMDisposeBuilder(builder)
|
||||||
}
|
}
|
||||||
isEnumEntry -> {
|
isEnumEntry -> {
|
||||||
// Produce entry getter.
|
// Produce entry getter.
|
||||||
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
cname = "_konan_function_${owner.nextFunctionIndex()}"
|
||||||
generateFunction(owner.codegen, owner.kGetObjectFuncType, cname) {
|
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)
|
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.KonanLibraryWriter
|
||||||
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
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.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
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.SourceManager
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
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.DumpIrTreeVisitor
|
||||||
|
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||||
import org.jetbrains.kotlin.ir.util.endOffsetOrUndefined
|
import org.jetbrains.kotlin.ir.util.endOffsetOrUndefined
|
||||||
import org.jetbrains.kotlin.ir.util.startOffsetOrUndefined
|
import org.jetbrains.kotlin.ir.util.startOffsetOrUndefined
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
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.name.FqName
|
||||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||||
import java.lang.System.out
|
import java.lang.System.out
|
||||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||||
@@ -56,7 +58,7 @@ import kotlin.LazyThreadSafetyMode.PUBLICATION
|
|||||||
internal class SpecialDeclarationsFactory(val context: Context) {
|
internal class SpecialDeclarationsFactory(val context: Context) {
|
||||||
private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) }
|
private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) }
|
||||||
private val outerThisFields = mutableMapOf<ClassDescriptor, IrField>()
|
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>()
|
private val loweredEnums = mutableMapOf<ClassDescriptor, LoweredEnum>()
|
||||||
|
|
||||||
object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
|
object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
|
||||||
@@ -83,20 +85,31 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): FunctionDescriptor {
|
fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): IrSimpleFunction {
|
||||||
val descriptor = overriddenFunctionDescriptor.descriptor.original
|
val irFunction = overriddenFunctionDescriptor.descriptor
|
||||||
|
val descriptor = irFunction.descriptor
|
||||||
assert(overriddenFunctionDescriptor.needBridge,
|
assert(overriddenFunctionDescriptor.needBridge,
|
||||||
{ "Function $descriptor is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor}" })
|
{ "Function $descriptor is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor}" })
|
||||||
val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections
|
val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections
|
||||||
return bridgesDescriptors.getOrPut(descriptor to bridgeDirections) {
|
return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) {
|
||||||
SimpleFunctionDescriptorImpl.create(
|
val newDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||||
/* containingDeclaration = */ descriptor.containingDeclaration,
|
/* containingDeclaration = */ descriptor.containingDeclaration,
|
||||||
/* annotations = */ Annotations.EMPTY,
|
/* annotations = */ Annotations.EMPTY,
|
||||||
/* name = */ "<bridge-$bridgeDirections>${descriptor.functionName}".synthesizedName,
|
/* name = */ "<bridge-$bridgeDirections>${irFunction.functionName}".synthesizedName,
|
||||||
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
/* source = */ SourceElement.NO_SOURCE).apply {
|
/* source = */ SourceElement.NO_SOURCE).apply {
|
||||||
initializeBridgeDescriptor(this, descriptor, bridgeDirections.array)
|
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) {
|
override val reflectionTypes: ReflectionTypes by lazy(PUBLICATION) {
|
||||||
ReflectionTypes(moduleDescriptor, FqName("konan.internal"))
|
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)
|
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.descriptors.impl.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
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.ir.util.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||||
@@ -43,7 +42,7 @@ internal object DECLARATION_ORIGIN_ENUM :
|
|||||||
internal data class LoweredEnum(val implObject: IrClass,
|
internal data class LoweredEnum(val implObject: IrClass,
|
||||||
val valuesField: IrField,
|
val valuesField: IrField,
|
||||||
val valuesGetter: IrSimpleFunction,
|
val valuesGetter: IrSimpleFunction,
|
||||||
val itemGetterSymbol: IrFunctionSymbol,
|
val itemGetterSymbol: IrSimpleFunctionSymbol,
|
||||||
val itemGetterDescriptor: FunctionDescriptor,
|
val itemGetterDescriptor: FunctionDescriptor,
|
||||||
val entriesMap: Map<Name, Int>)
|
val entriesMap: Map<Name, Int>)
|
||||||
|
|
||||||
@@ -74,7 +73,11 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) {
|
|||||||
val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor).apply {
|
val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor).apply {
|
||||||
createParameterDeclarations()
|
createParameterDeclarations()
|
||||||
addFakeOverrides()
|
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)
|
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)
|
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 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 getter = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||||
|
|
||||||
val typeParameterT = genericArrayType.declaredTypeParameters[0]
|
val typeParameterT = genericArrayType.declaredTypeParameters[0]
|
||||||
|
|||||||
+1
-1
@@ -90,7 +90,7 @@ fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironme
|
|||||||
phaser.phase(KonanPhase.BACKEND) {
|
phaser.phase(KonanPhase.BACKEND) {
|
||||||
phaser.phase(KonanPhase.LOWER) {
|
phaser.phase(KonanPhase.LOWER) {
|
||||||
KonanLower(context).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)
|
context.ir.moduleIndexForCodegen = ModuleIndex(context.ir.irModule)
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.BITCODE) {
|
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.runOnFilePostfix
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
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.common.validateIrModule
|
||||||
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.referenceAllTypeExternalClassifiers
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.*
|
import org.jetbrains.kotlin.backend.konan.lower.*
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.DefaultArgumentStubGenerator
|
import org.jetbrains.kotlin.backend.konan.lower.DefaultArgumentStubGenerator
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.DefaultParameterInjector
|
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.backend.konan.lower.LocalDeclarationsLowering
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
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
|
import org.jetbrains.kotlin.ir.util.replaceUnboundSymbols
|
||||||
|
|
||||||
internal class KonanLower(val context: Context) {
|
internal class KonanLower(val context: Context) {
|
||||||
|
|
||||||
fun lower() {
|
fun lower() {
|
||||||
|
val irModule = context.irModule!!
|
||||||
|
|
||||||
// Phases to run against whole module.
|
// Phases to run against whole module.
|
||||||
lowerModule(context.irModule!!)
|
lowerModule(irModule)
|
||||||
|
|
||||||
// Phases to run against a file.
|
// Phases to run against a file.
|
||||||
context.irModule!!.files.forEach {
|
irModule.files.forEach {
|
||||||
lowerFile(it)
|
lowerFile(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
irModule.checkDeclarationParents()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lowerModule(irModule: IrModuleFragment) {
|
private fun lowerModule(irModule: IrModuleFragment) {
|
||||||
@@ -73,8 +79,17 @@ internal class KonanLower(val context: Context) {
|
|||||||
irModule.files.forEach(LateinitLowering(context)::lower)
|
irModule.files.forEach(LateinitLowering(context)::lower)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
val symbolTable = context.ir.symbols.symbolTable
|
||||||
irModule.replaceUnboundSymbols(context)
|
irModule.referenceAllTypeExternalClassifiers(symbolTable)
|
||||||
|
|
||||||
|
do {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
irModule.replaceUnboundSymbols(context)
|
||||||
|
irModule.referenceAllTypeExternalClassifiers(symbolTable)
|
||||||
|
} while (symbolTable.unboundClasses.isNotEmpty())
|
||||||
|
|
||||||
|
irModule.patchDeclarationParents()
|
||||||
|
|
||||||
validateIrModule(context, irModule)
|
validateIrModule(context, irModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +159,7 @@ internal class KonanLower(val context: Context) {
|
|||||||
WorkersBridgesBuilding(context).lower(irFile)
|
WorkersBridgesBuilding(context).lower(irFile)
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.AUTOBOX) {
|
phaser.phase(KonanPhase.AUTOBOX) {
|
||||||
validateIrFile(context, irFile)
|
// validateIrFile(context, irFile) // Temporarily disabled until moving to new IR finished.
|
||||||
Autoboxing(context).lower(irFile)
|
Autoboxing(context).lower(irFile)
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.RETURNS_INSERTION) {
|
phaser.phase(KonanPhase.RETURNS_INSERTION) {
|
||||||
|
|||||||
+5
@@ -80,3 +80,8 @@ object KonanPlatform : TargetPlatform("Konan") {
|
|||||||
|
|
||||||
override val platformConfigurator: PlatformConfigurator = KonanPlatformConfigurator
|
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
|
package org.jetbrains.kotlin.backend.konan.descriptors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
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.functionName
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
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
|
internal class OverriddenFunctionDescriptor(
|
||||||
// We check that either method is open, or one of declarations it overrides is open.
|
val descriptor: SimpleFunctionDescriptor,
|
||||||
get() = isOverridable || DescriptorUtils.getAllOverriddenDeclarations(this).any { it.isOverridable }
|
overriddenDescriptor: SimpleFunctionDescriptor
|
||||||
|
) {
|
||||||
internal class OverriddenFunctionDescriptor(val descriptor: FunctionDescriptor, overriddenDescriptor: FunctionDescriptor) {
|
|
||||||
val overriddenDescriptor = overriddenDescriptor.original
|
val overriddenDescriptor = overriddenDescriptor.original
|
||||||
|
|
||||||
val needBridge: Boolean
|
val needBridge: Boolean
|
||||||
@@ -44,16 +39,15 @@ internal class OverriddenFunctionDescriptor(val descriptor: FunctionDescriptor,
|
|||||||
return descriptor.canObjCClassMethodBeCalledVirtually(this.overriddenDescriptor)
|
return descriptor.canObjCClassMethodBeCalledVirtually(this.overriddenDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We check that either method is open, or one of declarations it overrides is open.
|
return overriddenDescriptor.isOverridable
|
||||||
return overriddenDescriptor.canBeCalledVirtually
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val inheritsBridge: Boolean
|
val inheritsBridge: Boolean
|
||||||
get() = !descriptor.kind.isReal
|
get() = !descriptor.isReal
|
||||||
&& OverridingUtil.overrides(descriptor.target, overriddenDescriptor)
|
&& descriptor.target.overrides(overriddenDescriptor)
|
||||||
&& descriptor.bridgeDirectionsTo(overriddenDescriptor).allNotNeeded()
|
&& descriptor.bridgeDirectionsTo(overriddenDescriptor).allNotNeeded()
|
||||||
|
|
||||||
fun getImplementation(context: Context): FunctionDescriptor {
|
fun getImplementation(context: Context): SimpleFunctionDescriptor {
|
||||||
val target = descriptor.target
|
val target = descriptor.target
|
||||||
if (!needBridge) return target
|
if (!needBridge) return target
|
||||||
val bridgeOwner = if (inheritsBridge) {
|
val bridgeOwner = if (inheritsBridge) {
|
||||||
@@ -90,17 +84,18 @@ internal class ClassVtablesBuilder(val classDescriptor: ClassDescriptor, val con
|
|||||||
|
|
||||||
assert(!classDescriptor.isInterface)
|
assert(!classDescriptor.isInterface)
|
||||||
|
|
||||||
val superVtableEntries = if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(classDescriptor)) {
|
val superVtableEntries = if (classDescriptor.isSpecialClassWithNoSupertypes()) {
|
||||||
emptyList()
|
emptyList()
|
||||||
} else {
|
} else {
|
||||||
context.getVtableBuilder(classDescriptor.getSuperClassOrAny()).vtableEntries
|
val superClass = classDescriptor.getSuperClassNotAny() ?: context.ir.symbols.any.owner
|
||||||
|
context.getVtableBuilder(superClass).vtableEntries
|
||||||
}
|
}
|
||||||
|
|
||||||
val methods = classDescriptor.sortedContributedMethods
|
val methods = classDescriptor.sortedContributedMethods
|
||||||
val newVtableSlots = mutableListOf<OverriddenFunctionDescriptor>()
|
val newVtableSlots = mutableListOf<OverriddenFunctionDescriptor>()
|
||||||
|
|
||||||
val inheritedVtableSlots = superVtableEntries.map { superMethod ->
|
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) {
|
if (overridingMethod == null) {
|
||||||
superMethod
|
superMethod
|
||||||
} else {
|
} else {
|
||||||
@@ -122,7 +117,7 @@ internal class ClassVtablesBuilder(val classDescriptor: ClassDescriptor, val con
|
|||||||
inheritedVtableSlots + filteredNewVtableSlots.sortedBy { it.overriddenDescriptor.functionName.localHash.value }
|
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 bridgeDirections = function.target.bridgeDirectionsTo(function.original)
|
||||||
val index = vtableEntries.indexOfFirst { it.descriptor == function.original && it.bridgeDirections == bridgeDirections }
|
val index = vtableEntries.indexOfFirst { it.descriptor == function.original && it.bridgeDirections == bridgeDirections }
|
||||||
if (index < 0) throw Error(function.toString() + " not in vtable of " + classDescriptor.toString())
|
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
|
package org.jetbrains.kotlin.backend.konan.descriptors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.atMostOne
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns
|
|
||||||
import org.jetbrains.kotlin.backend.konan.isValueType
|
import org.jetbrains.kotlin.backend.konan.isValueType
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.isExported
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
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.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
||||||
import org.jetbrains.kotlin.name.FqName
|
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.SimpleType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
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)
|
* 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 }
|
val superInterfacesImplementedInterfaces = superInterfaces.flatMap { it.implementedInterfaces }
|
||||||
return (superClassImplementedInterfaces +
|
return (superClassImplementedInterfaces +
|
||||||
superInterfacesImplementedInterfaces +
|
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
|
* TODO: this method is actually a part of resolve and probably duplicates another one
|
||||||
*/
|
*/
|
||||||
internal fun <T : CallableMemberDescriptor> T.resolveFakeOverride(): T {
|
internal tailrec fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction {
|
||||||
if (this.kind.isReal) {
|
if (this.isReal) {
|
||||||
return this
|
return this
|
||||||
} else {
|
} else {
|
||||||
val overridden = OverridingUtil.getOverriddenDeclarations(this)
|
return overriddenSymbols
|
||||||
val filtered = OverridingUtil.filterOutOverridden(overridden)
|
.firstOrNull { it.owner.modality != Modality.ABSTRACT }!!
|
||||||
// TODO: is it correct to take first?
|
.owner.resolveFakeOverride()
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return filtered.first { it.modality != Modality.ABSTRACT } as T
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val intrinsicAnnotation = FqName("konan.internal.Intrinsic")
|
private val intrinsicAnnotation = FqName("konan.internal.Intrinsic")
|
||||||
|
|
||||||
internal val CallableDescriptor.isIntrinsic: Boolean
|
internal val FunctionDescriptor.isIntrinsic: Boolean
|
||||||
get() = this.annotations.hasAnnotation(intrinsicAnnotation)
|
get() = this.annotations.hasAnnotation(intrinsicAnnotation)
|
||||||
|
|
||||||
private val intrinsicTypes = setOf(
|
private val intrinsicTypes = setOf(
|
||||||
@@ -81,7 +70,7 @@ private val intrinsicTypes = setOf(
|
|||||||
"kotlin.Float", "kotlin.Double"
|
"kotlin.Float", "kotlin.Double"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val arrayTypes = setOf(
|
internal val arrayTypes = setOf(
|
||||||
"kotlin.Array",
|
"kotlin.Array",
|
||||||
"kotlin.ByteArray",
|
"kotlin.ByteArray",
|
||||||
"kotlin.CharArray",
|
"kotlin.CharArray",
|
||||||
@@ -105,82 +94,20 @@ internal val ClassDescriptor.isArray: Boolean
|
|||||||
internal val ClassDescriptor.isInterface: Boolean
|
internal val ClassDescriptor.isInterface: Boolean
|
||||||
get() = (this.kind == ClassKind.INTERFACE)
|
get() = (this.kind == ClassKind.INTERFACE)
|
||||||
|
|
||||||
private val konanInternalPackageName = FqName.fromSegments(listOf("konan", "internal"))
|
internal val IrClass.sortedContributedMethods: List<SimpleFunctionDescriptor>
|
||||||
|
|
||||||
/**
|
|
||||||
* @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>
|
|
||||||
get () = contributedMethods.sortedBy {
|
get () = contributedMethods.sortedBy {
|
||||||
it.functionName.localHash.value
|
it.functionName.localHash.value
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val MemberScope.contributedMethods: List<FunctionDescriptor>
|
internal val IrClass.contributedMethods: List<SimpleFunctionDescriptor>
|
||||||
get () {
|
get () = this.simpleFunctions()
|
||||||
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
|
fun ClassDescriptor.isAbstract() = this.modality == Modality.SEALED || this.modality == Modality.ABSTRACT
|
||||||
|| this.kind == ClassKind.ENUM_CLASS
|
|| this.kind == ClassKind.ENUM_CLASS
|
||||||
|
|
||||||
internal fun FunctionDescriptor.hasValueTypeAt(index: Int): Boolean {
|
internal fun FunctionDescriptor.hasValueTypeAt(index: Int): Boolean {
|
||||||
when (index) {
|
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() }
|
1 -> return extensionReceiverParameter.let { it != null && it.type.isValueType() }
|
||||||
else -> return this.valueParameters[index - 2].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 {
|
internal fun FunctionDescriptor.hasReferenceAt(index: Int): Boolean {
|
||||||
when (index) {
|
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() }
|
1 -> return extensionReceiverParameter.let { it != null && !it.type.isValueType() }
|
||||||
else -> return !this.valueParameters[index - 2].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)
|
internal fun FunctionDescriptor.needBridgeTo(target: FunctionDescriptor)
|
||||||
= (0..this.valueParameters.size + 1).any { needBridgeToAt(target, it) }
|
= (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
|
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 {
|
internal enum class BridgeDirection {
|
||||||
NOT_NEEDED,
|
NOT_NEEDED,
|
||||||
FROM_VALUE_TYPE,
|
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)
|
val ourDirections = BridgeDirections(this.valueParameters.size)
|
||||||
for (index in ourDirections.array.indices)
|
for (index in ourDirections.array.indices)
|
||||||
ourDirections.array[index] = this.bridgeDirectionToAt(overriddenDescriptor, index)
|
ourDirections.array[index] = this.bridgeDirectionToAt(overriddenDescriptor, index)
|
||||||
|
|
||||||
val target = this.target
|
val target = this.target
|
||||||
if (!kind.isReal && modality != Modality.ABSTRACT
|
if (!this.isReal && modality != Modality.ABSTRACT
|
||||||
&& OverridingUtil.overrides(target, overriddenDescriptor)
|
&& target.overrides(overriddenDescriptor)
|
||||||
&& ourDirections == target.bridgeDirectionsTo(overriddenDescriptor)) {
|
&& ourDirections == target.bridgeDirectionsTo(overriddenDescriptor)) {
|
||||||
// Bridge is inherited from superclass.
|
// Bridge is inherited from superclass.
|
||||||
return BridgeDirections(this.valueParameters.size)
|
return BridgeDirections(this.valueParameters.size)
|
||||||
@@ -265,82 +215,10 @@ internal fun FunctionDescriptor.bridgeDirectionsTo(overriddenDescriptor: Functio
|
|||||||
}
|
}
|
||||||
|
|
||||||
tailrec internal fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor {
|
tailrec internal fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor {
|
||||||
return if (this is PackageFragmentDescriptor) this
|
val parent = this.parent
|
||||||
else this.containingDeclaration!!.findPackage()
|
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 =
|
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.Ir
|
||||||
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
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.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.backend.konan.lower.TestProcessor
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
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.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
import org.jetbrains.kotlin.ir.util.constructors
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
@@ -51,10 +50,56 @@ internal class KonanIr(context: Context, irModule: IrModuleFragment): Ir<Context
|
|||||||
lateinit var moduleIndexForCodegen: ModuleIndex
|
lateinit var moduleIndexForCodegen: ModuleIndex
|
||||||
|
|
||||||
override var symbols: KonanSymbols by Delegates.notNull()
|
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) {
|
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 =
|
val interopNativePointedGetRawPointer =
|
||||||
symbolTable.referenceSimpleFunction(context.interopBuiltIns.nativePointedGetRawPointer)
|
symbolTable.referenceSimpleFunction(context.interopBuiltIns.nativePointedGetRawPointer)
|
||||||
|
|
||||||
@@ -83,6 +128,15 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
|
|||||||
val interopInterpretObjCPointerOrNull =
|
val interopInterpretObjCPointerOrNull =
|
||||||
symbolTable.referenceSimpleFunction(context.interopBuiltIns.interpretObjCPointerOrNull)
|
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 getNativeNullPtr = symbolTable.referenceSimpleFunction(context.builtIns.getNativeNullPtr)
|
||||||
|
|
||||||
val boxFunctions = ValueType.values().associate {
|
val boxFunctions = ValueType.values().associate {
|
||||||
@@ -97,7 +151,7 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
|
|||||||
val valueClassToBox = ValueType.values().associate {
|
val valueClassToBox = ValueType.values().associate {
|
||||||
val valueClassId = ClassId.topLevel(it.classFqName.toSafe())
|
val valueClassId = ClassId.topLevel(it.classFqName.toSafe())
|
||||||
val valueClassDescriptor = context.builtIns.builtInsModule.findClassAcrossModuleDependencies(valueClassId)!!
|
val valueClassDescriptor = context.builtIns.builtInsModule.findClassAcrossModuleDependencies(valueClassId)!!
|
||||||
valueClassDescriptor to boxClasses[it]!!
|
symbolTable.referenceClass(valueClassDescriptor) to boxClasses[it]!!
|
||||||
}
|
}
|
||||||
|
|
||||||
val unboxFunctions = ValueType.values().mapNotNull {
|
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)
|
.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 baseClassSuite = getKonanTestClass("BaseClassSuite")
|
||||||
val topLevelSuite = getKonanTestClass("TopLevelSuite")
|
val topLevelSuite = getKonanTestClass("TopLevelSuite")
|
||||||
val testFunctionKind = getKonanTestClass("TestFunctionKind")
|
val testFunctionKind = getKonanTestClass("TestFunctionKind")
|
||||||
@@ -267,8 +330,17 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
|
|||||||
|
|
||||||
private val testFunctionKindCache = mutableMapOf<TestProcessor.FunctionKind, IrEnumEntrySymbol>()
|
private val testFunctionKindCache = mutableMapOf<TestProcessor.FunctionKind, IrEnumEntrySymbol>()
|
||||||
fun getTestFunctionKind(kind: TestProcessor.FunctionKind): IrEnumEntrySymbol = testFunctionKindCache.getOrPut(kind) {
|
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
|
kind.runtimeKindName, NoLookupLocation.FROM_BACKEND
|
||||||
) as ClassDescriptor)
|
) 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 classes: Map<ClassDescriptor, IrClass>
|
||||||
|
|
||||||
|
val enumEntries: Map<ClassDescriptor, IrEnumEntry>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains all functions declared in [module]
|
* Contains all functions declared in [module]
|
||||||
*/
|
*/
|
||||||
@@ -41,6 +43,7 @@ class ModuleIndex(val module: IrModuleFragment) {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
val map = mutableMapOf<ClassDescriptor, IrClass>()
|
val map = mutableMapOf<ClassDescriptor, IrClass>()
|
||||||
|
enumEntries = mutableMapOf()
|
||||||
|
|
||||||
module.acceptVoid(object : IrElementVisitorVoid {
|
module.acceptVoid(object : IrElementVisitorVoid {
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) {
|
||||||
@@ -58,6 +61,12 @@ class ModuleIndex(val module: IrModuleFragment) {
|
|||||||
map[declaration.descriptor] = declaration
|
map[declaration.descriptor] = declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitEnumEntry(declaration: IrEnumEntry) {
|
||||||
|
super.visitEnumEntry(declaration)
|
||||||
|
|
||||||
|
enumEntries[declaration.descriptor] = declaration
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction) {
|
override fun visitFunction(declaration: IrFunction) {
|
||||||
super.visitFunction(declaration)
|
super.visitFunction(declaration)
|
||||||
functions[declaration.descriptor] = 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
|
package org.jetbrains.kotlin.backend.konan.llvm
|
||||||
|
|
||||||
import llvm.LLVMTypeRef
|
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.isAbstract
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||||
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.isValueType
|
import org.jetbrains.kotlin.backend.konan.isValueType
|
||||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
|
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
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.descriptors.annotations.AnnotationDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
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.constants.StringValue
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||||
|
|
||||||
|
|
||||||
// This file describes the ABI for Kotlin descriptors of exported declarations.
|
// This file describes the ABI for Kotlin descriptors of exported declarations.
|
||||||
// TODO: revise the naming scheme to ensure it produces unique names.
|
// TODO: revise the naming scheme to ensure it produces unique names.
|
||||||
// TODO: do not serialize descriptors of non-exported declarations.
|
// 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.
|
* and so should be computable from the descriptor itself without checking a backend state.
|
||||||
*/
|
*/
|
||||||
internal tailrec fun DeclarationDescriptor.isExported(): Boolean {
|
internal tailrec fun DeclarationDescriptor.isExported(): Boolean {
|
||||||
assert(!this.isExpectMember) { this }
|
// TODO: revise
|
||||||
|
|
||||||
if (this.annotations.findAnnotation(symbolNameAnnotation) != null) {
|
if (this.annotations.findAnnotation(symbolNameAnnotation) != null) {
|
||||||
// Treat any `@SymbolName` declaration as exported.
|
// Treat any `@SymbolName` declaration as exported.
|
||||||
@@ -73,7 +71,7 @@ internal tailrec fun DeclarationDescriptor.isExported(): Boolean {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DescriptorUtils.isAnonymousObject(this))
|
if (this.isAnonymousObject)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if (this is ConstructorDescriptor && constructedClass.kind.isSingleton) {
|
if (this is ConstructorDescriptor && constructedClass.kind.isSingleton) {
|
||||||
@@ -82,19 +80,33 @@ internal tailrec fun DeclarationDescriptor.isExported(): Boolean {
|
|||||||
return constructedClass.isExported()
|
return constructedClass.isExported()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this is PropertyAccessorDescriptor) {
|
if (this is IrFunction) {
|
||||||
return this.correspondingProperty.isExported()
|
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,
|
// If the declaration is explicitly marked as non-public,
|
||||||
// then it must not be accessible from other modules.
|
// then it must not be accessible from other modules.
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this is DeclarationDescriptorNonRoot) {
|
val parent = this.parent
|
||||||
// If the declaration is not root, then check its container too.
|
if (parent is IrDeclaration) {
|
||||||
return containingDeclaration.isExported()
|
return parent.isExported()
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@@ -158,8 +170,8 @@ private val FunctionDescriptor.signature: String
|
|||||||
val signatureSuffix =
|
val signatureSuffix =
|
||||||
when {
|
when {
|
||||||
this.typeParameters.isNotEmpty() -> "Generic"
|
this.typeParameters.isNotEmpty() -> "Generic"
|
||||||
returnType.let { it != null && it.isValueType() } -> "ValueType"
|
returnType.isValueType() -> "ValueType"
|
||||||
returnType.let { it != null && !KotlinBuiltIns.isUnitOrNullableUnit(it) } -> typeToHashString(returnType!!)
|
!KotlinBuiltIns.isUnitOrNullableUnit(returnType) -> typeToHashString(returnType)
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
return "$extensionReceiverPart($argsPart)$signatureSuffix"
|
return "$extensionReceiverPart($argsPart)$signatureSuffix"
|
||||||
@@ -188,7 +200,7 @@ internal val FunctionDescriptor.functionName: String
|
|||||||
internal val FunctionDescriptor.symbolName: String
|
internal val FunctionDescriptor.symbolName: String
|
||||||
get() {
|
get() {
|
||||||
if (!this.isExported()) {
|
if (!this.isExported()) {
|
||||||
throw AssertionError(this.toString())
|
throw AssertionError(this.descriptor.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
this.annotations.findAnnotation(symbolNameAnnotation)?.let {
|
this.annotations.findAnnotation(symbolNameAnnotation)?.let {
|
||||||
@@ -204,19 +216,20 @@ internal val FunctionDescriptor.symbolName: String
|
|||||||
return name // no wrapping currently required
|
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."
|
if (it.isRoot) "" else "$it."
|
||||||
}
|
}
|
||||||
return "kfun:$containingDeclarationPart$functionName"
|
return "kfun:$containingDeclarationPart$functionName"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val PropertyDescriptor.symbolName: String
|
internal val IrField.symbolName: String
|
||||||
get() {
|
get() {
|
||||||
val containingDeclarationPart = containingDeclaration.fqNameSafe.let {
|
val containingDeclarationPart = parent.fqNameSafe.let {
|
||||||
if (it.isRoot) "" else "$it."
|
if (it.isRoot) "" else "$it."
|
||||||
}
|
}
|
||||||
val extensionReceiverPart = this.extensionReceiverParameter?.let { "${it.type}." } ?: ""
|
return "kprop:$containingDeclarationPart$name"
|
||||||
return "kprop:$containingDeclarationPart$extensionReceiverPart$name"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +248,7 @@ internal fun RuntimeAware.getLlvmFunctionType(function: FunctionDescriptor): LLV
|
|||||||
val returnType = when {
|
val returnType = when {
|
||||||
original is ConstructorDescriptor -> voidType
|
original is ConstructorDescriptor -> voidType
|
||||||
original.isSuspend -> kObjHeaderPtr // Suspend functions return Any?.
|
original.isSuspend -> kObjHeaderPtr // Suspend functions return Any?.
|
||||||
else -> getLLVMReturnType(original.returnType!!)
|
else -> getLLVMReturnType(original.returnType)
|
||||||
}
|
}
|
||||||
val paramTypes = ArrayList(original.allParameters.map { getLLVMType(it.type) })
|
val paramTypes = ArrayList(original.allParameters.map { getLLVMType(it.type) })
|
||||||
if (original.isSuspend)
|
if (original.isSuspend)
|
||||||
|
|||||||
+8
-15
@@ -21,14 +21,9 @@ import kotlinx.cinterop.*
|
|||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
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.descriptors.stdlibModule
|
||||||
import org.jetbrains.kotlin.backend.konan.isObjCClass
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||||
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
|
|
||||||
|
|
||||||
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
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 {
|
fun typeInfoForAllocation(constructedClass: ClassDescriptor): LLVMValueRef {
|
||||||
val descriptorForTypeInfo = if (constructedClass.isObjCClass()) {
|
val descriptorForTypeInfo = if (constructedClass.isObjCClass()) {
|
||||||
context.interopBuiltIns.objCPointerHolder
|
context.ir.symbols.objCPointerHolder.owner
|
||||||
} else {
|
} else {
|
||||||
constructedClass
|
constructedClass
|
||||||
}
|
}
|
||||||
@@ -549,7 +544,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
assert (typeInfoPtr.type == codegen.kTypeInfoPtr) { LLVMPrintTypeToString(typeInfoPtr.type)!!.toKString() }
|
assert (typeInfoPtr.type == codegen.kTypeInfoPtr) { LLVMPrintTypeToString(typeInfoPtr.type)!!.toKString() }
|
||||||
val llvmMethod = if (!owner.isInterface) {
|
val llvmMethod = if (!owner.isInterface) {
|
||||||
// If this is a virtual method of the class - we can call via vtable.
|
// 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 vtablePlace = gep(typeInfoPtr, Int32(1).llvm) // typeInfoPtr + 1
|
||||||
val vtable = bitcast(kInt8PtrPtr, vtablePlace)
|
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].
|
* Note: the same code is generated as IR in [org.jetbrains.kotlin.backend.konan.lower.EnumUsageLowering].
|
||||||
*/
|
*/
|
||||||
fun getEnumEntry(descriptor: ClassDescriptor, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
fun getEnumEntry(descriptor: IrEnumEntry, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
||||||
assert(descriptor.kind == ClassKind.ENUM_ENTRY)
|
|
||||||
|
|
||||||
val enumClassDescriptor = descriptor.containingDeclaration as ClassDescriptor
|
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 ordinal = loweredEnum.entriesMap[descriptor.name]!!
|
||||||
val values = call(
|
val values = call(
|
||||||
loweredEnum.valuesGetter.descriptor.original.llvmFunction,
|
loweredEnum.valuesGetter.llvmFunction,
|
||||||
emptyList(),
|
emptyList(),
|
||||||
Lifetime.ARGUMENT,
|
Lifetime.ARGUMENT,
|
||||||
exceptionHandler
|
exceptionHandler
|
||||||
)
|
)
|
||||||
|
|
||||||
return call(
|
return call(
|
||||||
loweredEnum.itemGetterDescriptor.original.llvmFunction,
|
loweredEnum.itemGetterSymbol.owner.llvmFunction,
|
||||||
listOf(values, Int32(ordinal).llvm),
|
listOf(values, Int32(ordinal).llvm),
|
||||||
Lifetime.GLOBAL,
|
Lifetime.GLOBAL,
|
||||||
exceptionHandler
|
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.CurrentKonanModule
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.DeserializedKonanModule
|
import org.jetbrains.kotlin.backend.konan.descriptors.DeserializedKonanModule
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.LlvmSymbolOrigin
|
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.konan.target.KonanTarget
|
||||||
import org.jetbrains.kotlin.backend.konan.hash.GlobalHash
|
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.isNativeBinary
|
||||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
|
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
|
||||||
import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl
|
import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl
|
||||||
import org.jetbrains.kotlin.backend.konan.library.withResolvedDependencies
|
import org.jetbrains.kotlin.backend.konan.library.withResolvedDependencies
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment
|
||||||
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.IrField
|
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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
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.properties.ReadOnlyProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
@@ -162,7 +159,14 @@ internal interface ContextUtils : RuntimeAware {
|
|||||||
val staticData: StaticData
|
val staticData: StaticData
|
||||||
get() = context.llvm.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.
|
* LLVM function generated from the Kotlin function.
|
||||||
@@ -170,10 +174,7 @@ internal interface ContextUtils : RuntimeAware {
|
|||||||
*/
|
*/
|
||||||
val FunctionDescriptor.llvmFunction: LLVMValueRef
|
val FunctionDescriptor.llvmFunction: LLVMValueRef
|
||||||
get() {
|
get() {
|
||||||
assert (this.kind.isReal)
|
assert (this.isReal)
|
||||||
if (this is TypeAliasConstructorDescriptor) {
|
|
||||||
return this.underlyingConstructorDescriptor.llvmFunction
|
|
||||||
}
|
|
||||||
|
|
||||||
return if (isExternal(this)) {
|
return if (isExternal(this)) {
|
||||||
context.llvm.externalFunction(this.symbolName, getLlvmFunctionType(this),
|
context.llvm.externalFunction(this.symbolName, getLlvmFunctionType(this),
|
||||||
@@ -209,12 +210,6 @@ internal interface ContextUtils : RuntimeAware {
|
|||||||
val ClassDescriptor.llvmTypeInfoPtr: LLVMValueRef
|
val ClassDescriptor.llvmTypeInfoPtr: LLVMValueRef
|
||||||
get() = typeInfoPtr.llvm
|
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].
|
* Returns contents of this [GlobalHash].
|
||||||
*
|
*
|
||||||
|
|||||||
+2
-2
@@ -21,8 +21,8 @@ import kotlinx.cinterop.memScoped
|
|||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanVersion
|
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.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.SourceManager.FileEntry
|
import org.jetbrains.kotlin.ir.SourceManager.FileEntry
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
|
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>
|
internal val FunctionDescriptor.types:List<KotlinType>
|
||||||
get() {
|
get() {
|
||||||
val parameters = valueParameters.map{it.type}
|
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)
|
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.returnType?.isUnit() == true &&
|
||||||
it.hasSingleArrayOfStringParameter &&
|
it.hasSingleArrayOfStringParameter &&
|
||||||
it.typeParameters.isEmpty() &&
|
it.typeParameters.isEmpty() &&
|
||||||
it.isExported()
|
it.visibility.isPublicAPI
|
||||||
}
|
}
|
||||||
if (main == null) {
|
if (main == null) {
|
||||||
context.reportCompilationError("Could not find '$entryName' in '$packageName' package.")
|
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 kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
|
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.common.ir.ir2string
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
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.objcexport.ObjCExport
|
||||||
import org.jetbrains.kotlin.backend.konan.optimizations.*
|
import org.jetbrains.kotlin.backend.konan.optimizations.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.SourceManager
|
import org.jetbrains.kotlin.ir.SourceManager
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
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.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
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.util.getArguments
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
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.resolve.descriptorUtil.fqNameUnsafe
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
|
||||||
internal fun emitLLVM(context: Context) {
|
internal fun emitLLVM(context: Context) {
|
||||||
@@ -153,7 +151,7 @@ internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid {
|
|||||||
override fun visitClass(declaration: IrClass) {
|
override fun visitClass(declaration: IrClass) {
|
||||||
super.visitClass(declaration)
|
super.visitClass(declaration)
|
||||||
|
|
||||||
val descriptor = declaration.descriptor
|
val descriptor = declaration
|
||||||
if (descriptor.isIntrinsic) {
|
if (descriptor.isIntrinsic) {
|
||||||
// do not generate any code for intrinsic classes as they require special handling
|
// do not generate any code for intrinsic classes as they require special handling
|
||||||
return
|
return
|
||||||
@@ -181,7 +179,7 @@ internal interface CodeContext {
|
|||||||
*
|
*
|
||||||
* @param value may be null iff target type is `Unit`.
|
* @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)
|
fun genBreak(destination: IrBreak)
|
||||||
|
|
||||||
@@ -270,7 +268,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
private object TopLevelCodeContext : CodeContext {
|
private object TopLevelCodeContext : CodeContext {
|
||||||
private fun unsupported(any: Any? = null): Nothing = throw UnsupportedOperationException(any?.toString() ?: "")
|
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()
|
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.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
||||||
appendLlvmUsed("llvm.compiler.used", context.llvm.compilerUsedGlobals)
|
appendLlvmUsed("llvm.compiler.used", context.llvm.compilerUsedGlobals)
|
||||||
appendStaticInitializers()
|
appendStaticInitializers()
|
||||||
appendEntryPointSelector(findMainEntryPoint(context))
|
appendEntryPointSelector(context.ir.symbols.entryPoint?.owner)
|
||||||
if (context.isDynamicLibrary) {
|
if (context.isDynamicLibrary) {
|
||||||
appendCAdapters()
|
appendCAdapters()
|
||||||
}
|
}
|
||||||
@@ -371,7 +369,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
appendingTo(bbDeinit) {
|
appendingTo(bbDeinit) {
|
||||||
context.llvm.fileInitializers.forEach {
|
context.llvm.fileInitializers.forEach {
|
||||||
val descriptor = it.descriptor
|
val descriptor = it
|
||||||
if (descriptor.type.isValueType())
|
if (descriptor.type.isValueType())
|
||||||
return@forEach // Is not a subject for memory management.
|
return@forEach // Is not a subject for memory management.
|
||||||
val address = context.llvmDeclarations.forStaticField(descriptor).storage
|
val address = context.llvmDeclarations.forStaticField(descriptor).storage
|
||||||
@@ -386,7 +384,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
.forEach {
|
.forEach {
|
||||||
if (it.initializer?.expression !is IrConst<*>?) {
|
if (it.initializer?.expression !is IrConst<*>?) {
|
||||||
val initialization = evaluateExpression(it.initializer!!.expression)
|
val initialization = evaluateExpression(it.initializer!!.expression)
|
||||||
val address = context.llvmDeclarations.forStaticField(it.descriptor).storage
|
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||||
storeAny(initialization, address)
|
storeAny(initialization, address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -479,7 +477,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
override fun visitConstructor(declaration: IrConstructor) {
|
override fun visitConstructor(declaration: IrConstructor) {
|
||||||
context.log{"visitConstructor : ${ir2string(declaration)}"}
|
context.log{"visitConstructor : ${ir2string(declaration)}"}
|
||||||
if (declaration.descriptor.containingDeclaration.isIntrinsic) {
|
if (declaration.constructedClass.isIntrinsic) {
|
||||||
// Do not generate any ctors for intrinsic classes.
|
// Do not generate any ctors for intrinsic classes.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -489,18 +487,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
return
|
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)
|
visitFunction(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,19 +529,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
function: IrFunction?,
|
function: IrFunction?,
|
||||||
private val functionGenerationContext: FunctionGenerationContext): InnerScopeImpl() {
|
private val functionGenerationContext: FunctionGenerationContext): InnerScopeImpl() {
|
||||||
|
|
||||||
val parameters = bindParameters(function?.descriptor)
|
val parameters = bindParameters(function)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (function != null) {
|
if (function != null) {
|
||||||
parameters.forEach{
|
parameters.forEach{
|
||||||
val descriptor = it.key
|
val descriptor = it.key
|
||||||
val ir = when {
|
val ir = descriptor
|
||||||
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 local = functionGenerationContext.vars.createParameter(descriptor,
|
val local = functionGenerationContext.vars.createParameter(descriptor,
|
||||||
debugInfoIfNeeded(function, ir))
|
debugInfoIfNeeded(function, ir))
|
||||||
@@ -587,15 +567,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
}
|
}
|
||||||
|
|
||||||
var llvmFunction:LLVMValueRef? = declaration?.let{
|
var llvmFunction:LLVMValueRef? = declaration?.let{
|
||||||
codegen.llvmFunction(declaration.descriptor)
|
codegen.llvmFunction(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var name:String? = declaration?.descriptor?.name?.asString()
|
private var name:String? = declaration?.descriptor?.name?.asString()
|
||||||
|
|
||||||
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
|
override fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) {
|
||||||
if (declaration == null || target == declaration.descriptor) {
|
if (declaration == null || target == declaration) {
|
||||||
if (target.returnsUnit()) {
|
if ((target as IrFunction).returnsUnit()) {
|
||||||
assert (value == null)
|
|
||||||
functionGenerationContext.ret(null)
|
functionGenerationContext.ret(null)
|
||||||
} else {
|
} else {
|
||||||
functionGenerationContext.ret(value!!)
|
functionGenerationContext.ret(value!!)
|
||||||
@@ -654,7 +633,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
if (declaration.descriptor.isExternal) return
|
if (declaration.descriptor.isExternal) return
|
||||||
if (body == null) return
|
if (body == null) return
|
||||||
|
|
||||||
generateFunction(codegen, declaration.descriptor,
|
generateFunction(codegen, declaration,
|
||||||
declaration.location(declaration.startLine(), declaration.startColumn()),
|
declaration.location(declaration.startLine(), declaration.startColumn()),
|
||||||
declaration.location(declaration.endLine(), declaration.endColumn())) {
|
declaration.location(declaration.endLine(), declaration.endColumn())) {
|
||||||
using(FunctionScope(declaration, it)) {
|
using(FunctionScope(declaration, it)) {
|
||||||
@@ -674,7 +653,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
|
|
||||||
if (declaration.descriptor.usedAnnotation) {
|
if (declaration.descriptor.usedAnnotation) {
|
||||||
context.llvm.usedFunctions.add(codegen.llvmFunction(declaration.descriptor))
|
context.llvm.usedFunctions.add(codegen.llvmFunction(declaration))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.shouldVerifyBitCode())
|
if (context.shouldVerifyBitCode())
|
||||||
@@ -713,7 +692,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
override fun visitProperty(declaration: IrProperty) {
|
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) {
|
override fun visitField(declaration: IrField) {
|
||||||
context.log{"visitField : ${ir2string(declaration)}"}
|
context.log{"visitField : ${ir2string(declaration)}"}
|
||||||
debugFieldDeclaration(declaration)
|
debugFieldDeclaration(declaration)
|
||||||
val descriptor = declaration.descriptor
|
val descriptor = declaration
|
||||||
if (context.needGlobalInit(declaration)) {
|
if (context.needGlobalInit(declaration)) {
|
||||||
val type = codegen.getLLVMType(descriptor.type)
|
val type = codegen.getLLVMType(descriptor.type)
|
||||||
val globalProperty = context.llvmDeclarations.forStaticField(descriptor).storage
|
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 =
|
private fun evaluateGetObjectValue(value: IrGetObjectValue): LLVMValueRef =
|
||||||
functionGenerationContext.getObjectValue(
|
functionGenerationContext.getObjectValue(
|
||||||
value.descriptor,
|
value.symbol.owner,
|
||||||
currentCodeContext.exceptionHandler,
|
currentCodeContext.exceptionHandler,
|
||||||
value.startLocation
|
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")
|
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.
|
// 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).
|
// 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.
|
// 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) {
|
for (catch in catches) {
|
||||||
fun genCatchBlock() {
|
fun genCatchBlock() {
|
||||||
using(VariableScope()) {
|
using(VariableScope()) {
|
||||||
currentCodeContext.genDeclareVariable(catch.parameter, exception, null)
|
currentCodeContext.genDeclareVariable(catch.catchParameter, exception, null)
|
||||||
evaluateExpressionAndJump(catch.result, success)
|
evaluateExpressionAndJump(catch.result, success)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1008,7 +991,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
genCatchBlock()
|
genCatchBlock()
|
||||||
return // Remaining catch clauses are unreachable.
|
return // Remaining catch clauses are unreachable.
|
||||||
} else {
|
} else {
|
||||||
val isInstance = genInstanceOf(exception, catch.parameter.type)
|
val isInstance = genInstanceOf(exception, catch.getCatchParameterTypeClass(context)!!)
|
||||||
val body = functionGenerationContext.basicBlock("catch", catch.startLocation)
|
val body = functionGenerationContext.basicBlock("catch", catch.startLocation)
|
||||||
val nextCheck = functionGenerationContext.basicBlock("catchCheck", catch.endLocation)
|
val nextCheck = functionGenerationContext.basicBlock("catchCheck", catch.endLocation)
|
||||||
functionGenerationContext.condBr(isInstance, body, nextCheck)
|
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 {
|
private fun evaluateGetValue(value: IrGetValue): LLVMValueRef {
|
||||||
context.log{"evaluateGetValue : ${ir2string(value)}"}
|
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 {
|
private fun evaluateSetVariable(value: IrSetVariable): LLVMValueRef {
|
||||||
context.log{"evaluateSetVariable : ${ir2string(value)}"}
|
context.log{"evaluateSetVariable : ${ir2string(value)}"}
|
||||||
val result = evaluateExpression(value.value)
|
val result = evaluateExpression(value.value)
|
||||||
val variable = currentCodeContext.getDeclaredVariable(value.descriptor)
|
val variable = currentCodeContext.getDeclaredVariable(value.symbol.owner)
|
||||||
functionGenerationContext.vars.store(result, variable)
|
functionGenerationContext.vars.store(result, variable)
|
||||||
assert(value.type.isUnit())
|
assert(value.type.isUnit())
|
||||||
return functionGenerationContext.theUnitInstanceRef.llvm
|
return functionGenerationContext.theUnitInstanceRef.llvm
|
||||||
@@ -1177,7 +1167,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
functionScope = locationInfo.scope,
|
functionScope = locationInfo.scope,
|
||||||
diType = element.descriptor.type.diType(context, codegen.llvmTargetData),
|
diType = element.descriptor.type.diType(context, codegen.llvmTargetData),
|
||||||
name = element.descriptor.name,
|
name = element.descriptor.name,
|
||||||
argNo = (element.descriptor as? ValueParameterDescriptor)?.index ?: 0,
|
argNo = if (element.isValueParameter) element.index else 0,
|
||||||
file = file,
|
file = file,
|
||||||
line = locationInfo.line,
|
line = locationInfo.line,
|
||||||
location = location)
|
location = location)
|
||||||
@@ -1189,7 +1179,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
context.log{"generateVariable : ${ir2string(variable)}"}
|
context.log{"generateVariable : ${ir2string(variable)}"}
|
||||||
val value = variable.initializer?.let { evaluateExpression(it) }
|
val value = variable.initializer?.let { evaluateExpression(it) }
|
||||||
currentCodeContext.genDeclareVariable(
|
currentCodeContext.genDeclareVariable(
|
||||||
variable.descriptor, value, debugInfoIfNeeded(
|
variable, value, debugInfoIfNeeded(
|
||||||
(currentCodeContext.functionScope() as FunctionScope).declaration, variable))
|
(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 {
|
private fun evaluateCast(value: IrTypeOperatorCall): LLVMValueRef {
|
||||||
context.log{"evaluateCast : ${ir2string(value)}"}
|
context.log{"evaluateCast : ${ir2string(value)}"}
|
||||||
val type = value.typeOperand
|
val dstDescriptor = value.getTypeOperandClass(context)!!
|
||||||
assert(!KotlinBuiltIns.isPrimitiveType(type) && !KotlinBuiltIns.isPrimitiveType(value.argument.type))
|
|
||||||
assert(!type.isTypeParameter())
|
assert(!KotlinBuiltIns.isPrimitiveType(dstDescriptor.defaultType) &&
|
||||||
val dstDescriptor = TypeUtils.getClassDescriptor(type) // Get class descriptor for dst type.
|
!KotlinBuiltIns.isPrimitiveType(value.argument.type))
|
||||||
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor!!) // Get TypeInfo for dst type.
|
|
||||||
|
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor) // Get TypeInfo for dst type.
|
||||||
val srcArg = evaluateExpression(value.argument) // Evaluate src expression.
|
val srcArg = evaluateExpression(value.argument) // Evaluate src expression.
|
||||||
val srcObjInfoPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, srcArg) // Cast src to ObjInfoPtr.
|
val srcObjInfoPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, srcArg) // Cast src to ObjInfoPtr.
|
||||||
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
|
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.br(bbExit)
|
||||||
|
|
||||||
functionGenerationContext.positionAtEnd(bbInstanceOf)
|
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)
|
functionGenerationContext.br(bbExit)
|
||||||
val bbInstanceOfResult = functionGenerationContext.currentBlock
|
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 {
|
private fun genInstanceOf(obj: LLVMValueRef, dstClass: IrClass): LLVMValueRef {
|
||||||
val dstDescriptor = TypeUtils.getClassDescriptor(type) ?: return kTrue // Get class descriptor for dst type.
|
val dstTypeInfo = codegen.typeInfoValue(dstClass) // Get TypeInfo for dst type.
|
||||||
// Reified parameters are not yet supported.
|
|
||||||
// Workaround for reified parameters
|
|
||||||
|
|
||||||
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor) // Get TypeInfo for dst type.
|
|
||||||
val srcObjInfoPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, obj) // Cast src to ObjInfoPtr.
|
val srcObjInfoPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, obj) // Cast src to ObjInfoPtr.
|
||||||
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
|
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) {
|
if (value.descriptor.dispatchReceiverParameter != null) {
|
||||||
val thisPtr = evaluateExpression(value.receiver!!)
|
val thisPtr = evaluateExpression(value.receiver!!)
|
||||||
return functionGenerationContext.loadSlot(
|
return functionGenerationContext.loadSlot(
|
||||||
fieldPtrOfClass(thisPtr, value.descriptor), value.descriptor.isVar())
|
fieldPtrOfClass(thisPtr, value.symbol.owner), value.descriptor.isVar())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert (value.receiver == null)
|
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())
|
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) {
|
if (value.descriptor.dispatchReceiverParameter != null) {
|
||||||
val thisPtr = evaluateExpression(value.receiver!!)
|
val thisPtr = evaluateExpression(value.receiver!!)
|
||||||
functionGenerationContext.storeAny(valueToAssign, fieldPtrOfClass(thisPtr, value.descriptor))
|
functionGenerationContext.storeAny(valueToAssign, fieldPtrOfClass(thisPtr, value.symbol.owner))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert (value.receiver == null)
|
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)
|
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 fieldInfo = context.llvmDeclarations.forField(value)
|
||||||
|
|
||||||
val classDescriptor = value.containingDeclaration as ClassDescriptor
|
val classDescriptor = value.containingDeclaration as ClassDescriptor
|
||||||
@@ -1402,7 +1396,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
return if (classDescriptor.isObjCClass()) {
|
return if (classDescriptor.isObjCClass()) {
|
||||||
assert(classDescriptor.isKotlinObjCClass())
|
assert(classDescriptor.isKotlinObjCClass())
|
||||||
|
|
||||||
val objCPtr = callDirect(context.interopBuiltIns.objCPointerHolderValue.getter!!,
|
val objCPtr = callDirect(context.ir.symbols.objCPointerHolderValueGetter.owner,
|
||||||
listOf(objectPtr), Lifetime.IRRELEVANT)
|
listOf(objectPtr), Lifetime.IRRELEVANT)
|
||||||
|
|
||||||
val objCDeclarations = context.llvmDeclarations.forClass(classDescriptor).objCDeclarations!!
|
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 evaluated = evaluateExpression(value)
|
||||||
|
|
||||||
val target = expression.returnTarget
|
val target = expression.returnTargetSymbol.owner
|
||||||
val ret = if (target.returnsUnit()) {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
evaluated
|
|
||||||
}
|
|
||||||
|
|
||||||
currentCodeContext.genReturn(target, ret)
|
currentCodeContext.genReturn(target, evaluated)
|
||||||
return codegen.kNothingFakeValue
|
return codegen.kNothingFakeValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1487,15 +1476,15 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
return resultPhi!!
|
return resultPhi!!
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
|
override fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) {
|
||||||
if (target != returnableBlock.descriptor) { // It is not our "local return".
|
if (target != returnableBlock) { // It is not our "local return".
|
||||||
super.genReturn(target, value)
|
super.genReturn(target, value)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// It is local return from current function.
|
// It is local return from current function.
|
||||||
functionGenerationContext.br(getExit()) // Generate branch on exit block.
|
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.
|
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() {
|
private inner class ClassScope(val clazz:IrClass) : InnerScopeImpl() {
|
||||||
val isExported
|
val isExported
|
||||||
get() = clazz.descriptor.isExported()
|
get() = clazz.isExported()
|
||||||
var offsetInBits = 0L
|
var offsetInBits = 0L
|
||||||
val members = mutableListOf<DIDerivedTypeRef>()
|
val members = mutableListOf<DIDerivedTypeRef>()
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@@ -1547,7 +1536,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
tag = DwarfTag.DW_TAG_structure_type.value,
|
tag = DwarfTag.DW_TAG_structure_type.value,
|
||||||
refBuilder = context.debugInfo.builder,
|
refBuilder = context.debugInfo.builder,
|
||||||
refScope = (currentCodeContext.fileScope() as FileScope).file.file() as DIScopeOpaqueRef,
|
refScope = (currentCodeContext.fileScope() as FileScope).file.file() as DIScopeOpaqueRef,
|
||||||
name = clazz.descriptor.typeInfoSymbolName,
|
name = clazz.typeInfoSymbolName,
|
||||||
refFile = file().file(),
|
refFile = file().file(),
|
||||||
line = clazz.startLine()) as DITypeOpaqueRef
|
line = clazz.startLine()) as DITypeOpaqueRef
|
||||||
else null
|
else null
|
||||||
@@ -1619,12 +1608,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun evaluateSpecialIntrinsicCall(expression: IrFunctionAccessExpression): LLVMValueRef? {
|
private fun evaluateSpecialIntrinsicCall(expression: IrFunctionAccessExpression): LLVMValueRef? {
|
||||||
if (expression.descriptor.isIntrinsic) {
|
val function = expression.symbol.owner as IrFunction
|
||||||
when (expression.descriptor.original) {
|
|
||||||
|
if (function.isIntrinsic) {
|
||||||
|
when (function.descriptor) {
|
||||||
context.interopBuiltIns.objCObjectInitBy -> {
|
context.interopBuiltIns.objCObjectInitBy -> {
|
||||||
val receiver = evaluateExpression(expression.extensionReceiver!!)
|
val receiver = evaluateExpression(expression.extensionReceiver!!)
|
||||||
val irConstructorCall = expression.getValueArgument(0) as IrCall
|
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 constructorArgs = evaluateExplicitArgs(irConstructorCall)
|
||||||
val args = listOf(receiver) + constructorArgs
|
val args = listOf(receiver) + constructorArgs
|
||||||
callDirect(constructorDescriptor, args, Lifetime.IRRELEVANT)
|
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 callee = expression as IrCall
|
||||||
val initializer = callee.getValueArgument(1) as IrCall
|
val initializer = callee.getValueArgument(1) as IrCall
|
||||||
val thiz = evaluateExpression(callee.getValueArgument(0)!!)
|
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
|
return codegen.theUnitInstanceRef.llvm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1661,7 +1656,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
updateBuilderDebugLocation(value)
|
updateBuilderDebugLocation(value)
|
||||||
when {
|
when {
|
||||||
value is IrDelegatingConstructorCall ->
|
value is IrDelegatingConstructorCall ->
|
||||||
return delegatingConstructorCall(value.descriptor, args)
|
return delegatingConstructorCall(value.symbol.owner, args)
|
||||||
|
|
||||||
else ->
|
else ->
|
||||||
return evaluateFunctionCall(value as IrCall, args, resultLifetime(value))
|
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(
|
scope.members.add(DICreateMemberType(
|
||||||
refBuilder = context.debugInfo.builder,
|
refBuilder = context.debugInfo.builder,
|
||||||
refScope = scope.scope as DIScopeOpaqueRef,
|
refScope = scope.scope as DIScopeOpaqueRef,
|
||||||
name = expression.descriptor.symbolName,
|
name = expression.symbolName,
|
||||||
file = irFile.file(),
|
file = irFile.file(),
|
||||||
lineNum = expression.startLine(),
|
lineNum = expression.startLine(),
|
||||||
sizeInBits = sizeInBits,
|
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")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private fun FunctionDescriptor.scope(startLine:Int): DIScopeOpaqueRef? {
|
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 coroutineImplDescriptor = context.ir.symbols.coroutineImpl.owner
|
||||||
private val doResumeFunctionDescriptor = coroutineImplDescriptor.unsubstitutedMemberScope
|
private val doResumeFunctionDescriptor = coroutineImplDescriptor.declarations
|
||||||
.getContributedFunctions(Name.identifier("doResume"), NoLookupLocation.FROM_BACKEND).single()
|
.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "doResume" }
|
||||||
|
|
||||||
private fun getContinuation(): LLVMValueRef {
|
private fun getContinuation(): LLVMValueRef {
|
||||||
val caller = functionGenerationContext.functionDescriptor!!
|
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.
|
codegen.param(caller, caller.allParameters.size) // The last argument.
|
||||||
else {
|
else {
|
||||||
// Suspend call from non-suspend function - must be [CoroutineImpl].
|
// 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'" })
|
{ "Expected 'CoroutineImpl.doResume' but was '$caller'" })
|
||||||
currentCodeContext.genGetValue(caller.dispatchReceiverParameter!!) // Coroutine itself is a continuation.
|
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.
|
* 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())
|
assert (expression.getArguments().isEmpty())
|
||||||
|
|
||||||
val descriptor = expression.descriptor
|
val descriptor = expression.symbol.owner as IrFunction
|
||||||
assert (descriptor.dispatchReceiverParameter == null)
|
assert (descriptor.dispatchReceiverParameter == null)
|
||||||
|
|
||||||
val entry = codegen.functionEntryPointAddress(descriptor)
|
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 bbResume = functionGenerationContext.basicBlock("resume", expression.resumeResult.startLocation)
|
||||||
val id = currentCodeContext.addResumePoint(bbResume)
|
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 {
|
continuationBlock(expression.type, expression.result.startLocation).run {
|
||||||
val normalResult = evaluateExpression(expression.result)
|
val normalResult = evaluateExpression(expression.result)
|
||||||
jump(this, normalResult)
|
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>,
|
private fun evaluateFunctionCall(callee: IrCall, args: List<LLVMValueRef>,
|
||||||
resultLifetime: Lifetime): LLVMValueRef {
|
resultLifetime: Lifetime): LLVMValueRef {
|
||||||
val descriptor = callee.descriptor
|
val descriptor = callee.symbol.owner as IrFunction
|
||||||
|
|
||||||
val argsWithContinuationIfNeeded = if (descriptor.isSuspend)
|
val argsWithContinuationIfNeeded = if (descriptor.isSuspend)
|
||||||
args + getContinuation()
|
args + getContinuation()
|
||||||
@@ -1918,11 +1913,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
if (callee is IrPrivateFunctionCall)
|
if (callee is IrPrivateFunctionCall)
|
||||||
return evaluatePrivateFunctionCall(callee, argsWithContinuationIfNeeded, resultLifetime)
|
return evaluatePrivateFunctionCall(callee, argsWithContinuationIfNeeded, resultLifetime)
|
||||||
|
|
||||||
when (descriptor) {
|
when {
|
||||||
is IrBuiltinOperatorDescriptorBase -> return evaluateOperatorCall (callee, argsWithContinuationIfNeeded)
|
descriptor.origin == IrDeclarationOrigin.IR_BUILTINS_STUB ->
|
||||||
is ConstructorDescriptor -> return evaluateConstructorCall (callee, argsWithContinuationIfNeeded)
|
return evaluateOperatorCall(callee, argsWithContinuationIfNeeded)
|
||||||
else -> return evaluateSimpleFunctionCall(
|
|
||||||
descriptor, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifier)
|
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 functionPlacePtr = LLVMBuildGEP(functionGenerationContext.builder, functionsList, cValuesOf(kImmZero, functionIndex), 2, "")!!
|
||||||
val functionPtr = functionGenerationContext.load(functionPlacePtr)
|
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)
|
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>,
|
descriptor: FunctionDescriptor, args: List<LLVMValueRef>,
|
||||||
resultLifetime: Lifetime, superClass: ClassDescriptor? = null): LLVMValueRef {
|
resultLifetime: Lifetime, superClass: ClassDescriptor? = null): LLVMValueRef {
|
||||||
//context.log{"evaluateSimpleFunctionCall : $tmpVariableName = ${ir2string(value)}"}
|
//context.log{"evaluateSimpleFunctionCall : $tmpVariableName = ${ir2string(value)}"}
|
||||||
if (descriptor.isOverridable && superClass == null)
|
if (superClass == null && descriptor is SimpleFunctionDescriptor && descriptor.isOverridable)
|
||||||
return callVirtual(descriptor, args, resultLifetime)
|
return callVirtual(descriptor, args, resultLifetime)
|
||||||
else
|
else
|
||||||
return callDirect(descriptor, args, resultLifetime)
|
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 {
|
private fun evaluateConstructorCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
context.log{"evaluateConstructorCall : ${ir2string(callee)}"}
|
context.log{"evaluateConstructorCall : ${ir2string(callee)}"}
|
||||||
return memScoped {
|
return memScoped {
|
||||||
val constructedClass = (callee.descriptor as ConstructorDescriptor).constructedClass
|
val constructedClass = (callee.symbol as IrConstructorSymbol).owner.constructedClass
|
||||||
val thisValue = if (constructedClass.isArray) {
|
val thisValue = if (constructedClass.isArray) {
|
||||||
assert(args.isNotEmpty() && args[0].type == int32Type)
|
assert(args.isNotEmpty() && args[0].type == int32Type)
|
||||||
functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), args[0],
|
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,
|
functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), count = kImmZero,
|
||||||
lifetime = resultLifetime(callee))
|
lifetime = resultLifetime(callee))
|
||||||
} else if (constructedClass.isKotlinObjCClass()) {
|
} else if (constructedClass.isKotlinObjCClass()) {
|
||||||
callDirect(context.interopBuiltIns.allocObjCObject, listOf(genGetObjCClass(constructedClass)),
|
callDirect(context.ir.symbols.allocObjCObject.owner, listOf(genGetObjCClass(constructedClass)),
|
||||||
resultLifetime(callee))
|
resultLifetime(callee))
|
||||||
} else {
|
} else {
|
||||||
functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee))
|
functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee))
|
||||||
}
|
}
|
||||||
evaluateSimpleFunctionCall(callee.descriptor,
|
evaluateSimpleFunctionCall(callee.symbol.owner as IrFunction,
|
||||||
listOf(thisValue) + args, Lifetime.IRRELEVANT /* constructor doesn't return anything */)
|
listOf(thisValue) + args, Lifetime.IRRELEVANT /* constructor doesn't return anything */)
|
||||||
thisValue
|
thisValue
|
||||||
}
|
}
|
||||||
@@ -2074,8 +2073,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
interop.getObjCClass -> {
|
interop.getObjCClass -> {
|
||||||
val typeArgument = callee.getTypeArgument(descriptor.typeParameters.single())
|
val typeArgument = callee.getTypeArgument(descriptor.typeParameters.single())
|
||||||
val classDescriptor = TypeUtils.getClassDescriptor(typeArgument!!)!!
|
val irClass = context.ir.getClass(typeArgument!!)!!
|
||||||
genGetObjCClass(classDescriptor)
|
genGetObjCClass(irClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
interop.getObjCMessenger -> {
|
interop.getObjCMessenger -> {
|
||||||
@@ -2090,16 +2089,16 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
context.ir.symbols.getClassTypeInfo.descriptor -> {
|
context.ir.symbols.getClassTypeInfo.descriptor -> {
|
||||||
val typeArgument = callee.getTypeArgumentOrDefault(descriptor.typeParameters.single())
|
val typeArgument = callee.getTypeArgumentOrDefault(descriptor.typeParameters.single())
|
||||||
val typeArgumentClass = TypeUtils.getClassDescriptor(typeArgument)
|
val typeArgumentClass = context.ir.getClass(typeArgument)
|
||||||
if (typeArgumentClass == null) {
|
if (typeArgumentClass == null) {
|
||||||
// E.g. for `T::class` in a body of an inline function itself.
|
// E.g. for `T::class` in a body of an inline function itself.
|
||||||
functionGenerationContext.unreachable()
|
functionGenerationContext.unreachable()
|
||||||
kNullInt8Ptr
|
kNullInt8Ptr
|
||||||
} else {
|
} else {
|
||||||
val classDescriptor = context.ir.symbols.valueClassToBox[typeArgumentClass]?.descriptor
|
val irClass = context.ir.symbols.valueClassToBox[typeArgumentClass.symbol]?.owner
|
||||||
?: typeArgumentClass
|
?: typeArgumentClass
|
||||||
|
|
||||||
val typeInfo = codegen.typeInfoValue(classDescriptor)
|
val typeInfo = codegen.typeInfoValue(irClass)
|
||||||
LLVMConstBitCast(typeInfo, kInt8Ptr)!!
|
LLVMConstBitCast(typeInfo, kInt8Ptr)!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2107,8 +2106,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
context.ir.symbols.createUninitializedInstance.descriptor -> {
|
context.ir.symbols.createUninitializedInstance.descriptor -> {
|
||||||
val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0]
|
val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0]
|
||||||
val enumClass = callee.getTypeArgument(typeParameterT)!!
|
val enumClass = callee.getTypeArgument(typeParameterT)!!
|
||||||
val enumClassDescriptor = enumClass.constructor.declarationDescriptor as ClassDescriptor
|
val enumIrClass = context.ir.getClass(enumClass)!!
|
||||||
functionGenerationContext.allocInstance(enumClassDescriptor, resultLifetime(callee))
|
functionGenerationContext.allocInstance(enumIrClass, resultLifetime(callee))
|
||||||
}
|
}
|
||||||
|
|
||||||
context.ir.symbols.listOfInternal.descriptor -> {
|
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 {
|
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)
|
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 {
|
private fun evaluateOperatorCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
context.log{"evaluateOperatorCall : origin:${ir2string(callee)}"}
|
context.log{"evaluateOperatorCall : origin:${ir2string(callee)}"}
|
||||||
val descriptor = callee.descriptor
|
val descriptor = callee.symbol.owner as IrFunction
|
||||||
val ib = context.irModule!!.irBuiltins
|
val ib = context.irModule!!.irBuiltins
|
||||||
|
|
||||||
with(functionGenerationContext) {
|
with(functionGenerationContext) {
|
||||||
return when {
|
return when {
|
||||||
descriptor == ib.eqeqeq -> icmpEq(args[0], args[1])
|
descriptor == ib.eqeqeqFun -> icmpEq(args[0], args[1])
|
||||||
descriptor == ib.booleanNot -> icmpNe(args[0], kTrue)
|
descriptor == ib.booleanNotFun -> icmpNe(args[0], kTrue)
|
||||||
|
|
||||||
descriptor.isComparisonDescriptor(ib.greaterFunByOperandType) -> {
|
descriptor.isComparisonDescriptor(ib.greaterFunByOperandType) -> {
|
||||||
if (args[0].type.isFloatingPoint()) fcmpGt(args[0], args[1])
|
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 {
|
descriptor: ClassConstructorDescriptor, args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
|
|
||||||
val constructedClass = functionGenerationContext.constructedClass!!
|
val constructedClass = functionGenerationContext.constructedClass!!
|
||||||
val thisPtr = currentCodeContext.genGetValue(constructedClass.thisAsReceiverParameter)
|
val thisPtr = currentCodeContext.genGetValue(constructedClass.thisReceiver!!)
|
||||||
|
|
||||||
if (constructedClass.isObjCClass()) {
|
if (constructedClass.isObjCClass()) {
|
||||||
return codegen.theUnitInstanceRef.llvm
|
return codegen.theUnitInstanceRef.llvm
|
||||||
|
|||||||
+26
-32
@@ -18,44 +18,40 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
|
|
||||||
import llvm.LLVMStoreSizeOfType
|
import llvm.LLVMStoreSizeOfType
|
||||||
import llvm.LLVMValueRef
|
import llvm.LLVMValueRef
|
||||||
|
import org.jetbrains.kotlin.backend.common.atMostOne
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
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.getStringValue
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.getStringValueOrNull
|
import org.jetbrains.kotlin.backend.konan.descriptors.getStringValueOrNull
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.isFinalClass
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
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.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
|
|
||||||
|
|
||||||
internal class KotlinObjCClassInfoGenerator(override val context: Context) : ContextUtils {
|
internal class KotlinObjCClassInfoGenerator(override val context: Context) : ContextUtils {
|
||||||
fun generate(irClass: IrClass) {
|
fun generate(irClass: IrClass) {
|
||||||
val descriptor = irClass.descriptor
|
assert(irClass.isFinalClass)
|
||||||
assert(descriptor.isFinalClass)
|
|
||||||
|
|
||||||
val objCLLvmDeclarations = context.llvmDeclarations.forClass(descriptor).objCDeclarations!!
|
val objCLLvmDeclarations = context.llvmDeclarations.forClass(irClass).objCDeclarations!!
|
||||||
|
|
||||||
val instanceMethods = generateInstanceMethodDescs(irClass)
|
val instanceMethods = generateInstanceMethodDescs(irClass)
|
||||||
|
|
||||||
val companionObjectDescriptor = descriptor.companionObjectDescriptor
|
val companionObject = irClass.declarations.filterIsInstance<IrClass>().atMostOne { it.isCompanion }
|
||||||
val classMethods = companionObjectDescriptor?.generateOverridingMethodDescs() ?: emptyList()
|
val classMethods = companionObject?.generateOverridingMethodDescs() ?: emptyList()
|
||||||
|
|
||||||
val superclassName = descriptor.getSuperClassNotAny()!!.let {
|
val superclassName = irClass.getSuperClassNotAny()!!.let {
|
||||||
context.llvm.imports.add(it.llvmSymbolOrigin)
|
context.llvm.imports.add(it.llvmSymbolOrigin)
|
||||||
it.name.asString()
|
it.name.asString()
|
||||||
}
|
}
|
||||||
val protocolNames = descriptor.getSuperInterfaces().map {
|
val protocolNames = irClass.getSuperInterfaces().map {
|
||||||
context.llvm.imports.add(it.llvmSymbolOrigin)
|
context.llvm.imports.add(it.llvmSymbolOrigin)
|
||||||
it.name.asString().removeSuffix("Protocol")
|
it.name.asString().removeSuffix("Protocol")
|
||||||
}
|
}
|
||||||
|
|
||||||
val bodySize =
|
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,
|
val info = Struct(runtime.kotlinObjCClassInfo,
|
||||||
className,
|
className,
|
||||||
@@ -73,8 +69,8 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
|||||||
Int32(bodySize),
|
Int32(bodySize),
|
||||||
objCLLvmDeclarations.bodyOffsetGlobal.pointer,
|
objCLLvmDeclarations.bodyOffsetGlobal.pointer,
|
||||||
|
|
||||||
descriptor.typeInfoPtr,
|
irClass.typeInfoPtr,
|
||||||
companionObjectDescriptor?.typeInfoPtr ?: NullPointer(runtime.typeInfoType),
|
companionObject?.typeInfoPtr ?: NullPointer(runtime.typeInfoType),
|
||||||
|
|
||||||
objCLLvmDeclarations.classPointerGlobal.pointer
|
objCLLvmDeclarations.classPointerGlobal.pointer
|
||||||
)
|
)
|
||||||
@@ -88,13 +84,12 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
|||||||
private fun generateInstanceMethodDescs(
|
private fun generateInstanceMethodDescs(
|
||||||
irClass: IrClass
|
irClass: IrClass
|
||||||
): List<ObjCMethodDesc> = mutableListOf<ObjCMethodDesc>().apply {
|
): List<ObjCMethodDesc> = mutableListOf<ObjCMethodDesc>().apply {
|
||||||
val descriptor = irClass.descriptor
|
addAll(irClass.generateOverridingMethodDescs())
|
||||||
addAll(descriptor.generateOverridingMethodDescs())
|
|
||||||
addAll(irClass.generateImpMethodDescs())
|
addAll(irClass.generateImpMethodDescs())
|
||||||
val allImplementedSelectors = this.map { it.selector }.toSet()
|
val allImplementedSelectors = this.map { it.selector }.toSet()
|
||||||
|
|
||||||
assert(descriptor.getSuperClassNotAny()!!.isExternalObjCClass())
|
assert(irClass.getSuperClassNotAny()!!.isExternalObjCClass())
|
||||||
val allInitMethodsInfo = descriptor.getSuperClassNotAny()!!.constructors
|
val allInitMethodsInfo = irClass.getSuperClassNotAny()!!.constructors
|
||||||
.mapNotNull { it.getObjCInitMethod()?.getExternalObjCMethodInfo() }
|
.mapNotNull { it.getObjCInitMethod()?.getExternalObjCMethodInfo() }
|
||||||
.filter { it.selector !in allImplementedSelectors }
|
.filter { it.selector !in allImplementedSelectors }
|
||||||
.distinctBy { it.selector }
|
.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 =
|
val exportObjCClassAnnotation =
|
||||||
descriptor.annotations.findAnnotation(context.interopBuiltIns.exportObjCClass.fqNameSafe)
|
irClass.annotations.findAnnotation(context.interopBuiltIns.exportObjCClass.fqNameSafe)
|
||||||
|
|
||||||
return if (exportObjCClassAnnotation != null) {
|
return if (exportObjCClassAnnotation != null) {
|
||||||
exportObjCClassAnnotation.getStringValueOrNull("name") ?: descriptor.name.asString()
|
exportObjCClassAnnotation.getStringValueOrNull("name") ?: irClass.name.asString()
|
||||||
} else if (descriptor.isExported()) {
|
} else if (irClass.isExported()) {
|
||||||
descriptor.fqNameSafe.asString()
|
irClass.fqNameSafe.asString()
|
||||||
} else {
|
} else {
|
||||||
null // Generate as anonymous.
|
null // Generate as anonymous.
|
||||||
}
|
}
|
||||||
@@ -138,22 +133,21 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun ClassDescriptor.generateOverridingMethodDescs(): List<ObjCMethodDesc> =
|
private fun IrClass.generateOverridingMethodDescs(): List<ObjCMethodDesc> =
|
||||||
this.unsubstitutedMemberScope.contributedMethods.filter {
|
this.simpleFunctions().filter { it.isReal }
|
||||||
it.kind.isReal && it !is ConstructorDescriptor
|
.mapNotNull { it.getObjCMethodInfo() }.map { generateMethodDesc(it) }
|
||||||
}.mapNotNull { it.getObjCMethodInfo() }.map { generateMethodDesc(it) }
|
|
||||||
|
|
||||||
private fun IrClass.generateImpMethodDescs(): List<ObjCMethodDesc> = this.declarations
|
private fun IrClass.generateImpMethodDescs(): List<ObjCMethodDesc> = this.declarations
|
||||||
.filterIsInstance<IrSimpleFunction>()
|
.filterIsInstance<IrSimpleFunction>()
|
||||||
.mapNotNull {
|
.mapNotNull {
|
||||||
val annotation =
|
val annotation =
|
||||||
it.descriptor.annotations.findAnnotation(context.interopBuiltIns.objCMethodImp.fqNameSafe) ?:
|
it.annotations.findAnnotation(context.interopBuiltIns.objCMethodImp.fqNameSafe) ?:
|
||||||
return@mapNotNull null
|
return@mapNotNull null
|
||||||
|
|
||||||
ObjCMethodDesc(
|
ObjCMethodDesc(
|
||||||
annotation.getStringValue("selector"),
|
annotation.getStringValue("selector"),
|
||||||
annotation.getStringValue("encoding"),
|
annotation.getStringValue("encoding"),
|
||||||
it.descriptor.llvmFunction
|
it.llvmFunction
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+39
-57
@@ -20,18 +20,13 @@ import kotlinx.cinterop.*
|
|||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
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 {
|
internal fun createLlvmDeclarations(context: Context): LlvmDeclarations {
|
||||||
val generator = DeclarationsGeneratorVisitor(context)
|
val generator = DeclarationsGeneratorVisitor(context)
|
||||||
@@ -47,8 +42,8 @@ internal fun createLlvmDeclarations(context: Context): LlvmDeclarations {
|
|||||||
internal class LlvmDeclarations(
|
internal class LlvmDeclarations(
|
||||||
private val functions: Map<FunctionDescriptor, FunctionLlvmDeclarations>,
|
private val functions: Map<FunctionDescriptor, FunctionLlvmDeclarations>,
|
||||||
private val classes: Map<ClassDescriptor, ClassLlvmDeclarations>,
|
private val classes: Map<ClassDescriptor, ClassLlvmDeclarations>,
|
||||||
private val fields: Map<PropertyDescriptor, FieldLlvmDeclarations>,
|
private val fields: Map<IrField, FieldLlvmDeclarations>,
|
||||||
private val staticFields: Map<PropertyDescriptor, StaticFieldLlvmDeclarations>,
|
private val staticFields: Map<IrField, StaticFieldLlvmDeclarations>,
|
||||||
private val theUnitInstanceRef: ConstPointer?
|
private val theUnitInstanceRef: ConstPointer?
|
||||||
) {
|
) {
|
||||||
fun forFunction(descriptor: FunctionDescriptor) = functions[descriptor] ?:
|
fun forFunction(descriptor: FunctionDescriptor) = functions[descriptor] ?:
|
||||||
@@ -57,10 +52,10 @@ internal class LlvmDeclarations(
|
|||||||
fun forClass(descriptor: ClassDescriptor) = classes[descriptor] ?:
|
fun forClass(descriptor: ClassDescriptor) = classes[descriptor] ?:
|
||||||
error(descriptor.toString())
|
error(descriptor.toString())
|
||||||
|
|
||||||
fun forField(descriptor: PropertyDescriptor) = fields[descriptor] ?:
|
fun forField(descriptor: IrField) = fields[descriptor] ?:
|
||||||
error(descriptor.toString())
|
error(descriptor.toString())
|
||||||
|
|
||||||
fun forStaticField(descriptor: PropertyDescriptor) = staticFields[descriptor] ?:
|
fun forStaticField(descriptor: IrField) = staticFields[descriptor] ?:
|
||||||
error(descriptor.toString())
|
error(descriptor.toString())
|
||||||
|
|
||||||
fun forSingleton(descriptor: ClassDescriptor) = forClass(descriptor).singletonDeclarations ?:
|
fun forSingleton(descriptor: ClassDescriptor) = forClass(descriptor).singletonDeclarations ?:
|
||||||
@@ -72,7 +67,7 @@ internal class LlvmDeclarations(
|
|||||||
|
|
||||||
internal class ClassLlvmDeclarations(
|
internal class ClassLlvmDeclarations(
|
||||||
val bodyType: LLVMTypeRef,
|
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 typeInfoGlobal: StaticData.Global,
|
||||||
val writableTypeInfoGlobal: StaticData.Global?,
|
val writableTypeInfoGlobal: StaticData.Global?,
|
||||||
val typeInfo: ConstPointer,
|
val typeInfo: ConstPointer,
|
||||||
@@ -101,7 +96,7 @@ internal class StaticFieldLlvmDeclarations(val storage: LLVMValueRef)
|
|||||||
*/
|
*/
|
||||||
internal fun ContextUtils.getFields(classDescriptor: ClassDescriptor) = context.getFields(classDescriptor)
|
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 superClass = classDescriptor.getSuperClassNotAny() // TODO: what if Any has fields?
|
||||||
val superFields = if (superClass != null) getFields(superClass) else emptyList()
|
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.
|
* 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:
|
// TODO: Here's what is going on here:
|
||||||
// The existence of a backing field for a property is only described in the IR,
|
// The existence of a backing field for a property is only described in the IR,
|
||||||
// but not in the PropertyDescriptor.
|
// 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
|
// In this function we check the presence of the backing field
|
||||||
// two ways: first we check IR, then we check the protobuf extension.
|
// two ways: first we check IR, then we check the protobuf extension.
|
||||||
|
|
||||||
val irClass = ir.moduleIndexForCodegen.classes[classDescriptor]
|
val irClass = classDescriptor
|
||||||
val fields = if (irClass != null) {
|
val fields = irClass.declarations.mapNotNull {
|
||||||
val declarations = irClass.declarations
|
when (it) {
|
||||||
|
is IrField -> it
|
||||||
declarations.mapNotNull {
|
is IrProperty -> it.konanBackingField
|
||||||
when (it) {
|
else -> null
|
||||||
is IrProperty -> it.backingField?.descriptor
|
|
||||||
is IrField -> it.descriptor
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
val properties = classDescriptor.unsubstitutedMemberScope.
|
|
||||||
getContributedDescriptors().
|
|
||||||
filterIsInstance<DeserializedPropertyDescriptor>()
|
|
||||||
|
|
||||||
properties.mapNotNull { it.backingField }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fields.sortedBy {
|
return fields.sortedBy {
|
||||||
it.fqNameSafe.localHash.value
|
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 {
|
val fieldTypes = fields.map {
|
||||||
@Suppress("DEPRECATION")
|
@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)!!
|
val classType = LLVMStructCreateNamed(LLVMGetModuleContext(context.llvmModule), name)!!
|
||||||
@@ -163,8 +149,8 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
|
|
||||||
val functions = mutableMapOf<FunctionDescriptor, FunctionLlvmDeclarations>()
|
val functions = mutableMapOf<FunctionDescriptor, FunctionLlvmDeclarations>()
|
||||||
val classes = mutableMapOf<ClassDescriptor, ClassLlvmDeclarations>()
|
val classes = mutableMapOf<ClassDescriptor, ClassLlvmDeclarations>()
|
||||||
val fields = mutableMapOf<PropertyDescriptor, FieldLlvmDeclarations>()
|
val fields = mutableMapOf<IrField, FieldLlvmDeclarations>()
|
||||||
val staticFields = mutableMapOf<PropertyDescriptor, StaticFieldLlvmDeclarations>()
|
val staticFields = mutableMapOf<IrField, StaticFieldLlvmDeclarations>()
|
||||||
var theUnitInstanceRef: ConstPointer? = null
|
var theUnitInstanceRef: ConstPointer? = null
|
||||||
|
|
||||||
private class Namer(val prefix: String) {
|
private class Namer(val prefix: String) {
|
||||||
@@ -183,7 +169,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
val objectNamer = Namer("object-")
|
val objectNamer = Namer("object-")
|
||||||
|
|
||||||
private fun getLocalName(parent: FqName, descriptor: DeclarationDescriptor): Name {
|
private fun getLocalName(parent: FqName, descriptor: DeclarationDescriptor): Name {
|
||||||
if (DescriptorUtils.isAnonymousObject(descriptor)) {
|
if (descriptor.isAnonymousObject) {
|
||||||
return objectNamer.getName(parent, descriptor)
|
return objectNamer.getName(parent, descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,20 +177,15 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getFqName(descriptor: DeclarationDescriptor): FqName {
|
private fun getFqName(descriptor: DeclarationDescriptor): FqName {
|
||||||
if (descriptor is PackageFragmentDescriptor) {
|
val parent = descriptor.parent
|
||||||
return descriptor.fqName
|
val parentFqName = when (parent) {
|
||||||
|
is IrPackageFragment -> parent.fqName
|
||||||
|
is IrDeclaration -> getFqName(parent)
|
||||||
|
else -> error(parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val localName = getLocalName(parentFqName, descriptor)
|
||||||
val containingDeclaration = descriptor.containingDeclaration
|
return parentFqName.child(localName)
|
||||||
val parent = if (containingDeclaration != null) {
|
|
||||||
getFqName(containingDeclaration)
|
|
||||||
} else {
|
|
||||||
FqName.ROOT
|
|
||||||
}
|
|
||||||
|
|
||||||
val localName = getLocalName(parent, descriptor)
|
|
||||||
return parent.child(localName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -223,17 +204,17 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
|
|
||||||
override fun visitClass(declaration: IrClass) {
|
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
|
// do not generate any declarations for intrinsic classes as they require special handling
|
||||||
} else {
|
} else {
|
||||||
this.classes[declaration.descriptor] = createClassDeclarations(declaration)
|
this.classes[declaration] = createClassDeclarations(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
super.visitClass(declaration)
|
super.visitClass(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createClassDeclarations(declaration: IrClass): ClassLlvmDeclarations {
|
private fun createClassDeclarations(declaration: IrClass): ClassLlvmDeclarations {
|
||||||
val descriptor = declaration.descriptor
|
val descriptor = declaration
|
||||||
|
|
||||||
val internalName = qualifyInternalName(descriptor)
|
val internalName = qualifyInternalName(descriptor)
|
||||||
|
|
||||||
@@ -317,7 +298,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
): SingletonLlvmDeclarations? {
|
): SingletonLlvmDeclarations? {
|
||||||
|
|
||||||
if (descriptor.isUnit()) {
|
if (descriptor.isUnit()) {
|
||||||
this.theUnitInstanceRef = staticData.createUnitInstance(descriptor, bodyType, typeInfoPtr)
|
this.theUnitInstanceRef = staticData.createUnitInstance(bodyType, typeInfoPtr)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,6 +311,8 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
val instanceFieldRef = addGlobal(
|
val instanceFieldRef = addGlobal(
|
||||||
symbolName, getLLVMType(descriptor.defaultType), isExported = isExported, threadLocal = true)
|
symbolName, getLLVMType(descriptor.defaultType), isExported = isExported, threadLocal = true)
|
||||||
|
|
||||||
|
LLVMSetInitializer(instanceFieldRef, kNullObjHeaderPtr)
|
||||||
|
|
||||||
return SingletonLlvmDeclarations(instanceFieldRef)
|
return SingletonLlvmDeclarations(instanceFieldRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,11 +336,10 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
override fun visitField(declaration: IrField) {
|
override fun visitField(declaration: IrField) {
|
||||||
super.visitField(declaration)
|
super.visitField(declaration)
|
||||||
|
|
||||||
val descriptor = declaration.descriptor
|
val descriptor = declaration
|
||||||
|
|
||||||
val dispatchReceiverParameter = descriptor.dispatchReceiverParameter
|
val containingClass = descriptor.containingClass
|
||||||
if (dispatchReceiverParameter != null) {
|
if (containingClass != null) {
|
||||||
val containingClass = dispatchReceiverParameter.containingDeclaration
|
|
||||||
val classDeclarations = this.classes[containingClass] ?: error(containingClass.toString())
|
val classDeclarations = this.classes[containingClass] ?: error(containingClass.toString())
|
||||||
|
|
||||||
val allFields = classDeclarations.fields
|
val allFields = classDeclarations.fields
|
||||||
@@ -381,9 +363,9 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
override fun visitFunction(declaration: IrFunction) {
|
override fun visitFunction(declaration: IrFunction) {
|
||||||
super.visitFunction(declaration)
|
super.visitFunction(declaration)
|
||||||
|
|
||||||
if (!declaration.descriptor.kind.isReal) return
|
if (!declaration.isReal) return
|
||||||
|
|
||||||
val descriptor = declaration.descriptor
|
val descriptor = declaration
|
||||||
val llvmFunctionType = getLlvmFunctionType(descriptor)
|
val llvmFunctionType = getLlvmFunctionType(descriptor)
|
||||||
|
|
||||||
if ((descriptor is ConstructorDescriptor && descriptor.getObjCInitMethod() != null)) {
|
if ((descriptor is ConstructorDescriptor && descriptor.getObjCInitMethod() != null)) {
|
||||||
@@ -402,7 +384,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
} else {
|
} else {
|
||||||
val symbolName = if (descriptor.isExported()) {
|
val symbolName = if (descriptor.isExported()) {
|
||||||
descriptor.symbolName.also {
|
descriptor.symbolName.also {
|
||||||
if (!MainFunctionDetector.isMain(descriptor)) {
|
if (!descriptor.isMain()) {
|
||||||
assert(LLVMGetNamedFunction(context.llvm.llvmModule, it) == null) { it }
|
assert(LLVMGetNamedFunction(context.llvm.llvmModule, it) == null) { it }
|
||||||
} else {
|
} else {
|
||||||
// As a workaround, allow `main` functions to clash because frontend accepts this.
|
// 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 llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||||
import org.jetbrains.kotlin.backend.konan.isExternalObjCClassMethod
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
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 {
|
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 size = getInstanceSize(bodyType, className)
|
||||||
|
|
||||||
val superTypeOrAny = classDesc.getSuperClassOrAny()
|
val superTypeOrAny = classDesc.getSuperClassNotAny() ?: context.ir.symbols.any.owner
|
||||||
val superType = if (KotlinBuiltIns.isAny(classDesc)) NullPointer(runtime.typeInfoType)
|
val superType = if (classDesc.isAny()) NullPointer(runtime.typeInfoType)
|
||||||
else superTypeOrAny.typeInfoPtr
|
else superTypeOrAny.typeInfoPtr
|
||||||
|
|
||||||
val interfaces = classDesc.implementedInterfaces.map { it.typeInfoPtr }
|
val interfaces = classDesc.implementedInterfaces.map { it.typeInfoPtr }
|
||||||
@@ -236,14 +233,14 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
|
|
||||||
val size = 0
|
val size = 0
|
||||||
|
|
||||||
val superClass = context.builtIns.any
|
val superClass = context.ir.symbols.any.owner
|
||||||
|
|
||||||
assert(superClass.implementedInterfaces.isEmpty())
|
assert(superClass.implementedInterfaces.isEmpty())
|
||||||
val interfaces = listOf(descriptor.typeInfoPtr)
|
val interfaces = listOf(descriptor.typeInfoPtr)
|
||||||
val interfacesPtr = staticData.placeGlobalConstArray("",
|
val interfacesPtr = staticData.placeGlobalConstArray("",
|
||||||
pointerType(runtime.typeInfoType), interfaces)
|
pointerType(runtime.typeInfoType), interfaces)
|
||||||
|
|
||||||
assert(superClass.getMemberScope().getVariableNames().isEmpty())
|
assert(superClass.declarations.all { it !is IrProperty && it !is IrField })
|
||||||
val objOffsetsPtr = NullPointer(int32Type)
|
val objOffsetsPtr = NullPointer(int32Type)
|
||||||
val objOffsetsCount = 0
|
val objOffsetsCount = 0
|
||||||
val fieldsPtr = NullPointer(runtime.fieldTableRecordType)
|
val fieldsPtr = NullPointer(runtime.fieldTableRecordType)
|
||||||
@@ -295,18 +292,18 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
private fun getReflectionInfo(descriptor: ClassDescriptor): ReflectionInfo {
|
private fun getReflectionInfo(descriptor: ClassDescriptor): ReflectionInfo {
|
||||||
// Use data from value class in type info for box class:
|
// Use data from value class in type info for box class:
|
||||||
val descriptorForReflection = context.ir.symbols.valueClassToBox.entries
|
val descriptorForReflection = context.ir.symbols.valueClassToBox.entries
|
||||||
.firstOrNull { it.value.descriptor == descriptor }
|
.firstOrNull { it.value.owner == descriptor }
|
||||||
?.key ?: descriptor
|
?.key?.owner ?: descriptor
|
||||||
|
|
||||||
return if (DescriptorUtils.isAnonymousObject(descriptorForReflection)) {
|
return if (descriptorForReflection.isAnonymousObject) {
|
||||||
ReflectionInfo(packageName = null, relativeName = null)
|
ReflectionInfo(packageName = null, relativeName = null)
|
||||||
} else if (DescriptorUtils.isLocal(descriptorForReflection)) {
|
} else if (descriptorForReflection.isLocal) {
|
||||||
ReflectionInfo(packageName = null, relativeName = descriptorForReflection.name.asString())
|
ReflectionInfo(packageName = null, relativeName = descriptorForReflection.name.asString())
|
||||||
} else {
|
} else {
|
||||||
ReflectionInfo(
|
ReflectionInfo(
|
||||||
packageName = descriptorForReflection.findPackage().fqName.asString(),
|
packageName = descriptorForReflection.findPackage().fqName.asString(),
|
||||||
relativeName = descriptorForReflection.parentsWithSelf
|
relativeName = generateSequence(descriptorForReflection, { it.parent as? ClassDescriptor })
|
||||||
.takeWhile { it is ClassDescriptor }.toList().reversed()
|
.toList().reversed()
|
||||||
.joinToString(".") { it.name.asString() }
|
.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 {
|
internal fun StaticData.createImmutableBinaryBlob(value: IrConst<String>): LLVMValueRef {
|
||||||
val args = value.value.map { Int8(it.toByte()).llvm }
|
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.LLVMSetLinkage
|
||||||
import llvm.LLVMTypeRef
|
import llvm.LLVMTypeRef
|
||||||
import llvm.LLVMValueRef
|
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.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
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.TypeProjection
|
||||||
import org.jetbrains.kotlin.types.replace
|
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 {
|
internal fun StaticData.createKotlinStringLiteral(value: String): ConstPointer {
|
||||||
val type = context.builtIns.stringType
|
|
||||||
|
|
||||||
val name = "kstr:" + value.globalHashBase64
|
val name = "kstr:" + value.globalHashBase64
|
||||||
val elements = value.toCharArray().map(::Char16)
|
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)
|
val res = createAlias(name, objRef)
|
||||||
LLVMSetLinkage(res.llvm, LLVMLinkage.LLVMWeakAnyLinkage)
|
LLVMSetLinkage(res.llvm, LLVMLinkage.LLVMWeakAnyLinkage)
|
||||||
@@ -56,20 +54,13 @@ internal fun StaticData.createKotlinStringLiteral(value: String): ConstPointer {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun StaticData.createRef(type: KotlinType, objHeaderPtr: ConstPointer): ConstPointer {
|
private fun StaticData.createRef(objHeaderPtr: ConstPointer) = objHeaderPtr.bitcast(kObjHeaderPtr)
|
||||||
val llvmType = getLLVMType(type)
|
|
||||||
return if (llvmType != objHeaderPtr.llvmType) {
|
|
||||||
objHeaderPtr.bitcast(llvmType)
|
|
||||||
} else {
|
|
||||||
objHeaderPtr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun StaticData.createKotlinArray(arrayType: KotlinType, elements: List<LLVMValueRef>) =
|
internal fun StaticData.createKotlinArray(arrayClass: IrClass, elements: List<LLVMValueRef>) =
|
||||||
createKotlinArray(arrayType, elements.map { constValue(it) }).llvm
|
createKotlinArray(arrayClass, elements.map { constValue(it) }).llvm
|
||||||
|
|
||||||
internal fun StaticData.createKotlinArray(arrayType: KotlinType, elements: List<ConstValue>): ConstPointer {
|
internal fun StaticData.createKotlinArray(arrayClass: IrClass, elements: List<ConstValue>): ConstPointer {
|
||||||
val typeInfo = arrayType.typeInfoPtr!!
|
val typeInfo = arrayClass.typeInfoPtr
|
||||||
|
|
||||||
val bodyElementType: LLVMTypeRef = elements.firstOrNull()?.llvmType ?: int8Type
|
val bodyElementType: LLVMTypeRef = elements.firstOrNull()?.llvmType ?: int8Type
|
||||||
// (use [0 x i8] as body if there are no elements)
|
// (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))
|
global.setInitializer(Struct(compositeType, arrayHeader, arrayBody))
|
||||||
|
|
||||||
return createRef(arrayType, objHeaderPtr)
|
return createRef(objHeaderPtr)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun StaticData.createKotlinObject(type: KotlinType, body: ConstValue): ConstPointer {
|
internal fun StaticData.createKotlinObject(type: IrClass, body: ConstValue): ConstPointer {
|
||||||
val typeInfo = type.typeInfoPtr!!
|
val typeInfo = type.typeInfoPtr
|
||||||
|
|
||||||
val compositeType = structType(runtime.objHeaderType, body.llvmType)
|
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))
|
global.setInitializer(Struct(compositeType, objHeader, body))
|
||||||
|
|
||||||
return createRef(type, objHeaderPtr)
|
return createRef(objHeaderPtr)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun StaticData.getArrayListClass(): ClassDescriptor {
|
private fun StaticData.getArrayListClass(): ClassDescriptor {
|
||||||
@@ -118,7 +109,7 @@ private fun StaticData.getArrayListClass(): ClassDescriptor {
|
|||||||
* @param length value for `length: Int` field.
|
* @param length value for `length: Int` field.
|
||||||
*/
|
*/
|
||||||
internal fun StaticData.createArrayList(elementType: TypeProjection, array: ConstPointer, length: Int): ConstPointer {
|
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>:
|
// type is ArrayList<elementType>:
|
||||||
val type = arrayListClass.defaultType.replace(listOf(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()))
|
val body = Struct(*(sorted.values.toTypedArray()))
|
||||||
|
|
||||||
return createKotlinObject(type, body)
|
return createKotlinObject(arrayListClass, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun StaticData.createUnitInstance(descriptor: ClassDescriptor,
|
internal fun StaticData.createUnitInstance(bodyType: LLVMTypeRef,
|
||||||
bodyType: LLVMTypeRef,
|
|
||||||
typeInfo: ConstPointer
|
typeInfo: ConstPointer
|
||||||
): ConstPointer {
|
): ConstPointer {
|
||||||
assert (descriptor.isUnit())
|
|
||||||
assert (getStructElements(bodyType).isEmpty())
|
assert (getStructElements(bodyType).isEmpty())
|
||||||
val objHeader = objHeader(typeInfo)
|
val objHeader = objHeader(typeInfo)
|
||||||
val global = this.placeGlobal(theUnitInstanceName, objHeader, isExported = true)
|
val global = this.placeGlobal(theUnitInstanceName, objHeader, isExported = true)
|
||||||
@@ -157,7 +146,7 @@ internal fun StaticData.createUnitInstance(descriptor: ClassDescriptor,
|
|||||||
|
|
||||||
internal val ContextUtils.theUnitInstanceRef: ConstPointer
|
internal val ContextUtils.theUnitInstanceRef: ConstPointer
|
||||||
get() {
|
get() {
|
||||||
val unitDescriptor = context.builtIns.unit
|
val unitDescriptor = context.ir.symbols.unit.owner
|
||||||
return if (isExternal(unitDescriptor)) {
|
return if (isExternal(unitDescriptor)) {
|
||||||
constPointer(importGlobal(
|
constPointer(importGlobal(
|
||||||
theUnitInstanceName,
|
theUnitInstanceName,
|
||||||
|
|||||||
+8
-1
@@ -18,8 +18,9 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
|
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
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.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.name.Name
|
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)
|
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 llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.CurrentKonanModule
|
import org.jetbrains.kotlin.backend.konan.descriptors.CurrentKonanModule
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
internal fun ObjCExportCodeGenerator.generateKotlinFunctionImpl(invokeMethod: FunctionDescriptor): ConstPointer {
|
internal fun ObjCExportCodeGenerator.generateKotlinFunctionImpl(invokeMethod: FunctionDescriptor): ConstPointer {
|
||||||
// TODO: consider also overriding methods of `Any`.
|
// TODO: consider also overriding methods of `Any`.
|
||||||
@@ -31,7 +30,7 @@ internal fun ObjCExportCodeGenerator.generateKotlinFunctionImpl(invokeMethod: Fu
|
|||||||
|
|
||||||
val function = generateFunction(
|
val function = generateFunction(
|
||||||
codegen,
|
codegen,
|
||||||
codegen.getLlvmFunctionType(invokeMethod),
|
codegen.getLlvmFunctionType(context.ir.get(invokeMethod)),
|
||||||
"invokeFunction$numberOfParameters"
|
"invokeFunction$numberOfParameters"
|
||||||
) {
|
) {
|
||||||
val args = (0 until numberOfParameters).map { index -> kotlinReferenceToObjC(param(index + 1)) }
|
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)
|
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)
|
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.common.descriptors.allParameters
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
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.*
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.objc.ObjCCodeGenerator
|
import org.jetbrains.kotlin.backend.konan.llvm.objc.ObjCCodeGenerator
|
||||||
import org.jetbrains.kotlin.backend.konan.objcexport.*
|
import org.jetbrains.kotlin.backend.konan.objcexport.*
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
internal class ObjCExportCodeGenerator(
|
internal class ObjCExportCodeGenerator(
|
||||||
codegen: CodeGenerator,
|
codegen: CodeGenerator,
|
||||||
@@ -153,7 +155,7 @@ internal class ObjCExportCodeGenerator(
|
|||||||
|
|
||||||
val value = genValue(Lifetime.ARGUMENT)
|
val value = genValue(Lifetime.ARGUMENT)
|
||||||
|
|
||||||
return callFromBridge(conversion.descriptor.llvmFunction, listOf(value), resultLifetime)
|
return callFromBridge(conversion.owner.llvmFunction, listOf(value), resultLifetime)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun emitRtti(
|
internal fun emitRtti(
|
||||||
@@ -329,15 +331,16 @@ private fun ObjCExportCodeGenerator.setObjCExportTypeInfo(
|
|||||||
val writableTypeInfoType = runtime.writableTypeInfoType!!
|
val writableTypeInfoType = runtime.writableTypeInfoType!!
|
||||||
val writableTypeInfoValue = Struct(writableTypeInfoType, objCExportAddition)
|
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.
|
// Note: this global replaces the external one with common linkage.
|
||||||
staticData.createGlobal(
|
staticData.createGlobal(
|
||||||
writableTypeInfoType,
|
writableTypeInfoType,
|
||||||
descriptor.writableTypeInfoSymbolName,
|
irClass.writableTypeInfoSymbolName,
|
||||||
isExported = true
|
isExported = true
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
context.llvmDeclarations.forClass(descriptor).writableTypeInfoGlobal!!.also {
|
context.llvmDeclarations.forClass(irClass).writableTypeInfoGlobal!!.also {
|
||||||
it.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
it.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -356,7 +359,7 @@ private fun ObjCExportCodeGenerator.emitBoxConverter(objCValueType: ObjCValueTyp
|
|||||||
val name = "${valueType.classFqName.shortName()}To${objCValueType.nsNumberName}"
|
val name = "${valueType.classFqName.shortName()}To${objCValueType.nsNumberName}"
|
||||||
|
|
||||||
val converter = generateFunction(codegen, kotlinToObjCFunctionType, name) {
|
val converter = generateFunction(codegen, kotlinToObjCFunctionType, name) {
|
||||||
val unboxFunction = symbols.getUnboxFunction(valueType).descriptor.llvmFunction
|
val unboxFunction = symbols.getUnboxFunction(valueType).owner.llvmFunction
|
||||||
val kotlinValue = callFromBridge(
|
val kotlinValue = callFromBridge(
|
||||||
unboxFunction,
|
unboxFunction,
|
||||||
listOf(param(0)),
|
listOf(param(0)),
|
||||||
@@ -385,15 +388,14 @@ private fun ObjCExportCodeGenerator.emitFunctionConverters() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun ObjCExportCodeGenerator.generateKotlinFunctionAdapterToBlock(numberOfParameters: Int): ConstPointer {
|
private fun ObjCExportCodeGenerator.generateKotlinFunctionAdapterToBlock(numberOfParameters: Int): ConstPointer {
|
||||||
val interfaceDescriptor = codegen.context.builtIns.getFunction(numberOfParameters)
|
val irInterface = context.ir.symbols.functions[numberOfParameters].owner
|
||||||
val invokeMethod = interfaceDescriptor.unsubstitutedMemberScope.getContributedFunctions(
|
val invokeMethod = irInterface.declarations.filterIsInstance<IrSimpleFunction>()
|
||||||
Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND
|
.single { it.name == OperatorNameConventions.INVOKE }
|
||||||
).single()
|
|
||||||
|
|
||||||
val invokeImpl = generateKotlinFunctionImpl(invokeMethod)
|
val invokeImpl = generateKotlinFunctionImpl(invokeMethod.descriptor)
|
||||||
|
|
||||||
return rttiGenerator.generateSyntheticInterfaceImpl(
|
return rttiGenerator.generateSyntheticInterfaceImpl(
|
||||||
interfaceDescriptor,
|
irInterface,
|
||||||
mapOf(invokeMethod to invokeImpl)
|
mapOf(invokeMethod to invokeImpl)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -414,7 +416,7 @@ private fun ObjCExportCodeGenerator.emitKotlinFunctionAdaptersToBlock() {
|
|||||||
private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() {
|
private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() {
|
||||||
setObjCExportTypeInfo(
|
setObjCExportTypeInfo(
|
||||||
context.builtIns.string,
|
context.builtIns.string,
|
||||||
constPointer(codegen.llvmFunction(context.interopBuiltIns.CreateNSStringFromKString))
|
constPointer(codegen.llvmFunction(context.ir.symbols.interopCreateNSStringFromKString.owner))
|
||||||
)
|
)
|
||||||
|
|
||||||
setObjCExportTypeInfo(
|
setObjCExportTypeInfo(
|
||||||
@@ -495,10 +497,11 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val targetIr = context.ir.get(target)
|
||||||
val llvmTarget = if (!isVirtual) {
|
val llvmTarget = if (!isVirtual) {
|
||||||
codegen.llvmFunction(target)
|
codegen.llvmFunction(targetIr)
|
||||||
} else {
|
} else {
|
||||||
lookupVirtualImpl(args.first(), target)
|
lookupVirtualImpl(args.first(), targetIr)
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetResult = callFromBridge(llvmTarget, args, Lifetime.ARGUMENT)
|
val targetResult = callFromBridge(llvmTarget, args, Lifetime.ARGUMENT)
|
||||||
@@ -533,13 +536,15 @@ private fun ObjCExportCodeGenerator.generateObjCImpForArrayConstructor(
|
|||||||
objCToKotlin(param(index + 2), typeBridge, Lifetime.ARGUMENT)
|
objCToKotlin(param(index + 2), typeBridge, Lifetime.ARGUMENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val targetIr = context.ir.get(target)
|
||||||
|
|
||||||
val arrayInstance = callFromBridge(
|
val arrayInstance = callFromBridge(
|
||||||
context.llvm.allocArrayFunction,
|
context.llvm.allocArrayFunction,
|
||||||
listOf(target.constructedClass.llvmTypeInfoPtr, kotlinValueArgs.first()),
|
listOf((targetIr as IrConstructor).constructedClass.llvmTypeInfoPtr, kotlinValueArgs.first()),
|
||||||
resultLifetime = Lifetime.ARGUMENT
|
resultLifetime = Lifetime.ARGUMENT
|
||||||
)
|
)
|
||||||
callFromBridge(
|
callFromBridge(
|
||||||
target.llvmFunction,
|
targetIr.llvmFunction,
|
||||||
listOf(arrayInstance) + kotlinValueArgs
|
listOf(arrayInstance) + kotlinValueArgs
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -564,7 +569,7 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
|||||||
|
|
||||||
val objcMsgSend = msgSender(objCFunctionType(methodBridge))
|
val objcMsgSend = msgSender(objCFunctionType(methodBridge))
|
||||||
|
|
||||||
val functionType = codegen.getLlvmFunctionType(descriptor)
|
val functionType = codegen.getLlvmFunctionType(context.ir.get(descriptor))
|
||||||
|
|
||||||
val result = generateFunction(codegen, functionType, "") {
|
val result = generateFunction(codegen, functionType, "") {
|
||||||
val args = mutableListOf<LLVMValueRef>()
|
val args = mutableListOf<LLVMValueRef>()
|
||||||
@@ -689,7 +694,8 @@ private fun ObjCExportCodeGenerator.vtableIndex(descriptor: FunctionDescriptor):
|
|||||||
return if (classDescriptor.isInterface) {
|
return if (classDescriptor.isInterface) {
|
||||||
null
|
null
|
||||||
} else {
|
} 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 {
|
inherited.forEach {
|
||||||
presentVtableBridges += vtableIndex(it)
|
presentVtableBridges += vtableIndex(it)
|
||||||
presentMethodTableBridges += it.functionName
|
presentMethodTableBridges += context.ir.get(it).functionName
|
||||||
}
|
}
|
||||||
|
|
||||||
uninherited.forEach {
|
uninherited.forEach {
|
||||||
val vtableIndex = vtableIndex(it)
|
val vtableIndex = vtableIndex(it)
|
||||||
val functionName = it.functionName
|
val functionName = context.ir.get(it).functionName
|
||||||
|
|
||||||
if (vtableIndex !in presentVtableBridges || functionName !in presentMethodTableBridges) {
|
if (vtableIndex !in presentVtableBridges || functionName !in presentMethodTableBridges) {
|
||||||
presentVtableBridges += vtableIndex
|
presentVtableBridges += vtableIndex
|
||||||
@@ -794,17 +800,18 @@ private fun ObjCExportCodeGenerator.createTypeAdapter(
|
|||||||
.filter { mapper.isBaseMethod(it) && it.isOverridable }
|
.filter { mapper.isBaseMethod(it) && it.isOverridable }
|
||||||
.map { createMethodVirtualAdapter(it) }
|
.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 objCName = namer.getClassOrProtocolName(descriptor)
|
||||||
|
|
||||||
val vtableSize = if (descriptor.kind == ClassKind.INTERFACE) {
|
val vtableSize = if (descriptor.kind == ClassKind.INTERFACE) {
|
||||||
-1
|
-1
|
||||||
} else {
|
} else {
|
||||||
context.getVtableBuilder(descriptor).vtableEntries.size
|
context.getVtableBuilder(irClass).vtableEntries.size
|
||||||
}
|
}
|
||||||
|
|
||||||
val vtable = if (!descriptor.isInterface && !descriptor.typeInfoHasVtableAttached) {
|
val vtable = if (!descriptor.isInterface && !irClass.typeInfoHasVtableAttached) {
|
||||||
staticData.placeGlobal("", rttiGenerator.vtable(descriptor)).also {
|
staticData.placeGlobal("", rttiGenerator.vtable(irClass)).also {
|
||||||
it.setConstant(true)
|
it.setConstant(true)
|
||||||
}.pointer.getElementPtr(0)
|
}.pointer.getElementPtr(0)
|
||||||
} else {
|
} else {
|
||||||
@@ -812,7 +819,7 @@ private fun ObjCExportCodeGenerator.createTypeAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val methodTable = if (!descriptor.isInterface && descriptor.isAbstract()) {
|
val methodTable = if (!descriptor.isInterface && descriptor.isAbstract()) {
|
||||||
rttiGenerator.methodTableRecords(descriptor)
|
rttiGenerator.methodTableRecords(irClass)
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
@@ -859,13 +866,16 @@ private fun ObjCExportCodeGenerator.createDirectAdapters(
|
|||||||
val implementation = if (this.modality == Modality.ABSTRACT) {
|
val implementation = if (this.modality == Modality.ABSTRACT) {
|
||||||
null
|
null
|
||||||
} else {
|
} 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
|
val superClassMethod = method.overriddenDescriptors
|
||||||
.atMostOne { !(it.containingDeclaration as ClassDescriptor).isInterface }
|
.atMostOne { !(it.containingDeclaration as ClassDescriptor).isInterface }?.original
|
||||||
|
|
||||||
val inheritedAdapters = superClassMethod?.getAllRequiredDirectAdapters().orEmpty()
|
val inheritedAdapters = superClassMethod?.getAllRequiredDirectAdapters().orEmpty()
|
||||||
val requiredAdapters = method.getAllRequiredDirectAdapters()
|
val requiredAdapters = method.getAllRequiredDirectAdapters()
|
||||||
@@ -914,7 +924,7 @@ private fun ObjCExportCodeGenerator.createObjectInstanceAdapter(
|
|||||||
return generateObjCToKotlinMethodAdapter(methodBridge, selector) {
|
return generateObjCToKotlinMethodAdapter(methodBridge, selector) {
|
||||||
initRuntimeIfNeeded() // For instance methods it gets called when allocating.
|
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))
|
ret(kotlinToObjC(value, ReferenceBridge))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -930,7 +940,7 @@ private fun ObjCExportCodeGenerator.createEnumEntryAdapter(
|
|||||||
return generateObjCToKotlinMethodAdapter(methodBridge, selector) {
|
return generateObjCToKotlinMethodAdapter(methodBridge, selector) {
|
||||||
initRuntimeIfNeeded() // For instance methods it gets called when allocating.
|
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))
|
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.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
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.createParameterDeclarations
|
||||||
|
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
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.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||||
@@ -48,7 +49,7 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
|
|||||||
val interop = context.interopBuiltIns
|
val interop = context.interopBuiltIns
|
||||||
val symbols = context.ir.symbols
|
val symbols = context.ir.symbols
|
||||||
val nullableAnyType = context.builtIns.nullableAnyType
|
val nullableAnyType = context.builtIns.nullableAnyType
|
||||||
var runtimeJobDescriptor: FunctionDescriptor? = null
|
lateinit var runtimeJobFunction: IrSimpleFunction
|
||||||
|
|
||||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||||
irDeclarationContainer.declarations.transformFlat {
|
irDeclarationContainer.declarations.transformFlat {
|
||||||
@@ -68,10 +69,11 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
|
|||||||
return expression
|
return expression
|
||||||
|
|
||||||
val job = expression.getValueArgument(3) as IrFunctionReference
|
val job = expression.getValueArgument(3) as IrFunctionReference
|
||||||
|
val jobFunction = (job.symbol as IrSimpleFunctionSymbol).owner
|
||||||
val jobDescriptor = job.descriptor
|
val jobDescriptor = job.descriptor
|
||||||
val arg = jobDescriptor.valueParameters[0]
|
val arg = jobDescriptor.valueParameters[0]
|
||||||
if (runtimeJobDescriptor == null) {
|
if (!::runtimeJobFunction.isInitialized) {
|
||||||
runtimeJobDescriptor = jobDescriptor.newCopyBuilder()
|
val runtimeJobDescriptor = jobDescriptor.newCopyBuilder()
|
||||||
.setReturnType(nullableAnyType)
|
.setReturnType(nullableAnyType)
|
||||||
.setValueParameters(listOf(ValueParameterDescriptorImpl(
|
.setValueParameters(listOf(ValueParameterDescriptorImpl(
|
||||||
containingDeclaration = jobDescriptor,
|
containingDeclaration = jobDescriptor,
|
||||||
@@ -87,8 +89,17 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
|
|||||||
source = arg.source
|
source = arg.source
|
||||||
)))
|
)))
|
||||||
.build()!!
|
.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
|
if (!overriddenJobDescriptor.needBridge) return expression
|
||||||
|
|
||||||
val bridge = context.buildBridge(
|
val bridge = context.buildBridge(
|
||||||
@@ -115,22 +126,9 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
|
|||||||
internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||||
|
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
val functions = mutableSetOf<FunctionDescriptor?>()
|
val builtBridges = mutableSetOf<IrSimpleFunction>()
|
||||||
irClass.declarations.forEach {
|
|
||||||
when (it) {
|
|
||||||
is IrFunction -> functions.add(it.descriptor)
|
|
||||||
is IrProperty -> {
|
|
||||||
functions.add(it.getter?.descriptor)
|
|
||||||
functions.add(it.setter?.descriptor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
irClass.descriptor.contributedMethods.forEach { functions.add(it) }
|
irClass.simpleFunctions()
|
||||||
|
|
||||||
val builtBridges = mutableSetOf<FunctionDescriptor>()
|
|
||||||
functions.filterNotNull()
|
|
||||||
.filterNot { it.modality == Modality.ABSTRACT }
|
|
||||||
.forEach { function ->
|
.forEach { function ->
|
||||||
function.allOverriddenDescriptors
|
function.allOverriddenDescriptors
|
||||||
.map { OverriddenFunctionDescriptor(function, it) }
|
.map { OverriddenFunctionDescriptor(function, it) }
|
||||||
@@ -151,7 +149,7 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
|||||||
?: return declaration
|
?: return declaration
|
||||||
val descriptor = declaration.descriptor
|
val descriptor = declaration.descriptor
|
||||||
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor)
|
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor)
|
||||||
if (typeSafeBarrierDescription == null || builtBridges.contains(descriptor))
|
if (typeSafeBarrierDescription == null || builtBridges.contains(declaration))
|
||||||
return declaration
|
return declaration
|
||||||
|
|
||||||
val irBuilder = context.createIrBuilder(declaration.symbol, declaration.startOffset, declaration.endOffset)
|
val irBuilder = context.createIrBuilder(declaration.symbol, declaration.startOffset, declaration.endOffset)
|
||||||
@@ -169,22 +167,13 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
|||||||
startOffset = irClass.startOffset,
|
startOffset = irClass.startOffset,
|
||||||
endOffset = irClass.endOffset,
|
endOffset = irClass.endOffset,
|
||||||
descriptor = descriptor,
|
descriptor = descriptor,
|
||||||
targetSymbol = irClass.findMember(descriptor.descriptor), // TODO: optimize.
|
targetSymbol = descriptor.descriptor.symbol,
|
||||||
superQualifierSymbol = irClass.symbol)
|
superQualifierSymbol = irClass.symbol)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrClass.findMember(descriptor: FunctionDescriptor): IrFunctionSymbol {
|
internal object DECLARATION_ORIGIN_BRIDGE_METHOD :
|
||||||
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 :
|
|
||||||
IrDeclarationOriginImpl("BRIDGE_METHOD")
|
IrDeclarationOriginImpl("BRIDGE_METHOD")
|
||||||
|
|
||||||
private fun IrBuilderWithScope.returnIfBadType(value: IrExpression,
|
private fun IrBuilderWithScope.returnIfBadType(value: IrExpression,
|
||||||
@@ -220,17 +209,20 @@ private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction,
|
|||||||
|
|
||||||
private fun Context.buildBridge(startOffset: Int, endOffset: Int,
|
private fun Context.buildBridge(startOffset: Int, endOffset: Int,
|
||||||
descriptor: OverriddenFunctionDescriptor, targetSymbol: IrFunctionSymbol,
|
descriptor: OverriddenFunctionDescriptor, targetSymbol: IrFunctionSymbol,
|
||||||
superQualifierSymbol: IrClassSymbol? = null): IrFunctionImpl {
|
superQualifierSymbol: IrClassSymbol? = null): IrFunction {
|
||||||
val bridgeDescriptor = specialDeclarationsFactory.getBridgeDescriptor(descriptor)
|
|
||||||
val bridge = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_BRIDGE_METHOD,
|
val bridge = specialDeclarationsFactory.getBridgeDescriptor(descriptor)
|
||||||
bridgeDescriptor).apply { createParameterDeclarations() }
|
|
||||||
|
if (bridge.modality == Modality.ABSTRACT) {
|
||||||
|
return bridge
|
||||||
|
}
|
||||||
|
|
||||||
val irBuilder = createIrBuilder(bridge.symbol, startOffset, endOffset)
|
val irBuilder = createIrBuilder(bridge.symbol, startOffset, endOffset)
|
||||||
bridge.body = irBuilder.irBlockBody(bridge) {
|
bridge.body = irBuilder.irBlockBody(bridge) {
|
||||||
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor)
|
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor.descriptor)
|
||||||
typeSafeBarrierDescription?.let { buildTypeSafeBarrier(bridge, descriptor.descriptor, it) }
|
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 */
|
superQualifierSymbol = superQualifierSymbol /* Call non-virtually */
|
||||||
).apply {
|
).apply {
|
||||||
bridge.dispatchReceiverParameter?.let {
|
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
|
+delegatingCall
|
||||||
else
|
else
|
||||||
+irReturn(delegatingCall)
|
+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.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
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.pop
|
||||||
import org.jetbrains.kotlin.backend.common.push
|
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.backend.konan.llvm.functionName
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
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.IrConstructorSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
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.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
|
||||||
@@ -69,7 +67,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
private var functionReferenceCount = 0
|
private var functionReferenceCount = 0
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
irFile.transformChildrenVoid(object: IrElementTransformerVoidWithContext() {
|
irFile.transform(object: IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
private val stack = mutableListOf<IrElement>()
|
private val stack = mutableListOf<IrElement>()
|
||||||
|
|
||||||
@@ -126,7 +124,12 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
return expression
|
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)
|
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset)
|
||||||
return irBuilder.irBlock(expression) {
|
return irBuilder.irBlock(expression) {
|
||||||
+loweredFunctionReference.functionReferenceClass
|
+loweredFunctionReference.functionReferenceClass
|
||||||
@@ -137,7 +140,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BuiltFunctionReference(val functionReferenceClass: IrClass,
|
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 val getContinuationSymbol = context.ir.symbols.getContinuation
|
||||||
|
|
||||||
private inner class FunctionReferenceBuilder(val containingDeclaration: DeclarationDescriptor,
|
private inner class FunctionReferenceBuilder(val containingDeclaration: DeclarationDescriptor,
|
||||||
|
val parent: IrDeclarationParent,
|
||||||
val functionReference: IrFunctionReference) {
|
val functionReference: IrFunctionReference) {
|
||||||
|
|
||||||
private val functionDescriptor = functionReference.descriptor
|
private val functionDescriptor = functionReference.descriptor
|
||||||
@@ -176,12 +180,14 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
val superTypes = mutableListOf(
|
val superTypes = mutableListOf(
|
||||||
kFunctionImplSymbol.owner.defaultType.replace(listOf(returnType))
|
kFunctionImplSymbol.owner.defaultType.replace(listOf(returnType))
|
||||||
)
|
)
|
||||||
|
val superClasses = mutableListOf(kFunctionImplSymbol.owner)
|
||||||
|
|
||||||
val numberOfParameters = unboundFunctionParameters.size
|
val numberOfParameters = unboundFunctionParameters.size
|
||||||
val functionClassDescriptor = context.reflectionTypes.getKFunction(numberOfParameters)
|
val functionClassDescriptor = context.reflectionTypes.getKFunction(numberOfParameters)
|
||||||
val functionParameterTypes = unboundFunctionParameters.map { it.type }
|
val functionParameterTypes = unboundFunctionParameters.map { it.type }
|
||||||
val functionClassTypeParameters = functionParameterTypes + returnType
|
val functionClassTypeParameters = functionParameterTypes + returnType
|
||||||
superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeParameters)
|
superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeParameters)
|
||||||
|
superClasses += context.ir.symbols.kFunctions[numberOfParameters].owner
|
||||||
|
|
||||||
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
||||||
var suspendFunctionClassTypeParameters: List<KotlinType>? = 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
|
Name.identifier("SuspendFunction${numberOfParameters - 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
||||||
suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) + lastParameterType.arguments.single().type
|
suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) + lastParameterType.arguments.single().type
|
||||||
superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeParameters)
|
superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeParameters)
|
||||||
|
superClasses += context.ir.symbols.suspendFunctions[numberOfParameters - 1].owner
|
||||||
}
|
}
|
||||||
|
|
||||||
functionReferenceClassDescriptor = ClassDescriptorImpl(
|
functionReferenceClassDescriptor = object : ClassDescriptorImpl(
|
||||||
/* containingDeclaration = */ containingDeclaration,
|
/* containingDeclaration = */ containingDeclaration,
|
||||||
/* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName,
|
/* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName,
|
||||||
/* modality = */ Modality.FINAL,
|
/* modality = */ Modality.FINAL,
|
||||||
@@ -202,13 +209,16 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
/* superTypes = */ superTypes,
|
/* superTypes = */ superTypes,
|
||||||
/* source = */ SourceElement.NO_SOURCE,
|
/* source = */ SourceElement.NO_SOURCE,
|
||||||
/* isExternal = */ false
|
/* isExternal = */ false
|
||||||
)
|
) {
|
||||||
|
override fun getVisibility() = Visibilities.PRIVATE
|
||||||
|
}
|
||||||
functionReferenceClass = IrClassImpl(
|
functionReferenceClass = IrClassImpl(
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
descriptor = functionReferenceClassDescriptor
|
descriptor = functionReferenceClassDescriptor
|
||||||
)
|
)
|
||||||
|
functionReferenceClass.parent = this.parent
|
||||||
|
|
||||||
|
|
||||||
val constructorBuilder = createConstructorBuilder()
|
val constructorBuilder = createConstructorBuilder()
|
||||||
@@ -222,33 +232,27 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionDescriptor)
|
suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
val inheritedKFunctionImpl = kFunctionImplSymbol.descriptor.unsubstitutedMemberScope
|
val memberScope = stub<MemberScope>("callable reference class")
|
||||||
.getContributedDescriptors()
|
|
||||||
.map { it.createFakeOverrideDescriptor(functionReferenceClassDescriptor) }
|
|
||||||
.filterNotNull()
|
|
||||||
val contributedDescriptors = (
|
|
||||||
inheritedKFunctionImpl + invokeMethodBuilder.symbol.descriptor + suspendInvokeMethodBuilder?.symbol?.descriptor
|
|
||||||
).filterNotNull().toList()
|
|
||||||
functionReferenceClassDescriptor.initialize(
|
functionReferenceClassDescriptor.initialize(
|
||||||
SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.symbol.descriptor), null)
|
memberScope, setOf(constructorBuilder.symbol.descriptor), null)
|
||||||
|
|
||||||
functionReferenceClass.createParameterDeclarations()
|
functionReferenceClass.createParameterDeclarations()
|
||||||
|
|
||||||
functionReferenceThis = functionReferenceClass.thisReceiver!!.symbol
|
functionReferenceThis = functionReferenceClass.thisReceiver!!.symbol
|
||||||
|
|
||||||
functionReferenceClass.addFakeOverrides()
|
|
||||||
|
|
||||||
constructorBuilder.initialize()
|
constructorBuilder.initialize()
|
||||||
functionReferenceClass.declarations.add(constructorBuilder.ir)
|
functionReferenceClass.addChild(constructorBuilder.ir)
|
||||||
|
|
||||||
invokeMethodBuilder.initialize()
|
invokeMethodBuilder.initialize()
|
||||||
functionReferenceClass.declarations.add(invokeMethodBuilder.ir)
|
functionReferenceClass.addChild(invokeMethodBuilder.ir)
|
||||||
|
|
||||||
suspendInvokeMethodBuilder?.let {
|
suspendInvokeMethodBuilder?.let {
|
||||||
it.initialize()
|
it.initialize()
|
||||||
functionReferenceClass.declarations.add(it.ir)
|
functionReferenceClass.addChild(it.ir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functionReferenceClass.setSuperSymbolsAndAddFakeOverrides(superClasses)
|
||||||
|
|
||||||
return BuiltFunctionReference(functionReferenceClass, constructorBuilder.ir)
|
return BuiltFunctionReference(functionReferenceClass, constructorBuilder.ir)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +303,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
IrConstKind.String, functionDescriptor.name.asString())
|
IrConstKind.String, functionDescriptor.name.asString())
|
||||||
putValueArgument(0, name)
|
putValueArgument(0, name)
|
||||||
val fqName = IrConstImpl(startOffset, endOffset, context.builtIns.stringType, IrConstKind.String,
|
val fqName = IrConstImpl(startOffset, endOffset, context.builtIns.stringType, IrConstKind.String,
|
||||||
functionDescriptor.fullName)
|
(functionReference.symbol.owner as IrFunction).fullName)
|
||||||
putValueArgument(1, fqName)
|
putValueArgument(1, fqName)
|
||||||
val bound = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType,
|
val bound = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType,
|
||||||
boundFunctionParameters.isNotEmpty())
|
boundFunctionParameters.isNotEmpty())
|
||||||
@@ -318,17 +322,8 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: what about private package level functions?
|
private val IrFunction.fullName: String
|
||||||
private val DeclarationDescriptor.fullName: String
|
get() = parent.fqNameSafe.child(Name.identifier(functionName)).asString()
|
||||||
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 fun createInvokeMethodBuilder(superFunctionDescriptor: FunctionDescriptor)
|
private fun createInvokeMethodBuilder(superFunctionDescriptor: FunctionDescriptor)
|
||||||
= object : SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
= object : SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||||
@@ -385,7 +380,10 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
val argument =
|
val argument =
|
||||||
if (!unboundArgsSet.contains(it))
|
if (!unboundArgsSet.contains(it))
|
||||||
// Bound parameter - read from field.
|
// Bound parameter - read from field.
|
||||||
irGetField(irGet(functionReferenceThis), argumentToPropertiesMap[it]!!)
|
irGetField(
|
||||||
|
irGet(function.dispatchReceiverParameter!!.symbol),
|
||||||
|
argumentToPropertiesMap[it]!!
|
||||||
|
)
|
||||||
else {
|
else {
|
||||||
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
|
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
|
||||||
// For suspend functions the last argument is continuation and it is implicit.
|
// For suspend functions the last argument is continuation and it is implicit.
|
||||||
@@ -420,7 +418,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
initialize()
|
initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
functionReferenceClass.declarations.add(propertyBuilder.ir)
|
functionReferenceClass.addChild(propertyBuilder.ir)
|
||||||
return propertyBuilder.ir.backingField!!.symbol
|
return propertyBuilder.ir.backingField!!.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-4
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.lower
|
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.IrElementTransformerVoidWithContext
|
||||||
import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext
|
import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext
|
||||||
import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope
|
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.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.*
|
import org.jetbrains.kotlin.descriptors.impl.*
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
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.Variance
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
|
|
||||||
class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor,
|
internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor,
|
||||||
val parentDescriptor: DeclarationDescriptor,
|
val parentDescriptor: DeclarationDescriptor,
|
||||||
val context: CommonBackendContext) {
|
val context: Context) {
|
||||||
|
|
||||||
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
|
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
|
||||||
private var typeSubstitutor: TypeSubstitutor? = null
|
private var typeSubstitutor: TypeSubstitutor? = null
|
||||||
@@ -503,7 +503,9 @@ class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor,
|
|||||||
origin = mapDeclarationOrigin(declaration.origin),
|
origin = mapDeclarationOrigin(declaration.origin),
|
||||||
descriptor = mapFunctionDeclaration(declaration.descriptor),
|
descriptor = mapFunctionDeclaration(declaration.descriptor),
|
||||||
body = declaration.body?.transform(this, null)
|
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) {
|
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||||
irDeclarationContainer.declarations.transformFlat { memberDeclaration ->
|
irDeclarationContainer.declarations.transformFlat { memberDeclaration ->
|
||||||
if (memberDeclaration is IrFunction)
|
if (memberDeclaration is IrFunction)
|
||||||
lower(memberDeclaration)
|
lower(memberDeclaration).also { functions ->
|
||||||
|
functions.forEach {
|
||||||
|
it.parent = irDeclarationContainer
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@@ -78,12 +82,18 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
|
|||||||
functionDescriptor.overriddenDescriptors.forEach { context.log{"DEFAULT-REPLACER: $it"} }
|
functionDescriptor.overriddenDescriptors.forEach { context.log{"DEFAULT-REPLACER: $it"} }
|
||||||
if (bodies.isNotEmpty()) {
|
if (bodies.isNotEmpty()) {
|
||||||
val newIrFunction = functionDescriptor.generateDefaultsFunction(context)
|
val newIrFunction = functionDescriptor.generateDefaultsFunction(context)
|
||||||
|
newIrFunction.parent = irFunction.parent
|
||||||
val descriptor = newIrFunction.descriptor
|
val descriptor = newIrFunction.descriptor
|
||||||
log { "$functionDescriptor -> $descriptor" }
|
log { "$functionDescriptor -> $descriptor" }
|
||||||
val builder = context.createIrBuilder(newIrFunction.symbol)
|
val builder = context.createIrBuilder(newIrFunction.symbol)
|
||||||
val body = builder.irBlockBody(irFunction) {
|
newIrFunction.body = builder.irBlockBody(newIrFunction) {
|
||||||
val params = mutableListOf<IrVariableSymbol>()
|
val params = mutableListOf<IrVariableSymbol>()
|
||||||
val variables = mutableMapOf<ValueDescriptor, IrValueSymbol>()
|
val variables = mutableMapOf<ValueDescriptor, IrValueSymbol>()
|
||||||
|
|
||||||
|
irFunction.dispatchReceiverParameter?.let {
|
||||||
|
variables[it.descriptor] = newIrFunction.dispatchReceiverParameter!!.symbol
|
||||||
|
}
|
||||||
|
|
||||||
if (descriptor.extensionReceiverParameter != null) {
|
if (descriptor.extensionReceiverParameter != null) {
|
||||||
variables[functionDescriptor.extensionReceiverParameter!!] =
|
variables[functionDescriptor.extensionReceiverParameter!!] =
|
||||||
newIrFunction.extensionReceiverParameter!!.symbol
|
newIrFunction.extensionReceiverParameter!!.symbol
|
||||||
@@ -157,20 +167,8 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
|
|||||||
irFunction.valueParameters.forEach {
|
irFunction.valueParameters.forEach {
|
||||||
it.defaultValue = null
|
it.defaultValue = null
|
||||||
}
|
}
|
||||||
return if (functionDescriptor is ClassConstructorDescriptor)
|
|
||||||
listOf(irFunction, IrConstructorImpl(
|
return listOf(irFunction, newIrFunction)
|
||||||
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)
|
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?>>> {
|
private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? {
|
||||||
val descriptor = expression.descriptor as FunctionDescriptor
|
if (!this.descriptor.needsDefaultArgumentsLowering) return null
|
||||||
val keyDescriptor = if (DescriptorUtils.isOverride(descriptor))
|
|
||||||
DescriptorUtils.getAllOverriddenDescriptors(descriptor).first { it.needsDefaultArgumentsLowering }
|
if (this !is IrSimpleFunction) return this
|
||||||
else
|
|
||||||
descriptor.original
|
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)
|
val realFunction = keyDescriptor.generateDefaultsFunction(context)
|
||||||
|
realFunction.parent = keyFunction.parent
|
||||||
val realDescriptor = realFunction.descriptor
|
val realDescriptor = realFunction.descriptor
|
||||||
|
|
||||||
log { "$descriptor -> $realDescriptor" }
|
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.IrPropertyReference
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
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.constructors
|
||||||
import org.jetbrains.kotlin.ir.util.functions
|
import org.jetbrains.kotlin.ir.util.functions
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
@@ -120,16 +121,14 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
|||||||
declaration.transformChildrenVoid(this)
|
declaration.transformChildrenVoid(this)
|
||||||
|
|
||||||
val initializer = declaration.delegate.initializer!!
|
val initializer = declaration.delegate.initializer!!
|
||||||
return IrVariableImpl(declaration.startOffset, declaration.endOffset,
|
declaration.delegate.initializer = IrBlockImpl(initializer.startOffset, initializer.endOffset, initializer.type, null,
|
||||||
declaration.origin, declaration.delegate.descriptor,
|
listOf(
|
||||||
IrBlockImpl(initializer.startOffset, initializer.endOffset, initializer.type, null,
|
declaration.getter,
|
||||||
listOf(
|
declaration.setter,
|
||||||
declaration.getter,
|
initializer
|
||||||
declaration.setter,
|
).filterNotNull())
|
||||||
initializer
|
|
||||||
).filterNotNull())
|
|
||||||
)
|
|
||||||
|
|
||||||
|
return declaration.delegate
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
|
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
|
||||||
@@ -191,7 +190,7 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
|||||||
if (kProperties.isNotEmpty()) {
|
if (kProperties.isNotEmpty()) {
|
||||||
val initializers = kProperties.values.sortedBy { it.second }.map { it.first }
|
val initializers = kProperties.values.sortedBy { it.second }.map { it.first }
|
||||||
// TODO: move to object for lazy initialization.
|
// TODO: move to object for lazy initialization.
|
||||||
irFile.declarations.add(0, kPropertiesField.apply {
|
irFile.addChild(kPropertiesField.apply {
|
||||||
initializer = IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
initializer = IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
context.createArrayOfExpression(kPropertyImplType, initializers, 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.ClassLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
|
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.common.runOnFilePostfix
|
||||||
import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter
|
import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM
|
import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
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.addSimpleDelegatingConstructor
|
||||||
import org.jetbrains.kotlin.backend.common.ir.createArrayOfExpression
|
import org.jetbrains.kotlin.backend.common.ir.createArrayOfExpression
|
||||||
import org.jetbrains.kotlin.backend.common.ir.createSimpleDelegatingConstructorDescriptor
|
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.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
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.TypeProjectionImpl
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
|
||||||
@@ -187,7 +186,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
val defaultClass = createDefaultClassForEnumEntries()
|
val defaultClass = createDefaultClassForEnumEntries()
|
||||||
lowerEnumClassBody()
|
lowerEnumClassBody()
|
||||||
if (defaultClass != null)
|
if (defaultClass != null)
|
||||||
irClass.declarations.add(defaultClass)
|
irClass.addChild(defaultClass)
|
||||||
createImplObject()
|
createImplObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,15 +274,11 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val contributedDescriptors = irClass.descriptor.unsubstitutedMemberScope
|
val memberScope = stub<MemberScope>("enum default class")
|
||||||
.getContributedDescriptors()
|
defaultClassDescriptor.initialize(memberScope, constructors, null)
|
||||||
.map { it.createFakeOverrideDescriptor(defaultClassDescriptor) }
|
|
||||||
.filterNotNull()
|
|
||||||
.toList()
|
|
||||||
defaultClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null)
|
|
||||||
|
|
||||||
defaultClass.createParameterDeclarations()
|
defaultClass.createParameterDeclarations()
|
||||||
defaultClass.addFakeOverrides()
|
defaultClass.setSuperSymbolsAndAddFakeOverrides(listOf(irClass))
|
||||||
|
|
||||||
return defaultClass
|
return defaultClass
|
||||||
}
|
}
|
||||||
@@ -325,10 +320,10 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
constructorOfAny, implObject.descriptor.constructors.single(),
|
constructorOfAny, implObject.descriptor.constructors.single(),
|
||||||
DECLARATION_ORIGIN_ENUM)
|
DECLARATION_ORIGIN_ENUM)
|
||||||
|
|
||||||
implObject.declarations.add(createSyntheticValuesPropertyDeclaration(enumEntries))
|
implObject.addChild(createSyntheticValuesPropertyDeclaration(enumEntries))
|
||||||
implObject.declarations.add(createValuesPropertyInitializer(enumEntries))
|
implObject.addChild(createValuesPropertyInitializer(enumEntries))
|
||||||
|
|
||||||
irClass.declarations.add(implObject)
|
irClass.addChild(implObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val genericCreateUninitializedInstanceSymbol = context.ir.symbols.createUninitializedInstance
|
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))
|
getter.body = IrBlockBodyImpl(startOffset, endOffset, listOf(returnStatement))
|
||||||
|
|
||||||
return IrPropertyImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM,
|
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
|
private val initInstanceSymbol = context.ir.symbols.initInstance
|
||||||
@@ -432,6 +429,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
loweredConstructorDescriptor,
|
loweredConstructorDescriptor,
|
||||||
enumConstructor.body!! // will be transformed later
|
enumConstructor.body!! // will be transformed later
|
||||||
)
|
)
|
||||||
|
loweredEnumConstructor.parent = enumConstructor.parent
|
||||||
|
|
||||||
loweredEnumConstructors[constructorDescriptor] = loweredEnumConstructor
|
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.declarations.getDefault
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
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.symbols.impl.createValueSymbol
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
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.
|
typeSubstitutor = createTypeSubstitutor(callee) // Type parameters will be substituted with type arguments.
|
||||||
) as IrFunction
|
) as IrFunction
|
||||||
|
|
||||||
|
val irReturnableBlockSymbol = IrReturnableBlockSymbolImpl(copyFunctionDeclaration.descriptor.original)
|
||||||
|
|
||||||
val evaluationStatements = evaluateArguments(callee, copyFunctionDeclaration) // And list of evaluation statements.
|
val evaluationStatements = evaluateArguments(callee, copyFunctionDeclaration) // And list of evaluation statements.
|
||||||
|
|
||||||
val statements = (copyFunctionDeclaration.body as IrBlockBody).statements // IR statements from function copy.
|
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
|
val descriptor = caller.descriptor.original
|
||||||
if (descriptor.isInlineConstructor) {
|
if (descriptor.isInlineConstructor) {
|
||||||
val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall
|
val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall
|
||||||
val irBuilder = context.createIrBuilder(copyFunctionDeclaration.symbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
|
||||||
irBuilder.run {
|
irBuilder.run {
|
||||||
val constructorDescriptor = delegatingConstructorCall.descriptor.original
|
val constructorDescriptor = delegatingConstructorCall.descriptor.original
|
||||||
val constructorCall = irCall(delegatingConstructorCall.symbol,
|
val constructorCall = irCall(delegatingConstructorCall.symbol,
|
||||||
@@ -166,7 +169,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
type = returnType,
|
type = returnType,
|
||||||
descriptor = copyFunctionDeclaration.descriptor.original,
|
symbol = irReturnableBlockSymbol,
|
||||||
origin = null,
|
origin = null,
|
||||||
statements = statements,
|
statements = statements,
|
||||||
sourceFileName = sourceFileName
|
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.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
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.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
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.createParameterDeclarations
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
@@ -118,7 +116,23 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
|||||||
|
|
||||||
initializer.createParameterDeclarations()
|
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
|
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.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
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.IrBlockBody
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
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.expressions.impl.IrSetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
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.util.transformFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
@@ -57,7 +59,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
private fun createOuterThisField() {
|
private fun createOuterThisField() {
|
||||||
val field = context.specialDeclarationsFactory.getOuterThisField(classDescriptor)
|
val field = context.specialDeclarationsFactory.getOuterThisField(classDescriptor)
|
||||||
outerThisFieldSymbol = field.symbol
|
outerThisFieldSymbol = field.symbol
|
||||||
irClass.declarations.add(field)
|
irClass.addChild(field)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lowerConstructors() {
|
private fun lowerConstructors() {
|
||||||
@@ -109,7 +111,16 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
var innerClass: ClassDescriptor
|
var innerClass: ClassDescriptor
|
||||||
if (constructorSymbol == null || constructorSymbol.descriptor.constructedClass != classDescriptor) {
|
if (constructorSymbol == null || constructorSymbol.descriptor.constructedClass != classDescriptor) {
|
||||||
innerClass = 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 {
|
} else {
|
||||||
// For constructor we have outer class as dispatchReceiverParameter.
|
// For constructor we have outer class as dispatchReceiverParameter.
|
||||||
innerClass = DescriptorUtils.getContainingClass(classDescriptor) ?:
|
innerClass = DescriptorUtils.getContainingClass(classDescriptor) ?:
|
||||||
|
|||||||
+1
-1
@@ -123,7 +123,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}.let { irClass.declarations.addAll(it) }
|
}.let { irClass.addChildren(it) }
|
||||||
|
|
||||||
if (irClass.descriptor.annotations.hasAnnotation(interop.exportObjCClass.fqNameSafe)) {
|
if (irClass.descriptor.annotations.hasAnnotation(interop.exportObjCClass.fqNameSafe)) {
|
||||||
val irBuilder = context.createIrBuilder(currentFile.symbol).at(irClass)
|
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.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
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.createParameterDeclarations
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
@@ -144,6 +145,17 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
|||||||
"LocalClassContext for ${descriptor}"
|
"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) {
|
private inner class LocalDeclarationsTransformer(val memberDeclaration: IrDeclaration) {
|
||||||
val localFunctions: MutableMap<FunctionDescriptor, LocalFunctionContext> = LinkedHashMap()
|
val localFunctions: MutableMap<FunctionDescriptor, LocalFunctionContext> = LinkedHashMap()
|
||||||
val localClasses: MutableMap<ClassDescriptor, LocalClassContext> = LinkedHashMap()
|
val localClasses: MutableMap<ClassDescriptor, LocalClassContext> = LinkedHashMap()
|
||||||
@@ -169,6 +181,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
|||||||
rewriteDeclarations()
|
rewriteDeclarations()
|
||||||
|
|
||||||
val result = collectRewrittenDeclarations()
|
val result = collectRewrittenDeclarations()
|
||||||
|
result.forEach { it.parent = memberDeclaration.parent }
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +222,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
|||||||
// Replace local function definition with an empty composite.
|
// Replace local function definition with an empty composite.
|
||||||
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType)
|
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType)
|
||||||
} else {
|
} 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]
|
val constructorContext = localClassConstructors[declaration.descriptor]
|
||||||
if (constructorContext != null) {
|
if (constructorContext != null) {
|
||||||
return constructorContext.transformedDeclaration.apply {
|
return constructorContext.transformedDeclaration.apply {
|
||||||
|
this.parent = declaration.parent
|
||||||
this.body = declaration.body!!
|
this.body = declaration.body!!
|
||||||
|
|
||||||
declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
|
declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
|
||||||
@@ -361,7 +382,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
|||||||
localClassContext.capturedValueToField.forEach { capturedValue, field ->
|
localClassContext.capturedValueToField.forEach { capturedValue, field ->
|
||||||
val startOffset = irClass.startOffset
|
val startOffset = irClass.startOffset
|
||||||
val endOffset = irClass.endOffset
|
val endOffset = irClass.endOffset
|
||||||
irClass.declarations.add(field)
|
irClass.addChild(field)
|
||||||
|
|
||||||
for (constructorContext in constructorsCallingSuper) {
|
for (constructorContext in constructorsCallingSuper) {
|
||||||
val blockBody = constructorContext.declaration.body as? IrBlockBody
|
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.explicitParameters
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.getFunction
|
import org.jetbrains.kotlin.backend.common.descriptors.getFunction
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.replace
|
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.ir.createOverriddenDescriptor
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
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.ir.visitors.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
@@ -301,6 +301,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
|
|
||||||
fun build(): BuiltCoroutine {
|
fun build(): BuiltCoroutine {
|
||||||
val superTypes = mutableListOf<KotlinType>(coroutineImplClassDescriptor.defaultType)
|
val superTypes = mutableListOf<KotlinType>(coroutineImplClassDescriptor.defaultType)
|
||||||
|
val superClasses = mutableListOf<IrClass>(coroutineImplSymbol.owner)
|
||||||
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
||||||
var functionClassDescriptor: ClassDescriptor? = null
|
var functionClassDescriptor: ClassDescriptor? = null
|
||||||
var suspendFunctionClassTypeArguments: List<KotlinType>? = null
|
var suspendFunctionClassTypeArguments: List<KotlinType>? = null
|
||||||
@@ -313,12 +314,14 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
val unboundParameterTypes = unboundFunctionParameters.map { it.type }
|
val unboundParameterTypes = unboundFunctionParameters.map { it.type }
|
||||||
suspendFunctionClassTypeArguments = unboundParameterTypes + irFunction.descriptor.returnType!!
|
suspendFunctionClassTypeArguments = unboundParameterTypes + irFunction.descriptor.returnType!!
|
||||||
superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeArguments)
|
superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeArguments)
|
||||||
|
superClasses += context.ir.symbols.suspendFunctions[numberOfParameters].owner
|
||||||
|
|
||||||
functionClassDescriptor = kotlinPackageScope.getContributedClassifier(
|
functionClassDescriptor = kotlinPackageScope.getContributedClassifier(
|
||||||
Name.identifier("Function${numberOfParameters + 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
Name.identifier("Function${numberOfParameters + 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
||||||
val continuationType = continuationClassDescriptor.defaultType.replace(listOf(irFunction.descriptor.returnType!!))
|
val continuationType = continuationClassDescriptor.defaultType.replace(listOf(irFunction.descriptor.returnType!!))
|
||||||
functionClassTypeArguments = unboundParameterTypes + continuationType + context.builtIns.nullableAnyType
|
functionClassTypeArguments = unboundParameterTypes + continuationType + context.builtIns.nullableAnyType
|
||||||
superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeArguments)
|
superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeArguments)
|
||||||
|
superClasses += context.ir.symbols.functions[numberOfParameters + 1].owner
|
||||||
|
|
||||||
}
|
}
|
||||||
coroutineClassDescriptor = ClassDescriptorImpl(
|
coroutineClassDescriptor = ClassDescriptorImpl(
|
||||||
@@ -336,6 +339,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||||
descriptor = coroutineClassDescriptor
|
descriptor = coroutineClassDescriptor
|
||||||
)
|
)
|
||||||
|
coroutineClass.parent = irFunction.parent
|
||||||
|
|
||||||
|
|
||||||
val overriddenMap = mutableMapOf<CallableMemberDescriptor, CallableMemberDescriptor>()
|
val overriddenMap = mutableMapOf<CallableMemberDescriptor, CallableMemberDescriptor>()
|
||||||
@@ -375,40 +379,35 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
doResumeFunctionSymbol = doResumeMethodBuilder.symbol)
|
doResumeFunctionSymbol = doResumeMethodBuilder.symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
val inheritedFromCoroutineImpl = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
val memberScope = stub<MemberScope>("coroutine class")
|
||||||
.getContributedDescriptors()
|
coroutineClassDescriptor.initialize(memberScope, constructors, null)
|
||||||
.map { overriddenMap[it] ?: it.createFakeOverrideDescriptor(coroutineClassDescriptor) }
|
|
||||||
val contributedDescriptors = (
|
|
||||||
inheritedFromCoroutineImpl + invokeMethodBuilder?.symbol?.descriptor
|
|
||||||
).filterNotNull().toList()
|
|
||||||
coroutineClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null)
|
|
||||||
|
|
||||||
coroutineClass.createParameterDeclarations()
|
coroutineClass.createParameterDeclarations()
|
||||||
|
|
||||||
coroutineClassThis = coroutineClass.thisReceiver!!.symbol
|
coroutineClassThis = coroutineClass.thisReceiver!!.symbol
|
||||||
|
|
||||||
coroutineClass.addFakeOverrides()
|
|
||||||
|
|
||||||
coroutineConstructorBuilder.initialize()
|
coroutineConstructorBuilder.initialize()
|
||||||
coroutineClass.declarations.add(coroutineConstructorBuilder.ir)
|
coroutineClass.addChild(coroutineConstructorBuilder.ir)
|
||||||
|
|
||||||
coroutineFactoryConstructorBuilder?.let {
|
coroutineFactoryConstructorBuilder?.let {
|
||||||
it.initialize()
|
it.initialize()
|
||||||
coroutineClass.declarations.add(it.ir)
|
coroutineClass.addChild(it.ir)
|
||||||
}
|
}
|
||||||
|
|
||||||
createMethodBuilder?.let {
|
createMethodBuilder?.let {
|
||||||
it.initialize()
|
it.initialize()
|
||||||
coroutineClass.declarations.add(it.ir)
|
coroutineClass.addChild(it.ir)
|
||||||
}
|
}
|
||||||
|
|
||||||
invokeMethodBuilder?.let {
|
invokeMethodBuilder?.let {
|
||||||
it.initialize()
|
it.initialize()
|
||||||
coroutineClass.declarations.add(it.ir)
|
coroutineClass.addChild(it.ir)
|
||||||
}
|
}
|
||||||
|
|
||||||
doResumeMethodBuilder.initialize()
|
doResumeMethodBuilder.initialize()
|
||||||
coroutineClass.declarations.add(doResumeMethodBuilder.ir)
|
coroutineClass.addChild(doResumeMethodBuilder.ir)
|
||||||
|
|
||||||
|
coroutineClass.setSuperSymbolsAndAddFakeOverrides(superClasses)
|
||||||
|
|
||||||
return BuiltCoroutine(
|
return BuiltCoroutine(
|
||||||
coroutineClass = coroutineClass,
|
coroutineClass = coroutineClass,
|
||||||
@@ -569,6 +568,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
|
|
||||||
createParameterDeclarations()
|
createParameterDeclarations()
|
||||||
|
|
||||||
|
val thisReceiver = this.dispatchReceiverParameter!!.symbol
|
||||||
|
|
||||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||||
+irReturn(
|
+irReturn(
|
||||||
@@ -579,7 +580,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
if (unboundArgsSet.contains(it))
|
if (unboundArgsSet.contains(it))
|
||||||
irGet(valueParameters[unboundIndex++].symbol)
|
irGet(valueParameters[unboundIndex++].symbol)
|
||||||
else
|
else
|
||||||
irGetField(irGet(coroutineClassThis), argumentToPropertiesMap[it]!!)
|
irGetField(irGet(thisReceiver), argumentToPropertiesMap[it]!!)
|
||||||
}.forEachIndexed { index, argument ->
|
}.forEachIndexed { index, argument ->
|
||||||
putValueArgument(index, argument)
|
putValueArgument(index, argument)
|
||||||
}
|
}
|
||||||
@@ -640,12 +641,14 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
|
|
||||||
createParameterDeclarations()
|
createParameterDeclarations()
|
||||||
|
|
||||||
|
val thisReceiver = this.dispatchReceiverParameter!!.symbol
|
||||||
|
|
||||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||||
+irReturn(
|
+irReturn(
|
||||||
irCall(doResumeFunctionSymbol).apply {
|
irCall(doResumeFunctionSymbol).apply {
|
||||||
dispatchReceiver = irCall(createFunctionSymbol).apply {
|
dispatchReceiver = irCall(createFunctionSymbol).apply {
|
||||||
dispatchReceiver = irGet(coroutineClassThis)
|
dispatchReceiver = irGet(thisReceiver)
|
||||||
valueParameters.forEachIndexed { index, parameter ->
|
valueParameters.forEachIndexed { index, parameter ->
|
||||||
putValueArgument(index, irGet(parameter.symbol))
|
putValueArgument(index, irGet(parameter.symbol))
|
||||||
}
|
}
|
||||||
@@ -673,7 +676,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
initialize()
|
initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
coroutineClass.declarations.add(propertyBuilder.ir)
|
coroutineClass.addChild(propertyBuilder.ir)
|
||||||
return propertyBuilder.symbol
|
return propertyBuilder.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,7 +712,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
outType = context.builtIns.nullableAnyType,
|
outType = context.builtIns.nullableAnyType,
|
||||||
isMutable = true)
|
isMutable = true)
|
||||||
)
|
)
|
||||||
val label = coroutineClassDescriptor.unsubstitutedMemberScope
|
val label = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
||||||
.getContributedVariables(Name.identifier("label"), NoLookupLocation.FROM_BACKEND).single()
|
.getContributedVariables(Name.identifier("label"), NoLookupLocation.FROM_BACKEND).single()
|
||||||
|
|
||||||
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
||||||
@@ -747,6 +750,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
|
|
||||||
originalBody.transformChildrenVoid(object : IrElementTransformerVoid() {
|
originalBody.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
|
|
||||||
|
private val thisReceiver = function.dispatchReceiverParameter!!.symbol
|
||||||
|
|
||||||
// Replace returns to refer to the new function.
|
// Replace returns to refer to the new function.
|
||||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
@@ -763,7 +768,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
|
|
||||||
val capturedValue = argumentToPropertiesMap[expression.descriptor]
|
val capturedValue = argumentToPropertiesMap[expression.descriptor]
|
||||||
?: return expression
|
?: return expression
|
||||||
return irGetField(irGet(coroutineClassThis), capturedValue)
|
return irGetField(irGet(thisReceiver), capturedValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save/restore state at suspension points.
|
// Save/restore state at suspension points.
|
||||||
@@ -782,10 +787,10 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
val scope = liveLocals[suspensionPoint]!!
|
val scope = liveLocals[suspensionPoint]!!
|
||||||
return irBlock(expression) {
|
return irBlock(expression) {
|
||||||
scope.forEach {
|
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 {
|
+irCall(coroutineImplLabelSetterSymbol).apply {
|
||||||
dispatchReceiver = irGet(coroutineClassThis)
|
dispatchReceiver = irGet(thisReceiver)
|
||||||
putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter.symbol))
|
putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter.symbol))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -794,7 +799,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
val scope = liveLocals[suspensionPoint]!!
|
val scope = liveLocals[suspensionPoint]!!
|
||||||
return irBlock(expression) {
|
return irBlock(expression) {
|
||||||
scope.forEach {
|
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,
|
endOffset = endOffset,
|
||||||
type = context.builtIns.unitType,
|
type = context.builtIns.unitType,
|
||||||
suspensionPointId = irCall(coroutineImplLabelGetterSymbol).apply {
|
suspensionPointId = irCall(coroutineImplLabelGetterSymbol).apply {
|
||||||
dispatchReceiver = irGet(coroutineClassThis)
|
dispatchReceiver = irGet(function.dispatchReceiverParameter!!.symbol)
|
||||||
},
|
},
|
||||||
result = irBlock(startOffset, endOffset) {
|
result = irBlock(startOffset, endOffset) {
|
||||||
+irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception.
|
+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.IrClassSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.util.addFakeOverrides
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
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.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||||
@@ -499,6 +496,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
addMember(instanceGetterBuilder.ir)
|
addMember(instanceGetterBuilder.ir)
|
||||||
companionGetterBuilder?.let { addMember(it.ir) }
|
companionGetterBuilder?.let { addMember(it.ir) }
|
||||||
addFakeOverrides()
|
addFakeOverrides()
|
||||||
|
setSuperSymbols(context.ir.symbols.symbolTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doInitialize() {
|
override fun doInitialize() {
|
||||||
@@ -546,7 +544,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
irFile.packageFragmentDescriptor,
|
irFile.packageFragmentDescriptor,
|
||||||
testClass.functions)) {
|
testClass.functions)) {
|
||||||
initialize()
|
initialize()
|
||||||
irFile.declarations.add(ir)
|
irFile.addChild(ir)
|
||||||
irFile.addTopLevelInitializer(
|
irFile.addTopLevelInitializer(
|
||||||
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, ir.symbol.constructors.single())
|
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.explicitParameters
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
|
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.ValueType
|
||||||
import org.jetbrains.kotlin.backend.konan.correspondingValueType
|
import org.jetbrains.kotlin.backend.konan.correspondingValueType
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isArray
|
import org.jetbrains.kotlin.backend.konan.descriptors.isArray
|
||||||
@@ -33,7 +34,7 @@ import org.jetbrains.kotlin.types.typeUtil.isUnit
|
|||||||
|
|
||||||
internal interface ObjCExportMapper {
|
internal interface ObjCExportMapper {
|
||||||
fun getCategoryMembersFor(descriptor: ClassDescriptor): List<CallableMemberDescriptor>
|
fun getCategoryMembersFor(descriptor: ClassDescriptor): List<CallableMemberDescriptor>
|
||||||
val maxFunctionTypeParameterCount get() = 22
|
val maxFunctionTypeParameterCount get() = KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS
|
||||||
fun isSpecialMapped(descriptor: ClassDescriptor): Boolean
|
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.DirectedGraphNode
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint
|
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
|
|
||||||
internal class CallGraphNode(val graph: CallGraph, val symbol: DataFlowIR.FunctionSymbol)
|
internal class CallGraphNode(val graph: CallGraph, val symbol: DataFlowIR.FunctionSymbol)
|
||||||
@@ -94,7 +93,7 @@ internal class CallGraphBuilder(val context: Context,
|
|||||||
|
|
||||||
fun build(): CallGraph {
|
fun build(): CallGraph {
|
||||||
val rootSet = if (hasMain) {
|
val rootSet = if (hasMain) {
|
||||||
listOf(symbolTable.mapFunction(findMainEntryPoint(context)!!).resolved()) +
|
listOf(symbolTable.mapFunction(context.ir.symbols.entryPoint!!.owner).resolved()) +
|
||||||
moduleDFG.functions
|
moduleDFG.functions
|
||||||
.map { it.key }
|
.map { it.key }
|
||||||
.filter { it.isGlobalInitializer }
|
.filter { it.isGlobalInitializer }
|
||||||
|
|||||||
+86
-80
@@ -16,69 +16,60 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.optimizations
|
package org.jetbrains.kotlin.backend.konan.optimizations
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
|
import org.jetbrains.kotlin.backend.common.atMostOne
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole
|
import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole
|
||||||
import org.jetbrains.kotlin.backend.common.peek
|
import org.jetbrains.kotlin.backend.common.peek
|
||||||
import org.jetbrains.kotlin.backend.common.pop
|
import org.jetbrains.kotlin.backend.common.pop
|
||||||
import org.jetbrains.kotlin.backend.common.push
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
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.isInterface
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.target
|
import org.jetbrains.kotlin.backend.konan.descriptors.target
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.IrSuspendableExpression
|
import org.jetbrains.kotlin.backend.konan.ir.IrSuspendableExpression
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.IrSuspensionPoint
|
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.functionName
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
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.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
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.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
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.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
private fun computeErasure(type: KotlinType, erasure: MutableList<ClassDescriptor>) {
|
private fun computeErasure(type: KotlinType, context: Context, erasure: MutableList<ClassDescriptor>) {
|
||||||
val descriptor = type.constructor.declarationDescriptor
|
val irClass = context.ir.getClass(type)
|
||||||
when (descriptor) {
|
if (irClass != null) {
|
||||||
is ClassDescriptor -> erasure += descriptor
|
erasure += irClass
|
||||||
is TypeParameterDescriptor -> {
|
} else {
|
||||||
|
val descriptor = type.constructor.declarationDescriptor
|
||||||
|
if (descriptor is TypeParameterDescriptor) {
|
||||||
descriptor.upperBounds.forEach {
|
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>()
|
val result = mutableListOf<ClassDescriptor>()
|
||||||
computeErasure(this, result)
|
computeErasure(this, context, result)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MemberScope.getOverridingOf(function: FunctionDescriptor) = when (function) {
|
private fun IrClass.getOverridingOf(function: FunctionDescriptor) = (function as? SimpleFunctionDescriptor)?.let {
|
||||||
is PropertyGetterDescriptor ->
|
it.allOverriddenDescriptors.atMostOne { it.parent == this }
|
||||||
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 IrTypeOperator.isCast() =
|
private fun IrTypeOperator.isCast() =
|
||||||
@@ -122,7 +113,7 @@ private class VariableValues {
|
|||||||
if (element !is IrGetValue)
|
if (element !is IrGetValue)
|
||||||
result += element
|
result += element
|
||||||
else {
|
else {
|
||||||
val descriptor = element.descriptor
|
val descriptor = element.symbol.owner
|
||||||
if (descriptor is VariableDescriptor && !seen.contains(descriptor))
|
if (descriptor is VariableDescriptor && !seen.contains(descriptor))
|
||||||
dfs(descriptor, seen, result)
|
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>>) {
|
val suspendableExpressionValues: Map<IrSuspendableExpression, List<IrSuspensionPoint>>) {
|
||||||
|
|
||||||
fun forEachValue(expression: IrExpression, block: (IrExpression) -> Unit) {
|
fun forEachValue(expression: IrExpression, block: (IrExpression) -> Unit) {
|
||||||
@@ -187,11 +179,14 @@ private class ExpressionValuesExtractor(val returnableBlockValues: Map<IrReturna
|
|||||||
is IrSetField -> block(expression)
|
is IrSetField -> block(expression)
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
if ((expression.type.isUnit() || expression.type.isNothing())) {
|
val classSymbol = when {
|
||||||
block(IrGetObjectValueImpl(expression.startOffset, expression.endOffset,
|
expression.type.isUnit() -> context.ir.symbols.unit
|
||||||
expression.type, IrClassSymbolImpl(expression.type.constructor.declarationDescriptor as ClassDescriptor)))
|
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.
|
// All suspension points within specified suspendable expression.
|
||||||
private val suspendableExpressionValues = mutableMapOf<IrSuspendableExpression, MutableList<IrSuspensionPoint>>()
|
private val suspendableExpressionValues = mutableMapOf<IrSuspendableExpression, MutableList<IrSuspensionPoint>>()
|
||||||
|
|
||||||
private val expressionValuesExtractor = ExpressionValuesExtractor(returnableBlockValues, suspendableExpressionValues)
|
private val expressionValuesExtractor = ExpressionValuesExtractor(context, returnableBlockValues, suspendableExpressionValues)
|
||||||
|
|
||||||
fun build(): ModuleDFG {
|
fun build(): ModuleDFG {
|
||||||
val functions = mutableMapOf<DataFlowIR.FunctionSymbol, DataFlowIR.Function>()
|
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("Analysing function ${declaration.descriptor}")
|
||||||
println("IR: ${ir2stringWhole(declaration)}")
|
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("Analysing global field ${declaration.descriptor}")
|
||||||
println("IR: ${ir2stringWhole(declaration)}")
|
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.
|
// Find all interesting expressions, variables and functions.
|
||||||
val visitor = ElementFinderVisitor()
|
val visitor = ElementFinderVisitor()
|
||||||
body.acceptVoid(visitor)
|
body.acceptVoid(visitor)
|
||||||
@@ -346,14 +341,13 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
|
|
||||||
if (expression is IrCall && expression.symbol == scheduleImplSymbol) {
|
if (expression is IrCall && expression.symbol == scheduleImplSymbol) {
|
||||||
// Producer of scheduleImpl is called externally, we need to reflect this somehow.
|
// Producer of scheduleImpl is called externally, we need to reflect this somehow.
|
||||||
@Suppress("DEPRECATION")
|
val producerInvocation = IrCallImpl(expression.startOffset, expression.endOffset,
|
||||||
val producerInvocation = IrCallImpl(expression.startOffset, expression.endOffset, scheduleImplProducerInvokeDescriptor)
|
scheduleImplProducerInvoke.symbol, scheduleImplProducerInvoke.descriptor)
|
||||||
producerInvocation.dispatchReceiver = expression.getValueArgument(2)
|
producerInvocation.dispatchReceiver = expression.getValueArgument(2)
|
||||||
expressions += producerInvocation
|
expressions += producerInvocation
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression is IrReturnableBlock) {
|
if (expression is IrReturnableBlock) {
|
||||||
returnableBlocks.put(expression.descriptor, expression)
|
|
||||||
returnableBlockValues.put(expression, mutableListOf())
|
returnableBlockValues.put(expression, mutableListOf())
|
||||||
}
|
}
|
||||||
if (expression is IrSuspendableExpression) {
|
if (expression is IrSuspendableExpression) {
|
||||||
@@ -363,8 +357,6 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
if (expression is IrSuspensionPoint)
|
if (expression is IrSuspensionPoint)
|
||||||
suspendableExpressionValues[suspendableExpressionStack.peek()!!]!!.add(expression)
|
suspendableExpressionValues[suspendableExpressionStack.peek()!!]!!.add(expression)
|
||||||
super.visitExpression(expression)
|
super.visitExpression(expression)
|
||||||
if (expression is IrReturnableBlock)
|
|
||||||
returnableBlocks.remove(expression.descriptor)
|
|
||||||
if (expression is IrSuspendableExpression)
|
if (expression is IrSuspendableExpression)
|
||||||
suspendableExpressionStack.pop()
|
suspendableExpressionStack.pop()
|
||||||
}
|
}
|
||||||
@@ -375,7 +367,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn) {
|
override fun visitReturn(expression: IrReturn) {
|
||||||
val returnableBlock = returnableBlocks[expression.returnTarget]
|
val returnableBlock = expression.returnTargetSymbol.owner as? IrReturnableBlock
|
||||||
if (returnableBlock != null) {
|
if (returnableBlock != null) {
|
||||||
returnableBlockValues[returnableBlock]!!.add(expression.value)
|
returnableBlockValues[returnableBlock]!!.add(expression.value)
|
||||||
} else { // Non-local return.
|
} else { // Non-local return.
|
||||||
@@ -391,39 +383,43 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCatch(aCatch: IrCatch) {
|
override fun visitCatch(aCatch: IrCatch) {
|
||||||
catchParameters.add(aCatch.parameter)
|
catchParameters.add(aCatch.catchParameter)
|
||||||
super.visitCatch(aCatch)
|
super.visitCatch(aCatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSetVariable(expression: IrSetVariable) {
|
override fun visitSetVariable(expression: IrSetVariable) {
|
||||||
super.visitSetVariable(expression)
|
super.visitSetVariable(expression)
|
||||||
assignVariable(expression.descriptor, expression.value)
|
assignVariable(expression.symbol.owner, expression.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitVariable(declaration: IrVariable) {
|
override fun visitVariable(declaration: IrVariable) {
|
||||||
variableValues.addEmpty(declaration.descriptor)
|
variableValues.addEmpty(declaration)
|
||||||
super.visitVariable(declaration)
|
super.visitVariable(declaration)
|
||||||
declaration.initializer?.let { assignVariable(declaration.descriptor, it) }
|
declaration.initializer?.let { assignVariable(declaration, it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val doResumeFunctionDescriptor = context.getInternalClass("CoroutineImpl").unsubstitutedMemberScope
|
private val doResumeFunctionSymbol =
|
||||||
.getContributedFunctions(Name.identifier("doResume"), NoLookupLocation.FROM_BACKEND).single()
|
context.ir.symbols.coroutineImpl.owner.declarations
|
||||||
|
.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "doResume" }.symbol
|
||||||
|
|
||||||
private val getContinuationSymbol = context.ir.symbols.getContinuation
|
private val getContinuationSymbol = context.ir.symbols.getContinuation
|
||||||
private val continuationType = getContinuationSymbol.descriptor.returnType!!
|
private val continuationType = getContinuationSymbol.descriptor.returnType!!
|
||||||
|
|
||||||
private val arrayGetSymbol = context.ir.symbols.arrayGet
|
private val arrayGetSymbol = context.ir.symbols.arrayGet
|
||||||
private val arraySetSymbol = context.ir.symbols.arraySet
|
private val arraySetSymbol = context.ir.symbols.arraySet
|
||||||
private val scheduleImplSymbol = context.ir.symbols.scheduleImpl
|
private val scheduleImplSymbol = context.ir.symbols.scheduleImpl
|
||||||
|
private val scheduleImplProducerClassSymbol = context.ir.symbols.functions[0]
|
||||||
private val scheduleImplProducerParam = scheduleImplSymbol.descriptor.valueParameters[2].also {
|
private val scheduleImplProducerParam = scheduleImplSymbol.descriptor.valueParameters[2].also {
|
||||||
assert(it.name.asString() == "producer")
|
assert(it.name.asString() == "producer")
|
||||||
|
assert(it.type.constructor.declarationDescriptor == scheduleImplProducerClassSymbol.descriptor)
|
||||||
}
|
}
|
||||||
private val scheduleImplProducerInvokeDescriptor = scheduleImplProducerParam.type.memberScope
|
private val scheduleImplProducerInvoke = scheduleImplProducerClassSymbol.owner.simpleFunctions()
|
||||||
.getContributedFunctions(Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND).single()
|
.single { it.name == OperatorNameConventions.INVOKE }
|
||||||
|
|
||||||
private inner class FunctionDFGBuilder(val expressionValuesExtractor: ExpressionValuesExtractor,
|
private inner class FunctionDFGBuilder(val expressionValuesExtractor: ExpressionValuesExtractor,
|
||||||
val variableValues: VariableValues,
|
val variableValues: VariableValues,
|
||||||
val descriptor: CallableDescriptor,
|
val descriptor: DeclarationDescriptor,
|
||||||
val expressions: List<IrExpression>,
|
val expressions: List<IrExpression>,
|
||||||
val returnValues: List<IrExpression>,
|
val returnValues: List<IrExpression>,
|
||||||
val thrownValues: 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 allParameters = (descriptor as? FunctionDescriptor)?.allParameters ?: emptyList()
|
||||||
private val templateParameters = allParameters.withIndex().associateBy({ it.value }, { DataFlowIR.Node.Parameter(it.index) })
|
private val templateParameters = allParameters.withIndex().associateBy({ it.value }, { DataFlowIR.Node.Parameter(it.index) })
|
||||||
|
|
||||||
private val continuationParameter =
|
private val continuationParameter = if (descriptor !is IrSimpleFunction) {
|
||||||
if (descriptor.isSuspend)
|
null
|
||||||
DataFlowIR.Node.Parameter(allParameters.size)
|
} else if (descriptor.isSuspend) {
|
||||||
else {
|
DataFlowIR.Node.Parameter(allParameters.size)
|
||||||
if (doResumeFunctionDescriptor in descriptor.overriddenDescriptors) // <this> is a CoroutineImpl inheritor.
|
} else if (doResumeFunctionSymbol in descriptor.overriddenSymbols) { // <this> is a CoroutineImpl inheritor.
|
||||||
templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation.
|
templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation.
|
||||||
else null
|
} else {
|
||||||
}
|
null
|
||||||
|
}
|
||||||
|
|
||||||
private fun getContinuation() = continuationParameter ?: error("Function $descriptor has no continuation parameter")
|
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 {
|
private fun choosePrimary(erasure: List<ClassDescriptor>): ClassDescriptor {
|
||||||
if (erasure.size == 1) return erasure[0]
|
if (erasure.size == 1) return erasure[0]
|
||||||
// A parameter with constraints - choose class if exists.
|
// 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 {
|
fun build(): DataFlowIR.Function {
|
||||||
|
val isSuspend = descriptor is IrSimpleFunction && descriptor.isSuspend
|
||||||
|
|
||||||
expressions.forEach { getNode(it) }
|
expressions.forEach { getNode(it) }
|
||||||
|
|
||||||
|
val returnNodeType = when (descriptor) {
|
||||||
|
is IrField -> descriptor.type
|
||||||
|
is IrFunction -> descriptor.returnType
|
||||||
|
else -> error(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
val returnsNode = DataFlowIR.Node.Variable(
|
val returnsNode = DataFlowIR.Node.Variable(
|
||||||
values = returnValues.map { expressionToEdge(it) },
|
values = returnValues.map { expressionToEdge(it) },
|
||||||
type = symbolTable.mapType(descriptor.returnType ?: context.builtIns.unitType),
|
type = symbolTable.mapType(returnNodeType),
|
||||||
kind = DataFlowIR.VariableKind.Temporary
|
kind = DataFlowIR.VariableKind.Temporary
|
||||||
)
|
)
|
||||||
val throwsNode = DataFlowIR.Node.Variable(
|
val throwsNode = DataFlowIR.Node.Variable(
|
||||||
values = thrownValues.map { expressionToEdge(it) },
|
values = thrownValues.map { expressionToEdge(it) },
|
||||||
type = symbolTable.mapClass(context.builtIns.throwable),
|
type = symbolTable.mapClass(context.ir.symbols.throwable.owner),
|
||||||
kind = DataFlowIR.VariableKind.Temporary
|
kind = DataFlowIR.VariableKind.Temporary
|
||||||
)
|
)
|
||||||
variables.forEach { descriptor, node ->
|
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 +
|
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()))
|
val parameterTypes = (allParameters.map { it.type } + (if (isSuspend) listOf(continuationType) else emptyList()))
|
||||||
.map { symbolTable.mapClass(choosePrimary(it.erasure())) }
|
.map { symbolTable.mapClass(choosePrimary(it.erasure(context))) }
|
||||||
.toTypedArray()
|
.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(
|
return DataFlowIR.Function(
|
||||||
symbol = symbolTable.mapFunction(descriptor),
|
symbol = symbolTable.mapFunction(descriptor),
|
||||||
parameterTypes = parameterTypes,
|
parameterTypes = parameterTypes,
|
||||||
@@ -499,10 +505,10 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
|
|
||||||
private fun getNode(expression: IrExpression): DataFlowIR.Node {
|
private fun getNode(expression: IrExpression): DataFlowIR.Node {
|
||||||
if (expression is IrGetValue) {
|
if (expression is IrGetValue) {
|
||||||
val descriptor = expression.descriptor
|
val descriptor = expression.symbol.owner
|
||||||
if (descriptor is ParameterDescriptor)
|
if (descriptor is IrValueParameter)
|
||||||
return templateParameters[descriptor]!!
|
return templateParameters[descriptor]!!
|
||||||
return variables[descriptor as VariableDescriptor]!!
|
return variables[descriptor]!!
|
||||||
}
|
}
|
||||||
return nodes.getOrPut(expression) {
|
return nodes.getOrPut(expression) {
|
||||||
DEBUG_OUTPUT(0) {
|
DEBUG_OUTPUT(0) {
|
||||||
@@ -541,7 +547,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
symbolTable.mapType(value.type),
|
symbolTable.mapType(value.type),
|
||||||
if (value.type.isNothing()) // <Nothing> is not a singleton though its instance is get with <IrGetObject> operation.
|
if (value.type.isNothing()) // <Nothing> is not a singleton though its instance is get with <IrGetObject> operation.
|
||||||
null
|
null
|
||||||
else symbolTable.mapFunction(value.descriptor.constructors.single())
|
else symbolTable.mapFunction(value.symbol.owner.constructors.single())
|
||||||
)
|
)
|
||||||
|
|
||||||
is IrCall -> when (value.symbol) {
|
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)!!))
|
expressionToEdge(value.getValueArgument(0)!!), expressionToEdge(value.getValueArgument(1)!!))
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val callee = value.descriptor
|
val callee = value.symbol.owner as IrFunction
|
||||||
val arguments = value.getArguments()
|
val arguments = value.getArguments()
|
||||||
.map { expressionToEdge(it.second) }
|
.map { expressionToEdge(it.second) }
|
||||||
.let {
|
.let {
|
||||||
@@ -580,11 +586,11 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
symbolTable.mapClass(owner),
|
symbolTable.mapClass(owner),
|
||||||
callee.functionName.localHash.value,
|
callee.functionName.localHash.value,
|
||||||
arguments,
|
arguments,
|
||||||
symbolTable.mapType(callee.returnType!!),
|
symbolTable.mapType(callee.returnType),
|
||||||
value
|
value
|
||||||
)
|
)
|
||||||
} else {
|
} 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" })
|
assert(vtableIndex >= 0, { "Unable to find function $callee in vtable of $owner" })
|
||||||
DataFlowIR.Node.VtableCall(
|
DataFlowIR.Node.VtableCall(
|
||||||
symbolTable.mapFunction(callee.target),
|
symbolTable.mapFunction(callee.target),
|
||||||
@@ -596,7 +602,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val actualCallee = (value.superQualifier?.unsubstitutedMemberScope?.getOverridingOf(callee) ?: callee).target
|
val actualCallee = (value.superQualifierSymbol?.owner?.getOverridingOf(callee) ?: callee).target
|
||||||
DataFlowIR.Node.StaticCall(
|
DataFlowIR.Node.StaticCall(
|
||||||
symbolTable.mapFunction(actualCallee),
|
symbolTable.mapFunction(actualCallee),
|
||||||
arguments,
|
arguments,
|
||||||
@@ -611,12 +617,12 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
|
|
||||||
is IrDelegatingConstructorCall -> {
|
is IrDelegatingConstructorCall -> {
|
||||||
val thiz = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
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 }
|
val arguments = listOf(thiz) + value.getArguments().map { it.second }
|
||||||
DataFlowIR.Node.StaticCall(
|
DataFlowIR.Node.StaticCall(
|
||||||
symbolTable.mapFunction(value.descriptor),
|
symbolTable.mapFunction(value.symbol.owner),
|
||||||
arguments.map { expressionToEdge(it) },
|
arguments.map { expressionToEdge(it) },
|
||||||
symbolTable.mapClass(context.builtIns.unit),
|
symbolTable.mapClass(context.ir.symbols.unit.owner),
|
||||||
symbolTable.mapType(thiz.type),
|
symbolTable.mapType(thiz.type),
|
||||||
value
|
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.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
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.isObjCClass
|
||||||
import org.jetbrains.kotlin.backend.konan.isValueType
|
import org.jetbrains.kotlin.backend.konan.isValueType
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.isExported
|
import org.jetbrains.kotlin.backend.konan.llvm.isExported
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.symbolName
|
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.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
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.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
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
|
private inline fun takeName(block: () -> String) = if (TAKE_NAMES) block() else null
|
||||||
|
|
||||||
val classMap = mutableMapOf<ClassDescriptor, Type>()
|
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_ESCAPES = Name.identifier("Escapes")
|
||||||
private val NAME_POINTS_TO = Name.identifier("PointsTo")
|
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 konanPackage = context.builtIns.builtInsModule.getPackage(FQ_NAME_KONAN).memberScope
|
||||||
private val escapesAnnotationDescriptor = konanPackage.getContributedClassifier(
|
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 escapesWhoDescriptor = escapesAnnotationDescriptor.unsubstitutedPrimaryConstructor!!.valueParameters.single()
|
||||||
private val pointsToAnnotationDescriptor = konanPackage.getContributedClassifier(
|
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()
|
private val pointsToOnWhomDescriptor = pointsToAnnotationDescriptor.unsubstitutedPrimaryConstructor!!.valueParameters.single()
|
||||||
|
|
||||||
var privateTypeIndex = 0
|
var privateTypeIndex = 0
|
||||||
@@ -448,17 +447,17 @@ internal object DataFlowIR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction) {
|
override fun visitFunction(declaration: IrFunction) {
|
||||||
declaration.body?.let { mapFunction(declaration.descriptor) }
|
declaration.body?.let { mapFunction(declaration) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitField(declaration: IrField) {
|
override fun visitField(declaration: IrField) {
|
||||||
declaration.initializer?.let { mapFunction(declaration.descriptor) }
|
declaration.initializer?.let { mapFunction(declaration) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass) {
|
override fun visitClass(declaration: IrClass) {
|
||||||
declaration.acceptChildrenVoid(this)
|
declaration.acceptChildrenVoid(this)
|
||||||
|
|
||||||
mapClass(declaration.descriptor)
|
mapClass(declaration)
|
||||||
}
|
}
|
||||||
}, data = null)
|
}, data = null)
|
||||||
}
|
}
|
||||||
@@ -501,40 +500,27 @@ internal object DataFlowIR {
|
|||||||
return type
|
return type
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mapType(type: KotlinType) = mapClass(type.erasure().single())
|
fun mapType(type: KotlinType) = mapClass(type.erasure(context).single())
|
||||||
|
|
||||||
// TODO: use from LlvmDeclarations.
|
// TODO: use from LlvmDeclarations.
|
||||||
private fun getFqName(descriptor: DeclarationDescriptor): FqName {
|
private fun getFqName(descriptor: DeclarationDescriptor): FqName =
|
||||||
if (descriptor is PackageFragmentDescriptor) {
|
descriptor.parent.fqNameSafe.child(descriptor.name)
|
||||||
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 val FunctionDescriptor.internalName get() = getFqName(this).asString() + "#internal"
|
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) {
|
functionMap.getOrPut(it) {
|
||||||
when (it) {
|
when (it) {
|
||||||
is PropertyDescriptor -> {
|
is IrField -> {
|
||||||
// A global property initializer.
|
// 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" })
|
FunctionSymbol.Private(privateFunIndex++, 0, module, -1, true, takeName { "${it.symbolName}_init" })
|
||||||
}
|
}
|
||||||
|
|
||||||
is FunctionDescriptor -> {
|
is FunctionDescriptor -> {
|
||||||
val name = if (it.isExported()) it.symbolName else it.internalName
|
val name = if (it.isExported()) it.symbolName else it.internalName
|
||||||
val numberOfParameters = it.allParameters.size + if (it.isSuspend) 1 else 0
|
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 escapesAnnotation = it.annotations.findAnnotation(FQ_NAME_ESCAPES)
|
||||||
val pointsToAnnotation = it.annotations.findAnnotation(FQ_NAME_POINTS_TO)
|
val pointsToAnnotation = it.annotations.findAnnotation(FQ_NAME_POINTS_TO)
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@@ -544,7 +530,7 @@ internal object DataFlowIR {
|
|||||||
FunctionSymbol.External(name.localHash.value, numberOfParameters, false, escapesBitMask,
|
FunctionSymbol.External(name.localHash.value, numberOfParameters, false, escapesBitMask,
|
||||||
pointsToBitMask?.let { it.map { it.value }.toIntArray() }, takeName { name })
|
pointsToBitMask?.let { it.map { it.value }.toIntArray() }, takeName { name })
|
||||||
} else {
|
} else {
|
||||||
val isAbstract = it.modality == Modality.ABSTRACT
|
val isAbstract = it is SimpleFunctionDescriptor && it.modality == Modality.ABSTRACT
|
||||||
val classDescriptor = it.containingDeclaration as? ClassDescriptor
|
val classDescriptor = it.containingDeclaration as? ClassDescriptor
|
||||||
val placeToFunctionsTable = !isAbstract && it !is ConstructorDescriptor && classDescriptor != null
|
val placeToFunctionsTable = !isAbstract && it !is ConstructorDescriptor && classDescriptor != null
|
||||||
&& classDescriptor.kind != ClassKind.ANNOTATION_CLASS
|
&& classDescriptor.kind != ClassKind.ANNOTATION_CLASS
|
||||||
|
|||||||
+3
-3
@@ -66,7 +66,7 @@ internal object Devirtualization {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
val entryPoint = findMainEntryPoint(context)
|
val entryPoint = context.ir.symbols.entryPoint?.owner
|
||||||
val exportedFunctions =
|
val exportedFunctions =
|
||||||
if (entryPoint != null)
|
if (entryPoint != null)
|
||||||
listOf(moduleDFG.symbolTable.mapFunction(entryPoint).resolved())
|
listOf(moduleDFG.symbolTable.mapFunction(entryPoint).resolved())
|
||||||
@@ -97,7 +97,7 @@ internal object Devirtualization {
|
|||||||
val moduleDFG: ModuleDFG,
|
val moduleDFG: ModuleDFG,
|
||||||
val externalModulesDFG: ExternalModulesDFG) {
|
val externalModulesDFG: ExternalModulesDFG) {
|
||||||
|
|
||||||
private val entryPoint = findMainEntryPoint(context)
|
private val entryPoint = context.ir.symbols.entryPoint?.owner
|
||||||
|
|
||||||
private val symbolTable = moduleDFG.symbolTable
|
private val symbolTable = moduleDFG.symbolTable
|
||||||
|
|
||||||
@@ -506,7 +506,7 @@ internal object Devirtualization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val result = mutableMapOf<DataFlowIR.Node.VirtualCall, Pair<DevirtualizedCallSite, DataFlowIR.FunctionSymbol>>()
|
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
|
functions.values
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.filter { constraintGraph.functions.containsKey(it.symbol) }
|
.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.DirectedGraphCondensationBuilder
|
||||||
import org.jetbrains.kotlin.backend.konan.DirectedGraphMultiNode
|
import org.jetbrains.kotlin.backend.konan.DirectedGraphMultiNode
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.Lifetime
|
import org.jetbrains.kotlin.backend.konan.llvm.Lifetime
|
||||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
|
||||||
internal object EscapeAnalysis {
|
internal object EscapeAnalysis {
|
||||||
@@ -605,7 +604,7 @@ internal object EscapeAnalysis {
|
|||||||
reachable += parameters.size
|
reachable += parameters.size
|
||||||
reachabilities.add(reachable.toIntArray())
|
reachabilities.add(reachable.toIntArray())
|
||||||
visited.forEach { node ->
|
visited.forEach { node ->
|
||||||
if (node !is ParameterDescriptor)
|
if (node !is DataFlowIR.Node.Parameter)
|
||||||
nodes[node]!!.addIncomingParameter(it.index)
|
nodes[node]!!.addIncomingParameter(it.index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+214
-11
@@ -16,27 +16,30 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.serialization
|
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.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
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.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.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) {
|
internal fun DeclarationDescriptor.symbolName(): String = when (this) {
|
||||||
is FunctionDescriptor
|
is FunctionDescriptor
|
||||||
-> this.symbolName
|
-> this.uniqueName
|
||||||
is PropertyDescriptor
|
is PropertyDescriptor
|
||||||
-> this.symbolName
|
-> this.uniqueName
|
||||||
is ClassDescriptor
|
is ClassDescriptor
|
||||||
-> this.typeInfoSymbolName
|
-> this.uniqueName
|
||||||
else -> error("Unexpected exported descriptor: $this")
|
else -> error("Unexpected exported descriptor: $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,3 +94,203 @@ val IrBuiltIns.irBuiltInDescriptors
|
|||||||
.map(IrSimpleFunction::descriptor)
|
.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.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.ir.util.addFakeOverrides
|
import org.jetbrains.kotlin.ir.util.addFakeOverrides
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
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.KonanDescriptorSerializer
|
||||||
import org.jetbrains.kotlin.serialization.KonanIr
|
import org.jetbrains.kotlin.serialization.KonanIr
|
||||||
import org.jetbrains.kotlin.serialization.KonanIr.IrConst.ValueCase.*
|
import org.jetbrains.kotlin.serialization.KonanIr.IrConst.ValueCase.*
|
||||||
@@ -1209,6 +1211,7 @@ internal class IrDeserializer(val context: Context,
|
|||||||
|
|
||||||
clazz.createParameterDeclarations()
|
clazz.createParameterDeclarations()
|
||||||
clazz.addFakeOverrides()
|
clazz.addFakeOverrides()
|
||||||
|
clazz.setSuperSymbols(context.ir.symbols.symbolTable)
|
||||||
|
|
||||||
return clazz
|
return clazz
|
||||||
|
|
||||||
@@ -1222,6 +1225,7 @@ internal class IrDeserializer(val context: Context,
|
|||||||
descriptor, body as IrBody)
|
descriptor, body as IrBody)
|
||||||
|
|
||||||
function.createParameterDeclarations()
|
function.createParameterDeclarations()
|
||||||
|
function.setOverrides(context.ir.symbols.symbolTable)
|
||||||
|
|
||||||
proto.defaultArgumentList.forEach {
|
proto.defaultArgumentList.forEach {
|
||||||
val expr = deserializeExpression(it.value)
|
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.common.push
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
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.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
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.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
|
|
||||||
@Deprecated("")
|
@Deprecated("")
|
||||||
@@ -93,7 +86,7 @@ private fun IrModuleFragment.mergeFrom(other: IrModuleFragment): Unit {
|
|||||||
if (thisPackage == null) {
|
if (thisPackage == null) {
|
||||||
this.externalPackageFragments.add(it)
|
this.externalPackageFragments.add(it)
|
||||||
} else {
|
} else {
|
||||||
thisPackage.declarations.addAll(it.declarations)
|
thisPackage.addChildren(it.declarations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,42 +113,47 @@ private class IrUnboundSymbolReplacer(
|
|||||||
val descriptorToSymbol: Map<DeclarationDescriptor, IrSymbol>
|
val descriptorToSymbol: Map<DeclarationDescriptor, IrSymbol>
|
||||||
) : IrElementTransformerVoid() {
|
) : 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? {
|
referenceSymbol: (SymbolTable, D) -> S): S? {
|
||||||
|
|
||||||
if (this.isBound) {
|
if (this.isBound) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
localDescriptorToSymbol[this.descriptor]?.lastOrNull()?.let {
|
||||||
|
return it as S
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
descriptorToSymbol[this.descriptor]?.let {
|
descriptorToSymbol[this.descriptor]?.let {
|
||||||
return it as S
|
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
|
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? {
|
private inline fun <reified S : IrSymbol> S.replaceLocal(): S? {
|
||||||
return if (this.isBound) {
|
return if (this.isBound) {
|
||||||
null
|
null
|
||||||
} else {
|
} 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 {
|
override fun visitClassReference(expression: IrClassReference): IrExpression {
|
||||||
val symbol = expression.symbol.let {
|
val symbol = expression.symbol.replace(SymbolTable::referenceClassifier)
|
||||||
if (it.isBound) {
|
?: return super.visitClassReference(expression)
|
||||||
return super.visitClassReference(expression)
|
|
||||||
}
|
|
||||||
|
|
||||||
descriptorToSymbol[it.descriptor]?.let {
|
|
||||||
it as IrClassifierSymbol
|
|
||||||
}
|
|
||||||
|
|
||||||
symbolTable.referenceClassifier(it.descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
return with(expression) {
|
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 {
|
override fun visitGetField(expression: IrGetField): IrExpression {
|
||||||
val symbol = expression.symbol.replaceOrSame(SymbolTable::referenceField)
|
val symbol = expression.symbol.replaceOrSame(SymbolTable::referenceField)
|
||||||
|
|
||||||
@@ -358,7 +359,20 @@ private class IrUnboundSymbolReplacer(
|
|||||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||||
returnTargetStack.push(declaration.symbol)
|
returnTargetStack.push(declaration.symbol)
|
||||||
try {
|
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 {
|
} finally {
|
||||||
returnTargetStack.pop()
|
returnTargetStack.pop()
|
||||||
}
|
}
|
||||||
|
|||||||
+277
-8
@@ -17,23 +17,25 @@
|
|||||||
package org.jetbrains.kotlin.ir.util
|
package org.jetbrains.kotlin.ir.util
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
|
||||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
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.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import java.lang.reflect.Proxy
|
||||||
|
|
||||||
//TODO: delete file on next kotlin dependency update
|
//TODO: delete file on next kotlin dependency update
|
||||||
internal fun IrExpression.isNullConst() = this is IrConst<*> && this.kind == IrConstKind.Null
|
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)
|
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
|
#kotlinCompilerModule=org.jetbrains.kotlin:kotlin-compiler:1.1-SNAPSHOT
|
||||||
# Download artifacts of https://teamcity.jetbrains.com/viewType.html?buildTypeId=Kotlin_120_Compiler
|
# Download artifacts of https://teamcity.jetbrains.com/viewType.html?buildTypeId=Kotlin_120_Compiler
|
||||||
testDataVersion=1226829:id
|
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
|
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-610
|
kotlinCompilerVersion=1.2.40-dev-837
|
||||||
kotlinScriptRuntimeVersion=1.2.40-dev-610
|
kotlinScriptRuntimeVersion=1.2.40-dev-837
|
||||||
kotlinStdLibVersion=1.2.40-dev-610
|
kotlinStdLibVersion=1.2.40-dev-837
|
||||||
kotlinReflectVersion=1.2.40-dev-610
|
kotlinReflectVersion=1.2.40-dev-837
|
||||||
konanVersion=0.6.1
|
konanVersion=0.6.1
|
||||||
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
|
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
|
||||||
|
|
||||||
##
|
##
|
||||||
# required for performance mesuarement tasks
|
# required for performance mesuarement tasks
|
||||||
|
|
||||||
kotlinStdLibJdk8Version=1.2.40-dev-610
|
kotlinStdLibJdk8Version=1.2.40-dev-837
|
||||||
kotlinGradlePluginVersion=1.2.40-dev-610
|
kotlinGradlePluginVersion=1.2.40-dev-837
|
||||||
|
|||||||
Reference in New Issue
Block a user