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