Compiler symbolization part 3
This commit is contained in:
+68
-92
@@ -6,16 +6,13 @@
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
@@ -23,8 +20,9 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -67,52 +65,41 @@ internal val Context.getBoxFunction: (IrClass) -> IrSimpleFunction by Context.la
|
||||
val parameterType = unboxedType
|
||||
val returnType = boxedType
|
||||
|
||||
val descriptor = SimpleFunctionDescriptorImpl.create(
|
||||
inlinedClass.descriptor,
|
||||
Annotations.EMPTY,
|
||||
Name.special("<box>"),
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
val parameter = ValueParameterDescriptorImpl(
|
||||
descriptor,
|
||||
null,
|
||||
0,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier("value"),
|
||||
parameterType.toKotlinType(),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
descriptor.initialize(
|
||||
null,
|
||||
null,
|
||||
emptyList(),
|
||||
listOf(parameter),
|
||||
returnType.toKotlinType(),
|
||||
Modality.FINAL,
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
|
||||
val startOffset = inlinedClass.startOffset
|
||||
val endOffset = inlinedClass.endOffset
|
||||
|
||||
IrFunctionImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, descriptor, returnType).apply {
|
||||
this.valueParameters.add(IrValueParameterImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
parameter,
|
||||
parameterType,
|
||||
null
|
||||
))
|
||||
|
||||
this.parent = inlinedClass
|
||||
val descriptor = WrappedSimpleFunctionDescriptor()
|
||||
IrFunctionImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrSimpleFunctionSymbolImpl(descriptor),
|
||||
Name.special("<box>"),
|
||||
Visibilities.PUBLIC,
|
||||
Modality.FINAL,
|
||||
returnType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = false
|
||||
).also { function ->
|
||||
function.valueParameters.add(WrappedValueParameterDescriptor().let {
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrValueParameterSymbolImpl(it),
|
||||
Name.identifier("value"),
|
||||
index = 0,
|
||||
varargElementType = null,
|
||||
isCrossinline = false,
|
||||
type = parameterType,
|
||||
isNoinline = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = function
|
||||
}
|
||||
})
|
||||
descriptor.bind(function)
|
||||
function.parent = inlinedClass
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,52 +115,41 @@ internal val Context.getUnboxFunction: (IrClass) -> IrSimpleFunction by Context.
|
||||
val parameterType = boxedType
|
||||
val returnType = unboxedType
|
||||
|
||||
val descriptor = SimpleFunctionDescriptorImpl.create(
|
||||
inlinedClass.descriptor,
|
||||
Annotations.EMPTY,
|
||||
Name.special("<unbox>"),
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
val parameter = ValueParameterDescriptorImpl(
|
||||
descriptor,
|
||||
null,
|
||||
0,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier("value"),
|
||||
parameterType.toKotlinType(),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
descriptor.initialize(
|
||||
null,
|
||||
null,
|
||||
emptyList(),
|
||||
listOf(parameter),
|
||||
returnType.toKotlinType(),
|
||||
Modality.FINAL,
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
|
||||
val startOffset = inlinedClass.startOffset
|
||||
val endOffset = inlinedClass.endOffset
|
||||
|
||||
IrFunctionImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, descriptor, returnType).apply {
|
||||
this.valueParameters.add(IrValueParameterImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
parameter,
|
||||
parameterType,
|
||||
null
|
||||
))
|
||||
|
||||
this.parent = inlinedClass
|
||||
val descriptor = WrappedSimpleFunctionDescriptor()
|
||||
IrFunctionImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrSimpleFunctionSymbolImpl(descriptor),
|
||||
Name.special("<unbox>"),
|
||||
Visibilities.PUBLIC,
|
||||
Modality.FINAL,
|
||||
returnType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = false
|
||||
).also { function ->
|
||||
function.valueParameters.add(WrappedValueParameterDescriptor().let {
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrValueParameterSymbolImpl(it),
|
||||
Name.identifier("value"),
|
||||
index = 0,
|
||||
varargElementType = null,
|
||||
isCrossinline = false,
|
||||
type = parameterType,
|
||||
isNoinline = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = function
|
||||
}
|
||||
})
|
||||
descriptor.bind(function)
|
||||
function.parent = inlinedClass
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+62
-124
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.backend.konan
|
||||
import llvm.LLVMDumpModule
|
||||
import llvm.LLVMModuleRef
|
||||
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.validateIrModule
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIr
|
||||
@@ -20,8 +22,6 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.SourceManager
|
||||
@@ -29,15 +29,13 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
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.builtins.konan.KonanBuiltIns
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -51,6 +49,8 @@ import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
import java.lang.System.out
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
import kotlin.reflect.KProperty
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||
|
||||
/**
|
||||
* Offset for synthetic elements created by lowerings and not attributable to other places in the source code.
|
||||
@@ -97,7 +97,7 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
||||
}
|
||||
|
||||
fun getLoweredEnum(enumClass: IrClass): LoweredEnum {
|
||||
assert(enumClass.kind == ClassKind.ENUM_CLASS, { "Expected enum class but was: ${enumClass.descriptor}" })
|
||||
assert(enumClass.kind == ClassKind.ENUM_CLASS) { "Expected enum class but was: ${enumClass.descriptor}" }
|
||||
return loweredEnums.getOrPut(enumClass) {
|
||||
enumSpecialDeclarationsFactory.createLoweredEnum(enumClass)
|
||||
}
|
||||
@@ -125,143 +125,81 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
||||
|
||||
fun getBridge(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): IrSimpleFunction {
|
||||
val irFunction = overriddenFunctionDescriptor.descriptor
|
||||
assert(overriddenFunctionDescriptor.needBridge,
|
||||
{ "Function ${irFunction.descriptor} is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor.descriptor}" })
|
||||
assert(overriddenFunctionDescriptor.needBridge) {
|
||||
"Function ${irFunction.descriptor} is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor.descriptor}"
|
||||
}
|
||||
val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections
|
||||
return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) {
|
||||
createBridge(irFunction, bridgeDirections)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createBridge(function: IrFunction, bridgeDirections: BridgeDirections): IrFunctionImpl {
|
||||
private fun createBridge(function: IrSimpleFunction,
|
||||
bridgeDirections: BridgeDirections) = WrappedSimpleFunctionDescriptor().let { descriptor ->
|
||||
val startOffset = function.startOffset
|
||||
val endOffset = function.endOffset
|
||||
val returnType = when (bridgeDirections.array[0]) {
|
||||
BridgeDirection.TO_VALUE_TYPE,
|
||||
BridgeDirection.NOT_NEEDED -> function.returnType
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyNType
|
||||
}
|
||||
|
||||
val dispatchReceiver = when (bridgeDirections.array[1]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> function.dispatchReceiverParameter!!
|
||||
BridgeDirection.NOT_NEEDED -> function.dispatchReceiverParameter
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyClass.owner.thisReceiver!!
|
||||
}
|
||||
|
||||
val extensionReceiverType = when (bridgeDirections.array[2]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> function.extensionReceiverParameter!!.type
|
||||
BridgeDirection.NOT_NEEDED -> function.extensionReceiverParameter?.type
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyNType
|
||||
}
|
||||
|
||||
val valueParameterTypes = function.valueParameters.mapIndexed { index, valueParameter ->
|
||||
when (bridgeDirections.array[index + 3]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> valueParameter.type
|
||||
BridgeDirection.NOT_NEEDED -> valueParameter.type
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyNType
|
||||
}
|
||||
}
|
||||
val bridgeDescriptor = createBridgeDescriptor(
|
||||
function,
|
||||
bridgeDirections,
|
||||
returnType,
|
||||
dispatchReceiver,
|
||||
extensionReceiverType,
|
||||
valueParameterTypes
|
||||
)
|
||||
|
||||
val bridge = IrFunctionImpl(
|
||||
function.startOffset,
|
||||
function.endOffset,
|
||||
IrFunctionImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_BRIDGE_METHOD(function),
|
||||
bridgeDescriptor,
|
||||
returnType
|
||||
IrSimpleFunctionSymbolImpl(descriptor),
|
||||
"<bridge-$bridgeDirections>${function.functionName}".synthesizedName,
|
||||
function.visibility,
|
||||
function.modality,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = function.isSuspend,
|
||||
returnType = returnType
|
||||
).apply {
|
||||
this.parent = function.parent
|
||||
}
|
||||
descriptor.bind(this)
|
||||
parent = function.parent
|
||||
|
||||
bridge.dispatchReceiverParameter = dispatchReceiver?.let {
|
||||
IrValueParameterImpl(
|
||||
it.startOffset,
|
||||
it.endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
it.descriptor,
|
||||
it.type,
|
||||
null
|
||||
)
|
||||
}
|
||||
val dispatchReceiver = when (bridgeDirections.array[1]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> function.dispatchReceiverParameter!!
|
||||
BridgeDirection.NOT_NEEDED -> function.dispatchReceiverParameter
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyClass.owner.thisReceiver!!
|
||||
}
|
||||
|
||||
extensionReceiverType?.let {
|
||||
val extensionReceiverParameter = function.extensionReceiverParameter!!
|
||||
bridge.extensionReceiverParameter = IrValueParameterImpl(
|
||||
extensionReceiverParameter.startOffset,
|
||||
extensionReceiverParameter.endOffset,
|
||||
extensionReceiverParameter.origin,
|
||||
bridge.descriptor.extensionReceiverParameter!!,
|
||||
it, null
|
||||
)
|
||||
}
|
||||
function.valueParameters.mapIndexedTo(bridge.valueParameters) { index, valueParameter ->
|
||||
val type = valueParameterTypes[index]
|
||||
val extensionReceiver = when (bridgeDirections.array[2]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> function.extensionReceiverParameter!!
|
||||
BridgeDirection.NOT_NEEDED -> function.extensionReceiverParameter
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyClass.owner.thisReceiver!!
|
||||
}
|
||||
|
||||
IrValueParameterImpl(
|
||||
valueParameter.startOffset,
|
||||
valueParameter.endOffset,
|
||||
valueParameter.origin,
|
||||
bridge.descriptor.valueParameters[index],
|
||||
type, valueParameter.varargElementType
|
||||
)
|
||||
}
|
||||
val valueParameterTypes = function.valueParameters.mapIndexed { index, valueParameter ->
|
||||
when (bridgeDirections.array[index + 3]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> valueParameter.type
|
||||
BridgeDirection.NOT_NEEDED -> valueParameter.type
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyNType
|
||||
}
|
||||
}
|
||||
|
||||
function.typeParameters.mapTo(bridge.typeParameters) {
|
||||
IrTypeParameterImpl(it.startOffset, it.endOffset, it.origin, it.descriptor).apply {
|
||||
superTypes += it.superTypes
|
||||
dispatchReceiverParameter = dispatchReceiver?.copyTo(this)
|
||||
extensionReceiverParameter = extensionReceiver?.copyTo(this)
|
||||
function.valueParameters.mapTo(valueParameters) { it.copyTo(this, type = valueParameterTypes[it.index]) }
|
||||
|
||||
function.typeParameters.mapIndexedTo(typeParameters) { index, parameter ->
|
||||
WrappedTypeParameterDescriptor().let {
|
||||
IrTypeParameterImpl(
|
||||
startOffset, endOffset,
|
||||
origin,
|
||||
IrTypeParameterSymbolImpl(it),
|
||||
parameter.name,
|
||||
index,
|
||||
parameter.isReified,
|
||||
parameter.variance
|
||||
).apply {
|
||||
it.bind(this)
|
||||
superTypes += parameter.superTypes
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bridge
|
||||
}
|
||||
|
||||
private fun createBridgeDescriptor(
|
||||
function: IrFunction,
|
||||
bridgeDirections: BridgeDirections,
|
||||
returnType: IrType,
|
||||
dispatchReceiverParameter: IrValueParameter?,
|
||||
extensionReceiverType: IrType?,
|
||||
valueParameterTypes: List<IrType>
|
||||
): SimpleFunctionDescriptor {
|
||||
|
||||
val descriptor = function.descriptor
|
||||
val bridgeDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
/* containingDeclaration = */ descriptor.containingDeclaration,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* name = */ "<bridge-$bridgeDirections>${function.functionName}".synthesizedName,
|
||||
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/* source = */ SourceElement.NO_SOURCE)
|
||||
|
||||
val valueParameters = descriptor.valueParameters.mapIndexed { index, valueParameterDescriptor ->
|
||||
ValueParameterDescriptorImpl(
|
||||
containingDeclaration = valueParameterDescriptor.containingDeclaration,
|
||||
original = null,
|
||||
index = index,
|
||||
annotations = Annotations.EMPTY,
|
||||
name = valueParameterDescriptor.name,
|
||||
outType = valueParameterTypes[index].toKotlinType(),
|
||||
declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(),
|
||||
isCrossinline = valueParameterDescriptor.isCrossinline,
|
||||
isNoinline = valueParameterDescriptor.isNoinline,
|
||||
varargElementType = valueParameterDescriptor.varargElementType,
|
||||
source = SourceElement.NO_SOURCE)
|
||||
}
|
||||
bridgeDescriptor.initialize(
|
||||
/* receiverParameterType = */ extensionReceiverType?.toKotlinType(),
|
||||
/* dispatchReceiverParameter = */ dispatchReceiverParameter?.descriptor as ReceiverParameterDescriptor?,
|
||||
/* typeParameters = */ descriptor.typeParameters,
|
||||
/* unsubstitutedValueParameters = */ valueParameters,
|
||||
/* unsubstitutedReturnType = */ returnType.toKotlinType(),
|
||||
/* modality = */ descriptor.modality,
|
||||
/* visibility = */ descriptor.visibility).apply {
|
||||
isSuspend = descriptor.isSuspend
|
||||
}
|
||||
return bridgeDescriptor
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+81
-101
@@ -5,143 +5,123 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedFieldDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.enumEntries
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.typeWith
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
|
||||
|
||||
internal object DECLARATION_ORIGIN_ENUM :
|
||||
IrDeclarationOriginImpl("ENUM")
|
||||
internal object DECLARATION_ORIGIN_ENUM : IrDeclarationOriginImpl("ENUM")
|
||||
|
||||
internal data class LoweredEnum(val implObject: IrClass,
|
||||
val valuesField: IrField,
|
||||
val valuesGetter: IrSimpleFunction,
|
||||
val itemGetterSymbol: IrSimpleFunctionSymbol,
|
||||
val itemGetterDescriptor: FunctionDescriptor,
|
||||
val entriesMap: Map<Name, Int>)
|
||||
|
||||
internal class EnumSpecialDeclarationsFactory(val context: Context) {
|
||||
fun createLoweredEnum(enumClass: IrClass): LoweredEnum {
|
||||
val enumClassDescriptor = enumClass.descriptor
|
||||
private val symbols = context.ir.symbols
|
||||
|
||||
fun createLoweredEnum(enumClass: IrClass): LoweredEnum {
|
||||
val startOffset = enumClass.startOffset
|
||||
val endOffset = enumClass.endOffset
|
||||
|
||||
val implObjectDescriptor = ClassDescriptorImpl(enumClassDescriptor, "OBJECT".synthesizedName, Modality.FINAL,
|
||||
ClassKind.OBJECT, listOf(context.builtIns.anyType), SourceElement.NO_SOURCE, false, LockBasedStorageManager.NO_LOCKS)
|
||||
|
||||
val implObject = IrClassImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, implObjectDescriptor).apply {
|
||||
createParameterDeclarations()
|
||||
val implObject = WrappedClassDescriptor().let {
|
||||
IrClassImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
IrClassSymbolImpl(it),
|
||||
"OBJECT".synthesizedName,
|
||||
ClassKind.OBJECT,
|
||||
Visibilities.PUBLIC,
|
||||
Modality.FINAL,
|
||||
isCompanion = false,
|
||||
isInner = false,
|
||||
isData = false,
|
||||
isExternal = false,
|
||||
isInline = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = enumClass
|
||||
createParameterDeclarations()
|
||||
}
|
||||
}
|
||||
|
||||
val valuesProperty = createEnumValuesField(enumClassDescriptor, implObjectDescriptor)
|
||||
val valuesType = context.ir.symbols.array.typeWith(enumClass.defaultType)
|
||||
val valuesField = IrFieldImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesProperty, valuesType)
|
||||
|
||||
val valuesGetterDescriptor = createValuesGetterDescriptor(enumClassDescriptor, implObjectDescriptor)
|
||||
val valuesGetter = IrFunctionImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
valuesGetterDescriptor,
|
||||
valuesType
|
||||
).also {
|
||||
it.parent = implObject
|
||||
it.createDispatchReceiverParameter()
|
||||
val valuesType = symbols.array.typeWith(enumClass.defaultType)
|
||||
val valuesField = WrappedFieldDescriptor().let {
|
||||
IrFieldImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
IrFieldSymbolImpl(it),
|
||||
"VALUES".synthesizedName,
|
||||
valuesType,
|
||||
Visibilities.PRIVATE,
|
||||
isFinal = true,
|
||||
isExternal = false,
|
||||
isStatic = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = implObject
|
||||
}
|
||||
}
|
||||
|
||||
val memberScope = MemberScope.Empty
|
||||
val valuesGetter = WrappedSimpleFunctionDescriptor().let {
|
||||
IrFunctionImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
IrSimpleFunctionSymbolImpl(it),
|
||||
"get-VALUES".synthesizedName,
|
||||
Visibilities.PUBLIC,
|
||||
Modality.FINAL,
|
||||
valuesType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = implObject
|
||||
}
|
||||
}
|
||||
|
||||
val constructorOfAny = context.irBuiltIns.anyClass.owner.constructors.first()
|
||||
// TODO: why primary?
|
||||
val constructor = implObject.addSimpleDelegatingConstructor(
|
||||
implObject.addSimpleDelegatingConstructor(
|
||||
constructorOfAny,
|
||||
context.irBuiltIns,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
true
|
||||
true // TODO: why primary?
|
||||
)
|
||||
val constructorDescriptor = constructor.descriptor
|
||||
|
||||
implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor)
|
||||
implObject.setSuperSymbolsAndAddFakeOverrides(listOf(context.irBuiltIns.anyType))
|
||||
implObject.parent = enumClass
|
||||
valuesField.parent = implObject
|
||||
implObject.superTypes += context.irBuiltIns.anyType
|
||||
implObject.addFakeOverrides()
|
||||
|
||||
val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor)
|
||||
val itemGetterSymbol = symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||
val enumEntriesMap = enumClass.declarations
|
||||
.filterIsInstance<IrEnumEntry>()
|
||||
.sortedBy { it.name }
|
||||
.withIndex()
|
||||
.associate { it.value.name to it.index }
|
||||
.toMap()
|
||||
|
||||
return LoweredEnum(
|
||||
implObject,
|
||||
valuesField,
|
||||
valuesGetter,
|
||||
itemGetterSymbol, itemGetterDescriptor,
|
||||
createEnumEntriesMap(enumClassDescriptor))
|
||||
itemGetterSymbol,
|
||||
enumEntriesMap)
|
||||
}
|
||||
|
||||
private fun createValuesGetterDescriptor(enumClassDescriptor: ClassDescriptor, implObjectDescriptor: ClassDescriptor)
|
||||
: FunctionDescriptor {
|
||||
val returnType = genericArrayType.defaultType.replace(listOf(TypeProjectionImpl(enumClassDescriptor.defaultType)))
|
||||
val result = SimpleFunctionDescriptorImpl.create(
|
||||
/* containingDeclaration = */ implObjectDescriptor,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* name = */ "get-VALUES".synthesizedName,
|
||||
/* kind = */ CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
/* source = */ SourceElement.NO_SOURCE)
|
||||
result.initialize(
|
||||
/* receiverParameterType = */ null,
|
||||
/* dispatchReceiverParameter = */ null,
|
||||
/* typeParameters = */ listOf(),
|
||||
/* unsubstitutedValueParameters = */ listOf(),
|
||||
/* unsubstitutedReturnType = */ returnType,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PUBLIC)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun createEnumValuesField(enumClassDescriptor: ClassDescriptor, implObjectDescriptor: ClassDescriptor): PropertyDescriptor {
|
||||
val valuesArrayType = context.builtIns.getArrayType(Variance.INVARIANT, enumClassDescriptor.defaultType)
|
||||
val receiver = ReceiverParameterDescriptorImpl(
|
||||
implObjectDescriptor,
|
||||
ImplicitClassReceiver(implObjectDescriptor, null),
|
||||
Annotations.EMPTY
|
||||
)
|
||||
return PropertyDescriptorImpl.create(implObjectDescriptor, Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC,
|
||||
false, "VALUES".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE,
|
||||
false, false, false, false, false, false).apply {
|
||||
|
||||
this.setType(valuesArrayType, emptyList(), receiver, null)
|
||||
this.initialize(null, null)
|
||||
}
|
||||
}
|
||||
|
||||
private val genericArrayType = context.ir.symbols.array.descriptor
|
||||
|
||||
private fun getEnumItemGetter(enumClassDescriptor: ClassDescriptor): Pair<IrSimpleFunctionSymbol, FunctionDescriptor> {
|
||||
val getter = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||
|
||||
val typeParameterT = genericArrayType.declaredTypeParameters[0]
|
||||
val enumClassType = enumClassDescriptor.defaultType
|
||||
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType)))
|
||||
return getter to getter.descriptor.substitute(typeSubstitutor)!!
|
||||
}
|
||||
|
||||
private fun createEnumEntriesMap(enumClassDescriptor: ClassDescriptor): Map<Name, Int> {
|
||||
val map = mutableMapOf<Name, Int>()
|
||||
enumClassDescriptor.enumEntries
|
||||
.sortedBy { it.name }
|
||||
.forEachIndexed { index, entry -> map.put(entry.name, index) }
|
||||
return map
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-18
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.backend.konan.lower.ExpectDeclarationsRemoving
|
||||
import org.jetbrains.kotlin.backend.konan.lower.FinallyBlocksLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.LateinitLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.SharedVariablesLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.VarargInjectionLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.loops.ForLoopsLowering
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
@@ -65,10 +64,6 @@ internal class KonanLower(val context: Context, val parentPhaser: PhaseManager)
|
||||
irModule.files.forEach(InteropLoweringPart1(context)::lower)
|
||||
}
|
||||
|
||||
phaser.phase(KonanPhase.LOWER_LATEINIT) {
|
||||
irModule.files.forEach(LateinitLowering(context)::lower)
|
||||
}
|
||||
|
||||
val symbolTable = context.ir.symbols.symbolTable
|
||||
|
||||
do {
|
||||
@@ -82,6 +77,9 @@ internal class KonanLower(val context: Context, val parentPhaser: PhaseManager)
|
||||
}
|
||||
|
||||
private fun lowerFile(irFile: IrFile, phaser: PhaseManager) {
|
||||
phaser.phase(KonanPhase.LOWER_LATEINIT) {
|
||||
LateinitLowering(context).lower(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_STRING_CONCAT) {
|
||||
StringConcatenationLowering(context).lower(irFile)
|
||||
}
|
||||
@@ -94,13 +92,6 @@ internal class KonanLower(val context: Context, val parentPhaser: PhaseManager)
|
||||
phaser.phase(KonanPhase.LOWER_ENUMS) {
|
||||
EnumClassLowering(context).run(irFile)
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: this is workaround for issue of unitialized parents in IrDeclaration,
|
||||
* the last one detected in [EnumClassLowering]. The issue appears in [DefaultArgumentStubGenerator].
|
||||
*/
|
||||
irFile.patchDeclarationParents()
|
||||
|
||||
phaser.phase(KonanPhase.LOWER_INITIALIZERS) {
|
||||
InitializersLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
@@ -113,12 +104,6 @@ internal class KonanLower(val context: Context, val parentPhaser: PhaseManager)
|
||||
phaser.phase(KonanPhase.LOWER_CALLABLES) {
|
||||
CallableReferenceLowering(context).lower(irFile)
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: this is workaround for issue of unitialized parents in IrDeclaration,
|
||||
* the last one detected in [CallableReferenceLowering]. The issue appears in [LocalDeclarationsLowering].
|
||||
*/
|
||||
irFile.patchDeclarationParents()
|
||||
phaser.phase(KonanPhase.LOWER_LOCAL_FUNCTIONS) {
|
||||
LocalDeclarationsLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
|
||||
+8
-28
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint
|
||||
import org.jetbrains.kotlin.backend.konan.lower.TestProcessor
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
|
||||
import org.jetbrains.kotlin.config.coroutinesPackageFqName
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
@@ -370,6 +369,9 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
|
||||
val getContinuation = symbolTable.referenceSimpleFunction(
|
||||
context.getInternalFunctions("getContinuation").single())
|
||||
|
||||
val returnIfSuspended = symbolTable.referenceSimpleFunction(
|
||||
context.getInternalFunctions("returnIfSuspended").single())
|
||||
|
||||
val konanSuspendCoroutineUninterceptedOrReturn = symbolTable.referenceSimpleFunction(
|
||||
context.getInternalFunctions("suspendCoroutineUninterceptedOrReturn").single())
|
||||
|
||||
@@ -435,10 +437,14 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
|
||||
} && !it.isExpect
|
||||
}
|
||||
|
||||
val isInitializedGetterDescriptor = isInitializedPropertyDescriptor.getter!!
|
||||
val isInitializedGetter = symbolTable.referenceSimpleFunction(isInitializedPropertyDescriptor.getter!!)
|
||||
|
||||
val kFunctionImpl = symbolTable.referenceClass(context.reflectionTypes.kFunctionImpl)
|
||||
|
||||
val kMutableProperty0 = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty0)
|
||||
val kMutableProperty1 = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty1)
|
||||
val kMutableProperty2 = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty2)
|
||||
|
||||
val kProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty0Impl)
|
||||
val kProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl)
|
||||
val kProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty2Impl)
|
||||
@@ -502,32 +508,6 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
|
||||
val topLevelSuite = getKonanTestClass("TopLevelSuite")
|
||||
val testFunctionKind = getKonanTestClass("TestFunctionKind")
|
||||
|
||||
val baseClassSuiteConstructor = baseClassSuite.descriptor.constructors.single {
|
||||
it.valueParameters.size == 2 &&
|
||||
KotlinBuiltIns.isString(it.valueParameters[0].type) && // name: String
|
||||
KotlinBuiltIns.isBoolean(it.valueParameters[1].type) // ignored: Boolean
|
||||
}
|
||||
|
||||
val topLevelSuiteConstructor = symbolTable.referenceConstructor(topLevelSuite.descriptor.constructors.single {
|
||||
it.valueParameters.size == 1 &&
|
||||
KotlinBuiltIns.isString(it.valueParameters[0].type) // name: String
|
||||
})
|
||||
|
||||
val topLevelSuiteRegisterFunction =
|
||||
getFunction(Name.identifier("registerFunction"), topLevelSuite.descriptor.defaultType) {
|
||||
it.valueParameters.size == 2 &&
|
||||
it.valueParameters[0].type == testFunctionKind.descriptor.defaultType && // kind: TestFunctionKind
|
||||
it.valueParameters[1].type.isFunctionType // function: () -> Unit
|
||||
}
|
||||
|
||||
val topLevelSuiteRegisterTestCase =
|
||||
getFunction(Name.identifier("registerTestCase"), topLevelSuite.descriptor.defaultType) {
|
||||
it.valueParameters.size == 3 &&
|
||||
KotlinBuiltIns.isString(it.valueParameters[0].type) && // name: String
|
||||
it.valueParameters[1].type.isFunctionType && // function: () -> Unit
|
||||
KotlinBuiltIns.isBoolean(it.valueParameters[2].type) // ignored: Boolean
|
||||
}
|
||||
|
||||
private val testFunctionKindCache = mutableMapOf<TestProcessor.FunctionKind, IrEnumEntrySymbol>()
|
||||
fun getTestFunctionKind(kind: TestProcessor.FunctionKind): IrEnumEntrySymbol = testFunctionKindCache.getOrPut(kind) {
|
||||
symbolTable.referenceEnumEntry(testFunctionKind.descriptor.unsubstitutedMemberScope.getContributedClassifier(
|
||||
|
||||
+21
-35
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
import org.jetbrains.kotlin.backend.common.AbstractValueUsageTransformer
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.atMostOne
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.target
|
||||
@@ -15,9 +17,7 @@ import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.containsNull
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isOverridable
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isSuspend
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
@@ -67,17 +68,17 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
||||
}
|
||||
}
|
||||
|
||||
private var currentFunctionDescriptor: IrFunction? = null
|
||||
private var currentFunction: IrFunction? = null
|
||||
|
||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
currentFunctionDescriptor = declaration
|
||||
currentFunction = declaration
|
||||
val result = super.visitFunction(declaration)
|
||||
currentFunctionDescriptor = null
|
||||
currentFunction = null
|
||||
return result
|
||||
}
|
||||
|
||||
override fun IrExpression.useAsReturnValue(returnTarget: IrReturnTargetSymbol): IrExpression = when (returnTarget) {
|
||||
is IrSimpleFunctionSymbol -> if (returnTarget.owner.isSuspend && returnTarget == currentFunctionDescriptor?.symbol) {
|
||||
is IrSimpleFunctionSymbol -> if (returnTarget.owner.isSuspend && returnTarget == currentFunction?.symbol) {
|
||||
this.useAs(irBuiltIns.anyNType)
|
||||
} else {
|
||||
this.useAs(returnTarget.owner.returnType)
|
||||
@@ -389,6 +390,7 @@ private class InlineClassTransformer(private val context: Context) : IrBuildingT
|
||||
}
|
||||
|
||||
(irConstructor.body as IrBlockBody).statements.forEach { statement ->
|
||||
statement.setDeclarationsParent(result)
|
||||
+statement.transform(object : IrElementTransformerVoid() {
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||
expression.transformChildrenVoid()
|
||||
@@ -435,38 +437,22 @@ private val Context.getLoweredInlineClassConstructor: (IrConstructor) -> IrSimpl
|
||||
require(irConstructor.constructedClass.isInlined())
|
||||
require(!irConstructor.isPrimary)
|
||||
|
||||
val descriptor = SimpleFunctionDescriptorImpl.create(
|
||||
irConstructor.descriptor.containingDeclaration,
|
||||
irConstructor.descriptor.annotations,
|
||||
Name.special("<constructor>"),
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
irConstructor.descriptor.source
|
||||
)
|
||||
|
||||
val parameterDescriptors = irConstructor.descriptor.valueParameters.map {
|
||||
it.copy(descriptor, it.name, it.index)
|
||||
}
|
||||
|
||||
descriptor.initialize(
|
||||
null,
|
||||
null,
|
||||
emptyList(),
|
||||
parameterDescriptors,
|
||||
irConstructor.descriptor.returnType,
|
||||
Modality.FINAL,
|
||||
irConstructor.visibility
|
||||
)
|
||||
|
||||
val descriptor = WrappedSimpleFunctionDescriptor(irConstructor.descriptor.annotations, irConstructor.descriptor.source)
|
||||
IrFunctionImpl(
|
||||
irConstructor.startOffset,
|
||||
irConstructor.endOffset,
|
||||
irConstructor.startOffset, irConstructor.endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
descriptor,
|
||||
irConstructor.returnType
|
||||
IrSimpleFunctionSymbolImpl(descriptor),
|
||||
Name.special("<constructor>"),
|
||||
irConstructor.visibility,
|
||||
Modality.FINAL,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = false,
|
||||
returnType = irConstructor.returnType
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
parent = irConstructor.parent
|
||||
irConstructor.valueParameters.mapTo(this.valueParameters) {
|
||||
it.copy(this.descriptor.valueParameters[it.index])
|
||||
}
|
||||
irConstructor.valueParameters.mapTo(valueParameters) { it.copyTo(this) }
|
||||
}
|
||||
}
|
||||
+34
-46
@@ -7,15 +7,14 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -26,6 +25,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isNullableAny
|
||||
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
||||
@@ -64,54 +65,41 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
|
||||
|
||||
val job = expression.getValueArgument(3) as IrFunctionReference
|
||||
val jobFunction = (job.symbol as IrSimpleFunctionSymbol).owner
|
||||
val jobDescriptor = job.descriptor
|
||||
val arg = jobDescriptor.valueParameters[0]
|
||||
|
||||
if (!::runtimeJobFunction.isInitialized) {
|
||||
val runtimeJobDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
jobDescriptor.containingDeclaration,
|
||||
jobDescriptor.annotations,
|
||||
jobDescriptor.name,
|
||||
jobDescriptor.kind,
|
||||
jobDescriptor.source
|
||||
val arg = jobFunction.valueParameters[0]
|
||||
val startOffset = jobFunction.startOffset
|
||||
val endOffset = jobFunction.endOffset
|
||||
runtimeJobFunction = WrappedSimpleFunctionDescriptor().let {
|
||||
IrFunctionImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrSimpleFunctionSymbolImpl(it),
|
||||
jobFunction.name,
|
||||
jobFunction.visibility,
|
||||
jobFunction.modality,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = false,
|
||||
returnType = context.irBuiltIns.anyNType
|
||||
).apply {
|
||||
initialize(
|
||||
null,
|
||||
null,
|
||||
emptyList(),
|
||||
listOf(ValueParameterDescriptorImpl(
|
||||
containingDeclaration = this,
|
||||
original = null,
|
||||
index = 0,
|
||||
annotations = Annotations.EMPTY,
|
||||
name = arg.name,
|
||||
outType = nullableAnyType,
|
||||
declaresDefaultValue = arg.declaresDefaultValue(),
|
||||
isCrossinline = arg.isCrossinline,
|
||||
isNoinline = arg.isNoinline,
|
||||
varargElementType = arg.varargElementType,
|
||||
source = arg.source
|
||||
)),
|
||||
nullableAnyType,
|
||||
jobDescriptor.modality,
|
||||
jobDescriptor.visibility
|
||||
)
|
||||
it.bind(this)
|
||||
}
|
||||
}
|
||||
|
||||
runtimeJobFunction = IrFunctionImpl(
|
||||
jobFunction.startOffset,
|
||||
jobFunction.endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
runtimeJobDescriptor,
|
||||
context.irBuiltIns.anyNType
|
||||
).also {
|
||||
it.valueParameters += IrValueParameterImpl(
|
||||
it.startOffset,
|
||||
it.endOffset,
|
||||
runtimeJobFunction.valueParameters += WrappedValueParameterDescriptor().let {
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
it.descriptor.valueParameters.single(),
|
||||
context.irBuiltIns.anyNType,
|
||||
null
|
||||
)
|
||||
IrValueParameterSymbolImpl(it),
|
||||
arg.name,
|
||||
arg.index,
|
||||
type = context.irBuiltIns.anyNType,
|
||||
varargElementType = null,
|
||||
isCrossinline = arg.isCrossinline,
|
||||
isNoinline = arg.isNoinline
|
||||
).apply { it.bind(this) }
|
||||
}
|
||||
}
|
||||
val overriddenJobDescriptor = OverriddenFunctionDescriptor(jobFunction, runtimeJobFunction)
|
||||
|
||||
+149
-244
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
@@ -15,14 +17,7 @@ import org.jetbrains.kotlin.backend.common.push
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isFunctionOrKFunctionType
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
@@ -32,9 +27,8 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
@@ -42,8 +36,6 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
|
||||
internal class CallableReferenceLowering(val context: Context): FileLoweringPass {
|
||||
|
||||
@@ -108,12 +100,9 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
}
|
||||
|
||||
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 loweredFunctionReference = FunctionReferenceBuilder(parent, expression).build()
|
||||
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol,
|
||||
expression.startOffset, expression.endOffset)
|
||||
return irBuilder.irBlock(expression) {
|
||||
+loweredFunctionReference.functionReferenceClass
|
||||
+irCall(loweredFunctionReference.functionReferenceConstructor.symbol).apply {
|
||||
@@ -138,34 +127,64 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
|
||||
private val getContinuationSymbol = symbols.getContinuation
|
||||
|
||||
private inner class FunctionReferenceBuilder(val containingDeclaration: DeclarationDescriptor,
|
||||
val parent: IrDeclarationParent,
|
||||
private inner class FunctionReferenceBuilder(val parent: IrDeclarationParent,
|
||||
val functionReference: IrFunctionReference) {
|
||||
|
||||
private val functionDescriptor = functionReference.descriptor.original
|
||||
private val irFunction = functionReference.symbol.owner
|
||||
private val functionParameters = irFunction.explicitParameters
|
||||
private val startOffset = functionReference.startOffset
|
||||
private val endOffset = functionReference.endOffset
|
||||
private val referencedFunction = functionReference.symbol.owner
|
||||
private val functionParameters = referencedFunction.explicitParameters
|
||||
private val boundFunctionParameters = functionReference.getArgumentsWithIr().map { it.first }
|
||||
private val unboundFunctionParameters = functionParameters - boundFunctionParameters
|
||||
|
||||
private lateinit var functionReferenceClassDescriptor: ClassDescriptorImpl
|
||||
private lateinit var functionReferenceClass: IrClassImpl
|
||||
private lateinit var functionReferenceThis: IrValueParameterSymbol
|
||||
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrField>
|
||||
private val typeArgumentsMap = referencedFunction.typeParameters.associate { typeParam ->
|
||||
typeParam.symbol to functionReference.getTypeArgument(typeParam.index)!!
|
||||
}
|
||||
|
||||
private val functionReferenceClass = WrappedClassDescriptor().let {
|
||||
IrClassImpl(
|
||||
startOffset,endOffset,
|
||||
DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
IrClassSymbolImpl(it),
|
||||
"${referencedFunction.name}\$FUNCTION_REFERENCE\$${context.functionReferenceCount++}".synthesizedName,
|
||||
ClassKind.CLASS,
|
||||
Visibilities.PRIVATE,
|
||||
Modality.FINAL,
|
||||
isCompanion = false,
|
||||
isInner = false,
|
||||
isData = false,
|
||||
isExternal = false,
|
||||
isInline = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = this@FunctionReferenceBuilder.parent
|
||||
createParameterDeclarations()
|
||||
}
|
||||
}
|
||||
|
||||
private val functionReferenceThis = functionReferenceClass.thisReceiver!!
|
||||
|
||||
private val argumentToPropertiesMap = boundFunctionParameters.associate {
|
||||
it to createField(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
it.type,
|
||||
it.name,
|
||||
isMutable = false,
|
||||
owner = functionReferenceClass
|
||||
)
|
||||
}
|
||||
|
||||
private val kFunctionImplSymbol = symbols.kFunctionImpl
|
||||
|
||||
private val kFunctionImplConstructorSymbol = kFunctionImplSymbol.constructors.single()
|
||||
|
||||
val isKFunction = functionReference.type.classifierOrNull?.descriptor
|
||||
?.getFunctionalClassKind() == FunctionClassDescriptor.Kind.KFunction
|
||||
val isKFunction = functionReference.type.isKFunction()
|
||||
|
||||
fun build(): BuiltFunctionReference {
|
||||
val startOffset = functionReference.startOffset
|
||||
val endOffset = functionReference.endOffset
|
||||
|
||||
val superClassType = if (isKFunction) {
|
||||
kFunctionImplSymbol.typeWith(irFunction.returnType)
|
||||
kFunctionImplSymbol.typeWith(referencedFunction.returnType)
|
||||
} else {
|
||||
irBuiltIns.anyType
|
||||
}
|
||||
@@ -181,7 +200,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
}
|
||||
|
||||
val functionParameterTypes = unboundFunctionParameters.map { it.type }
|
||||
val functionClassTypeParameters = functionParameterTypes + irFunction.returnType
|
||||
val functionClassTypeParameters = functionParameterTypes + referencedFunction.returnType
|
||||
superTypes += functionIrClass.symbol.typeWith(functionClassTypeParameters)
|
||||
|
||||
var suspendFunctionIrClass: IrClass? = null
|
||||
@@ -190,136 +209,65 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
lastParameterType as IrSimpleType
|
||||
// If the last parameter is Continuation<> inherit from SuspendFunction.
|
||||
suspendFunctionIrClass = symbols.suspendFunctions[numberOfParameters - 1].owner
|
||||
var suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) +
|
||||
val suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) +
|
||||
(lastParameterType.arguments.single().typeOrNull ?: irBuiltIns.anyNType)
|
||||
superTypes += suspendFunctionIrClass.symbol.typeWith(suspendFunctionClassTypeParameters)
|
||||
}
|
||||
|
||||
functionReferenceClassDescriptor = object : ClassDescriptorImpl(
|
||||
/* containingDeclaration = */ containingDeclaration,
|
||||
/* name = */ "${functionDescriptor.name}\$FUNCTION_REFERENCE\$${context.functionReferenceCount++}".synthesizedName,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* kind = */ ClassKind.CLASS,
|
||||
/* superTypes = */ superTypes.map { it.toKotlinType() },
|
||||
/* source = */ SourceElement.NO_SOURCE,
|
||||
/* isExternal = */ false,
|
||||
/* storageManager = */ LockBasedStorageManager.NO_LOCKS
|
||||
) {
|
||||
override fun getVisibility() = Visibilities.PRIVATE
|
||||
}
|
||||
functionReferenceClass = IrClassImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
descriptor = functionReferenceClassDescriptor
|
||||
)
|
||||
functionReferenceClass.parent = this.parent
|
||||
val constructor = buildConstructor()
|
||||
buildInvokeMethod(functionIrClass.simpleFunctions().single { it.name.asString() == "invoke" })
|
||||
suspendFunctionIrClass?.let { buildInvokeMethod(it.simpleFunctions().single { it.name.asString() == "invoke" }) }
|
||||
|
||||
functionReferenceClass.superTypes += superTypes
|
||||
functionReferenceClass.addFakeOverrides()
|
||||
|
||||
val constructorBuilder = createConstructorBuilder()
|
||||
|
||||
val invokeFunctionSymbol =
|
||||
functionIrClass.simpleFunctions().single { it.name.asString() == "invoke" }.symbol
|
||||
val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionSymbol, functionReferenceClass)
|
||||
|
||||
var suspendInvokeMethodBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>? = null
|
||||
if (suspendFunctionIrClass != null) {
|
||||
val suspendInvokeFunctionSymbol =
|
||||
suspendFunctionIrClass.simpleFunctions().single { it.name.asString() == "invoke" }.symbol
|
||||
suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionSymbol, functionReferenceClass)
|
||||
}
|
||||
|
||||
val memberScope = stub<MemberScope>("callable reference class")
|
||||
functionReferenceClassDescriptor.initialize(
|
||||
memberScope, setOf(constructorBuilder.symbol.descriptor), null)
|
||||
|
||||
functionReferenceClass.createParameterDeclarations()
|
||||
|
||||
functionReferenceThis = functionReferenceClass.thisReceiver!!.symbol
|
||||
|
||||
constructorBuilder.initialize()
|
||||
functionReferenceClass.addChild(constructorBuilder.ir)
|
||||
|
||||
invokeMethodBuilder.initialize()
|
||||
functionReferenceClass.addChild(invokeMethodBuilder.ir)
|
||||
|
||||
suspendInvokeMethodBuilder?.let {
|
||||
it.initialize()
|
||||
functionReferenceClass.addChild(it.ir)
|
||||
}
|
||||
|
||||
functionReferenceClass.setSuperSymbolsAndAddFakeOverrides(superTypes)
|
||||
|
||||
return BuiltFunctionReference(functionReferenceClass, constructorBuilder.ir)
|
||||
return BuiltFunctionReference(functionReferenceClass, constructor)
|
||||
}
|
||||
|
||||
private fun createConstructorBuilder()
|
||||
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
||||
private fun buildConstructor() = WrappedClassConstructorDescriptor().let {
|
||||
IrConstructorImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
IrConstructorSymbolImpl(it),
|
||||
Name.special("<init>"),
|
||||
Visibilities.PUBLIC,
|
||||
functionReferenceClass.defaultType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isPrimary = true
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = functionReferenceClass
|
||||
functionReferenceClass.declarations += this
|
||||
|
||||
override fun buildSymbol() = IrConstructorSymbolImpl(
|
||||
ClassConstructorDescriptorImpl.create(
|
||||
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* isPrimary = */ false,
|
||||
/* source = */ SourceElement.NO_SOURCE
|
||||
)
|
||||
)
|
||||
|
||||
override fun doInitialize() {
|
||||
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||
val constructorParameters = boundFunctionParameters.mapIndexed { index, parameter ->
|
||||
parameter.descriptor.copyAsValueParameter(descriptor, index)
|
||||
}
|
||||
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
||||
descriptor.returnType = functionReferenceClassDescriptor.defaultType
|
||||
}
|
||||
|
||||
override fun buildIr(): IrConstructor {
|
||||
argumentToPropertiesMap = boundFunctionParameters.associate {
|
||||
it.descriptor to buildField(it.name, it.type, false)
|
||||
boundFunctionParameters.mapIndexedTo(valueParameters) { index, parameter ->
|
||||
parameter.copyTo(this, DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, index,
|
||||
type = parameter.type.substitute(typeArgumentsMap))
|
||||
}
|
||||
|
||||
val startOffset = functionReference.startOffset
|
||||
val endOffset = functionReference.endOffset
|
||||
return IrConstructorImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
symbol = symbol,
|
||||
returnType = functionReferenceClass.defaultType
|
||||
).apply {
|
||||
|
||||
val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset)
|
||||
|
||||
boundFunctionParameters.mapIndexedTo(this.valueParameters) { index, parameter ->
|
||||
parameter.copy(descriptor.valueParameters[index])
|
||||
body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody {
|
||||
if (!isKFunction)
|
||||
+irDelegatingConstructorCall(irBuiltIns.anyClass.owner.constructors.single())
|
||||
else +irDelegatingConstructorCall(kFunctionImplConstructorSymbol.owner).apply {
|
||||
val stringType = irBuiltIns.stringType
|
||||
val name = IrConstImpl(startOffset, endOffset, stringType,
|
||||
IrConstKind.String, referencedFunction.name.asString())
|
||||
putValueArgument(0, name)
|
||||
val fqName = IrConstImpl(startOffset, endOffset, stringType, IrConstKind.String,
|
||||
(functionReference.symbol.owner).fullName)
|
||||
putValueArgument(1, fqName)
|
||||
val bound = IrConstImpl.boolean(startOffset, endOffset, context.irBuiltIns.booleanType,
|
||||
boundFunctionParameters.isNotEmpty())
|
||||
putValueArgument(2, bound)
|
||||
val needReceiver = boundFunctionParameters.singleOrNull()?.descriptor is ReceiverParameterDescriptor
|
||||
val receiver = if (needReceiver) irGet(valueParameters.single()) else irNull()
|
||||
putValueArgument(3, receiver)
|
||||
putValueArgument(4, irKType(this@CallableReferenceLowering.context, referencedFunction.returnType))
|
||||
}
|
||||
|
||||
body = irBuilder.irBlockBody {
|
||||
if (!isKFunction) +irDelegatingConstructorCall(irBuiltIns.anyClass.owner.constructors.single())
|
||||
else +IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
kFunctionImplConstructorSymbol, kFunctionImplConstructorSymbol.descriptor, 0).apply {
|
||||
val stringType = irBuiltIns.stringType
|
||||
val name = IrConstImpl(startOffset, endOffset, stringType,
|
||||
IrConstKind.String, functionDescriptor.name.asString())
|
||||
putValueArgument(0, name)
|
||||
val fqName = IrConstImpl(startOffset, endOffset, stringType, IrConstKind.String,
|
||||
(functionReference.symbol.owner).fullName)
|
||||
putValueArgument(1, fqName)
|
||||
val bound = IrConstImpl.boolean(startOffset, endOffset, context.irBuiltIns.booleanType,
|
||||
boundFunctionParameters.isNotEmpty())
|
||||
putValueArgument(2, bound)
|
||||
val needReceiver = boundFunctionParameters.singleOrNull()?.descriptor is ReceiverParameterDescriptor
|
||||
val receiver = if (needReceiver) irGet(valueParameters.single()) else irNull()
|
||||
putValueArgument(3, receiver)
|
||||
putValueArgument(4, irKType(this@CallableReferenceLowering.context, irFunction.returnType))
|
||||
}
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, irBuiltIns.unitType)
|
||||
// Save all arguments to fields.
|
||||
boundFunctionParameters.forEachIndexed { index, parameter ->
|
||||
+irSetField(irGet(functionReferenceThis.owner), argumentToPropertiesMap[parameter.descriptor]!!, irGet(valueParameters[index]))
|
||||
}
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, irBuiltIns.unitType)
|
||||
// Save all arguments to fields.
|
||||
boundFunctionParameters.forEachIndexed { index, parameter ->
|
||||
+irSetField(irGet(functionReferenceThis), argumentToPropertiesMap[parameter]!!, irGet(valueParameters[index]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -328,108 +276,65 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
private val IrFunction.fullName: String
|
||||
get() = parent.fqNameSafe.child(Name.identifier(functionName)).asString()
|
||||
|
||||
private fun createInvokeMethodBuilder(superFunctionSymbol: IrSimpleFunctionSymbol, parent: IrClass)
|
||||
= object : SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||
private fun buildInvokeMethod(superFunction: IrSimpleFunction) = WrappedSimpleFunctionDescriptor().let {
|
||||
IrFunctionImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
IrSimpleFunctionSymbolImpl(it),
|
||||
superFunction.name,
|
||||
Visibilities.PRIVATE,
|
||||
Modality.FINAL,
|
||||
referencedFunction.returnType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = superFunction.isSuspend
|
||||
).apply {
|
||||
it.bind(this)
|
||||
val function = this
|
||||
parent = functionReferenceClass
|
||||
functionReferenceClass.declarations += function
|
||||
|
||||
val superFunctionDescriptor: FunctionDescriptor = superFunctionSymbol.descriptor
|
||||
this.createDispatchReceiverParameter()
|
||||
|
||||
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||
SimpleFunctionDescriptorImpl.create(
|
||||
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* name = */ Name.identifier("invoke"),
|
||||
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/* source = */ SourceElement.NO_SOURCE
|
||||
)
|
||||
)
|
||||
|
||||
override fun doInitialize() {
|
||||
val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl
|
||||
val valueParameters = superFunctionDescriptor.valueParameters
|
||||
.map { it.copyAsValueParameter(descriptor, it.index) }
|
||||
|
||||
descriptor.initialize(
|
||||
/* receiverParameterType = */ null,
|
||||
/* dispatchReceiverParameter = */ functionReferenceClassDescriptor.thisAsReceiverParameter,
|
||||
/* typeParameters = */ emptyList(),
|
||||
/* unsubstitutedValueParameters = */ valueParameters,
|
||||
/* unsubstitutedReturnType = */ superFunctionDescriptor.returnType,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PRIVATE).apply {
|
||||
overriddenDescriptors += superFunctionDescriptor
|
||||
isSuspend = superFunctionDescriptor.isSuspend
|
||||
superFunction.valueParameters.mapIndexedTo(valueParameters) { index, parameter ->
|
||||
parameter.copyTo(this, DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, index,
|
||||
type = parameter.type.substitute(typeArgumentsMap))
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildIr(): IrSimpleFunction {
|
||||
val startOffset = functionReference.startOffset
|
||||
val endOffset = functionReference.endOffset
|
||||
val ourSymbol = symbol
|
||||
return IrFunctionImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
symbol = ourSymbol,
|
||||
returnType = superFunctionSymbol.owner.returnType // FIXME: substitute
|
||||
).apply {
|
||||
overriddenSymbols += superFunction.symbol
|
||||
|
||||
val function = this
|
||||
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
||||
|
||||
this.parent = parent
|
||||
|
||||
this.createDispatchReceiverParameter()
|
||||
|
||||
superFunctionSymbol.owner.valueParameters.mapTo(this.valueParameters) {
|
||||
it.copy(descriptor.valueParameters[it.index]) // FIXME: substitute
|
||||
}
|
||||
|
||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||
+irReturn(
|
||||
irCall(functionReference.symbol).apply {
|
||||
var unboundIndex = 0
|
||||
val unboundArgsSet = unboundFunctionParameters.toSet()
|
||||
functionParameters.forEach {
|
||||
val argument =
|
||||
if (!unboundArgsSet.contains(it))
|
||||
// Bound parameter - read from field.
|
||||
irGetField(
|
||||
irGet(function.dispatchReceiverParameter!!),
|
||||
argumentToPropertiesMap[it.descriptor]!!
|
||||
)
|
||||
else {
|
||||
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
|
||||
// For suspend functions the last argument is continuation and it is implicit.
|
||||
irCall(getContinuationSymbol.owner,
|
||||
listOf(returnType))
|
||||
else
|
||||
irGet(valueParameters[unboundIndex++])
|
||||
}
|
||||
when (it) {
|
||||
irFunction.dispatchReceiverParameter -> dispatchReceiver = argument
|
||||
irFunction.extensionReceiverParameter -> extensionReceiver = argument
|
||||
else -> putValueArgument(it.index, argument)
|
||||
}
|
||||
body = context.createIrBuilder(function.symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset) {
|
||||
+irReturn(
|
||||
irCall(functionReference.symbol).apply {
|
||||
var unboundIndex = 0
|
||||
val unboundArgsSet = unboundFunctionParameters.toSet()
|
||||
for (parameter in functionParameters) {
|
||||
val argument =
|
||||
if (!unboundArgsSet.contains(parameter))
|
||||
// Bound parameter - read from field.
|
||||
irGetField(
|
||||
irGet(function.dispatchReceiverParameter!!),
|
||||
argumentToPropertiesMap[parameter]!!
|
||||
)
|
||||
else {
|
||||
if (function.isSuspend && unboundIndex == valueParameters.size)
|
||||
// For suspend functions the last argument is continuation and it is implicit.
|
||||
irCall(getContinuationSymbol.owner, listOf(returnType))
|
||||
else
|
||||
irGet(valueParameters[unboundIndex++])
|
||||
}
|
||||
when (parameter) {
|
||||
referencedFunction.dispatchReceiverParameter -> dispatchReceiver = argument
|
||||
referencedFunction.extensionReceiverParameter -> extensionReceiver = argument
|
||||
else -> putValueArgument(parameter.index, argument)
|
||||
}
|
||||
assert(unboundIndex == valueParameters.size, { "Not all arguments of <invoke> are used" })
|
||||
}
|
||||
)
|
||||
}
|
||||
assert(unboundIndex == valueParameters.size) { "Not all arguments of <invoke> are used" }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildField(name: Name, type: IrType, isMutable: Boolean): IrField = createField(
|
||||
functionReference.startOffset,
|
||||
functionReference.endOffset,
|
||||
type,
|
||||
name,
|
||||
isMutable,
|
||||
DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
functionReferenceClassDescriptor
|
||||
).also {
|
||||
functionReferenceClass.addChild(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+4
-5
@@ -57,12 +57,11 @@ internal class DataClassOperatorsLowering(val context: Context): FunctionLowerin
|
||||
extensionReceiver = argument
|
||||
}
|
||||
} else {
|
||||
val tmp = scope.createTemporaryVariable(argument)
|
||||
val call = irCall(newCallee, typeArguments).apply {
|
||||
extensionReceiver = irGet(tmp)
|
||||
}
|
||||
irBlock(argument) {
|
||||
+tmp
|
||||
val tmp = irTemporary(argument)
|
||||
val call = irCall(newCallee, typeArguments).apply {
|
||||
extensionReceiver = irGet(tmp)
|
||||
}
|
||||
+irIfThenElse(call.type,
|
||||
irEqeqeq(irGet(tmp), irNull()),
|
||||
if (isToString)
|
||||
|
||||
+2
-2
@@ -71,7 +71,7 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context,
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
(declaration.descriptor as WrappedPropertyDescriptor).bind(declaration)
|
||||
(declaration.descriptor as WrappedFieldDescriptor).bind(declaration)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context,
|
||||
WrappedClassDescriptor(descriptor.annotations, descriptor.source)
|
||||
|
||||
override fun remapDeclaredField(descriptor: PropertyDescriptor) =
|
||||
WrappedPropertyDescriptor(descriptor.annotations, descriptor.source)
|
||||
WrappedFieldDescriptor(descriptor.annotations, descriptor.source)
|
||||
|
||||
override fun remapDeclaredSimpleFunction(descriptor: FunctionDescriptor) =
|
||||
WrappedSimpleFunctionDescriptor(descriptor.annotations, descriptor.source)
|
||||
|
||||
+55
-58
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedFieldDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
@@ -19,7 +20,6 @@ import org.jetbrains.kotlin.backend.konan.SYNTHETIC_OFFSET
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
||||
@@ -33,19 +33,15 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.types.typeWith
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.replace
|
||||
|
||||
internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass {
|
||||
private var tempIndex = 0
|
||||
@@ -59,7 +55,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
|
||||
val classSymbol =
|
||||
if (isLocal) {
|
||||
assert(receiverTypes.isEmpty(), { "Local delegated property cannot have explicit receiver" })
|
||||
assert(receiverTypes.isEmpty()) { "Local delegated property cannot have explicit receiver" }
|
||||
when {
|
||||
isMutable -> symbols.kLocalDelegatedMutablePropertyImpl
|
||||
else -> symbols.kLocalDelegatedPropertyImpl
|
||||
@@ -87,29 +83,37 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
return classSymbol.constructors.single() to arguments
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.replace(vararg type: KotlinType): SimpleType {
|
||||
return this.defaultType.replace(type.map(::TypeProjectionImpl))
|
||||
}
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
val kProperties = mutableMapOf<VariableDescriptorWithAccessors, Pair<IrExpression, Int>>()
|
||||
|
||||
val arrayClass = context.ir.symbols.array.owner
|
||||
|
||||
val arrayItemGetter = arrayClass.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||
val arrayItemGetter = arrayClass.functions.single { it.name == Name.identifier("get") }
|
||||
|
||||
val anyType = context.irBuiltIns.anyType
|
||||
val kPropertyImplType = context.ir.symbols.kProperty1Impl.typeWith(anyType, anyType)
|
||||
|
||||
val kPropertiesFieldType: IrType = context.ir.symbols.array.typeWith(kPropertyImplType)
|
||||
|
||||
val kPropertiesField = IrFieldImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
|
||||
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION,
|
||||
createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor,
|
||||
kPropertiesFieldType.toKotlinType()
|
||||
),
|
||||
kPropertiesFieldType
|
||||
)
|
||||
val kPropertiesField = WrappedFieldDescriptor(
|
||||
Annotations.create(listOf(AnnotationDescriptorImpl(context.ir.symbols.sharedImmutable.defaultType,
|
||||
emptyMap(), SourceElement.NO_SOURCE)))
|
||||
).let {
|
||||
IrFieldImpl(
|
||||
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
|
||||
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION,
|
||||
IrFieldSymbolImpl(it),
|
||||
"KPROPERTIES".synthesizedName,
|
||||
kPropertiesFieldType,
|
||||
Visibilities.PRIVATE,
|
||||
isFinal = true,
|
||||
isExternal = false,
|
||||
isStatic = true
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = irFile
|
||||
}
|
||||
}
|
||||
|
||||
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||
|
||||
@@ -135,18 +139,20 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset)
|
||||
irBuilder.run {
|
||||
val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null }
|
||||
if (receiversCount == 1) // Has receiver.
|
||||
return createKProperty(expression, this)
|
||||
else if (receiversCount == 2)
|
||||
throw AssertionError("Callable reference to properties with two receivers is not allowed: ${expression.descriptor}")
|
||||
else { // Cache KProperties with no arguments.
|
||||
val field = kProperties.getOrPut(expression.descriptor) {
|
||||
createKProperty(expression, this) to kProperties.size
|
||||
}
|
||||
return when (receiversCount) {
|
||||
1 -> createKProperty(expression, this) // Has receiver.
|
||||
|
||||
return irCall(arrayItemGetter).apply {
|
||||
dispatchReceiver = irGetField(null, kPropertiesField)
|
||||
putValueArgument(0, irInt(field.second))
|
||||
2 -> error("Callable reference to properties with two receivers is not allowed: ${expression.descriptor}")
|
||||
|
||||
else -> { // Cache KProperties with no arguments.
|
||||
val field = kProperties.getOrPut(expression.descriptor) {
|
||||
createKProperty(expression, this) to kProperties.size
|
||||
}
|
||||
|
||||
irCall(arrayItemGetter).apply {
|
||||
dispatchReceiver = irGetField(null, kPropertiesField)
|
||||
putValueArgument(0, irInt(field.second))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,11 +194,8 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
// TODO: move to object for lazy initialization.
|
||||
irFile.declarations.add(0, kPropertiesField.apply {
|
||||
initializer = IrExpressionBodyImpl(startOffset, endOffset,
|
||||
context.createArrayOfExpression(kPropertyImplType, initializers,
|
||||
startOffset, endOffset))
|
||||
context.createArrayOfExpression(startOffset, endOffset, kPropertyImplType, initializers))
|
||||
})
|
||||
|
||||
kPropertiesField.parent = irFile
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,15 +238,18 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
type = getterKFunctionType,
|
||||
symbol = expression.getter!!,
|
||||
descriptor = getter.descriptor,
|
||||
typeArgumentsCount = 0
|
||||
typeArgumentsCount = getter.typeParameters.size,
|
||||
valueArgumentsCount = getter.valueParameters.size
|
||||
).apply {
|
||||
this.dispatchReceiver = dispatchReceiver?.let { irGet(it) }
|
||||
this.extensionReceiver = extensionReceiver?.let { irGet(it) }
|
||||
for (index in 0 until expression.typeArgumentsCount)
|
||||
putTypeArgument(index, expression.getTypeArgument(index))
|
||||
}
|
||||
}
|
||||
|
||||
val setterCallableReference = expression.setter?.owner?.let {
|
||||
if (!isKMutablePropertyType(expression.type.toKotlinType())) null
|
||||
val setterCallableReference = expression.setter?.owner?.let { setter ->
|
||||
if (!isKMutablePropertyType(expression.type)) null
|
||||
else {
|
||||
val setterKFunctionType = this@PropertyDelegationLowering.context.ir.symbols.getKFunctionType(
|
||||
context.irBuiltIns.unitType,
|
||||
@@ -254,11 +260,14 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
endOffset = endOffset,
|
||||
type = setterKFunctionType,
|
||||
symbol = expression.setter!!,
|
||||
descriptor = it.descriptor,
|
||||
typeArgumentsCount = 0
|
||||
descriptor = setter.descriptor,
|
||||
typeArgumentsCount = setter.typeParameters.size,
|
||||
valueArgumentsCount = setter.valueParameters.size
|
||||
).apply {
|
||||
this.dispatchReceiver = dispatchReceiver?.let { irGet(it) }
|
||||
this.extensionReceiver = extensionReceiver?.let { irGet(it) }
|
||||
for (index in 0 until expression.typeArgumentsCount)
|
||||
putTypeArgument(index, expression.getTypeArgument(index))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,32 +306,20 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
}
|
||||
}
|
||||
|
||||
private fun isKMutablePropertyType(type: KotlinType): Boolean {
|
||||
val arguments = type.arguments
|
||||
val expectedClassDescriptor = when (arguments.size) {
|
||||
private fun isKMutablePropertyType(type: IrType): Boolean {
|
||||
if (type !is IrSimpleType) return false
|
||||
val expectedClass = when (type.arguments.size) {
|
||||
0 -> return false
|
||||
1 -> context.reflectionTypes.kMutableProperty0
|
||||
2 -> context.reflectionTypes.kMutableProperty1
|
||||
3 -> context.reflectionTypes.kMutableProperty2
|
||||
1 -> context.ir.symbols.kMutableProperty0
|
||||
2 -> context.ir.symbols.kMutableProperty1
|
||||
3 -> context.ir.symbols.kMutableProperty2
|
||||
else -> throw AssertionError("More than 2 receivers is not allowed")
|
||||
}
|
||||
return type == expectedClassDescriptor.defaultType.replace(arguments)
|
||||
return type.classifier == expectedClass
|
||||
}
|
||||
|
||||
private object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION :
|
||||
IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION")
|
||||
|
||||
private fun createKPropertiesFieldDescriptor(containingDeclaration: DeclarationDescriptor, fieldType: KotlinType): PropertyDescriptorImpl {
|
||||
return PropertyDescriptorImpl.create(containingDeclaration,
|
||||
Annotations.create(listOf(AnnotationDescriptorImpl(context.ir.symbols.sharedImmutable.defaultType,
|
||||
emptyMap(), SourceElement.NO_SOURCE))), Modality.FINAL, Visibilities.PRIVATE,
|
||||
false, "KPROPERTIES".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE,
|
||||
false, false, false, false, false, false).apply {
|
||||
|
||||
this.setType(fieldType, emptyList(), null, null)
|
||||
this.initialize(null, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrBuilderWithScope.irKType(context: KonanBackendContext, type: IrType): IrExpression {
|
||||
|
||||
+218
-224
@@ -8,7 +8,11 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||
@@ -17,8 +21,6 @@ import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -28,14 +30,17 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin.ARGUMENTS_REORDERIN
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.typeWith
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
|
||||
internal class EnumSyntheticFunctionsBuilder(val context: Context) {
|
||||
fun buildValuesExpression(startOffset: Int, endOffset: Int,
|
||||
@@ -105,9 +110,7 @@ internal class EnumUsageLowering(val context: Context)
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val descriptor = expression.descriptor as? FunctionDescriptor
|
||||
?: return expression
|
||||
if (descriptor.original != enumValuesDescriptor && descriptor.original != enumValueOfDescriptor)
|
||||
if (expression.symbol != enumValuesSymbol && expression.symbol != enumValueOfSymbol)
|
||||
return expression
|
||||
|
||||
val irClassSymbol = expression.getTypeArgument(0)!!.classifierOrNull as? IrClassSymbol
|
||||
@@ -119,19 +122,17 @@ internal class EnumUsageLowering(val context: Context)
|
||||
|
||||
assert (irClass.kind == ClassKind.ENUM_CLASS)
|
||||
|
||||
return if (descriptor.original == enumValuesDescriptor) {
|
||||
enumSyntheticFunctionsBuilder.buildValuesExpression(expression.startOffset, expression.endOffset, irClass)
|
||||
} else {
|
||||
val value = expression.getValueArgument(0)!!
|
||||
enumSyntheticFunctionsBuilder.buildValueOfExpression(expression.startOffset, expression.endOffset, irClass, value)
|
||||
}
|
||||
return if (expression.symbol == enumValuesSymbol) {
|
||||
enumSyntheticFunctionsBuilder.buildValuesExpression(expression.startOffset, expression.endOffset, irClass)
|
||||
} else {
|
||||
val value = expression.getValueArgument(0)!!
|
||||
enumSyntheticFunctionsBuilder.buildValueOfExpression(expression.startOffset, expression.endOffset, irClass, value)
|
||||
}
|
||||
}
|
||||
|
||||
private val enumValueOfSymbol = context.ir.symbols.enumValueOf
|
||||
private val enumValueOfDescriptor = enumValueOfSymbol.descriptor
|
||||
|
||||
private val enumValuesSymbol = context.ir.symbols.enumValues
|
||||
private val enumValuesDescriptor = enumValuesSymbol.descriptor
|
||||
|
||||
private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClass: IrClass, name: Name): IrExpression {
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass)
|
||||
@@ -154,8 +155,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
override fun lower(irClass: IrClass) {
|
||||
val descriptor = irClass.descriptor
|
||||
if (descriptor.kind != ClassKind.ENUM_CLASS) return
|
||||
if (irClass.kind != ClassKind.ENUM_CLASS) return
|
||||
EnumClassTransformer(irClass).run()
|
||||
}
|
||||
|
||||
@@ -166,10 +166,9 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
private inner class EnumClassTransformer(val irClass: IrClass) {
|
||||
private val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(irClass)
|
||||
private val loweredEnumConstructors = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
||||
private val descriptorToIrConstructorWithDefaultArguments = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
||||
private val defaultEnumEntryConstructors = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
||||
private val loweredEnumConstructorParameters = mutableMapOf<ValueParameterDescriptor, ValueParameterDescriptor>()
|
||||
private val loweredEnumConstructors = mutableMapOf<IrConstructor, IrConstructor>()
|
||||
private val defaultEnumEntryConstructors = mutableMapOf<IrConstructor, IrConstructor>()
|
||||
private val loweredEnumConstructorParameters = mutableMapOf<IrValueParameter, IrValueParameter>()
|
||||
private val enumSyntheticFunctionsBuilder = EnumSyntheticFunctionsBuilder(context)
|
||||
|
||||
fun run() {
|
||||
@@ -177,9 +176,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
lowerEnumConstructors(irClass)
|
||||
lowerEnumEntriesClasses()
|
||||
val defaultClass = createDefaultClassForEnumEntries()
|
||||
lowerEnumClassBody()
|
||||
if (defaultClass != null)
|
||||
irClass.addChild(defaultClass)
|
||||
lowerEnumClassBody(defaultClass)
|
||||
createImplObject()
|
||||
}
|
||||
|
||||
@@ -225,48 +222,44 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
private fun createDefaultClassForEnumEntries(): IrClass? {
|
||||
if (!irClass.declarations.any({ it is IrEnumEntry && it.correspondingClass == null })) return null
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
val descriptor = irClass.descriptor
|
||||
val defaultClassDescriptor = ClassDescriptorImpl(descriptor, "DEFAULT".synthesizedName, Modality.FINAL,
|
||||
ClassKind.CLASS, listOf(descriptor.defaultType), SourceElement.NO_SOURCE, false, LockBasedStorageManager.NO_LOCKS)
|
||||
val defaultClass = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, defaultClassDescriptor)
|
||||
defaultClass.createParameterDeclarations()
|
||||
|
||||
|
||||
val constructors = mutableSetOf<ClassConstructorDescriptor>()
|
||||
|
||||
descriptor.constructors.forEach {
|
||||
val loweredEnumIrConstructor = loweredEnumConstructors[it]!!
|
||||
val loweredEnumConstructor = loweredEnumIrConstructor.descriptor
|
||||
|
||||
val constructor = defaultClass.addSimpleDelegatingConstructor(
|
||||
loweredEnumIrConstructor,
|
||||
context.irBuiltIns,
|
||||
DECLARATION_ORIGIN_ENUM
|
||||
)
|
||||
|
||||
val constructorDescriptor = constructor.descriptor
|
||||
constructors.add(constructorDescriptor)
|
||||
defaultEnumEntryConstructors.put(loweredEnumConstructor, constructor)
|
||||
|
||||
val irConstructor = descriptorToIrConstructorWithDefaultArguments[loweredEnumConstructor]
|
||||
if (irConstructor != null) {
|
||||
it.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
|
||||
val loweredArgument = loweredEnumConstructor.valueParameters[argument.loweredIndex()]
|
||||
val body = irConstructor.getDefault(loweredArgument)!!.deepCopyWithVariables()
|
||||
body.transformChildrenVoid(ParameterMapper(constructor))
|
||||
body.accept(SetDeclarationsParentVisitor, constructor)
|
||||
constructor.putDefault(constructorDescriptor.valueParameters[loweredArgument.index], body)
|
||||
}
|
||||
if (!irClass.declarations.any { it is IrEnumEntry && it.correspondingClass == null }) return null
|
||||
val defaultClass = WrappedClassDescriptor().let {
|
||||
IrClassImpl(
|
||||
irClass.startOffset, irClass.endOffset,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
IrClassSymbolImpl(it),
|
||||
"DEFAULT".synthesizedName,
|
||||
ClassKind.CLASS,
|
||||
Visibilities.PRIVATE,
|
||||
Modality.FINAL,
|
||||
isCompanion = false,
|
||||
isInner = false,
|
||||
isData = false,
|
||||
isExternal = false,
|
||||
isInline = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = irClass
|
||||
irClass.declarations += this
|
||||
createParameterDeclarations()
|
||||
}
|
||||
}
|
||||
|
||||
val memberScope = stub<MemberScope>("enum default class")
|
||||
defaultClassDescriptor.initialize(memberScope, constructors, null)
|
||||
for (superConstructor in irClass.constructors) {
|
||||
val constructor = defaultClass.addSimpleDelegatingConstructor(superConstructor, context.irBuiltIns)
|
||||
defaultEnumEntryConstructors[superConstructor] = constructor
|
||||
|
||||
defaultClass.setSuperSymbolsAndAddFakeOverrides(listOf(irClass.defaultType))
|
||||
for (parameter in constructor.valueParameters) {
|
||||
val defaultValue = superConstructor.valueParameters[parameter.index].defaultValue ?: continue
|
||||
val body = defaultValue.deepCopyWithVariables()
|
||||
body.transformChildrenVoid(ParameterMapper(superConstructor, constructor, false))
|
||||
body.patchDeclarationParents(constructor)
|
||||
parameter.defaultValue = body
|
||||
}
|
||||
}
|
||||
|
||||
defaultClass.superTypes += irClass.defaultType
|
||||
defaultClass.addFakeOverrides()
|
||||
|
||||
return defaultClass
|
||||
}
|
||||
@@ -302,39 +295,42 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
++i
|
||||
}
|
||||
|
||||
implObject.addChild(createSyntheticValuesPropertyDeclaration(enumEntries))
|
||||
implObject.addChild(createValuesPropertyInitializer(enumEntries))
|
||||
implObject.declarations += createSyntheticValuesPropertyDeclaration(enumEntries)
|
||||
implObject.declarations += createValuesPropertyInitializer(enumEntries)
|
||||
|
||||
irClass.addChild(implObject)
|
||||
irClass.declarations += implObject
|
||||
}
|
||||
|
||||
private val genericCreateUninitializedInstanceSymbol = context.ir.symbols.createUninitializedInstance
|
||||
private val genericCreateUninitializedInstanceDescriptor = genericCreateUninitializedInstanceSymbol.descriptor
|
||||
private val createUninitializedInstance = context.ir.symbols.createUninitializedInstance.owner
|
||||
|
||||
private fun createSyntheticValuesPropertyDeclaration(enumEntries: List<IrEnumEntry>): IrPropertyImpl {
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
|
||||
val irValuesInitializer = context.createArrayOfExpression(irClass.defaultType,
|
||||
val irValuesInitializer = context.createArrayOfExpression(
|
||||
startOffset, endOffset,
|
||||
irClass.defaultType,
|
||||
enumEntries
|
||||
.sortedBy { it.descriptor.name }
|
||||
.sortedBy { it.name }
|
||||
.map {
|
||||
val initializer = it.initializerExpression
|
||||
val entryConstructorCall = when {
|
||||
initializer is IrCall -> initializer
|
||||
initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL ->
|
||||
initializer.statements.last() as IrCall
|
||||
else -> error("Unexpected initializer: $initializer")
|
||||
}
|
||||
val entryConstructor = entryConstructorCall.symbol.owner as IrConstructor
|
||||
val entryClass = entryConstructor.constructedClass
|
||||
initializer is IrCall -> initializer
|
||||
|
||||
initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL ->
|
||||
initializer.statements.last() as IrCall
|
||||
|
||||
else -> error("Unexpected initializer: $initializer")
|
||||
}
|
||||
val entryClass = (entryConstructorCall.symbol.owner as IrConstructor).constructedClass
|
||||
|
||||
irCall(startOffset, endOffset,
|
||||
genericCreateUninitializedInstanceSymbol.owner,
|
||||
createUninitializedInstance,
|
||||
listOf(entryClass.defaultType)
|
||||
)
|
||||
|
||||
}, startOffset, endOffset)
|
||||
}
|
||||
)
|
||||
val irField = loweredEnum.valuesField.apply {
|
||||
initializer = IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer)
|
||||
}
|
||||
@@ -344,15 +340,13 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
||||
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
||||
val value = IrGetFieldImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
startOffset, endOffset,
|
||||
loweredEnum.valuesField.symbol,
|
||||
loweredEnum.valuesField.type,
|
||||
receiver
|
||||
)
|
||||
val returnStatement = IrReturnImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.nothingType,
|
||||
loweredEnum.valuesGetter.symbol,
|
||||
value
|
||||
@@ -360,14 +354,14 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
getter.body = IrBlockBodyImpl(startOffset, endOffset, listOf(returnStatement))
|
||||
|
||||
return IrPropertyImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM,
|
||||
false, loweredEnum.valuesField.descriptor, irField, getter, null).also {
|
||||
it.parent = loweredEnum.implObject
|
||||
false, loweredEnum.valuesField.descriptor, irField, getter, null).apply {
|
||||
parent = loweredEnum.implObject
|
||||
}
|
||||
}
|
||||
|
||||
private val initInstanceSymbol = context.ir.symbols.initInstance
|
||||
|
||||
private val arrayGetSymbol = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||
private val arrayGetSymbol = context.ir.symbols.array.functions.single { it.owner.name == Name.identifier("get") }
|
||||
|
||||
private val arrayType = context.ir.symbols.array.typeWith(irClass.defaultType)
|
||||
|
||||
@@ -376,17 +370,23 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val endOffset = irClass.endOffset
|
||||
|
||||
fun IrBlockBodyBuilder.initInstanceCall(instance: IrCall, constructor: IrCall): IrCall =
|
||||
irCall(initInstanceSymbol).apply {
|
||||
putValueArgument(0, instance)
|
||||
putValueArgument(1, constructor)
|
||||
}
|
||||
irCall(initInstanceSymbol).apply {
|
||||
putValueArgument(0, instance)
|
||||
putValueArgument(1, constructor)
|
||||
}
|
||||
|
||||
return IrAnonymousInitializerImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, loweredEnum.implObject.descriptor).apply {
|
||||
parent = irClass
|
||||
val implObject = loweredEnum.implObject
|
||||
return IrAnonymousInitializerImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
IrAnonymousInitializerSymbolImpl(WrappedClassDescriptor())
|
||||
).apply {
|
||||
parent = implObject
|
||||
body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody(irClass) {
|
||||
val instances = irTemporary(irGetField(irGet(loweredEnum.implObject.thisReceiver!!), loweredEnum.valuesField))
|
||||
val receiver = implObject.thisReceiver!!
|
||||
val instances = irTemporary(irGetField(irGet(receiver), loweredEnum.valuesField))
|
||||
enumEntries
|
||||
.sortedBy { it.descriptor.name }
|
||||
.sortedBy { it.name }
|
||||
.withIndex()
|
||||
.forEach {
|
||||
val instance = irCall(arrayGetSymbol).apply {
|
||||
@@ -394,19 +394,22 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
putValueArgument(0, irInt(it.index))
|
||||
}
|
||||
val initializer = it.value.initializerExpression!!
|
||||
initializer.patchDeclarationParents(implObject)
|
||||
when {
|
||||
initializer is IrCall -> +initInstanceCall(instance, initializer)
|
||||
|
||||
initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> {
|
||||
val statements = initializer.statements
|
||||
val constructorCall = statements.last() as IrCall
|
||||
statements[statements.lastIndex] = initInstanceCall(instance, constructorCall)
|
||||
+initializer
|
||||
}
|
||||
|
||||
else -> error("Unexpected initializer: $initializer")
|
||||
}
|
||||
}
|
||||
+irCall(this@EnumClassLowering.context.ir.symbols.freeze, listOf(arrayType)).apply {
|
||||
extensionReceiver = irGet(loweredEnum.implObject.thisReceiver!!)
|
||||
extensionReceiver = irGet(receiver)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -456,85 +459,75 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
private fun transformEnumConstructor(enumConstructor: IrConstructor): IrConstructor {
|
||||
val loweredEnumConstructor = lowerEnumConstructor(enumConstructor)
|
||||
|
||||
enumConstructor.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach {
|
||||
val body = enumConstructor.getDefault(it)!!
|
||||
body.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
val descriptor = expression.descriptor
|
||||
when (descriptor) {
|
||||
is ValueParameterDescriptor -> {
|
||||
val parameter = loweredEnumConstructor.valueParameters[descriptor.loweredIndex()]
|
||||
return IrGetValueImpl(expression.startOffset,
|
||||
expression.endOffset,
|
||||
parameter.type,
|
||||
parameter.symbol)
|
||||
}
|
||||
}
|
||||
return expression
|
||||
}
|
||||
})
|
||||
loweredEnumConstructor.valueParameters[it.loweredIndex()].defaultValue = body
|
||||
descriptorToIrConstructorWithDefaultArguments[loweredEnumConstructor.descriptor] = loweredEnumConstructor
|
||||
for (parameter in enumConstructor.valueParameters) {
|
||||
val defaultValue = parameter.defaultValue ?: continue
|
||||
defaultValue.transformChildrenVoid(ParameterMapper(enumConstructor, loweredEnumConstructor, true))
|
||||
loweredEnumConstructor.valueParameters[parameter.loweredIndex].defaultValue = defaultValue
|
||||
defaultValue.patchDeclarationParents(loweredEnumConstructor)
|
||||
}
|
||||
return loweredEnumConstructor
|
||||
}
|
||||
|
||||
private fun lowerEnumConstructor(enumConstructor: IrConstructor): IrConstructorImpl {
|
||||
val loweredConstructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
|
||||
enumConstructor.descriptor.containingDeclaration,
|
||||
enumConstructor.descriptor.annotations,
|
||||
enumConstructor.descriptor.isPrimary,
|
||||
enumConstructor.descriptor.source
|
||||
)
|
||||
val valueParameters =
|
||||
listOf(
|
||||
loweredConstructorDescriptor.createValueParameter(
|
||||
0,
|
||||
"name",
|
||||
context.irBuiltIns.stringType,
|
||||
enumConstructor.startOffset,
|
||||
enumConstructor.endOffset
|
||||
),
|
||||
loweredConstructorDescriptor.createValueParameter(
|
||||
1,
|
||||
"ordinal",
|
||||
context.irBuiltIns.intType,
|
||||
enumConstructor.startOffset,
|
||||
enumConstructor.endOffset
|
||||
)
|
||||
) +
|
||||
enumConstructor.valueParameters.map {
|
||||
val descriptor = it.descriptor as ValueParameterDescriptor
|
||||
val loweredValueParameterDescriptor = descriptor.copy(
|
||||
loweredConstructorDescriptor,
|
||||
it.name,
|
||||
descriptor.loweredIndex()
|
||||
)
|
||||
loweredEnumConstructorParameters[descriptor] = loweredValueParameterDescriptor
|
||||
it.copy(loweredValueParameterDescriptor)
|
||||
}
|
||||
|
||||
loweredConstructorDescriptor.initialize(
|
||||
valueParameters.map { it.descriptor as ValueParameterDescriptor },
|
||||
Visibilities.PROTECTED
|
||||
)
|
||||
loweredConstructorDescriptor.returnType = enumConstructor.descriptor.returnType
|
||||
val loweredEnumConstructor = IrConstructorImpl(
|
||||
enumConstructor.startOffset, enumConstructor.endOffset, enumConstructor.origin,
|
||||
loweredConstructorDescriptor,
|
||||
enumConstructor.returnType,
|
||||
enumConstructor.body!!
|
||||
)
|
||||
loweredEnumConstructor.valueParameters += valueParameters
|
||||
loweredEnumConstructor.parent = enumConstructor.parent
|
||||
|
||||
loweredEnumConstructors[enumConstructor.descriptor] = loweredEnumConstructor
|
||||
|
||||
return loweredEnumConstructor
|
||||
}
|
||||
|
||||
private fun lowerEnumClassBody() {
|
||||
irClass.transformChildrenVoid(EnumClassBodyTransformer())
|
||||
private fun lowerEnumConstructor(constructor: IrConstructor): IrConstructorImpl {
|
||||
val startOffset = constructor.startOffset
|
||||
val endOffset = constructor.endOffset
|
||||
val loweredConstructor = WrappedClassConstructorDescriptor(
|
||||
constructor.descriptor.annotations,
|
||||
constructor.descriptor.source
|
||||
).let {
|
||||
IrConstructorImpl(
|
||||
startOffset, endOffset,
|
||||
constructor.origin,
|
||||
IrConstructorSymbolImpl(it),
|
||||
constructor.name,
|
||||
Visibilities.PROTECTED,
|
||||
constructor.returnType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isPrimary = constructor.isPrimary
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = constructor.parent
|
||||
body = constructor.body!! // Will be transformed later.
|
||||
}
|
||||
}
|
||||
|
||||
fun createSynthesizedValueParameter(index: Int, name: String, type: IrType) =
|
||||
WrappedValueParameterDescriptor().let {
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
IrValueParameterSymbolImpl(it),
|
||||
Name.identifier(name),
|
||||
index,
|
||||
type,
|
||||
varargElementType = null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = loweredConstructor
|
||||
}
|
||||
}
|
||||
|
||||
loweredConstructor.valueParameters += createSynthesizedValueParameter(0, "name", context.irBuiltIns.stringType)
|
||||
loweredConstructor.valueParameters += createSynthesizedValueParameter(1, "ordinal", context.irBuiltIns.intType)
|
||||
constructor.valueParameters.mapTo(loweredConstructor.valueParameters) {
|
||||
it.copyTo(loweredConstructor, index = it.loweredIndex).apply {
|
||||
loweredEnumConstructorParameters[it] = this
|
||||
}
|
||||
}
|
||||
|
||||
loweredEnumConstructors[constructor] = loweredConstructor
|
||||
|
||||
return loweredConstructor
|
||||
}
|
||||
|
||||
private fun lowerEnumClassBody(defaultClass: IrClass?) {
|
||||
irClass.transformChildrenVoid(EnumClassBodyTransformer(defaultClass))
|
||||
// Enum entries's classes have already been pulled out to the upper level - clear them up.
|
||||
irClass.declarations.filterIsInstance<IrEnumEntry>().forEach { it.correspondingClass = null }
|
||||
}
|
||||
|
||||
private inner class InEnumClassConstructor(val enumClassConstructor: IrConstructor) :
|
||||
@@ -544,11 +537,12 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val endOffset = enumConstructorCall.endOffset
|
||||
val origin = enumConstructorCall.origin
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
val result = IrDelegatingConstructorCallImpl(
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
enumConstructorCall.symbol, enumConstructorCall.descriptor, enumConstructorCall.typeArgumentsCount)
|
||||
enumConstructorCall.symbol)
|
||||
|
||||
assert(result.descriptor.valueParameters.size == 2) {
|
||||
assert(result.symbol.owner.valueParameters.size == 2) {
|
||||
"Enum(String, Int) constructor call expected:\n${result.dump()}"
|
||||
}
|
||||
|
||||
@@ -570,16 +564,18 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
override fun transform(delegatingConstructorCall: IrDelegatingConstructorCall): IrExpression {
|
||||
val descriptor = delegatingConstructorCall.descriptor
|
||||
val startOffset = delegatingConstructorCall.startOffset
|
||||
val endOffset = delegatingConstructorCall.endOffset
|
||||
|
||||
val loweredDelegatedConstructor = loweredEnumConstructors.getOrElse(descriptor) {
|
||||
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor")
|
||||
val delegatingConstructor = delegatingConstructorCall.symbol.owner
|
||||
val loweredDelegatingConstructor = loweredEnumConstructors.getOrElse(delegatingConstructor) {
|
||||
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $delegatingConstructor")
|
||||
}
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType,
|
||||
loweredDelegatedConstructor.symbol, loweredDelegatedConstructor.descriptor, 0)
|
||||
val result = IrDelegatingConstructorCallImpl(
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
loweredDelegatingConstructor.symbol)
|
||||
|
||||
val firstParameter = enumClassConstructor.valueParameters[0]
|
||||
result.putValueArgument(0,
|
||||
@@ -588,25 +584,26 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
result.putValueArgument(1,
|
||||
IrGetValueImpl(startOffset, endOffset, secondParameter.type, secondParameter.symbol))
|
||||
|
||||
descriptor.valueParameters.forEach { valueParameter ->
|
||||
result.putValueArgument(valueParameter.loweredIndex(), delegatingConstructorCall.getValueArgument(valueParameter))
|
||||
delegatingConstructor.valueParameters.forEach {
|
||||
result.putValueArgument(it.loweredIndex, delegatingConstructorCall.getValueArgument(it.index))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private abstract inner class InEnumEntry(private val enumEntry: ClassDescriptor) : EnumConstructorCallTransformer {
|
||||
private abstract inner class InEnumEntry(private val enumEntry: IrEnumEntry) : EnumConstructorCallTransformer {
|
||||
|
||||
override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression {
|
||||
val name = enumEntry.name.asString()
|
||||
val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(enumEntry)
|
||||
val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(enumEntry.descriptor)
|
||||
|
||||
val descriptor = enumConstructorCall.descriptor
|
||||
val startOffset = enumConstructorCall.startOffset
|
||||
val endOffset = enumConstructorCall.endOffset
|
||||
|
||||
val loweredConstructor = loweredEnumConstructors.getOrElse(descriptor) {
|
||||
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor")
|
||||
val enumConstructor = enumConstructorCall.symbol.owner
|
||||
val loweredConstructor = loweredEnumConstructors.getOrElse(enumConstructor) {
|
||||
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $enumConstructor")
|
||||
}
|
||||
|
||||
val result = createConstructorCall(startOffset, endOffset, loweredConstructor.symbol)
|
||||
@@ -616,9 +613,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
result.putValueArgument(1,
|
||||
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal))
|
||||
|
||||
descriptor.valueParameters.forEach { valueParameter ->
|
||||
val i = valueParameter.index
|
||||
result.putValueArgument(i + 2, enumConstructorCall.getValueArgument(i))
|
||||
enumConstructor.valueParameters.forEach {
|
||||
result.putValueArgument(it.loweredIndex, enumConstructorCall.getValueArgument(it.index))
|
||||
}
|
||||
|
||||
return result
|
||||
@@ -631,7 +627,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
abstract fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrMemberAccessExpression
|
||||
}
|
||||
|
||||
private inner class InEnumEntryClassConstructor(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
||||
private inner class InEnumEntryClassConstructor(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
@@ -640,25 +636,23 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
startOffset,
|
||||
endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
loweredConstructor,
|
||||
loweredConstructor.descriptor,
|
||||
0
|
||||
loweredConstructor
|
||||
)
|
||||
}
|
||||
|
||||
private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
||||
private inner class InEnumEntryInitializer(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrCall {
|
||||
val irConstructorSymbol = defaultEnumEntryConstructors[loweredConstructor.descriptor]?.symbol
|
||||
val irConstructorSymbol = defaultEnumEntryConstructors[loweredConstructor.owner]?.symbol
|
||||
?: loweredConstructor
|
||||
return IrCallImpl(startOffset, endOffset, irConstructorSymbol.owner.returnType, irConstructorSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class EnumClassBodyTransformer : IrElementTransformerVoid() {
|
||||
private inner class EnumClassBodyTransformer(val defaultClass: IrClass?) : IrElementTransformerVoid() {
|
||||
private var enumConstructorCallTransformer: EnumConstructorCallTransformer? = null
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
if (declaration.descriptor.kind == ClassKind.ENUM_CLASS)
|
||||
if (declaration.kind == ClassKind.ENUM_CLASS || declaration == defaultClass)
|
||||
return declaration
|
||||
return super.visitClass(declaration)
|
||||
}
|
||||
@@ -666,27 +660,25 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
override fun visitEnumEntry(declaration: IrEnumEntry): IrStatement {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||
|
||||
enumConstructorCallTransformer = InEnumEntryInitializer(declaration.descriptor)
|
||||
enumConstructorCallTransformer = InEnumEntryInitializer(declaration)
|
||||
|
||||
var result: IrEnumEntry = IrEnumEntryImpl(declaration.startOffset, declaration.endOffset, declaration.origin,
|
||||
declaration.descriptor, null, declaration.initializerExpression)
|
||||
result = super.visitEnumEntry(result) as IrEnumEntry
|
||||
declaration.initializerExpression = declaration.initializerExpression?.transform(this, data = null)
|
||||
|
||||
enumConstructorCallTransformer = null
|
||||
|
||||
return result
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor): IrStatement {
|
||||
val constructorDescriptor = declaration.descriptor
|
||||
val containingClass = constructorDescriptor.containingDeclaration
|
||||
val containingClass = declaration.parentAsClass
|
||||
|
||||
// TODO local (non-enum) class in enum class constructor?
|
||||
val previous = enumConstructorCallTransformer
|
||||
|
||||
if (containingClass.kind == ClassKind.ENUM_ENTRY) {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||
enumConstructorCallTransformer = InEnumEntryClassConstructor(containingClass)
|
||||
val entry = irClass.declarations.filterIsInstance<IrEnumEntry>().single { it.correspondingClass == containingClass }
|
||||
enumConstructorCallTransformer = InEnumEntryClassConstructor(entry)
|
||||
} else if (containingClass.kind == ClassKind.ENUM_CLASS) {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||
enumConstructorCallTransformer = InEnumClassConstructor(declaration)
|
||||
@@ -703,7 +695,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val callTransformer = enumConstructorCallTransformer ?:
|
||||
throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" + irClass.dump())
|
||||
throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" + irClass.dump())
|
||||
|
||||
|
||||
return callTransformer.transform(expression)
|
||||
@@ -712,9 +704,9 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
if (expression.descriptor.containingDeclaration.kind == ClassKind.ENUM_CLASS) {
|
||||
if (expression.symbol.owner.parentAsClass.kind == ClassKind.ENUM_CLASS) {
|
||||
val callTransformer = enumConstructorCallTransformer ?:
|
||||
throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" + irClass.dump())
|
||||
throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" + irClass.dump())
|
||||
|
||||
return callTransformer.transform(expression)
|
||||
}
|
||||
@@ -722,34 +714,36 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
val loweredParameter = loweredEnumConstructorParameters[expression.descriptor]
|
||||
if (loweredParameter != null) {
|
||||
val loweredEnumConstructor = loweredEnumConstructors[expression.descriptor.containingDeclaration]!!
|
||||
val loweredIrParameter = loweredEnumConstructor.valueParameters[loweredParameter.index]
|
||||
assert(loweredIrParameter.descriptor == loweredParameter)
|
||||
return IrGetValueImpl(expression.startOffset, expression.endOffset, loweredIrParameter.type,
|
||||
loweredIrParameter.symbol, expression.origin)
|
||||
val parameter = expression.symbol.owner
|
||||
val loweredParameter = loweredEnumConstructorParameters[parameter]
|
||||
return if (loweredParameter == null) {
|
||||
expression
|
||||
} else {
|
||||
return expression
|
||||
IrGetValueImpl(expression.startOffset, expression.endOffset, loweredParameter.type,
|
||||
loweredParameter.symbol, expression.origin)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ValueParameterDescriptor.loweredIndex(): Int = index + 2
|
||||
private val IrValueParameter.loweredIndex: Int get() = index + 2
|
||||
|
||||
private class ParameterMapper(superConstructor: IrConstructor,
|
||||
val constructor: IrConstructor,
|
||||
val useLoweredIndex: Boolean) : IrElementTransformerVoid() {
|
||||
private val valueParameters = superConstructor.valueParameters.toSet()
|
||||
|
||||
private class ParameterMapper(val originalConstructor: IrConstructor) : IrElementTransformerVoid() {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
val descriptor = expression.descriptor
|
||||
when (descriptor) {
|
||||
is ValueParameterDescriptor -> {
|
||||
val parameter = originalConstructor.valueParameters[descriptor.index]
|
||||
return IrGetValueImpl(expression.startOffset,
|
||||
expression.endOffset,
|
||||
parameter.type,
|
||||
parameter.symbol)
|
||||
}
|
||||
|
||||
val superParameter = expression.symbol.owner as? IrValueParameter ?: return expression
|
||||
if (valueParameters.contains(superParameter)) {
|
||||
val index = if (useLoweredIndex) superParameter.loweredIndex else superParameter.index
|
||||
val parameter = constructor.valueParameters[index]
|
||||
return IrGetValueImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
parameter.type,
|
||||
parameter.symbol)
|
||||
}
|
||||
return expression
|
||||
}
|
||||
|
||||
+25
-15
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.peek
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
import org.jetbrains.kotlin.backend.common.push
|
||||
@@ -16,11 +17,11 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.getClass
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
@@ -87,24 +88,33 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo
|
||||
return expression
|
||||
}
|
||||
|
||||
private fun createEnumOrdinalVariable(enumVariable: IrVariable): IrVariable {
|
||||
val ordinalPropertyGetter = context.ir.symbols.enum.getPropertyGetter("ordinal")!!
|
||||
val getOrdinal = IrCallImpl(
|
||||
// Create temporary variable for subject's ordinal.
|
||||
private fun createEnumOrdinalVariable(enumVariable: IrVariable) = WrappedVariableDescriptor().let {
|
||||
IrVariableImpl(
|
||||
enumVariable.startOffset, enumVariable.endOffset,
|
||||
ordinalPropertyGetter.owner.returnType,
|
||||
ordinalPropertyGetter
|
||||
IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
|
||||
IrVariableSymbolImpl(it),
|
||||
Name.identifier(enumVariable.name.asString() + "_ordinal"),
|
||||
context.irBuiltIns.intType,
|
||||
isVar = false,
|
||||
isConst = false,
|
||||
isLateinit = false
|
||||
).apply {
|
||||
dispatchReceiver = IrGetValueImpl(
|
||||
it.bind(this)
|
||||
parent = enumVariable.parent
|
||||
|
||||
val ordinalPropertyGetter = context.ir.symbols.enum.getPropertyGetter("ordinal")!!
|
||||
initializer = IrCallImpl(
|
||||
enumVariable.startOffset, enumVariable.endOffset,
|
||||
enumVariable.type, enumVariable.symbol
|
||||
)
|
||||
ordinalPropertyGetter.owner.returnType,
|
||||
ordinalPropertyGetter
|
||||
).apply {
|
||||
dispatchReceiver = IrGetValueImpl(
|
||||
enumVariable.startOffset, enumVariable.endOffset,
|
||||
enumVariable.type, enumVariable.symbol
|
||||
)
|
||||
}
|
||||
}
|
||||
// Create temporary variable for subject's ordinal.
|
||||
val ordinalDescriptor = IrTemporaryVariableDescriptorImpl(enumVariable.descriptor.containingDeclaration,
|
||||
Name.identifier(enumVariable.name.asString() + "_ordinal"), context.builtIns.intType)
|
||||
return IrVariableImpl(enumVariable.startOffset, enumVariable.endOffset,
|
||||
IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, ordinalDescriptor,
|
||||
context.irBuiltIns.intType, getOrdinal)
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
|
||||
+37
-42
@@ -7,16 +7,13 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol
|
||||
@@ -25,17 +22,15 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.builders.irGet
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.setDeclarationsParent
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, IrElementTransformerVoidWithContext() {
|
||||
|
||||
private val symbols get() = context.ir.symbols
|
||||
private val symbols = context.ir.symbols
|
||||
|
||||
private interface HighLevelJump {
|
||||
fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression): IrExpression
|
||||
@@ -66,7 +61,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
|
||||
private abstract class Scope
|
||||
|
||||
private class ReturnableScope(val descriptor: CallableDescriptor): Scope()
|
||||
private class ReturnableScope(val symbol: IrReturnTargetSymbol): Scope()
|
||||
|
||||
private class LoopScope(val loop: IrLoop): Scope()
|
||||
|
||||
@@ -92,7 +87,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
}
|
||||
|
||||
override fun visitFunctionNew(declaration: IrFunction): IrStatement {
|
||||
using(ReturnableScope(declaration.descriptor)) {
|
||||
using(ReturnableScope(declaration.symbol)) {
|
||||
return super.visitFunctionNew(declaration)
|
||||
}
|
||||
}
|
||||
@@ -101,7 +96,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
if (expression !is IrReturnableBlockImpl)
|
||||
return super.visitContainerExpression(expression)
|
||||
|
||||
using(ReturnableScope(expression.descriptor)) {
|
||||
using(ReturnableScope(expression.symbol)) {
|
||||
return super.visitContainerExpression(expression)
|
||||
}
|
||||
}
|
||||
@@ -142,7 +137,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
return performHighLevelJump(
|
||||
targetScopePredicate = { it is ReturnableScope && it.descriptor == expression.returnTarget },
|
||||
targetScopePredicate = { it is ReturnableScope && it.symbol == expression.returnTargetSymbol },
|
||||
jump = Return(expression.returnTargetSymbol),
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
@@ -184,7 +179,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
val currentTryScope = tryScopes[index]
|
||||
currentTryScope.jumps.getOrPut(jump) {
|
||||
val type = (jump as? Return)?.target?.owner?.returnType ?: value.type
|
||||
val symbol = getIrReturnableBlockSymbol(jump.toString(), type)
|
||||
val symbol = IrReturnableBlockSymbolImpl(WrappedSimpleFunctionDescriptor())
|
||||
with(currentTryScope) {
|
||||
irBuilder.run {
|
||||
val inlinedFinally = irInlineFinally(symbol, type, expression, finallyExpression)
|
||||
@@ -223,14 +218,21 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
type = context.irBuiltIns.nothingType
|
||||
)
|
||||
val transformedFinallyExpression = finallyExpression.transform(transformer, null)
|
||||
val parameter = IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration = currentScope!!.scope.scopeOwner,
|
||||
name = Name.identifier("t"),
|
||||
outType = context.builtIns.throwable.defaultType
|
||||
)
|
||||
val catchParameter = IrVariableImpl(
|
||||
startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter,
|
||||
symbols.throwable.owner.defaultType)
|
||||
val catchParameter = WrappedVariableDescriptor().let {
|
||||
IrVariableImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.CATCH_PARAMETER,
|
||||
IrVariableSymbolImpl(it),
|
||||
Name.identifier("t"),
|
||||
symbols.throwable.owner.defaultType,
|
||||
isVar = false,
|
||||
isConst = false,
|
||||
isLateinit = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = this@run.parent
|
||||
}
|
||||
}
|
||||
|
||||
val syntheticTry = IrTryImpl(
|
||||
startOffset = startOffset,
|
||||
@@ -240,7 +242,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
catches = listOf(
|
||||
irCatch(catchParameter).apply {
|
||||
result = irBlock {
|
||||
+finallyExpression.copy()
|
||||
+copy(finallyExpression)
|
||||
+irThrow(irGet(catchParameter))
|
||||
}
|
||||
}),
|
||||
@@ -248,7 +250,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
)
|
||||
using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
|
||||
val fallThroughType = aTry.type
|
||||
val fallThroughSymbol = getIrReturnableBlockSymbol("fallThrough", fallThroughType)
|
||||
val fallThroughSymbol = IrReturnableBlockSymbolImpl(WrappedSimpleFunctionDescriptor())
|
||||
val transformedResult = aTry.tryResult.transform(transformer, null)
|
||||
transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult)
|
||||
for (aCatch in aTry.catches) {
|
||||
@@ -264,39 +266,32 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
private fun IrBuilderWithScope.irInlineFinally(symbol: IrReturnableBlockSymbol, type: IrType,
|
||||
value: IrExpression,
|
||||
finallyExpression: IrExpression): IrExpression {
|
||||
val returnType = symbol.descriptor.returnType!!
|
||||
return when {
|
||||
returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, type) {
|
||||
val returnTypeClassifier = (type as? IrSimpleType)?.classifier
|
||||
return when (returnTypeClassifier) {
|
||||
symbols.unit, symbols.nothing -> irBlock(value, null, type) {
|
||||
+irReturnableBlock(symbol, type) {
|
||||
+value
|
||||
}
|
||||
+finallyExpression.copy()
|
||||
+copy(finallyExpression)
|
||||
}
|
||||
else -> irBlock(value, null, type) {
|
||||
val tmp = irTemporary(irReturnableBlock(symbol, type) {
|
||||
+irReturn(symbol, value)
|
||||
})
|
||||
+finallyExpression.copy()
|
||||
+copy(finallyExpression)
|
||||
+irGet(tmp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFakeFunctionDescriptor(name: String, returnType: KotlinType) =
|
||||
SimpleFunctionDescriptorImpl.create(currentScope!!.scope.scopeOwner, Annotations.EMPTY, name.synthesizedName,
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE).apply {
|
||||
initialize(null, null, emptyList(), emptyList(), returnType, Modality.ABSTRACT, Visibilities.PRIVATE)
|
||||
}
|
||||
|
||||
private fun getIrReturnableBlockSymbol(name: String, returnType: IrType): IrReturnableBlockSymbol =
|
||||
IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType.toKotlinType()))
|
||||
|
||||
private inline fun <reified T : IrElement> T.copy() = this.deepCopyWithVariables()
|
||||
private inline fun <reified T : IrElement> IrBuilderWithScope.copy(element: T) =
|
||||
element.deepCopyWithVariables().setDeclarationsParent(parent)
|
||||
|
||||
fun IrBuilderWithScope.irReturn(target: IrReturnTargetSymbol, value: IrExpression) =
|
||||
IrReturnImpl(startOffset, endOffset, context.irBuiltIns.nothingType, target, value)
|
||||
|
||||
inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, type: IrType, body: IrBlockBuilder.() -> Unit) =
|
||||
private inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol,
|
||||
type: IrType, body: IrBlockBuilder.() -> Unit) =
|
||||
IrReturnableBlockImpl(startOffset, endOffset, type, symbol, null,
|
||||
IrBlockBuilder(context, scope, startOffset, endOffset, null, type)
|
||||
.block(body).statements)
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole
|
||||
import org.jetbrains.kotlin.backend.common.lower.CoroutineIntrinsicLambdaOrigin
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
|
||||
@@ -150,7 +151,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerWithC
|
||||
if (!callSite.descriptor.needsInlining)
|
||||
return callSite
|
||||
val functionDescriptor = callSite.descriptor.resolveFakeOverride().original
|
||||
if (functionDescriptor == context.ir.symbols.isInitializedGetterDescriptor)
|
||||
if (callSite.symbol == context.ir.symbols.isInitializedGetter)
|
||||
return callSite
|
||||
|
||||
val callee = getFunctionDeclaration(functionDescriptor)
|
||||
|
||||
+58
-48
@@ -7,13 +7,12 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.isNonGeneratedAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.irDelegatingConstructorCall
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -21,10 +20,10 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.hasPrimaryConstructor
|
||||
|
||||
internal class InitializersLowering(val context: CommonBackendContext) : ClassLoweringPass {
|
||||
|
||||
@@ -41,8 +40,8 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
|
||||
fun lowerInitializers() {
|
||||
collectAndRemoveInitializers()
|
||||
val initializerMethodSymbol = createInitializerMethod()
|
||||
lowerConstructors(initializerMethodSymbol)
|
||||
val initializeMethodSymbol = createInitializerMethod()
|
||||
lowerConstructors(initializeMethodSymbol)
|
||||
}
|
||||
|
||||
private fun collectAndRemoveInitializers() {
|
||||
@@ -63,7 +62,9 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
val initializer = declaration.initializer ?: return declaration
|
||||
val startOffset = initializer.startOffset
|
||||
val endOffset = initializer.endOffset
|
||||
initializers.add(IrBlockImpl(startOffset, endOffset, context.irBuiltIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER,
|
||||
initializers.add(IrBlockImpl(startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER,
|
||||
listOf(
|
||||
IrSetFieldImpl(startOffset, endOffset, declaration.symbol,
|
||||
IrGetValueImpl(
|
||||
@@ -72,7 +73,8 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
),
|
||||
initializer.expression,
|
||||
context.irBuiltIns.unitType,
|
||||
STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER))))
|
||||
STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER)))
|
||||
)
|
||||
declaration.initializer = null
|
||||
return declaration
|
||||
}
|
||||
@@ -88,52 +90,54 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
private fun createInitializerMethod(): IrSimpleFunctionSymbol? {
|
||||
if (irClass.declarations.any { it is IrConstructor && it.isPrimary })
|
||||
return null // Place initializers in the primary constructor.
|
||||
val initializerMethodDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
/* containingDeclaration = */ irClass.descriptor,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* name = */ "INITIALIZER".synthesizedName,
|
||||
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/* source = */ SourceElement.NO_SOURCE)
|
||||
initializerMethodDescriptor.initialize(
|
||||
/* receiverParameterType = */ null,
|
||||
/* dispatchReceiverParameter = */ irClass.descriptor.thisAsReceiverParameter,
|
||||
/* typeParameters = */ listOf(),
|
||||
/* unsubstitutedValueParameters = */ listOf(),
|
||||
/* returnType = */ context.builtIns.unitType,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PRIVATE)
|
||||
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
val initializer = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ANONYMOUS_INITIALIZER,
|
||||
initializerMethodDescriptor, context.irBuiltIns.unitType)
|
||||
val initializeFun = WrappedSimpleFunctionDescriptor().let {
|
||||
IrFunctionImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_ANONYMOUS_INITIALIZER,
|
||||
IrSimpleFunctionSymbolImpl(it),
|
||||
"INITIALIZER".synthesizedName,
|
||||
Visibilities.PRIVATE,
|
||||
Modality.FINAL,
|
||||
context.irBuiltIns.unitType,
|
||||
isInline = false,
|
||||
isSuspend = false,
|
||||
isExternal = false,
|
||||
isTailrec = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = irClass
|
||||
irClass.declarations.add(this)
|
||||
|
||||
initializer.body = IrBlockBodyImpl(startOffset, endOffset, initializers)
|
||||
createDispatchReceiverParameter()
|
||||
|
||||
initializer.parent = irClass
|
||||
initializer.createDispatchReceiverParameter()
|
||||
body = IrBlockBodyImpl(startOffset, endOffset, initializers)
|
||||
}
|
||||
}
|
||||
|
||||
initializers.forEach {
|
||||
it.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
for (initializer in initializers) {
|
||||
initializer.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
if (expression.symbol == irClass.thisReceiver!!.symbol) {
|
||||
return IrGetValueImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
initializer.dispatchReceiverParameter!!.type,
|
||||
initializer.dispatchReceiverParameter!!.symbol
|
||||
initializeFun.dispatchReceiverParameter!!.type,
|
||||
initializeFun.dispatchReceiverParameter!!.symbol
|
||||
)
|
||||
}
|
||||
return expression
|
||||
}
|
||||
})
|
||||
initializer.patchDeclarationParents(initializeFun)
|
||||
}
|
||||
|
||||
irClass.declarations.add(initializer)
|
||||
|
||||
return initializer.symbol
|
||||
return initializeFun.symbol
|
||||
}
|
||||
|
||||
private fun lowerConstructors(initializerMethodSymbol: IrSimpleFunctionSymbol?) {
|
||||
private fun lowerConstructors(initializeMethodSymbol: IrSimpleFunctionSymbol?) {
|
||||
if (irClass.kind == ClassKind.ANNOTATION_CLASS) {
|
||||
if (irClass.isNonGeneratedAnnotation()) return
|
||||
|
||||
@@ -158,14 +162,16 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
blockBody.statements.transformFlat {
|
||||
when {
|
||||
it is IrInstanceInitializerCall -> {
|
||||
if (initializerMethodSymbol == null) {
|
||||
assert(declaration.descriptor.isPrimary)
|
||||
if (initializeMethodSymbol == null) {
|
||||
assert(declaration.isPrimary)
|
||||
for (initializer in initializers)
|
||||
initializer.patchDeclarationParents(declaration)
|
||||
initializers
|
||||
} else {
|
||||
val startOffset = it.startOffset
|
||||
val endOffset = it.endOffset
|
||||
listOf(IrCallImpl(startOffset, endOffset,
|
||||
context.irBuiltIns.unitType, initializerMethodSymbol
|
||||
context.irBuiltIns.unitType, initializeMethodSymbol
|
||||
).apply {
|
||||
dispatchReceiver = IrGetValueImpl(
|
||||
startOffset, endOffset,
|
||||
@@ -174,20 +180,24 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
})
|
||||
}
|
||||
}
|
||||
/**
|
||||
* IR for kotlin.Any is:
|
||||
* BLOCK_BODY
|
||||
* DELEGATING_CONSTRUCTOR_CALL 'constructor Any()'
|
||||
* INSTANCE_INITIALIZER_CALL classDescriptor='Any'
|
||||
*
|
||||
* to avoid possible recursion we manually reject body generation for Any.
|
||||
*/
|
||||
it is IrDelegatingConstructorCall && irClass.descriptor == context.builtIns.any
|
||||
&& it.descriptor == declaration.descriptor -> listOf()
|
||||
|
||||
/**
|
||||
* IR for kotlin.Any is:
|
||||
* BLOCK_BODY
|
||||
* DELEGATING_CONSTRUCTOR_CALL 'constructor Any()'
|
||||
* INSTANCE_INITIALIZER_CALL classDescriptor='Any'
|
||||
*
|
||||
* to avoid possible recursion we manually reject body generation for Any.
|
||||
*/
|
||||
it is IrDelegatingConstructorCall
|
||||
&& irClass.symbol == context.irBuiltIns.anyClass
|
||||
&& it.symbol == declaration.symbol -> {
|
||||
listOf()
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
declaration.parent = irClass
|
||||
|
||||
return declaration
|
||||
}
|
||||
|
||||
+16
-27
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.lower.callsSuper
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
@@ -21,9 +20,12 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
|
||||
internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
override fun lower(irClass: IrClass) {
|
||||
@@ -31,12 +33,10 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
private inner class InnerClassTransformer(val irClass: IrClass) {
|
||||
val classDescriptor = irClass.descriptor
|
||||
|
||||
lateinit var outerThisFieldSymbol: IrFieldSymbol
|
||||
|
||||
fun lowerInnerClass() {
|
||||
if (!irClass.descriptor.isInner) return
|
||||
if (!irClass.isInner) return
|
||||
|
||||
createOuterThisField()
|
||||
lowerOuterThisReferences()
|
||||
@@ -84,10 +84,9 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val implicitThisClass = expression.descriptor.getClassDescriptorForImplicitThis() ?:
|
||||
return expression
|
||||
val implicitThisClass = (expression.symbol.owner.parent as? IrClass) ?: return expression
|
||||
|
||||
if (implicitThisClass == classDescriptor) return expression
|
||||
if (implicitThisClass == irClass) return expression
|
||||
|
||||
val constructorSymbol = currentFunction!!.scope.scopeOwnerSymbol as? IrConstructorSymbol
|
||||
|
||||
@@ -97,27 +96,27 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
var irThis: IrExpression
|
||||
var innerClass: IrClass
|
||||
if (constructorSymbol == null || constructorSymbol.descriptor.constructedClass != classDescriptor) {
|
||||
if (constructorSymbol == null || constructorSymbol.owner.parentAsClass != irClass) {
|
||||
innerClass = irClass
|
||||
val currentIrFunction = currentFunction!!.scope.scopeOwnerSymbol.owner as IrFunction
|
||||
|
||||
val currentFunctionReceiver = currentIrFunction.dispatchReceiverParameter
|
||||
val thisParameter = if (currentFunctionReceiver?.descriptor == irClass.thisReceiver!!.descriptor) {
|
||||
currentFunctionReceiver
|
||||
} else {
|
||||
irClass.thisReceiver!!
|
||||
}
|
||||
val thisParameter =
|
||||
if (currentFunctionReceiver?.type?.classifierOrNull == irClass.symbol)
|
||||
currentFunctionReceiver
|
||||
else
|
||||
irClass.thisReceiver!!
|
||||
|
||||
irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin)
|
||||
} else {
|
||||
// For constructor we have outer class as dispatchReceiverParameter.
|
||||
innerClass = irClass.parent as? IrClass ?:
|
||||
throw AssertionError("No containing class for inner class $classDescriptor")
|
||||
throw AssertionError("No containing class for inner class ${irClass.dump()}")
|
||||
val thisParameter = constructorSymbol.owner.dispatchReceiverParameter!!
|
||||
irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin)
|
||||
}
|
||||
|
||||
while (innerClass.descriptor != implicitThisClass) {
|
||||
while (innerClass != implicitThisClass) {
|
||||
if (!innerClass.isInner) {
|
||||
// Captured 'this' unrelated to inner classes nesting hierarchy, leave it as is -
|
||||
// should be transformed by closures conversion.
|
||||
@@ -134,23 +133,13 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
val outer = innerClass.parent
|
||||
innerClass = outer as? IrClass ?:
|
||||
throw AssertionError("Unexpected containing declaration for inner class ${innerClass.descriptor}: $outer")
|
||||
throw AssertionError("Unexpected containing declaration for inner class ${innerClass.dump()}: $outer")
|
||||
}
|
||||
|
||||
return irThis
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun ValueDescriptor.getClassDescriptorForImplicitThis(): ClassDescriptor? {
|
||||
if (this is ReceiverParameterDescriptor) {
|
||||
val receiverValue = value
|
||||
if (receiverValue is ImplicitClassReceiver) {
|
||||
return receiverValue.classDescriptor
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+25
-46
@@ -9,10 +9,7 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isReal
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -21,45 +18,29 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
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.ir.symbols.IrVariableSymbol
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal class LateinitLowering(
|
||||
val context: Context,
|
||||
private val generateParameterNameInAssertion: Boolean = false
|
||||
) : FileLoweringPass {
|
||||
|
||||
private val isInitializedGetterDescriptor = context.ir.symbols.isInitializedGetterDescriptor
|
||||
private val isInitializedGetter = context.ir.symbols.isInitializedGetter
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
val lateinitPropertyToField = mutableMapOf<PropertyDescriptor, IrField>()
|
||||
irFile.acceptVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitProperty(declaration: IrProperty) {
|
||||
super.visitProperty(declaration)
|
||||
|
||||
if (declaration.isLateinit && declaration.descriptor.kind.isReal) {
|
||||
lateinitPropertyToField[declaration.descriptor] = declaration.backingField!!
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) {
|
||||
|
||||
override fun visitVariable(declaration: IrVariable): IrStatement {
|
||||
declaration.transformChildrenVoid(this)
|
||||
|
||||
val descriptor = declaration.descriptor
|
||||
if (!descriptor.isLateInit) return declaration
|
||||
if (!declaration.isLateinit) return declaration
|
||||
|
||||
assert(declaration.initializer == null, { "'lateinit' modifier is not allowed for variables with initializer" })
|
||||
assert(!KotlinBuiltIns.isPrimitiveType(descriptor.type), { "'lateinit' modifier is not allowed on primitive types" })
|
||||
assert(declaration.initializer == null) {
|
||||
"'lateinit' modifier is not allowed for variables with initializer"
|
||||
}
|
||||
builder.at(declaration).run {
|
||||
declaration.initializer = irNull()
|
||||
}
|
||||
@@ -68,16 +49,14 @@ internal class LateinitLowering(
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
val symbol = expression.symbol
|
||||
val descriptor = symbol.descriptor as? VariableDescriptor
|
||||
if (descriptor == null || !descriptor.isLateInit) return expression
|
||||
if (symbol !is IrVariableSymbol || !symbol.owner.isLateinit) return expression
|
||||
|
||||
assert(!KotlinBuiltIns.isPrimitiveType(descriptor.type), { "'lateinit' modifier is not allowed on primitive types" })
|
||||
builder.at(expression).run {
|
||||
return irBlock(expression) {
|
||||
// TODO: do data flow analysis to check if value is proved to be not-null.
|
||||
+irIfThen(
|
||||
irEqualsNull(irGet(expression.type, symbol)),
|
||||
throwUninitializedPropertyAccessException(symbol)
|
||||
throwUninitializedPropertyAccessException(symbol.owner.name)
|
||||
)
|
||||
+irGet(expression.type, symbol)
|
||||
}
|
||||
@@ -87,17 +66,17 @@ internal class LateinitLowering(
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val descriptor = expression.descriptor
|
||||
if (descriptor != isInitializedGetterDescriptor) return expression
|
||||
if (expression.symbol != isInitializedGetter) return expression
|
||||
|
||||
val propertyReference = expression.extensionReceiver!! as IrPropertyReference
|
||||
assert(propertyReference.extensionReceiver == null, { "'lateinit' modifier is not allowed on extension properties" })
|
||||
val propertyDescriptor = propertyReference.descriptor.resolveFakeOverride().original
|
||||
assert(propertyReference.extensionReceiver == null) {
|
||||
"'lateinit' modifier is not allowed on extension properties"
|
||||
}
|
||||
val getter = propertyReference.getter?.owner ?: TODO(propertyReference.dump())
|
||||
val property = getter.resolveFakeOverride().correspondingProperty!!
|
||||
|
||||
val type = propertyDescriptor.type
|
||||
assert(!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" })
|
||||
builder.at(expression).run {
|
||||
val field = lateinitPropertyToField[propertyDescriptor]!!
|
||||
val field = property.backingField!!
|
||||
val fieldValue = irGetField(propertyReference.dispatchReceiver, field)
|
||||
return irNotEquals(fieldValue, irNull())
|
||||
}
|
||||
@@ -106,13 +85,15 @@ internal class LateinitLowering(
|
||||
override fun visitProperty(declaration: IrProperty): IrStatement {
|
||||
declaration.transformChildrenVoid(this)
|
||||
|
||||
if (!declaration.descriptor.isLateInit || !declaration.descriptor.kind.isReal)
|
||||
if (!declaration.isLateinit || !declaration.isReal)
|
||||
return declaration
|
||||
|
||||
val backingField = declaration.backingField!!
|
||||
transformGetter(backingField, declaration.getter!!)
|
||||
|
||||
assert(backingField.initializer == null, { "'lateinit' modifier is not allowed for properties with initializer" })
|
||||
assert(backingField.initializer == null) {
|
||||
"'lateinit' modifier is not allowed for properties with initializer"
|
||||
}
|
||||
val irBuilder = context.createIrBuilder(backingField.symbol, declaration.startOffset, declaration.endOffset)
|
||||
irBuilder.run {
|
||||
backingField.initializer = irExprBody(irNull())
|
||||
@@ -122,8 +103,6 @@ internal class LateinitLowering(
|
||||
}
|
||||
|
||||
private fun transformGetter(backingField: IrField, getter: IrFunction) {
|
||||
val type = backingField.descriptor.type
|
||||
assert(!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" })
|
||||
val irBuilder = context.createIrBuilder(getter.symbol, getter.startOffset, getter.endOffset)
|
||||
irBuilder.run {
|
||||
getter.body = irBlockBody {
|
||||
@@ -134,7 +113,7 @@ internal class LateinitLowering(
|
||||
context.irBuiltIns.nothingType,
|
||||
irNotEquals(irGet(resultVar), irNull()),
|
||||
irReturn(irGet(resultVar)),
|
||||
throwUninitializedPropertyAccessException(backingField.symbol)
|
||||
throwUninitializedPropertyAccessException(backingField.name)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -142,7 +121,7 @@ internal class LateinitLowering(
|
||||
})
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.throwUninitializedPropertyAccessException(backingFieldSymbol: IrSymbol) =
|
||||
private fun IrBuilderWithScope.throwUninitializedPropertyAccessException(name: Name) =
|
||||
irCall(throwErrorFunction, context.irBuiltIns.nothingType).apply {
|
||||
if (generateParameterNameInAssertion) {
|
||||
putValueArgument(
|
||||
@@ -151,7 +130,7 @@ internal class LateinitLowering(
|
||||
startOffset,
|
||||
endOffset,
|
||||
context.irBuiltIns.stringType,
|
||||
backingFieldSymbol.descriptor.name.asString()
|
||||
name.asString()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
+5
-4
@@ -8,19 +8,20 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.builders.irGetObject
|
||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
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.types.typeUtil.isUnit
|
||||
|
||||
internal class ReturnsInsertionLowering(val context: Context) : FileLoweringPass {
|
||||
private val symbols = context.ir.symbols
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.acceptVoid(object : IrElementVisitorVoid {
|
||||
@@ -32,10 +33,10 @@ internal class ReturnsInsertionLowering(val context: Context) : FileLoweringPass
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
val body = declaration.body
|
||||
if ((declaration.descriptor is ConstructorDescriptor || declaration.descriptor.returnType!!.isUnit()) && body != null) {
|
||||
if ((declaration is IrConstructor || declaration.returnType.classifierOrNull == symbols.unit) && body != null) {
|
||||
val irBuilder = context.createIrBuilder(declaration.symbol, declaration.startOffset, declaration.endOffset)
|
||||
irBuilder.run {
|
||||
(body as IrBlockBody).statements += irReturn(irGetObject(this@ReturnsInsertionLowering.context.ir.symbols.unit))
|
||||
(body as IrBlockBody).statements += irReturn(irGetObject(symbols.unit))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-127
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import java.util.*
|
||||
|
||||
object CoroutineIntrinsicLambdaOrigin: IrStatementOriginImpl("Coroutine intrinsic lambda")
|
||||
|
||||
// TODO: Fix .parent for variables and use from common backend.
|
||||
class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPass {
|
||||
override fun lower(irFunction: IrFunction) {
|
||||
SharedVariablesTransformer(irFunction).lowerSharedVariables()
|
||||
}
|
||||
|
||||
private inner class SharedVariablesTransformer(val irFunction: IrFunction) {
|
||||
val sharedVariables = mutableSetOf<IrVariable>()
|
||||
|
||||
fun lowerSharedVariables() {
|
||||
collectSharedVariables()
|
||||
if (sharedVariables.isEmpty()) return
|
||||
|
||||
rewriteSharedVariables()
|
||||
}
|
||||
|
||||
private fun collectSharedVariables() {
|
||||
irFunction.acceptVoid(object : IrElementVisitorVoid {
|
||||
val relevantVars = mutableSetOf<IrVariable>()
|
||||
val functionsVariables = mutableListOf<MutableSet<IrVariable>>()
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
functionsVariables.push(mutableSetOf())
|
||||
declaration.acceptChildrenVoid(this)
|
||||
functionsVariables.pop()
|
||||
}
|
||||
|
||||
override fun visitContainerExpression(expression: IrContainerExpression) {
|
||||
if (expression !is IrReturnableBlock || expression.origin != CoroutineIntrinsicLambdaOrigin)
|
||||
super.visitContainerExpression(expression)
|
||||
else {
|
||||
functionsVariables.push(mutableSetOf())
|
||||
expression.acceptChildrenVoid(this)
|
||||
functionsVariables.pop()
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitVariable(declaration: IrVariable) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
if (declaration.isVar) {
|
||||
relevantVars.add(declaration)
|
||||
functionsVariables.peek()!!.add(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitVariableAccess(expression: IrValueAccessExpression) {
|
||||
expression.acceptChildrenVoid(this)
|
||||
|
||||
val value = expression.symbol.owner
|
||||
//if (descriptor in relevantVars && descriptor.containingDeclaration != currentDeclaration) {
|
||||
// TODO: fix lowerings to match check `(value as IrVariable).parent != currentDeclaration`
|
||||
if (value in relevantVars && !functionsVariables.peek()!!.contains(value)) {
|
||||
sharedVariables.add(value as IrVariable)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun rewriteSharedVariables() {
|
||||
val transformedVariableSymbols = HashMap<IrValueSymbol, IrVariableSymbol>()
|
||||
|
||||
irFunction.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitVariable(declaration: IrVariable): IrStatement {
|
||||
declaration.transformChildrenVoid(this)
|
||||
|
||||
if (declaration !in sharedVariables) return declaration
|
||||
|
||||
val newDeclaration = context.sharedVariablesManager.declareSharedVariable(declaration)
|
||||
transformedVariableSymbols[declaration.symbol] = newDeclaration.symbol
|
||||
|
||||
return context.sharedVariablesManager.defineSharedValue(declaration, newDeclaration)
|
||||
}
|
||||
})
|
||||
|
||||
irFunction.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val newSymbol = getTransformedSymbol(expression.symbol) ?: return expression
|
||||
|
||||
return context.sharedVariablesManager.getSharedValue(newSymbol, expression)
|
||||
}
|
||||
|
||||
override fun visitSetVariable(expression: IrSetVariable): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val newDescriptor = getTransformedSymbol(expression.symbol) ?: return expression
|
||||
|
||||
return context.sharedVariablesManager.setSharedValue(newDescriptor, expression)
|
||||
}
|
||||
|
||||
private fun getTransformedSymbol(oldSymbol: IrValueSymbol): IrVariableSymbol? =
|
||||
transformedVariableSymbols.getOrElse(oldSymbol) {
|
||||
assert(oldSymbol.owner !in sharedVariables) {
|
||||
"Shared variable is not transformed: $oldSymbol"
|
||||
}
|
||||
null
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
+472
-602
File diff suppressed because it is too large
Load Diff
+235
-301
@@ -5,47 +5,38 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.replace
|
||||
import org.jetbrains.kotlin.backend.common.ir.createFakeOverrideDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope
|
||||
import org.jetbrains.kotlin.backend.common.lower.SymbolWithIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.reportWarning
|
||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithoutArguments
|
||||
import org.jetbrains.kotlin.backend.konan.SYNTHETIC_OFFSET
|
||||
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
internal class TestProcessor (val context: KonanBackendContext) {
|
||||
@@ -60,72 +51,65 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
val IGNORE_FQ_NAME = FqName.fromSegments(listOf("kotlin", "test" , "Ignore"))
|
||||
}
|
||||
|
||||
val symbols = context.ir.symbols
|
||||
private val symbols = context.ir.symbols
|
||||
|
||||
val baseClassSuiteDescriptor = symbols.baseClassSuite.descriptor
|
||||
private val baseClassSuite = symbols.baseClassSuite.owner
|
||||
|
||||
private val topLevelSuiteNames = mutableSetOf<String>()
|
||||
|
||||
// region Useful extensions.
|
||||
var testSuiteCnt = 0
|
||||
fun Name.synthesizeSuiteClassName() = identifier.synthesizeSuiteClassName()
|
||||
fun String.synthesizeSuiteClassName() = "$this\$test\$${testSuiteCnt++}".synthesizedName
|
||||
private var testSuiteCnt = 0
|
||||
private fun Name.synthesizeSuiteClassName() = identifier.synthesizeSuiteClassName()
|
||||
private fun String.synthesizeSuiteClassName() = "$this\$test\$${testSuiteCnt++}".synthesizedName
|
||||
|
||||
// IrFile always uses a forward slash as a directory separator.
|
||||
private val IrFile.fileName
|
||||
get() = name.substringAfterLast('/')
|
||||
|
||||
private val IrFile.topLevelSuiteName: String
|
||||
get() {
|
||||
val packageFqName = packageFragmentDescriptor.fqName
|
||||
val packageFqName = fqName
|
||||
val shortFileName = PackagePartClassUtils.getFilePartShortName(fileName)
|
||||
return if (packageFqName.isRoot) shortFileName else "$packageFqName.$shortFileName"
|
||||
}
|
||||
|
||||
private fun MutableList<TestFunction>.registerFunction(
|
||||
function: IrFunctionSymbol,
|
||||
function: IrFunction,
|
||||
kinds: Collection<Pair<FunctionKind, /* ignored: */ Boolean>>) =
|
||||
kinds.forEach { (kind, ignored) ->
|
||||
add(TestFunction(function, kind, ignored))
|
||||
}
|
||||
|
||||
private fun MutableList<TestFunction>.registerFunction(
|
||||
function: IrFunctionSymbol,
|
||||
function: IrFunction,
|
||||
kind: FunctionKind,
|
||||
ignored: Boolean
|
||||
) = add(TestFunction(function, kind, ignored))
|
||||
|
||||
private fun <T: IrElement> IrStatementsBuilder<T>.generateFunctionRegistration(
|
||||
receiver: IrValueDeclaration,
|
||||
registerTestCase: IrFunctionSymbol,
|
||||
registerFunction: IrFunctionSymbol,
|
||||
registerTestCase: IrFunction,
|
||||
registerFunction: IrFunction,
|
||||
functions: Collection<TestFunction>) {
|
||||
functions.forEach {
|
||||
if (it.kind == FunctionKind.TEST) {
|
||||
// Call registerTestCase(name: String, testFunction: () -> Unit) method.
|
||||
+irCall(registerTestCase, registerTestCase.descriptor.returnType!!.toErasedIrType()).apply {
|
||||
+irCall(registerTestCase).apply {
|
||||
dispatchReceiver = irGet(receiver)
|
||||
putValueArgument(0, IrConstImpl.string(
|
||||
SYNTHETIC_OFFSET,
|
||||
SYNTHETIC_OFFSET,
|
||||
context.irBuiltIns.stringType,
|
||||
it.function.descriptor.name.identifier)
|
||||
)
|
||||
putValueArgument(0, irString(it.function.name.identifier))
|
||||
putValueArgument(1, IrFunctionReferenceImpl(
|
||||
SYNTHETIC_OFFSET,
|
||||
SYNTHETIC_OFFSET,
|
||||
descriptor.valueParameters[1].type.toErasedIrType(),
|
||||
it.function,
|
||||
it.function.descriptor, 0))
|
||||
putValueArgument(2, IrConstImpl.boolean(
|
||||
SYNTHETIC_OFFSET,
|
||||
SYNTHETIC_OFFSET,
|
||||
context.irBuiltIns.booleanType,
|
||||
it.ignored
|
||||
))
|
||||
registerTestCase.valueParameters[1].type,
|
||||
it.function.symbol,
|
||||
it.function.descriptor,
|
||||
typeArgumentsCount = 0,
|
||||
valueArgumentsCount = 0))
|
||||
putValueArgument(2, irBoolean(it.ignored))
|
||||
}
|
||||
} else {
|
||||
// Call registerFunction(kind: TestFunctionKind, () -> Unit) method.
|
||||
+irCall(registerFunction, registerFunction.descriptor.returnType!!.toErasedIrType()).apply {
|
||||
+irCall(registerFunction).apply {
|
||||
dispatchReceiver = irGet(receiver)
|
||||
val testKindEntry = it.kind.runtimeKind
|
||||
putValueArgument(0, IrGetEnumValueImpl(
|
||||
@@ -134,12 +118,13 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
symbols.testFunctionKind.typeWithoutArguments,
|
||||
testKindEntry)
|
||||
)
|
||||
putValueArgument(1, IrFunctionReferenceImpl(
|
||||
putValueArgument(1, IrFunctionReferenceImpl(SYNTHETIC_OFFSET,
|
||||
SYNTHETIC_OFFSET,
|
||||
SYNTHETIC_OFFSET,
|
||||
descriptor.valueParameters[1].type.toErasedIrType(),
|
||||
it.function,
|
||||
it.function.descriptor, 0))
|
||||
registerFunction.valueParameters[1].type,
|
||||
it.function.symbol,
|
||||
it.function.descriptor,
|
||||
typeArgumentsCount = 0,
|
||||
valueArgumentsCount = 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,7 +134,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
// region Classes for annotation collection.
|
||||
internal enum class FunctionKind(annotationNameString: String, runtimeKindString: String) {
|
||||
TEST("kotlin.test.Test", "") {
|
||||
override val runtimeKindName: Name get() = throw NotImplementedError()
|
||||
override val runtimeKindName: Name get() = throw NotImplementedError()
|
||||
},
|
||||
|
||||
BEFORE_EACH("kotlin.test.BeforeEach", "BEFORE_EACH"),
|
||||
@@ -169,34 +154,34 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
private val FunctionKind.runtimeKind: IrEnumEntrySymbol
|
||||
get() = symbols.getTestFunctionKind(this)
|
||||
|
||||
private fun IrType.isTestFunctionKind() = classifierOrNull == symbols.testFunctionKind
|
||||
|
||||
private data class TestFunction(
|
||||
val function: IrFunctionSymbol,
|
||||
val function: IrFunction,
|
||||
val kind: FunctionKind,
|
||||
val ignored: Boolean
|
||||
)
|
||||
|
||||
private inner class TestClass(val ownerClass: IrClassSymbol) {
|
||||
var companion: IrClassSymbol? = null
|
||||
private inner class TestClass(val ownerClass: IrClass) {
|
||||
var companion: IrClass? = null
|
||||
val functions = mutableListOf<TestFunction>()
|
||||
|
||||
fun registerFunction(
|
||||
function: IrFunctionSymbol,
|
||||
function: IrFunction,
|
||||
kinds: Collection<Pair<FunctionKind, /* ignored: */ Boolean>>
|
||||
) = functions.registerFunction(function, kinds)
|
||||
fun registerFunction(function: IrFunctionSymbol, kind: FunctionKind, ignored: Boolean) =
|
||||
|
||||
fun registerFunction(function: IrFunction, kind: FunctionKind, ignored: Boolean) =
|
||||
functions.registerFunction(function, kind, ignored)
|
||||
}
|
||||
|
||||
private inner class AnnotationCollector(val irFile: IrFile) : IrElementVisitorVoid {
|
||||
val testClasses = mutableMapOf<IrClassSymbol, TestClass>()
|
||||
val testClasses = mutableMapOf<IrClass, TestClass>()
|
||||
val topLevelFunctions = mutableListOf<TestFunction>()
|
||||
|
||||
private fun MutableMap<IrClassSymbol, TestClass>.getTestClass(key: IrClassSymbol) =
|
||||
private fun MutableMap<IrClass, TestClass>.getTestClass(key: IrClass) =
|
||||
getOrPut(key) { TestClass(key) }
|
||||
|
||||
private fun MutableMap<IrClassSymbol, TestClass>.getTestClass(key: ClassDescriptor) =
|
||||
getTestClass(symbols.symbolTable.referenceClass(key))
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
@@ -227,45 +212,50 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
}
|
||||
}
|
||||
|
||||
fun registerClassFunction(classDescriptor: ClassDescriptor,
|
||||
function: IrFunctionSymbol,
|
||||
fun registerClassFunction(irClass: IrClass,
|
||||
function: IrFunction,
|
||||
kinds: Collection<Pair<FunctionKind, /* ignored: */ Boolean>>) {
|
||||
|
||||
fun warn(msg: String) = context.reportWarning(msg, irFile, function.owner)
|
||||
fun warn(msg: String) = context.reportWarning(msg, irFile, function)
|
||||
|
||||
kinds.forEach { (kind, ignored) ->
|
||||
val annotation = kind.annotationFqName
|
||||
when (kind) {
|
||||
in FunctionKind.INSTANCE_KINDS -> with(classDescriptor) {
|
||||
in FunctionKind.INSTANCE_KINDS -> with(irClass) {
|
||||
when {
|
||||
isInner ->
|
||||
warn("Annotation $annotation is not allowed for methods of an inner class")
|
||||
|
||||
isAbstract() -> {
|
||||
// We cannot create an abstract test class but it's allowed to mark its methods as
|
||||
// tests because the class can be extended. So skip this case without warnings.
|
||||
}
|
||||
isCompanionObject ->
|
||||
|
||||
isCompanion ->
|
||||
warn("Annotation $annotation is not allowed for methods of a companion object")
|
||||
|
||||
constructors.none { it.valueParameters.size == 0 } ->
|
||||
warn("Test class has no default constructor: ${fqNameSafe}")
|
||||
warn("Test class has no default constructor: $fqNameSafe")
|
||||
|
||||
else ->
|
||||
testClasses.getTestClass(classDescriptor).registerFunction(function, kind, ignored)
|
||||
testClasses.getTestClass(irClass).registerFunction(function, kind, ignored)
|
||||
}
|
||||
}
|
||||
in FunctionKind.COMPANION_KINDS ->
|
||||
when {
|
||||
classDescriptor.isCompanionObject -> {
|
||||
val containingClass = classDescriptor.containingDeclaration as ClassDescriptor
|
||||
irClass.isCompanion -> {
|
||||
val containingClass = irClass.parentAsClass
|
||||
val testClass = testClasses.getTestClass(containingClass)
|
||||
testClass.companion = symbols.symbolTable.referenceClass(classDescriptor)
|
||||
testClass.companion = irClass
|
||||
testClass.registerFunction(function, kind, ignored)
|
||||
}
|
||||
classDescriptor.kind == ClassKind.OBJECT -> {
|
||||
testClasses.getTestClass(classDescriptor).registerFunction(function, kind, ignored)
|
||||
|
||||
irClass.kind == ClassKind.OBJECT -> {
|
||||
testClasses.getTestClass(irClass).registerFunction(function, kind, ignored)
|
||||
}
|
||||
|
||||
else -> warn("Annotation $annotation is only allowed for methods of an object " +
|
||||
"(named or companion) or top level functions")
|
||||
|
||||
}
|
||||
else -> throw IllegalStateException("Unreachable")
|
||||
}
|
||||
@@ -274,14 +264,14 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
|
||||
fun IrFunction.checkFunctionSignature() {
|
||||
// Test runner requires test functions to have the following signature: () -> Unit.
|
||||
if (descriptor.returnType != context.builtIns.unitType) {
|
||||
if (!returnType.isUnit()) {
|
||||
context.reportCompilationError(
|
||||
"Test function must return Unit: ${descriptor.fqNameSafe}", irFile, this
|
||||
"Test function must return Unit: $fqNameSafe", irFile, this
|
||||
)
|
||||
}
|
||||
if (descriptor.valueParameters.isNotEmpty()) {
|
||||
if (valueParameters.isNotEmpty()) {
|
||||
context.reportCompilationError(
|
||||
"Test function must have no arguments: ${descriptor.fqNameSafe}", irFile, this
|
||||
"Test function must have no arguments: $fqNameSafe", irFile, this
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -314,7 +304,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
// TODO: Use symbols instead of containingDeclaration when such information is available.
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
val symbol = declaration.symbol
|
||||
val owner = declaration.descriptor.containingDeclaration
|
||||
val parent = declaration.parent
|
||||
|
||||
warnAboutLoneIgnore(symbol)
|
||||
val kinds = FunctionKind.values().mapNotNull { kind ->
|
||||
@@ -329,10 +319,10 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
}
|
||||
declaration.checkFunctionSignature()
|
||||
|
||||
when (owner) {
|
||||
is PackageFragmentDescriptor -> topLevelFunctions.registerFunction(symbol, kinds)
|
||||
is ClassDescriptor -> registerClassFunction(owner, symbol, kinds)
|
||||
else -> UnsupportedOperationException("Cannot create test function $declaration (defined in $owner")
|
||||
when (parent) {
|
||||
is IrPackageFragment -> topLevelFunctions.registerFunction(declaration, kinds)
|
||||
is IrClass -> registerClassFunction(parent, declaration, kinds)
|
||||
else -> UnsupportedOperationException("Cannot create test function $declaration (defined in $parent")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -340,60 +330,36 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
|
||||
//region Symbol and IR builders
|
||||
|
||||
/** Base class for getters (createInstance and getCompanion). */
|
||||
private abstract inner class GetterBuilder(val returnType: IrType,
|
||||
val testSuite: IrClassSymbol,
|
||||
val getterName: Name)
|
||||
: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrFunction>() {
|
||||
|
||||
val superFunction = baseClassSuiteDescriptor
|
||||
.unsubstitutedMemberScope
|
||||
.getContributedFunctions(getterName, NoLookupLocation.FROM_BACKEND)
|
||||
.single { it.valueParameters.isEmpty() }
|
||||
|
||||
|
||||
override fun doInitialize() {
|
||||
val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl
|
||||
descriptor.initialize(
|
||||
/* receiverParameterType = */ null,
|
||||
/* dispatchReceiverParameter = */ testSuite.descriptor.thisAsReceiverParameter,
|
||||
/* typeParameters = */ emptyList(),
|
||||
/* unsubstitutedValueParameters = */ emptyList(),
|
||||
/* returnType = */ returnType.toKotlinType(),
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PROTECTED
|
||||
).apply {
|
||||
overriddenDescriptors += superFunction
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||
SimpleFunctionDescriptorImpl.create(
|
||||
/* containingDeclaration = */ testSuite.descriptor,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* name = */ getterName,
|
||||
/* kind = */ CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
/* source = */ SourceElement.NO_SOURCE
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a method in `[testSuite]` class with name `[getterName]`
|
||||
* Builds a method in `[owner]` class with name `[getterName]`
|
||||
* returning a reference to an object represented by `[objectSymbol]`.
|
||||
*/
|
||||
private inner class ObjectGetterBuilder(val objectSymbol: IrClassSymbol, testSuite: IrClassSymbol, getterName: Name)
|
||||
: GetterBuilder(objectSymbol.typeWithoutArguments, testSuite, getterName) {
|
||||
|
||||
override fun buildIr(): IrFunction = IrFunctionImpl(
|
||||
private fun buildObjectGetter(objectSymbol: IrClassSymbol,
|
||||
owner: IrClass,
|
||||
getterName: Name) = WrappedSimpleFunctionDescriptor().let { descriptor ->
|
||||
IrFunctionImpl(
|
||||
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
|
||||
TEST_SUITE_GENERATED_MEMBER,
|
||||
symbol,
|
||||
this@ObjectGetterBuilder.returnType
|
||||
IrSimpleFunctionSymbolImpl(descriptor),
|
||||
getterName,
|
||||
Visibilities.PROTECTED,
|
||||
Modality.FINAL,
|
||||
objectSymbol.typeWithStarProjections,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = false
|
||||
).apply {
|
||||
val builder = context.createIrBuilder(symbol)
|
||||
createParameterDeclarations(context.ir.symbols.symbolTable)
|
||||
body = builder.irBlockBody {
|
||||
descriptor.bind(this)
|
||||
parent = owner
|
||||
|
||||
val superFunction = baseClassSuite.simpleFunctions()
|
||||
.single { it.name == getterName && it.valueParameters.isEmpty() }
|
||||
|
||||
createDispatchReceiverParameter()
|
||||
overriddenSymbols += superFunction.symbol
|
||||
|
||||
body = context.createIrBuilder(symbol).irBlockBody {
|
||||
+irReturn(IrGetObjectValueImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
|
||||
objectSymbol.typeWithoutArguments, objectSymbol)
|
||||
)
|
||||
@@ -405,234 +371,202 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
* Builds a method in `[testSuite]` class with name `[getterName]`
|
||||
* returning a new instance of class referenced by [classSymbol].
|
||||
*/
|
||||
private inner class InstanceGetterBuilder(val classSymbol: IrClassSymbol, testSuite: IrClassSymbol, getterName: Name)
|
||||
: GetterBuilder(classSymbol.typeWithStarProjections, testSuite, getterName) {
|
||||
|
||||
override fun buildIr() = IrFunctionImpl(
|
||||
private fun buildInstanceGetter(classSymbol: IrClassSymbol,
|
||||
owner: IrClass,
|
||||
getterName: Name) = WrappedSimpleFunctionDescriptor().let { descriptor ->
|
||||
IrFunctionImpl(
|
||||
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
|
||||
TEST_SUITE_GENERATED_MEMBER,
|
||||
symbol,
|
||||
this@InstanceGetterBuilder.returnType
|
||||
IrSimpleFunctionSymbolImpl(descriptor),
|
||||
getterName,
|
||||
Visibilities.PROTECTED,
|
||||
Modality.FINAL,
|
||||
classSymbol.typeWithStarProjections,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = false
|
||||
).apply {
|
||||
val builder = context.createIrBuilder(symbol)
|
||||
createParameterDeclarations(context.ir.symbols.symbolTable)
|
||||
body = builder.irBlockBody {
|
||||
descriptor.bind(this)
|
||||
parent = owner
|
||||
|
||||
val superFunction = baseClassSuite.simpleFunctions()
|
||||
.single { it.name == getterName && it.valueParameters.isEmpty() }
|
||||
|
||||
createDispatchReceiverParameter()
|
||||
overriddenSymbols += superFunction.symbol
|
||||
|
||||
body = context.createIrBuilder(symbol).irBlockBody {
|
||||
val constructor = classSymbol.owner.constructors.single { it.valueParameters.isEmpty() }
|
||||
+irReturn(irCall(constructor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val baseClassSuiteConstructor = baseClassSuite.constructors.single {
|
||||
it.valueParameters.size == 2
|
||||
&& it.valueParameters[0].type.isString() // name: String
|
||||
&& it.valueParameters[1].type.isBoolean() // ignored: Boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a constructor for a test suite class representing a test class (any class in the original IrFile with
|
||||
* method(s) annotated with @Test). The test suite class is a subclass of ClassTestSuite<T>
|
||||
* where T is the test class.
|
||||
*/
|
||||
private inner class ClassSuiteConstructorBuilder(val suiteName: String,
|
||||
val testClassType: KotlinType,
|
||||
val testCompanionType: KotlinType,
|
||||
val testSuite: IrClassSymbol,
|
||||
val functions: Collection<TestFunction>,
|
||||
val ignored: Boolean)
|
||||
: SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
||||
|
||||
private fun IrClassSymbol.getFunction(name: String, predicate: (FunctionDescriptor) -> Boolean) =
|
||||
symbols.symbolTable.referenceFunction(descriptor.unsubstitutedMemberScope
|
||||
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
|
||||
.single(predicate))
|
||||
|
||||
override fun buildIr() = IrConstructorImpl(
|
||||
private fun buildClassSuiteConstructor(suiteName: String,
|
||||
testClassType: IrType,
|
||||
testCompanionType: IrType,
|
||||
testSuite: IrClassSymbol,
|
||||
owner: IrClass,
|
||||
functions: Collection<TestFunction>,
|
||||
ignored: Boolean) = WrappedClassConstructorDescriptor().let { descriptor ->
|
||||
IrConstructorImpl(
|
||||
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
|
||||
TEST_SUITE_GENERATED_MEMBER,
|
||||
symbol,
|
||||
testSuite.typeWithStarProjections
|
||||
IrConstructorSymbolImpl(descriptor),
|
||||
Name.special("<init>"),
|
||||
Visibilities.PUBLIC,
|
||||
testSuite.typeWithStarProjections,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isPrimary = true
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
parent = owner
|
||||
|
||||
createParameterDeclarations(context.ir.symbols.symbolTable)
|
||||
fun IrClass.getFunction(name: String, predicate: (IrSimpleFunction) -> Boolean) =
|
||||
simpleFunctions().single { it.name.asString() == name && predicate(it) }
|
||||
|
||||
val registerTestCase = symbols.baseClassSuite.getFunction("registerTestCase") {
|
||||
it.valueParameters.size == 3 &&
|
||||
KotlinBuiltIns.isString(it.valueParameters[0].type) && // name: String
|
||||
it.valueParameters[1].type.isFunctionType && // function: testClassType.() -> Unit
|
||||
KotlinBuiltIns.isBoolean(it.valueParameters[2].type) // ignored: Boolean
|
||||
val registerTestCase = baseClassSuite.getFunction("registerTestCase") {
|
||||
it.valueParameters.size == 3
|
||||
&& it.valueParameters[0].type.isString() // name: String
|
||||
&& it.valueParameters[1].type.isFunction() // function: testClassType.() -> Unit
|
||||
&& it.valueParameters[2].type.isBoolean() // ignored: Boolean
|
||||
}
|
||||
val registerFunction = symbols.baseClassSuite.getFunction("registerFunction") {
|
||||
it.valueParameters.size == 2 &&
|
||||
it.valueParameters[0].type == symbols.testFunctionKind.descriptor.defaultType && // kind: TestFunctionKind
|
||||
it.valueParameters[1].type.isFunctionType // function: () -> Unit
|
||||
val registerFunction = baseClassSuite.getFunction("registerFunction") {
|
||||
it.valueParameters.size == 2
|
||||
&& it.valueParameters[0].type.isTestFunctionKind() // kind: TestFunctionKind
|
||||
&& it.valueParameters[1].type.isFunction() // function: () -> Unit
|
||||
}
|
||||
|
||||
body = context.createIrBuilder(symbol).irBlockBody {
|
||||
val superConstructor = symbols.baseClassSuiteConstructor
|
||||
+IrDelegatingConstructorCallImpl(
|
||||
startOffset = SYNTHETIC_OFFSET,
|
||||
endOffset = SYNTHETIC_OFFSET,
|
||||
type = context.irBuiltIns.unitType,
|
||||
symbol = symbols.symbolTable.referenceConstructor(superConstructor),
|
||||
descriptor = superConstructor,
|
||||
typeArgumentsCount = 2
|
||||
).apply {
|
||||
putTypeArgument(0, testClassType.toErasedIrType())
|
||||
putTypeArgument(1, testCompanionType.toErasedIrType())
|
||||
+irDelegatingConstructorCall(baseClassSuiteConstructor).apply {
|
||||
putTypeArgument(0, testClassType)
|
||||
putTypeArgument(1, testCompanionType)
|
||||
|
||||
putValueArgument(0, IrConstImpl.string(
|
||||
SYNTHETIC_OFFSET,
|
||||
SYNTHETIC_OFFSET,
|
||||
context.irBuiltIns.stringType,
|
||||
suiteName)
|
||||
)
|
||||
putValueArgument(1, IrConstImpl.boolean(
|
||||
SYNTHETIC_OFFSET,
|
||||
SYNTHETIC_OFFSET,
|
||||
context.irBuiltIns.booleanType,
|
||||
ignored
|
||||
))
|
||||
putValueArgument(0, irString(suiteName))
|
||||
putValueArgument(1, irBoolean(ignored))
|
||||
}
|
||||
generateFunctionRegistration(testSuite.owner.thisReceiver!!,
|
||||
registerTestCase, registerFunction, functions)
|
||||
}
|
||||
}
|
||||
|
||||
override fun doInitialize() {
|
||||
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||
descriptor.initialize(emptyList(), Visibilities.PUBLIC).apply {
|
||||
returnType = testSuite.descriptor.defaultType
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildSymbol() = IrConstructorSymbolImpl(
|
||||
ClassConstructorDescriptorImpl.createSynthesized(
|
||||
testSuite.descriptor,
|
||||
Annotations.EMPTY,
|
||||
true,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun KotlinType.toErasedIrType(): IrType = context.ir.translateErased(this)
|
||||
private val IrClass.ignored: Boolean get() = descriptor.annotations.hasAnnotation(IGNORE_FQ_NAME)
|
||||
|
||||
/**
|
||||
* Builds a test suite class representing a test class (any class in the original IrFile with method(s)
|
||||
* annotated with @Test). The test suite class is a subclass of ClassTestSuite<T> where T is the test class.
|
||||
*/
|
||||
private inner class ClassSuiteBuilder(testClass: IrClassSymbol,
|
||||
testCompanion: IrClassSymbol?,
|
||||
val containingDeclaration: DeclarationDescriptor,
|
||||
val functions: Collection<TestFunction>)
|
||||
: SymbolWithIrBuilder<IrClassSymbol, IrClass>() {
|
||||
|
||||
private val IrClassSymbol.ignored: Boolean get() = descriptor.annotations.hasAnnotation(IGNORE_FQ_NAME)
|
||||
private val IrClassSymbol.isObject: Boolean get() = descriptor.kind == ClassKind.OBJECT
|
||||
|
||||
val suiteName = testClass.descriptor.fqNameSafe.toString()
|
||||
val suiteClassName = testClass.descriptor.name.synthesizeSuiteClassName()
|
||||
|
||||
val testClassType = testClass.descriptor.defaultType
|
||||
val testCompanionType = if (testClass.isObject) {
|
||||
testClassType
|
||||
} else {
|
||||
testCompanion?.descriptor?.defaultType ?: context.irBuiltIns.nothing
|
||||
}
|
||||
|
||||
val superType = baseClassSuiteDescriptor.defaultType.replace(listOf(testClassType, testCompanionType))
|
||||
|
||||
val constructorBuilder = ClassSuiteConstructorBuilder(
|
||||
suiteName, testClassType, testCompanionType, symbol, functions, testClass.ignored
|
||||
)
|
||||
|
||||
val instanceGetterBuilder: GetterBuilder
|
||||
val companionGetterBuilder: GetterBuilder?
|
||||
|
||||
init {
|
||||
if (testClass.isObject) {
|
||||
instanceGetterBuilder = ObjectGetterBuilder(testClass, symbol, INSTANCE_GETTER_NAME)
|
||||
companionGetterBuilder = ObjectGetterBuilder(testClass, symbol, COMPANION_GETTER_NAME)
|
||||
} else {
|
||||
instanceGetterBuilder = InstanceGetterBuilder(testClass, symbol, INSTANCE_GETTER_NAME)
|
||||
companionGetterBuilder = testCompanion?.let {
|
||||
ObjectGetterBuilder(it, symbol, COMPANION_GETTER_NAME)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildIr() = symbols.symbolTable.declareClass(
|
||||
SYNTHETIC_OFFSET,
|
||||
SYNTHETIC_OFFSET,
|
||||
private fun buildClassSuite(testClass: IrClass,
|
||||
testCompanion: IrClass?,
|
||||
functions: Collection<TestFunction>) = WrappedClassDescriptor().let { descriptor ->
|
||||
IrClassImpl(
|
||||
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
|
||||
TEST_SUITE_CLASS,
|
||||
symbol.descriptor).apply {
|
||||
IrClassSymbolImpl(descriptor),
|
||||
testClass.name.synthesizeSuiteClassName(),
|
||||
ClassKind.CLASS,
|
||||
Visibilities.PRIVATE,
|
||||
Modality.FINAL,
|
||||
isCompanion = false,
|
||||
isInner = false,
|
||||
isData = false,
|
||||
isExternal = false,
|
||||
isInline = false
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
createParameterDeclarations()
|
||||
addMember(constructorBuilder.ir)
|
||||
addMember(instanceGetterBuilder.ir)
|
||||
companionGetterBuilder?.let { addMember(it.ir) }
|
||||
addFakeOverrides(symbols.symbolTable)
|
||||
setSuperSymbols(symbols.symbolTable)
|
||||
}
|
||||
|
||||
override fun doInitialize() {
|
||||
val descriptor = symbol.descriptor as ClassDescriptorImpl
|
||||
val constructorDescriptor = constructorBuilder.symbol.descriptor
|
||||
val testClassType = testClass.defaultType
|
||||
val testCompanionType = if (testClass.kind == ClassKind.OBJECT) {
|
||||
testClassType
|
||||
} else {
|
||||
testCompanion?.defaultType ?: context.irBuiltIns.nothingType
|
||||
}
|
||||
|
||||
val contributedDescriptors = baseClassSuiteDescriptor
|
||||
.unsubstitutedMemberScope
|
||||
.getContributedDescriptors()
|
||||
.map {
|
||||
when {
|
||||
it == instanceGetterBuilder.superFunction -> instanceGetterBuilder.symbol.descriptor
|
||||
it == companionGetterBuilder?.superFunction -> companionGetterBuilder.symbol.descriptor
|
||||
else -> it.createFakeOverrideDescriptor(symbol.descriptor as ClassDescriptorImpl)
|
||||
}
|
||||
}.filterNotNull()
|
||||
|
||||
descriptor.initialize(
|
||||
SimpleMemberScope(contributedDescriptors),setOf(constructorDescriptor), constructorDescriptor
|
||||
val constructor = buildClassSuiteConstructor(
|
||||
testClass.fqNameSafe.toString(), testClassType, testCompanionType,
|
||||
symbol, this, functions, testClass.ignored
|
||||
)
|
||||
|
||||
constructorBuilder.initialize()
|
||||
instanceGetterBuilder.initialize()
|
||||
companionGetterBuilder?.initialize()
|
||||
}
|
||||
val instanceGetter: IrFunction
|
||||
val companionGetter: IrFunction?
|
||||
|
||||
override fun buildSymbol() = symbols.symbolTable.referenceClass(
|
||||
ClassDescriptorImpl(
|
||||
/* containingDeclaration = */ containingDeclaration,
|
||||
/* name = */ suiteClassName,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* kind = */ ClassKind.CLASS,
|
||||
/* superTypes = */ listOf(superType),
|
||||
/* source = */ SourceElement.NO_SOURCE,
|
||||
/* isExternal = */ false,
|
||||
/* storageManager = */ LockBasedStorageManager.NO_LOCKS
|
||||
)
|
||||
)
|
||||
if (testClass.kind == ClassKind.OBJECT) {
|
||||
instanceGetter = buildObjectGetter(testClass.symbol, this, INSTANCE_GETTER_NAME)
|
||||
companionGetter = buildObjectGetter(testClass.symbol, this, COMPANION_GETTER_NAME)
|
||||
} else {
|
||||
instanceGetter = buildInstanceGetter(testClass.symbol, this, INSTANCE_GETTER_NAME)
|
||||
companionGetter = testCompanion?.let {
|
||||
buildObjectGetter(it.symbol, this, COMPANION_GETTER_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
declarations += constructor
|
||||
declarations += instanceGetter
|
||||
companionGetter?.let { declarations += it }
|
||||
|
||||
superTypes += symbols.baseClassSuite.typeWith(listOf(testClassType, testCompanionType))
|
||||
addFakeOverrides()
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
// region IR generation methods
|
||||
private fun generateClassSuite(irFile: IrFile, testClass: TestClass) =
|
||||
with(ClassSuiteBuilder(testClass.ownerClass,
|
||||
testClass.companion,
|
||||
irFile.packageFragmentDescriptor,
|
||||
testClass.functions)) {
|
||||
initialize()
|
||||
irFile.addChild(ir)
|
||||
val irConstructor = ir.constructors.single()
|
||||
irFile.addTopLevelInitializer(
|
||||
IrCallImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, irConstructor.returnType, irConstructor.symbol),
|
||||
context, threadLocal = true)
|
||||
with(buildClassSuite(testClass.ownerClass, testClass.companion,testClass.functions)) {
|
||||
irFile.addChild(this)
|
||||
val irConstructor = constructors.single()
|
||||
context.createIrBuilder(irFile.symbol).run {
|
||||
irFile.addTopLevelInitializer(
|
||||
irCall(irConstructor),
|
||||
this@TestProcessor.context,
|
||||
threadLocal = true)
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if this fqName already used or not. */
|
||||
private fun checkSuiteName(irFile: IrFile, name: String): Boolean {
|
||||
if (topLevelSuiteNames.contains(name)) {
|
||||
context.reportCompilationError("Package '${irFile.packageFragmentDescriptor.fqName}' has top-level test " +
|
||||
context.reportCompilationError("Package '${irFile.fqName}' has top-level test " +
|
||||
"functions in several files with the same name: '${irFile.fileName}'")
|
||||
return false
|
||||
}
|
||||
topLevelSuiteNames.add(name)
|
||||
return true
|
||||
}
|
||||
|
||||
private val topLevelSuite = symbols.topLevelSuite.owner
|
||||
private val topLevelSuiteConstructor = topLevelSuite.constructors.single {
|
||||
it.valueParameters.size == 1
|
||||
&& it.valueParameters[0].type.isString()
|
||||
}
|
||||
private val topLevelSuiteRegisterFunction = topLevelSuite.simpleFunctions().single {
|
||||
it.name.asString() == "registerFunction"
|
||||
&& it.valueParameters.size == 2
|
||||
&& it.valueParameters[0].type.isTestFunctionKind()
|
||||
&& it.valueParameters[1].type.isFunction()
|
||||
}
|
||||
private val topLevelSuiteRegisterTestCase = topLevelSuite.simpleFunctions().single {
|
||||
it.name.asString() == "registerTestCase"
|
||||
&& it.valueParameters.size == 3
|
||||
&& it.valueParameters[0].type.isString()
|
||||
&& it.valueParameters[1].type.isFunction()
|
||||
&& it.valueParameters[2].type.isBoolean()
|
||||
}
|
||||
|
||||
private fun generateTopLevelSuite(irFile: IrFile, functions: Collection<TestFunction>) {
|
||||
val builder = context.createIrBuilder(irFile.symbol)
|
||||
val suiteName = irFile.topLevelSuiteName
|
||||
@@ -643,14 +577,14 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
// TODO: an awful hack, we make this initializer thread local, so that it doesn't freeze suite,
|
||||
// and later on we could modify some suite's properties. This shall be redesigned.
|
||||
irFile.addTopLevelInitializer(builder.irBlock {
|
||||
val constructorCall = irCall(symbols.topLevelSuiteConstructor).apply {
|
||||
val constructorCall = irCall(topLevelSuiteConstructor).apply {
|
||||
putValueArgument(0, IrConstImpl.string(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
|
||||
context.irBuiltIns.stringType, suiteName))
|
||||
}
|
||||
val testSuiteVal = irTemporary(constructorCall, "topLevelTestSuite")
|
||||
generateFunctionRegistration(testSuiteVal,
|
||||
symbols.topLevelSuiteRegisterTestCase,
|
||||
symbols.topLevelSuiteRegisterFunction,
|
||||
topLevelSuiteRegisterTestCase,
|
||||
topLevelSuiteRegisterFunction,
|
||||
functions)
|
||||
}, context, threadLocal = true)
|
||||
}
|
||||
|
||||
+33
-44
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedString
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -38,7 +39,6 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
|
||||
class VarargInjectionLowering constructor(val context: CommonBackendContext): DeclarationContainerLoweringPass {
|
||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||
irDeclarationContainer.declarations.forEach{
|
||||
@@ -99,63 +99,53 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
|
||||
|
||||
override fun visitVararg(expression: IrVararg): IrExpression {
|
||||
expression.transformChildrenVoid(transformer)
|
||||
|
||||
val hasSpreadElement = hasSpreadElement(expression)
|
||||
val irBuilder = context.createIrBuilder(owner, expression.startOffset, expression.endOffset)
|
||||
irBuilder.run {
|
||||
return irBuilder.irBlock(expression, null, expression.type) {
|
||||
val type = expression.varargElementType
|
||||
log { "$expression: array type:$type, is array of primitives ${!expression.type.isArray()}" }
|
||||
val arrayHandle = arrayType(expression.type)
|
||||
val block = irBlock(expression.type)
|
||||
|
||||
val vars = expression.elements.map {
|
||||
val initVar = scope.createTemporaryVariable(
|
||||
(it as? IrSpreadElement)?.expression ?: it as IrExpression,
|
||||
"elem".synthesizedString, true)
|
||||
block.statements.add(initVar)
|
||||
it to initVar
|
||||
it to irTemporaryVar(
|
||||
(it as? IrSpreadElement)?.expression ?: it as IrExpression,
|
||||
"elem".synthesizedString
|
||||
)
|
||||
}.toMap()
|
||||
val arraySize = calculateArraySize(arrayHandle, hasSpreadElement, scope, expression, vars)
|
||||
val array = arrayHandle.createArray(this, expression.varargElementType, arraySize)
|
||||
|
||||
val arrayTmpVariable = scope.createTemporaryVariable(array, "array".synthesizedString, true)
|
||||
val indexTmpVariable = scope.createTemporaryVariable(kIntZero, "index".synthesizedString, true)
|
||||
block.statements.add(arrayTmpVariable)
|
||||
if (hasSpreadElement) {
|
||||
block.statements.add(indexTmpVariable)
|
||||
}
|
||||
val arrayTmpVariable = irTemporaryVar(array, "array".synthesizedString)
|
||||
lateinit var indexTmpVariable: IrVariable
|
||||
if (hasSpreadElement)
|
||||
indexTmpVariable = irTemporaryVar(kIntZero, "index".synthesizedString)
|
||||
expression.elements.forEachIndexed { i, element ->
|
||||
irBuilder.startOffset = element.startOffset
|
||||
irBuilder.endOffset = element.endOffset
|
||||
irBuilder.apply {
|
||||
log { "element:$i> ${ir2string(element)}" }
|
||||
val dst = vars[element]!!
|
||||
if (element !is IrSpreadElement) {
|
||||
val setArrayElementCall = irCall(arrayHandle.setMethodSymbol.owner)
|
||||
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable)
|
||||
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable) else irConstInt(i))
|
||||
setArrayElementCall.putValueArgument(1, irGet(dst))
|
||||
block.statements.add(setArrayElementCall)
|
||||
if (hasSpreadElement) {
|
||||
block.statements.add(incrementVariable(indexTmpVariable, kIntOne))
|
||||
}
|
||||
} else {
|
||||
val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst)), "length".synthesizedString)
|
||||
block.statements.add(arraySizeVariable)
|
||||
val copyCall = irCall(arrayHandle.copyRangeToSymbol.owner).apply {
|
||||
extensionReceiver = irGet(dst)
|
||||
putValueArgument(0, irGet(arrayTmpVariable)) /* destination */
|
||||
putValueArgument(1, kIntZero) /* fromIndex */
|
||||
putValueArgument(2, irGet(arraySizeVariable)) /* toIndex */
|
||||
putValueArgument(3, irGet(indexTmpVariable)) /* destinationIndex */
|
||||
}
|
||||
block.statements.add(copyCall)
|
||||
block.statements.add(incrementVariable(indexTmpVariable, irGet(arraySizeVariable)))
|
||||
log { "element:$i:spread element> ${ir2string(element.expression)}" }
|
||||
irBuilder.at(element.startOffset, element.endOffset)
|
||||
log { "element:$i> ${ir2string(element)}" }
|
||||
val dst = vars[element]!!
|
||||
if (element !is IrSpreadElement) {
|
||||
+irCall(arrayHandle.setMethodSymbol.owner).apply {
|
||||
dispatchReceiver = irGet(arrayTmpVariable)
|
||||
putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable) else irConstInt(i))
|
||||
putValueArgument(1, irGet(dst))
|
||||
}
|
||||
if (hasSpreadElement)
|
||||
+incrementVariable(indexTmpVariable, kIntOne)
|
||||
} else {
|
||||
val arraySizeVariable = irTemporary(irArraySize(arrayHandle, irGet(dst)), "length".synthesizedString)
|
||||
+irCall(arrayHandle.copyRangeToSymbol.owner).apply {
|
||||
extensionReceiver = irGet(dst)
|
||||
putValueArgument(0, irGet(arrayTmpVariable)) /* destination */
|
||||
putValueArgument(1, kIntZero) /* fromIndex */
|
||||
putValueArgument(2, irGet(arraySizeVariable)) /* toIndex */
|
||||
putValueArgument(3, irGet(indexTmpVariable)) /* destinationIndex */
|
||||
}
|
||||
+incrementVariable(indexTmpVariable, irGet(arraySizeVariable))
|
||||
log { "element:$i:spread element> ${ir2string(element.expression)}" }
|
||||
}
|
||||
}
|
||||
block.statements.add(irGet(arrayTmpVariable))
|
||||
return block
|
||||
+irGet(arrayTmpVariable)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -273,6 +263,5 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
|
||||
|
||||
private fun IrBuilderWithScope.irConstInt(value: Int): IrConst<Int> =
|
||||
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, value)
|
||||
private fun IrBuilderWithScope.irBlock(type: IrType): IrBlock = IrBlockImpl(startOffset, endOffset, type)
|
||||
private val IrBuilderWithScope.kIntZero get() = irConstInt(0)
|
||||
private val IrBuilderWithScope.kIntOne get() = irConstInt(1)
|
||||
|
||||
-1
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ internal class BackingFieldVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
if (declaration.isInner)
|
||||
declaration.addChild(context.specialDeclarationsFactory.getOuterThisField(declaration))
|
||||
declaration.declarations += context.specialDeclarationsFactory.getOuterThisField(declaration)
|
||||
|
||||
// Mark all dangling fields (they are created when class is inherited via delegation).
|
||||
declaration.declarations.filterIsInstance<IrField>().forEach {
|
||||
|
||||
+142
-252
@@ -6,22 +6,21 @@
|
||||
package org.jetbrains.kotlin.ir.util
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.substitute
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom
|
||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||
import org.jetbrains.kotlin.backend.konan.KonanCompilationException
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
@@ -30,14 +29,15 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.OverridingStrategy
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.isRestrictsSuspensionReceiver
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -50,38 +50,29 @@ internal fun IrExpression.isNullConst() = this is IrConst<*> && this.kind == IrC
|
||||
private var topLevelInitializersCounter = 0
|
||||
|
||||
internal fun IrFile.addTopLevelInitializer(expression: IrExpression, context: KonanBackendContext, threadLocal: Boolean) {
|
||||
val fieldDescriptor = PropertyDescriptorImpl.create(
|
||||
this.packageFragmentDescriptor,
|
||||
val descriptor = WrappedFieldDescriptor(
|
||||
if (threadLocal)
|
||||
Annotations.create(listOf(AnnotationDescriptorImpl(context.ir.symbols.threadLocal.defaultType,
|
||||
emptyMap(), SourceElement.NO_SOURCE)))
|
||||
else
|
||||
Annotations.EMPTY,
|
||||
Modality.FINAL,
|
||||
Visibilities.PRIVATE,
|
||||
false,
|
||||
"topLevelInitializer${topLevelInitializersCounter++}".synthesizedName,
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
SourceElement.NO_SOURCE,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
Annotations.EMPTY
|
||||
)
|
||||
|
||||
fieldDescriptor.setType(expression.type.toKotlinType(), emptyList(), null, null)
|
||||
fieldDescriptor.initialize(null, null)
|
||||
|
||||
val irField = IrFieldImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
IrDeclarationOrigin.DEFINED, fieldDescriptor, expression.type
|
||||
)
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrFieldSymbolImpl(descriptor),
|
||||
"topLevelInitializer${topLevelInitializersCounter++}".synthesizedName,
|
||||
expression.type,
|
||||
Visibilities.PRIVATE,
|
||||
isFinal = true,
|
||||
isExternal = false,
|
||||
isStatic = true
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
|
||||
irField.initializer = IrExpressionBodyImpl(expression.startOffset, expression.endOffset, expression)
|
||||
|
||||
this.addChild(irField)
|
||||
initializer = IrExpressionBodyImpl(expression.startOffset, expression.endOffset, expression)
|
||||
}
|
||||
addChild(irField)
|
||||
}
|
||||
|
||||
fun IrClass.addFakeOverrides(symbolTable: SymbolTable) {
|
||||
@@ -155,72 +146,6 @@ fun IrFunction.createParameterDeclarations(symbolTable: SymbolTable) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFakeOverride(
|
||||
descriptor: CallableMemberDescriptor,
|
||||
overriddenDeclarations: List<IrDeclaration>,
|
||||
irClass: IrClass
|
||||
): IrDeclaration {
|
||||
|
||||
// TODO: this function doesn't substitute types.
|
||||
fun IrSimpleFunction.copyFake(descriptor: FunctionDescriptor): IrSimpleFunction = IrFunctionImpl(
|
||||
irClass.startOffset, irClass.endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, descriptor, returnType
|
||||
).also {
|
||||
it.parent = irClass
|
||||
it.createDispatchReceiverParameter()
|
||||
|
||||
it.extensionReceiverParameter = this.extensionReceiverParameter?.let {
|
||||
IrValueParameterImpl(
|
||||
it.startOffset,
|
||||
it.endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
it.descriptor.extensionReceiverParameter!!,
|
||||
it.type,
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
this.valueParameters.mapTo(it.valueParameters) { oldParameter ->
|
||||
IrValueParameterImpl(
|
||||
oldParameter.startOffset,
|
||||
oldParameter.endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
it.descriptor.valueParameters[oldParameter.index],
|
||||
oldParameter.type,
|
||||
(oldParameter as? IrValueParameter)?.varargElementType
|
||||
)
|
||||
}
|
||||
|
||||
this.typeParameters.mapTo(it.typeParameters) { oldParameter ->
|
||||
IrTypeParameterImpl(
|
||||
irClass.startOffset,
|
||||
irClass.endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
it.descriptor.typeParameters[oldParameter.index]
|
||||
).apply {
|
||||
superTypes += oldParameter.superTypes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val copiedDeclaration = overriddenDeclarations.first()
|
||||
|
||||
return when (copiedDeclaration) {
|
||||
is IrSimpleFunction -> copiedDeclaration.copyFake(descriptor as FunctionDescriptor)
|
||||
is IrProperty -> IrPropertyImpl(
|
||||
irClass.startOffset,
|
||||
irClass.endOffset,
|
||||
IrDeclarationOrigin.FAKE_OVERRIDE,
|
||||
descriptor as PropertyDescriptor
|
||||
).apply {
|
||||
parent = irClass
|
||||
getter = copiedDeclaration.getter?.copyFake(descriptor.getter!!)
|
||||
setter = copiedDeclaration.setter?.copyFake(descriptor.setter!!)
|
||||
}
|
||||
else -> error(copiedDeclaration)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun IrSimpleFunction.setOverrides(symbolTable: ReferenceSymbolTable) {
|
||||
assert(this.overriddenSymbols.isEmpty())
|
||||
|
||||
@@ -229,44 +154,6 @@ fun IrSimpleFunction.setOverrides(symbolTable: ReferenceSymbolTable) {
|
||||
}
|
||||
}
|
||||
|
||||
fun IrClass.simpleFunctions(): List<IrSimpleFunction> = this.declarations.flatMap {
|
||||
when (it) {
|
||||
is IrSimpleFunction -> listOf(it)
|
||||
is IrProperty -> listOfNotNull(it.getter, it.setter)
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
fun IrClass.createParameterDeclarations() {
|
||||
thisReceiver = IrValueParameterImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.INSTANCE_RECEIVER,
|
||||
descriptor.thisAsReceiverParameter,
|
||||
this.symbol.typeWith(this.typeParameters.map { it.defaultType }),
|
||||
null
|
||||
).also { valueParameter ->
|
||||
valueParameter.parent = this
|
||||
}
|
||||
|
||||
assert(typeParameters.isEmpty())
|
||||
assert(descriptor.declaredTypeParameters.isEmpty())
|
||||
}
|
||||
|
||||
fun IrFunction.createDispatchReceiverParameter() {
|
||||
assert(this.dispatchReceiverParameter == null)
|
||||
|
||||
val descriptor = this.descriptor.dispatchReceiverParameter ?: return
|
||||
|
||||
this.dispatchReceiverParameter = IrValueParameterImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
descriptor,
|
||||
(parent as IrClass).defaultType,
|
||||
null
|
||||
).also { it.parent = this }
|
||||
}
|
||||
|
||||
fun IrClass.createParameterDeclarations(symbolTable: SymbolTable) {
|
||||
this.descriptor.declaredTypeParameters.mapTo(this.typeParameters) {
|
||||
IrTypeParameterImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, it).apply {
|
||||
@@ -283,29 +170,6 @@ fun IrClass.createParameterDeclarations(symbolTable: SymbolTable) {
|
||||
)
|
||||
}
|
||||
|
||||
fun IrClass.setSuperSymbols(superTypes: List<IrType>) {
|
||||
val supers = superTypes.map { it.getClass()!! }
|
||||
assert(this.superDescriptors().toSet() == supers.map { it.descriptor }.toSet())
|
||||
assert(this.superTypes.isEmpty())
|
||||
this.superTypes += superTypes
|
||||
|
||||
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: ReferenceSymbolTable) {
|
||||
assert(this.superTypes.isEmpty())
|
||||
this.descriptor.typeConstructor.supertypes.mapTo(this.superTypes) { symbolTable.translateErased(it) }
|
||||
@@ -315,52 +179,110 @@ fun IrClass.setSuperSymbols(symbolTable: ReferenceSymbolTable) {
|
||||
}
|
||||
}
|
||||
|
||||
fun IrClass.setSuperSymbolsAndAddFakeOverrides(superTypes: List<IrType>) {
|
||||
val overriddenSuperMembers = this.declarations.map { it.descriptor }
|
||||
.filterIsInstance<CallableMemberDescriptor>().flatMap { it.overriddenDescriptors.map { it.original } }.toSet()
|
||||
fun IrClass.simpleFunctions() = declarations.flatMap {
|
||||
when (it) {
|
||||
is IrSimpleFunction -> listOf(it)
|
||||
is IrProperty -> listOfNotNull(it.getter, it.setter)
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
val unoverriddenSuperMembers = superTypes.map { it.getClass()!! }.flatMap {
|
||||
it.declarations.filter { it.descriptor !in overriddenSuperMembers }.mapNotNull {
|
||||
when (it) {
|
||||
is IrSimpleFunction -> it.descriptor to it
|
||||
is IrProperty -> it.descriptor to it
|
||||
else -> null
|
||||
fun IrClass.createParameterDeclarations() {
|
||||
assert (thisReceiver == null)
|
||||
|
||||
thisReceiver = WrappedReceiverParameterDescriptor().let {
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.INSTANCE_RECEIVER,
|
||||
IrValueParameterSymbolImpl(it),
|
||||
Name.special("<this>"),
|
||||
0,
|
||||
symbol.typeWith(typeParameters.map { it.defaultType }),
|
||||
null,
|
||||
false,
|
||||
false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = this@createParameterDeclarations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun IrFunction.createDispatchReceiverParameter(origin: IrDeclarationOrigin? = null) {
|
||||
assert(dispatchReceiverParameter == null)
|
||||
|
||||
dispatchReceiverParameter = WrappedReceiverParameterDescriptor().let {
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset,
|
||||
origin ?: parentAsClass.origin,
|
||||
IrValueParameterSymbolImpl(it),
|
||||
Name.special("<this>"),
|
||||
0,
|
||||
parentAsClass.defaultType,
|
||||
null,
|
||||
false,
|
||||
false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = this@createDispatchReceiverParameter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun IrClass.addFakeOverrides() {
|
||||
fun IrDeclaration.toList() = when (this) {
|
||||
is IrSimpleFunction -> listOf(this)
|
||||
is IrProperty -> listOfNotNull(getter, setter)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
val overriddenFunctions = declarations
|
||||
.flatMap { it.toList() }
|
||||
.flatMap { it.overriddenSymbols.map { it.owner } }
|
||||
.toSet()
|
||||
|
||||
val unoverriddenSuperFunctions = superTypes
|
||||
.map { it.getClass()!! }
|
||||
.flatMap { irClass ->
|
||||
irClass.declarations
|
||||
.flatMap { it.toList() }
|
||||
.filter { it !in overriddenFunctions }
|
||||
}
|
||||
}
|
||||
}.toMap()
|
||||
.toMutableSet()
|
||||
|
||||
val irClass = this
|
||||
// TODO: A dirty hack.
|
||||
val groupedUnoverriddenSuperFunctions = unoverriddenSuperFunctions.groupBy { it.name.asString() + it.allParameters.size }
|
||||
|
||||
val overridingStrategy = object : OverridingStrategy() {
|
||||
override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) {
|
||||
val overriddenDeclarations =
|
||||
fakeOverride.overriddenDescriptors.map { unoverriddenSuperMembers[it]!! }
|
||||
fun createFakeOverride(overriddenFunctions: List<IrSimpleFunction>) =
|
||||
overriddenFunctions.first().let { irFunction ->
|
||||
val descriptor = WrappedSimpleFunctionDescriptor()
|
||||
IrFunctionImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
IrDeclarationOrigin.FAKE_OVERRIDE,
|
||||
IrSimpleFunctionSymbolImpl(descriptor),
|
||||
irFunction.name,
|
||||
Visibilities.INHERITED,
|
||||
Modality.OPEN,
|
||||
irFunction.returnType,
|
||||
irFunction.isInline,
|
||||
irFunction.isExternal,
|
||||
irFunction.isTailrec,
|
||||
irFunction.isSuspend
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
parent = this@addFakeOverrides
|
||||
overriddenSymbols += overriddenFunctions.map { it.symbol }
|
||||
copyParameterDeclarationsFrom(irFunction)
|
||||
}
|
||||
}
|
||||
|
||||
assert(overriddenDeclarations.isNotEmpty())
|
||||
val fakeOverriddenFunctions = groupedUnoverriddenSuperFunctions
|
||||
.asSequence()
|
||||
.associate { it.value.first() to createFakeOverride(it.value) }
|
||||
.toMutableMap()
|
||||
|
||||
irClass.declarations.add(createFakeOverride(fakeOverride, overriddenDeclarations, irClass))
|
||||
}
|
||||
|
||||
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.keys.groupBy { it.name }.forEach { (name, members) ->
|
||||
OverridingUtil.generateOverridesInFunctionGroup(
|
||||
name,
|
||||
members,
|
||||
emptyList(),
|
||||
this.descriptor,
|
||||
overridingStrategy
|
||||
)
|
||||
}
|
||||
|
||||
this.setSuperSymbols(superTypes)
|
||||
declarations += fakeOverriddenFunctions.values
|
||||
}
|
||||
|
||||
private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int =
|
||||
@@ -389,6 +311,11 @@ fun IrDeclarationContainer.addChild(declaration: IrDeclaration) {
|
||||
declaration.accept(SetDeclarationsParentVisitor, this)
|
||||
}
|
||||
|
||||
fun <T: IrElement> T.setDeclarationsParent(parent: IrDeclarationParent): T {
|
||||
accept(SetDeclarationsParentVisitor, parent)
|
||||
return this
|
||||
}
|
||||
|
||||
object SetDeclarationsParentVisitor : IrElementVisitor<Unit, IrDeclarationParent> {
|
||||
override fun visitElement(element: IrElement, data: IrDeclarationParent) {
|
||||
if (element !is IrDeclarationParent) {
|
||||
@@ -612,25 +539,6 @@ fun IrMemberAccessExpression.getArgumentsWithIr(): List<Pair<IrValueParameter, I
|
||||
return res
|
||||
}
|
||||
|
||||
fun CallableMemberDescriptor.createValueParameter(
|
||||
index: Int,
|
||||
name: String,
|
||||
type: IrType,
|
||||
startOffset: Int,
|
||||
endOffset: Int
|
||||
): IrValueParameter {
|
||||
val descriptor = ValueParameterDescriptorImpl(
|
||||
this, null,
|
||||
index,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier(name),
|
||||
type.toKotlinType(),
|
||||
false, false, false, null, SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
return IrValueParameterImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, descriptor, type, null)
|
||||
}
|
||||
|
||||
fun ReferenceSymbolTable.translateErased(type: KotlinType): IrSimpleType {
|
||||
val descriptor = TypeUtils.getClassDescriptor(type)
|
||||
if (descriptor == null) return translateErased(type.immediateSupertypes().first())
|
||||
@@ -643,9 +551,9 @@ fun ReferenceSymbolTable.translateErased(type: KotlinType): IrSimpleType {
|
||||
}
|
||||
|
||||
fun CommonBackendContext.createArrayOfExpression(
|
||||
startOffset: Int, endOffset: Int,
|
||||
arrayElementType: IrType,
|
||||
arrayElements: List<IrExpression>,
|
||||
startOffset: Int, endOffset: Int
|
||||
arrayElements: List<IrExpression>
|
||||
): IrExpression {
|
||||
|
||||
val arrayType = ir.symbols.array.typeWith(arrayElementType)
|
||||
@@ -659,34 +567,27 @@ fun CommonBackendContext.createArrayOfExpression(
|
||||
fun createField(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
type: IrType,
|
||||
name: Name,
|
||||
isMutable: Boolean,
|
||||
origin: IrDeclarationOrigin,
|
||||
owner: ClassDescriptor
|
||||
): IrField {
|
||||
val descriptor = PropertyDescriptorImpl.create(
|
||||
/* containingDeclaration = */ owner,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PRIVATE,
|
||||
/* isVar = */ isMutable,
|
||||
/* name = */ name,
|
||||
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/* source = */ SourceElement.NO_SOURCE,
|
||||
/* lateInit = */ false,
|
||||
/* isConst = */ false,
|
||||
/* isExpect = */ false,
|
||||
/* isActual = */ false,
|
||||
/* isExternal = */ false,
|
||||
/* isDelegated = */ false
|
||||
owner: IrClass
|
||||
) = WrappedFieldDescriptor().let {
|
||||
IrFieldImpl(
|
||||
startOffset, endOffset,
|
||||
origin,
|
||||
IrFieldSymbolImpl(it),
|
||||
name,
|
||||
type,
|
||||
Visibilities.PRIVATE,
|
||||
!isMutable,
|
||||
false,
|
||||
false
|
||||
).apply {
|
||||
initialize(null, null)
|
||||
|
||||
setType(type.toKotlinType(), emptyList(), owner.thisAsReceiverParameter, null)
|
||||
it.bind(this)
|
||||
owner.declarations += this
|
||||
parent = owner
|
||||
}
|
||||
|
||||
return IrFieldImpl(startOffset, endOffset, origin, descriptor, type)
|
||||
}
|
||||
|
||||
fun IrValueParameter.copy(newDescriptor: ParameterDescriptor): IrValueParameter {
|
||||
@@ -710,16 +611,5 @@ val IrType.isSimpleTypeWithQuestionMark: Boolean
|
||||
fun IrClass.defaultOrNullableType(hasQuestionMark: Boolean) =
|
||||
if (hasQuestionMark) this.defaultType.makeNullable() else this.defaultType
|
||||
|
||||
fun FunctionDescriptor.createOverriddenDescriptor(owner: ClassDescriptor, final: Boolean = true): FunctionDescriptor {
|
||||
return this.newCopyBuilder()
|
||||
.setOwner(owner)
|
||||
.setCopyOverrides(true)
|
||||
.setModality(if (final) Modality.FINAL else Modality.OPEN)
|
||||
.setDispatchReceiverParameter(owner.thisAsReceiverParameter)
|
||||
.build()!!.apply {
|
||||
overriddenDescriptors = listOf(this@createOverriddenDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrFunction.isRestrictedSuspendFunction(languageVersionSettings: LanguageVersionSettings): Boolean =
|
||||
this.descriptor.extensionReceiverParameter?.type?.isRestrictsSuspensionReceiver(languageVersionSettings) == true
|
||||
|
||||
Reference in New Issue
Block a user