Migrate compiler to IR types
This commit is contained in:
committed by
SvyatoslavScherbina
parent
fd016db33a
commit
9bbecf33d2
+55
-32
@@ -16,17 +16,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.declarations.getDefault
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,45 +44,64 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
*
|
||||
* TODO: consider making this visitor non-recursive to make it more general.
|
||||
*/
|
||||
abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrElementTransformerVoid() {
|
||||
internal abstract class AbstractValueUsageTransformer(
|
||||
val builtIns: KotlinBuiltIns,
|
||||
val symbols: KonanSymbols,
|
||||
val irBuiltIns: IrBuiltIns
|
||||
): IrElementTransformerVoid() {
|
||||
|
||||
protected open fun IrExpression.useAs(type: KotlinType): IrExpression = this
|
||||
protected open fun IrExpression.useAs(type: IrType): IrExpression = this
|
||||
|
||||
protected open fun IrExpression.useAsStatement(): IrExpression = this
|
||||
|
||||
protected open fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: KotlinType): IrExpression =
|
||||
protected open fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: IrType): IrExpression =
|
||||
this
|
||||
|
||||
protected open fun IrExpression.useAsValue(value: ValueDescriptor): IrExpression = this.useAs(value.type)
|
||||
protected open fun IrExpression.useAsValue(value: IrValueDeclaration): IrExpression = this.useAs(value.type)
|
||||
|
||||
protected open fun IrExpression.useAsArgument(parameter: ParameterDescriptor): IrExpression =
|
||||
this.useAsValue(parameter)
|
||||
|
||||
protected open fun IrExpression.useAsDispatchReceiver(expression: IrMemberAccessExpression): IrExpression =
|
||||
this.useAsArgument(expression.descriptor.dispatchReceiverParameter!!)
|
||||
protected open fun IrExpression.useAsDispatchReceiver(expression: IrFunctionAccessExpression): IrExpression =
|
||||
this.useAsArgument(expression.symbol.owner.dispatchReceiverParameter!!)
|
||||
|
||||
protected open fun IrExpression.useAsExtensionReceiver(expression: IrMemberAccessExpression): IrExpression =
|
||||
this.useAsArgument(expression.descriptor.extensionReceiverParameter!!)
|
||||
protected open fun IrExpression.useAsExtensionReceiver(expression: IrFunctionAccessExpression): IrExpression =
|
||||
this.useAsArgument(expression.symbol.owner.extensionReceiverParameter!!)
|
||||
|
||||
protected open fun IrExpression.useAsValueArgument(expression: IrMemberAccessExpression,
|
||||
protected open fun IrExpression.useAsValueArgument(expression: IrFunctionAccessExpression,
|
||||
parameter: ValueParameterDescriptor): IrExpression =
|
||||
this.useAsArgument(parameter)
|
||||
|
||||
protected open fun IrExpression.useForVariable(variable: VariableDescriptor): IrExpression =
|
||||
private fun IrExpression.useForVariable(variable: VariableDescriptor): IrExpression =
|
||||
this.useAsValue(variable)
|
||||
|
||||
protected open fun IrExpression.useForField(field: PropertyDescriptor): IrExpression =
|
||||
this.useForVariable(field)
|
||||
private fun IrExpression.useForField(field: IrField): IrExpression =
|
||||
this.useAs(field.type)
|
||||
|
||||
protected open fun IrExpression.useAsReturnValue(returnTarget: CallableDescriptor): IrExpression {
|
||||
val returnType = returnTarget.returnType ?: return this
|
||||
return this.useAs(returnType)
|
||||
}
|
||||
protected open fun IrExpression.useAsReturnValue(returnTarget: IrReturnTargetSymbol): IrExpression =
|
||||
when (returnTarget) {
|
||||
is IrSimpleFunctionSymbol -> this.useAs(returnTarget.owner.returnType)
|
||||
is IrConstructorSymbol -> this.useAs(irBuiltIns.unitType)
|
||||
is IrReturnableBlockSymbol -> this.useAs(returnTarget.owner.type)
|
||||
else -> error(returnTarget)
|
||||
}
|
||||
|
||||
protected open fun IrExpression.useAsResult(enclosing: IrExpression): IrExpression =
|
||||
this.useAs(enclosing.type)
|
||||
|
||||
override fun visitMemberAccess(expression: IrMemberAccessExpression): IrExpression {
|
||||
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
with(expression) {
|
||||
@@ -86,7 +109,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
extensionReceiver = extensionReceiver?.useAsExtensionReceiver(expression)
|
||||
for (index in descriptor.valueParameters.indices) {
|
||||
val argument = getValueArgument(index) ?: continue
|
||||
val parameter = descriptor.valueParameters[index]
|
||||
val parameter = symbol.owner.valueParameters[index]
|
||||
putValueArgument(index, argument.useAsValueArgument(expression, parameter))
|
||||
}
|
||||
}
|
||||
@@ -130,7 +153,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
expression.value = expression.value.useAsReturnValue(expression.returnTarget)
|
||||
expression.value = expression.value.useAsReturnValue(expression.returnTargetSymbol)
|
||||
|
||||
return expression
|
||||
}
|
||||
@@ -138,7 +161,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
override fun visitSetVariable(expression: IrSetVariable): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
expression.value = expression.value.useForVariable(expression.descriptor)
|
||||
expression.value = expression.value.useForVariable(expression.symbol.owner)
|
||||
|
||||
return expression
|
||||
}
|
||||
@@ -146,7 +169,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
override fun visitSetField(expression: IrSetField): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
expression.value = expression.value.useForField(expression.descriptor)
|
||||
expression.value = expression.value.useForField(expression.symbol.owner)
|
||||
|
||||
return expression
|
||||
}
|
||||
@@ -155,7 +178,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
declaration.transformChildrenVoid(this)
|
||||
|
||||
declaration.initializer?.let {
|
||||
it.expression = it.expression.useForField(declaration.descriptor)
|
||||
it.expression = it.expression.useForField(declaration)
|
||||
}
|
||||
|
||||
return declaration
|
||||
@@ -164,7 +187,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
override fun visitVariable(declaration: IrVariable): IrVariable {
|
||||
declaration.transformChildrenVoid(this)
|
||||
|
||||
declaration.initializer = declaration.initializer?.useForVariable(declaration.descriptor)
|
||||
declaration.initializer = declaration.initializer?.useForVariable(declaration)
|
||||
|
||||
return declaration
|
||||
}
|
||||
@@ -173,7 +196,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
for (irBranch in expression.branches) {
|
||||
irBranch.condition = irBranch.condition.useAs(builtIns.booleanType)
|
||||
irBranch.condition = irBranch.condition.useAs(irBuiltIns.booleanType)
|
||||
irBranch.result = irBranch.result.useAsResult(expression)
|
||||
}
|
||||
|
||||
@@ -183,7 +206,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
override fun visitLoop(loop: IrLoop): IrExpression {
|
||||
loop.transformChildrenVoid(this)
|
||||
|
||||
loop.condition = loop.condition.useAs(builtIns.booleanType)
|
||||
loop.condition = loop.condition.useAs(irBuiltIns.booleanType)
|
||||
|
||||
loop.body = loop.body?.useAsStatement()
|
||||
|
||||
@@ -193,7 +216,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
override fun visitThrow(expression: IrThrow): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
expression.value = expression.value.useAs(builtIns.throwable.defaultType)
|
||||
expression.value = expression.value.useAs(symbols.throwable.owner.defaultType)
|
||||
|
||||
return expression
|
||||
}
|
||||
@@ -238,8 +261,8 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
declaration.transformChildrenVoid(this)
|
||||
|
||||
declaration.descriptor.valueParameters.forEach { parameter ->
|
||||
val defaultValue = declaration.getDefault(parameter)
|
||||
declaration.valueParameters.forEach { parameter ->
|
||||
val defaultValue = parameter.defaultValue
|
||||
if (defaultValue is IrExpressionBody) {
|
||||
defaultValue.expression = defaultValue.expression.useAsArgument(parameter)
|
||||
}
|
||||
@@ -247,7 +270,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
|
||||
declaration.body?.let {
|
||||
if (it is IrExpressionBody) {
|
||||
it.expression = it.expression.useAsReturnValue(declaration.descriptor)
|
||||
it.expression = it.expression.useAsReturnValue(declaration.symbol)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -21,6 +21,7 @@ import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
@@ -29,6 +30,9 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
internal fun KonanSymbols.getTypeConversion(actualType: KotlinType, expectedType: KotlinType) =
|
||||
getTypeConversion(actualType.correspondingValueType, expectedType.correspondingValueType)
|
||||
|
||||
internal fun KonanSymbols.getTypeConversion(actualType: IrType, expectedType: IrType) =
|
||||
getTypeConversion(actualType.correspondingValueType, expectedType.correspondingValueType)
|
||||
|
||||
internal fun KonanSymbols.getTypeConversion(
|
||||
actualValueType: ValueType?,
|
||||
expectedValueType: ValueType?
|
||||
|
||||
+140
-89
@@ -18,18 +18,16 @@ package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.LLVMDumpModule
|
||||
import llvm.LLVMModuleRef
|
||||
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
|
||||
import org.jetbrains.kotlin.backend.common.ReflectionTypes
|
||||
import org.jetbrains.kotlin.backend.common.validateIrModule
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.initialize
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.DescriptorsFactory
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIr
|
||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter
|
||||
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD
|
||||
import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
@@ -42,23 +40,23 @@ import org.jetbrains.kotlin.ir.SourceManager
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.ir.util.endOffsetOrUndefined
|
||||
import org.jetbrains.kotlin.ir.util.startOffsetOrUndefined
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||
import org.jetbrains.kotlin.metadata.KonanLinkData
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.lang.System.out
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
|
||||
@@ -66,72 +64,49 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
||||
private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) }
|
||||
private val outerThisFields = mutableMapOf<ClassDescriptor, IrField>()
|
||||
private val bridgesDescriptors = mutableMapOf<Pair<IrSimpleFunction, BridgeDirections>, IrSimpleFunction>()
|
||||
private val loweredEnums = mutableMapOf<ClassDescriptor, LoweredEnum>()
|
||||
private val ordinals = mutableMapOf<IrClass, Map<ClassDescriptor, Int>>()
|
||||
private val loweredEnums = mutableMapOf<IrClass, LoweredEnum>()
|
||||
private val ordinals = mutableMapOf<ClassDescriptor, Map<ClassDescriptor, Int>>()
|
||||
|
||||
object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
|
||||
IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
||||
|
||||
fun getOuterThisField(innerClassDescriptor: ClassDescriptor): IrField =
|
||||
if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor")
|
||||
else outerThisFields.getOrPut(innerClassDescriptor) {
|
||||
val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) ?:
|
||||
throw AssertionError("No containing class for inner class $innerClassDescriptor")
|
||||
fun getOuterThisField(innerClass: IrClass): IrField =
|
||||
if (!innerClass.descriptor.isInner) throw AssertionError("Class is not inner: ${innerClass.descriptor}")
|
||||
else outerThisFields.getOrPut(innerClass.descriptor) {
|
||||
val outerClass = innerClass.parent as? IrClass
|
||||
?: throw AssertionError("No containing class for inner class ${innerClass.descriptor}")
|
||||
|
||||
val receiver = ReceiverParameterDescriptorImpl(innerClassDescriptor, ImplicitClassReceiver(innerClassDescriptor))
|
||||
val receiver = ReceiverParameterDescriptorImpl(innerClass.descriptor, ImplicitClassReceiver(innerClass.descriptor))
|
||||
val descriptor = PropertyDescriptorImpl.create(
|
||||
innerClassDescriptor, Annotations.EMPTY, Modality.FINAL,
|
||||
innerClass.descriptor, Annotations.EMPTY, Modality.FINAL,
|
||||
Visibilities.PRIVATE, false, "this$0".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
SourceElement.NO_SOURCE, false, false, false, false, false, false
|
||||
).initialize(outerClassDescriptor.defaultType, dispatchReceiverParameter = receiver)
|
||||
).apply {
|
||||
val receiverType: KotlinType? = null
|
||||
this.setType(outerClass.descriptor.defaultType, emptyList(), receiver, receiverType)
|
||||
initialize(null, null)
|
||||
}
|
||||
|
||||
IrFieldImpl(
|
||||
innerClassDescriptor.startOffsetOrUndefined,
|
||||
innerClassDescriptor.endOffsetOrUndefined,
|
||||
innerClass.descriptor.startOffsetOrUndefined,
|
||||
innerClass.descriptor.endOffsetOrUndefined,
|
||||
DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS,
|
||||
descriptor
|
||||
descriptor,
|
||||
outerClass.defaultType
|
||||
)
|
||||
}
|
||||
|
||||
fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): IrSimpleFunction {
|
||||
val irFunction = overriddenFunctionDescriptor.descriptor
|
||||
val descriptor = irFunction.descriptor
|
||||
assert(overriddenFunctionDescriptor.needBridge,
|
||||
{ "Function $descriptor is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor.descriptor}" })
|
||||
val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections
|
||||
return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) {
|
||||
val bridgeDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
/* containingDeclaration = */ descriptor.containingDeclaration,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* name = */ "<bridge-$bridgeDirections>${irFunction.functionName}".synthesizedName,
|
||||
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/* source = */ SourceElement.NO_SOURCE).apply {
|
||||
initializeBridgeDescriptor(this, descriptor, bridgeDirections.array)
|
||||
}
|
||||
|
||||
IrFunctionImpl(
|
||||
irFunction.startOffset,
|
||||
irFunction.endOffset,
|
||||
DECLARATION_ORIGIN_BRIDGE_METHOD(irFunction),
|
||||
bridgeDescriptor
|
||||
).apply {
|
||||
createParameterDeclarations()
|
||||
this.parent = overriddenFunctionDescriptor.descriptor.parent
|
||||
}
|
||||
fun getLoweredEnum(enumClass: IrClass): LoweredEnum {
|
||||
assert(enumClass.kind == ClassKind.ENUM_CLASS, { "Expected enum class but was: ${enumClass.descriptor}" })
|
||||
return loweredEnums.getOrPut(enumClass) {
|
||||
enumSpecialDeclarationsFactory.createLoweredEnum(enumClass)
|
||||
}
|
||||
}
|
||||
|
||||
fun getLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum {
|
||||
assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS, { "Expected enum class but was: $enumClassDescriptor" })
|
||||
return loweredEnums.getOrPut(enumClassDescriptor) {
|
||||
enumSpecialDeclarationsFactory.createLoweredEnum(enumClassDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignOrdinalsToEnumEntries(irClass: IrClass): Map<ClassDescriptor, Int> {
|
||||
private fun assignOrdinalsToEnumEntries(classDescriptor: ClassDescriptor): Map<ClassDescriptor, Int> {
|
||||
val enumEntryOrdinals = mutableMapOf<ClassDescriptor, Int>()
|
||||
irClass.declarations.filterIsInstance<IrEnumEntry>().forEachIndexed { index, entry ->
|
||||
enumEntryOrdinals[entry.descriptor] = index
|
||||
classDescriptor.enumEntries.forEachIndexed { index, entry ->
|
||||
enumEntryOrdinals[entry] = index
|
||||
}
|
||||
return enumEntryOrdinals
|
||||
}
|
||||
@@ -145,54 +120,130 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
||||
.first { entryDescriptor.name == enumClassDescriptor.c.nameResolver.getName(it.name) }
|
||||
.getExtension(KonanLinkData.enumEntryOrdinal)
|
||||
}
|
||||
val enumClass = context.ir.getEnum(enumClassDescriptor)
|
||||
return ordinals.getOrPut(enumClass) { assignOrdinalsToEnumEntries(enumClass) }[entryDescriptor]!!
|
||||
return ordinals.getOrPut(enumClassDescriptor) { assignOrdinalsToEnumEntries(enumClassDescriptor) }[entryDescriptor]!!
|
||||
}
|
||||
|
||||
private fun initializeBridgeDescriptor(bridgeDescriptor: SimpleFunctionDescriptorImpl,
|
||||
descriptor: FunctionDescriptor,
|
||||
bridgeDirections: Array<BridgeDirection>) {
|
||||
val returnType = when (bridgeDirections[0]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> descriptor.returnType!!
|
||||
BridgeDirection.NOT_NEEDED -> descriptor.returnType
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.nullableAnyType
|
||||
fun getBridge(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): IrSimpleFunction {
|
||||
val irFunction = overriddenFunctionDescriptor.descriptor
|
||||
assert(overriddenFunctionDescriptor.needBridge,
|
||||
{ "Function ${irFunction.descriptor} is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor.descriptor}" })
|
||||
val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections
|
||||
return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) {
|
||||
createBridge(irFunction, bridgeDirections)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createBridge(function: IrFunction, bridgeDirections: BridgeDirections): IrFunctionImpl {
|
||||
val returnType = when (bridgeDirections.array[0]) {
|
||||
BridgeDirection.TO_VALUE_TYPE,
|
||||
BridgeDirection.NOT_NEEDED -> function.returnType
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyNType
|
||||
}
|
||||
|
||||
val extensionReceiverType = when (bridgeDirections[1]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> descriptor.extensionReceiverParameter!!.type
|
||||
BridgeDirection.NOT_NEEDED -> descriptor.extensionReceiverParameter?.type
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.nullableAnyType
|
||||
val extensionReceiverType = when (bridgeDirections.array[1]) {
|
||||
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 + 2]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> valueParameter.type
|
||||
BridgeDirection.NOT_NEEDED -> valueParameter.type
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.irBuiltIns.anyNType
|
||||
}
|
||||
}
|
||||
val bridgeDescriptor = createBridgeDescriptor(
|
||||
function,
|
||||
bridgeDirections,
|
||||
returnType,
|
||||
extensionReceiverType,
|
||||
valueParameterTypes
|
||||
)
|
||||
|
||||
val bridge = IrFunctionImpl(
|
||||
function.startOffset,
|
||||
function.endOffset,
|
||||
DECLARATION_ORIGIN_BRIDGE_METHOD(function),
|
||||
bridgeDescriptor
|
||||
).apply {
|
||||
this.returnType = returnType
|
||||
this.parent = function.parent
|
||||
}
|
||||
|
||||
bridge.createDispatchReceiverParameter()
|
||||
extensionReceiverType?.let {
|
||||
val extensionReceiverParameter = function.extensionReceiverParameter!!
|
||||
bridge.extensionReceiverParameter = IrValueParameterImpl(
|
||||
extensionReceiverParameter.startOffset,
|
||||
extensionReceiverParameter.endOffset,
|
||||
extensionReceiverParameter.origin,
|
||||
bridge.descriptor.extensionReceiverParameter!!,
|
||||
it, null
|
||||
)
|
||||
}
|
||||
function.valueParameters.mapIndexedTo(bridge.valueParameters) { index, valueParameter ->
|
||||
val type = valueParameterTypes[index]
|
||||
|
||||
IrValueParameterImpl(
|
||||
valueParameter.startOffset,
|
||||
valueParameter.endOffset,
|
||||
valueParameter.origin,
|
||||
bridge.descriptor.valueParameters[index],
|
||||
type, valueParameter.varargElementType
|
||||
)
|
||||
}
|
||||
|
||||
function.typeParameters.mapTo(bridge.typeParameters) {
|
||||
IrTypeParameterImpl(it.startOffset, it.endOffset, it.origin, it.descriptor).apply {
|
||||
superTypes += it.superTypes
|
||||
}
|
||||
}
|
||||
|
||||
return bridge
|
||||
}
|
||||
|
||||
private fun createBridgeDescriptor(
|
||||
function: IrFunction,
|
||||
bridgeDirections: BridgeDirections,
|
||||
returnType: IrType,
|
||||
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 ->
|
||||
val outType = when (bridgeDirections[index + 2]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> valueParameterDescriptor.type
|
||||
BridgeDirection.NOT_NEEDED -> valueParameterDescriptor.type
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.nullableAnyType
|
||||
}
|
||||
ValueParameterDescriptorImpl(
|
||||
ValueParameterDescriptorImpl(
|
||||
containingDeclaration = valueParameterDescriptor.containingDeclaration,
|
||||
original = null,
|
||||
index = index,
|
||||
annotations = Annotations.EMPTY,
|
||||
name = valueParameterDescriptor.name,
|
||||
outType = outType,
|
||||
declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(),
|
||||
isCrossinline = valueParameterDescriptor.isCrossinline,
|
||||
isNoinline = valueParameterDescriptor.isNoinline,
|
||||
varargElementType = valueParameterDescriptor.varargElementType,
|
||||
source = SourceElement.NO_SOURCE)
|
||||
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,
|
||||
/* receiverParameterType = */ extensionReceiverType?.toKotlinType(),
|
||||
/* dispatchReceiverParameter = */ descriptor.dispatchReceiverParameter,
|
||||
/* typeParameters = */ descriptor.typeParameters,
|
||||
/* unsubstitutedValueParameters = */ valueParameters,
|
||||
/* unsubstitutedReturnType = */ returnType,
|
||||
/* unsubstitutedReturnType = */ returnType.toKotlinType(),
|
||||
/* modality = */ descriptor.modality,
|
||||
/* visibility = */ descriptor.visibility).apply {
|
||||
isSuspend = descriptor.isSuspend
|
||||
isSuspend = descriptor.isSuspend
|
||||
}
|
||||
return bridgeDescriptor
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+33
-22
@@ -16,10 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.initialize
|
||||
import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.ir.createSimpleDelegatingConstructorDescriptor
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.enumEntries
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.*
|
||||
@@ -31,10 +31,7 @@ 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.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.replace
|
||||
import org.jetbrains.kotlin.types.*
|
||||
|
||||
|
||||
internal object DECLARATION_ORIGIN_ENUM :
|
||||
@@ -48,36 +45,45 @@ internal data class LoweredEnum(val implObject: IrClass,
|
||||
val entriesMap: Map<Name, Int>)
|
||||
|
||||
internal class EnumSpecialDeclarationsFactory(val context: Context) {
|
||||
fun createLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum {
|
||||
fun createLoweredEnum(enumClass: IrClass): LoweredEnum {
|
||||
val enumClassDescriptor = enumClass.descriptor
|
||||
|
||||
val startOffset = enumClassDescriptor.startOffsetOrUndefined
|
||||
val endOffset = enumClassDescriptor.endOffsetOrUndefined
|
||||
val startOffset = enumClass.startOffset
|
||||
val endOffset = enumClass.endOffset
|
||||
|
||||
val implObjectDescriptor = ClassDescriptorImpl(enumClassDescriptor, "OBJECT".synthesizedName, Modality.FINAL,
|
||||
ClassKind.OBJECT, listOf(context.builtIns.anyType), SourceElement.NO_SOURCE, false, LockBasedStorageManager.NO_LOCKS)
|
||||
|
||||
val implObject = IrClassImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, implObjectDescriptor).apply {
|
||||
createParameterDeclarations()
|
||||
}
|
||||
|
||||
val valuesProperty = createEnumValuesField(enumClassDescriptor, implObjectDescriptor)
|
||||
val valuesField = IrFieldImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesProperty)
|
||||
val valuesType = context.ir.symbols.array.typeWith(enumClass.defaultType)
|
||||
val valuesField = IrFieldImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesProperty, valuesType)
|
||||
|
||||
val valuesGetterDescriptor = createValuesGetterDescriptor(enumClassDescriptor, implObjectDescriptor)
|
||||
val valuesGetter = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesGetterDescriptor).apply {
|
||||
createParameterDeclarations()
|
||||
val valuesGetter = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesGetterDescriptor).also {
|
||||
it.returnType = valuesType
|
||||
it.parent = implObject
|
||||
it.createDispatchReceiverParameter()
|
||||
}
|
||||
|
||||
val memberScope = MemberScope.Empty
|
||||
|
||||
val constructorOfAny = context.builtIns.any.constructors.first()
|
||||
val constructorOfAny = context.irBuiltIns.anyClass.owner.constructors.first()
|
||||
// TODO: why primary?
|
||||
val constructorDescriptor = implObjectDescriptor.createSimpleDelegatingConstructorDescriptor(constructorOfAny, true)
|
||||
val constructor = implObject.addSimpleDelegatingConstructor(
|
||||
constructorOfAny,
|
||||
context.irBuiltIns,
|
||||
DECLARATION_ORIGIN_ENUM,
|
||||
true
|
||||
)
|
||||
val constructorDescriptor = constructor.descriptor
|
||||
|
||||
implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor)
|
||||
val implObject = IrClassImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, implObjectDescriptor).apply {
|
||||
createParameterDeclarations()
|
||||
addFakeOverrides()
|
||||
setSuperSymbols(listOf(context.ir.symbols.any.owner))
|
||||
}
|
||||
implObject.parent = context.ir.getEnum(enumClassDescriptor)
|
||||
valuesGetter.parent = implObject
|
||||
implObject.setSuperSymbolsAndAddFakeOverrides(listOf(context.irBuiltIns.anyType))
|
||||
implObject.parent = enumClass
|
||||
valuesField.parent = implObject
|
||||
|
||||
val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor)
|
||||
@@ -115,7 +121,12 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) {
|
||||
val receiver = ReceiverParameterDescriptorImpl(implObjectDescriptor, ImplicitClassReceiver(implObjectDescriptor))
|
||||
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).initialize(valuesArrayType, dispatchReceiverParameter = receiver)
|
||||
false, false, false, false, false, false).apply {
|
||||
|
||||
val receiverType: KotlinType? = null
|
||||
this.setType(valuesArrayType, emptyList(), receiver, receiverType)
|
||||
this.initialize(null, null)
|
||||
}
|
||||
}
|
||||
|
||||
private val genericArrayType = context.ir.symbols.array.descriptor
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironme
|
||||
context.irModule = module
|
||||
context.ir.symbols = symbols
|
||||
|
||||
validateIrModule(context, module)
|
||||
// validateIrModule(context, module)
|
||||
}
|
||||
phaser.phase(KonanPhase.SERIALIZER) {
|
||||
markBackingFields(context)
|
||||
|
||||
-6
@@ -18,13 +18,9 @@ package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.referenceAllTypeExternalClassifiers
|
||||
import org.jetbrains.kotlin.backend.konan.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.lower.DefaultArgumentStubGenerator
|
||||
import org.jetbrains.kotlin.backend.konan.lower.DefaultParameterInjector
|
||||
import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.LateinitLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.LocalDeclarationsLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.SharedVariablesLowering
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
@@ -83,12 +79,10 @@ internal class KonanLower(val context: Context) {
|
||||
}
|
||||
|
||||
val symbolTable = context.ir.symbols.symbolTable
|
||||
irModule.referenceAllTypeExternalClassifiers(symbolTable)
|
||||
|
||||
do {
|
||||
@Suppress("DEPRECATION")
|
||||
irModule.replaceUnboundSymbols(context)
|
||||
irModule.referenceAllTypeExternalClassifiers(symbolTable)
|
||||
} while (symbolTable.unboundClasses.isNotEmpty())
|
||||
|
||||
irModule.patchDeclarationParents()
|
||||
|
||||
+73
@@ -17,7 +17,14 @@
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
/**
|
||||
@@ -96,3 +103,69 @@ val KotlinType.correspondingValueType: ValueType?
|
||||
get() = ValueType.values().firstOrNull {
|
||||
isRepresentedAs(it)
|
||||
}
|
||||
|
||||
|
||||
//////
|
||||
|
||||
private fun IrType.isConstructedFromGivenClass(fqName: FqNameUnsafe) =
|
||||
(this.classifierOrNull as? IrClassSymbol)?.descriptor?.fqNameSafe?.toUnsafe() == fqName
|
||||
|
||||
private val IrClassifierSymbol.ownerSuperTypes: List<IrType>
|
||||
get() = when (this) {
|
||||
is IrClassSymbol -> this.owner.superTypes
|
||||
is IrTypeParameterSymbol -> this.owner.superTypes
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return `true` if this type must be represented as given value type in generated code.
|
||||
*/
|
||||
tailrec fun IrType.isRepresentedAs(valueType: ValueType): Boolean {
|
||||
if (this !is IrSimpleType) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (this.hasQuestionMark && !valueType.isNullable) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (this.isConstructedFromGivenClass(valueType.classFqName)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Supertypes should be checked even for "final" value types (e.g. Int)
|
||||
// to treat type parameter `T` with `Int` upper bound as value type.
|
||||
// This behavior is observed on Kotlin JVM and used in interop implementation.
|
||||
//
|
||||
// However to optimize this method only first supertype is checked
|
||||
// (it is supposed to be enough in all sane cases).
|
||||
val firstSupertype = this.classifier.ownerSuperTypes.firstOrNull() ?: return false
|
||||
return firstSupertype.isRepresentedAs(valueType)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `true` if this type without `null` value must be represented as given value type in generated code.
|
||||
*
|
||||
* TODO: this method can be considered as a hack; rework its usages.
|
||||
*/
|
||||
tailrec fun IrType.notNullableIsRepresentedAs(valueType: ValueType): Boolean {
|
||||
if (this.isConstructedFromGivenClass(valueType.classFqName)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// See comment in [isRepresentedAs].
|
||||
val firstSupertype = this.classifierOrNull?.ownerSuperTypes?.firstOrNull() ?: return false
|
||||
return firstSupertype.notNullableIsRepresentedAs(valueType)
|
||||
}
|
||||
|
||||
fun IrType.isValueType() = ValueType.values().any { this.isRepresentedAs(it) }
|
||||
|
||||
/**
|
||||
* @return the [ValueType] given type represented in generated code as,
|
||||
* or `null` if represented as object reference.
|
||||
*/
|
||||
val IrType.correspondingValueType: ValueType?
|
||||
get() = ValueType.values().firstOrNull {
|
||||
isRepresentedAs(it)
|
||||
}
|
||||
+1
-1
@@ -61,7 +61,7 @@ internal class OverriddenFunctionDescriptor(
|
||||
} else {
|
||||
descriptor
|
||||
}
|
||||
context.specialDeclarationsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor))
|
||||
context.specialDeclarationsFactory.getBridge(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor))
|
||||
}
|
||||
return if (implementation.modality == Modality.ABSTRACT) null else implementation
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,9 +21,9 @@ import org.jetbrains.kotlin.backend.konan.isValueType
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
/**
|
||||
* List of all implemented interfaces (including those which implemented by a super class)
|
||||
|
||||
+27
-16
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.konan.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager
|
||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
@@ -34,8 +35,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.types.*
|
||||
|
||||
internal class KonanSharedVariablesManager(val context: KonanBackendContext) : SharedVariablesManager {
|
||||
@@ -55,7 +56,7 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S
|
||||
}
|
||||
|
||||
private fun refType(elementType: KotlinType): KotlinType {
|
||||
return refClass.owner.defaultType.replace(listOf(TypeProjectionImpl(elementType)))
|
||||
return refClass.descriptor.defaultType.replace(listOf(TypeProjectionImpl(elementType)))
|
||||
}
|
||||
|
||||
private fun getElementPropertyDescriptor(sharedVariableDescriptor: VariableDescriptor): PropertyDescriptor {
|
||||
@@ -74,18 +75,19 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S
|
||||
false, false, variableDescriptor.source
|
||||
)
|
||||
|
||||
val valueType = originalDeclaration.descriptor.type
|
||||
|
||||
val refConstructorTypeArguments = mapOf(refClassConstructor.descriptor.typeParameters[0] to valueType)
|
||||
val valueType = originalDeclaration.type
|
||||
|
||||
val refConstructorCall = IrCallImpl(
|
||||
originalDeclaration.startOffset, originalDeclaration.endOffset,
|
||||
refClassConstructor, refConstructor(valueType), refConstructorTypeArguments
|
||||
)
|
||||
refClass.typeWith(valueType),
|
||||
refClassConstructor, refConstructor(valueType.toKotlinType()), 1
|
||||
).apply {
|
||||
putTypeArgument(0, valueType)
|
||||
}
|
||||
|
||||
return IrVariableImpl(
|
||||
originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin,
|
||||
sharedVariableDescriptor
|
||||
sharedVariableDescriptor, refConstructorCall.type
|
||||
).apply {
|
||||
initializer = refConstructorCall
|
||||
}
|
||||
@@ -97,16 +99,18 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S
|
||||
val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableDeclaration.descriptor)
|
||||
|
||||
val sharedVariableInitialization =
|
||||
IrCallImpl(initializer.startOffset, initializer.endOffset, elementProperty.setter!!.symbol,
|
||||
IrCallImpl(initializer.startOffset, initializer.endOffset,
|
||||
context.irBuiltIns.unitType, elementProperty.setter!!.symbol,
|
||||
elementPropertyDescriptor.setter!!)
|
||||
|
||||
sharedVariableInitialization.dispatchReceiver =
|
||||
IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableDeclaration.symbol)
|
||||
IrGetValueImpl(initializer.startOffset, initializer.endOffset,
|
||||
sharedVariableDeclaration.type, sharedVariableDeclaration.symbol)
|
||||
|
||||
sharedVariableInitialization.putValueArgument(0, initializer)
|
||||
|
||||
return IrCompositeImpl(
|
||||
originalDeclaration.startOffset, originalDeclaration.endOffset, context.builtIns.unitType, null,
|
||||
originalDeclaration.startOffset, originalDeclaration.endOffset, context.irBuiltIns.unitType, null,
|
||||
listOf(sharedVariableDeclaration, sharedVariableInitialization)
|
||||
)
|
||||
}
|
||||
@@ -115,18 +119,25 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S
|
||||
|
||||
val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableSymbol.descriptor)
|
||||
|
||||
return IrCallImpl(originalGet.startOffset, originalGet.endOffset, elementProperty.getter!!.symbol,
|
||||
return IrCallImpl(originalGet.startOffset, originalGet.endOffset,
|
||||
originalGet.type, elementProperty.getter!!.symbol,
|
||||
elementPropertyDescriptor.getter!!).apply {
|
||||
dispatchReceiver = IrGetValueImpl(originalGet.startOffset, originalGet.endOffset, sharedVariableSymbol)
|
||||
dispatchReceiver = IrGetValueImpl(
|
||||
originalGet.startOffset, originalGet.endOffset,
|
||||
sharedVariableSymbol.owner.type, sharedVariableSymbol
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetVariable): IrExpression {
|
||||
val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableSymbol.descriptor)
|
||||
|
||||
return IrCallImpl(originalSet.startOffset, originalSet.endOffset, elementProperty.setter!!.symbol,
|
||||
elementPropertyDescriptor.setter!!).apply {
|
||||
dispatchReceiver = IrGetValueImpl(originalSet.startOffset, originalSet.endOffset, sharedVariableSymbol)
|
||||
return IrCallImpl(originalSet.startOffset, originalSet.endOffset, context.irBuiltIns.unitType,
|
||||
elementProperty.setter!!.symbol, elementPropertyDescriptor.setter!!).apply {
|
||||
dispatchReceiver = IrGetValueImpl(
|
||||
originalSet.startOffset, originalSet.endOffset,
|
||||
sharedVariableSymbol.owner.type, sharedVariableSymbol
|
||||
)
|
||||
putValueArgument(0, originalSet.value)
|
||||
}
|
||||
}
|
||||
|
||||
+58
-15
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS
|
||||
import org.jetbrains.kotlin.backend.konan.ValueType
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.konanInternal
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint
|
||||
import org.jetbrains.kotlin.backend.konan.lower.TestProcessor
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
@@ -38,12 +39,19 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.translateErased
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
@@ -58,9 +66,6 @@ internal class KonanIr(context: Context, irModule: IrModuleFragment): Ir<Context
|
||||
|
||||
override var symbols: KonanSymbols by Delegates.notNull()
|
||||
|
||||
fun getClass(type: KotlinType): IrClass? =
|
||||
(type.constructor.declarationDescriptor as? ClassDescriptor)?.let { get(it) }
|
||||
|
||||
fun get(descriptor: FunctionDescriptor): IrFunction {
|
||||
return moduleIndexForCodegen.functions[descriptor]
|
||||
?: symbols.symbolTable.referenceFunction(descriptor).owner
|
||||
@@ -90,10 +95,35 @@ internal class KonanIr(context: Context, irModule: IrModuleFragment): Ir<Context
|
||||
?: symbols.symbolTable.referenceEnumEntry(descriptor).owner
|
||||
}
|
||||
|
||||
fun getEnum(descriptor: ClassDescriptor): IrClass {
|
||||
assert(descriptor.kind == ClassKind.ENUM_CLASS)
|
||||
return originalModuleIndex.classes[descriptor]
|
||||
?: symbols.symbolTable.referenceClass(descriptor).owner
|
||||
fun translateErased(type: KotlinType): IrSimpleType = symbols.symbolTable.translateErased(type)
|
||||
|
||||
fun translateBroken(type: KotlinType): IrType {
|
||||
val declarationDescriptor = type.constructor.declarationDescriptor
|
||||
return when (declarationDescriptor) {
|
||||
is ClassDescriptor -> {
|
||||
val classifier = IrClassSymbolImpl(declarationDescriptor)
|
||||
val typeArguments = type.arguments.map {
|
||||
if (it.isStarProjection) {
|
||||
IrStarProjectionImpl
|
||||
} else {
|
||||
makeTypeProjection(translateBroken(it.type), it.projectionKind)
|
||||
}
|
||||
}
|
||||
IrSimpleTypeImpl(
|
||||
classifier,
|
||||
type.isMarkedNullable,
|
||||
typeArguments,
|
||||
emptyList()
|
||||
)
|
||||
}
|
||||
is TypeParameterDescriptor -> IrSimpleTypeImpl(
|
||||
IrTypeParameterSymbolImpl(declarationDescriptor),
|
||||
type.isMarkedNullable,
|
||||
emptyList(),
|
||||
emptyList()
|
||||
)
|
||||
else -> error(declarationDescriptor ?: "null")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +135,8 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
|
||||
val throwable = symbolTable.referenceClass(builtIns.throwable)
|
||||
val string = symbolTable.referenceClass(builtIns.string)
|
||||
val enum = symbolTable.referenceClass(builtIns.enum)
|
||||
val nativePtr = symbolTable.referenceClass(context.builtIns.nativePtr)
|
||||
val nativePtrType = nativePtr.typeWith(arguments = emptyList())
|
||||
|
||||
val arrayList = symbolTable.referenceClass(getArrayListClassDescriptor(context))
|
||||
|
||||
@@ -225,19 +257,25 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
|
||||
val getProgressionLast = context.getInternalFunctions("getProgressionLast")
|
||||
.map { Pair(it.returnType, symbolTable.referenceSimpleFunction(it)) }.toMap()
|
||||
|
||||
val arrayContentToString = arrayTypes.associateBy({ it }, { findArrayExtension(it, "contentToString") })
|
||||
val arrayContentHashCode = arrayTypes.associateBy({ it }, { findArrayExtension(it, "contentHashCode") })
|
||||
val arrayContentToString = arrays.associateBy(
|
||||
{ it },
|
||||
{ findArrayExtension(it.descriptor, "contentToString") }
|
||||
)
|
||||
val arrayContentHashCode = arrays.associateBy(
|
||||
{ it },
|
||||
{ findArrayExtension(it.descriptor, "contentHashCode") }
|
||||
)
|
||||
|
||||
fun findArrayExtension(type: KotlinType, name: String): IrSimpleFunctionSymbol {
|
||||
val descriptor = builtInsPackage("kotlin", "collections")
|
||||
fun findArrayExtension(descriptor: ClassDescriptor, name: String): IrSimpleFunctionSymbol {
|
||||
val functionDescriptor = builtInsPackage("kotlin", "collections")
|
||||
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
|
||||
.singleOrNull {
|
||||
it.valueParameters.isEmpty()
|
||||
&& (it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.defaultType == type
|
||||
&& it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == descriptor
|
||||
&& !it.isExpect
|
||||
}
|
||||
?: throw Error(type.toString())
|
||||
return symbolTable.referenceSimpleFunction(descriptor)
|
||||
?: throw Error(descriptor.toString())
|
||||
return symbolTable.referenceSimpleFunction(functionDescriptor)
|
||||
}
|
||||
|
||||
override val copyRangeTo = arrays.map { symbol ->
|
||||
@@ -340,6 +378,11 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
|
||||
val kFunctions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS)
|
||||
.map { symbolTable.referenceClass(context.reflectionTypes.getKFunction(it)) }
|
||||
|
||||
fun getKFunctionType(returnType: IrType, parameterTypes: List<IrType>): IrType {
|
||||
val kFunctionClassSymbol = kFunctions[parameterTypes.size]
|
||||
return kFunctionClassSymbol.typeWith(parameterTypes + returnType)
|
||||
}
|
||||
|
||||
val suspendFunctions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS)
|
||||
.map { symbolTable.referenceClass(builtIns.getSuspendFunction(it)) }
|
||||
|
||||
|
||||
+6
-5
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
@@ -148,7 +149,7 @@ interface IrSuspendableExpression : IrExpression {
|
||||
var result: IrExpression
|
||||
}
|
||||
|
||||
class IrSuspensionPointImpl(startOffset: Int, endOffset: Int, type: KotlinType,
|
||||
class IrSuspensionPointImpl(startOffset: Int, endOffset: Int, type: IrType,
|
||||
override var suspensionPointIdParameter: IrVariable,
|
||||
override var result: IrExpression,
|
||||
override var resumeResult: IrExpression)
|
||||
@@ -170,7 +171,7 @@ class IrSuspensionPointImpl(startOffset: Int, endOffset: Int, type: KotlinType,
|
||||
}
|
||||
}
|
||||
|
||||
class IrSuspendableExpressionImpl(startOffset: Int, endOffset: Int, type: KotlinType,
|
||||
class IrSuspendableExpressionImpl(startOffset: Int, endOffset: Int, type: IrType,
|
||||
override var suspensionPointId: IrExpression, override var result: IrExpression)
|
||||
: IrExpressionBase(startOffset, endOffset, type), IrSuspendableExpression {
|
||||
|
||||
@@ -198,7 +199,7 @@ internal interface IrPrivateFunctionCall : IrCall {
|
||||
|
||||
internal class IrPrivateFunctionCallImpl(startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: KotlinType,
|
||||
type: IrType,
|
||||
override val symbol: IrFunctionSymbol,
|
||||
override val descriptor: FunctionDescriptor,
|
||||
override val virtualCallee: IrCall?,
|
||||
@@ -235,9 +236,9 @@ internal interface IrPrivateClassReference : IrClassReference {
|
||||
|
||||
internal class IrPrivateClassReferenceImpl(startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: KotlinType,
|
||||
type: IrType,
|
||||
symbol: IrClassifierSymbol,
|
||||
override val classType: KotlinType,
|
||||
override val classType: IrType,
|
||||
override val moduleDescriptor: ModuleDescriptor,
|
||||
override val totalClasses: Int,
|
||||
override val classIndex: Int,
|
||||
|
||||
+3
-14
@@ -18,23 +18,16 @@ package org.jetbrains.kotlin.backend.konan.irasdescriptors
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.llvmSymbolOrigin
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.constants.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
|
||||
// This file contains some IR utilities which actually use descriptors.
|
||||
// TODO: port this code to IR.
|
||||
|
||||
internal val IrDeclaration.annotations get() = this.descriptor.annotations
|
||||
internal val IrDeclaration.isAnonymousObject get() = DescriptorUtils.isAnonymousObject(this.descriptor)
|
||||
internal val IrFunction.isExternal get() = this.descriptor.isExternal
|
||||
internal val IrDeclaration.isLocal get() = DescriptorUtils.isLocal(this.descriptor)
|
||||
@@ -59,9 +52,5 @@ internal val IrDeclaration.llvmSymbolOrigin get() = this.descriptor.llvmSymbolOr
|
||||
|
||||
internal fun IrFunction.isMain() = MainFunctionDetector.isMain(this.descriptor)
|
||||
|
||||
internal fun IrTypeOperatorCall.getTypeOperandClass(context: Context): IrClass? =
|
||||
context.ir.getClass(this.typeOperand)
|
||||
|
||||
internal fun IrCatch.getCatchParameterTypeClass(context: Context): IrClass? =
|
||||
context.ir.getClass(this.catchParameter.type)
|
||||
internal fun IrType.isObjCObjectType() = this.toKotlinType().isObjCObjectType()
|
||||
|
||||
|
||||
+3
-1
@@ -27,5 +27,7 @@ internal typealias ConstructorDescriptor = IrConstructor
|
||||
internal typealias ClassConstructorDescriptor = IrConstructor
|
||||
internal typealias PackageFragmentDescriptor = IrPackageFragment
|
||||
internal typealias VariableDescriptor = IrVariable
|
||||
internal typealias ValueDescriptor = IrSymbolDeclaration<IrValueSymbol>
|
||||
internal typealias ValueDescriptor = IrValueDeclaration
|
||||
internal typealias ParameterDescriptor = IrValueParameter
|
||||
internal typealias ValueParameterDescriptor = IrValueParameter
|
||||
internal typealias TypeParameterDescriptor = IrTypeParameter
|
||||
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.irasdescriptors
|
||||
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
|
||||
val IrClassifierSymbol.typeWithoutArguments: IrType
|
||||
get() = when (this) {
|
||||
is IrClassSymbol -> {
|
||||
require(this.descriptor.declaredTypeParameters.isEmpty())
|
||||
this.typeWith(arguments = emptyList())
|
||||
}
|
||||
is IrTypeParameterSymbol -> this.defaultType
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
val IrClassifierSymbol.typeWithStarProjections
|
||||
get() = when (this) {
|
||||
is IrClassSymbol -> createType(
|
||||
hasQuestionMark = false,
|
||||
arguments = this.descriptor.declaredTypeParameters.map { IrStarProjectionImpl }
|
||||
)
|
||||
is IrTypeParameterSymbol -> this.defaultType
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
val IrTypeParameterSymbol.defaultType: IrType get() = IrSimpleTypeImpl(
|
||||
this,
|
||||
false,
|
||||
emptyList(),
|
||||
emptyList()
|
||||
)
|
||||
val IrTypeParameter.defaultType: IrType get() = this.symbol.defaultType
|
||||
|
||||
fun IrClassifierSymbol.typeWith(vararg arguments: IrType): IrSimpleType = typeWith(arguments.toList())
|
||||
|
||||
fun IrClassifierSymbol.typeWith(arguments: List<IrType>): IrSimpleType =
|
||||
IrSimpleTypeImpl(
|
||||
this,
|
||||
false,
|
||||
arguments.map { makeTypeProjection(it, Variance.INVARIANT) },
|
||||
emptyList()
|
||||
)
|
||||
|
||||
fun IrClass.typeWith(arguments: List<IrType>) = this.symbol.typeWith(arguments)
|
||||
|
||||
fun IrClassSymbol.createType(hasQuestionMark: Boolean, arguments: List<IrTypeArgument>): IrSimpleType =
|
||||
IrSimpleTypeImpl(
|
||||
this,
|
||||
hasQuestionMark,
|
||||
arguments,
|
||||
emptyList()
|
||||
)
|
||||
|
||||
fun IrType.getClass(): IrClass? =
|
||||
(this.classifierOrNull as? IrClassSymbol)?.owner
|
||||
|
||||
fun IrType.makeNullableAsSpecified(nullable: Boolean): IrType =
|
||||
if (nullable) this.makeNullable() else this.makeNotNull()
|
||||
|
||||
fun IrType.containsNull(): Boolean = if (this is IrSimpleType) {
|
||||
if (this.hasQuestionMark) {
|
||||
true
|
||||
} else {
|
||||
val classifier = this.classifier
|
||||
when (classifier) {
|
||||
is IrClassSymbol -> false
|
||||
is IrTypeParameterSymbol -> classifier.owner.superTypes.any { it.containsNull() }
|
||||
else -> error(classifier)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
||||
// TODO: get rid of these:
|
||||
fun IrType.isSubtypeOf(other: KotlinType): Boolean = this.toKotlinType().isSubtypeOf(other)
|
||||
fun IrType.isSubtypeOf(other: IrType): Boolean = this.isSubtypeOf(other.toKotlinType())
|
||||
|
||||
val IrType.isFunctionOrKFunctionType: Boolean
|
||||
get() = when (this) {
|
||||
is IrSimpleType -> {
|
||||
val kind = classifier.descriptor.getFunctionalClassKind()
|
||||
kind == FunctionClassDescriptor.Kind.Function || kind == FunctionClassDescriptor.Kind.KFunction
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
internal tailrec fun IrType.getErasedTypeClass(): IrClassSymbol {
|
||||
val classifier = this.classifierOrFail
|
||||
return when (classifier) {
|
||||
is IrClassSymbol -> classifier
|
||||
is IrTypeParameterSymbol -> classifier.owner.superTypes.first().getErasedTypeClass()
|
||||
else -> error(classifier)
|
||||
}
|
||||
}
|
||||
+16
-142
@@ -23,28 +23,15 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.getTypeArgumentOrDefault
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.explicitParameters
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.constants.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
val IrConstructor.constructedClass get() = this.parent as IrClass
|
||||
|
||||
@@ -88,26 +75,6 @@ val IrFunction.allParameters: List<IrValueParameter>
|
||||
explicitParameters
|
||||
}
|
||||
|
||||
/**
|
||||
* @return naturally-ordered list of the parameters that can have values specified at call site.
|
||||
*/
|
||||
val IrFunction.explicitParameters: List<IrValueParameter>
|
||||
get() {
|
||||
val result = ArrayList<IrValueParameter>(valueParameters.size + 2)
|
||||
|
||||
this.dispatchReceiverParameter?.let {
|
||||
result.add(it)
|
||||
}
|
||||
|
||||
this.extensionReceiverParameter?.let {
|
||||
result.add(it)
|
||||
}
|
||||
|
||||
result.addAll(valueParameters)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
val IrValueParameter.isVararg get() = this.varargElementType != null
|
||||
|
||||
val IrFunction.isSuspend get() = this is IrSimpleFunction && this.isSuspend
|
||||
@@ -116,6 +83,7 @@ fun IrClass.isUnit() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.unit.toSafe()
|
||||
|
||||
fun IrClass.isKotlinArray() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.array.toSafe()
|
||||
|
||||
val IrClass.superClasses get() = this.superTypes.map { it.classifierOrFail as IrClassSymbol }
|
||||
fun IrClass.getSuperClassNotAny() = this.superClasses.map { it.owner }.atMostOne { !it.isInterface && !it.isAny() }
|
||||
|
||||
fun IrClass.isAny() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.any.toSafe()
|
||||
@@ -132,7 +100,8 @@ val IrProperty.konanBackingField: IrField?
|
||||
this.startOffset,
|
||||
this.endOffset,
|
||||
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
|
||||
backingFieldDescriptor
|
||||
backingFieldDescriptor,
|
||||
this.getter!!.returnType // TODO: this copies the behaviour found in backing field descriptor creation, but both are incorrect for property delegation.
|
||||
).also {
|
||||
it.parent = this.parent
|
||||
}
|
||||
@@ -143,9 +112,6 @@ val IrProperty.konanBackingField: IrField?
|
||||
return null
|
||||
}
|
||||
|
||||
val IrClass.defaultType: KotlinType
|
||||
get() = this.thisReceiver!!.type
|
||||
|
||||
val IrField.containingClass get() = this.parent as? IrClass
|
||||
|
||||
val IrFunction.isReal get() = this.origin != IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
@@ -177,109 +143,17 @@ fun IrSimpleFunction.overrides(other: IrSimpleFunction): Boolean {
|
||||
|
||||
fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing()
|
||||
|
||||
val IrClass.constructors get() = this.declarations.filterIsInstance<IrConstructor>()
|
||||
|
||||
internal val IrValueParameter.isValueParameter get() = this.index >= 0
|
||||
|
||||
fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTable) {
|
||||
val moduleDescriptor = this.descriptor
|
||||
private val IrCall.annotationClass
|
||||
get() = (this.symbol.owner as IrConstructor).constructedClass
|
||||
|
||||
fun KotlinType.referenceAllClassifiers() {
|
||||
TypeUtils.getClassDescriptor(this)?.let {
|
||||
if (!ErrorUtils.isError(it) && it.module != moduleDescriptor) {
|
||||
if (it.kind == ClassKind.ENUM_ENTRY) {
|
||||
symbolTable.referenceEnumEntry(it)
|
||||
} else {
|
||||
symbolTable.referenceClass(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
fun List<IrCall>.hasAnnotation(fqName: FqName): Boolean =
|
||||
this.any { it.annotationClass.fqNameSafe == fqName }
|
||||
|
||||
this.constructor.supertypes.forEach {
|
||||
it.referenceAllClassifiers()
|
||||
}
|
||||
}
|
||||
fun IrAnnotationContainer.hasAnnotation(fqName: FqName) =
|
||||
this.annotations.hasAnnotation(fqName)
|
||||
|
||||
val visitor = object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitValueParameter(declaration: IrValueParameter) {
|
||||
super.visitValueParameter(declaration)
|
||||
declaration.type.referenceAllClassifiers()
|
||||
}
|
||||
|
||||
override fun visitVariable(declaration: IrVariable) {
|
||||
super.visitVariable(declaration)
|
||||
declaration.type.referenceAllClassifiers()
|
||||
}
|
||||
|
||||
override fun visitExpression(expression: IrExpression) {
|
||||
super.visitExpression(expression)
|
||||
expression.type.referenceAllClassifiers()
|
||||
}
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclaration) {
|
||||
super.visitDeclaration(declaration)
|
||||
declaration.descriptor.annotations.getAllAnnotations().forEach {
|
||||
handleClassReferences(it.annotation)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleClassReferences(annotation: AnnotationDescriptor) {
|
||||
annotation.allValueArguments.values.forEach {
|
||||
it.accept(object : AnnotationArgumentVisitor<Unit, Nothing?> {
|
||||
|
||||
override fun visitKClassValue(p0: KClassValue?, p1: Nothing?) {
|
||||
p0?.value?.referenceAllClassifiers()
|
||||
}
|
||||
|
||||
override fun visitArrayValue(p0: ArrayValue?, p1: Nothing?) {
|
||||
p0?.value?.forEach { it.accept(this, null) }
|
||||
}
|
||||
|
||||
override fun visitAnnotationValue(p0: AnnotationValue?, p1: Nothing?) {
|
||||
p0?.let { handleClassReferences(p0.value) }
|
||||
}
|
||||
|
||||
override fun visitBooleanValue(p0: BooleanValue?, p1: Nothing?) {}
|
||||
override fun visitShortValue(p0: ShortValue?, p1: Nothing?) {}
|
||||
override fun visitByteValue(p0: ByteValue?, p1: Nothing?) {}
|
||||
override fun visitNullValue(p0: NullValue?, p1: Nothing?) {}
|
||||
override fun visitDoubleValue(p0: DoubleValue?, p1: Nothing?) {}
|
||||
override fun visitLongValue(p0: LongValue, p1: Nothing?) {}
|
||||
override fun visitCharValue(p0: CharValue?, p1: Nothing?) {}
|
||||
override fun visitIntValue(p0: IntValue?, p1: Nothing?) {}
|
||||
override fun visitUIntValue(p0: UIntValue?, p1: Nothing?) {}
|
||||
override fun visitUShortValue(p0: UShortValue?, p1: Nothing?) {}
|
||||
override fun visitUByteValue(p0: UByteValue?, p1: Nothing?) {}
|
||||
override fun visitULongValue(p0: ULongValue?, p1: Nothing?) {}
|
||||
override fun visitErrorValue(p0: ErrorValue?, p1: Nothing?) {}
|
||||
override fun visitFloatValue(p0: FloatValue?, p1: Nothing?) {}
|
||||
override fun visitEnumValue(p0: EnumValue?, p1: Nothing?) {}
|
||||
override fun visitStringValue(p0: StringValue?, p1: Nothing?) {}
|
||||
}, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
super.visitFunction(declaration)
|
||||
declaration.returnType.referenceAllClassifiers()
|
||||
}
|
||||
|
||||
override fun visitFunctionAccess(expression: IrFunctionAccessExpression) {
|
||||
super.visitFunctionAccess(expression)
|
||||
expression.descriptor.original.typeParameters.forEach {
|
||||
expression.getTypeArgumentOrDefault(it).referenceAllClassifiers()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.acceptVoid(visitor)
|
||||
this.dependencyModules.forEach { module ->
|
||||
module.externalPackageFragments.forEach {
|
||||
it.acceptVoid(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
fun List<IrCall>.findAnnotation(fqName: FqName): IrCall? = this.firstOrNull {
|
||||
it.annotationClass.fqNameSafe == fqName
|
||||
}
|
||||
|
||||
+20
-23
@@ -17,25 +17,19 @@
|
||||
package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import llvm.LLVMTypeRef
|
||||
import llvm.LLVMVoidType
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.isValueType
|
||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||
|
||||
|
||||
@@ -128,14 +122,14 @@ private val publishedApiAnnotation = FqName("kotlin.PublishedApi")
|
||||
|
||||
private val inlineExposedAnnotation = FqName("kotlin.internal.InlineExposed")
|
||||
|
||||
private fun acyclicTypeMangler(visited: MutableSet<TypeParameterDescriptor>, type: KotlinType): String {
|
||||
val descriptor = TypeUtils.getTypeParameterDescriptorOrNull(type)
|
||||
private fun acyclicTypeMangler(visited: MutableSet<TypeParameterDescriptor>, type: IrType): String {
|
||||
val descriptor = (type.classifierOrNull as? IrTypeParameterSymbol)?.owner
|
||||
if (descriptor != null) {
|
||||
val upperBounds = if (visited.contains(descriptor)) "" else {
|
||||
|
||||
visited.add(descriptor)
|
||||
|
||||
descriptor.upperBounds.map {
|
||||
descriptor.superTypes.map {
|
||||
val bound = acyclicTypeMangler(visited, it)
|
||||
if (bound == "kotlin.Any?") "" else "_$bound"
|
||||
}.joinToString("")
|
||||
@@ -143,24 +137,27 @@ private fun acyclicTypeMangler(visited: MutableSet<TypeParameterDescriptor>, typ
|
||||
return "#GENERIC" + upperBounds
|
||||
}
|
||||
|
||||
var hashString = TypeUtils.getClassDescriptor(type)!!.fqNameSafe.asString()
|
||||
var hashString = type.getClass()!!.fqNameSafe.asString()
|
||||
if (type !is IrSimpleType) error(type)
|
||||
if (!type.arguments.isEmpty()) {
|
||||
hashString += "<${type.arguments.map {
|
||||
if (it.isStarProjection()) {
|
||||
"#STAR"
|
||||
} else {
|
||||
val variance = it.projectionKind.label
|
||||
val projection = if (variance == "") "" else "${variance}_"
|
||||
projection + acyclicTypeMangler(visited, it.type)
|
||||
when (it) {
|
||||
is IrStarProjection -> "#STAR"
|
||||
is IrTypeProjection -> {
|
||||
val variance = it.variance.label
|
||||
val projection = if (variance == "") "" else "${variance}_"
|
||||
projection + acyclicTypeMangler(visited, it.type)
|
||||
}
|
||||
else -> error(it)
|
||||
}
|
||||
}.joinToString(",")}>"
|
||||
}
|
||||
|
||||
if (type.isMarkedNullable) hashString += "?"
|
||||
if (type.hasQuestionMark) hashString += "?"
|
||||
return hashString
|
||||
}
|
||||
|
||||
private fun typeToHashString(type: KotlinType)
|
||||
private fun typeToHashString(type: IrType)
|
||||
= acyclicTypeMangler(mutableSetOf<TypeParameterDescriptor>(), type)
|
||||
|
||||
private val FunctionDescriptor.signature: String
|
||||
@@ -175,7 +172,7 @@ private val FunctionDescriptor.signature: String
|
||||
when {
|
||||
this.typeParameters.isNotEmpty() -> "Generic"
|
||||
returnType.isValueType() -> "ValueType"
|
||||
!KotlinBuiltIns.isUnitOrNullableUnit(returnType) -> typeToHashString(returnType)
|
||||
!returnType.isUnitOrNullableUnit() -> typeToHashString(returnType)
|
||||
else -> ""
|
||||
}
|
||||
return "$extensionReceiverPart($argsPart)$signatureSuffix"
|
||||
@@ -188,7 +185,7 @@ internal val FunctionDescriptor.functionName: String
|
||||
this.getObjCMethodInfo()?.let {
|
||||
return buildString {
|
||||
if (extensionReceiverParameter != null) {
|
||||
append(TypeUtils.getClassDescriptor(extensionReceiverParameter!!.type)!!.name)
|
||||
append(extensionReceiverParameter!!.type.getClass()!!.name)
|
||||
append(".")
|
||||
}
|
||||
|
||||
@@ -235,7 +232,7 @@ internal val IrField.symbolName: String
|
||||
|
||||
}
|
||||
|
||||
private fun getStringValue(annotation: AnnotationDescriptor): String? {
|
||||
internal fun getStringValue(annotation: AnnotationDescriptor): String? {
|
||||
return annotation.allValueArguments.values.ifNotEmpty {
|
||||
val stringValue = single() as? StringValue
|
||||
stringValue?.value
|
||||
|
||||
+3
-1
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.backend.konan.descriptors.stdlibModule
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.objc.ObjCDataGenerator
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
@@ -709,7 +711,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
*/
|
||||
fun getEnumEntry(descriptor: IrEnumEntry, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
||||
val enumClassDescriptor = descriptor.containingDeclaration as ClassDescriptor
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor.descriptor)
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
|
||||
|
||||
val ordinal = loweredEnum.entriesMap[descriptor.name]!!
|
||||
val values = call(
|
||||
|
||||
+5
-8
@@ -20,9 +20,8 @@ import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.ValueType
|
||||
import org.jetbrains.kotlin.backend.konan.isRepresentedAs
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
|
||||
private val valueTypes = ValueType.values().associate {
|
||||
it to when (it) {
|
||||
@@ -41,7 +40,7 @@ private val valueTypes = ValueType.values().associate {
|
||||
internal val ValueType.llvmType
|
||||
get() = valueTypes[this]!!
|
||||
|
||||
internal fun RuntimeAware.getLLVMType(type: KotlinType): LLVMTypeRef {
|
||||
internal fun RuntimeAware.getLLVMType(type: IrType): LLVMTypeRef {
|
||||
for ((valueType, llvmType) in valueTypes) {
|
||||
if (type.isRepresentedAs(valueType)) {
|
||||
return llvmType
|
||||
@@ -54,13 +53,11 @@ internal fun RuntimeAware.getLLVMType(type: KotlinType): LLVMTypeRef {
|
||||
internal fun RuntimeAware.getLLVMType(type: DataFlowIR.Type) =
|
||||
type.correspondingValueType?.let { valueTypes[it]!! } ?: this.kObjHeaderPtr
|
||||
|
||||
internal fun RuntimeAware.getLLVMReturnType(type: KotlinType): LLVMTypeRef {
|
||||
internal fun RuntimeAware.getLLVMReturnType(type: IrType): LLVMTypeRef {
|
||||
return when {
|
||||
type.isUnit() -> LLVMVoidType()!!
|
||||
// TODO: stdlib have methods taking Nothing, such as kotlin.collections.EmptySet.contains().
|
||||
// KotlinBuiltIns.isNothing(type) -> LLVMVoidType()
|
||||
else -> getLLVMType(type)
|
||||
}
|
||||
}
|
||||
|
||||
fun RuntimeAware.isObjectType(type: KotlinType) : Boolean = isObjectType(getLLVMType(type))
|
||||
}
|
||||
+2
-2
@@ -184,8 +184,8 @@ private fun debugInfoBaseType(context:Context, targetData:LLVMTargetDataRef, typ
|
||||
|
||||
internal val FunctionDescriptor.types:List<KotlinType>
|
||||
get() {
|
||||
val parameters = valueParameters.map{it.type}
|
||||
return listOf(returnType, *parameters.toTypedArray())
|
||||
val parameters = descriptor.valueParameters.map{it.type}
|
||||
return listOf(descriptor.returnType!!, *parameters.toTypedArray())
|
||||
}
|
||||
|
||||
internal fun KotlinType.size(context:Context) = context.debugInfo.llvmTypeSizes.getOrDefault(this, context.debugInfo.otherTypeSize)
|
||||
|
||||
+30
-39
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.*
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -36,6 +35,8 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
@@ -43,11 +44,6 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
val IrClassSymbol.objectIsShared get() = owner.origin == DECLARATION_ORIGIN_ENUM
|
||||
|
||||
@@ -862,7 +858,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
* Creates new [ContinuationBlock] that receives the value of given Kotlin type
|
||||
* and generates [code] starting from its beginning.
|
||||
*/
|
||||
private fun continuationBlock(type: KotlinType,
|
||||
private fun continuationBlock(type: IrType,
|
||||
locationInfo: LocationInfo?, code: (ContinuationBlock) -> Unit = {}): ContinuationBlock {
|
||||
val entry = functionGenerationContext.basicBlock("continuation_block", locationInfo)
|
||||
|
||||
@@ -893,7 +889,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
throw IllegalStateException("IrVararg neither was lowered nor can be statically evaluated")
|
||||
}
|
||||
|
||||
val arrayClass = context.ir.getClass(value.type)!!
|
||||
val arrayClass = value.type.getClass()!!
|
||||
|
||||
// Note: even if all elements are const, they aren't guaranteed to be statically initialized.
|
||||
// E.g. an element may be a pointer to lazy-initialized object (aka singleton).
|
||||
@@ -934,7 +930,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
*/
|
||||
private val handler by lazy {
|
||||
using(outerContext) {
|
||||
continuationBlock(context.builtIns.throwable.defaultType, endLocationInfoFromScope()) {
|
||||
continuationBlock(context.ir.symbols.throwable.owner.defaultType, endLocationInfoFromScope()) {
|
||||
genHandler(it.value)
|
||||
}
|
||||
}
|
||||
@@ -1008,7 +1004,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
genCatchBlock()
|
||||
return // Remaining catch clauses are unreachable.
|
||||
} else {
|
||||
val isInstance = genInstanceOf(exception, catch.getCatchParameterTypeClass(context)!!)
|
||||
val isInstance = genInstanceOf(exception, catch.catchParameter.type.getClass()!!)
|
||||
val body = functionGenerationContext.basicBlock("catch", catch.startLocation)
|
||||
val nextCheck = functionGenerationContext.basicBlock("catchCheck", catch.endLocation)
|
||||
functionGenerationContext.condBr(isInstance, body, nextCheck)
|
||||
@@ -1058,8 +1054,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
private fun evaluateWhen(expression: IrWhen): LLVMValueRef {
|
||||
context.log{"evaluateWhen : ${ir2string(expression)}"}
|
||||
var bbExit: LLVMBasicBlockRef? = null // By default "when" does not have "exit".
|
||||
val isUnit = KotlinBuiltIns.isUnit(expression.type)
|
||||
val isNothing = KotlinBuiltIns.isNothing(expression.type)
|
||||
val isUnit = expression.type.isUnit()
|
||||
val isNothing = expression.type.isNothing()
|
||||
|
||||
// We may not cover all cases if IrWhen is used as statement.
|
||||
val coverAllCases = isUnconditional(expression.branches.last())
|
||||
@@ -1143,14 +1139,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun evaluateGetValue(value: IrGetValue): LLVMValueRef {
|
||||
context.log{"evaluateGetValue : ${ir2string(value)}"}
|
||||
val symbol = value.symbol
|
||||
val ir: IrSymbolDeclaration<IrValueSymbol> = when (symbol) {
|
||||
is IrVariableSymbol -> symbol.owner
|
||||
is IrValueParameterSymbol -> symbol.owner
|
||||
else -> error(symbol)
|
||||
}
|
||||
|
||||
return currentCodeContext.genGetValue(ir)
|
||||
return currentCodeContext.genGetValue(value.symbol.owner)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -1221,11 +1210,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun KotlinType.isPrimitiveInteger(): Boolean {
|
||||
return isPrimitiveNumberType() &&
|
||||
!KotlinBuiltIns.isFloat(this) &&
|
||||
!KotlinBuiltIns.isDouble(this) &&
|
||||
!KotlinBuiltIns.isChar(this)
|
||||
private fun IrType.isPrimitiveInteger(): Boolean {
|
||||
return this.isPrimitiveType() &&
|
||||
!this.isBoolean() &&
|
||||
!this.isFloat() &&
|
||||
!this.isDouble() &&
|
||||
!this.isChar()
|
||||
}
|
||||
|
||||
private fun evaluateIntegerCoercion(value: IrTypeOperatorCall): LLVMValueRef {
|
||||
@@ -1259,10 +1249,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun evaluateCast(value: IrTypeOperatorCall): LLVMValueRef {
|
||||
context.log{"evaluateCast : ${ir2string(value)}"}
|
||||
val dstDescriptor = value.getTypeOperandClass(context)!!
|
||||
val dstDescriptor = value.typeOperand.getClass()!!
|
||||
|
||||
assert(!KotlinBuiltIns.isPrimitiveType(dstDescriptor.defaultType) &&
|
||||
!KotlinBuiltIns.isPrimitiveType(value.argument.type))
|
||||
assert(!dstDescriptor.defaultType.isValueType() &&
|
||||
!value.argument.type.isValueType())
|
||||
|
||||
val srcArg = evaluateExpression(value.argument) // Evaluate src expression.
|
||||
|
||||
@@ -1304,11 +1294,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
functionGenerationContext.condBr(condition, bbNull, bbInstanceOf)
|
||||
|
||||
functionGenerationContext.positionAtEnd(bbNull)
|
||||
val resultNull = if (TypeUtils.isNullableType(type)) kTrue else kFalse
|
||||
val resultNull = if (type.containsNull()) kTrue else kFalse
|
||||
functionGenerationContext.br(bbExit)
|
||||
|
||||
functionGenerationContext.positionAtEnd(bbInstanceOf)
|
||||
val typeOperandClass = value.getTypeOperandClass(context)
|
||||
val typeOperandClass = value.typeOperand.getClass()
|
||||
val resultInstanceOf = if (typeOperandClass != null) {
|
||||
genInstanceOf(srcArg, typeOperandClass)
|
||||
} else {
|
||||
@@ -1883,7 +1873,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionDescriptor.returnsUnit() = returnType == context.builtIns.unitType && !isSuspend
|
||||
private fun FunctionDescriptor.returnsUnit() = returnType.isUnit() && !isSuspend
|
||||
|
||||
/**
|
||||
* Evaluates all arguments of [expression] that are explicitly represented in the IR.
|
||||
@@ -1906,7 +1896,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun evaluateFunctionReference(expression: IrFunctionReference): LLVMValueRef {
|
||||
// TODO: consider creating separate IR element for pointer to function.
|
||||
assert (TypeUtils.getClassDescriptor(expression.type) == context.interopBuiltIns.cPointer)
|
||||
assert (expression.type.getClass()?.descriptor == context.interopBuiltIns.cPointer)
|
||||
|
||||
assert (expression.getArguments().isEmpty())
|
||||
|
||||
@@ -2105,6 +2095,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun evaluateIntrinsicCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val descriptor = callee.descriptor.original
|
||||
val function = callee.symbol.owner
|
||||
val name = descriptor.fqNameUnsafe.asString()
|
||||
|
||||
when (name) {
|
||||
@@ -2137,13 +2128,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
interop.nativePointedGetRawPointer, interop.cPointerGetRawValue -> args.single()
|
||||
|
||||
in interop.readPrimitive -> {
|
||||
val pointerType = pointerType(codegen.getLLVMType(descriptor.returnType!!))
|
||||
val pointerType = pointerType(codegen.getLLVMType(function.returnType))
|
||||
val rawPointer = args.last()
|
||||
val pointer = functionGenerationContext.bitcast(pointerType, rawPointer)
|
||||
functionGenerationContext.load(pointer)
|
||||
}
|
||||
in interop.writePrimitive -> {
|
||||
val pointerType = pointerType(codegen.getLLVMType(descriptor.valueParameters.last().type))
|
||||
val pointerType = pointerType(codegen.getLLVMType(function.valueParameters.last().type))
|
||||
val rawPointer = args[1]
|
||||
val pointer = functionGenerationContext.bitcast(pointerType, rawPointer)
|
||||
functionGenerationContext.store(args[2], pointer)
|
||||
@@ -2154,7 +2145,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
interop.getPointerSize -> Int32(LLVMPointerSize(codegen.llvmTargetData)).llvm
|
||||
context.builtIns.nativePtrToLong -> {
|
||||
val intPtrValue = functionGenerationContext.ptrToInt(args.single(), codegen.intPtrType)
|
||||
val resultType = functionGenerationContext.getLLVMType(descriptor.returnType!!)
|
||||
val resultType = functionGenerationContext.getLLVMType(function.returnType)
|
||||
|
||||
if (resultType == intPtrValue.type) {
|
||||
intPtrValue
|
||||
@@ -2169,7 +2160,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
interop.getObjCClass -> {
|
||||
val typeArgument = callee.getTypeArgument(descriptor.typeParameters.single())
|
||||
val irClass = context.ir.getClass(typeArgument!!)!!
|
||||
val irClass = typeArgument!!.getClass()!!
|
||||
genGetObjCClass(irClass)
|
||||
}
|
||||
|
||||
@@ -2184,8 +2175,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
interop.writeBits -> genWriteBits(args)
|
||||
|
||||
context.ir.symbols.getClassTypeInfo.descriptor -> {
|
||||
val typeArgument = callee.getTypeArgumentOrDefault(descriptor.typeParameters.single())
|
||||
val typeArgumentClass = context.ir.getClass(typeArgument)
|
||||
val typeArgument = callee.getTypeArgument(0)!!
|
||||
val typeArgumentClass = typeArgument.getClass()
|
||||
if (typeArgumentClass == null) {
|
||||
// E.g. for `T::class` in a body of an inline function itself.
|
||||
functionGenerationContext.unreachable()
|
||||
@@ -2202,7 +2193,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
context.ir.symbols.createUninitializedInstance.descriptor -> {
|
||||
val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0]
|
||||
val enumClass = callee.getTypeArgument(typeParameterT)!!
|
||||
val enumIrClass = context.ir.getClass(enumClass)!!
|
||||
val enumIrClass = enumClass.getClass()!!
|
||||
functionGenerationContext.allocInstance(enumIrClass, resultLifetime(callee))
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.getStringValueOrNull
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
|
||||
|
||||
+2
-1
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -140,7 +141,7 @@ private fun Context.getDeclaredFields(classDescriptor: ClassDescriptor): List<Ir
|
||||
private fun ContextUtils.createClassBodyType(name: String, fields: List<IrField>): LLVMTypeRef {
|
||||
val fieldTypes = fields.map {
|
||||
@Suppress("DEPRECATION")
|
||||
getLLVMType(if (it.isDelegate) context.builtIns.nullableAnyType else it.type)
|
||||
getLLVMType(if (it.isDelegate) context.irBuiltIns.anyNType else it.type)
|
||||
}
|
||||
|
||||
val classType = LLVMStructCreateNamed(LLVMGetModuleContext(context.llvmModule), name)!!
|
||||
|
||||
+2
-2
@@ -101,9 +101,9 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
private fun exportTypeInfoIfRequired(classDesc: ClassDescriptor, typeInfoGlobal: LLVMValueRef?) {
|
||||
val annot = classDesc.descriptor.annotations.findAnnotation(FqName("konan.ExportTypeInfo"))
|
||||
if (annot != null) {
|
||||
val nameValue = annot.allValueArguments.values.single() as StringValue
|
||||
val name = getStringValue(annot)!!
|
||||
// TODO: use LLVMAddAlias?
|
||||
val global = addGlobal(nameValue.value, pointerType(runtime.typeInfoType), isExported = true)
|
||||
val global = addGlobal(name, pointerType(runtime.typeInfoType), isExported = true)
|
||||
LLVMSetInitializer(global, typeInfoGlobal)
|
||||
}
|
||||
}
|
||||
|
||||
-3
@@ -18,9 +18,6 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import kotlinx.cinterop.*
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
interface RuntimeAware {
|
||||
val runtime: Runtime
|
||||
|
||||
-1
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
/**
|
||||
* Provides utilities to create static data.
|
||||
|
||||
-3
@@ -20,7 +20,6 @@ import llvm.LLVMLinkage
|
||||
import llvm.LLVMSetLinkage
|
||||
import llvm.LLVMTypeRef
|
||||
import llvm.LLVMValueRef
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.defaultType
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.llvmSymbolOrigin
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
@@ -28,8 +27,6 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.TypeProjection
|
||||
import org.jetbrains.kotlin.types.replace
|
||||
|
||||
|
||||
private fun StaticData.objHeader(typeInfo: ConstPointer): Struct {
|
||||
|
||||
-6
@@ -176,9 +176,3 @@ internal fun debugInfoParameterLocation(builder: DIBuilderRef?,
|
||||
|
||||
return VariableDebugLocation(localVariable = variableDeclaration!!, location = location, file = file, line = line)
|
||||
}
|
||||
|
||||
private val ValueDescriptor.type get() = when (this) {
|
||||
is IrVariable -> this.type
|
||||
is IrValueParameter -> this.type
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
+2
-3
@@ -19,18 +19,17 @@ package org.jetbrains.kotlin.backend.konan.llvm.objcexport
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.CurrentKonanModule
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
internal fun ObjCExportCodeGenerator.generateKotlinFunctionImpl(invokeMethod: FunctionDescriptor): ConstPointer {
|
||||
internal fun ObjCExportCodeGenerator.generateKotlinFunctionImpl(invokeMethod: IrSimpleFunction): ConstPointer {
|
||||
// TODO: consider also overriding methods of `Any`.
|
||||
|
||||
val numberOfParameters = invokeMethod.valueParameters.size
|
||||
|
||||
val function = generateFunction(
|
||||
codegen,
|
||||
codegen.getLlvmFunctionType(context.ir.get(invokeMethod)),
|
||||
codegen.getLlvmFunctionType(invokeMethod),
|
||||
"invokeFunction$numberOfParameters"
|
||||
) {
|
||||
val args = (0 until numberOfParameters).map { index -> kotlinReferenceToObjC(param(index + 1)) }
|
||||
|
||||
+1
-1
@@ -380,7 +380,7 @@ private fun ObjCExportCodeGenerator.generateKotlinFunctionAdapterToBlock(numberO
|
||||
val invokeMethod = irInterface.declarations.filterIsInstance<IrSimpleFunction>()
|
||||
.single { it.name == OperatorNameConventions.INVOKE }
|
||||
|
||||
val invokeImpl = generateKotlinFunctionImpl(invokeMethod.descriptor)
|
||||
val invokeImpl = generateKotlinFunctionImpl(invokeMethod)
|
||||
|
||||
return rttiGenerator.generateSyntheticInterfaceImpl(
|
||||
irInterface,
|
||||
|
||||
+65
-52
@@ -18,22 +18,25 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.AbstractValueUsageTransformer
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.target
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.containsNull
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isOverridable
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isSuspend
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.makeNullableAsSpecified
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.makeNullable
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
|
||||
/**
|
||||
* Boxes and unboxes values of value types when necessary.
|
||||
@@ -48,9 +51,11 @@ internal class Autoboxing(val context: Context) : FileLoweringPass {
|
||||
|
||||
}
|
||||
|
||||
private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTransformer(context.builtIns) {
|
||||
|
||||
val symbols = context.ir.symbols
|
||||
private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTransformer(
|
||||
context.builtIns,
|
||||
context.ir.symbols,
|
||||
context.irBuiltIns
|
||||
) {
|
||||
|
||||
// TODO: should we handle the cases when expression type
|
||||
// is not equal to e.g. called function return type?
|
||||
@@ -59,23 +64,23 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
||||
/**
|
||||
* @return type to use for runtime type checks instead of given one (e.g. `IntBox` instead of `Int`)
|
||||
*/
|
||||
private fun getRuntimeReferenceType(type: KotlinType): KotlinType {
|
||||
private fun getRuntimeReferenceType(type: IrType): IrType {
|
||||
ValueType.values().forEach {
|
||||
if (type.notNullableIsRepresentedAs(it)) {
|
||||
return getBoxType(it).makeNullableAsSpecified(TypeUtils.isNullableType(type))
|
||||
return getBoxType(it).makeNullableAsSpecified(type.containsNull())
|
||||
}
|
||||
}
|
||||
|
||||
return type
|
||||
}
|
||||
|
||||
override fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: KotlinType): IrExpression {
|
||||
override fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: IrType): IrExpression {
|
||||
return if (operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT ||
|
||||
operator == IrTypeOperator.IMPLICIT_INTEGER_COERCION) {
|
||||
this
|
||||
} else {
|
||||
// Codegen expects the argument of type-checking operator to be an object reference:
|
||||
this.useAs(builtIns.nullableAnyType)
|
||||
this.useAs(context.irBuiltIns.anyNType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +91,7 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
||||
}
|
||||
|
||||
val newTypeOperand = getRuntimeReferenceType(expression.typeOperand)
|
||||
val newTypeOperandClassifier = newTypeOperand.classifierOrFail
|
||||
|
||||
return when (expression.operator) {
|
||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
|
||||
@@ -101,7 +107,7 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
||||
}
|
||||
|
||||
IrTypeOperatorCallImpl(expression.startOffset, expression.endOffset,
|
||||
newExpressionType, expression.operator, newTypeOperand,
|
||||
newExpressionType, expression.operator, newTypeOperand, newTypeOperandClassifier,
|
||||
expression.argument).useAs(expression.type)
|
||||
}
|
||||
|
||||
@@ -110,40 +116,49 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
||||
expression
|
||||
} else {
|
||||
IrTypeOperatorCallImpl(expression.startOffset, expression.endOffset,
|
||||
expression.type, expression.operator, newTypeOperand, expression.argument)
|
||||
expression.type, expression.operator, newTypeOperand, newTypeOperandClassifier,
|
||||
expression.argument)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var currentFunctionDescriptor: FunctionDescriptor? = null
|
||||
private var currentFunctionDescriptor: IrFunction? = null
|
||||
|
||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
currentFunctionDescriptor = declaration.descriptor
|
||||
currentFunctionDescriptor = declaration
|
||||
val result = super.visitFunction(declaration)
|
||||
currentFunctionDescriptor = null
|
||||
return result
|
||||
}
|
||||
|
||||
override fun IrExpression.useAsReturnValue(returnTarget: CallableDescriptor): IrExpression {
|
||||
if (returnTarget.isSuspend && returnTarget == currentFunctionDescriptor)
|
||||
return this.useAs(context.builtIns.nullableAnyType)
|
||||
val returnType = returnTarget.returnType
|
||||
?: return this
|
||||
return this.useAs(returnType)
|
||||
override fun IrExpression.useAsReturnValue(returnTarget: IrReturnTargetSymbol): IrExpression = when (returnTarget) {
|
||||
is IrSimpleFunctionSymbol -> if (returnTarget.owner.isSuspend && returnTarget == currentFunctionDescriptor?.symbol) {
|
||||
this.useAs(irBuiltIns.anyNType)
|
||||
} else {
|
||||
this.useAs(returnTarget.owner.returnType)
|
||||
}
|
||||
is IrConstructorSymbol -> this.useAs(irBuiltIns.unitType)
|
||||
is IrReturnableBlockSymbol -> this.useAs(returnTarget.owner.type)
|
||||
else -> error(returnTarget)
|
||||
}
|
||||
|
||||
override fun IrExpression.useAs(type: KotlinType): IrExpression {
|
||||
override fun IrExpression.useAs(type: IrType): IrExpression {
|
||||
val interop = context.interopBuiltIns
|
||||
if (this.isNullConst() && interop.nullableInteropValueTypes.any { type.isRepresentedAs(it) }) {
|
||||
return IrCallImpl(startOffset, endOffset, symbols.getNativeNullPtr).uncheckedCast(type)
|
||||
return IrCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
symbols.getNativeNullPtr.owner.returnType,
|
||||
symbols.getNativeNullPtr
|
||||
).uncheckedCast(type)
|
||||
}
|
||||
|
||||
val actualType = when (this) {
|
||||
is IrCall -> {
|
||||
if (this.descriptor.isSuspend) context.builtIns.nullableAnyType
|
||||
else this.callTarget.returnType ?: this.type
|
||||
if (this.symbol.owner.isSuspend) irBuiltIns.anyNType
|
||||
else this.callTarget.returnType
|
||||
}
|
||||
is IrGetField -> this.descriptor.original.type
|
||||
is IrGetField -> this.symbol.owner.type
|
||||
|
||||
is IrTypeOperatorCall -> when (this.operator) {
|
||||
IrTypeOperator.IMPLICIT_INTEGER_COERCION ->
|
||||
@@ -159,65 +174,63 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
||||
return this.adaptIfNecessary(actualType, type)
|
||||
}
|
||||
|
||||
private val IrMemberAccessExpression.target: CallableDescriptor get() = when (this) {
|
||||
private val IrFunctionAccessExpression.target: IrFunction get() = when (this) {
|
||||
is IrCall -> this.callTarget
|
||||
is IrDelegatingConstructorCall -> this.descriptor.original
|
||||
is IrDelegatingConstructorCall -> this.symbol.owner
|
||||
else -> TODO(this.render())
|
||||
}
|
||||
|
||||
private val IrCall.callTarget: FunctionDescriptor
|
||||
get() = if (superQualifier == null && descriptor.isOverridable) {
|
||||
private val IrCall.callTarget: IrFunction
|
||||
get() = if (superQualifier == null && symbol.owner.isOverridable) {
|
||||
// A virtual call.
|
||||
descriptor.original
|
||||
symbol.owner
|
||||
} else {
|
||||
descriptor.target
|
||||
symbol.owner.target
|
||||
}
|
||||
|
||||
override fun IrExpression.useAsDispatchReceiver(expression: IrMemberAccessExpression): IrExpression {
|
||||
override fun IrExpression.useAsDispatchReceiver(expression: IrFunctionAccessExpression): IrExpression {
|
||||
return this.useAsArgument(expression.target.dispatchReceiverParameter!!)
|
||||
}
|
||||
|
||||
override fun IrExpression.useAsExtensionReceiver(expression: IrMemberAccessExpression): IrExpression {
|
||||
override fun IrExpression.useAsExtensionReceiver(expression: IrFunctionAccessExpression): IrExpression {
|
||||
return this.useAsArgument(expression.target.extensionReceiverParameter!!)
|
||||
}
|
||||
|
||||
override fun IrExpression.useAsValueArgument(expression: IrMemberAccessExpression,
|
||||
parameter: ValueParameterDescriptor): IrExpression {
|
||||
override fun IrExpression.useAsValueArgument(expression: IrFunctionAccessExpression,
|
||||
parameter: IrValueParameter): IrExpression {
|
||||
|
||||
return this.useAsArgument(expression.target.valueParameters[parameter.index])
|
||||
}
|
||||
|
||||
override fun IrExpression.useForField(field: PropertyDescriptor): IrExpression {
|
||||
return this.useForVariable(field.original)
|
||||
}
|
||||
|
||||
private fun IrExpression.adaptIfNecessary(actualType: KotlinType, expectedType: KotlinType): IrExpression {
|
||||
private fun IrExpression.adaptIfNecessary(actualType: IrType, expectedType: IrType): IrExpression {
|
||||
val conversion = symbols.getTypeConversion(actualType, expectedType)
|
||||
return if (conversion == null) {
|
||||
this
|
||||
} else {
|
||||
val parameter = conversion.descriptor.explicitParameters.single()
|
||||
val parameter = conversion.owner.explicitParameters.single()
|
||||
val argument = this.uncheckedCast(parameter.type)
|
||||
|
||||
IrCallImpl(startOffset, endOffset, conversion).apply {
|
||||
addArguments(listOf(parameter to argument))
|
||||
IrCallImpl(startOffset, endOffset, conversion.owner.returnType, conversion).apply {
|
||||
addArguments(mapOf(parameter to argument))
|
||||
}.uncheckedCast(this.type) // Try not to bring new type incompatibilities.
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
expression.transformChildrenVoid()
|
||||
assert(expression.getArgumentsWithIr().isEmpty())
|
||||
return expression
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts this expression to `type` without changing its representation in generated code.
|
||||
*/
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
private fun IrExpression.uncheckedCast(type: KotlinType): IrExpression {
|
||||
private fun IrExpression.uncheckedCast(type: IrType): IrExpression {
|
||||
// TODO: apply some cast if types are incompatible; not required currently.
|
||||
return this
|
||||
}
|
||||
|
||||
private val ValueType.shortName
|
||||
get() = this.classFqName.shortName()
|
||||
|
||||
private fun getBoxType(valueType: ValueType) =
|
||||
context.getInternalClass("${valueType.shortName}Box").defaultType
|
||||
private fun getBoxType(valueType: ValueType) = symbols.boxClasses[valueType]!!.owner.defaultType
|
||||
|
||||
}
|
||||
|
||||
+35
-20
@@ -23,26 +23,27 @@ import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isNullableAny
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
internal class WorkersBridgesBuilding(val context: Context) : DeclarationContainerLoweringPass, IrElementTransformerVoid() {
|
||||
|
||||
@@ -100,7 +101,16 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
runtimeJobDescriptor
|
||||
).also {
|
||||
it.createParameterDeclarations()
|
||||
it.returnType = context.irBuiltIns.anyNType
|
||||
|
||||
it.valueParameters += IrValueParameterImpl(
|
||||
it.startOffset,
|
||||
it.endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
it.descriptor.valueParameters.single(),
|
||||
context.irBuiltIns.anyNType,
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
val overriddenJobDescriptor = OverriddenFunctionDescriptor(jobFunction, runtimeJobFunction)
|
||||
@@ -118,7 +128,7 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
|
||||
type = job.type,
|
||||
symbol = bridge.symbol,
|
||||
descriptor = bridge.descriptor,
|
||||
typeArguments = null)
|
||||
typeArgumentsCount = 0)
|
||||
)
|
||||
return expression
|
||||
}
|
||||
@@ -158,7 +168,7 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||
|
||||
val irBuilder = context.createIrBuilder(declaration.symbol, declaration.startOffset, declaration.endOffset)
|
||||
declaration.body = irBuilder.irBlockBody(declaration) {
|
||||
buildTypeSafeBarrier(declaration, descriptor, typeSafeBarrierDescription)
|
||||
buildTypeSafeBarrier(declaration, declaration, typeSafeBarrierDescription)
|
||||
body.statements.forEach { +it }
|
||||
}
|
||||
return declaration
|
||||
@@ -187,7 +197,7 @@ internal val IrFunction.bridgeTarget: IrFunction?
|
||||
get() = (origin as? DECLARATION_ORIGIN_BRIDGE_METHOD)?.bridgeTarget
|
||||
|
||||
private fun IrBuilderWithScope.returnIfBadType(value: IrExpression,
|
||||
type: KotlinType,
|
||||
type: IrType,
|
||||
returnValueOnFail: IrExpression)
|
||||
= irIfThen(irNotIs(value, type), irReturn(returnValueOnFail))
|
||||
|
||||
@@ -199,18 +209,18 @@ private fun IrBuilderWithScope.irConst(value: Any?) = when (value) {
|
||||
}
|
||||
|
||||
private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction,
|
||||
originalDescriptor: FunctionDescriptor,
|
||||
originalFunction: IrFunction,
|
||||
typeSafeBarrierDescription: BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription) {
|
||||
val valueParameters = function.valueParameters
|
||||
val originalValueParameters = originalDescriptor.valueParameters
|
||||
val originalValueParameters = originalFunction.valueParameters
|
||||
for (i in valueParameters.indices) {
|
||||
if (!typeSafeBarrierDescription.checkParameter(i))
|
||||
continue
|
||||
val type = originalValueParameters[i].type
|
||||
if (type != context.builtIns.nullableAnyType) {
|
||||
+returnIfBadType(irGet(valueParameters[i].symbol), type,
|
||||
if (!type.isNullableAny()) {
|
||||
+returnIfBadType(irGet(valueParameters[i]), type,
|
||||
if (typeSafeBarrierDescription == BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT)
|
||||
irGet(valueParameters[2].symbol)
|
||||
irGet(valueParameters[2])
|
||||
else irConst(typeSafeBarrierDescription.defaultValue)
|
||||
)
|
||||
}
|
||||
@@ -221,7 +231,7 @@ private fun Context.buildBridge(startOffset: Int, endOffset: Int,
|
||||
descriptor: OverriddenFunctionDescriptor, targetSymbol: IrFunctionSymbol,
|
||||
superQualifierSymbol: IrClassSymbol? = null): IrFunction {
|
||||
|
||||
val bridge = specialDeclarationsFactory.getBridgeDescriptor(descriptor)
|
||||
val bridge = specialDeclarationsFactory.getBridge(descriptor)
|
||||
|
||||
if (bridge.modality == Modality.ABSTRACT) {
|
||||
return bridge
|
||||
@@ -230,23 +240,28 @@ private fun Context.buildBridge(startOffset: Int, endOffset: Int,
|
||||
val irBuilder = createIrBuilder(bridge.symbol, startOffset, endOffset)
|
||||
bridge.body = irBuilder.irBlockBody(bridge) {
|
||||
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor.descriptor)
|
||||
typeSafeBarrierDescription?.let { buildTypeSafeBarrier(bridge, descriptor.descriptor.descriptor, it) }
|
||||
typeSafeBarrierDescription?.let { buildTypeSafeBarrier(bridge, descriptor.descriptor, it) }
|
||||
|
||||
val delegatingCall = IrCallImpl(startOffset, endOffset, targetSymbol, targetSymbol.descriptor,
|
||||
val delegatingCall = IrCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
(targetSymbol.owner as IrFunction).returnType,
|
||||
targetSymbol,
|
||||
targetSymbol.descriptor,
|
||||
superQualifierSymbol = superQualifierSymbol /* Call non-virtually */
|
||||
).apply {
|
||||
bridge.dispatchReceiverParameter?.let {
|
||||
dispatchReceiver = irGet(it.symbol)
|
||||
dispatchReceiver = irGet(it)
|
||||
}
|
||||
bridge.extensionReceiverParameter?.let {
|
||||
extensionReceiver = irGet(it.symbol)
|
||||
extensionReceiver = irGet(it)
|
||||
}
|
||||
bridge.valueParameters.forEachIndexed { index, parameter ->
|
||||
this.putValueArgument(index, irGet(parameter.symbol))
|
||||
this.putValueArgument(index, irGet(parameter))
|
||||
}
|
||||
}
|
||||
|
||||
if (KotlinBuiltIns.isUnitOrNullableUnit(bridge.returnType))
|
||||
if (bridge.returnType.isUnit())
|
||||
+delegatingCall
|
||||
else
|
||||
+irReturn(delegatingCall)
|
||||
|
||||
+22
-18
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
|
||||
import org.jetbrains.kotlin.backend.common.lower.at
|
||||
import org.jetbrains.kotlin.backend.common.lower.irNot
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.containsNull
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isSubtypeOf
|
||||
import org.jetbrains.kotlin.backend.konan.isValueType
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
@@ -33,13 +35,13 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.makeNullable
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.ir.builders.irGet
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isNothing
|
||||
import org.jetbrains.kotlin.ir.util.isNullConst
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.isNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
|
||||
/**
|
||||
* This lowering pass lowers some calls to [IrBuiltinOperatorDescriptor]s.
|
||||
@@ -82,9 +84,11 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
||||
irBuiltins.eqeqeq -> lowerEqeqeq(expression)
|
||||
|
||||
irBuiltins.throwNpe -> IrCallImpl(expression.startOffset, expression.endOffset,
|
||||
context.ir.symbols.ThrowNullPointerException.owner.returnType,
|
||||
context.ir.symbols.ThrowNullPointerException)
|
||||
|
||||
irBuiltins.noWhenBranchMatchedException -> IrCallImpl(expression.startOffset, expression.endOffset,
|
||||
context.ir.symbols.ThrowNoWhenBranchMatchedException.owner.returnType,
|
||||
context.ir.symbols.ThrowNoWhenBranchMatchedException)
|
||||
|
||||
else -> expression
|
||||
@@ -148,8 +152,8 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
||||
putValueArgument(0, rhs)
|
||||
}
|
||||
|
||||
val lhsIsNotNullable = !lhs.type.isNullable()
|
||||
val rhsIsNotNullable = !rhs.type.isNullable()
|
||||
val lhsIsNotNullable = !lhs.type.containsNull()
|
||||
val rhsIsNotNullable = !rhs.type.containsNull()
|
||||
|
||||
return if (expression.descriptor in ieee754EqualsDescriptors()) {
|
||||
if (lhsIsNotNullable && rhsIsNotNullable)
|
||||
@@ -159,15 +163,15 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
||||
val rhsTemp = irTemporary(rhs)
|
||||
if (lhsIsNotNullable xor rhsIsNotNullable) { // Exactly one nullable.
|
||||
+irLogicalAnd(
|
||||
irIsNotNull(irGet((if (lhsIsNotNullable) rhsTemp else lhsTemp).symbol)),
|
||||
callEquals(irGet(lhsTemp.symbol), irGet(rhsTemp.symbol))
|
||||
irIsNotNull(irGet(if (lhsIsNotNullable) rhsTemp else lhsTemp)),
|
||||
callEquals(irGet(lhsTemp), irGet(rhsTemp))
|
||||
)
|
||||
} else { // Both are nullable.
|
||||
+irIfThenElse(builtIns.booleanType, irIsNull(irGet(lhsTemp.symbol)),
|
||||
irIsNull(irGet(rhsTemp.symbol)),
|
||||
+irIfThenElse(context.irBuiltIns.booleanType, irIsNull(irGet(lhsTemp)),
|
||||
irIsNull(irGet(rhsTemp)),
|
||||
irLogicalAnd(
|
||||
irIsNotNull(irGet(rhsTemp.symbol)),
|
||||
callEquals(irGet(lhsTemp.symbol), irGet(rhsTemp.symbol))
|
||||
irIsNotNull(irGet(rhsTemp)),
|
||||
callEquals(irGet(lhsTemp), irGet(rhsTemp))
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -179,12 +183,12 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
||||
irBlock {
|
||||
val lhsTemp = irTemporary(lhs)
|
||||
if (rhsIsNotNullable)
|
||||
+irLogicalAnd(irIsNotNull(irGet(lhsTemp.symbol)), callEquals(irGet(lhsTemp.symbol), rhs))
|
||||
+irLogicalAnd(irIsNotNull(irGet(lhsTemp)), callEquals(irGet(lhsTemp), rhs))
|
||||
else {
|
||||
val rhsTemp = irTemporary(rhs)
|
||||
+irIfThenElse(builtIns.booleanType, irIsNull(irGet(lhsTemp.symbol)),
|
||||
irIsNull(irGet(rhsTemp.symbol)),
|
||||
callEquals(irGet(lhsTemp.symbol), irGet(rhsTemp.symbol))
|
||||
+irIfThenElse(irBuiltins.booleanType, irIsNull(irGet(lhsTemp)),
|
||||
irIsNull(irGet(rhsTemp)),
|
||||
callEquals(irGet(lhsTemp), irGet(rhsTemp))
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -193,7 +197,7 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectIntrinsic(from: List<IrSimpleFunctionSymbol>, lhsType: KotlinType, rhsType: KotlinType, allowNullable: Boolean) =
|
||||
private fun selectIntrinsic(from: List<IrSimpleFunctionSymbol>, lhsType: IrType, rhsType: IrType, allowNullable: Boolean) =
|
||||
from.atMostOne {
|
||||
val leftParamType = it.owner.valueParameters[0].type
|
||||
val rightParamType = it.owner.valueParameters[1].type
|
||||
|
||||
+85
-70
@@ -18,16 +18,14 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.getFunction
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.isFunctionOrKFunctionType
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.replace
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
import org.jetbrains.kotlin.backend.common.push
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isFunctionOrKFunctionType
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
@@ -47,19 +45,20 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
internal class CallableReferenceLowering(val context: Context): FileLoweringPass {
|
||||
|
||||
@@ -161,15 +160,16 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
val parent: IrDeclarationParent,
|
||||
val functionReference: IrFunctionReference) {
|
||||
|
||||
private val functionDescriptor = functionReference.descriptor
|
||||
private val functionParameters = functionDescriptor.explicitParameters
|
||||
private val boundFunctionParameters = functionReference.getArguments().map { it.first }
|
||||
private val functionDescriptor = functionReference.descriptor.original
|
||||
private val irFunction = functionReference.symbol.owner
|
||||
private val functionParameters = irFunction.explicitParameters
|
||||
private val boundFunctionParameters = functionReference.getArgumentsWithIr().map { it.first }
|
||||
private val unboundFunctionParameters = functionParameters - boundFunctionParameters
|
||||
|
||||
private lateinit var functionReferenceClassDescriptor: ClassDescriptorImpl
|
||||
private lateinit var functionReferenceClass: IrClassImpl
|
||||
private lateinit var functionReferenceThis: IrValueParameterSymbol
|
||||
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrFieldSymbol>
|
||||
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrField>
|
||||
|
||||
private val kFunctionImplSymbol = context.ir.symbols.kFunctionImpl
|
||||
|
||||
@@ -177,29 +177,26 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
val startOffset = functionReference.startOffset
|
||||
val endOffset = functionReference.endOffset
|
||||
|
||||
val returnType = functionDescriptor.returnType!!
|
||||
val superTypes = mutableListOf(
|
||||
kFunctionImplSymbol.owner.defaultType.replace(listOf(returnType))
|
||||
)
|
||||
val superClasses = mutableListOf(kFunctionImplSymbol.owner)
|
||||
val returnType = irFunction.returnType
|
||||
val superTypes = mutableListOf(kFunctionImplSymbol.typeWith(returnType))
|
||||
|
||||
val numberOfParameters = unboundFunctionParameters.size
|
||||
val functionClassDescriptor = context.reflectionTypes.getKFunction(numberOfParameters)
|
||||
|
||||
val functionIrClass = context.ir.symbols.kFunctions[numberOfParameters].owner
|
||||
val functionParameterTypes = unboundFunctionParameters.map { it.type }
|
||||
val functionClassTypeParameters = functionParameterTypes + returnType
|
||||
superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeParameters)
|
||||
superClasses += context.ir.symbols.kFunctions[numberOfParameters].owner
|
||||
superTypes += functionIrClass.symbol.typeWith(functionClassTypeParameters)
|
||||
|
||||
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
||||
var suspendFunctionClassTypeParameters: List<KotlinType>? = null
|
||||
var suspendFunctionIrClass: IrClass? = null
|
||||
var suspendFunctionClassTypeParameters: List<IrType>? = null
|
||||
val lastParameterType = unboundFunctionParameters.lastOrNull()?.type
|
||||
if (lastParameterType != null && TypeUtils.getClassDescriptor(lastParameterType) == continuationClassDescriptor) {
|
||||
if (lastParameterType != null && lastParameterType.classifierOrNull?.descriptor == continuationClassDescriptor) {
|
||||
lastParameterType as IrSimpleType
|
||||
// If the last parameter is Continuation<> inherit from SuspendFunction.
|
||||
suspendFunctionClassDescriptor = kotlinPackageScope.getContributedClassifier(
|
||||
Name.identifier("SuspendFunction${numberOfParameters - 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
||||
suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) + lastParameterType.arguments.single().type
|
||||
superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeParameters)
|
||||
superClasses += context.ir.symbols.suspendFunctions[numberOfParameters - 1].owner
|
||||
suspendFunctionIrClass = context.ir.symbols.suspendFunctions[numberOfParameters - 1].owner
|
||||
suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) +
|
||||
(lastParameterType.arguments.single().typeOrNull ?: context.irBuiltIns.anyNType)
|
||||
superTypes += suspendFunctionIrClass.symbol.typeWith(suspendFunctionClassTypeParameters)
|
||||
}
|
||||
|
||||
functionReferenceClassDescriptor = object : ClassDescriptorImpl(
|
||||
@@ -207,7 +204,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
/* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* kind = */ ClassKind.CLASS,
|
||||
/* superTypes = */ superTypes,
|
||||
/* superTypes = */ superTypes.map { it.toKotlinType() },
|
||||
/* source = */ SourceElement.NO_SOURCE,
|
||||
/* isExternal = */ false,
|
||||
/* storageManager = */ LockBasedStorageManager.NO_LOCKS
|
||||
@@ -225,13 +222,15 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
|
||||
val constructorBuilder = createConstructorBuilder()
|
||||
|
||||
val invokeFunctionDescriptor = functionClassDescriptor.getFunction("invoke", functionClassTypeParameters)
|
||||
val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionDescriptor)
|
||||
val invokeFunctionSymbol =
|
||||
functionIrClass.simpleFunctions().single { it.name.asString() == "invoke" }.symbol
|
||||
val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionSymbol, functionReferenceClass)
|
||||
|
||||
var suspendInvokeMethodBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>? = null
|
||||
if (suspendFunctionClassDescriptor != null) {
|
||||
val suspendInvokeFunctionDescriptor = suspendFunctionClassDescriptor.getFunction("invoke", suspendFunctionClassTypeParameters!!)
|
||||
suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionDescriptor)
|
||||
if (suspendFunctionIrClass != null) {
|
||||
val suspendInvokeFunctionSymbol =
|
||||
suspendFunctionIrClass.simpleFunctions().single { it.name.asString() == "invoke" }.symbol
|
||||
suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionSymbol, functionReferenceClass)
|
||||
}
|
||||
|
||||
val memberScope = stub<MemberScope>("callable reference class")
|
||||
@@ -253,7 +252,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
functionReferenceClass.addChild(it.ir)
|
||||
}
|
||||
|
||||
functionReferenceClass.setSuperSymbolsAndAddFakeOverrides(superClasses)
|
||||
functionReferenceClass.setSuperSymbolsAndAddFakeOverrides(superTypes)
|
||||
|
||||
return BuiltFunctionReference(functionReferenceClass, constructorBuilder.ir)
|
||||
}
|
||||
@@ -275,15 +274,19 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
override fun doInitialize() {
|
||||
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||
val constructorParameters = boundFunctionParameters.mapIndexed { index, parameter ->
|
||||
parameter.copyAsValueParameter(descriptor, index)
|
||||
parameter.descriptor.copyAsValueParameter(descriptor, index)
|
||||
}
|
||||
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
||||
descriptor.returnType = functionReferenceClassDescriptor.defaultType
|
||||
}
|
||||
|
||||
override fun buildIr(): IrConstructor {
|
||||
|
||||
val symbols = this@CallableReferenceLowering.context.ir.symbols
|
||||
val irBuiltIns = context.irBuiltIns
|
||||
|
||||
argumentToPropertiesMap = boundFunctionParameters.associate {
|
||||
it to buildPropertyWithBackingField(it.name, it.type, false)
|
||||
it.descriptor to buildField(it.name, it.type, false)
|
||||
}
|
||||
|
||||
val startOffset = functionReference.startOffset
|
||||
@@ -294,30 +297,36 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
symbol = symbol).apply {
|
||||
|
||||
returnType = functionReferenceClass.defaultType
|
||||
|
||||
val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset)
|
||||
|
||||
createParameterDeclarations()
|
||||
boundFunctionParameters.mapIndexedTo(this.valueParameters) { index, parameter ->
|
||||
parameter.copy(descriptor.valueParameters[index])
|
||||
}
|
||||
|
||||
body = irBuilder.irBlockBody {
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
kFunctionImplConstructorSymbol, kFunctionImplConstructorSymbol.descriptor).apply {
|
||||
val name = IrConstImpl(startOffset, endOffset, context.builtIns.stringType,
|
||||
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, context.builtIns.stringType, IrConstKind.String,
|
||||
val fqName = IrConstImpl(startOffset, endOffset, stringType, IrConstKind.String,
|
||||
(functionReference.symbol.owner).fullName)
|
||||
putValueArgument(1, fqName)
|
||||
val bound = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType,
|
||||
val bound = IrConstImpl.boolean(startOffset, endOffset, context.irBuiltIns.booleanType,
|
||||
boundFunctionParameters.isNotEmpty())
|
||||
putValueArgument(2, bound)
|
||||
val needReceiver = boundFunctionParameters.singleOrNull() is ReceiverParameterDescriptor
|
||||
val receiver = if (needReceiver) irGet(valueParameters.single().symbol) else irNull()
|
||||
val needReceiver = boundFunctionParameters.singleOrNull()?.descriptor is ReceiverParameterDescriptor
|
||||
val receiver = if (needReceiver) irGet(valueParameters.single()) else irNull()
|
||||
putValueArgument(3, receiver)
|
||||
}
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol)
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, irBuiltIns.unitType)
|
||||
// Save all arguments to fields.
|
||||
boundFunctionParameters.forEachIndexed { index, parameter ->
|
||||
+irSetField(irGet(functionReferenceThis), argumentToPropertiesMap[parameter]!!, irGet(valueParameters[index].symbol))
|
||||
+irSetField(irGet(functionReferenceThis.owner), argumentToPropertiesMap[parameter.descriptor]!!, irGet(valueParameters[index]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,9 +336,11 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
private val IrFunction.fullName: String
|
||||
get() = parent.fqNameSafe.child(Name.identifier(functionName)).asString()
|
||||
|
||||
private fun createInvokeMethodBuilder(superFunctionDescriptor: FunctionDescriptor)
|
||||
private fun createInvokeMethodBuilder(superFunctionSymbol: IrSimpleFunctionSymbol, parent: IrClass)
|
||||
= object : SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||
|
||||
val superFunctionDescriptor: FunctionDescriptor = superFunctionSymbol.descriptor
|
||||
|
||||
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||
SimpleFunctionDescriptorImpl.create(
|
||||
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||
@@ -368,10 +379,18 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
symbol = ourSymbol).apply {
|
||||
|
||||
returnType = superFunctionSymbol.owner.returnType // FIXME: substitute
|
||||
|
||||
val function = this
|
||||
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
||||
|
||||
createParameterDeclarations()
|
||||
this.parent = parent
|
||||
|
||||
this.createDispatchReceiverParameter()
|
||||
|
||||
superFunctionSymbol.owner.valueParameters.mapTo(this.valueParameters) {
|
||||
it.copy(descriptor.valueParameters[it.index]) // FIXME: substitute
|
||||
}
|
||||
|
||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||
+irReturn(
|
||||
@@ -383,21 +402,21 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
if (!unboundArgsSet.contains(it))
|
||||
// Bound parameter - read from field.
|
||||
irGetField(
|
||||
irGet(function.dispatchReceiverParameter!!.symbol),
|
||||
argumentToPropertiesMap[it]!!
|
||||
irGet(function.dispatchReceiverParameter!!),
|
||||
argumentToPropertiesMap[it.descriptor]!!
|
||||
)
|
||||
else {
|
||||
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
|
||||
// For suspend functions the last argument is continuation and it is implicit.
|
||||
irCall(getContinuationSymbol,
|
||||
listOf(ourSymbol.descriptor.returnType!!))
|
||||
irCall(getContinuationSymbol.owner,
|
||||
listOf(returnType))
|
||||
else
|
||||
irGet(valueParameters[unboundIndex++].symbol)
|
||||
irGet(valueParameters[unboundIndex++])
|
||||
}
|
||||
when (it) {
|
||||
functionDescriptor.dispatchReceiverParameter -> dispatchReceiver = argument
|
||||
functionDescriptor.extensionReceiverParameter -> extensionReceiver = argument
|
||||
else -> putValueArgument((it as ValueParameterDescriptor).index, argument)
|
||||
irFunction.dispatchReceiverParameter -> dispatchReceiver = argument
|
||||
irFunction.extensionReceiverParameter -> extensionReceiver = argument
|
||||
else -> putValueArgument(it.index, argument)
|
||||
}
|
||||
}
|
||||
assert(unboundIndex == valueParameters.size, { "Not all arguments of <invoke> are used" })
|
||||
@@ -408,21 +427,17 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildPropertyWithBackingField(name: Name, type: KotlinType, isMutable: Boolean): IrFieldSymbol {
|
||||
val propertyBuilder = context.createPropertyWithBackingFieldBuilder(
|
||||
startOffset = functionReference.startOffset,
|
||||
endOffset = functionReference.endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
owner = functionReferenceClassDescriptor,
|
||||
name = name,
|
||||
type = type,
|
||||
isMutable = isMutable).apply {
|
||||
initialize()
|
||||
}
|
||||
|
||||
functionReferenceClass.addChild(propertyBuilder.ir)
|
||||
return propertyBuilder.ir.backingField!!.symbol
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -4,10 +4,11 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
|
||||
import org.jetbrains.kotlin.backend.common.lower.at
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.types.isString
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
|
||||
@@ -29,14 +30,14 @@ internal class CompileTimeEvaluateLowering(val context: Context): FileLoweringPa
|
||||
// TODO: refer functions more reliably.
|
||||
|
||||
if (elementsArr.elements.any { it is IrSpreadElement }
|
||||
|| !elementsArr.elements.all { it is IrConst<*> && KotlinBuiltIns.isString(it.type) })
|
||||
|| !elementsArr.elements.all { it is IrConst<*> && it.type.isString() })
|
||||
return expression
|
||||
|
||||
|
||||
builder.at(expression)
|
||||
|
||||
val typeArguments = descriptor.typeParameters.map { expression.getTypeArgument(it)!! }
|
||||
return builder.irCall(context.ir.symbols.listOfInternal, typeArguments).apply {
|
||||
val typeArgument = expression.getTypeArgument(0)!!
|
||||
return builder.irCall(context.ir.symbols.listOfInternal.owner, listOf(typeArgument)).apply {
|
||||
putValueArgument(0, elementsArr)
|
||||
}
|
||||
}
|
||||
|
||||
+19
-22
@@ -20,15 +20,15 @@ import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
|
||||
internal class DataClassOperatorsLowering(val context: Context): FunctionLoweringPass {
|
||||
|
||||
@@ -45,40 +45,37 @@ internal class DataClassOperatorsLowering(val context: Context): FunctionLowerin
|
||||
return expression
|
||||
|
||||
val argument = expression.getValueArgument(0)!!
|
||||
val argumentType = argument.type.makeNotNullable()
|
||||
val genericType =
|
||||
if (argumentType.arguments.isEmpty())
|
||||
argumentType
|
||||
else
|
||||
(argumentType.constructor.declarationDescriptor as ClassDescriptor).defaultType
|
||||
val isToString = descriptor == irBuiltins.dataClassArrayMemberToString
|
||||
val newSymbol = if (isToString)
|
||||
context.ir.symbols.arrayContentToString[genericType]!!
|
||||
val argumentClassifier = argument.type.classifierOrFail
|
||||
|
||||
val isToString = expression.symbol == irBuiltins.dataClassArrayMemberToStringSymbol
|
||||
val newCalleeSymbol = if (isToString)
|
||||
context.ir.symbols.arrayContentToString[argumentClassifier]!!
|
||||
else
|
||||
context.ir.symbols.arrayContentHashCode[genericType]!!
|
||||
context.ir.symbols.arrayContentHashCode[argumentClassifier]!!
|
||||
|
||||
val newCallee = newCalleeSymbol.owner
|
||||
|
||||
val startOffset = expression.startOffset
|
||||
val endOffset = expression.endOffset
|
||||
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
||||
|
||||
return irBuilder.run {
|
||||
val typeArguments =
|
||||
if (argumentType.arguments.isEmpty())
|
||||
emptyList<KotlinType>()
|
||||
else argumentType.arguments.map { it.type }
|
||||
if (!argument.type.isMarkedNullable) {
|
||||
irCall(newSymbol, typeArguments).apply {
|
||||
// TODO: use more precise type arguments.
|
||||
val typeArguments = (0 until newCallee.typeParameters.size).map { irBuiltins.anyNType }
|
||||
|
||||
if (!argument.type.isSimpleTypeWithQuestionMark) {
|
||||
irCall(newCallee, typeArguments).apply {
|
||||
extensionReceiver = argument
|
||||
}
|
||||
} else {
|
||||
val tmp = scope.createTemporaryVariable(argument)
|
||||
val call = irCall(newSymbol, typeArguments).apply {
|
||||
extensionReceiver = irGet(tmp.symbol)
|
||||
val call = irCall(newCallee, typeArguments).apply {
|
||||
extensionReceiver = irGet(tmp)
|
||||
}
|
||||
irBlock(argument) {
|
||||
+tmp
|
||||
+irIfThenElse(call.type,
|
||||
irEqeqeq(irGet(tmp.symbol), irNull()),
|
||||
irEqeqeq(irGet(tmp), irNull()),
|
||||
if (isToString)
|
||||
irString("null")
|
||||
else
|
||||
|
||||
+147
-24
@@ -24,14 +24,17 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.createClassSymbolOrNull
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.makeNullable
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
@@ -46,7 +49,6 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
|
||||
internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor,
|
||||
val parentDescriptor: DeclarationDescriptor,
|
||||
@@ -484,7 +486,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
return IrCallImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
type = newDescriptor.returnType!!,
|
||||
type = context.ir.translateErased(newDescriptor.returnType!!),
|
||||
descriptor = newDescriptor,
|
||||
typeArgumentsCount = expression.typeArgumentsCount,
|
||||
origin = expression.origin,
|
||||
@@ -497,19 +499,100 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
override fun visitFunction(declaration: IrFunction): IrFunction =
|
||||
IrFunctionImpl(
|
||||
startOffset = declaration.startOffset,
|
||||
endOffset = declaration.endOffset,
|
||||
origin = mapDeclarationOrigin(declaration.origin),
|
||||
descriptor = mapFunctionDeclaration(declaration.descriptor),
|
||||
body = declaration.body?.transform(this, null)
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction): IrFunction {
|
||||
val descriptor = mapFunctionDeclaration(declaration.descriptor)
|
||||
return IrFunctionImpl(
|
||||
startOffset = declaration.startOffset,
|
||||
endOffset = declaration.endOffset,
|
||||
origin = mapDeclarationOrigin(declaration.origin),
|
||||
descriptor = descriptor
|
||||
).also {
|
||||
it.returnType = context.ir.translateErased(descriptor.returnType!!)
|
||||
it.body = declaration.body?.transform(this, null)
|
||||
|
||||
it.setOverrides(context.ir.symbols.symbolTable)
|
||||
}.transformParameters(declaration)
|
||||
}.transformParameters1(declaration)
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor): IrConstructor {
|
||||
val descriptor = mapConstructorDeclaration(declaration.descriptor)
|
||||
return IrConstructorImpl(
|
||||
startOffset = declaration.startOffset,
|
||||
endOffset = declaration.endOffset,
|
||||
origin = mapDeclarationOrigin(declaration.origin),
|
||||
descriptor = descriptor
|
||||
).also {
|
||||
it.returnType = context.ir.translateErased(descriptor.returnType)
|
||||
it.body = declaration.body?.transform(this, null)
|
||||
}.transformParameters1(declaration)
|
||||
}
|
||||
|
||||
private fun FunctionDescriptor.getTypeParametersToTransform() =
|
||||
when {
|
||||
this is PropertyAccessorDescriptor -> correspondingProperty.typeParameters
|
||||
else -> typeParameters
|
||||
}
|
||||
|
||||
protected fun <T : IrFunction> T.transformParameters1(original: T): T =
|
||||
apply {
|
||||
transformTypeParameters(original, descriptor.getTypeParametersToTransform())
|
||||
transformValueParameters1(original)
|
||||
}
|
||||
|
||||
protected fun <T : IrFunction> T.transformValueParameters1(original: T) =
|
||||
apply {
|
||||
dispatchReceiverParameter =
|
||||
original.dispatchReceiverParameter?.replaceDescriptor1(
|
||||
descriptor.dispatchReceiverParameter ?: throw AssertionError("No dispatch receiver in $descriptor")
|
||||
)
|
||||
|
||||
extensionReceiverParameter =
|
||||
original.extensionReceiverParameter?.replaceDescriptor1(
|
||||
descriptor.extensionReceiverParameter ?: throw AssertionError("No extension receiver in $descriptor")
|
||||
)
|
||||
|
||||
original.valueParameters.mapIndexedTo(valueParameters) { i, originalValueParameter ->
|
||||
originalValueParameter.replaceDescriptor1(descriptor.valueParameters[i])
|
||||
}
|
||||
}
|
||||
|
||||
protected fun IrValueParameter.replaceDescriptor1(newDescriptor: ParameterDescriptor) =
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset,
|
||||
mapDeclarationOrigin(origin),
|
||||
newDescriptor,
|
||||
context.ir.translateErased(newDescriptor.type),
|
||||
(newDescriptor as? ValueParameterDescriptor)?.varargElementType?.let { context.ir.translateErased(it) },
|
||||
defaultValue?.transform(this@InlineCopyIr, null)
|
||||
).apply {
|
||||
transformAnnotations(this)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrGetValue {
|
||||
val descriptor = mapValueReference(expression.descriptor)
|
||||
return IrGetValueImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
context.ir.translateErased(descriptor.type),
|
||||
descriptor,
|
||||
mapStatementOrigin(expression.origin)
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitVariable(declaration: IrVariable): IrVariable {
|
||||
val descriptor = mapVariableDeclaration(declaration.descriptor)
|
||||
return IrVariableImpl(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
mapDeclarationOrigin(declaration.origin),
|
||||
descriptor,
|
||||
context.ir.translateErased(descriptor.type),
|
||||
declaration.initializer?.transform(this, null)
|
||||
).apply {
|
||||
transformAnnotations(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : IrFunction> T.transformDefaults(original: T): T {
|
||||
for (originalValueParameter in original.descriptor.valueParameters) {
|
||||
val valueParameter = descriptor.valueParameters[originalValueParameter.index]
|
||||
@@ -522,7 +605,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
fun getTypeOperatorReturnType(operator: IrTypeOperator, type: KotlinType) : KotlinType {
|
||||
fun getTypeOperatorReturnType(operator: IrTypeOperator, type: IrType) : IrType {
|
||||
return when (operator) {
|
||||
IrTypeOperator.CAST,
|
||||
IrTypeOperator.IMPLICIT_CAST,
|
||||
@@ -531,22 +614,24 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type
|
||||
IrTypeOperator.SAFE_CAST -> type.makeNullable()
|
||||
IrTypeOperator.INSTANCEOF,
|
||||
IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType
|
||||
IrTypeOperator.NOT_INSTANCEOF -> context.irBuiltIns.booleanType
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrTypeOperatorCall {
|
||||
val typeOperand = substituteType(expression.typeOperand)!!
|
||||
val returnType = getTypeOperatorReturnType(expression.operator, typeOperand)
|
||||
val erasedTypeOperand = substituteAndEraseType(expression.typeOperand)!!
|
||||
val typeOperand = substituteAndBreakType(expression.typeOperand)
|
||||
val returnType = getTypeOperatorReturnType(expression.operator, erasedTypeOperand)
|
||||
return IrTypeOperatorCallImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
type = returnType,
|
||||
operator = expression.operator,
|
||||
typeOperand = typeOperand,
|
||||
argument = expression.argument.transform(this, null)
|
||||
argument = expression.argument.transform(this, null),
|
||||
typeOperandClassifier = (typeOperand as IrSimpleType).classifier
|
||||
)
|
||||
}
|
||||
|
||||
@@ -556,7 +641,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
IrReturnImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
type = substituteType(expression.type)!!,
|
||||
type = substituteAndEraseType(expression.type)!!,
|
||||
returnTargetDescriptor = mapReturnTarget(expression.returnTarget),
|
||||
value = expression.value.transform(this, null)
|
||||
)
|
||||
@@ -577,7 +662,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
} else {
|
||||
IrBlockImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
substituteType(expression.type)!!,
|
||||
substituteAndEraseType(expression.type)!!,
|
||||
mapStatementOrigin(expression.origin),
|
||||
expression.statements.map { it.transform(this, null) }
|
||||
)
|
||||
@@ -587,7 +672,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override fun visitClassReference(expression: IrClassReference): IrClassReference {
|
||||
val newExpressionType = substituteType(expression.type)!! // Substituted expression type.
|
||||
val newExpressionType = substituteAndEraseType(expression.type)!! // Substituted expression type.
|
||||
val newDescriptorType = substituteType(expression.descriptor.defaultType)!! // Substituted type of referenced class.
|
||||
val classDescriptor = newDescriptorType.constructor.declarationDescriptor!! // Get ClassifierDescriptor of the referenced class.
|
||||
return IrClassReferenceImpl(
|
||||
@@ -602,7 +687,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override fun visitGetClass(expression: IrGetClass): IrGetClass {
|
||||
val type = substituteType(expression.type)!!
|
||||
val type = substituteAndEraseType(expression.type)!!
|
||||
return IrGetClassImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
@@ -616,6 +701,27 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
|
||||
return irLoop
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrClass {
|
||||
val descriptor = this.mapClassDeclaration(declaration.descriptor)
|
||||
|
||||
return context.ir.symbols.symbolTable.declareClass(
|
||||
declaration.startOffset, declaration.endOffset, mapDeclarationOrigin(declaration.origin),
|
||||
descriptor
|
||||
).apply {
|
||||
declaration.declarations.mapTo(this.declarations) {
|
||||
it.transform(this@InlineCopyIr, null) as IrDeclaration
|
||||
}
|
||||
this.transformAnnotations(declaration)
|
||||
this.thisReceiver = declaration.thisReceiver?.replaceDescriptor1(this.descriptor.thisAsReceiverParameter)
|
||||
|
||||
this.transformTypeParameters(declaration, this.descriptor.declaredTypeParameters)
|
||||
|
||||
descriptor.defaultType.constructor.supertypes.mapTo(this.superTypes) {
|
||||
context.ir.translateErased(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -627,12 +733,24 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
return descriptorSubstituteMap[oldClassDescriptor]?.let { (it as ClassDescriptor).defaultType } ?: substitutedType
|
||||
}
|
||||
|
||||
private fun substituteAndEraseType(oldType: IrType?): IrType? {
|
||||
oldType ?: return null
|
||||
|
||||
val substitutedKotlinType = substituteType(oldType.toKotlinType())
|
||||
?: return oldType
|
||||
return context.ir.translateErased(substitutedKotlinType)
|
||||
}
|
||||
|
||||
private fun substituteAndBreakType(oldType: IrType): IrType {
|
||||
return context.ir.translateBroken(substituteType(oldType.toKotlinType())!!)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun IrMemberAccessExpression.substituteTypeArguments(original: IrMemberAccessExpression) {
|
||||
for (index in 0 until original.typeArgumentsCount) {
|
||||
val originalTypeArgument = original.getTypeArgument(index)
|
||||
val newTypeArgument = substituteType(originalTypeArgument)!!
|
||||
val newTypeArgument = substituteAndBreakType(originalTypeArgument!!)
|
||||
this.putTypeArgument(index, newTypeArgument)
|
||||
}
|
||||
}
|
||||
@@ -649,7 +767,10 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
|
||||
class SubstitutedDescriptor(val inlinedFunction: FunctionDescriptor, val descriptor: DeclarationDescriptor)
|
||||
|
||||
class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>)
|
||||
internal class DescriptorSubstitutorForExternalScope(
|
||||
val globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>,
|
||||
val context: Context
|
||||
)
|
||||
: IrElementTransformerVoidWithContext() {
|
||||
|
||||
private val variableSubstituteMap = mutableMapOf<VariableDescriptor, VariableDescriptor>()
|
||||
@@ -710,6 +831,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
|
||||
endOffset = declaration.endOffset,
|
||||
origin = declaration.origin,
|
||||
descriptor = newDescriptor,
|
||||
type = context.ir.translateErased(newDescriptor.type),
|
||||
initializer = declaration.initializer
|
||||
)
|
||||
}
|
||||
@@ -725,6 +847,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
|
||||
return IrGetValueImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
type = context.ir.translateErased(newDescriptor.type),
|
||||
origin = expression.origin,
|
||||
symbol = createValueSymbol(newDescriptor)
|
||||
)
|
||||
@@ -743,7 +866,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
|
||||
return IrCallImpl(
|
||||
startOffset = oldExpression.startOffset,
|
||||
endOffset = oldExpression.endOffset,
|
||||
type = newDescriptor.returnType!!,
|
||||
type = context.ir.translateErased(newDescriptor.returnType!!),
|
||||
symbol = createFunctionSymbol(newDescriptor),
|
||||
descriptor = newDescriptor,
|
||||
typeArgumentsCount = oldExpression.typeArgumentsCount,
|
||||
|
||||
-471
@@ -1,471 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
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.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
|
||||
open class DefaultArgumentStubGenerator constructor(val context: CommonBackendContext): DeclarationContainerLoweringPass {
|
||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||
irDeclarationContainer.declarations.transformFlat { memberDeclaration ->
|
||||
if (memberDeclaration is IrFunction)
|
||||
lower(memberDeclaration).also { functions ->
|
||||
functions.forEach {
|
||||
it.parent = irDeclarationContainer
|
||||
}
|
||||
}
|
||||
else
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val symbols = context.ir.symbols
|
||||
|
||||
private fun lower(irFunction: IrFunction): List<IrFunction> {
|
||||
val functionDescriptor = irFunction.descriptor
|
||||
|
||||
if (!functionDescriptor.needsDefaultArgumentsLowering)
|
||||
return listOf(irFunction)
|
||||
|
||||
val bodies = functionDescriptor.valueParameters
|
||||
.mapNotNull{irFunction.getDefault(it)}
|
||||
|
||||
|
||||
log { "detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions" }
|
||||
functionDescriptor.overriddenDescriptors.forEach { context.log{"DEFAULT-REPLACER: $it"} }
|
||||
if (bodies.isNotEmpty()) {
|
||||
val newIrFunction = functionDescriptor.generateDefaultsFunction(context)
|
||||
newIrFunction.parent = irFunction.parent
|
||||
val descriptor = newIrFunction.descriptor
|
||||
log { "$functionDescriptor -> $descriptor" }
|
||||
val builder = context.createIrBuilder(newIrFunction.symbol)
|
||||
newIrFunction.body = builder.irBlockBody(newIrFunction) {
|
||||
val params = mutableListOf<IrVariableSymbol>()
|
||||
val variables = mutableMapOf<ValueDescriptor, IrValueSymbol>()
|
||||
|
||||
irFunction.dispatchReceiverParameter?.let {
|
||||
variables[it.descriptor] = newIrFunction.dispatchReceiverParameter!!.symbol
|
||||
}
|
||||
|
||||
if (descriptor.extensionReceiverParameter != null) {
|
||||
variables[functionDescriptor.extensionReceiverParameter!!] =
|
||||
newIrFunction.extensionReceiverParameter!!.symbol
|
||||
}
|
||||
|
||||
for (valueParameter in functionDescriptor.valueParameters) {
|
||||
val parameterSymbol = newIrFunction.valueParameters[valueParameter.index].symbol
|
||||
val temporaryVariableSymbol =
|
||||
IrVariableSymbolImpl(scope.createTemporaryVariableDescriptor(parameterSymbol.descriptor))
|
||||
params.add(temporaryVariableSymbol)
|
||||
variables.put(valueParameter, temporaryVariableSymbol)
|
||||
if (valueParameter.hasDefaultValue()) {
|
||||
val kIntAnd = symbols.intAnd
|
||||
val condition = irNotEquals(irCall(kIntAnd).apply {
|
||||
dispatchReceiver = irGet(maskParameterSymbol(newIrFunction, valueParameter.index / 32))
|
||||
putValueArgument(0, irInt(1 shl (valueParameter.index % 32)))
|
||||
}, irInt(0))
|
||||
val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter)
|
||||
|
||||
/* Use previously calculated values in next expression. */
|
||||
expressionBody.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
log { "GetValue: ${expression.descriptor}" }
|
||||
val valueSymbol = variables[expression.descriptor] ?: return expression
|
||||
return irGet(valueSymbol)
|
||||
}
|
||||
})
|
||||
val variableInitialization = irIfThenElse(
|
||||
type = temporaryVariableSymbol.descriptor.type,
|
||||
condition = condition,
|
||||
thenPart = expressionBody.expression,
|
||||
elsePart = irGet(parameterSymbol))
|
||||
+ scope.createTemporaryVariable(
|
||||
symbol = temporaryVariableSymbol,
|
||||
initializer = variableInitialization)
|
||||
/* Mapping calculated values with its origin variables. */
|
||||
} else {
|
||||
+ scope.createTemporaryVariable(
|
||||
symbol = temporaryVariableSymbol,
|
||||
initializer = irGet(parameterSymbol))
|
||||
}
|
||||
}
|
||||
if (irFunction is IrConstructor) {
|
||||
+ IrDelegatingConstructorCallImpl(
|
||||
startOffset = irFunction.startOffset,
|
||||
endOffset = irFunction.endOffset,
|
||||
symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor
|
||||
).apply {
|
||||
params.forEachIndexed { i, variable ->
|
||||
putValueArgument(i, irGet(variable))
|
||||
}
|
||||
if (functionDescriptor.dispatchReceiverParameter != null) {
|
||||
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
+irReturn(irCall(irFunction.symbol).apply {
|
||||
if (functionDescriptor.dispatchReceiverParameter != null) {
|
||||
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol)
|
||||
}
|
||||
if (functionDescriptor.extensionReceiverParameter != null) {
|
||||
extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!]!!)
|
||||
}
|
||||
params.forEachIndexed { i, variable ->
|
||||
putValueArgument(i, irGet(variable))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// Remove default argument initializers.
|
||||
irFunction.valueParameters.forEach {
|
||||
it.defaultValue = null
|
||||
}
|
||||
|
||||
return listOf(irFunction, newIrFunction)
|
||||
}
|
||||
return listOf(irFunction)
|
||||
}
|
||||
|
||||
|
||||
private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" }
|
||||
}
|
||||
|
||||
private fun Scope.createTemporaryVariableDescriptor(parameterDescriptor: ParameterDescriptor?): VariableDescriptor =
|
||||
IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration = this.scopeOwner,
|
||||
name = parameterDescriptor!!.name.asString().synthesizedName,
|
||||
outType = parameterDescriptor.type,
|
||||
isMutable = false)
|
||||
|
||||
private fun Scope.createTemporaryVariable(symbol: IrVariableSymbol, initializer: IrExpression) =
|
||||
IrVariableImpl(
|
||||
startOffset = initializer.startOffset,
|
||||
endOffset = initializer.endOffset,
|
||||
origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
|
||||
symbol = symbol).apply {
|
||||
|
||||
this.initializer = initializer
|
||||
}
|
||||
|
||||
private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor): IrExpressionBody {
|
||||
return irFunction.getDefault(valueParameter) ?: TODO("FIXME!!!")
|
||||
}
|
||||
|
||||
private fun maskParameterDescriptor(function: IrFunction, number: Int) =
|
||||
maskParameterSymbol(function, number).descriptor as ValueParameterDescriptor
|
||||
private fun maskParameterSymbol(function: IrFunction, number: Int) =
|
||||
function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }.symbol
|
||||
|
||||
private fun markerParameterDescriptor(descriptor: FunctionDescriptor) = descriptor.valueParameters.single { it.name == kConstructorMarkerName }
|
||||
|
||||
fun nullConst(expression: IrElement, type: KotlinType) = when {
|
||||
KotlinBuiltIns.isFloat(type) -> IrConstImpl.float (expression.startOffset, expression.endOffset, type, 0.0F)
|
||||
KotlinBuiltIns.isDouble(type) -> IrConstImpl.double (expression.startOffset, expression.endOffset, type, 0.0)
|
||||
KotlinBuiltIns.isBoolean(type) -> IrConstImpl.boolean (expression.startOffset, expression.endOffset, type, false)
|
||||
KotlinBuiltIns.isByte(type) -> IrConstImpl.byte (expression.startOffset, expression.endOffset, type, 0)
|
||||
KotlinBuiltIns.isChar(type) -> IrConstImpl.char (expression.startOffset, expression.endOffset, type, 0.toChar())
|
||||
KotlinBuiltIns.isShort(type) -> IrConstImpl.short (expression.startOffset, expression.endOffset, type, 0)
|
||||
KotlinBuiltIns.isInt(type) -> IrConstImpl.int (expression.startOffset, expression.endOffset, type, 0)
|
||||
KotlinBuiltIns.isLong(type) -> IrConstImpl.long (expression.startOffset, expression.endOffset, type, 0)
|
||||
else -> IrConstImpl.constNull (expression.startOffset, expression.endOffset, type.builtIns.nullableNothingType)
|
||||
}
|
||||
|
||||
class DefaultParameterInjector constructor(val context: CommonBackendContext): BodyLoweringPass {
|
||||
override fun lower(irBody: IrBody) {
|
||||
|
||||
irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||
super.visitDelegatingConstructorCall(expression)
|
||||
val descriptor = expression.descriptor
|
||||
if (!descriptor.needsDefaultArgumentsLowering)
|
||||
return expression
|
||||
val argumentsCount = argumentCount(expression)
|
||||
if (argumentsCount == descriptor.valueParameters.size)
|
||||
return expression
|
||||
val (symbolForCall, params) = parametersForCall(expression)
|
||||
return IrDelegatingConstructorCallImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
symbol = symbolForCall as IrConstructorSymbol,
|
||||
descriptor = symbolForCall.descriptor)
|
||||
.apply {
|
||||
params.forEach {
|
||||
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
|
||||
putValueArgument(it.first.index, it.second)
|
||||
}
|
||||
dispatchReceiver = expression.dispatchReceiver
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
super.visitCall(expression)
|
||||
val functionDescriptor = expression.descriptor
|
||||
|
||||
if (!functionDescriptor.needsDefaultArgumentsLowering)
|
||||
return expression
|
||||
|
||||
val argumentsCount = argumentCount(expression)
|
||||
if (argumentsCount == functionDescriptor.valueParameters.size)
|
||||
return expression
|
||||
val (symbol, params) = parametersForCall(expression)
|
||||
val descriptor = symbol.descriptor
|
||||
descriptor.typeParameters.forEach { log { "$descriptor [${it.index}]: $it" } }
|
||||
descriptor.original.typeParameters.forEach { log { "${descriptor.original}[${it.index}] : $it" } }
|
||||
return IrCallImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
symbol = symbol,
|
||||
descriptor = descriptor,
|
||||
typeArguments = expression.descriptor.typeParameters.map{it to (expression.getTypeArgument(it) ?: it.defaultType) }.toMap())
|
||||
.apply {
|
||||
params.forEach {
|
||||
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
|
||||
putValueArgument(it.first.index, it.second)
|
||||
}
|
||||
expression.extensionReceiver?.apply{
|
||||
extensionReceiver = expression.extensionReceiver
|
||||
}
|
||||
expression.dispatchReceiver?.apply {
|
||||
dispatchReceiver = expression.dispatchReceiver
|
||||
}
|
||||
log { "call::extension@: ${ir2string(expression.extensionReceiver)}" }
|
||||
log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" }
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? {
|
||||
if (!this.descriptor.needsDefaultArgumentsLowering) return null
|
||||
|
||||
if (this !is IrSimpleFunction) return this
|
||||
|
||||
this.overriddenSymbols.forEach {
|
||||
it.owner.findSuperMethodWithDefaultArguments()?.let { return it }
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
private fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<Pair<ValueParameterDescriptor, IrExpression?>>> {
|
||||
val descriptor = expression.descriptor
|
||||
val keyFunction = expression.symbol.owner.findSuperMethodWithDefaultArguments()!!
|
||||
val keyDescriptor = keyFunction.descriptor
|
||||
val realFunction = keyDescriptor.generateDefaultsFunction(context)
|
||||
realFunction.parent = keyFunction.parent
|
||||
val realDescriptor = realFunction.descriptor
|
||||
|
||||
log { "$descriptor -> $realDescriptor" }
|
||||
val maskValues = Array((descriptor.valueParameters.size + 31) / 32, { 0 })
|
||||
val params = mutableListOf<Pair<ValueParameterDescriptor, IrExpression?>>()
|
||||
params.addAll(descriptor.valueParameters.mapIndexed { i, _ ->
|
||||
val valueArgument = expression.getValueArgument(i)
|
||||
if (valueArgument == null) {
|
||||
val maskIndex = i / 32
|
||||
maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (i % 32))
|
||||
}
|
||||
val valueParameterDescriptor = realDescriptor.valueParameters[i]
|
||||
val defaultValueArgument = if (valueParameterDescriptor.isVararg) null else nullConst(expression, valueParameterDescriptor.type)
|
||||
valueParameterDescriptor to (valueArgument ?: defaultValueArgument)
|
||||
})
|
||||
maskValues.forEachIndexed { i, maskValue ->
|
||||
params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int(
|
||||
startOffset = irBody.startOffset,
|
||||
endOffset = irBody.endOffset,
|
||||
type = descriptor.builtIns.intType,
|
||||
value = maskValue)
|
||||
}
|
||||
if (expression.descriptor is ClassConstructorDescriptor) {
|
||||
val defaultArgumentMarker = context.ir.symbols.defaultConstructorMarker
|
||||
params += markerParameterDescriptor(realDescriptor) to IrGetObjectValueImpl(
|
||||
startOffset = irBody.startOffset,
|
||||
endOffset = irBody.endOffset,
|
||||
type = defaultArgumentMarker.owner.defaultType,
|
||||
symbol = defaultArgumentMarker)
|
||||
}
|
||||
else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
|
||||
params += realDescriptor.valueParameters.last() to
|
||||
IrConstImpl.constNull(irBody.startOffset, irBody.endOffset, context.builtIns.any.defaultType)
|
||||
}
|
||||
params.forEach {
|
||||
log { "descriptor::${realDescriptor.name.asString()}#${it.first.index}: ${it.first.name.asString()}" }
|
||||
}
|
||||
return Pair(realFunction.symbol, params)
|
||||
}
|
||||
|
||||
private fun argumentCount(expression: IrMemberAccessExpression) =
|
||||
expression.descriptor.valueParameters.count { expression.getValueArgument(it) != null }
|
||||
})
|
||||
}
|
||||
|
||||
private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" }
|
||||
}
|
||||
|
||||
private val CallableMemberDescriptor.needsDefaultArgumentsLowering
|
||||
get() = valueParameters.any { it.hasDefaultValue() } && !(this is FunctionDescriptor && isInline)
|
||||
|
||||
private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendContext): IrFunction {
|
||||
return context.ir.defaultParameterDeclarationsCache.getOrPut(this) {
|
||||
val descriptor = when (this) {
|
||||
is ClassConstructorDescriptor ->
|
||||
ClassConstructorDescriptorImpl.create(
|
||||
/* containingDeclaration = */ containingDeclaration,
|
||||
/* annotations = */ annotations,
|
||||
/* isPrimary = */ false,
|
||||
/* source = */ source)
|
||||
else -> {
|
||||
val name = Name.identifier("$name\$default")
|
||||
|
||||
SimpleFunctionDescriptorImpl.create(
|
||||
/* containingDeclaration = */ containingDeclaration,
|
||||
/* annotations = */ annotations,
|
||||
/* name = */ name,
|
||||
/* kind = */ CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
/* source = */ source)
|
||||
}
|
||||
}
|
||||
|
||||
val syntheticParameters = MutableList((valueParameters.size + 31) / 32) { i ->
|
||||
valueParameter(descriptor, valueParameters.size + i, parameterMaskName(i), descriptor.builtIns.intType)
|
||||
}
|
||||
if (this is ClassConstructorDescriptor) {
|
||||
syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1,
|
||||
kConstructorMarkerName,
|
||||
context.ir.symbols.defaultConstructorMarker.owner.defaultType)
|
||||
}
|
||||
else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
|
||||
syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1,
|
||||
"handler".synthesizedName,
|
||||
context.ir.symbols.any.owner.defaultType)
|
||||
}
|
||||
|
||||
descriptor.initialize(
|
||||
/* receiverParameterType = */ extensionReceiverParameter?.type,
|
||||
/* dispatchReceiverParameter = */ dispatchReceiverParameter,
|
||||
/* typeParameters = */ typeParameters.map {
|
||||
TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
/* containingDeclaration = */ descriptor,
|
||||
/* annotations = */ it.annotations,
|
||||
/* reified = */ it.isReified,
|
||||
/* variance = */ it.variance,
|
||||
/* name = */ it.name,
|
||||
/* index = */ it.index,
|
||||
/* source = */ it.source,
|
||||
/* reportCycleError = */ null,
|
||||
/* supertypeLoopsChecker = */ SupertypeLoopChecker.EMPTY
|
||||
).apply {
|
||||
it.upperBounds.forEach { addUpperBound(it) }
|
||||
setInitialized()
|
||||
}
|
||||
},
|
||||
/* unsubstitutedValueParameters = */ valueParameters.map {
|
||||
ValueParameterDescriptorImpl(
|
||||
containingDeclaration = descriptor,
|
||||
original = null, /* ValueParameterDescriptorImpl::copy do not save original. */
|
||||
index = it.index,
|
||||
annotations = it.annotations,
|
||||
name = it.name,
|
||||
outType = it.type,
|
||||
declaresDefaultValue = false,
|
||||
isCrossinline = it.isCrossinline,
|
||||
isNoinline = it.isNoinline,
|
||||
varargElementType = it.varargElementType,
|
||||
source = it.source)
|
||||
} + syntheticParameters,
|
||||
/* unsubstitutedReturnType = */ returnType,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ this.visibility)
|
||||
descriptor.isSuspend = this.isSuspend
|
||||
context.log{"adds to cache[$this] = $descriptor"}
|
||||
|
||||
val startOffset = this.startOffsetOrUndefined
|
||||
val endOffset = this.endOffsetOrUndefined
|
||||
|
||||
val result: IrFunction = when (descriptor) {
|
||||
is ClassConstructorDescriptor -> IrConstructorImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||
descriptor
|
||||
)
|
||||
|
||||
else -> IrFunctionImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||
descriptor
|
||||
)
|
||||
}
|
||||
|
||||
result.createParameterDeclarations()
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER :
|
||||
IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT")
|
||||
|
||||
private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: KotlinType): ValueParameterDescriptor {
|
||||
return ValueParameterDescriptorImpl(
|
||||
containingDeclaration = descriptor,
|
||||
original = null,
|
||||
index = index,
|
||||
annotations = Annotations.EMPTY,
|
||||
name = name,
|
||||
outType = type,
|
||||
declaresDefaultValue = false,
|
||||
isCrossinline = false,
|
||||
isNoinline = false,
|
||||
varargElementType = null,
|
||||
source = SourceElement.NO_SOURCE
|
||||
)
|
||||
}
|
||||
|
||||
internal val kConstructorMarkerName = "marker".synthesizedName
|
||||
|
||||
private fun parameterMaskName(number: Int) = "mask$number".synthesizedName
|
||||
+56
-56
@@ -16,15 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.initialize
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.ir.createArrayOfExpression
|
||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
@@ -35,15 +33,14 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrLocalDelegatedProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrLocalDelegatedPropertyReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.util.addChild
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.functions
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -55,10 +52,10 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
||||
private val reflectionTypes = context.reflectionTypes
|
||||
private var tempIndex = 0
|
||||
|
||||
private fun getKPropertyImplConstructor(receiverTypes: List<KotlinType>,
|
||||
returnType: KotlinType,
|
||||
private fun getKPropertyImplConstructor(receiverTypes: List<IrType>,
|
||||
returnType: IrType,
|
||||
isLocal: Boolean,
|
||||
isMutable: Boolean) : Pair<IrConstructorSymbol, Map<TypeParameterDescriptor, KotlinType>> {
|
||||
isMutable: Boolean) : Pair<IrConstructorSymbol, List<IrType>> {
|
||||
|
||||
val symbols = context.ir.symbols
|
||||
|
||||
@@ -87,10 +84,7 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
||||
}
|
||||
}
|
||||
|
||||
val typeParameters = classSymbol.descriptor.declaredTypeParameters
|
||||
val arguments = (receiverTypes + listOf(returnType))
|
||||
.mapIndexed { index, type -> typeParameters[index] to type }
|
||||
.toMap()
|
||||
|
||||
return classSymbol.constructors.single() to arguments
|
||||
}
|
||||
@@ -102,17 +96,21 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
||||
override fun lower(irFile: IrFile) {
|
||||
val kProperties = mutableMapOf<VariableDescriptorWithAccessors, Pair<IrExpression, Int>>()
|
||||
|
||||
val arrayClass = context.ir.symbols.array
|
||||
val arrayClass = context.ir.symbols.array.owner
|
||||
|
||||
val arrayItemGetter = arrayClass.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||
|
||||
val kPropertyImplType = reflectionTypes.kProperty1Impl.replace(context.builtIns.anyType, context.builtIns.anyType)
|
||||
val anyType = context.irBuiltIns.anyType
|
||||
val kPropertyImplType = context.ir.symbols.kProperty1Impl.typeWith(anyType, anyType)
|
||||
|
||||
val kPropertiesFieldType: IrType = context.ir.symbols.array.typeWith(kPropertyImplType)
|
||||
|
||||
val kPropertiesField = IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION,
|
||||
createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor,
|
||||
context.builtIns.array.replace(kPropertyImplType)
|
||||
)
|
||||
kPropertiesFieldType.toKotlinType()
|
||||
),
|
||||
kPropertiesFieldType
|
||||
)
|
||||
|
||||
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||
@@ -148,11 +146,9 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
||||
createKProperty(expression, this) to kProperties.size
|
||||
}
|
||||
|
||||
return irCall(arrayItemGetter, typeArguments = listOf(kPropertyImplType)).apply {
|
||||
dispatchReceiver =
|
||||
IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField.symbol)
|
||||
|
||||
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second))
|
||||
return irCall(arrayItemGetter).apply {
|
||||
dispatchReceiver = irGetField(null, kPropertiesField)
|
||||
putValueArgument(0, irInt(field.second))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,14 +169,16 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
||||
else { // Cache KProperties with no arguments.
|
||||
// TODO: what about `receiversCount == 1` case?
|
||||
val field = kProperties.getOrPut(propertyDescriptor) {
|
||||
createLocalKProperty(propertyDescriptor, this) to kProperties.size
|
||||
createLocalKProperty(
|
||||
propertyDescriptor,
|
||||
expression.getter.owner.returnType,
|
||||
this
|
||||
) to kProperties.size
|
||||
}
|
||||
|
||||
return irCall(arrayItemGetter, typeArguments = listOf(kPropertyImplType)).apply {
|
||||
dispatchReceiver =
|
||||
IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField.symbol)
|
||||
|
||||
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second))
|
||||
return irCall(arrayItemGetter).apply {
|
||||
dispatchReceiver = irGetField(null, kPropertiesField)
|
||||
putValueArgument(0, irInt(field.second))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,23 +201,23 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
||||
val startOffset = expression.startOffset
|
||||
val endOffset = expression.endOffset
|
||||
return irBuilder.irBlock(expression) {
|
||||
val receiverTypes = mutableListOf<KotlinType>()
|
||||
val receiverTypes = mutableListOf<IrType>()
|
||||
val dispatchReceiver = expression.dispatchReceiver.let {
|
||||
if (it == null)
|
||||
null
|
||||
else
|
||||
irTemporary(value = it, nameHint = "\$dispatchReceiver${tempIndex++}").symbol
|
||||
irTemporary(value = it, nameHint = "\$dispatchReceiver${tempIndex++}")
|
||||
}
|
||||
val extensionReceiver = expression.extensionReceiver.let {
|
||||
if (it == null)
|
||||
null
|
||||
else
|
||||
irTemporary(value = it, nameHint = "\$extensionReceiver${tempIndex++}").symbol
|
||||
irTemporary(value = it, nameHint = "\$extensionReceiver${tempIndex++}")
|
||||
}
|
||||
val propertyDescriptor = expression.descriptor
|
||||
val returnType = expression.getter?.owner?.returnType ?: expression.field!!.owner.type
|
||||
|
||||
val returnType = propertyDescriptor.type
|
||||
val getterCallableReference = propertyDescriptor.getter?.let { getter ->
|
||||
val getterCallableReference = expression.getter?.owner?.let { getter ->
|
||||
getter.extensionReceiverParameter.let {
|
||||
if (it != null && expression.extensionReceiver == null)
|
||||
receiverTypes.add(it.type)
|
||||
@@ -228,39 +226,37 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
||||
if (it != null && expression.dispatchReceiver == null)
|
||||
receiverTypes.add(it.type)
|
||||
}
|
||||
val getterKFunctionType = reflectionTypes.getKFunctionType(
|
||||
annotations = Annotations.EMPTY,
|
||||
receiverType = receiverTypes.firstOrNull(),
|
||||
parameterTypes = if (receiverTypes.size < 2) listOf() else listOf(receiverTypes[1]),
|
||||
returnType = returnType)
|
||||
val getterKFunctionType = this@PropertyDelegationLowering.context.ir.symbols.getKFunctionType(
|
||||
returnType,
|
||||
receiverTypes
|
||||
)
|
||||
IrFunctionReferenceImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = getterKFunctionType,
|
||||
symbol = expression.getter!!,
|
||||
descriptor = getter,
|
||||
typeArguments = null
|
||||
descriptor = getter.descriptor,
|
||||
typeArgumentsCount = 0
|
||||
).apply {
|
||||
this.dispatchReceiver = dispatchReceiver?.let { irGet(it) }
|
||||
this.extensionReceiver = extensionReceiver?.let { irGet(it) }
|
||||
}
|
||||
}
|
||||
|
||||
val setterCallableReference = propertyDescriptor.setter?.let {
|
||||
if (!isKMutablePropertyType(expression.type)) null
|
||||
val setterCallableReference = expression.setter?.owner?.let {
|
||||
if (!isKMutablePropertyType(expression.type.toKotlinType())) null
|
||||
else {
|
||||
val setterKFunctionType = reflectionTypes.getKFunctionType(
|
||||
annotations = Annotations.EMPTY,
|
||||
receiverType = receiverTypes.firstOrNull(),
|
||||
parameterTypes = if (receiverTypes.size < 2) listOf(returnType) else listOf(receiverTypes[1], returnType),
|
||||
returnType = context.builtIns.unitType)
|
||||
val setterKFunctionType = this@PropertyDelegationLowering.context.ir.symbols.getKFunctionType(
|
||||
context.irBuiltIns.unitType,
|
||||
receiverTypes + returnType
|
||||
)
|
||||
IrFunctionReferenceImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = setterKFunctionType,
|
||||
symbol = expression.setter!!,
|
||||
descriptor = it,
|
||||
typeArguments = null
|
||||
descriptor = it.descriptor,
|
||||
typeArgumentsCount = 0
|
||||
).apply {
|
||||
this.dispatchReceiver = dispatchReceiver?.let { irGet(it) }
|
||||
this.extensionReceiver = extensionReceiver?.let { irGet(it) }
|
||||
@@ -273,7 +269,7 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
||||
returnType = returnType,
|
||||
isLocal = false,
|
||||
isMutable = setterCallableReference != null)
|
||||
val initializer = irCall(symbol, constructorTypeArguments).apply {
|
||||
val initializer = irCall(symbol.owner, constructorTypeArguments).apply {
|
||||
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
||||
if (getterCallableReference != null)
|
||||
putValueArgument(1, getterCallableReference)
|
||||
@@ -285,16 +281,15 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
||||
}
|
||||
|
||||
private fun createLocalKProperty(propertyDescriptor: VariableDescriptorWithAccessors,
|
||||
propertyType: IrType,
|
||||
irBuilder: IrBuilderWithScope): IrExpression {
|
||||
irBuilder.run {
|
||||
val returnType = propertyDescriptor.type
|
||||
|
||||
val (symbol, constructorTypeArguments) = getKPropertyImplConstructor(
|
||||
receiverTypes = emptyList(),
|
||||
returnType = returnType,
|
||||
returnType = propertyType,
|
||||
isLocal = true,
|
||||
isMutable = false)
|
||||
val initializer = irCall(symbol, constructorTypeArguments).apply {
|
||||
val initializer = irCall(symbol.owner, constructorTypeArguments).apply {
|
||||
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
||||
}
|
||||
return initializer
|
||||
@@ -316,10 +311,15 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
||||
private object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION :
|
||||
IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION")
|
||||
|
||||
private fun createKPropertiesFieldDescriptor(containingDeclaration: DeclarationDescriptor, fieldType: SimpleType): PropertyDescriptorImpl {
|
||||
private fun createKPropertiesFieldDescriptor(containingDeclaration: DeclarationDescriptor, fieldType: KotlinType): PropertyDescriptorImpl {
|
||||
return PropertyDescriptorImpl.create(containingDeclaration, Annotations.EMPTY, Modality.FINAL, Visibilities.PRIVATE,
|
||||
false, "KPROPERTIES".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE,
|
||||
false, false, false, false, false, false).initialize(fieldType)
|
||||
false, false, false, false, false, false).apply {
|
||||
|
||||
val receiverType: KotlinType? = null
|
||||
this.setType(fieldType, emptyList(), null, receiverType)
|
||||
this.initialize(null, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+200
-143
@@ -20,16 +20,19 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
|
||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor
|
||||
import org.jetbrains.kotlin.backend.common.ir.createArrayOfExpression
|
||||
import org.jetbrains.kotlin.backend.common.ir.createSimpleDelegatingConstructorDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
@@ -38,61 +41,60 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
|
||||
|
||||
internal class EnumSyntheticFunctionsBuilder(val context: Context) {
|
||||
fun buildValuesExpression(startOffset: Int, endOffset: Int,
|
||||
enumClassDescriptor: ClassDescriptor): IrExpression {
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
|
||||
enumClass: IrClass): IrExpression {
|
||||
|
||||
val typeParameterT = genericValuesDescriptor.typeParameters[0]
|
||||
val enumClassType = enumClassDescriptor.defaultType
|
||||
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType)))
|
||||
val substitutedValueOf = genericValuesDescriptor.substitute(typeSubstitutor)!!
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass)
|
||||
|
||||
return IrCallImpl(startOffset, endOffset,
|
||||
genericValuesSymbol, substitutedValueOf, mapOf(typeParameterT to enumClassType))
|
||||
return irCall(startOffset, endOffset, genericValuesSymbol.owner, listOf(enumClass.defaultType))
|
||||
.apply {
|
||||
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
||||
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
||||
putValueArgument(0, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver))
|
||||
loweredEnum.implObject.defaultType,
|
||||
loweredEnum.implObject.symbol)
|
||||
putValueArgument(0, IrGetFieldImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
loweredEnum.valuesField.symbol,
|
||||
loweredEnum.valuesField.type,
|
||||
receiver
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fun buildValueOfExpression(startOffset: Int, endOffset: Int,
|
||||
enumClassDescriptor: ClassDescriptor,
|
||||
enumClass: IrClass,
|
||||
value: IrExpression): IrExpression {
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass)
|
||||
|
||||
val typeParameterT = genericValueOfDescriptor.typeParameters[0]
|
||||
val enumClassType = enumClassDescriptor.defaultType
|
||||
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType)))
|
||||
val substitutedValueOf = genericValueOfDescriptor.substitute(typeSubstitutor)!!
|
||||
|
||||
return IrCallImpl(startOffset, endOffset,
|
||||
genericValueOfSymbol, substitutedValueOf, mapOf(typeParameterT to enumClassType))
|
||||
return irCall(startOffset, endOffset, genericValueOfSymbol.owner, listOf(enumClass.defaultType))
|
||||
.apply {
|
||||
putValueArgument(0, value)
|
||||
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
||||
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
||||
putValueArgument(1, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver))
|
||||
putValueArgument(1, IrGetFieldImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
loweredEnum.valuesField.symbol,
|
||||
loweredEnum.valuesField.type,
|
||||
receiver
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
private val genericValueOfSymbol = context.ir.symbols.valueOfForEnum
|
||||
private val genericValueOfDescriptor = genericValueOfSymbol.descriptor
|
||||
|
||||
private val genericValuesSymbol = context.ir.symbols.valuesForEnum
|
||||
private val genericValuesDescriptor = genericValuesSymbol.descriptor
|
||||
}
|
||||
|
||||
internal class EnumUsageLowering(val context: Context)
|
||||
@@ -105,16 +107,13 @@ internal class EnumUsageLowering(val context: Context)
|
||||
}
|
||||
|
||||
override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression {
|
||||
val enumClassDescriptor = expression.descriptor.containingDeclaration as ClassDescriptor
|
||||
return loadEnumEntry(expression.startOffset, expression.endOffset, enumClassDescriptor, expression.descriptor.name)
|
||||
}
|
||||
|
||||
// TODO: remove as soon IR is fixed (there should no be any enum get with GET_OBJECT operation).
|
||||
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
||||
if (expression.descriptor.kind != ClassKind.ENUM_ENTRY)
|
||||
return super.visitGetObjectValue(expression)
|
||||
val enumClassDescriptor = expression.descriptor.containingDeclaration as ClassDescriptor
|
||||
return loadEnumEntry(expression.startOffset, expression.endOffset, enumClassDescriptor, expression.descriptor.name)
|
||||
val entry = expression.symbol.owner
|
||||
return loadEnumEntry(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
entry.parentAsClass,
|
||||
entry.name
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
@@ -125,18 +124,20 @@ internal class EnumUsageLowering(val context: Context)
|
||||
if (descriptor.original != enumValuesDescriptor && descriptor.original != enumValueOfDescriptor)
|
||||
return expression
|
||||
|
||||
val genericT = descriptor.original.typeParameters[0]
|
||||
val substitutedT = expression.getTypeArgument(genericT)!!
|
||||
val classDescriptor = substitutedT.constructor.declarationDescriptor as? ClassDescriptor
|
||||
val irClassSymbol = expression.getTypeArgument(0)!!.classifierOrNull as? IrClassSymbol
|
||||
?: return expression // Type parameter.
|
||||
|
||||
assert (classDescriptor.kind == ClassKind.ENUM_CLASS)
|
||||
if (irClassSymbol == context.ir.symbols.enum) return expression // Type parameter erased to 'Enum'.
|
||||
|
||||
val irClass = irClassSymbol.owner
|
||||
|
||||
assert (irClass.kind == ClassKind.ENUM_CLASS)
|
||||
|
||||
return if (descriptor.original == enumValuesDescriptor) {
|
||||
enumSyntheticFunctionsBuilder.buildValuesExpression(expression.startOffset, expression.endOffset, classDescriptor)
|
||||
enumSyntheticFunctionsBuilder.buildValuesExpression(expression.startOffset, expression.endOffset, irClass)
|
||||
} else {
|
||||
val value = expression.getValueArgument(0)!!
|
||||
enumSyntheticFunctionsBuilder.buildValueOfExpression(expression.startOffset, expression.endOffset, classDescriptor, value)
|
||||
enumSyntheticFunctionsBuilder.buildValueOfExpression(expression.startOffset, expression.endOffset, irClass, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,12 +147,12 @@ internal class EnumUsageLowering(val context: Context)
|
||||
private val enumValuesSymbol = context.ir.symbols.enumValues
|
||||
private val enumValuesDescriptor = enumValuesSymbol.descriptor
|
||||
|
||||
private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClassDescriptor: ClassDescriptor, name: Name): IrExpression {
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
|
||||
private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClass: IrClass, name: Name): IrExpression {
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass)
|
||||
val ordinal = loweredEnum.entriesMap[name]!!
|
||||
return IrCallImpl(startOffset, endOffset, loweredEnum.itemGetterSymbol, loweredEnum.itemGetterDescriptor).apply {
|
||||
dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol)
|
||||
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, enumClassDescriptor.module.builtIns.intType, ordinal))
|
||||
return irCall(startOffset, endOffset, loweredEnum.itemGetterSymbol.owner, emptyList()).apply {
|
||||
dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter.returnType, loweredEnum.valuesGetter.symbol)
|
||||
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,7 +179,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
private inner class EnumClassTransformer(val irClass: IrClass) {
|
||||
private val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(irClass.descriptor)
|
||||
private val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(irClass)
|
||||
private val loweredEnumConstructors = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
||||
private val descriptorToIrConstructorWithDefaultArguments = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
||||
private val defaultEnumEntryConstructors = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
||||
@@ -212,7 +213,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
blockBody.statements.transformFlat {
|
||||
if (it is IrEnumConstructorCall)
|
||||
listOf(it, IrInstanceInitializerCallImpl(declaration.startOffset, declaration.startOffset,
|
||||
irClass.symbol))
|
||||
irClass.symbol, context.irBuiltIns.unitType))
|
||||
else null
|
||||
}
|
||||
}
|
||||
@@ -245,17 +246,22 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val defaultClassDescriptor = ClassDescriptorImpl(descriptor, "DEFAULT".synthesizedName, Modality.FINAL,
|
||||
ClassKind.CLASS, listOf(descriptor.defaultType), SourceElement.NO_SOURCE, false, LockBasedStorageManager.NO_LOCKS)
|
||||
val defaultClass = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, defaultClassDescriptor)
|
||||
defaultClass.createParameterDeclarations()
|
||||
|
||||
|
||||
val constructors = mutableSetOf<ClassConstructorDescriptor>()
|
||||
|
||||
descriptor.constructors.forEach {
|
||||
val loweredEnumConstructorSymbol = loweredEnumConstructors[it]!!.symbol
|
||||
val loweredEnumConstructor = loweredEnumConstructorSymbol.descriptor
|
||||
val constructorDescriptor = defaultClassDescriptor.createSimpleDelegatingConstructorDescriptor(loweredEnumConstructor)
|
||||
val loweredEnumIrConstructor = loweredEnumConstructors[it]!!
|
||||
val loweredEnumConstructor = loweredEnumIrConstructor.descriptor
|
||||
|
||||
val constructor = defaultClass.addSimpleDelegatingConstructor(
|
||||
loweredEnumConstructorSymbol, constructorDescriptor,
|
||||
DECLARATION_ORIGIN_ENUM)
|
||||
loweredEnumIrConstructor,
|
||||
context.irBuiltIns,
|
||||
DECLARATION_ORIGIN_ENUM
|
||||
)
|
||||
|
||||
val constructorDescriptor = constructor.descriptor
|
||||
constructors.add(constructorDescriptor)
|
||||
defaultEnumEntryConstructors.put(loweredEnumConstructor, constructor)
|
||||
|
||||
@@ -273,8 +279,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val memberScope = stub<MemberScope>("enum default class")
|
||||
defaultClassDescriptor.initialize(memberScope, constructors, null)
|
||||
|
||||
defaultClass.createParameterDeclarations()
|
||||
defaultClass.setSuperSymbolsAndAddFakeOverrides(listOf(irClass))
|
||||
defaultClass.setSuperSymbolsAndAddFakeOverrides(listOf(irClass.defaultType))
|
||||
|
||||
return defaultClass
|
||||
}
|
||||
@@ -310,12 +315,6 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
++i
|
||||
}
|
||||
|
||||
val constructorOfAny = context.ir.symbols.any.constructors.single()
|
||||
|
||||
implObject.addSimpleDelegatingConstructor(
|
||||
constructorOfAny, implObject.descriptor.constructors.single(),
|
||||
DECLARATION_ORIGIN_ENUM)
|
||||
|
||||
implObject.addChild(createSyntheticValuesPropertyDeclaration(enumEntries))
|
||||
implObject.addChild(createValuesPropertyInitializer(enumEntries))
|
||||
|
||||
@@ -329,17 +328,19 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
|
||||
val irValuesInitializer = context.createArrayOfExpression(irClass.descriptor.defaultType,
|
||||
val irValuesInitializer = context.createArrayOfExpression(irClass.defaultType,
|
||||
enumEntries
|
||||
.sortedBy { it.descriptor.name }
|
||||
.map {
|
||||
val enumEntryClass = ((it.initializerExpression!! as IrCall).descriptor as ConstructorDescriptor).constructedClass
|
||||
val typeParameterT = genericCreateUninitializedInstanceDescriptor.typeParameters[0]
|
||||
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumEntryClass.defaultType)))
|
||||
val substitutedCreateUninitializedInstance = genericCreateUninitializedInstanceDescriptor.substitute(typeSubstitutor)!!
|
||||
IrCallImpl(startOffset, endOffset,
|
||||
genericCreateUninitializedInstanceSymbol, substitutedCreateUninitializedInstance, mapOf(typeParameterT to enumEntryClass.defaultType)
|
||||
val entryConstructorCall = it.initializerExpression!! as IrCall
|
||||
val entryConstructor = entryConstructorCall.symbol.owner as IrConstructor
|
||||
val entryClass = entryConstructor.constructedClass
|
||||
|
||||
irCall(startOffset, endOffset,
|
||||
genericCreateUninitializedInstanceSymbol.owner,
|
||||
listOf(entryClass.defaultType)
|
||||
)
|
||||
|
||||
}, startOffset, endOffset)
|
||||
val irField = loweredEnum.valuesField.apply {
|
||||
initializer = IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer)
|
||||
@@ -349,8 +350,20 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
||||
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
||||
val value = IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver)
|
||||
val returnStatement = IrReturnImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol, value)
|
||||
val value = IrGetFieldImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
loweredEnum.valuesField.symbol,
|
||||
loweredEnum.valuesField.type,
|
||||
receiver
|
||||
)
|
||||
val returnStatement = IrReturnImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
context.irBuiltIns.nothingType,
|
||||
loweredEnum.valuesGetter.symbol,
|
||||
value
|
||||
)
|
||||
getter.body = IrBlockBodyImpl(startOffset, endOffset, listOf(returnStatement))
|
||||
|
||||
return IrPropertyImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM,
|
||||
@@ -363,7 +376,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
private val arrayGetSymbol = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||
|
||||
private val arrayType = context.builtIns.getArrayType(Variance.INVARIANT, irClass.defaultType)
|
||||
private val arrayType = context.ir.symbols.array.typeWith(irClass.defaultType)
|
||||
|
||||
private fun createValuesPropertyInitializer(enumEntries: List<IrEnumEntry>): IrAnonymousInitializerImpl {
|
||||
val startOffset = irClass.startOffset
|
||||
@@ -371,13 +384,13 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
return IrAnonymousInitializerImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, loweredEnum.implObject.descriptor).apply {
|
||||
body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody(irClass) {
|
||||
val instances = irTemporary(irGetField(irGet(loweredEnum.implObject.thisReceiver!!.symbol), loweredEnum.valuesField.symbol))
|
||||
val instances = irTemporary(irGetField(irGet(loweredEnum.implObject.thisReceiver!!), loweredEnum.valuesField))
|
||||
enumEntries
|
||||
.sortedBy { it.descriptor.name }
|
||||
.withIndex()
|
||||
.forEach {
|
||||
val instance = irCall(arrayGetSymbol).apply {
|
||||
dispatchReceiver = irGet(instances.symbol)
|
||||
dispatchReceiver = irGet(instances)
|
||||
putValueArgument(0, irInt(it.index))
|
||||
}
|
||||
val initializer = it.value.initializerExpression!! as IrCall
|
||||
@@ -387,7 +400,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
}
|
||||
+irCall(this@EnumClassLowering.context.ir.symbols.freeze, listOf(arrayType)).apply {
|
||||
extensionReceiver = irGet(loweredEnum.implObject.thisReceiver!!.symbol)
|
||||
extensionReceiver = irGet(loweredEnum.implObject.thisReceiver!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,23 +409,35 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
private fun createSyntheticValuesMethodBody(declaration: IrFunction): IrBody {
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass.descriptor)
|
||||
val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass)
|
||||
|
||||
return IrBlockBodyImpl(startOffset, endOffset,
|
||||
listOf(IrReturnImpl(startOffset, endOffset, declaration.symbol, valuesExpression))
|
||||
)
|
||||
return IrBlockBodyImpl(startOffset, endOffset).apply {
|
||||
statements += IrReturnImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
context.irBuiltIns.nothingType,
|
||||
declaration.symbol,
|
||||
valuesExpression
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSyntheticValueOfMethodBody(declaration: IrFunction): IrBody {
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
val value = IrGetValueImpl(startOffset, endOffset, declaration.valueParameters[0].symbol)
|
||||
val valueOfExpression = enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass.descriptor, value)
|
||||
val parameter = declaration.valueParameters[0]
|
||||
val value = IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol)
|
||||
val valueOfExpression = enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass, value)
|
||||
|
||||
return IrBlockBodyImpl(
|
||||
startOffset, endOffset,
|
||||
listOf(IrReturnImpl(startOffset, endOffset, declaration.symbol, valueOfExpression))
|
||||
)
|
||||
return IrBlockBodyImpl(startOffset, endOffset).apply {
|
||||
statements += IrReturnImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
context.irBuiltIns.nothingType,
|
||||
declaration.symbol,
|
||||
valueOfExpression
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun lowerEnumConstructors(irClass: IrClass) {
|
||||
@@ -423,18 +448,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
private fun transformEnumConstructor(enumConstructor: IrConstructor): IrConstructor {
|
||||
val constructorDescriptor = enumConstructor.descriptor
|
||||
val loweredConstructorDescriptor = lowerEnumConstructor(constructorDescriptor)
|
||||
val loweredEnumConstructor = IrConstructorImpl(
|
||||
enumConstructor.startOffset, enumConstructor.endOffset, enumConstructor.origin,
|
||||
loweredConstructorDescriptor,
|
||||
enumConstructor.body!! // will be transformed later
|
||||
)
|
||||
loweredEnumConstructor.parent = enumConstructor.parent
|
||||
|
||||
loweredEnumConstructors[constructorDescriptor] = loweredEnumConstructor
|
||||
|
||||
loweredEnumConstructor.createParameterDeclarations()
|
||||
val loweredEnumConstructor = lowerEnumConstructor(enumConstructor)
|
||||
|
||||
enumConstructor.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach {
|
||||
val body = enumConstructor.getDefault(it)!!
|
||||
@@ -443,54 +457,75 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val descriptor = expression.descriptor
|
||||
when (descriptor) {
|
||||
is ValueParameterDescriptor -> {
|
||||
val parameter = loweredEnumConstructor.valueParameters[descriptor.loweredIndex()]
|
||||
return IrGetValueImpl(expression.startOffset,
|
||||
expression.endOffset,
|
||||
loweredEnumConstructor.valueParameters[descriptor.loweredIndex()].symbol)
|
||||
parameter.type,
|
||||
parameter.symbol)
|
||||
}
|
||||
}
|
||||
return expression
|
||||
}
|
||||
})
|
||||
loweredEnumConstructor.putDefault(loweredConstructorDescriptor.valueParameters[it.loweredIndex()], body)
|
||||
descriptorToIrConstructorWithDefaultArguments[loweredConstructorDescriptor] = loweredEnumConstructor
|
||||
loweredEnumConstructor.valueParameters[it.loweredIndex()].defaultValue = body
|
||||
descriptorToIrConstructorWithDefaultArguments[loweredEnumConstructor.descriptor] = loweredEnumConstructor
|
||||
}
|
||||
return loweredEnumConstructor
|
||||
}
|
||||
|
||||
private fun lowerEnumConstructor(constructorDescriptor: ClassConstructorDescriptor): ClassConstructorDescriptor {
|
||||
private fun lowerEnumConstructor(enumConstructor: IrConstructor): IrConstructorImpl {
|
||||
val loweredConstructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
|
||||
constructorDescriptor.containingDeclaration,
|
||||
constructorDescriptor.annotations,
|
||||
constructorDescriptor.isPrimary,
|
||||
constructorDescriptor.source
|
||||
enumConstructor.descriptor.containingDeclaration,
|
||||
enumConstructor.descriptor.annotations,
|
||||
enumConstructor.descriptor.isPrimary,
|
||||
enumConstructor.descriptor.source
|
||||
)
|
||||
|
||||
val valueParameters =
|
||||
listOf(
|
||||
loweredConstructorDescriptor.createValueParameter(0, "name", context.builtIns.stringType),
|
||||
loweredConstructorDescriptor.createValueParameter(1, "ordinal", context.builtIns.intType)
|
||||
loweredConstructorDescriptor.createValueParameter(
|
||||
0,
|
||||
"name",
|
||||
context.irBuiltIns.stringType,
|
||||
enumConstructor.startOffset,
|
||||
enumConstructor.endOffset
|
||||
),
|
||||
loweredConstructorDescriptor.createValueParameter(
|
||||
1,
|
||||
"ordinal",
|
||||
context.irBuiltIns.intType,
|
||||
enumConstructor.startOffset,
|
||||
enumConstructor.endOffset
|
||||
)
|
||||
) +
|
||||
constructorDescriptor.valueParameters.map {
|
||||
lowerConstructorValueParameter(loweredConstructorDescriptor, it)
|
||||
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, Visibilities.PROTECTED)
|
||||
|
||||
loweredConstructorDescriptor.returnType = constructorDescriptor.returnType
|
||||
|
||||
return loweredConstructorDescriptor
|
||||
}
|
||||
|
||||
private fun lowerConstructorValueParameter(
|
||||
loweredConstructorDescriptor: ClassConstructorDescriptor,
|
||||
valueParameterDescriptor: ValueParameterDescriptor
|
||||
): ValueParameterDescriptor {
|
||||
val loweredValueParameterDescriptor = valueParameterDescriptor.copy(
|
||||
loweredConstructorDescriptor,
|
||||
valueParameterDescriptor.name,
|
||||
valueParameterDescriptor.loweredIndex()
|
||||
loweredConstructorDescriptor.initialize(
|
||||
valueParameters.map { it.descriptor as ValueParameterDescriptor },
|
||||
Visibilities.PROTECTED
|
||||
)
|
||||
loweredEnumConstructorParameters[valueParameterDescriptor] = loweredValueParameterDescriptor
|
||||
return loweredValueParameterDescriptor
|
||||
loweredConstructorDescriptor.returnType = enumConstructor.descriptor.returnType
|
||||
val loweredEnumConstructor = IrConstructorImpl(
|
||||
enumConstructor.startOffset, enumConstructor.endOffset, enumConstructor.origin,
|
||||
loweredConstructorDescriptor
|
||||
).apply {
|
||||
returnType = enumConstructor.returnType
|
||||
body = enumConstructor.body!! // will be transformed later
|
||||
}
|
||||
loweredEnumConstructor.valueParameters += valueParameters
|
||||
loweredEnumConstructor.parent = enumConstructor.parent
|
||||
|
||||
loweredEnumConstructors[enumConstructor.descriptor] = loweredEnumConstructor
|
||||
|
||||
return loweredEnumConstructor
|
||||
}
|
||||
|
||||
private fun lowerEnumClassBody() {
|
||||
@@ -505,7 +540,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val origin = enumConstructorCall.origin
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
enumConstructorCall.symbol, enumConstructorCall.descriptor)
|
||||
context.irBuiltIns.unitType,
|
||||
enumConstructorCall.symbol, enumConstructorCall.descriptor, enumConstructorCall.typeArgumentsCount)
|
||||
|
||||
assert(result.descriptor.valueParameters.size == 2) {
|
||||
"Enum(String, Int) constructor call expected:\n${result.dump()}"
|
||||
@@ -519,8 +555,12 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor")
|
||||
}
|
||||
|
||||
result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, nameParameter.symbol, origin))
|
||||
result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, ordinalParameter.symbol, origin))
|
||||
result.putValueArgument(0,
|
||||
IrGetValueImpl(startOffset, endOffset, nameParameter.type, nameParameter.symbol, origin)
|
||||
)
|
||||
result.putValueArgument(1,
|
||||
IrGetValueImpl(startOffset, endOffset, ordinalParameter.type, ordinalParameter.symbol, origin)
|
||||
)
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -534,13 +574,15 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor")
|
||||
}
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
loweredDelegatedConstructor.symbol, loweredDelegatedConstructor.descriptor)
|
||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType,
|
||||
loweredDelegatedConstructor.symbol, loweredDelegatedConstructor.descriptor, 0)
|
||||
|
||||
val firstParameter = enumClassConstructor.valueParameters[0]
|
||||
result.putValueArgument(0,
|
||||
IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[0].symbol))
|
||||
IrGetValueImpl(startOffset, endOffset, firstParameter.type, firstParameter.symbol))
|
||||
val secondParameter = enumClassConstructor.valueParameters[1]
|
||||
result.putValueArgument(1,
|
||||
IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[1].symbol))
|
||||
IrGetValueImpl(startOffset, endOffset, secondParameter.type, secondParameter.symbol))
|
||||
|
||||
descriptor.valueParameters.forEach { valueParameter ->
|
||||
result.putValueArgument(valueParameter.loweredIndex(), delegatingConstructorCall.getValueArgument(valueParameter))
|
||||
@@ -565,8 +607,10 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
val result = createConstructorCall(startOffset, endOffset, loweredConstructor.symbol)
|
||||
|
||||
result.putValueArgument(0, IrConstImpl.string(startOffset, endOffset, context.builtIns.stringType, name))
|
||||
result.putValueArgument(1, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, ordinal))
|
||||
result.putValueArgument(0,
|
||||
IrConstImpl.string(startOffset, endOffset, context.irBuiltIns.stringType, name))
|
||||
result.putValueArgument(1,
|
||||
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal))
|
||||
|
||||
descriptor.valueParameters.forEach { valueParameter ->
|
||||
val i = valueParameter.index
|
||||
@@ -584,14 +628,25 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
private inner class InEnumEntryClassConstructor(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol)
|
||||
= IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor, loweredConstructor.descriptor)
|
||||
override fun createConstructorCall(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
loweredConstructor: IrConstructorSymbol
|
||||
) = IrDelegatingConstructorCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
loweredConstructor,
|
||||
loweredConstructor.descriptor,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrCall {
|
||||
return IrCallImpl(startOffset, endOffset,
|
||||
defaultEnumEntryConstructors[loweredConstructor.descriptor]?.symbol ?: loweredConstructor)
|
||||
val irConstructorSymbol = defaultEnumEntryConstructors[loweredConstructor.descriptor]?.symbol
|
||||
?: loweredConstructor
|
||||
return IrCallImpl(startOffset, endOffset, irConstructorSymbol.owner.returnType, irConstructorSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -668,7 +723,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val loweredEnumConstructor = loweredEnumConstructors[expression.descriptor.containingDeclaration]!!
|
||||
val loweredIrParameter = loweredEnumConstructor.valueParameters[loweredParameter.index]
|
||||
assert(loweredIrParameter.descriptor == loweredParameter)
|
||||
return IrGetValueImpl(expression.startOffset, expression.endOffset,
|
||||
return IrGetValueImpl(expression.startOffset, expression.endOffset, loweredIrParameter.type,
|
||||
loweredIrParameter.symbol, expression.origin)
|
||||
} else {
|
||||
return expression
|
||||
@@ -685,9 +740,11 @@ private class ParameterMapper(val originalConstructor: IrConstructor) : IrElemen
|
||||
val descriptor = expression.descriptor
|
||||
when (descriptor) {
|
||||
is ValueParameterDescriptor -> {
|
||||
val parameter = originalConstructor.valueParameters[descriptor.index]
|
||||
return IrGetValueImpl(expression.startOffset,
|
||||
expression.endOffset,
|
||||
originalConstructor.valueParameters[descriptor.index].symbol)
|
||||
parameter.type,
|
||||
parameter.symbol)
|
||||
}
|
||||
}
|
||||
return expression
|
||||
|
||||
+26
-14
@@ -5,6 +5,8 @@ import org.jetbrains.kotlin.backend.common.peek
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
import org.jetbrains.kotlin.backend.common.push
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.containsNull
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.getClass
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
@@ -16,6 +18,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
@@ -50,11 +53,11 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo
|
||||
}
|
||||
val subject = irBlock.statements[0] as IrVariable
|
||||
// Subject should not be nullable because we will access the `ordinal` property.
|
||||
if (subject.type.isNullable()) {
|
||||
if (subject.type.containsNull()) {
|
||||
return false
|
||||
}
|
||||
// Check that subject is enum entry.
|
||||
val enumClass = subject.type.constructor.declarationDescriptor as? ClassDescriptor
|
||||
val enumClass = subject.type.getClass()
|
||||
?: return false
|
||||
return enumClass.kind == ClassKind.ENUM_CLASS
|
||||
}
|
||||
@@ -83,14 +86,22 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo
|
||||
|
||||
private fun createEnumOrdinalVariable(enumVariable: IrVariable): IrVariable {
|
||||
val ordinalPropertyGetter = context.ir.symbols.enum.getPropertyGetter("ordinal")!!
|
||||
val getOrdinal = IrCallImpl(enumVariable.startOffset, enumVariable.endOffset, ordinalPropertyGetter).apply {
|
||||
dispatchReceiver = IrGetValueImpl(enumVariable.startOffset, enumVariable.endOffset, enumVariable.symbol)
|
||||
val getOrdinal = IrCallImpl(
|
||||
enumVariable.startOffset, enumVariable.endOffset,
|
||||
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, getOrdinal)
|
||||
IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, ordinalDescriptor,
|
||||
context.irBuiltIns.intType, getOrdinal)
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
@@ -100,7 +111,7 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo
|
||||
}
|
||||
|
||||
private val areEqualByValue = context.ir.symbols.areEqualByValue.first {
|
||||
it.owner.valueParameters[0].type == context.builtIns.intType
|
||||
it.owner.valueParameters[0].type.classifierOrNull == context.ir.symbols.int
|
||||
}
|
||||
|
||||
// We are looking for branch that is a comparison of the subject and another enum entry.
|
||||
@@ -114,19 +125,20 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo
|
||||
}
|
||||
val lhs = callArgs[0].second
|
||||
val rhs = callArgs[1].second
|
||||
// Both entries should belong to the same class.
|
||||
if (lhs.type != rhs.type) {
|
||||
return call
|
||||
}
|
||||
|
||||
// If there is nothing on stack then nothing we can do.
|
||||
val (topmostSubject, topmostOrdinalProvider) = subjectWithOrdinalStack.peek()
|
||||
?: return call
|
||||
if (lhs is IrValueAccessExpression && lhs.symbol.owner == topmostSubject && rhs is IrGetEnumValue) {
|
||||
if (lhs is IrValueAccessExpression && lhs.symbol.owner == topmostSubject && rhs is IrGetEnumValue &&
|
||||
// Both entries should belong to the same class:
|
||||
topmostSubject.type.classifierOrNull?.owner == rhs.symbol.owner.parent) {
|
||||
val entryOrdinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(rhs.descriptor)
|
||||
val subjectOrdinal = topmostOrdinalProvider.value
|
||||
return IrCallImpl(call.startOffset, call.endOffset, areEqualByValue).apply {
|
||||
putValueArgument(0, IrGetValueImpl(lhs.startOffset, lhs.endOffset, subjectOrdinal.symbol))
|
||||
putValueArgument(1, IrConstImpl.int(rhs.startOffset, rhs.endOffset, context.builtIns.intType, entryOrdinal))
|
||||
return IrCallImpl(call.startOffset, call.endOffset, areEqualByValue.owner.returnType, areEqualByValue).apply {
|
||||
putValueArgument(0,
|
||||
IrGetValueImpl(lhs.startOffset, lhs.endOffset, subjectOrdinal.type, subjectOrdinal.symbol))
|
||||
putValueArgument(1,
|
||||
IrConstImpl.int(rhs.startOffset, rhs.endOffset, context.irBuiltIns.intType, entryOrdinal))
|
||||
}
|
||||
}
|
||||
return call
|
||||
|
||||
+5
-7
@@ -3,10 +3,7 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
@@ -79,20 +76,21 @@ internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPa
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
expression.transformChildrenVoid()
|
||||
val newSymbol = remapExpectValueSymbol(expression.symbol)
|
||||
val newValue = remapExpectValue(expression.symbol)
|
||||
?: return expression
|
||||
|
||||
return IrGetValueImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
newSymbol,
|
||||
newValue.type,
|
||||
newValue.symbol,
|
||||
expression.origin
|
||||
)
|
||||
}
|
||||
}, data = null)
|
||||
}
|
||||
|
||||
private fun remapExpectValueSymbol(symbol: IrValueSymbol): IrValueParameterSymbol? {
|
||||
private fun remapExpectValue(symbol: IrValueSymbol): IrValueParameter? {
|
||||
if (symbol !is IrValueParameterSymbol) {
|
||||
return null
|
||||
}
|
||||
@@ -120,6 +118,6 @@ internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPa
|
||||
}
|
||||
|
||||
else -> error(parent)
|
||||
}.symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+35
-27
@@ -36,39 +36,44 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.builders.irGet
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, IrElementTransformerVoidWithContext() {
|
||||
|
||||
private val symbols get() = context.ir.symbols
|
||||
|
||||
private interface HighLevelJump {
|
||||
fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression): IrExpression
|
||||
}
|
||||
|
||||
private data class Return(val target: IrReturnTargetSymbol): HighLevelJump {
|
||||
override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression)
|
||||
= IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, target, value)
|
||||
= IrReturnImpl(startOffset, endOffset, context.irBuiltIns.nothingType, target, value)
|
||||
}
|
||||
|
||||
private data class Break(val loop: IrLoop): HighLevelJump {
|
||||
override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression)
|
||||
= IrBlockImpl(startOffset, endOffset, context.builtIns.nothingType, null,
|
||||
= IrBlockImpl(startOffset, endOffset, context.irBuiltIns.nothingType, null,
|
||||
statements = listOf(
|
||||
value,
|
||||
IrBreakImpl(startOffset, endOffset, context.builtIns.nothingType, loop)
|
||||
IrBreakImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop)
|
||||
))
|
||||
}
|
||||
|
||||
private data class Continue(val loop: IrLoop): HighLevelJump {
|
||||
override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression)
|
||||
= IrBlockImpl(startOffset, endOffset, context.builtIns.nothingType, null,
|
||||
= IrBlockImpl(startOffset, endOffset, context.irBuiltIns.nothingType, null,
|
||||
statements = listOf(
|
||||
value,
|
||||
IrContinueImpl(startOffset, endOffset, context.builtIns.nothingType, loop)
|
||||
IrContinueImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop)
|
||||
))
|
||||
}
|
||||
|
||||
@@ -183,10 +188,11 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
|
||||
val currentTryScope = tryScopes[index]
|
||||
currentTryScope.jumps.getOrPut(jump) {
|
||||
val symbol = getIrReturnableBlockSymbol(jump.toString(), value.type)
|
||||
val type = value.type
|
||||
val symbol = getIrReturnableBlockSymbol(jump.toString(), type)
|
||||
with(currentTryScope) {
|
||||
irBuilder.run {
|
||||
val inlinedFinally = irInlineFinally(symbol, expression, finallyExpression)
|
||||
val inlinedFinally = irInlineFinally(symbol, type, expression, finallyExpression)
|
||||
expression = performHighLevelJump(
|
||||
tryScopes = tryScopes,
|
||||
index = index + 1,
|
||||
@@ -201,7 +207,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
return IrReturnImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = context.builtIns.nothingType,
|
||||
type = context.irBuiltIns.nothingType,
|
||||
returnTargetSymbol = it,
|
||||
value = value)
|
||||
}
|
||||
@@ -219,7 +225,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
val transformedTry = IrTryImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = context.builtIns.nothingType
|
||||
type = context.irBuiltIns.nothingType
|
||||
)
|
||||
val transformedFinallyExpression = finallyExpression.transform(transformer, null)
|
||||
val parameter = IrTemporaryVariableDescriptorImpl(
|
||||
@@ -228,24 +234,26 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
outType = context.builtIns.throwable.defaultType
|
||||
)
|
||||
val catchParameter = IrVariableImpl(
|
||||
startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter)
|
||||
startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter,
|
||||
symbols.throwable.owner.defaultType)
|
||||
|
||||
val syntheticTry = IrTryImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = context.builtIns.nothingType,
|
||||
type = context.irBuiltIns.nothingType,
|
||||
tryResult = transformedTry,
|
||||
catches = listOf(
|
||||
irCatch(catchParameter).apply {
|
||||
result = irBlock {
|
||||
+finallyExpression.copy()
|
||||
+irThrow(irGet(catchParameter.symbol))
|
||||
+irThrow(irGet(catchParameter))
|
||||
}
|
||||
}),
|
||||
finallyExpression = null
|
||||
)
|
||||
using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
|
||||
val fallThroughSymbol = getIrReturnableBlockSymbol("fallThrough", aTry.type)
|
||||
val fallThroughType = aTry.type
|
||||
val fallThroughSymbol = getIrReturnableBlockSymbol("fallThrough", fallThroughType)
|
||||
val transformedResult = aTry.tryResult.transform(transformer, null)
|
||||
transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult)
|
||||
for (aCatch in aTry.catches) {
|
||||
@@ -253,28 +261,28 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
transformedCatch.result = irReturn(fallThroughSymbol, transformedCatch.result)
|
||||
transformedTry.catches.add(transformedCatch)
|
||||
}
|
||||
return irInlineFinally(fallThroughSymbol, it.expression, it.finallyExpression)
|
||||
return irInlineFinally(fallThroughSymbol, fallThroughType, it.expression, it.finallyExpression)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.irInlineFinally(symbol: IrReturnableBlockSymbol,
|
||||
private fun IrBuilderWithScope.irInlineFinally(symbol: IrReturnableBlockSymbol, type: IrType,
|
||||
value: IrExpression,
|
||||
finallyExpression: IrExpression): IrExpression {
|
||||
val returnType = symbol.descriptor.returnType!!
|
||||
return when {
|
||||
returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, returnType) {
|
||||
+irReturnableBlock(symbol) {
|
||||
returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, type) {
|
||||
+irReturnableBlock(symbol, type) {
|
||||
+value
|
||||
}
|
||||
+finallyExpression.copy()
|
||||
}
|
||||
else -> irBlock(value, null, returnType) {
|
||||
val tmp = irTemporary(irReturnableBlock(symbol) {
|
||||
else -> irBlock(value, null, type) {
|
||||
val tmp = irTemporary(irReturnableBlock(symbol, type) {
|
||||
+irReturn(symbol, value)
|
||||
})
|
||||
+finallyExpression.copy()
|
||||
+irGet(tmp.symbol)
|
||||
+irGet(tmp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,16 +293,16 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
initialize(null, null, emptyList(), emptyList(), returnType, Modality.ABSTRACT, Visibilities.PRIVATE)
|
||||
}
|
||||
|
||||
private fun getIrReturnableBlockSymbol(name: String, returnType: KotlinType): IrReturnableBlockSymbol =
|
||||
IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType))
|
||||
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) =
|
||||
IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, target, value)
|
||||
IrReturnImpl(startOffset, endOffset, context.irBuiltIns.nothingType, target, value)
|
||||
|
||||
inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, body: IrBlockBuilder.() -> Unit) =
|
||||
IrReturnableBlockImpl(startOffset, endOffset, symbol.descriptor.returnType!!, symbol, null,
|
||||
IrBlockBuilder(context, scope, startOffset, endOffset, null, symbol.descriptor.returnType!!)
|
||||
inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, type: IrType, body: IrBlockBuilder.() -> Unit) =
|
||||
IrReturnableBlockImpl(startOffset, endOffset, type, symbol, null,
|
||||
IrBlockBuilder(context, scope, startOffset, endOffset, null, type)
|
||||
.block(body).statements)
|
||||
}
|
||||
+50
-42
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
@@ -36,6 +37,9 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
||||
import org.jetbrains.kotlin.ir.types.makeNotNull
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -134,36 +138,40 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
||||
|
||||
//region Util methods ==============================================================================================
|
||||
private fun IrExpression.castIfNecessary(progressionType: ProgressionType): IrExpression {
|
||||
val type = this.type.toKotlinType()
|
||||
assert(type in progressionElementClassesTypes || type in progressionElementClassesNullableTypes)
|
||||
return if (type == progressionType.elementType) {
|
||||
this
|
||||
} else {
|
||||
IrCallImpl(startOffset, endOffset, symbols.getFunction(progressionType.numberCastFunctionName, type))
|
||||
val function = symbols.getFunction(progressionType.numberCastFunctionName, type)
|
||||
IrCallImpl(startOffset, endOffset, function.owner.returnType, function)
|
||||
.apply { dispatchReceiver = this@castIfNecessary }
|
||||
}
|
||||
}
|
||||
|
||||
private fun DeclarationIrBuilder.ensureNotNullable(expression: IrExpression): IrExpression {
|
||||
return if (expression.type.isMarkedNullable) {
|
||||
irImplicitCast(expression, expression.type.makeNotNullable())
|
||||
return if (expression.type.isSimpleTypeWithQuestionMark) {
|
||||
irImplicitCast(expression, expression.type.makeNotNull())
|
||||
} else {
|
||||
expression
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrExpression.unaryMinus(): IrExpression =
|
||||
IrCallImpl(startOffset, endOffset, symbols.getUnaryOperator(OperatorNameConventions.UNARY_MINUS, type)).apply {
|
||||
dispatchReceiver = this@unaryMinus
|
||||
}
|
||||
private fun IrExpression.unaryMinus(): IrExpression {
|
||||
val unaryOperator = symbols.getUnaryOperator(OperatorNameConventions.UNARY_MINUS, type.toKotlinType())
|
||||
return IrCallImpl(startOffset, endOffset, unaryOperator.owner.returnType, unaryOperator).apply {
|
||||
dispatchReceiver = this@unaryMinus
|
||||
}
|
||||
}
|
||||
|
||||
private fun ProgressionInfo.defaultStep(startOffset: Int, endOffset: Int): IrExpression =
|
||||
progressionType.elementType.let { type ->
|
||||
val step = if (increasing) 1 else -1
|
||||
when {
|
||||
KotlinBuiltIns.isInt(type) || KotlinBuiltIns.isChar(type) ->
|
||||
IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, step)
|
||||
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, step)
|
||||
KotlinBuiltIns.isLong(type) ->
|
||||
IrConstImpl.long(startOffset, endOffset, context.builtIns.longType, step.toLong())
|
||||
IrConstImpl.long(startOffset, endOffset, context.irBuiltIns.longType, step.toLong())
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
@@ -178,9 +186,9 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
||||
// Used only by the assert.
|
||||
private fun stepHasRightType(step: IrExpression, progressionType: ProgressionType) =
|
||||
((progressionType.isCharProgression() || progressionType.isIntProgression()) &&
|
||||
KotlinBuiltIns.isInt(step.type.makeNotNullable())) ||
|
||||
KotlinBuiltIns.isInt(step.type.toKotlinType().makeNotNullable())) ||
|
||||
(progressionType.isLongProgression() &&
|
||||
KotlinBuiltIns.isLong(step.type.makeNotNullable()))
|
||||
KotlinBuiltIns.isLong(step.type.toKotlinType().makeNotNullable()))
|
||||
|
||||
private fun irCheckProgressionStep(progressionType: ProgressionType,
|
||||
step: IrExpression): Pair<IrExpression, Boolean> {
|
||||
@@ -193,25 +201,25 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
||||
// so there is no need to cast it.
|
||||
assert(stepHasRightType(step, progressionType))
|
||||
|
||||
val symbol = symbols.checkProgressionStep[step.type.makeNotNullable()]
|
||||
val symbol = symbols.checkProgressionStep[step.type.toKotlinType().makeNotNullable()]
|
||||
?: throw IllegalArgumentException("Unknown progression element type: ${step.type}")
|
||||
return IrCallImpl(step.startOffset, step.endOffset, symbol).apply {
|
||||
return IrCallImpl(step.startOffset, step.endOffset, symbol.owner.returnType, symbol).apply {
|
||||
putValueArgument(0, step)
|
||||
} to true
|
||||
}
|
||||
|
||||
private fun irGetProgressionLast(progressionType: ProgressionType,
|
||||
first: IrVariableSymbol,
|
||||
first: IrVariable,
|
||||
lastExpression: IrExpression,
|
||||
step: IrVariableSymbol): IrExpression {
|
||||
step: IrVariable): IrExpression {
|
||||
val symbol = symbols.getProgressionLast[progressionType.elementType]
|
||||
?: throw IllegalArgumentException("Unknown progression element type: ${lastExpression.type}")
|
||||
val startOffset = lastExpression.startOffset
|
||||
val endOffset = lastExpression.endOffset
|
||||
return IrCallImpl(startOffset, lastExpression.endOffset, symbol).apply {
|
||||
putValueArgument(0, IrGetValueImpl(startOffset, endOffset, first))
|
||||
return IrCallImpl(startOffset, lastExpression.endOffset, symbol.owner.returnType, symbol).apply {
|
||||
putValueArgument(0, IrGetValueImpl(startOffset, endOffset, first.type, first.symbol))
|
||||
putValueArgument(1, lastExpression.castIfNecessary(progressionType))
|
||||
putValueArgument(2, IrGetValueImpl(startOffset, endOffset, step))
|
||||
putValueArgument(2, IrGetValueImpl(startOffset, endOffset, step.type, step.symbol))
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
@@ -236,11 +244,11 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
||||
/** Contains information about variables used in the loop. */
|
||||
private data class ForLoopInfo(
|
||||
val progressionInfo: ProgressionInfo,
|
||||
val inductionVariable: IrVariableSymbol,
|
||||
val bound: IrVariableSymbol,
|
||||
val last: IrVariableSymbol,
|
||||
val step: IrVariableSymbol,
|
||||
var loopVariable: IrVariableSymbol? = null)
|
||||
val inductionVariable: IrVariable,
|
||||
val bound: IrVariable,
|
||||
val last: IrVariable,
|
||||
val step: IrVariable,
|
||||
var loopVariable: IrVariable? = null)
|
||||
|
||||
private inner class ProgressionInfoBuilder : IrElementVisitor<ProgressionInfo?, Nothing?> {
|
||||
|
||||
@@ -287,7 +295,7 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
||||
override fun visitElement(element: IrElement, data: Nothing?): ProgressionInfo? = null
|
||||
|
||||
override fun visitCall(expression: IrCall, data: Nothing?): ProgressionInfo? {
|
||||
val type = expression.type
|
||||
val type = expression.type.toKotlinType()
|
||||
val progressionType = when {
|
||||
type.isSubtypeOf(symbols.charProgression.descriptor.defaultType) -> CHAR_PROGRESSION
|
||||
type.isSubtypeOf(symbols.intProgression.descriptor.defaultType) -> INT_PROGRESSION
|
||||
@@ -362,15 +370,15 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
||||
var lastExpression: IrExpression? = null
|
||||
if (!closed) {
|
||||
val decrementSymbol = symbols.getUnaryOperator(OperatorNameConventions.DEC, boundValue.descriptor.type)
|
||||
lastExpression = irCall(decrementSymbol).apply {
|
||||
dispatchReceiver = irGet(boundValue.symbol)
|
||||
lastExpression = irCall(decrementSymbol.owner).apply {
|
||||
dispatchReceiver = irGet(boundValue)
|
||||
}
|
||||
}
|
||||
if (needLastCalculation) {
|
||||
lastExpression = irGetProgressionLast(progressionType,
|
||||
inductionVariable.symbol,
|
||||
lastExpression ?: irGet(boundValue.symbol),
|
||||
stepValue.symbol)
|
||||
inductionVariable,
|
||||
lastExpression ?: irGet(boundValue),
|
||||
stepValue)
|
||||
}
|
||||
val lastValue = if (lastExpression != null) {
|
||||
scope.createTemporaryVariable(lastExpression,
|
||||
@@ -383,12 +391,12 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
||||
}
|
||||
|
||||
iteratorToLoopInfo[symbol] = ForLoopInfo(progressionInfo,
|
||||
inductionVariable.symbol,
|
||||
boundValue.symbol,
|
||||
lastValue.symbol,
|
||||
stepValue.symbol)
|
||||
inductionVariable,
|
||||
boundValue,
|
||||
lastValue,
|
||||
stepValue)
|
||||
|
||||
return IrCompositeImpl(startOffset, endOffset, context.builtIns.unitType, null, statements)
|
||||
return IrCompositeImpl(startOffset, endOffset, context.irBuiltIns.unitType, null, statements)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,15 +414,15 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
||||
forLoopInfo.inductionVariable.descriptor.type,
|
||||
forLoopInfo.step.descriptor.type
|
||||
)
|
||||
forLoopInfo.loopVariable = variable.symbol
|
||||
forLoopInfo.loopVariable = variable
|
||||
|
||||
with(builder) {
|
||||
variable.initializer = irGet(forLoopInfo.inductionVariable)
|
||||
val increment = irSetVar(forLoopInfo.inductionVariable,
|
||||
irCallOp(plusOperator, irGet(forLoopInfo.inductionVariable), irGet(forLoopInfo.step)))
|
||||
irCallOp(plusOperator.owner, irGet(forLoopInfo.inductionVariable), irGet(forLoopInfo.step)))
|
||||
return IrCompositeImpl(variable.startOffset,
|
||||
variable.endOffset,
|
||||
context.irBuiltIns.unit,
|
||||
context.irBuiltIns.unitType,
|
||||
IrStatementOrigin.FOR_LOOP_NEXT,
|
||||
listOf(variable, increment))
|
||||
}
|
||||
@@ -427,16 +435,16 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
||||
return irCall(context.irBuiltIns.greaterFunByOperandType[context.irBuiltIns.int]?.symbol!!).apply {
|
||||
val minConst = when {
|
||||
progressionType.isIntProgression() -> IrConstImpl
|
||||
.int(startOffset, endOffset, context.builtIns.intType, Int.MIN_VALUE)
|
||||
.int(startOffset, endOffset, context.irBuiltIns.intType, Int.MIN_VALUE)
|
||||
progressionType.isCharProgression() -> IrConstImpl
|
||||
.char(startOffset, endOffset, context.builtIns.charType, 0.toChar())
|
||||
.char(startOffset, endOffset, context.irBuiltIns.charType, 0.toChar())
|
||||
progressionType.isLongProgression() -> IrConstImpl
|
||||
.long(startOffset, endOffset, context.builtIns.longType, Long.MIN_VALUE)
|
||||
.long(startOffset, endOffset, context.irBuiltIns.longType, Long.MIN_VALUE)
|
||||
else -> throw IllegalArgumentException("Unknown progression type")
|
||||
}
|
||||
val compareToCall = irCall(symbols.getBinaryOperator(OperatorNameConventions.COMPARE_TO,
|
||||
forLoopInfo.bound.descriptor.type,
|
||||
minConst.type)).apply {
|
||||
minConst.type.toKotlinType())).apply {
|
||||
dispatchReceiver = irGet(forLoopInfo.bound)
|
||||
putValueArgument(0, minConst)
|
||||
}
|
||||
@@ -458,7 +466,7 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
||||
forLoopInfo.last.descriptor.type)
|
||||
|
||||
val check: IrExpression = irCall(comparingBuiltIn!!).apply {
|
||||
putValueArgument(0, irCallOp(compareTo, irGet(forLoopInfo.inductionVariable), irGet(forLoopInfo.last)))
|
||||
putValueArgument(0, irCallOp(compareTo.owner, irGet(forLoopInfo.inductionVariable), irGet(forLoopInfo.last)))
|
||||
putValueArgument(1, irInt(0))
|
||||
}
|
||||
|
||||
|
||||
+17
-13
@@ -41,8 +41,9 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -66,7 +67,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
|
||||
fun inline(irModule: IrModuleFragment): IrElement {
|
||||
val transformedModule = irModule.accept(this, null)
|
||||
DescriptorSubstitutorForExternalScope(globalSubstituteMap).run(transformedModule) // Transform calls to object that might be returned from inline function call.
|
||||
DescriptorSubstitutorForExternalScope(globalSubstituteMap, context).run(transformedModule) // Transform calls to object that might be returned from inline function call.
|
||||
return transformedModule
|
||||
}
|
||||
|
||||
@@ -157,8 +158,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
|
||||
irBuilder.run {
|
||||
val constructorDescriptor = delegatingConstructorCall.descriptor.original
|
||||
val constructorCall = irCall(delegatingConstructorCall.symbol,
|
||||
constructorDescriptor.typeParameters.associate { it to delegatingConstructorCall.getTypeArgument(it)!! }).apply {
|
||||
val constructorCall = irCall(delegatingConstructorCall.symbol, callee.type,
|
||||
constructorDescriptor.typeParameters.map { delegatingConstructorCall.getTypeArgument(it)!! }).apply {
|
||||
constructorDescriptor.valueParameters.forEach { putValueArgument(it, delegatingConstructorCall.getValueArgument(it)) }
|
||||
}
|
||||
val oldThis = delegatingConstructorCall.descriptor.constructedClass.thisAsReceiverParameter
|
||||
@@ -167,12 +168,12 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
nameHint = delegatingConstructorCall.descriptor.fqNameSafe.toString() + ".this"
|
||||
)
|
||||
statements[0] = newThis
|
||||
substituteMap[oldThis] = irGet(newThis.symbol)
|
||||
statements.add(irReturn(irGet(newThis.symbol)))
|
||||
substituteMap[oldThis] = irGet(newThis)
|
||||
statements.add(irReturn(irGet(newThis)))
|
||||
}
|
||||
}
|
||||
|
||||
val returnType = copyFunctionDeclaration.descriptor.returnType!! // Substituted return type.
|
||||
val returnType = copyFunctionDeclaration.returnType // Substituted return type.
|
||||
val sourceFileName = context.ir.originalModuleIndex.declarationToFile[caller.descriptor.original]?:""
|
||||
val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call".
|
||||
startOffset = startOffset,
|
||||
@@ -235,6 +236,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
val immediateCall = IrCallImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
type = expression.type,
|
||||
symbol = functionArgument.symbol,
|
||||
descriptor = functionArgument.descriptor).apply {
|
||||
functionParameters.forEach {
|
||||
@@ -290,7 +292,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
val substitutionContext = mutableMapOf<TypeConstructor, TypeProjection>()
|
||||
for (index in 0 until irCall.typeArgumentsCount) {
|
||||
val typeArgument = irCall.getTypeArgument(index) ?: continue
|
||||
substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument)
|
||||
substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument.toKotlinType())
|
||||
}
|
||||
return TypeSubstitutor.create(substitutionContext)
|
||||
}
|
||||
@@ -359,8 +361,9 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
}
|
||||
|
||||
val parametersWithDefaultToArgument = mutableListOf<ParameterToArgument>()
|
||||
functionDescriptor.valueParameters.forEach { parameterDescriptor -> // Iterate value parameter descriptors.
|
||||
val argument = valueArguments[parameterDescriptor.index] // Get appropriate argument from call site.
|
||||
irFunction.valueParameters.forEach { parameter -> // Iterate value parameters.
|
||||
val parameterDescriptor = parameter.descriptor as ValueParameterDescriptor
|
||||
val argument = valueArguments[parameterDescriptor.index] // Get appropriate argument from call site.
|
||||
when {
|
||||
argument != null -> { // Argument is good enough.
|
||||
parameterToArgument += ParameterToArgument( // Associate current parameter with the argument.
|
||||
@@ -381,8 +384,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
val emptyArray = IrVarargImpl(
|
||||
startOffset = irCall.startOffset,
|
||||
endOffset = irCall.endOffset,
|
||||
type = parameterDescriptor.type,
|
||||
varargElementType = parameterDescriptor.varargElementType!!
|
||||
type = parameter.type,
|
||||
varargElementType = parameter.varargElementType!!
|
||||
)
|
||||
parameterToArgument += ParameterToArgument(
|
||||
parameterDescriptor = parameterDescriptor,
|
||||
@@ -432,7 +435,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
val getVal = IrGetValueImpl( // Create new expression, representing access the new variable.
|
||||
startOffset = currentScope.irElement.startOffset,
|
||||
endOffset = currentScope.irElement.endOffset,
|
||||
symbol = createValueSymbol(newVariable.descriptor)
|
||||
type = newVariable.type,
|
||||
symbol = newVariable.symbol
|
||||
)
|
||||
substituteMap[parameterDescriptor] = getVal // Parameter will be replaced with the new variable.
|
||||
}
|
||||
|
||||
+25
-10
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.addChild
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.ir.util.createDispatchReceiverParameter
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
@@ -64,7 +64,7 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
|
||||
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement {
|
||||
initializers.add(IrBlockImpl(declaration.startOffset, declaration.endOffset,
|
||||
context.builtIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER, declaration.body.statements))
|
||||
context.irBuiltIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER, declaration.body.statements))
|
||||
return declaration
|
||||
}
|
||||
|
||||
@@ -72,11 +72,16 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
val initializer = declaration.initializer ?: return declaration
|
||||
val startOffset = initializer.startOffset
|
||||
val endOffset = initializer.endOffset
|
||||
initializers.add(IrBlockImpl(startOffset, endOffset, context.builtIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER,
|
||||
initializers.add(IrBlockImpl(startOffset, endOffset, context.irBuiltIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER,
|
||||
listOf(
|
||||
IrSetFieldImpl(startOffset, endOffset, declaration.symbol,
|
||||
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
|
||||
initializer.expression, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER))))
|
||||
IrGetValueImpl(
|
||||
startOffset, endOffset,
|
||||
irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol
|
||||
),
|
||||
initializer.expression,
|
||||
context.irBuiltIns.unitType,
|
||||
STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER))))
|
||||
declaration.initializer = null
|
||||
return declaration
|
||||
}
|
||||
@@ -109,9 +114,13 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
val initializer = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ANONYMOUS_INITIALIZER,
|
||||
initializerMethodDescriptor, IrBlockBodyImpl(startOffset, endOffset, initializers))
|
||||
initializerMethodDescriptor)
|
||||
|
||||
initializer.createParameterDeclarations()
|
||||
initializer.returnType = context.irBuiltIns.unitType
|
||||
initializer.body = IrBlockBodyImpl(startOffset, endOffset, initializers)
|
||||
|
||||
initializer.parent = irClass
|
||||
initializer.createDispatchReceiverParameter()
|
||||
|
||||
initializers.forEach {
|
||||
it.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
@@ -120,6 +129,7 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
return IrGetValueImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
initializer.dispatchReceiverParameter!!.type,
|
||||
initializer.dispatchReceiverParameter!!.symbol
|
||||
)
|
||||
} else {
|
||||
@@ -129,7 +139,7 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
})
|
||||
}
|
||||
|
||||
irClass.addChild(initializer)
|
||||
irClass.declarations.add(initializer)
|
||||
|
||||
return initializer.symbol
|
||||
}
|
||||
@@ -156,8 +166,13 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
} else {
|
||||
val startOffset = it.startOffset
|
||||
val endOffset = it.endOffset
|
||||
listOf(IrCallImpl(startOffset, endOffset, initializerMethodSymbol).apply {
|
||||
dispatchReceiver = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol)
|
||||
listOf(IrCallImpl(startOffset, endOffset,
|
||||
context.irBuiltIns.unitType, initializerMethodSymbol
|
||||
).apply {
|
||||
dispatchReceiver = IrGetValueImpl(
|
||||
startOffset, endOffset,
|
||||
irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+24
-17
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.util.addChild
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
|
||||
internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
@@ -57,7 +56,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
private fun createOuterThisField() {
|
||||
val field = context.specialDeclarationsFactory.getOuterThisField(classDescriptor)
|
||||
val field = context.specialDeclarationsFactory.getOuterThisField(irClass)
|
||||
outerThisFieldSymbol = field.symbol
|
||||
irClass.addChild(field)
|
||||
}
|
||||
@@ -78,12 +77,15 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}")
|
||||
val startOffset = irConstructor.startOffset
|
||||
val endOffset = irConstructor.endOffset
|
||||
val thisReceiver = irClass.thisReceiver!!
|
||||
val outerReceiver = irConstructor.dispatchReceiverParameter!!
|
||||
blockBody.statements.add(
|
||||
0,
|
||||
IrSetFieldImpl(
|
||||
startOffset, endOffset, outerThisFieldSymbol,
|
||||
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
|
||||
IrGetValueImpl(startOffset, endOffset, irConstructor.dispatchReceiverParameter!!.symbol)
|
||||
IrGetValueImpl(startOffset, endOffset, thisReceiver.type, thisReceiver.symbol),
|
||||
IrGetValueImpl(startOffset, endOffset, outerReceiver.type, outerReceiver.symbol),
|
||||
context.irBuiltIns.unitType
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -108,28 +110,28 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val origin = expression.origin
|
||||
|
||||
var irThis: IrExpression
|
||||
var innerClass: ClassDescriptor
|
||||
var innerClass: IrClass
|
||||
if (constructorSymbol == null || constructorSymbol.descriptor.constructedClass != classDescriptor) {
|
||||
innerClass = classDescriptor
|
||||
innerClass = irClass
|
||||
val currentIrFunction = currentFunction!!.scope.scopeOwnerSymbol.owner as IrFunction
|
||||
|
||||
val currentFunctionReceiver = currentIrFunction.dispatchReceiverParameter
|
||||
val thisSymbol = if (currentFunctionReceiver?.descriptor == irClass.thisReceiver!!.descriptor) {
|
||||
val thisParameter = if (currentFunctionReceiver?.descriptor == irClass.thisReceiver!!.descriptor) {
|
||||
currentFunctionReceiver
|
||||
} else {
|
||||
irClass.thisReceiver!!
|
||||
}.symbol
|
||||
}
|
||||
|
||||
irThis = IrGetValueImpl(startOffset, endOffset, thisSymbol, origin)
|
||||
irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin)
|
||||
} else {
|
||||
// For constructor we have outer class as dispatchReceiverParameter.
|
||||
innerClass = DescriptorUtils.getContainingClass(classDescriptor) ?:
|
||||
innerClass = irClass.parent as? IrClass ?:
|
||||
throw AssertionError("No containing class for inner class $classDescriptor")
|
||||
irThis = IrGetValueImpl(startOffset, endOffset,
|
||||
constructorSymbol.owner.dispatchReceiverParameter!!.symbol, origin)
|
||||
val thisParameter = constructorSymbol.owner.dispatchReceiverParameter!!
|
||||
irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin)
|
||||
}
|
||||
|
||||
while (innerClass != implicitThisClass) {
|
||||
while (innerClass.descriptor != implicitThisClass) {
|
||||
if (!innerClass.isInner) {
|
||||
// Captured 'this' unrelated to inner classes nesting hierarchy, leave it as is -
|
||||
// should be transformed by closures conversion.
|
||||
@@ -137,11 +139,16 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
val outerThisField = context.specialDeclarationsFactory.getOuterThisField(innerClass)
|
||||
irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField.symbol, irThis, origin)
|
||||
irThis = IrGetFieldImpl(
|
||||
startOffset, endOffset,
|
||||
outerThisField.symbol, outerThisField.type,
|
||||
irThis,
|
||||
origin
|
||||
)
|
||||
|
||||
val outer = innerClass.containingDeclaration
|
||||
innerClass = outer as? ClassDescriptor ?:
|
||||
throw AssertionError("Unexpected containing declaration for inner class $innerClass: $outer")
|
||||
val outer = innerClass.parent
|
||||
innerClass = outer as? IrClass ?:
|
||||
throw AssertionError("Unexpected containing declaration for inner class ${innerClass.descriptor}: $outer")
|
||||
}
|
||||
|
||||
return irThis
|
||||
|
||||
+129
-101
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.common.peek
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
@@ -26,12 +25,13 @@ import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructors
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.getObjCMethodInfo
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isReal
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
|
||||
@@ -41,10 +41,12 @@ import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -53,10 +55,6 @@ import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
internal class InteropLoweringPart1(val context: Context) : IrBuildingTransformer(context), FileLoweringPass {
|
||||
|
||||
@@ -83,7 +81,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
private fun IrBuilderWithScope.getObjCClass(classSymbol: IrClassSymbol): IrExpression {
|
||||
val classDescriptor = classSymbol.descriptor
|
||||
assert(!classDescriptor.isObjCMetaClass())
|
||||
return irCall(symbols.interopGetObjCClass, listOf(classDescriptor.defaultType))
|
||||
return irCall(symbols.interopGetObjCClass, symbols.nativePtrType, listOf(classSymbol.typeWithStarProjections))
|
||||
}
|
||||
|
||||
private val outerClasses = mutableListOf<IrClass>()
|
||||
@@ -131,7 +129,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
val superClass = irClass.getSuperClassNotAny()!!
|
||||
val superConstructors = superClass.constructors.filter {
|
||||
constructor.overridesConstructor(it)
|
||||
}
|
||||
}.toList()
|
||||
|
||||
val superConstructor = superConstructors.singleOrNull() ?: run {
|
||||
val annotation = context.interopBuiltIns.objCOverrideInit.name
|
||||
@@ -179,38 +177,42 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
initMethod.name,
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
SourceElement.NO_SOURCE
|
||||
).apply {
|
||||
val valueParameters = initMethod.valueParameters.map {
|
||||
ValueParameterDescriptorImpl(
|
||||
this,
|
||||
null,
|
||||
it.index,
|
||||
Annotations.EMPTY,
|
||||
it.name,
|
||||
it.type,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
it.varargElementType,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
}
|
||||
initialize(
|
||||
)
|
||||
|
||||
val valueParameters = initMethod.valueParameters.map {
|
||||
val descriptor = ValueParameterDescriptorImpl(
|
||||
resultDescriptor,
|
||||
null,
|
||||
irClass.descriptor.thisAsReceiverParameter,
|
||||
emptyList<TypeParameterDescriptor>(),
|
||||
valueParameters,
|
||||
irClass.defaultType,
|
||||
Modality.OPEN,
|
||||
Visibilities.PUBLIC
|
||||
it.index,
|
||||
Annotations.EMPTY,
|
||||
it.name,
|
||||
it.descriptor.type,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
it.varargElementType?.toKotlinType(),
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
it.copy(descriptor)
|
||||
}
|
||||
resultDescriptor.initialize(
|
||||
null,
|
||||
irClass.descriptor.thisAsReceiverParameter,
|
||||
emptyList<TypeParameterDescriptor>(),
|
||||
valueParameters.map { it.descriptor as ValueParameterDescriptor },
|
||||
irClass.descriptor.defaultType,
|
||||
Modality.OPEN,
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
|
||||
return IrFunctionImpl(
|
||||
constructor.startOffset, constructor.endOffset, OVERRIDING_INITIALIZER_BY_CONSTRUCTOR,
|
||||
resultDescriptor
|
||||
).also { result ->
|
||||
result.createParameterDeclarations()
|
||||
result.returnType = irClass.defaultType
|
||||
result.parent = irClass
|
||||
result.createDispatchReceiverParameter()
|
||||
result.valueParameters += valueParameters
|
||||
|
||||
result.overriddenSymbols.add(initMethod.symbol)
|
||||
result.descriptor.overriddenDescriptors = listOf(initMethod.descriptor)
|
||||
@@ -218,10 +220,10 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
result.body = context.createIrBuilder(result.symbol).irBlockBody(result) {
|
||||
+irReturn(
|
||||
irCall(symbols.interopObjCObjectInitBy, listOf(irClass.defaultType)).apply {
|
||||
extensionReceiver = irGet(result.dispatchReceiverParameter!!.symbol)
|
||||
putValueArgument(0, irCall(constructor.symbol).also {
|
||||
extensionReceiver = irGet(result.dispatchReceiverParameter!!)
|
||||
putValueArgument(0, irCall(constructor).also {
|
||||
result.valueParameters.forEach { parameter ->
|
||||
it.putValueArgument(parameter.index, irGet(parameter.symbol))
|
||||
it.putValueArgument(parameter.index, irGet(parameter))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -236,9 +238,9 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
IrDeclarationOriginImpl("OVERRIDING_INITIALIZER_BY_CONSTRUCTOR")
|
||||
|
||||
private fun IrConstructor.overridesConstructor(other: IrConstructor): Boolean {
|
||||
return this.valueParameters.size == other.valueParameters.size &&
|
||||
this.valueParameters.all {
|
||||
val otherParameter = other.valueParameters[it.index]
|
||||
return this.descriptor.valueParameters.size == other.descriptor.valueParameters.size &&
|
||||
this.descriptor.valueParameters.all {
|
||||
val otherParameter = other.descriptor.valueParameters[it.index]
|
||||
it.name == otherParameter.name && it.type == otherParameter.type
|
||||
}
|
||||
}
|
||||
@@ -260,10 +262,10 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
}
|
||||
}
|
||||
|
||||
val returnType = function.descriptor.returnType!!
|
||||
val returnType = function.returnType
|
||||
|
||||
if (!returnType.isUnit()) {
|
||||
context.reportCompilationError("Unexpected $action method return type: $returnType\n" +
|
||||
context.reportCompilationError("Unexpected $action method return type: ${returnType.toKotlinType()}\n" +
|
||||
"Only 'Unit' is supported here",
|
||||
currentFile, function
|
||||
)
|
||||
@@ -303,7 +305,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
private fun getMethodSignatureEncoding(function: IrFunction): String {
|
||||
assert(function.extensionReceiverParameter == null)
|
||||
assert(function.valueParameters.all { it.type.isObjCObjectType() })
|
||||
assert(function.descriptor.returnType!!.isUnit())
|
||||
assert(function.returnType.isUnit())
|
||||
|
||||
// Note: these values are valid for x86_64 and arm64.
|
||||
return when (function.valueParameters.size) {
|
||||
@@ -319,10 +321,10 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
private fun generateFunctionImp(selector: String, function: IrFunction): IrSimpleFunction {
|
||||
val signatureEncoding = getMethodSignatureEncoding(function)
|
||||
|
||||
val returnType = function.descriptor.returnType!!
|
||||
val returnType = function.returnType
|
||||
assert(returnType.isUnit())
|
||||
|
||||
val nativePtrType = context.builtIns.nativePtr.defaultType
|
||||
val nativePtrType = context.ir.symbols.nativePtrType
|
||||
|
||||
val parameterTypes = mutableListOf(nativePtrType) // id self
|
||||
|
||||
@@ -353,7 +355,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
index,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier("p$index"),
|
||||
it,
|
||||
it.toKotlinType(),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
@@ -366,7 +368,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
null, null,
|
||||
emptyList(),
|
||||
valueParameters,
|
||||
returnType,
|
||||
function.descriptor.returnType,
|
||||
Modality.FINAL,
|
||||
Visibilities.PRIVATE
|
||||
)
|
||||
@@ -375,20 +377,33 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
function.startOffset, function.endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
newDescriptor
|
||||
).apply { createParameterDeclarations() }
|
||||
).apply {
|
||||
this.returnType = function.returnType
|
||||
|
||||
parameterTypes.mapIndexedTo(this.valueParameters) { index, it ->
|
||||
IrValueParameterImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
descriptor.valueParameters[index],
|
||||
it,
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val builder = context.createIrBuilder(newFunction.symbol)
|
||||
newFunction.body = builder.irBlockBody(newFunction) {
|
||||
+irCall(function.symbol).apply {
|
||||
+irCall(function).apply {
|
||||
dispatchReceiver = interpretObjCPointer(
|
||||
irGet(newFunction.valueParameters[0].symbol),
|
||||
irGet(newFunction.valueParameters[0]),
|
||||
function.dispatchReceiverParameter!!.type
|
||||
)
|
||||
|
||||
function.valueParameters.forEachIndexed { index, parameter ->
|
||||
putValueArgument(index,
|
||||
interpretObjCPointer(
|
||||
irGet(newFunction.valueParameters[index + 2].symbol),
|
||||
irGet(newFunction.valueParameters[index + 2]),
|
||||
parameter.type
|
||||
)
|
||||
)
|
||||
@@ -399,8 +414,8 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
return newFunction
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.interpretObjCPointer(expression: IrExpression, type: KotlinType): IrExpression {
|
||||
val callee: IrFunctionSymbol = if (TypeUtils.isNullableType(type)) {
|
||||
private fun IrBuilderWithScope.interpretObjCPointer(expression: IrExpression, type: IrType): IrExpression {
|
||||
val callee: IrFunctionSymbol = if (type.containsNull()) {
|
||||
symbols.interopInterpretObjCPointerOrNull
|
||||
} else {
|
||||
symbols.interopInterpretObjCPointer
|
||||
@@ -534,7 +549,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
val initCall = builder.genLoweredObjCMethodCall(
|
||||
initMethodInfo,
|
||||
superQualifier = symbolTable.referenceClass(expression.descriptor.constructedClass),
|
||||
receiver = builder.getRawPtr(builder.irGet(constructedClass.thisReceiver!!.symbol)),
|
||||
receiver = builder.getRawPtr(builder.irGet(constructedClass.thisReceiver!!)),
|
||||
arguments = initMethod.valueParameters.map { expression.getValueArgument(it)!! }
|
||||
)
|
||||
|
||||
@@ -544,10 +559,17 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
|
||||
return builder.irBlock(expression) {
|
||||
// Required for the IR to be valid, will be ignored in codegen:
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset, superConstructor, superConstructor.descriptor)
|
||||
+IrDelegatingConstructorCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
superConstructor,
|
||||
superConstructor.descriptor,
|
||||
0
|
||||
)
|
||||
|
||||
+irCall(symbols.interopObjCObjectSuperInitCheck).apply {
|
||||
extensionReceiver = irGet(constructedClass.thisReceiver!!.symbol)
|
||||
extensionReceiver = irGet(constructedClass.thisReceiver!!)
|
||||
putValueArgument(0, initCall)
|
||||
}
|
||||
}
|
||||
@@ -560,10 +582,10 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
receiver: IrExpression, arguments: List<IrExpression>): IrExpression {
|
||||
|
||||
val superClass = superQualifier?.let { getObjCClass(it) } ?:
|
||||
irCall(symbols.getNativeNullPtr)
|
||||
irCall(symbols.getNativeNullPtr, symbols.nativePtrType)
|
||||
|
||||
val bridge = symbolTable.referenceSimpleFunction(info.bridge)
|
||||
return irCall(bridge).apply {
|
||||
return irCall(bridge, symbolTable.translateErased(info.bridge.returnType!!)).apply {
|
||||
putValueArgument(0, superClass)
|
||||
putValueArgument(1, receiver)
|
||||
|
||||
@@ -646,18 +668,16 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
return when (descriptor) {
|
||||
context.interopBuiltIns.typeOf -> {
|
||||
val typeArgument = expression.getSingleTypeArgument()
|
||||
val classDescriptor = TypeUtils.getClassDescriptor(typeArgument)
|
||||
val classSymbol = typeArgument.classifierOrNull as? IrClassSymbol
|
||||
|
||||
if (classDescriptor == null) {
|
||||
if (classSymbol == null) {
|
||||
expression
|
||||
} else {
|
||||
val companionObjectDescriptor = classDescriptor.companionObjectDescriptor ?:
|
||||
val classDescriptor = classSymbol.descriptor
|
||||
val companionObject = classDescriptor.companionObjectDescriptor ?:
|
||||
error("native variable class $classDescriptor must have the companion object")
|
||||
|
||||
IrGetObjectValueImpl(
|
||||
expression.startOffset, expression.endOffset, companionObjectDescriptor.defaultType,
|
||||
symbolTable.referenceClass(companionObjectDescriptor)
|
||||
)
|
||||
builder.at(expression).irGetObject(symbolTable.referenceClass(companionObject))
|
||||
}
|
||||
}
|
||||
else -> expression
|
||||
@@ -674,14 +694,14 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
val initCall = genLoweredObjCMethodCall(
|
||||
initMethodInfo,
|
||||
superQualifier = null,
|
||||
receiver = irGet(allocated.symbol),
|
||||
receiver = irGet(allocated),
|
||||
arguments = arguments
|
||||
)
|
||||
|
||||
+IrTryImpl(startOffset, endOffset, initCall.type).apply {
|
||||
tryResult = initCall
|
||||
finallyExpression = irCall(symbols.interopObjCRelease).apply {
|
||||
putValueArgument(0, irGet(allocated.symbol)) // Balance pointer retained by alloc.
|
||||
putValueArgument(0, irGet(allocated)) // Balance pointer retained by alloc.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -770,8 +790,8 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
}
|
||||
|
||||
val targetSymbol = irCallableReference.symbol
|
||||
val target = targetSymbol.descriptor
|
||||
val signatureTypes = target.allParameters.map { it.type } + target.returnType!!
|
||||
val target = targetSymbol.owner
|
||||
val signatureTypes = target.allParameters.map { it.type } + target.returnType
|
||||
|
||||
signatureTypes.forEachIndexed { index, type ->
|
||||
type.ensureSupportedInCallbacks(
|
||||
@@ -781,9 +801,10 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
}
|
||||
|
||||
descriptor.typeParameters.forEachIndexed { index, typeParameterDescriptor ->
|
||||
val typeArgument = expression.getTypeArgument(typeParameterDescriptor)!!
|
||||
val signatureType = signatureTypes[index]
|
||||
if (typeArgument != signatureType) {
|
||||
val typeArgument = expression.getTypeArgument(typeParameterDescriptor)!!.toKotlinType()
|
||||
val signatureType = signatureTypes[index].toKotlinType()
|
||||
if (typeArgument.constructor != signatureType.constructor ||
|
||||
typeArgument.isMarkedNullable != signatureType.isMarkedNullable) {
|
||||
context.reportCompilationError(
|
||||
"C function signature element mismatch: expected '$signatureType', got '$typeArgument'",
|
||||
irFile, expression
|
||||
@@ -794,8 +815,8 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
IrFunctionReferenceImpl(
|
||||
builder.startOffset, builder.endOffset,
|
||||
expression.type,
|
||||
targetSymbol, target,
|
||||
typeArguments = null)
|
||||
targetSymbol, target.descriptor,
|
||||
typeArgumentsCount = 0)
|
||||
}
|
||||
|
||||
interop.scheduleFunction -> {
|
||||
@@ -812,9 +833,9 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
val target = targetSymbol.descriptor
|
||||
val jobPointer = IrFunctionReferenceImpl(
|
||||
builder.startOffset, builder.endOffset,
|
||||
interop.cPointer.defaultType,
|
||||
symbols.scheduleImpl.owner.valueParameters[3].type,
|
||||
targetSymbol, target,
|
||||
typeArguments = null)
|
||||
typeArgumentsCount = 0)
|
||||
|
||||
builder.irCall(symbols.scheduleImpl).apply {
|
||||
putValueArgument(0, expression.dispatchReceiver)
|
||||
@@ -827,33 +848,36 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
interop.signExtend, interop.narrow -> {
|
||||
|
||||
val integerTypePredicates = arrayOf(
|
||||
KotlinBuiltIns::isByte, KotlinBuiltIns::isShort, KotlinBuiltIns::isInt, KotlinBuiltIns::isLong
|
||||
IrType::isByte, IrType::isShort, IrType::isInt, IrType::isLong
|
||||
)
|
||||
|
||||
val receiver = expression.extensionReceiver!!
|
||||
val typeOperand = expression.getSingleTypeArgument()
|
||||
val kotlinTypeOperand = typeOperand.toKotlinType()
|
||||
|
||||
val receiverTypeIndex = integerTypePredicates.indexOfFirst { it(receiver.type) }
|
||||
val typeOperandIndex = integerTypePredicates.indexOfFirst { it(typeOperand) }
|
||||
|
||||
val receiverKotlinType = receiver.type.toKotlinType()
|
||||
|
||||
if (receiverTypeIndex == -1) {
|
||||
context.reportCompilationError("Receiver's type ${receiver.type} is not an integer type",
|
||||
context.reportCompilationError("Receiver's type $receiverKotlinType is not an integer type",
|
||||
irFile, receiver)
|
||||
}
|
||||
|
||||
if (typeOperandIndex == -1) {
|
||||
context.reportCompilationError("Type argument $typeOperand is not an integer type",
|
||||
context.reportCompilationError("Type argument $kotlinTypeOperand is not an integer type",
|
||||
irFile, expression)
|
||||
}
|
||||
|
||||
when (descriptor) {
|
||||
interop.signExtend -> if (receiverTypeIndex > typeOperandIndex) {
|
||||
context.reportCompilationError("unable to sign extend ${receiver.type} to $typeOperand",
|
||||
context.reportCompilationError("unable to sign extend $receiverKotlinType to $kotlinTypeOperand",
|
||||
irFile, expression)
|
||||
}
|
||||
|
||||
interop.narrow -> if (receiverTypeIndex < typeOperandIndex) {
|
||||
context.reportCompilationError("unable to narrow ${receiver.type} to $typeOperand",
|
||||
context.reportCompilationError("unable to narrow $receiverKotlinType to $kotlinTypeOperand",
|
||||
irFile, expression)
|
||||
}
|
||||
|
||||
@@ -863,8 +887,12 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
val receiverClass = symbols.integerClasses.single {
|
||||
receiver.type.isSubtypeOf(it.owner.defaultType)
|
||||
}
|
||||
val targetClass = symbols.integerClasses.single {
|
||||
typeOperand.isSubtypeOf(it.owner.defaultType)
|
||||
}
|
||||
|
||||
val conversionSymbol = receiverClass.functions.single {
|
||||
it.descriptor.name == Name.identifier("to$typeOperand")
|
||||
it.descriptor.name == Name.identifier("to${targetClass.owner.name}")
|
||||
}
|
||||
|
||||
builder.irCall(conversionSymbol).apply {
|
||||
@@ -880,16 +908,16 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
|
||||
returnType.checkCTypeNullability(::reportError)
|
||||
|
||||
val invokeImpl = symbols.interopInvokeImpls[TypeUtils.getClassDescriptor(returnType)] ?:
|
||||
val invokeImpl = symbols.interopInvokeImpls[returnType.getClass()?.descriptor] ?:
|
||||
context.reportCompilationError(
|
||||
"Invocation of C function pointer with return type '$returnType' is not supported yet",
|
||||
"Invocation of C function pointer with return type '${returnType.toKotlinType()}' is not supported yet",
|
||||
irFile, expression
|
||||
)
|
||||
|
||||
builder.irCall(invokeImpl).apply {
|
||||
putValueArgument(0, expression.extensionReceiver)
|
||||
|
||||
val varargParameter = invokeImpl.descriptor.valueParameters[1]
|
||||
val varargParameter = invokeImpl.owner.valueParameters[1]
|
||||
val varargArgument = IrVarargImpl(
|
||||
startOffset, endOffset, varargParameter.type, varargParameter.varargElementType!!
|
||||
).apply {
|
||||
@@ -897,7 +925,7 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
this.addElement(expression.getValueArgument(it)!!)
|
||||
}
|
||||
}
|
||||
putValueArgument(varargParameter, varargArgument)
|
||||
putValueArgument(varargParameter.index, varargArgument)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -928,31 +956,31 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinType.ensureSupportedInCallbacks(isReturnType: Boolean, reportError: (String) -> Nothing) {
|
||||
private fun IrType.ensureSupportedInCallbacks(isReturnType: Boolean, reportError: (String) -> Nothing) {
|
||||
this.checkCTypeNullability(reportError)
|
||||
|
||||
if (isReturnType && KotlinBuiltIns.isUnit(this)) {
|
||||
if (isReturnType && this.isUnit()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (KotlinBuiltIns.isPrimitiveType(this)) {
|
||||
if (this.isPrimitiveType()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (TypeUtils.getClassDescriptor(this) == interop.cPointer) {
|
||||
if (this.getClass()?.descriptor == interop.cPointer) {
|
||||
return
|
||||
}
|
||||
|
||||
reportError("Type $this is not supported in callback signature")
|
||||
reportError("Type ${this.toKotlinType()} is not supported in callback signature")
|
||||
}
|
||||
|
||||
private fun KotlinType.checkCTypeNullability(reportError: (String) -> Nothing) {
|
||||
if (KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType(this) && this.isMarkedNullable) {
|
||||
reportError("Type $this must not be nullable when used in C function signature")
|
||||
private fun IrType.checkCTypeNullability(reportError: (String) -> Nothing) {
|
||||
if (this.isNullablePrimitiveType()) {
|
||||
reportError("Type ${this.toKotlinType()} must not be nullable when used in C function signature")
|
||||
}
|
||||
|
||||
if (TypeUtils.getClassDescriptor(this) == interop.cPointer && !this.isMarkedNullable) {
|
||||
reportError("Type $this must be nullable when used in C function signature")
|
||||
if (this.getClass() == interop.cPointer && !this.isSimpleTypeWithQuestionMark) {
|
||||
reportError("Type ${this.toKotlinType()} must be nullable when used in C function signature")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -986,15 +1014,15 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrCall.getSingleTypeArgument(): KotlinType {
|
||||
private fun IrCall.getSingleTypeArgument(): IrType {
|
||||
val typeParameter = descriptor.original.typeParameters.single()
|
||||
return getTypeArgument(typeParameter)!!
|
||||
}
|
||||
|
||||
private fun IrBuilder.irFloat(value: Float) =
|
||||
IrConstImpl.float(startOffset, endOffset, context.builtIns.floatType, value)
|
||||
IrConstImpl.float(startOffset, endOffset, context.irBuiltIns.floatType, value)
|
||||
|
||||
private fun IrBuilder.irDouble(value: Double) =
|
||||
IrConstImpl.double(startOffset, endOffset, context.builtIns.doubleType, value)
|
||||
IrConstImpl.double(startOffset, endOffset, context.irBuiltIns.doubleType, value)
|
||||
|
||||
private fun Annotations.hasAnnotation(descriptor: ClassDescriptor) = this.hasAnnotation(descriptor.fqNameSafe)
|
||||
|
||||
+36
-27
@@ -21,23 +21,23 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||
@@ -59,6 +59,21 @@ internal class LateinitLowering(
|
||||
private val isInitializedGetterDescriptor = isInitializedPropertyDescriptor.getter!!
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
val lateinitPropertyToField = mutableMapOf<PropertyDescriptor, IrField>()
|
||||
irFile.acceptVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitProperty(declaration: IrProperty) {
|
||||
super.visitProperty(declaration)
|
||||
|
||||
if (declaration.isLateinit && declaration.descriptor.kind.isReal) {
|
||||
lateinitPropertyToField[declaration.descriptor] = declaration.backingField!!
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) {
|
||||
|
||||
override fun visitVariable(declaration: IrVariable): IrStatement {
|
||||
@@ -85,10 +100,10 @@ internal class LateinitLowering(
|
||||
return irBlock(expression) {
|
||||
// TODO: do data flow analysis to check if value is proved to be not-null.
|
||||
+irIfThen(
|
||||
irEqualsNull(irGet(symbol)),
|
||||
irEqualsNull(irGet(expression.type, symbol)),
|
||||
throwUninitializedPropertyAccessException(symbol)
|
||||
)
|
||||
+irGet(symbol)
|
||||
+irGet(expression.type, symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,19 +116,13 @@ internal class LateinitLowering(
|
||||
|
||||
val propertyReference = expression.extensionReceiver!! as IrPropertyReference
|
||||
assert(propertyReference.extensionReceiver == null, { "'lateinit' modifier is not allowed on extension properties" })
|
||||
// TODO: Take propertyReference.fieldSymbol as soon as it will show up in IR.
|
||||
val propertyDescriptor = propertyReference.descriptor.resolveFakeOverride().original
|
||||
|
||||
val type = propertyDescriptor.type
|
||||
assert(!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" })
|
||||
builder.at(expression).run {
|
||||
@Suppress("DEPRECATION")
|
||||
val fieldValue = IrGetFieldImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
propertyDescriptor,
|
||||
propertyReference.dispatchReceiver
|
||||
)
|
||||
val field = lateinitPropertyToField[propertyDescriptor]!!
|
||||
val fieldValue = irGetField(propertyReference.dispatchReceiver, field)
|
||||
return irNotEquals(fieldValue, irNull())
|
||||
}
|
||||
}
|
||||
@@ -125,7 +134,7 @@ internal class LateinitLowering(
|
||||
return declaration
|
||||
|
||||
val backingField = declaration.backingField!!
|
||||
transformGetter(backingField.symbol, declaration.getter!!)
|
||||
transformGetter(backingField, declaration.getter!!)
|
||||
|
||||
assert(backingField.initializer == null, { "'lateinit' modifier is not allowed for properties with initializer" })
|
||||
val irBuilder = context.createIrBuilder(backingField.symbol, declaration.startOffset, declaration.endOffset)
|
||||
@@ -136,20 +145,20 @@ internal class LateinitLowering(
|
||||
return declaration
|
||||
}
|
||||
|
||||
private fun transformGetter(backingFieldSymbol: IrFieldSymbol, getter: IrFunction) {
|
||||
val type = backingFieldSymbol.descriptor.type
|
||||
private fun transformGetter(backingField: IrField, getter: IrFunction) {
|
||||
val type = backingField.descriptor.type
|
||||
assert(!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" })
|
||||
val irBuilder = context.createIrBuilder(getter.symbol, getter.startOffset, getter.endOffset)
|
||||
irBuilder.run {
|
||||
getter.body = irBlockBody {
|
||||
val resultVar = irTemporary(
|
||||
irGetField(getter.dispatchReceiverParameter?.let { irGet(it.symbol) }, backingFieldSymbol)
|
||||
irGetField(getter.dispatchReceiverParameter?.let { irGet(it) }, backingField)
|
||||
)
|
||||
+irIfThenElse(
|
||||
context.builtIns.nothingType,
|
||||
irNotEquals(irGet(resultVar.symbol), irNull()),
|
||||
irReturn(irGet(resultVar.symbol)),
|
||||
throwUninitializedPropertyAccessException(backingFieldSymbol)
|
||||
context.irBuiltIns.nothingType,
|
||||
irNotEquals(irGet(resultVar), irNull()),
|
||||
irReturn(irGet(resultVar)),
|
||||
throwUninitializedPropertyAccessException(backingField.symbol)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -158,14 +167,14 @@ internal class LateinitLowering(
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.throwUninitializedPropertyAccessException(backingFieldSymbol: IrSymbol) =
|
||||
irCall(throwErrorFunction).apply {
|
||||
irCall(throwErrorFunction, context.irBuiltIns.nothingType).apply {
|
||||
if (generateParameterNameInAssertion) {
|
||||
putValueArgument(
|
||||
0,
|
||||
IrConstImpl.string(
|
||||
startOffset,
|
||||
endOffset,
|
||||
context.builtIns.stringType,
|
||||
context.irBuiltIns.stringType,
|
||||
backingFieldSymbol.descriptor.name.asString()
|
||||
)
|
||||
)
|
||||
|
||||
-754
@@ -1,754 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.lower.Closure
|
||||
import org.jetbrains.kotlin.backend.common.lower.ClosureAnnotator
|
||||
import org.jetbrains.kotlin.backend.common.lower.callsSuper
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.util.addChild
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parents
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.util.*
|
||||
|
||||
// TODO: Remove as soon as its version is fixed in common code.
|
||||
class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContainerLoweringPass {
|
||||
|
||||
private object DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE :
|
||||
IrDeclarationOriginImpl("FIELD_FOR_CAPTURED_VALUE") {}
|
||||
|
||||
private object STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE :
|
||||
IrStatementOriginImpl("INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE") {}
|
||||
|
||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||
if (irDeclarationContainer is IrDeclaration &&
|
||||
irDeclarationContainer.descriptor.parents.any { it is CallableDescriptor }) {
|
||||
|
||||
// Lowering of non-local declarations handles all local declarations inside.
|
||||
// This declaration is local and shouldn't be considered.
|
||||
return
|
||||
}
|
||||
|
||||
// Continuous numbering across all declarations in the container.
|
||||
lambdasCount = 0
|
||||
|
||||
irDeclarationContainer.declarations.transformFlat { memberDeclaration ->
|
||||
// TODO: may be do the opposite - specify the list of IR elements which need not to be transformed
|
||||
when (memberDeclaration) {
|
||||
is IrFunction -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||
is IrProperty -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||
is IrField -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||
is IrAnonymousInitializer -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var lambdasCount = 0
|
||||
|
||||
private abstract class LocalContext {
|
||||
/**
|
||||
* @return the expression to get the value for given descriptor, or `null` if [IrGetValue] should be used.
|
||||
*/
|
||||
abstract fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression?
|
||||
}
|
||||
|
||||
private abstract class LocalContextWithClosureAsParameters : LocalContext() {
|
||||
|
||||
abstract val declaration: IrFunction
|
||||
open val descriptor: FunctionDescriptor
|
||||
get() = declaration.descriptor
|
||||
|
||||
abstract val transformedDescriptor: FunctionDescriptor
|
||||
abstract val transformedDeclaration: IrFunction
|
||||
|
||||
val capturedValueToParameter: MutableMap<ValueDescriptor, IrValueParameterSymbol> = HashMap()
|
||||
|
||||
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
|
||||
val newSymbol = capturedValueToParameter[descriptor] ?: return null
|
||||
|
||||
return IrGetValueImpl(startOffset, endOffset, newSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
private class LocalFunctionContext(override val declaration: IrFunction) : LocalContextWithClosureAsParameters() {
|
||||
lateinit var closure: Closure
|
||||
|
||||
override lateinit var transformedDescriptor: FunctionDescriptor
|
||||
override lateinit var transformedDeclaration: IrSimpleFunction
|
||||
|
||||
var index: Int = -1
|
||||
|
||||
override fun toString(): String =
|
||||
"LocalFunctionContext for $descriptor"
|
||||
}
|
||||
|
||||
private class LocalClassConstructorContext(override val declaration: IrConstructor) : LocalContextWithClosureAsParameters() {
|
||||
override val descriptor: ClassConstructorDescriptor
|
||||
get() = declaration.descriptor
|
||||
|
||||
override lateinit var transformedDescriptor: ClassConstructorDescriptor
|
||||
override lateinit var transformedDeclaration: IrConstructor
|
||||
|
||||
override fun toString(): String =
|
||||
"LocalClassConstructorContext for $descriptor"
|
||||
}
|
||||
|
||||
private class LocalClassContext(val declaration: IrClass) : LocalContext() {
|
||||
val descriptor: ClassDescriptor
|
||||
get() = declaration.descriptor
|
||||
|
||||
lateinit var closure: Closure
|
||||
|
||||
val capturedValueToField: MutableMap<ValueDescriptor, IrField> = HashMap()
|
||||
|
||||
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
|
||||
val field = capturedValueToField[descriptor] ?: return null
|
||||
|
||||
return IrGetFieldImpl(startOffset, endOffset, field.symbol,
|
||||
receiver = IrGetValueImpl(startOffset, endOffset, declaration.thisReceiver!!.symbol)
|
||||
)
|
||||
}
|
||||
|
||||
override fun toString(): String =
|
||||
"LocalClassContext for ${descriptor}"
|
||||
}
|
||||
|
||||
private class LocalClassMemberContext(val member: IrFunction, val classContext: LocalClassContext) : LocalContext() {
|
||||
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
|
||||
val field = classContext.capturedValueToField[descriptor] ?: return null
|
||||
|
||||
return IrGetFieldImpl(startOffset, endOffset, field.symbol,
|
||||
receiver = IrGetValueImpl(startOffset, endOffset, member.dispatchReceiverParameter!!.symbol)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private inner class LocalDeclarationsTransformer(val memberDeclaration: IrDeclaration) {
|
||||
val localFunctions: MutableMap<FunctionDescriptor, LocalFunctionContext> = LinkedHashMap()
|
||||
val localClasses: MutableMap<ClassDescriptor, LocalClassContext> = LinkedHashMap()
|
||||
val localClassConstructors: MutableMap<ClassConstructorDescriptor, LocalClassConstructorContext> = LinkedHashMap()
|
||||
|
||||
val transformedDeclarations = mutableMapOf<DeclarationDescriptor, IrSymbol>()
|
||||
|
||||
val FunctionDescriptor.transformed: IrFunctionSymbol?
|
||||
get() = transformedDeclarations[this] as IrFunctionSymbol?
|
||||
|
||||
val oldParameterToNew: MutableMap<ParameterDescriptor, IrValueParameterSymbol> = HashMap()
|
||||
val newParameterToOld: MutableMap<ParameterDescriptor, ParameterDescriptor> = HashMap()
|
||||
val newParameterToCaptured: MutableMap<ValueParameterDescriptor, IrValueSymbol> = HashMap()
|
||||
|
||||
fun lowerLocalDeclarations(): List<IrDeclaration>? {
|
||||
collectLocalDeclarations()
|
||||
if (localFunctions.isEmpty() && localClasses.isEmpty()) return null
|
||||
|
||||
collectClosures()
|
||||
|
||||
transformDescriptors()
|
||||
|
||||
rewriteDeclarations()
|
||||
|
||||
val result = collectRewrittenDeclarations()
|
||||
result.forEach { it.parent = memberDeclaration.parent }
|
||||
return result
|
||||
}
|
||||
|
||||
private fun collectRewrittenDeclarations(): ArrayList<IrDeclaration> =
|
||||
ArrayList<IrDeclaration>(localFunctions.size + localClasses.size + 1).apply {
|
||||
add(memberDeclaration)
|
||||
|
||||
localFunctions.values.mapTo(this) {
|
||||
val original = it.declaration
|
||||
it.transformedDeclaration.apply {
|
||||
this.body = original.body
|
||||
|
||||
original.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
|
||||
val body = original.getDefault(argument)!!
|
||||
oldParameterToNew[argument]!!.owner.defaultValue = body
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
localClasses.values.mapTo(this) {
|
||||
it.declaration
|
||||
}
|
||||
}
|
||||
|
||||
private inner class FunctionBodiesRewriter(val localContext: LocalContext?) : IrElementTransformerVoid() {
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
if (declaration.descriptor in localClasses) {
|
||||
// Replace local class definition with an empty composite.
|
||||
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType)
|
||||
} else {
|
||||
return super.visitClass(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
if (declaration.descriptor in localFunctions) {
|
||||
// Replace local function definition with an empty composite.
|
||||
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType)
|
||||
} else {
|
||||
if (localContext is LocalClassContext && declaration.parent == localContext.declaration) {
|
||||
return declaration.apply {
|
||||
val classMemberLocalContext = LocalClassMemberContext(declaration, localContext)
|
||||
transformChildrenVoid(FunctionBodiesRewriter(classMemberLocalContext))
|
||||
}
|
||||
} else {
|
||||
return super.visitFunction(declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor): IrStatement {
|
||||
// Body is transformed separately. See loop over constructors in rewriteDeclarations().
|
||||
|
||||
val constructorContext = localClassConstructors[declaration.descriptor]
|
||||
if (constructorContext != null) {
|
||||
return constructorContext.transformedDeclaration.apply {
|
||||
this.parent = declaration.parent
|
||||
this.body = declaration.body!!
|
||||
|
||||
declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
|
||||
val body = declaration.getDefault(argument)!!
|
||||
oldParameterToNew[argument]!!.owner.defaultValue = body
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return super.visitConstructor(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
val descriptor = expression.descriptor
|
||||
|
||||
localContext?.irGet(expression.startOffset, expression.endOffset, descriptor)?.let {
|
||||
return it
|
||||
}
|
||||
|
||||
oldParameterToNew[descriptor]?.let {
|
||||
return IrGetValueImpl(expression.startOffset, expression.endOffset, it)
|
||||
}
|
||||
|
||||
return expression
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val oldCallee = expression.descriptor.original
|
||||
val newCallee = oldCallee.transformed ?: return expression
|
||||
|
||||
val newCall = createNewCall(expression, newCallee).fillArguments(expression)
|
||||
|
||||
return newCall
|
||||
}
|
||||
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val oldCallee = expression.descriptor.original
|
||||
val newCallee = transformedDeclarations[oldCallee] as IrConstructorSymbol? ?: return expression
|
||||
|
||||
val newExpression = IrDelegatingConstructorCallImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
newCallee,
|
||||
newCallee.descriptor,
|
||||
remapTypeArguments(expression, newCallee.descriptor)
|
||||
).fillArguments(expression)
|
||||
|
||||
return newExpression
|
||||
}
|
||||
|
||||
private fun <T : IrMemberAccessExpression> T.fillArguments(oldExpression: IrMemberAccessExpression): T {
|
||||
|
||||
mapValueParameters { newValueParameterDescriptor ->
|
||||
val oldParameter = newParameterToOld[newValueParameterDescriptor]
|
||||
|
||||
if (oldParameter != null) {
|
||||
oldExpression.getValueArgument(oldParameter as ValueParameterDescriptor)
|
||||
} else {
|
||||
// The callee expects captured value as argument.
|
||||
val capturedValueSymbol =
|
||||
newParameterToCaptured[newValueParameterDescriptor] ?:
|
||||
throw AssertionError("Non-mapped parameter $newValueParameterDescriptor")
|
||||
|
||||
val capturedValueDescriptor = capturedValueSymbol.descriptor
|
||||
localContext?.irGet(
|
||||
oldExpression.startOffset, oldExpression.endOffset,
|
||||
capturedValueDescriptor
|
||||
) ?:
|
||||
// Captured value is directly available for the caller.
|
||||
IrGetValueImpl(oldExpression.startOffset, oldExpression.endOffset,
|
||||
oldParameterToNew[capturedValueDescriptor] ?: capturedValueSymbol)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dispatchReceiver = oldExpression.dispatchReceiver
|
||||
extensionReceiver = oldExpression.extensionReceiver
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val oldCallee = expression.descriptor.original
|
||||
val newCallee = oldCallee.transformed ?: return expression
|
||||
|
||||
val newCallableReference = IrFunctionReferenceImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type, // TODO functional type for transformed descriptor
|
||||
newCallee,
|
||||
newCallee.descriptor,
|
||||
remapTypeArguments(expression, newCallee.descriptor),
|
||||
expression.origin
|
||||
).fillArguments(expression)
|
||||
|
||||
return newCallableReference
|
||||
}
|
||||
|
||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val oldReturnTarget = expression.returnTarget
|
||||
val newReturnTarget = oldReturnTarget.transformed ?: return expression
|
||||
|
||||
return IrReturnImpl(expression.startOffset, expression.endOffset, newReturnTarget, expression.value)
|
||||
}
|
||||
|
||||
override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression {
|
||||
if (expression.descriptor in transformedDeclarations) {
|
||||
TODO()
|
||||
}
|
||||
return super.visitDeclarationReference(expression)
|
||||
}
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclaration): IrStatement {
|
||||
if (declaration.descriptor in transformedDeclarations) {
|
||||
TODO()
|
||||
}
|
||||
return super.visitDeclaration(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
private fun rewriteFunctionBody(irDeclaration: IrDeclaration, localContext: LocalContext?) {
|
||||
irDeclaration.transformChildrenVoid(FunctionBodiesRewriter(localContext))
|
||||
}
|
||||
|
||||
private fun rewriteClassMembers(irClass: IrClass, localClassContext: LocalClassContext) {
|
||||
irClass.transformChildrenVoid(FunctionBodiesRewriter(localClassContext))
|
||||
|
||||
val classDescriptor = irClass.descriptor
|
||||
val constructorsCallingSuper = classDescriptor.constructors
|
||||
.map { localClassConstructors[it]!! }
|
||||
.filter { it.declaration.callsSuper() }
|
||||
assert(constructorsCallingSuper.any(), { "Expected at least one constructor calling super; class: $classDescriptor" })
|
||||
|
||||
localClassContext.capturedValueToField.forEach { capturedValue, field ->
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
irClass.addChild(field)
|
||||
|
||||
for (constructorContext in constructorsCallingSuper) {
|
||||
val blockBody = constructorContext.declaration.body as? IrBlockBody
|
||||
?: throw AssertionError("Unexpected constructor body: ${constructorContext.declaration.body}")
|
||||
val capturedValueExpression = constructorContext.irGet(startOffset, endOffset, capturedValue)!!
|
||||
blockBody.statements.add(0,
|
||||
IrSetFieldImpl(startOffset, endOffset, field.symbol,
|
||||
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
|
||||
capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun rewriteDeclarations() {
|
||||
localFunctions.values.forEach {
|
||||
rewriteFunctionBody(it.declaration, it)
|
||||
}
|
||||
|
||||
localClassConstructors.values.forEach {
|
||||
rewriteFunctionBody(it.declaration, it)
|
||||
}
|
||||
|
||||
localClasses.values.forEach {
|
||||
rewriteClassMembers(it.declaration, it)
|
||||
}
|
||||
|
||||
rewriteFunctionBody(memberDeclaration, null)
|
||||
}
|
||||
|
||||
private fun createNewCall(oldCall: IrCall, newCallee: IrFunctionSymbol) =
|
||||
if (oldCall is IrCallWithShallowCopy)
|
||||
oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifierSymbol)
|
||||
else
|
||||
IrCallImpl(
|
||||
oldCall.startOffset, oldCall.endOffset,
|
||||
newCallee,
|
||||
newCallee.descriptor,
|
||||
remapTypeArguments(oldCall, newCallee.descriptor),
|
||||
oldCall.origin, oldCall.superQualifierSymbol
|
||||
)
|
||||
|
||||
private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: CallableDescriptor): Map<TypeParameterDescriptor, KotlinType>? {
|
||||
val oldCallee = oldExpression.descriptor.original
|
||||
|
||||
return if (oldCallee.typeParameters.isEmpty())
|
||||
null
|
||||
else oldCallee.typeParameters.associateBy(
|
||||
{ newCallee.typeParameters[it.index] },
|
||||
{ oldExpression.getTypeArgumentOrDefault(it) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun transformDescriptors() {
|
||||
localFunctions.values.forEach {
|
||||
createLiftedDescriptor(it)
|
||||
}
|
||||
|
||||
localClasses.values.forEach {
|
||||
createFieldsForCapturedValues(it)
|
||||
}
|
||||
|
||||
localClassConstructors.values.forEach {
|
||||
createTransformedConstructorDescriptor(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun suggestLocalName(descriptor: DeclarationDescriptor): String {
|
||||
localFunctions[descriptor]?.let {
|
||||
if (it.index >= 0)
|
||||
return "lambda-${it.index}"
|
||||
}
|
||||
|
||||
return descriptor.name.asString()
|
||||
}
|
||||
|
||||
private fun generateNameForLiftedDeclaration(descriptor: DeclarationDescriptor,
|
||||
newOwner: DeclarationDescriptor): Name =
|
||||
Name.identifier(
|
||||
descriptor.parentsWithSelf
|
||||
.takeWhile { it != newOwner }
|
||||
.toList().reversed()
|
||||
.map { suggestLocalName(it) }
|
||||
.joinToString(separator = "$")
|
||||
)
|
||||
|
||||
private fun createLiftedDescriptor(localFunctionContext: LocalFunctionContext) {
|
||||
val oldDescriptor = localFunctionContext.descriptor
|
||||
|
||||
val memberOwner = memberDeclaration.descriptor.containingDeclaration!!
|
||||
val newDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
memberOwner,
|
||||
oldDescriptor.annotations,
|
||||
generateNameForLiftedDeclaration(oldDescriptor, memberOwner),
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
oldDescriptor.source
|
||||
).apply {
|
||||
isTailrec = oldDescriptor.isTailrec
|
||||
isSuspend = oldDescriptor.isSuspend
|
||||
// TODO: copy other properties or consider using `FunctionDescriptor.CopyBuilder`.
|
||||
}
|
||||
|
||||
localFunctionContext.transformedDescriptor = newDescriptor
|
||||
|
||||
if (oldDescriptor.dispatchReceiverParameter != null) {
|
||||
throw AssertionError("local functions must not have dispatch receiver")
|
||||
}
|
||||
|
||||
val newDispatchReceiverParameter = null
|
||||
|
||||
// Do not substitute type parameters for now.
|
||||
val newTypeParameters = oldDescriptor.typeParameters
|
||||
|
||||
// TODO: consider using fields to access the closure of enclosing class.
|
||||
val capturedValues = localFunctionContext.closure.capturedValues
|
||||
|
||||
val newValueParameters = createTransformedValueParameters(localFunctionContext, capturedValues)
|
||||
|
||||
newDescriptor.initialize(
|
||||
oldDescriptor.extensionReceiverParameter?.type,
|
||||
newDispatchReceiverParameter,
|
||||
newTypeParameters,
|
||||
newValueParameters,
|
||||
oldDescriptor.returnType,
|
||||
Modality.FINAL,
|
||||
Visibilities.PRIVATE
|
||||
)
|
||||
|
||||
oldDescriptor.extensionReceiverParameter?.let {
|
||||
newParameterToOld.putAbsentOrSame(newDescriptor.extensionReceiverParameter!!, it)
|
||||
}
|
||||
|
||||
localFunctionContext.transformedDeclaration = with(localFunctionContext.declaration) {
|
||||
IrFunctionImpl(startOffset, endOffset, origin, newDescriptor)
|
||||
}.apply {
|
||||
createParameterDeclarations()
|
||||
recordTransformedValueParameters(localFunctionContext)
|
||||
transformedDeclarations[oldDescriptor] = this.symbol
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTransformedValueParameters(localContext: LocalContextWithClosureAsParameters,
|
||||
capturedValues: List<IrValueSymbol>)
|
||||
: List<ValueParameterDescriptor> {
|
||||
|
||||
val oldDescriptor = localContext.descriptor
|
||||
val newDescriptor = localContext.transformedDescriptor
|
||||
|
||||
val closureParametersCount = capturedValues.size
|
||||
val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size
|
||||
|
||||
val newValueParameters = ArrayList<ValueParameterDescriptor>(newValueParametersCount).apply {
|
||||
capturedValues.mapIndexedTo(this) { i, capturedValue ->
|
||||
createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply {
|
||||
newParameterToCaptured[this] = capturedValue
|
||||
}
|
||||
}
|
||||
|
||||
oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor ->
|
||||
createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply {
|
||||
newParameterToOld.putAbsentOrSame(this, oldValueParameterDescriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
return newValueParameters
|
||||
}
|
||||
|
||||
private fun IrFunction.recordTransformedValueParameters(localContext: LocalContextWithClosureAsParameters) {
|
||||
|
||||
valueParameters.forEach {
|
||||
val capturedValue = newParameterToCaptured[it.descriptor]
|
||||
if (capturedValue != null) {
|
||||
localContext.capturedValueToParameter[capturedValue.descriptor] = it.symbol
|
||||
}
|
||||
}
|
||||
|
||||
(listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).forEach {
|
||||
val oldParameter = newParameterToOld[it.descriptor]
|
||||
if (oldParameter != null) {
|
||||
oldParameterToNew.putAbsentOrSame(oldParameter, it.symbol)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun createTransformedConstructorDescriptor(constructorContext: LocalClassConstructorContext) {
|
||||
val oldDescriptor = constructorContext.descriptor
|
||||
val localClassContext = localClasses[oldDescriptor.containingDeclaration]!!
|
||||
val newDescriptor = ClassConstructorDescriptorImpl.create(
|
||||
localClassContext.descriptor,
|
||||
Annotations.EMPTY, oldDescriptor.isPrimary, oldDescriptor.source)
|
||||
|
||||
constructorContext.transformedDescriptor = newDescriptor
|
||||
|
||||
// Do not substitute type parameters for now.
|
||||
val newTypeParameters = oldDescriptor.typeParameters
|
||||
|
||||
val capturedValues = localClasses[oldDescriptor.containingDeclaration]!!.closure.capturedValues
|
||||
|
||||
val newValueParameters = createTransformedValueParameters(constructorContext, capturedValues)
|
||||
|
||||
newDescriptor.initialize(
|
||||
newValueParameters,
|
||||
Visibilities.PRIVATE,
|
||||
newTypeParameters
|
||||
)
|
||||
newDescriptor.returnType = oldDescriptor.returnType
|
||||
|
||||
oldDescriptor.dispatchReceiverParameter?.let {
|
||||
newParameterToOld.putAbsentOrSame(newDescriptor.dispatchReceiverParameter!!, it)
|
||||
}
|
||||
|
||||
oldDescriptor.extensionReceiverParameter?.let {
|
||||
throw AssertionError("constructors can't have extension receiver")
|
||||
}
|
||||
|
||||
constructorContext.transformedDeclaration = with(constructorContext.declaration) {
|
||||
IrConstructorImpl(startOffset, endOffset, origin, newDescriptor)
|
||||
}.apply {
|
||||
createParameterDeclarations()
|
||||
recordTransformedValueParameters(constructorContext)
|
||||
transformedDeclarations[oldDescriptor] = this.symbol
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFieldsForCapturedValues(localClassContext: LocalClassContext) {
|
||||
val classDescriptor = localClassContext.descriptor
|
||||
|
||||
localClassContext.closure.capturedValues.forEach { capturedValue ->
|
||||
val fieldDescriptor = PropertyDescriptorImpl.create(
|
||||
classDescriptor,
|
||||
Annotations.EMPTY,
|
||||
Modality.FINAL,
|
||||
Visibilities.PRIVATE,
|
||||
/* isVar = */ false,
|
||||
suggestNameForCapturedValue(capturedValue.descriptor),
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
SourceElement.NO_SOURCE,
|
||||
/* lateInit = */ false,
|
||||
/* isConst = */ false,
|
||||
/* isExpect = */ false,
|
||||
/* isActual = */ false,
|
||||
/* isExternal = */ false,
|
||||
/* isDelegated = */ false)
|
||||
|
||||
fieldDescriptor.initialize(/* getter = */ null, /* setter = */ null)
|
||||
|
||||
val extensionReceiverParameter: ReceiverParameterDescriptor? = null
|
||||
|
||||
fieldDescriptor.setType(
|
||||
capturedValue.descriptor.type,
|
||||
emptyList<TypeParameterDescriptor>(),
|
||||
classDescriptor.thisAsReceiverParameter,
|
||||
extensionReceiverParameter)
|
||||
|
||||
localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl(
|
||||
localClassContext.declaration.startOffset, localClassContext.declaration.endOffset,
|
||||
DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE,
|
||||
fieldDescriptor
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <K, V> MutableMap<K, V>.putAbsentOrSame(key: K, value: V) {
|
||||
val current = this.getOrPut(key, { value })
|
||||
|
||||
if (current != value) {
|
||||
error("$current != $value")
|
||||
}
|
||||
}
|
||||
|
||||
private fun suggestNameForCapturedValue(valueDescriptor: ValueDescriptor): Name =
|
||||
if (valueDescriptor.name.isSpecial) {
|
||||
val oldNameStr = valueDescriptor.name.asString()
|
||||
oldNameStr.substring(1, oldNameStr.length - 1).synthesizedName
|
||||
} else
|
||||
valueDescriptor.name
|
||||
|
||||
private fun createUnsubstitutedCapturedValueParameter(
|
||||
newParameterOwner: CallableMemberDescriptor,
|
||||
valueDescriptor: ValueDescriptor,
|
||||
index: Int
|
||||
): ValueParameterDescriptor =
|
||||
ValueParameterDescriptorImpl(
|
||||
newParameterOwner, null, index,
|
||||
valueDescriptor.annotations,
|
||||
suggestNameForCapturedValue(valueDescriptor),
|
||||
valueDescriptor.type,
|
||||
false, false, false, null, valueDescriptor.source
|
||||
)
|
||||
|
||||
private fun createUnsubstitutedParameter(
|
||||
newParameterOwner: CallableMemberDescriptor,
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
newIndex: Int
|
||||
): ValueParameterDescriptor =
|
||||
valueParameterDescriptor.copy(newParameterOwner, valueParameterDescriptor.name, newIndex)
|
||||
|
||||
|
||||
private fun collectClosures() {
|
||||
val annotator = ClosureAnnotator(memberDeclaration)
|
||||
localFunctions.forEach { descriptor, context ->
|
||||
context.closure = annotator.getFunctionClosure(descriptor)
|
||||
}
|
||||
|
||||
localClasses.forEach { descriptor, context ->
|
||||
context.closure = annotator.getClassClosure(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectLocalDeclarations() {
|
||||
memberDeclaration.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.declaredInFunction() = when (this.containingDeclaration) {
|
||||
is CallableDescriptor -> true
|
||||
is ClassDescriptor -> false
|
||||
is PackageFragmentDescriptor -> false
|
||||
else -> TODO(this.toString() + "\n" + this.containingDeclaration.toString())
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
val descriptor = declaration.descriptor
|
||||
|
||||
if (descriptor.visibility == Visibilities.LOCAL) {
|
||||
val localFunctionContext = LocalFunctionContext(declaration)
|
||||
|
||||
localFunctions[descriptor] = localFunctionContext
|
||||
|
||||
if (descriptor.name.isSpecial) {
|
||||
localFunctionContext.index = lambdasCount++
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
val descriptor = declaration.descriptor
|
||||
assert(descriptor.visibility != Visibilities.LOCAL)
|
||||
|
||||
if (descriptor.constructedClass.isInner) return
|
||||
|
||||
localClassConstructors[descriptor] = LocalClassConstructorContext(declaration)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
val descriptor = declaration.descriptor
|
||||
|
||||
if (descriptor.isInner) return
|
||||
|
||||
// Local nested classes can only be inner.
|
||||
assert(descriptor.declaredInFunction())
|
||||
|
||||
val localClassContext = LocalClassContext(declaration)
|
||||
localClasses[descriptor] = localClassContext
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+7
-4
@@ -20,11 +20,14 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
|
||||
import org.jetbrains.kotlin.backend.common.lower.at
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithoutArguments
|
||||
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
||||
import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
/**
|
||||
@@ -43,7 +46,7 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
||||
expression.transformChildrenVoid()
|
||||
builder.at(expression)
|
||||
|
||||
val typeArgument = expression.descriptor.defaultType
|
||||
val typeArgument = expression.symbol.typeWithStarProjections
|
||||
|
||||
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
|
||||
putValueArgument(0, builder.irCall(symbols.getClassTypeInfo, listOf(typeArgument)))
|
||||
@@ -54,7 +57,7 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
||||
expression.transformChildrenVoid()
|
||||
builder.at(expression)
|
||||
|
||||
val typeArgument = expression.type.arguments.single().type
|
||||
val typeArgument = expression.argument.type
|
||||
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
|
||||
val typeInfo = builder.irCall(symbols.getObjectTypeInfo).apply {
|
||||
putValueArgument(0, expression.argument)
|
||||
@@ -95,7 +98,7 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
||||
}
|
||||
expression.putValueArgument(0, IrConstImpl<String>(
|
||||
expression.startOffset, expression.endOffset,
|
||||
context.ir.symbols.immutableBinaryBlob.descriptor.defaultType,
|
||||
context.ir.symbols.immutableBinaryBlob.typeWithoutArguments,
|
||||
IrConstKind.String, builder.toString()))
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -24,8 +24,8 @@ import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
/**
|
||||
* This pass runs before inlining and performs the following additional transformations over some operations:
|
||||
|
||||
+244
-210
@@ -17,9 +17,7 @@
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.getFunction
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.replace
|
||||
import org.jetbrains.kotlin.backend.common.ir.createOverriddenDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
@@ -27,6 +25,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.ir.IrSuspendableExpressionImpl
|
||||
import org.jetbrains.kotlin.backend.konan.ir.IrSuspensionPoint
|
||||
import org.jetbrains.kotlin.backend.konan.ir.IrSuspensionPointImpl
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
@@ -35,12 +34,10 @@ import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
@@ -48,15 +45,12 @@ import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
|
||||
internal class SuspendFunctionsLowering(val context: Context): DeclarationContainerLoweringPass {
|
||||
|
||||
@@ -212,7 +206,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
}
|
||||
|
||||
private val symbols = context.ir.symbols
|
||||
private val getContinuationSymbol = symbols.getContinuation
|
||||
private val getContinuation = symbols.getContinuation.owner
|
||||
private val continuationClassSymbol = getContinuation.returnType.classifierOrFail as IrClassSymbol
|
||||
private val returnIfSuspendedDescriptor = context.getInternalFunctions("returnIfSuspended").single()
|
||||
|
||||
private fun removeReturnIfSuspendedCallAndSimplifyDelegatingCall(irFunction: IrFunction, delegatingCall: IrCall) {
|
||||
@@ -245,7 +240,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
putValueArgument(index, irGet(argument))
|
||||
}
|
||||
putValueArgument(functionParameters.size,
|
||||
irCall(getContinuationSymbol, listOf(descriptor.returnType!!)))
|
||||
irCall(getContinuation, listOf(irFunction.returnType)))
|
||||
}
|
||||
putValueArgument(0, irGetObject(symbols.unit)) // value
|
||||
putValueArgument(1, irNull()) // exception
|
||||
@@ -268,59 +263,50 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
private val coroutinesScope = context.irModule!!.descriptor.getPackage(COROUTINES_FQ_NAME).memberScope
|
||||
private val kotlinPackageScope = context.irModule!!.descriptor.getPackage(KOTLIN_FQ_NAME).memberScope
|
||||
|
||||
private val continuationClassDescriptor = coroutinesScope
|
||||
.getContributedClassifier(Name.identifier("Continuation"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
||||
|
||||
private inner class CoroutineBuilder(val irFunction: IrFunction, val functionReference: IrFunctionReference?) {
|
||||
|
||||
private val functionParameters = irFunction.descriptor.explicitParameters
|
||||
private val boundFunctionParameters = functionReference?.getArguments()?.map { it.first }
|
||||
private val functionParameters = irFunction.explicitParameters
|
||||
private val boundFunctionParameters = functionReference?.getArgumentsWithIr()?.map { it.first }
|
||||
private val unboundFunctionParameters = boundFunctionParameters?.let { functionParameters - it }
|
||||
|
||||
private var tempIndex = 0
|
||||
private var suspensionPointIdIndex = 0
|
||||
private lateinit var suspendResult: IrVariableSymbol
|
||||
private lateinit var dataArgument: IrValueParameterSymbol
|
||||
private lateinit var exceptionArgument: IrValueParameterSymbol
|
||||
private lateinit var suspendResult: IrVariable
|
||||
private lateinit var dataArgument: IrValueParameter
|
||||
private lateinit var exceptionArgument: IrValueParameter
|
||||
private lateinit var coroutineClassDescriptor: ClassDescriptorImpl
|
||||
private lateinit var coroutineClass: IrClassImpl
|
||||
private lateinit var coroutineClassThis: IrValueParameterSymbol
|
||||
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrFieldSymbol>
|
||||
private lateinit var coroutineClassThis: IrValueParameter
|
||||
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrField>
|
||||
|
||||
private val coroutineImplSymbol = symbols.coroutineImpl
|
||||
private val coroutineImplConstructorSymbol = coroutineImplSymbol.constructors.single()
|
||||
private val coroutineImplClassDescriptor = coroutineImplSymbol.descriptor
|
||||
private val create1FunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
||||
.getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND)
|
||||
.single { it.valueParameters.size == 1 }
|
||||
private val create1CompletionParameter = create1FunctionDescriptor.valueParameters[0]
|
||||
private val create1Function = coroutineImplSymbol.owner.simpleFunctions()
|
||||
.single { it.name.asString() == "create" && it.valueParameters.size == 1 }
|
||||
private val create1CompletionParameter = create1Function.valueParameters[0]
|
||||
|
||||
private val coroutineImplLabelGetterSymbol = coroutineImplSymbol.getPropertyGetter("label")!!
|
||||
private val coroutineImplLabelSetterSymbol = coroutineImplSymbol.getPropertySetter("label")!!
|
||||
|
||||
fun build(): BuiltCoroutine {
|
||||
val superTypes = mutableListOf<KotlinType>(coroutineImplClassDescriptor.defaultType)
|
||||
val superClasses = mutableListOf<IrClass>(coroutineImplSymbol.owner)
|
||||
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
||||
var functionClassDescriptor: ClassDescriptor? = null
|
||||
var suspendFunctionClassTypeArguments: List<KotlinType>? = null
|
||||
var functionClassTypeArguments: List<KotlinType>? = null
|
||||
val superTypes = mutableListOf<IrType>(coroutineImplSymbol.owner.defaultType)
|
||||
var suspendFunctionClass: IrClass? = null
|
||||
var functionClass: IrClass? = null
|
||||
var suspendFunctionClassTypeArguments: List<IrType>? = null
|
||||
var functionClassTypeArguments: List<IrType>? = null
|
||||
if (unboundFunctionParameters != null) {
|
||||
// Suspend lambda inherits SuspendFunction.
|
||||
val numberOfParameters = unboundFunctionParameters.size
|
||||
suspendFunctionClassDescriptor = kotlinPackageScope.getContributedClassifier(
|
||||
Name.identifier("SuspendFunction$numberOfParameters"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
||||
suspendFunctionClass = context.ir.symbols.suspendFunctions[numberOfParameters].owner
|
||||
val unboundParameterTypes = unboundFunctionParameters.map { it.type }
|
||||
suspendFunctionClassTypeArguments = unboundParameterTypes + irFunction.descriptor.returnType!!
|
||||
superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeArguments)
|
||||
superClasses += context.ir.symbols.suspendFunctions[numberOfParameters].owner
|
||||
suspendFunctionClassTypeArguments = unboundParameterTypes + irFunction.returnType
|
||||
superTypes += suspendFunctionClass.typeWith(suspendFunctionClassTypeArguments)
|
||||
|
||||
functionClassDescriptor = kotlinPackageScope.getContributedClassifier(
|
||||
Name.identifier("Function${numberOfParameters + 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
||||
val continuationType = continuationClassDescriptor.defaultType.replace(listOf(irFunction.descriptor.returnType!!))
|
||||
functionClassTypeArguments = unboundParameterTypes + continuationType + context.builtIns.nullableAnyType
|
||||
superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeArguments)
|
||||
superClasses += context.ir.symbols.functions[numberOfParameters + 1].owner
|
||||
functionClass = context.ir.symbols.functions[numberOfParameters + 1].owner
|
||||
val continuationType = continuationClassSymbol.typeWith(irFunction.returnType)
|
||||
functionClassTypeArguments = unboundParameterTypes + continuationType + context.irBuiltIns.anyNType
|
||||
superTypes += functionClass.typeWith(functionClassTypeArguments)
|
||||
|
||||
}
|
||||
coroutineClassDescriptor = ClassDescriptorImpl(
|
||||
@@ -328,11 +314,13 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
/* name = */ "${irFunction.descriptor.name}\$${coroutineId++}".synthesizedName,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* kind = */ ClassKind.CLASS,
|
||||
/* superTypes = */ superTypes,
|
||||
/* superTypes = */ superTypes.map { it.toKotlinType() },
|
||||
/* source = */ SourceElement.NO_SOURCE,
|
||||
/* isExternal = */ false,
|
||||
/* storageManager = */ LockBasedStorageManager.NO_LOCKS
|
||||
)
|
||||
).also {
|
||||
it.initialize(stub("coroutine class"), stub("coroutine class constructors"), null)
|
||||
}
|
||||
coroutineClass = IrClassImpl(
|
||||
startOffset = irFunction.startOffset,
|
||||
endOffset = irFunction.endOffset,
|
||||
@@ -340,17 +328,19 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
descriptor = coroutineClassDescriptor
|
||||
)
|
||||
coroutineClass.parent = irFunction.parent
|
||||
coroutineClass.createParameterDeclarations()
|
||||
coroutineClassThis = coroutineClass.thisReceiver!!
|
||||
|
||||
|
||||
val overriddenMap = mutableMapOf<CallableMemberDescriptor, CallableMemberDescriptor>()
|
||||
val constructors = mutableSetOf<ClassConstructorDescriptor>()
|
||||
val coroutineConstructorBuilder = createConstructorBuilder()
|
||||
constructors.add(coroutineConstructorBuilder.symbol.descriptor)
|
||||
coroutineConstructorBuilder.initialize()
|
||||
|
||||
val doResumeFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
||||
.getContributedFunctions(Name.identifier("doResume"), NoLookupLocation.FROM_BACKEND).single()
|
||||
val doResumeMethodBuilder = createDoResumeMethodBuilder(doResumeFunctionDescriptor)
|
||||
overriddenMap += doResumeFunctionDescriptor to doResumeMethodBuilder.symbol.descriptor
|
||||
val doResumeFunction = coroutineImplSymbol.owner.simpleFunctions()
|
||||
.single { it.name.asString() == "doResume" }
|
||||
val doResumeMethodBuilder = createDoResumeMethodBuilder(doResumeFunction, coroutineClass)
|
||||
doResumeMethodBuilder.initialize()
|
||||
overriddenMap += doResumeFunction.descriptor to doResumeMethodBuilder.symbol.descriptor
|
||||
|
||||
var coroutineFactoryConstructorBuilder: SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>? = null
|
||||
var createMethodBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>? = null
|
||||
@@ -358,7 +348,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
if (functionReference != null) {
|
||||
// Suspend lambda - create factory methods.
|
||||
coroutineFactoryConstructorBuilder = createFactoryConstructorBuilder(boundFunctionParameters!!)
|
||||
constructors.add(coroutineFactoryConstructorBuilder.symbol.descriptor)
|
||||
|
||||
val createFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
||||
.getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND)
|
||||
@@ -366,27 +355,24 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
createMethodBuilder = createCreateMethodBuilder(
|
||||
unboundArgs = unboundFunctionParameters!!,
|
||||
superFunctionDescriptor = createFunctionDescriptor,
|
||||
coroutineConstructorSymbol = coroutineConstructorBuilder.symbol)
|
||||
coroutineConstructor = coroutineConstructorBuilder.ir,
|
||||
coroutineClass = coroutineClass)
|
||||
createMethodBuilder.initialize()
|
||||
if (createFunctionDescriptor != null)
|
||||
overriddenMap += createFunctionDescriptor to createMethodBuilder.symbol.descriptor
|
||||
|
||||
val invokeFunctionDescriptor = functionClassDescriptor!!.getFunction("invoke", functionClassTypeArguments!!)
|
||||
val suspendInvokeFunctionDescriptor = suspendFunctionClassDescriptor!!.getFunction("invoke", suspendFunctionClassTypeArguments!!)
|
||||
val invokeFunctionDescriptor = functionClass!!.descriptor
|
||||
.getFunction("invoke", functionClassTypeArguments!!.map { it.toKotlinType() })
|
||||
val suspendInvokeFunctionDescriptor = suspendFunctionClass!!.descriptor
|
||||
.getFunction("invoke", suspendFunctionClassTypeArguments!!.map { it.toKotlinType() })
|
||||
invokeMethodBuilder = createInvokeMethodBuilder(
|
||||
suspendFunctionInvokeFunctionDescriptor = suspendInvokeFunctionDescriptor,
|
||||
functionInvokeFunctionDescriptor = invokeFunctionDescriptor,
|
||||
createFunctionSymbol = createMethodBuilder.symbol,
|
||||
doResumeFunctionSymbol = doResumeMethodBuilder.symbol)
|
||||
createFunction = createMethodBuilder.ir,
|
||||
doResumeFunction = doResumeMethodBuilder.ir,
|
||||
coroutineClass = coroutineClass)
|
||||
}
|
||||
|
||||
val memberScope = stub<MemberScope>("coroutine class")
|
||||
coroutineClassDescriptor.initialize(memberScope, constructors, null)
|
||||
|
||||
coroutineClass.createParameterDeclarations()
|
||||
|
||||
coroutineClassThis = coroutineClass.thisReceiver!!.symbol
|
||||
|
||||
coroutineConstructorBuilder.initialize()
|
||||
coroutineClass.addChild(coroutineConstructorBuilder.ir)
|
||||
|
||||
coroutineFactoryConstructorBuilder?.let {
|
||||
@@ -395,7 +381,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
}
|
||||
|
||||
createMethodBuilder?.let {
|
||||
it.initialize()
|
||||
coroutineClass.addChild(it.ir)
|
||||
}
|
||||
|
||||
@@ -404,10 +389,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
coroutineClass.addChild(it.ir)
|
||||
}
|
||||
|
||||
doResumeMethodBuilder.initialize()
|
||||
coroutineClass.addChild(doResumeMethodBuilder.ir)
|
||||
|
||||
coroutineClass.setSuperSymbolsAndAddFakeOverrides(superClasses)
|
||||
coroutineClass.setSuperSymbolsAndAddFakeOverrides(superTypes)
|
||||
|
||||
return BuiltCoroutine(
|
||||
coroutineClass = coroutineClass,
|
||||
@@ -428,21 +412,30 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
)
|
||||
)
|
||||
|
||||
private lateinit var constructorParameters: List<IrValueParameter>
|
||||
|
||||
override fun doInitialize() {
|
||||
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||
val constructorParameters = (
|
||||
constructorParameters = (
|
||||
functionParameters
|
||||
+ coroutineImplConstructorSymbol.descriptor.valueParameters[0] // completion.
|
||||
).mapIndexed { index, parameter -> parameter.copyAsValueParameter(descriptor, index) }
|
||||
+ coroutineImplConstructorSymbol.owner.valueParameters[0] // completion.
|
||||
).mapIndexed { index, parameter ->
|
||||
|
||||
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
||||
val parameterDescriptor = parameter.descriptor.copyAsValueParameter(descriptor, index)
|
||||
parameter.copy(parameterDescriptor)
|
||||
}
|
||||
|
||||
descriptor.initialize(
|
||||
constructorParameters.map { it.descriptor as ValueParameterDescriptor },
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
descriptor.returnType = coroutineClassDescriptor.defaultType
|
||||
}
|
||||
|
||||
override fun buildIr(): IrConstructor {
|
||||
// Save all arguments to fields.
|
||||
argumentToPropertiesMap = functionParameters.associate {
|
||||
it to buildPropertyWithBackingField(it.name, it.type, false)
|
||||
it.descriptor to addField(it.name, it.type, false)
|
||||
}
|
||||
|
||||
val startOffset = irFunction.startOffset
|
||||
@@ -453,25 +446,32 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||
symbol = symbol).apply {
|
||||
|
||||
createParameterDeclarations()
|
||||
returnType = coroutineClass.defaultType
|
||||
|
||||
this.valueParameters += constructorParameters
|
||||
|
||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||
body = irBuilder.irBlockBody {
|
||||
val completionParameter = valueParameters.last()
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply {
|
||||
putValueArgument(0, irGet(completionParameter.symbol))
|
||||
putValueArgument(0, irGet(completionParameter))
|
||||
}
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol)
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol, context.irBuiltIns.unitType)
|
||||
functionParameters.forEachIndexed { index, parameter ->
|
||||
+irSetField(irGet(coroutineClassThis), argumentToPropertiesMap[parameter]!!, irGet(valueParameters[index].symbol))
|
||||
+irSetField(
|
||||
irGet(coroutineClassThis),
|
||||
argumentToPropertiesMap[parameter.descriptor]!!,
|
||||
irGet(valueParameters[index])
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFactoryConstructorBuilder(boundParams: List<ParameterDescriptor>)
|
||||
private fun createFactoryConstructorBuilder(boundParams: List<IrValueParameter>)
|
||||
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
||||
|
||||
override fun buildSymbol() = IrConstructorSymbolImpl(
|
||||
@@ -483,12 +483,18 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
)
|
||||
)
|
||||
|
||||
lateinit var constructorParameters: List<IrValueParameter>
|
||||
|
||||
override fun doInitialize() {
|
||||
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||
val constructorParameters = boundParams.mapIndexed { index, parameter ->
|
||||
parameter.copyAsValueParameter(descriptor, index)
|
||||
constructorParameters = boundParams.mapIndexed { index, parameter ->
|
||||
val parameterDescriptor = parameter.descriptor.copyAsValueParameter(descriptor, index)
|
||||
parameter.copy(parameterDescriptor)
|
||||
}
|
||||
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
||||
descriptor.initialize(
|
||||
constructorParameters.map { it.descriptor as ValueParameterDescriptor },
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
descriptor.returnType = coroutineClassDescriptor.defaultType
|
||||
}
|
||||
|
||||
@@ -501,27 +507,32 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||
symbol = symbol).apply {
|
||||
|
||||
createParameterDeclarations()
|
||||
returnType = coroutineClass.defaultType
|
||||
|
||||
this.valueParameters += constructorParameters
|
||||
|
||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||
body = irBuilder.irBlockBody {
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType,
|
||||
coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply {
|
||||
putValueArgument(0, irNull()) // Completion.
|
||||
}
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol)
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol,
|
||||
context.irBuiltIns.unitType)
|
||||
// Save all arguments to fields.
|
||||
boundParams.forEachIndexed { index, parameter ->
|
||||
+irSetField(irGet(coroutineClassThis), argumentToPropertiesMap[parameter]!!, irGet(valueParameters[index].symbol))
|
||||
+irSetField(irGet(coroutineClassThis), argumentToPropertiesMap[parameter.descriptor]!!,
|
||||
irGet(valueParameters[index]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCreateMethodBuilder(unboundArgs: List<ParameterDescriptor>,
|
||||
private fun createCreateMethodBuilder(unboundArgs: List<IrValueParameter>,
|
||||
superFunctionDescriptor: FunctionDescriptor?,
|
||||
coroutineConstructorSymbol: IrConstructorSymbol)
|
||||
coroutineConstructor: IrConstructor,
|
||||
coroutineClass: IrClass)
|
||||
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||
|
||||
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||
@@ -534,19 +545,21 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
)
|
||||
)
|
||||
|
||||
lateinit var parameters: List<IrValueParameter>
|
||||
|
||||
override fun doInitialize() {
|
||||
val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl
|
||||
val valueParameters = (
|
||||
parameters = (
|
||||
unboundArgs + create1CompletionParameter
|
||||
).mapIndexed { index, parameter ->
|
||||
parameter.copyAsValueParameter(descriptor, index)
|
||||
parameter.copy(parameter.descriptor.copyAsValueParameter(descriptor, index))
|
||||
}
|
||||
|
||||
descriptor.initialize(
|
||||
/* receiverParameterType = */ null,
|
||||
/* dispatchReceiverParameter = */ coroutineClassDescriptor.thisAsReceiverParameter,
|
||||
/* typeParameters = */ emptyList(),
|
||||
/* unsubstitutedValueParameters = */ valueParameters,
|
||||
/* unsubstitutedValueParameters = */ parameters.map { it.descriptor as ValueParameterDescriptor },
|
||||
/* unsubstitutedReturnType = */ coroutineClassDescriptor.defaultType,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PRIVATE).apply {
|
||||
@@ -566,25 +579,29 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||
symbol = symbol).apply {
|
||||
|
||||
createParameterDeclarations()
|
||||
returnType = coroutineClass.defaultType
|
||||
parent = coroutineClass
|
||||
|
||||
val thisReceiver = this.dispatchReceiverParameter!!.symbol
|
||||
this.valueParameters += parameters
|
||||
this.createDispatchReceiverParameter()
|
||||
|
||||
val thisReceiver = this.dispatchReceiverParameter!!
|
||||
|
||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||
+irReturn(
|
||||
irCall(coroutineConstructorSymbol).apply {
|
||||
irCall(coroutineConstructor).apply {
|
||||
var unboundIndex = 0
|
||||
val unboundArgsSet = unboundArgs.toSet()
|
||||
functionParameters.map {
|
||||
if (unboundArgsSet.contains(it))
|
||||
irGet(valueParameters[unboundIndex++].symbol)
|
||||
irGet(valueParameters[unboundIndex++])
|
||||
else
|
||||
irGetField(irGet(thisReceiver), argumentToPropertiesMap[it]!!)
|
||||
irGetField(irGet(thisReceiver), argumentToPropertiesMap[it.descriptor]!!)
|
||||
}.forEachIndexed { index, argument ->
|
||||
putValueArgument(index, argument)
|
||||
}
|
||||
putValueArgument(functionParameters.size, irGet(valueParameters[unboundIndex].symbol))
|
||||
putValueArgument(functionParameters.size, irGet(valueParameters[unboundIndex]))
|
||||
assert(unboundIndex == valueParameters.size - 1,
|
||||
{ "Not all arguments of <create> are used" })
|
||||
})
|
||||
@@ -595,8 +612,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
|
||||
private fun createInvokeMethodBuilder(suspendFunctionInvokeFunctionDescriptor: FunctionDescriptor,
|
||||
functionInvokeFunctionDescriptor: FunctionDescriptor,
|
||||
createFunctionSymbol: IrFunctionSymbol,
|
||||
doResumeFunctionSymbol: IrFunctionSymbol)
|
||||
createFunction: IrFunction,
|
||||
doResumeFunction: IrFunction,
|
||||
coroutineClass: IrClass)
|
||||
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||
|
||||
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||
@@ -609,18 +627,20 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
)
|
||||
)
|
||||
|
||||
lateinit var parameters: List<IrValueParameter>
|
||||
|
||||
override fun doInitialize() {
|
||||
val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl
|
||||
val valueParameters = createFunctionSymbol.descriptor.valueParameters
|
||||
parameters = createFunction.valueParameters
|
||||
// Skip completion - invoke() already has it implicitly as a suspend function.
|
||||
.take(createFunctionSymbol.descriptor.valueParameters.size - 1)
|
||||
.map { it.copyAsValueParameter(descriptor, it.index) }
|
||||
.take(createFunction.valueParameters.size - 1)
|
||||
.map { it.copy(it.descriptor.copyAsValueParameter(descriptor, it.index)) }
|
||||
|
||||
descriptor.initialize(
|
||||
/* receiverParameterType = */ null,
|
||||
/* dispatchReceiverParameter = */ coroutineClassDescriptor.thisAsReceiverParameter,
|
||||
/* typeParameters = */ emptyList(),
|
||||
/* unsubstitutedValueParameters = */ valueParameters,
|
||||
/* unsubstitutedValueParameters = */ parameters.map { it.descriptor as ValueParameterDescriptor },
|
||||
/* unsubstitutedReturnType = */ irFunction.descriptor.returnType,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PRIVATE).apply {
|
||||
@@ -639,21 +659,25 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||
symbol = symbol).apply {
|
||||
|
||||
createParameterDeclarations()
|
||||
returnType = irFunction.returnType
|
||||
parent = coroutineClass
|
||||
|
||||
val thisReceiver = this.dispatchReceiverParameter!!.symbol
|
||||
valueParameters += parameters
|
||||
this.createDispatchReceiverParameter()
|
||||
|
||||
val thisReceiver = this.dispatchReceiverParameter!!
|
||||
|
||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||
+irReturn(
|
||||
irCall(doResumeFunctionSymbol).apply {
|
||||
dispatchReceiver = irCall(createFunctionSymbol).apply {
|
||||
irCall(doResumeFunction).apply {
|
||||
dispatchReceiver = irCall(createFunction).apply {
|
||||
dispatchReceiver = irGet(thisReceiver)
|
||||
valueParameters.forEachIndexed { index, parameter ->
|
||||
putValueArgument(index, irGet(parameter.symbol))
|
||||
putValueArgument(index, irGet(parameter))
|
||||
}
|
||||
putValueArgument(valueParameters.size,
|
||||
irCall(getContinuationSymbol, listOf(symbol.descriptor.returnType!!)))
|
||||
irCall(getContinuation, listOf(returnType)))
|
||||
}
|
||||
putValueArgument(0, irGetObject(symbols.unit)) // value
|
||||
putValueArgument(1, irNull()) // exception
|
||||
@@ -664,27 +688,23 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildPropertyWithBackingField(name: Name, type: KotlinType, isMutable: Boolean): IrFieldSymbol {
|
||||
val propertyBuilder = context.createPropertyWithBackingFieldBuilder(
|
||||
startOffset = irFunction.startOffset,
|
||||
endOffset = irFunction.endOffset,
|
||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||
owner = coroutineClassDescriptor,
|
||||
name = name,
|
||||
type = type,
|
||||
isMutable = isMutable).apply {
|
||||
initialize()
|
||||
}
|
||||
|
||||
coroutineClass.addChild(propertyBuilder.ir)
|
||||
return propertyBuilder.symbol
|
||||
private fun addField(name: Name, type: IrType, isMutable: Boolean): IrField = createField(
|
||||
irFunction.startOffset,
|
||||
irFunction.endOffset,
|
||||
type,
|
||||
name,
|
||||
isMutable,
|
||||
DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||
coroutineClassDescriptor
|
||||
).also {
|
||||
coroutineClass.addChild(it)
|
||||
}
|
||||
|
||||
private fun createDoResumeMethodBuilder(doResumeFunctionDescriptor: FunctionDescriptor)
|
||||
private fun createDoResumeMethodBuilder(doResumeFunction: IrFunction, coroutineClass: IrClass)
|
||||
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||
|
||||
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||
doResumeFunctionDescriptor.createOverriddenDescriptor(coroutineClassDescriptor)
|
||||
doResumeFunction.descriptor.createOverriddenDescriptor(coroutineClassDescriptor)
|
||||
)
|
||||
|
||||
override fun doInitialize() { }
|
||||
@@ -699,58 +719,76 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||
symbol = symbol).apply {
|
||||
|
||||
createParameterDeclarations()
|
||||
returnType = context.irBuiltIns.anyNType
|
||||
parent = coroutineClass
|
||||
|
||||
this.createDispatchReceiverParameter()
|
||||
|
||||
doResumeFunction.valueParameters.mapIndexedTo(this.valueParameters) { index, it ->
|
||||
it.copy(descriptor.valueParameters[index])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dataArgument = function.valueParameters[0].symbol
|
||||
exceptionArgument = function.valueParameters[1].symbol
|
||||
suspendResult = IrVariableSymbolImpl(
|
||||
IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration = irFunction.descriptor,
|
||||
name = "suspendResult".synthesizedName,
|
||||
outType = context.builtIns.nullableAnyType,
|
||||
isMutable = true)
|
||||
)
|
||||
val label = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
||||
.getContributedVariables(Name.identifier("label"), NoLookupLocation.FROM_BACKEND).single()
|
||||
dataArgument = function.valueParameters[0]
|
||||
exceptionArgument = function.valueParameters[1]
|
||||
|
||||
val label = coroutineImplSymbol.owner.declarations.filterIsInstance<IrProperty>()
|
||||
.single { it.name.asString() == "label" }
|
||||
|
||||
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
||||
function.body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||
|
||||
suspendResult = irVar(IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration = irFunction.descriptor,
|
||||
name = "suspendResult".synthesizedName,
|
||||
outType = context.builtIns.nullableAnyType,
|
||||
isMutable = true)
|
||||
, context.irBuiltIns.anyNType)
|
||||
|
||||
// Extract all suspend calls to temporaries in order to make correct jumps to them.
|
||||
originalBody.transformChildrenVoid(ExpressionSlicer(label.type))
|
||||
originalBody.transformChildrenVoid(ExpressionSlicer(label.getter!!.returnType))
|
||||
|
||||
val liveLocals = computeLivenessAtSuspensionPoints(originalBody)
|
||||
|
||||
val immutableLiveLocals = liveLocals.values.flatten().filterNot { it.descriptor.isVar }.toSet()
|
||||
val localsMap = immutableLiveLocals.associate {
|
||||
// TODO: Remove .descriptor as soon as all symbols are bound.
|
||||
it.descriptor to IrVariableSymbolImpl(
|
||||
val symbol = IrVariableSymbolImpl(
|
||||
IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration = irFunction.descriptor,
|
||||
name = it.descriptor.name,
|
||||
outType = it.descriptor.type,
|
||||
isMutable = true)
|
||||
name = it.descriptor.name,
|
||||
outType = it.descriptor.type,
|
||||
isMutable = true)
|
||||
)
|
||||
|
||||
val variable = IrVariableImpl(
|
||||
startOffset = it.startOffset,
|
||||
endOffset = it.endOffset,
|
||||
origin = it.origin,
|
||||
symbol = symbol,
|
||||
type = it.type
|
||||
)
|
||||
|
||||
it.descriptor to variable
|
||||
}
|
||||
|
||||
if (localsMap.isNotEmpty())
|
||||
transformVariables(originalBody, localsMap) // Make variables mutable in order to save/restore them.
|
||||
|
||||
val localToPropertyMap = mutableMapOf<IrVariableSymbol, IrFieldSymbol>()
|
||||
val localToPropertyMap = mutableMapOf<IrVariableSymbol, IrField>()
|
||||
// TODO: optimize by using the same property for different locals.
|
||||
liveLocals.values.forEach { scope ->
|
||||
scope.forEach {
|
||||
localToPropertyMap.getOrPut(it) {
|
||||
buildPropertyWithBackingField(it.descriptor.name, it.descriptor.type, true)
|
||||
localToPropertyMap.getOrPut(it.symbol) {
|
||||
addField(it.descriptor.name, it.type, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
originalBody.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
|
||||
private val thisReceiver = function.dispatchReceiverParameter!!.symbol
|
||||
private val thisReceiver = function.dispatchReceiverParameter!!
|
||||
|
||||
// Replace returns to refer to the new function.
|
||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||
@@ -783,23 +821,24 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
when (expression.symbol) {
|
||||
saveStateSymbol -> {
|
||||
saveState.symbol -> {
|
||||
val scope = liveLocals[suspensionPoint]!!
|
||||
return irBlock(expression) {
|
||||
scope.forEach {
|
||||
+irSetField(irGet(thisReceiver), localToPropertyMap[it]!!, irGet(localsMap[it.descriptor] ?: it))
|
||||
val variable = localsMap[it.descriptor] ?: it
|
||||
+irSetField(irGet(thisReceiver), localToPropertyMap[it.symbol]!!, irGet(variable))
|
||||
}
|
||||
+irCall(coroutineImplLabelSetterSymbol).apply {
|
||||
dispatchReceiver = irGet(thisReceiver)
|
||||
putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter.symbol))
|
||||
putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter))
|
||||
}
|
||||
}
|
||||
}
|
||||
restoreStateSymbol -> {
|
||||
restoreState.symbol -> {
|
||||
val scope = liveLocals[suspensionPoint]!!
|
||||
return irBlock(expression) {
|
||||
scope.forEach {
|
||||
+irSetVar(localsMap[it.descriptor] ?: it, irGetField(irGet(thisReceiver), localToPropertyMap[it]!!))
|
||||
+irSetVar(localsMap[it.descriptor] ?: it, irGetField(irGet(thisReceiver), localToPropertyMap[it.symbol]!!))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -812,26 +851,26 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
}
|
||||
})
|
||||
val statements = (originalBody as IrBlockBody).statements
|
||||
+irVar(suspendResult, null)
|
||||
+suspendResult
|
||||
+IrSuspendableExpressionImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = context.builtIns.unitType,
|
||||
type = context.irBuiltIns.unitType,
|
||||
suspensionPointId = irCall(coroutineImplLabelGetterSymbol).apply {
|
||||
dispatchReceiver = irGet(function.dispatchReceiverParameter!!.symbol)
|
||||
dispatchReceiver = irGet(function.dispatchReceiverParameter!!)
|
||||
},
|
||||
result = irBlock(startOffset, endOffset) {
|
||||
+irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception.
|
||||
statements.forEach { +it }
|
||||
})
|
||||
if (irFunction.descriptor.returnType!!.isUnit())
|
||||
if (irFunction.returnType.isUnit())
|
||||
+irReturn(irGetObject(symbols.unit)) // Insert explicit return for Unit functions.
|
||||
}
|
||||
return function
|
||||
}
|
||||
}
|
||||
|
||||
private fun transformVariables(element: IrElement, variablesMap: Map<VariableDescriptor, IrVariableSymbol>) {
|
||||
private fun transformVariables(element: IrElement, variablesMap: Map<VariableDescriptor, IrVariable>) {
|
||||
element.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
@@ -843,7 +882,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
return IrGetValueImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
symbol = newVariable,
|
||||
type = newVariable.type,
|
||||
symbol = newVariable.symbol,
|
||||
origin = expression.origin)
|
||||
}
|
||||
|
||||
@@ -856,7 +896,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
return IrSetVariableImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
symbol = newVariable,
|
||||
type = context.irBuiltIns.unitType,
|
||||
symbol = newVariable.symbol,
|
||||
value = expression.value,
|
||||
origin = expression.origin)
|
||||
}
|
||||
@@ -867,21 +908,17 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
val newVariable = variablesMap[declaration.symbol.descriptor]
|
||||
?: return declaration
|
||||
|
||||
return IrVariableImpl(
|
||||
startOffset = declaration.startOffset,
|
||||
endOffset = declaration.endOffset,
|
||||
origin = declaration.origin,
|
||||
symbol = newVariable).apply {
|
||||
initializer = declaration.initializer
|
||||
}
|
||||
newVariable.initializer = declaration.initializer
|
||||
|
||||
return newVariable
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun computeLivenessAtSuspensionPoints(body: IrBody): Map<IrSuspensionPoint, List<IrVariableSymbol>> {
|
||||
private fun computeLivenessAtSuspensionPoints(body: IrBody): Map<IrSuspensionPoint, List<IrVariable>> {
|
||||
// TODO: data flow analysis.
|
||||
// Just save all visible for now.
|
||||
val result = mutableMapOf<IrSuspensionPoint, List<IrVariableSymbol>>()
|
||||
val result = mutableMapOf<IrSuspensionPoint, List<IrVariable>>()
|
||||
body.acceptChildrenVoid(object: VariablesScopeTracker() {
|
||||
|
||||
override fun visitExpression(expression: IrExpression) {
|
||||
@@ -894,7 +931,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
suspensionPoint.result.acceptChildrenVoid(this)
|
||||
suspensionPoint.resumeResult.acceptChildrenVoid(this)
|
||||
|
||||
val visibleVariables = mutableListOf<IrVariableSymbol>()
|
||||
val visibleVariables = mutableListOf<IrVariable>()
|
||||
scopeStack.forEach { visibleVariables += it }
|
||||
result.put(suspensionPoint, visibleVariables)
|
||||
}
|
||||
@@ -904,7 +941,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
}
|
||||
|
||||
// These are marker descriptors to split up the lowering on two parts.
|
||||
private val saveStateSymbol = IrSimpleFunctionSymbolImpl(
|
||||
private val saveState = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED,
|
||||
SimpleFunctionDescriptorImpl.create(
|
||||
irFunction.descriptor,
|
||||
Annotations.EMPTY,
|
||||
@@ -912,10 +949,11 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
SourceElement.NO_SOURCE).apply {
|
||||
initialize(null, null, emptyList(), emptyList(), context.builtIns.unitType, Modality.ABSTRACT, Visibilities.PRIVATE)
|
||||
}
|
||||
)
|
||||
}).apply {
|
||||
returnType = context.irBuiltIns.unitType
|
||||
}
|
||||
|
||||
private val restoreStateSymbol = IrSimpleFunctionSymbolImpl(
|
||||
private val restoreState = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED,
|
||||
SimpleFunctionDescriptorImpl.create(
|
||||
irFunction.descriptor,
|
||||
Annotations.EMPTY,
|
||||
@@ -923,10 +961,11 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
SourceElement.NO_SOURCE).apply {
|
||||
initialize(null, null, emptyList(), emptyList(), context.builtIns.unitType, Modality.ABSTRACT, Visibilities.PRIVATE)
|
||||
}
|
||||
)
|
||||
}).apply {
|
||||
returnType = context.irBuiltIns.unitType
|
||||
}
|
||||
|
||||
private inner class ExpressionSlicer(val suspensionPointIdType: KotlinType): IrElementTransformerVoid() {
|
||||
private inner class ExpressionSlicer(val suspensionPointIdType: IrType): IrElementTransformerVoid() {
|
||||
// TODO: optimize - it has square complexity.
|
||||
|
||||
override fun visitSetField(expression: IrSetField): IrExpression {
|
||||
@@ -983,13 +1022,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
newChildren[index] = transformedChild
|
||||
else {
|
||||
// Save to temporary in order to save execution order.
|
||||
val tmp = IrVariableSymbolImpl(
|
||||
IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration = irFunction.descriptor,
|
||||
name = "tmp${tempIndex++}".synthesizedName,
|
||||
outType = transformedChild.type)
|
||||
)
|
||||
tempStatements += irVar(tmp, transformedChild)
|
||||
val tmp = irVar(transformedChild)
|
||||
|
||||
tempStatements += tmp
|
||||
newChildren[index] = irGet(tmp)
|
||||
}
|
||||
}
|
||||
@@ -1001,7 +1036,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
calledSaveState = true
|
||||
val firstArgument = newChildren[2]!!
|
||||
newChildren[2] = irBlock(firstArgument) {
|
||||
+irCall(saveStateSymbol)
|
||||
+irCall(saveState)
|
||||
+firstArgument
|
||||
}
|
||||
suspendCall = newChildren[2]
|
||||
@@ -1014,17 +1049,12 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
newChildren[numberOfChildren - 1] =
|
||||
irBlock(lastChild) {
|
||||
if (lastChild.isPure()) {
|
||||
+irCall(saveStateSymbol)
|
||||
+irCall(saveState)
|
||||
+lastChild
|
||||
} else {
|
||||
val tmp = IrVariableSymbolImpl(
|
||||
IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration = irFunction.descriptor,
|
||||
name = "tmp${tempIndex++}".synthesizedName,
|
||||
outType = lastChild.type)
|
||||
)
|
||||
+irVar(tmp, lastChild)
|
||||
+irCall(saveStateSymbol)
|
||||
val tmp = irVar(lastChild)
|
||||
+tmp
|
||||
+irCall(saveState)
|
||||
+irGet(tmp)
|
||||
}
|
||||
}
|
||||
@@ -1053,27 +1083,27 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
val suspensionPointIdParameter = IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration = irFunction.descriptor,
|
||||
name = "suspensionPointId${suspensionPointIdIndex++}".synthesizedName,
|
||||
outType = suspensionPointIdType)
|
||||
outType = suspensionPointIdType.toKotlinType())
|
||||
val suspensionPoint = IrSuspensionPointImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = context.builtIns.nullableAnyType,
|
||||
suspensionPointIdParameter = irVar(suspensionPointIdParameter, null),
|
||||
type = context.irBuiltIns.anyNType,
|
||||
suspensionPointIdParameter = irVar(suspensionPointIdParameter, suspensionPointIdType),
|
||||
result = irBlock(startOffset, endOffset) {
|
||||
if (!calledSaveState)
|
||||
+irCall(saveStateSymbol)
|
||||
+irSetVar(suspendResult, suspendCall)
|
||||
+irCall(saveState)
|
||||
+irSetVar(suspendResult.symbol, suspendCall)
|
||||
+irReturnIfSuspended(suspendResult)
|
||||
+irGet(suspendResult)
|
||||
},
|
||||
resumeResult = irBlock(startOffset, endOffset) {
|
||||
+irCall(restoreStateSymbol)
|
||||
+irCall(restoreState)
|
||||
+irThrowIfNotNull(exceptionArgument)
|
||||
+irGet(dataArgument)
|
||||
})
|
||||
val expressionResult = when {
|
||||
suspendCall.type.isUnit() -> irImplicitCoercionToUnit(suspensionPoint)
|
||||
else -> irCast(suspensionPoint, suspendCall.type, suspendCall.type)
|
||||
else -> irAs(suspensionPoint, suspendCall.type)
|
||||
}
|
||||
return irBlock(expression) {
|
||||
tempStatements.forEach { +it }
|
||||
@@ -1132,27 +1162,31 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
get() = this is IrCall && this.descriptor.original == returnIfSuspendedDescriptor
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.irVar(initializer: IrExpression) =
|
||||
irVar(
|
||||
IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration = irFunction.descriptor,
|
||||
name = "tmp${tempIndex++}".synthesizedName,
|
||||
outType = initializer.type.toKotlinType()
|
||||
),
|
||||
initializer.type
|
||||
).apply { this.initializer = initializer }
|
||||
|
||||
private fun IrBuilderWithScope.irVar(descriptor: VariableDescriptor, initializer: IrExpression?) =
|
||||
IrVariableImpl(startOffset, endOffset, DECLARATION_ORIGIN_COROUTINE_IMPL, descriptor, initializer)
|
||||
private fun IrBuilderWithScope.irVar(descriptor: VariableDescriptor, type: IrType) =
|
||||
IrVariableImpl(startOffset, endOffset, DECLARATION_ORIGIN_COROUTINE_IMPL, descriptor, type)
|
||||
|
||||
private fun IrBuilderWithScope.irVar(symbol: IrVariableSymbol, initializer: IrExpression?) =
|
||||
IrVariableImpl(startOffset, endOffset, DECLARATION_ORIGIN_COROUTINE_IMPL, symbol).apply {
|
||||
this.initializer = initializer
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.irReturnIfSuspended(value: IrValueSymbol) =
|
||||
private fun IrBuilderWithScope.irReturnIfSuspended(value: IrValueDeclaration) =
|
||||
irIfThen(irEqeqeq(irGet(value), irCall(symbols.coroutineSuspendedGetter)),
|
||||
irReturn(irGet(value)))
|
||||
|
||||
private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueSymbol) =
|
||||
private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueDeclaration) =
|
||||
irIfThen(irNot(irEqeqeq(irGet(exception), irNull())),
|
||||
irThrow(irImplicitCast(irGet(exception), exception.descriptor.type.makeNotNullable())))
|
||||
irThrow(irImplicitCast(irGet(exception), exception.type.makeNotNull())))
|
||||
}
|
||||
|
||||
private open class VariablesScopeTracker: IrElementVisitorVoid {
|
||||
|
||||
protected val scopeStack = mutableListOf<MutableSet<IrVariableSymbol>>(mutableSetOf())
|
||||
protected val scopeStack = mutableListOf<MutableSet<IrVariable>>(mutableSetOf())
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
@@ -1174,7 +1208,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
|
||||
override fun visitVariable(declaration: IrVariable) {
|
||||
super.visitVariable(declaration)
|
||||
scopeStack.peek()!!.add(declaration.symbol)
|
||||
scopeStack.peek()!!.add(declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
-37
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.backend.common.reportWarning
|
||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithoutArguments
|
||||
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
@@ -38,15 +40,14 @@ import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
@@ -98,50 +99,50 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
add(TestFunction(function, kind))
|
||||
|
||||
private fun <T: IrElement> IrStatementsBuilder<T>.generateFunctionRegistration(
|
||||
receiver: IrValueSymbol,
|
||||
receiver: IrValueDeclaration,
|
||||
registerTestCase: IrFunctionSymbol,
|
||||
registerFunction: IrFunctionSymbol,
|
||||
functions: Collection<TestFunction>) {
|
||||
functions.forEach {
|
||||
if (it.kind == FunctionKind.TEST) {
|
||||
// Call registerTestCase(name: String, testFunction: () -> Unit) method.
|
||||
+irCall(registerTestCase).apply {
|
||||
+irCall(registerTestCase, registerTestCase.descriptor.returnType!!.toErasedIrType()).apply {
|
||||
dispatchReceiver = irGet(receiver)
|
||||
putValueArgument(0, IrConstImpl.string(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
context.builtIns.stringType,
|
||||
context.irBuiltIns.stringType,
|
||||
it.function.descriptor.name.identifier)
|
||||
)
|
||||
putValueArgument(1, IrFunctionReferenceImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
descriptor.valueParameters[1].type,
|
||||
descriptor.valueParameters[1].type.toErasedIrType(),
|
||||
it.function,
|
||||
it.function.descriptor, emptyMap()))
|
||||
it.function.descriptor, 0))
|
||||
putValueArgument(2, IrConstImpl.boolean(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
context.builtIns.booleanType,
|
||||
context.irBuiltIns.booleanType,
|
||||
it.ignored
|
||||
))
|
||||
}
|
||||
} else {
|
||||
// Call registerFunction(kind: TestFunctionKind, () -> Unit) method.
|
||||
+irCall(registerFunction).apply {
|
||||
+irCall(registerFunction, registerFunction.descriptor.returnType!!.toErasedIrType()).apply {
|
||||
dispatchReceiver = irGet(receiver)
|
||||
val testKindEntry = it.kind.runtimeKind
|
||||
putValueArgument(0, IrGetEnumValueImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
testKindEntry.descriptor.defaultType,
|
||||
symbols.testFunctionKind.typeWithoutArguments,
|
||||
testKindEntry)
|
||||
)
|
||||
putValueArgument(1, IrFunctionReferenceImpl(UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
descriptor.valueParameters[1].type,
|
||||
descriptor.valueParameters[1].type.toErasedIrType(),
|
||||
it.function,
|
||||
it.function.descriptor, emptyMap()))
|
||||
it.function.descriptor, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +283,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
//region Symbol and IR builders
|
||||
|
||||
/** Base class for getters (createInstance and getCompanion). */
|
||||
private abstract inner class GetterBuilder(val returnType: KotlinType,
|
||||
private abstract inner class GetterBuilder(val returnType: IrType,
|
||||
val testSuite: IrClassSymbol,
|
||||
val getterName: Name)
|
||||
: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrFunction>() {
|
||||
@@ -300,7 +301,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
/* dispatchReceiverParameter = */ testSuite.descriptor.thisAsReceiverParameter,
|
||||
/* typeParameters = */ emptyList(),
|
||||
/* unsubstitutedValueParameters = */ emptyList(),
|
||||
/* returnType = */ returnType,
|
||||
/* returnType = */ returnType.toKotlinType(),
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PROTECTED
|
||||
).apply {
|
||||
@@ -324,18 +325,21 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
* returning a reference to an object represented by `[objectSymbol]`.
|
||||
*/
|
||||
private inner class ObjectGetterBuilder(val objectSymbol: IrClassSymbol, testSuite: IrClassSymbol, getterName: Name)
|
||||
: GetterBuilder(objectSymbol.descriptor.defaultType, testSuite, getterName) {
|
||||
: GetterBuilder(objectSymbol.typeWithoutArguments, testSuite, getterName) {
|
||||
|
||||
override fun buildIr(): IrFunction = IrFunctionImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
TEST_SUITE_GENERATED_MEMBER,
|
||||
symbol).apply {
|
||||
|
||||
this.returnType = this@ObjectGetterBuilder.returnType
|
||||
|
||||
val builder = context.createIrBuilder(symbol)
|
||||
createParameterDeclarations()
|
||||
createParameterDeclarations(context.ir.symbols.symbolTable)
|
||||
body = builder.irBlockBody {
|
||||
+irReturn(IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
objectSymbol.descriptor.defaultType, objectSymbol)
|
||||
objectSymbol.typeWithoutArguments, objectSymbol)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -346,17 +350,20 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
* returning a new instance of class referenced by [classSymbol].
|
||||
*/
|
||||
private inner class InstanceGetterBuilder(val classSymbol: IrClassSymbol, testSuite: IrClassSymbol, getterName: Name)
|
||||
: GetterBuilder(classSymbol.descriptor.defaultType, testSuite, getterName) {
|
||||
: GetterBuilder(classSymbol.typeWithStarProjections, testSuite, getterName) {
|
||||
|
||||
override fun buildIr() = IrFunctionImpl(
|
||||
startOffset = UNDEFINED_OFFSET,
|
||||
endOffset = UNDEFINED_OFFSET,
|
||||
origin = TEST_SUITE_GENERATED_MEMBER,
|
||||
symbol = symbol).apply {
|
||||
|
||||
this.returnType = this@InstanceGetterBuilder.returnType
|
||||
|
||||
val builder = context.createIrBuilder(symbol)
|
||||
createParameterDeclarations()
|
||||
createParameterDeclarations(context.ir.symbols.symbolTable)
|
||||
body = builder.irBlockBody {
|
||||
val constructor = classSymbol.constructors.single { it.descriptor.valueParameters.isEmpty() }
|
||||
val constructor = classSymbol.owner.constructors.single { it.valueParameters.isEmpty() }
|
||||
+irReturn(irCall(constructor))
|
||||
}
|
||||
}
|
||||
@@ -385,15 +392,18 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
UNDEFINED_OFFSET,
|
||||
TEST_SUITE_GENERATED_MEMBER,
|
||||
symbol).apply {
|
||||
createParameterDeclarations()
|
||||
|
||||
val registerTestCase = testSuite.getFunction("registerTestCase") {
|
||||
returnType = testSuite.typeWithStarProjections
|
||||
|
||||
createParameterDeclarations(context.ir.symbols.symbolTable)
|
||||
|
||||
val registerTestCase = symbols.baseClassSuite.getFunction("registerTestCase") {
|
||||
it.valueParameters.size == 3 &&
|
||||
KotlinBuiltIns.isString(it.valueParameters[0].type) && // name: String
|
||||
it.valueParameters[1].type.isFunctionType && // function: testClassType.() -> Unit
|
||||
KotlinBuiltIns.isBoolean(it.valueParameters[2].type) // ignored: Boolean
|
||||
}
|
||||
val registerFunction = testSuite.getFunction("registerFunction") {
|
||||
val registerFunction = symbols.baseClassSuite.getFunction("registerFunction") {
|
||||
it.valueParameters.size == 2 &&
|
||||
it.valueParameters[0].type == symbols.testFunctionKind.descriptor.defaultType && // kind: TestFunctionKind
|
||||
it.valueParameters[1].type.isFunctionType // function: () -> Unit
|
||||
@@ -404,26 +414,28 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
+IrDelegatingConstructorCallImpl(
|
||||
startOffset = UNDEFINED_OFFSET,
|
||||
endOffset = UNDEFINED_OFFSET,
|
||||
type = context.irBuiltIns.unitType,
|
||||
symbol = symbols.symbolTable.referenceConstructor(superConstructor),
|
||||
descriptor = superConstructor,
|
||||
typeArgumentsCount = 2
|
||||
).apply {
|
||||
copyTypeArgumentsFrom(mapOf(superConstructor.typeParameters[0] to testClassType,
|
||||
superConstructor.typeParameters[1] to testCompanionType))
|
||||
putTypeArgument(0, testClassType.toErasedIrType())
|
||||
putTypeArgument(1, testCompanionType.toErasedIrType())
|
||||
|
||||
putValueArgument(0, IrConstImpl.string(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
context.builtIns.stringType,
|
||||
context.irBuiltIns.stringType,
|
||||
suiteName)
|
||||
)
|
||||
putValueArgument(1, IrConstImpl.boolean(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
context.builtIns.booleanType,
|
||||
context.irBuiltIns.booleanType,
|
||||
ignored
|
||||
))
|
||||
}
|
||||
generateFunctionRegistration(testSuite.owner.thisReceiver!!.symbol,
|
||||
generateFunctionRegistration(testSuite.owner.thisReceiver!!,
|
||||
registerTestCase, registerFunction, functions)
|
||||
}
|
||||
}
|
||||
@@ -445,6 +457,8 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
)
|
||||
}
|
||||
|
||||
private fun KotlinType.toErasedIrType(): IrType = context.ir.translateErased(this)
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -489,17 +503,17 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildIr() = IrClassImpl(
|
||||
override fun buildIr() = symbols.symbolTable.declareClass(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
TEST_SUITE_CLASS,
|
||||
symbol).apply {
|
||||
symbol.descriptor).apply {
|
||||
createParameterDeclarations()
|
||||
addMember(constructorBuilder.ir)
|
||||
addMember(instanceGetterBuilder.ir)
|
||||
companionGetterBuilder?.let { addMember(it.ir) }
|
||||
addFakeOverrides()
|
||||
setSuperSymbols(context.ir.symbols.symbolTable)
|
||||
addFakeOverrides(symbols.symbolTable)
|
||||
setSuperSymbols(symbols.symbolTable)
|
||||
}
|
||||
|
||||
override fun doInitialize() {
|
||||
@@ -526,7 +540,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
companionGetterBuilder?.initialize()
|
||||
}
|
||||
|
||||
override fun buildSymbol() = IrClassSymbolImpl(
|
||||
override fun buildSymbol() = symbols.symbolTable.referenceClass(
|
||||
ClassDescriptorImpl(
|
||||
/* containingDeclaration = */ containingDeclaration,
|
||||
/* name = */ suiteClassName,
|
||||
@@ -549,8 +563,9 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
testClass.functions)) {
|
||||
initialize()
|
||||
irFile.addChild(ir)
|
||||
val irConstructor = ir.constructors.single()
|
||||
irFile.addTopLevelInitializer(
|
||||
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, ir.symbol.constructors.single())
|
||||
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irConstructor.returnType, irConstructor.symbol)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -575,10 +590,10 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
||||
irFile.addTopLevelInitializer(builder.irBlock {
|
||||
val constructorCall = irCall(symbols.topLevelSuiteConstructor).apply {
|
||||
putValueArgument(0, IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
context.builtIns.stringType, suiteName))
|
||||
context.irBuiltIns.stringType, suiteName))
|
||||
}
|
||||
val testSuiteVal = irTemporary(constructorCall, "topLevelTestSuite")
|
||||
generateFunctionRegistration(testSuiteVal.symbol,
|
||||
generateFunctionRegistration(testSuiteVal,
|
||||
symbols.topLevelSuiteRegisterTestCase,
|
||||
symbols.topLevelSuiteRegisterFunction,
|
||||
functions)
|
||||
|
||||
+30
-23
@@ -21,22 +21,27 @@ import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.at
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.containsNull
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isSubtypeOf
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.makeNotNull
|
||||
import org.jetbrains.kotlin.ir.types.makeNullable
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
|
||||
/**
|
||||
* This lowering pass lowers some [IrTypeOperatorCall]s.
|
||||
@@ -60,22 +65,24 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun
|
||||
return declaration
|
||||
}
|
||||
|
||||
private fun KotlinType.erasure(): KotlinType {
|
||||
val descriptor = this.constructor.declarationDescriptor
|
||||
return when (descriptor) {
|
||||
is ClassDescriptor -> this
|
||||
is TypeParameterDescriptor -> {
|
||||
val upperBound = descriptor.upperBounds.singleOrNull() ?:
|
||||
TODO("$descriptor : ${descriptor.upperBounds}")
|
||||
private fun IrType.erasure(): IrType {
|
||||
if (this !is IrSimpleType) return this
|
||||
|
||||
if (this.isMarkedNullable) {
|
||||
val classifier = this.classifier
|
||||
return when (classifier) {
|
||||
is IrClassSymbol -> this
|
||||
is IrTypeParameterSymbol -> {
|
||||
val upperBound = classifier.owner.superTypes.singleOrNull() ?:
|
||||
TODO("${classifier.descriptor} : ${classifier.descriptor.upperBounds}")
|
||||
|
||||
if (this.hasQuestionMark) {
|
||||
// `T?`
|
||||
upperBound.erasure().makeNullable()
|
||||
} else {
|
||||
upperBound.erasure()
|
||||
}
|
||||
}
|
||||
else -> TODO(this.toString())
|
||||
else -> TODO(classifier.toString())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,32 +90,32 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun
|
||||
builder.at(expression)
|
||||
val typeOperand = expression.typeOperand.erasure()
|
||||
|
||||
assert (!TypeUtils.hasNullableSuperType(typeOperand)) // So that `isNullable()` <=> `isMarkedNullable`.
|
||||
// assert (!TypeUtils.hasNullableSuperType(typeOperand)) // So that `isNullable()` <=> `isMarkedNullable`.
|
||||
|
||||
// TODO: consider the case when expression type is wrong e.g. due to generics-related unchecked casts.
|
||||
|
||||
return when {
|
||||
expression.argument.type.isSubtypeOf(typeOperand) -> expression.argument
|
||||
|
||||
expression.argument.type.isNullable() -> {
|
||||
expression.argument.type.containsNull() -> {
|
||||
with (builder) {
|
||||
irLetS(expression.argument) { argument ->
|
||||
irIfThenElse(
|
||||
type = expression.type,
|
||||
condition = irEqeqeq(irGet(argument), irNull()),
|
||||
condition = irEqeqeq(irGet(argument.owner), irNull()),
|
||||
|
||||
thenPart = if (typeOperand.isMarkedNullable)
|
||||
thenPart = if (typeOperand.isSimpleTypeWithQuestionMark)
|
||||
irNull()
|
||||
else
|
||||
irCall(throwTypeCastException),
|
||||
irCall(throwTypeCastException.owner),
|
||||
|
||||
elsePart = irAs(irGet(argument), typeOperand.makeNotNullable())
|
||||
elsePart = irAs(irGet(argument.owner), typeOperand.makeNotNull())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typeOperand.isMarkedNullable -> builder.irAs(expression.argument, typeOperand.makeNotNullable())
|
||||
typeOperand.isSimpleTypeWithQuestionMark -> builder.irAs(expression.argument, typeOperand.makeNotNull())
|
||||
|
||||
typeOperand == expression.typeOperand -> expression
|
||||
|
||||
@@ -124,8 +131,8 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun
|
||||
return builder.irBlock(expression) {
|
||||
+irLetS(expression.argument) { variable ->
|
||||
irIfThenElse(expression.type,
|
||||
condition = irIs(irGet(variable), typeOperand),
|
||||
thenPart = irImplicitCast(irGet(variable), typeOperand),
|
||||
condition = irIs(irGet(variable.owner), typeOperand),
|
||||
thenPart = irImplicitCast(irGet(variable.owner), typeOperand),
|
||||
elsePart = irNull())
|
||||
}
|
||||
}
|
||||
|
||||
+42
-31
@@ -35,24 +35,23 @@ import org.jetbrains.kotlin.backend.konan.isValueType
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.constructedClass
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
private fun getClassWithBoxingIncluded(type: KotlinType, ir: KonanIr): ClassDescriptor? {
|
||||
private fun getClassWithBoxingIncluded(type: IrType, ir: KonanIr): ClassDescriptor? {
|
||||
/*
|
||||
* Some primitive types can be null and some can't. Those that can't must be replaced with the corresponding box.
|
||||
* Int -> Int
|
||||
@@ -61,29 +60,29 @@ private fun getClassWithBoxingIncluded(type: KotlinType, ir: KonanIr): ClassDesc
|
||||
* CPointer -> CPointer
|
||||
* CPointer? -> CPointer
|
||||
*/
|
||||
return if (type.correspondingValueType == null && type.makeNotNullable().correspondingValueType != null)
|
||||
ir.getClass(ir.symbols.getTypeConversion(type.makeNotNullable(), type)!!.descriptor.returnType!!)!!
|
||||
return if (type.correspondingValueType == null && type.makeNotNull().correspondingValueType != null)
|
||||
ir.symbols.getTypeConversion(type.makeNotNull(), type)!!.owner.returnType.getClass()!!
|
||||
else
|
||||
ir.getClass(type)
|
||||
type.getClass()
|
||||
}
|
||||
|
||||
private fun computeErasure(type: KotlinType, ir: KonanIr, erasure: MutableList<ClassDescriptor>) {
|
||||
private fun computeErasure(type: IrType, ir: KonanIr, erasure: MutableList<ClassDescriptor>) {
|
||||
val irClass = getClassWithBoxingIncluded(type, ir)
|
||||
if (irClass != null) {
|
||||
erasure += irClass
|
||||
} else {
|
||||
val descriptor = type.constructor.declarationDescriptor
|
||||
if (descriptor is TypeParameterDescriptor) {
|
||||
descriptor.upperBounds.forEach {
|
||||
val classifier = type.classifierOrFail
|
||||
if (classifier is IrTypeParameterSymbol) {
|
||||
classifier.owner.superTypes.forEach {
|
||||
computeErasure(it, ir, erasure)
|
||||
}
|
||||
} else {
|
||||
TODO(descriptor.toString())
|
||||
TODO(classifier.descriptor.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun KotlinType.erasure(context: Context): List<ClassDescriptor> {
|
||||
internal fun IrType.erasure(context: Context): List<ClassDescriptor> {
|
||||
val result = mutableListOf<ClassDescriptor>()
|
||||
computeErasure(this, context.ir, result)
|
||||
return result
|
||||
@@ -163,7 +162,7 @@ private class ExpressionValuesExtractor(val context: Context,
|
||||
forEachValue(
|
||||
expression = (expression.statements.last() as? IrExpression)
|
||||
?: IrGetObjectValueImpl(expression.startOffset, expression.endOffset,
|
||||
context.builtIns.unitType, context.ir.symbols.unit),
|
||||
context.irBuiltIns.unitType, context.ir.symbols.unit),
|
||||
block = block
|
||||
)
|
||||
}
|
||||
@@ -187,7 +186,8 @@ private class ExpressionValuesExtractor(val context: Context,
|
||||
else { // Propagate cast to sub-values.
|
||||
forEachValue(expression.argument) { value ->
|
||||
with(expression) {
|
||||
block(IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, typeOperand, value))
|
||||
block(IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, typeOperand,
|
||||
typeOperand.classifierOrFail, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,7 +254,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor) {
|
||||
val body = declaration.body
|
||||
assert (body != null || declaration.symbol.constructedClass.kind == ClassKind.ANNOTATION_CLASS) {
|
||||
assert (body != null || declaration.constructedClass.kind == ClassKind.ANNOTATION_CLASS) {
|
||||
"Non-annotation class constructor has empty body"
|
||||
}
|
||||
DEBUG_OUTPUT(0) {
|
||||
@@ -280,7 +280,8 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
println("Analysing global field ${declaration.descriptor}")
|
||||
println("IR: ${ir2stringWhole(declaration)}")
|
||||
}
|
||||
analyze(declaration, IrSetFieldImpl(it.startOffset, it.endOffset, declaration.symbol, null, it.expression))
|
||||
analyze(declaration, IrSetFieldImpl(it.startOffset, it.endOffset, declaration.symbol, null,
|
||||
it.expression, context.irBuiltIns.unitType))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,11 +380,13 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
if (expression is IrCall && expression.symbol == scheduleImplSymbol) {
|
||||
// Producer and job of scheduleImpl are called externally, we need to reflect this somehow.
|
||||
val producerInvocation = IrCallImpl(expression.startOffset, expression.endOffset,
|
||||
scheduleImplProducerInvoke.returnType,
|
||||
scheduleImplProducerInvoke.symbol, scheduleImplProducerInvoke.descriptor)
|
||||
producerInvocation.dispatchReceiver = expression.getValueArgument(2)
|
||||
val jobFunctionReference = expression.getValueArgument(3) as? IrFunctionReference
|
||||
?: error("A function reference expected")
|
||||
val jobInvocation = IrCallImpl(expression.startOffset, expression.endOffset,
|
||||
jobFunctionReference.symbol.owner.returnType,
|
||||
jobFunctionReference.symbol, jobFunctionReference.descriptor)
|
||||
jobInvocation.putValueArgument(0, producerInvocation)
|
||||
|
||||
@@ -447,6 +450,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "doResume" }.symbol
|
||||
|
||||
private val getContinuationSymbol = context.ir.symbols.getContinuation
|
||||
private val continuationType = getContinuationSymbol.owner.returnType
|
||||
|
||||
private val arrayGetSymbol = context.ir.symbols.arrayGet
|
||||
private val arraySetSymbol = context.ir.symbols.arraySet
|
||||
@@ -631,21 +635,27 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
val owner = callee.containingDeclaration as ClassDescriptor
|
||||
val actualReceiverType = value.dispatchReceiver!!.type
|
||||
val receiverType =
|
||||
if (actualReceiverType.constructor.declarationDescriptor is TypeParameterDescriptor
|
||||
if (actualReceiverType.classifierOrNull is IrTypeParameterSymbol
|
||||
|| !callee.isReal /* Could be a bridge. */)
|
||||
symbolTable.mapClass(owner)
|
||||
else {
|
||||
val actualClassAtCallsite = actualReceiverType.constructor.declarationDescriptor as org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
assert (DescriptorUtils.isSubclass(actualClassAtCallsite, owner.descriptor)) {
|
||||
"Expected an inheritor of ${owner.descriptor}, but was $actualClassAtCallsite"
|
||||
val actualClassAtCallsite =
|
||||
actualReceiverType.classifierOrFail.descriptor
|
||||
as org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
// assert (DescriptorUtils.isSubclass(actualClassAtCallsite, owner.descriptor)) {
|
||||
// "Expected an inheritor of ${owner.descriptor}, but was $actualClassAtCallsite"
|
||||
// }
|
||||
if (DescriptorUtils.isSubclass(actualClassAtCallsite, owner.descriptor)) {
|
||||
symbolTable.mapType(
|
||||
actualReceiverType.let {
|
||||
if (it.isValueType()) // A virtual call on a value type - it must be boxed.
|
||||
context.ir.symbols.getTypeConversion(it, it.makeNullable())!!.owner.returnType
|
||||
else it
|
||||
}
|
||||
)
|
||||
} else {
|
||||
symbolTable.mapClass(owner)
|
||||
}
|
||||
symbolTable.mapType(
|
||||
actualReceiverType.let {
|
||||
if (it.isValueType()) // A virtual call on a value type - it must be boxed.
|
||||
context.ir.symbols.getTypeConversion(it, it.makeNullable())!!.descriptor.returnType!!
|
||||
else it
|
||||
}
|
||||
)
|
||||
}
|
||||
if (owner.isInterface) {
|
||||
val calleeHash = callee.functionName.localHash.value
|
||||
@@ -681,8 +691,9 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
}
|
||||
|
||||
is IrDelegatingConstructorCall -> {
|
||||
val thiz = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
(descriptor as ConstructorDescriptor).constructedClass.thisReceiver!!.symbol)
|
||||
val thisReceiver = (descriptor as ConstructorDescriptor).constructedClass.thisReceiver!!
|
||||
val thiz = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, thisReceiver.type,
|
||||
thisReceiver.symbol)
|
||||
val arguments = listOf(thiz) + value.getArguments().map { it.second }
|
||||
DataFlowIR.Node.StaticCall(
|
||||
symbolTable.mapFunction(value.symbol.owner),
|
||||
|
||||
+8
-8
@@ -35,6 +35,10 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetField
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isNothing
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||
@@ -42,10 +46,6 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.constants.IntValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
internal object DataFlowIR {
|
||||
|
||||
@@ -468,7 +468,7 @@ internal object DataFlowIR {
|
||||
private val pointsToOnWhomDescriptor = pointsToAnnotationDescriptor.unsubstitutedPrimaryConstructor!!.valueParameters.single()
|
||||
|
||||
private val getContinuationSymbol = context.ir.symbols.getContinuation
|
||||
private val continuationType = getContinuationSymbol.descriptor.returnType!!
|
||||
private val continuationType = getContinuationSymbol.owner.returnType
|
||||
|
||||
var privateTypeIndex = 0
|
||||
var privateFunIndex = 0
|
||||
@@ -524,7 +524,7 @@ internal object DataFlowIR {
|
||||
|
||||
classMap[descriptor] = type
|
||||
|
||||
type.superTypes += descriptor.defaultType.immediateSupertypes().map { mapType(it) }
|
||||
type.superTypes += descriptor.superTypes.map { mapType(it) }
|
||||
if (!isAbstract) {
|
||||
val vtableBuilder = context.getVtableBuilder(descriptor)
|
||||
type.vtable += vtableBuilder.vtableEntries.map { mapFunction(it.getImplementation(context)!!) }
|
||||
@@ -541,7 +541,7 @@ internal object DataFlowIR {
|
||||
return erasure.singleOrNull { !it.isInterface } ?: context.ir.symbols.any.owner
|
||||
}
|
||||
|
||||
fun mapType(type: KotlinType) = mapClass(choosePrimary(type.erasure(context)))
|
||||
fun mapType(type: IrType) = mapClass(choosePrimary(type.erasure(context)))
|
||||
|
||||
// TODO: use from LlvmDeclarations.
|
||||
private fun getFqName(descriptor: DeclarationDescriptor): FqName =
|
||||
@@ -605,7 +605,7 @@ internal object DataFlowIR {
|
||||
.map { mapClass(choosePrimary(it.erasure(context))) }
|
||||
.toTypedArray()
|
||||
symbol.returnType = mapType(if (descriptor.isSuspend)
|
||||
context.builtIns.anyType
|
||||
context.irBuiltIns.anyType
|
||||
else
|
||||
descriptor.returnType)
|
||||
|
||||
|
||||
+24
-24
@@ -27,8 +27,7 @@ import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.backend.konan.ir.IrPrivateClassReferenceImpl
|
||||
import org.jetbrains.kotlin.backend.konan.ir.IrPrivateFunctionCallImpl
|
||||
import org.jetbrains.kotlin.backend.konan.lower.nullConst
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.getErasedTypeClass
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.getErasedTypeClass
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -40,14 +39,14 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.getValueArgument
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrWhenImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.addArguments
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.ir.util.explicitParameters
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
@@ -1009,7 +1008,7 @@ internal object Devirtualization {
|
||||
|
||||
class PossiblyCoercedValue(val value: IrVariable, val coercion: IrFunctionSymbol?) {
|
||||
fun getFullValue(irBuilder: IrBuilderWithScope) = irBuilder.run {
|
||||
irCoerce(irGet(value.symbol), coercion)
|
||||
irCoerce(irGet(value), coercion)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1020,7 +1019,7 @@ internal object Devirtualization {
|
||||
val coercion = expression as IrCall
|
||||
PossiblyCoercedValue(
|
||||
irTemporary(irImplicitCast(coercion.getArguments().single().second,
|
||||
coercion.descriptor.explicitParameters.single().type))
|
||||
coercion.symbol.owner.explicitParameters.single().type))
|
||||
, coercion.symbol)
|
||||
}
|
||||
|
||||
@@ -1041,12 +1040,12 @@ internal object Devirtualization {
|
||||
val coercion = context.ir.symbols.getTypeConversion(type.correspondingValueType, targetType.correspondingValueType)
|
||||
?: return possiblyCoercedValue.getFullValue(this)
|
||||
if (prevCoercion == null)
|
||||
return irCoerce(irGet(value.symbol), coercion)
|
||||
return irCoerce(irGet(value), coercion)
|
||||
assertCoercionsMatch(coercion, prevCoercion)
|
||||
return irGet(value.symbol)
|
||||
return irGet(value)
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: KotlinType,
|
||||
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: IrType,
|
||||
devirtualizedCallee: DataFlowIR.FunctionSymbol.Declared) =
|
||||
IrPrivateFunctionCallImpl(
|
||||
startOffset = startOffset,
|
||||
@@ -1062,7 +1061,7 @@ internal object Devirtualization {
|
||||
virtualCallee = callee
|
||||
)
|
||||
|
||||
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: KotlinType,
|
||||
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: IrType,
|
||||
actualCallee: DataFlowIR.FunctionSymbol.Declared,
|
||||
receiver: IrVariable,
|
||||
extensionReceiver: PossiblyCoercedValue?,
|
||||
@@ -1070,7 +1069,7 @@ internal object Devirtualization {
|
||||
actualCallee.bridgeTarget.let {
|
||||
if (it == null)
|
||||
irDevirtualizedCall(callee, actualType, actualCallee).apply {
|
||||
this.dispatchReceiver = irGet(receiver.symbol)
|
||||
this.dispatchReceiver = irGet(receiver)
|
||||
this.extensionReceiver = extensionReceiver?.getFullValue(this@irDevirtualizedCall)
|
||||
callee.descriptor.valueParameters.forEach {
|
||||
putValueArgument(it.index, parameters[it]!!.getFullValue(this@irDevirtualizedCall))
|
||||
@@ -1079,7 +1078,7 @@ internal object Devirtualization {
|
||||
else {
|
||||
val bridgeTarget = it.resolved() as DataFlowIR.FunctionSymbol.Declared
|
||||
val callResult = irDevirtualizedCall(callee, actualType, bridgeTarget).apply {
|
||||
this.dispatchReceiver = irGet(receiver.symbol)
|
||||
this.dispatchReceiver = irGet(receiver)
|
||||
this.extensionReceiver = extensionReceiver?.let {
|
||||
irCoerceIfNeeded(
|
||||
type = actualCallee.parameterTypes[1].resolved(),
|
||||
@@ -1140,21 +1139,22 @@ internal object Devirtualization {
|
||||
val startOffset = expression.startOffset
|
||||
val endOffset = expression.endOffset
|
||||
val type = if (descriptor.isSuspend)
|
||||
context.builtIns.nullableAnyType
|
||||
else descriptor.original.returnType!!
|
||||
context.irBuiltIns.anyNType
|
||||
else expression.symbol.owner.returnType
|
||||
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset)
|
||||
irBuilder.run {
|
||||
val dispatchReceiver = expression.dispatchReceiver!!
|
||||
return when {
|
||||
possibleCallees.isEmpty() -> irBlock(expression) {
|
||||
+irCall(context.ir.symbols.throwInvalidReceiverTypeException).apply {
|
||||
putValueArgument(0, irCall(context.ir.symbols.kClassImplConstructor, listOf(dispatchReceiver.type)).apply {
|
||||
putValueArgument(0, irCall(context.ir.symbols.getObjectTypeInfo).apply {
|
||||
val throwExpr = irCall(context.ir.symbols.throwInvalidReceiverTypeException.owner).apply {
|
||||
putValueArgument(0, irCall(context.ir.symbols.kClassImplConstructor.owner, listOf(dispatchReceiver.type)).apply {
|
||||
putValueArgument(0, irCall(context.ir.symbols.getObjectTypeInfo.owner).apply {
|
||||
putValueArgument(0, dispatchReceiver)
|
||||
})
|
||||
})
|
||||
}
|
||||
+nullConst(expression, type)
|
||||
// Insert proper unboxing (unreachable code):
|
||||
+irCoerce(throwExpr, context.ir.symbols.getTypeConversion(throwExpr.type, type))
|
||||
}
|
||||
|
||||
optimize && possibleCallees.size == 1 -> { // Monomorphic callsite.
|
||||
@@ -1176,7 +1176,7 @@ internal object Devirtualization {
|
||||
it to irSplitCoercion(expression.getValueArgument(it)!!)
|
||||
}
|
||||
val typeInfo = irTemporary(irCall(context.ir.symbols.getObjectTypeInfo).apply {
|
||||
putValueArgument(0, irGet(receiver.symbol))
|
||||
putValueArgument(0, irGet(receiver))
|
||||
})
|
||||
|
||||
val branches = mutableListOf<IrBranchImpl>()
|
||||
@@ -1186,8 +1186,8 @@ internal object Devirtualization {
|
||||
val expectedTypeInfo = IrPrivateClassReferenceImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = nativePtrType,
|
||||
symbol = IrClassSymbolImpl(dispatchReceiver.type.getErasedTypeClass()),
|
||||
type = context.ir.symbols.nativePtrType,
|
||||
symbol = dispatchReceiver.type.getErasedTypeClass(),
|
||||
classType = receiver.type,
|
||||
moduleDescriptor = actualReceiverType.module!!.descriptor,
|
||||
totalClasses = actualReceiverType.module.numberOfClasses,
|
||||
@@ -1198,7 +1198,7 @@ internal object Devirtualization {
|
||||
irTrue() // Don't check last type in optimize mode.
|
||||
else
|
||||
irCall(nativePtrEqualityOperatorSymbol).apply {
|
||||
putValueArgument(0, irGet(typeInfo.symbol))
|
||||
putValueArgument(0, irGet(typeInfo))
|
||||
putValueArgument(1, expectedTypeInfo)
|
||||
}
|
||||
IrBranchImpl(
|
||||
@@ -1218,7 +1218,7 @@ internal object Devirtualization {
|
||||
irCall(context.ir.symbols.kClassImplConstructor,
|
||||
listOf(dispatchReceiver.type)
|
||||
).apply {
|
||||
putValueArgument(0, irGet(typeInfo.symbol))
|
||||
putValueArgument(0, irGet(typeInfo))
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
+63
-52
@@ -37,10 +37,10 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.addFakeOverrides
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.ir.util.setOverrides
|
||||
import org.jetbrains.kotlin.ir.util.setSuperSymbols
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer
|
||||
import org.jetbrains.kotlin.metadata.KonanIr
|
||||
import org.jetbrains.kotlin.metadata.KonanIr.IrConst.ValueCase.*
|
||||
@@ -82,6 +82,8 @@ internal class IrSerializer(val context: Context,
|
||||
return irDescriptorSerializer.serializeKotlinType(type)
|
||||
}
|
||||
|
||||
private fun serializeKotlinType(type: IrType) = serializeKotlinType(type.toKotlinType())
|
||||
|
||||
private fun serializeDescriptor(descriptor: DeclarationDescriptor): KonanIr.KotlinDescriptor {
|
||||
context.log{"### serializeDescriptor $descriptor"}
|
||||
|
||||
@@ -719,12 +721,12 @@ internal class IrDeserializer(val context: Context,
|
||||
private fun deserializeDescriptor(proto: KonanIr.KotlinDescriptor)
|
||||
= descriptorDeserializer.deserializeDescriptor(proto)
|
||||
|
||||
private fun deserializeTypeArguments(proto: KonanIr.TypeArguments): List<KotlinType> {
|
||||
private fun deserializeTypeArguments(proto: KonanIr.TypeArguments): List<IrType> {
|
||||
context.log{"### deserializeTypeArguments"}
|
||||
val result = mutableListOf<KotlinType>()
|
||||
val result = mutableListOf<IrType>()
|
||||
proto.typeArgumentList.forEach { type ->
|
||||
val kotlinType = deserializeKotlinType(type)
|
||||
result.add(kotlinType)
|
||||
result.add(kotlinType.brokenIr)
|
||||
context.log{"$kotlinType"}
|
||||
}
|
||||
return result
|
||||
@@ -782,6 +784,9 @@ internal class IrDeserializer(val context: Context,
|
||||
return element
|
||||
}
|
||||
|
||||
private val KotlinType.ir: IrType get() = context.ir.translateErased(this)
|
||||
private val KotlinType.brokenIr: IrType get() = context.ir.translateBroken(this)
|
||||
|
||||
private fun deserializeBlock(proto: KonanIr.IrBlock, start: Int, end: Int, type: KotlinType): IrBlock {
|
||||
val statements = mutableListOf<IrStatement>()
|
||||
val statementProtos = proto.statementList
|
||||
@@ -791,7 +796,7 @@ internal class IrDeserializer(val context: Context,
|
||||
|
||||
val isLambdaOrigin = if (proto.isLambdaOrigin) IrStatementOrigin.LAMBDA else null
|
||||
|
||||
return IrBlockImpl(start, end, type, isLambdaOrigin, statements)
|
||||
return IrBlockImpl(start, end, type.ir, isLambdaOrigin, statements)
|
||||
}
|
||||
|
||||
private fun deserializeMemberAccessCommon(access: IrMemberAccessExpression, proto: KonanIr.MemberAccessCommon) {
|
||||
@@ -819,7 +824,7 @@ internal class IrDeserializer(val context: Context,
|
||||
val descriptor = deserializeDescriptor(proto.classDescriptor) as ClassifierDescriptor
|
||||
/** TODO: [createClassifierSymbolForClassReference] is internal function */
|
||||
@Suppress("DEPRECATION")
|
||||
return IrClassReferenceImpl(start, end, type, descriptor, descriptor.defaultType)
|
||||
return IrClassReferenceImpl(start, end, type.ir, descriptor, descriptor.defaultType.ir)
|
||||
}
|
||||
|
||||
private fun deserializeCall(proto: KonanIr.IrCall, start: Int, end: Int, type: KotlinType): IrCall {
|
||||
@@ -832,13 +837,13 @@ internal class IrDeserializer(val context: Context,
|
||||
val call: IrCall = when (proto.kind) {
|
||||
KonanIr.IrCall.Primitive.NOT_PRIMITIVE ->
|
||||
// TODO: implement the last three args here.
|
||||
IrCallImpl(start, end, type, createFunctionSymbol(descriptor), descriptor, proto.memberAccess.typeArguments.typeArgumentCount, null, createClassSymbolOrNull(superDescriptor))
|
||||
IrCallImpl(start, end, type.ir, createFunctionSymbol(descriptor), descriptor, proto.memberAccess.typeArguments.typeArgumentCount, null, createClassSymbolOrNull(superDescriptor))
|
||||
KonanIr.IrCall.Primitive.NULLARY ->
|
||||
IrNullaryPrimitiveImpl(start, end, null, createFunctionSymbol(descriptor))
|
||||
IrNullaryPrimitiveImpl(start, end, type.ir, null, createFunctionSymbol(descriptor))
|
||||
KonanIr.IrCall.Primitive.UNARY ->
|
||||
IrUnaryPrimitiveImpl(start, end, null, createFunctionSymbol(descriptor))
|
||||
IrUnaryPrimitiveImpl(start, end, type.ir, null, createFunctionSymbol(descriptor))
|
||||
KonanIr.IrCall.Primitive.BINARY ->
|
||||
IrBinaryPrimitiveImpl(start, end, null, createFunctionSymbol(descriptor))
|
||||
IrBinaryPrimitiveImpl(start, end, type.ir, null, createFunctionSymbol(descriptor))
|
||||
else -> TODO("Unexpected primitive IrCall.")
|
||||
}
|
||||
deserializeMemberAccessCommon(call, proto.memberAccess)
|
||||
@@ -850,7 +855,7 @@ internal class IrDeserializer(val context: Context,
|
||||
|
||||
val descriptor = deserializeDescriptor(proto.descriptor) as CallableDescriptor
|
||||
val callable = when (descriptor) {
|
||||
is FunctionDescriptor -> IrFunctionReferenceImpl(start, end, type, createFunctionSymbol(descriptor), descriptor, proto.typeArguments.typeArgumentCount, null)
|
||||
is FunctionDescriptor -> IrFunctionReferenceImpl(start, end, type.ir, createFunctionSymbol(descriptor), descriptor, proto.typeArguments.typeArgumentCount, null)
|
||||
else -> TODO()
|
||||
}
|
||||
|
||||
@@ -866,12 +871,12 @@ internal class IrDeserializer(val context: Context,
|
||||
statementProtos.forEach {
|
||||
statements.add(deserializeStatement(it) as IrStatement)
|
||||
}
|
||||
return IrCompositeImpl(start, end, type, null, statements)
|
||||
return IrCompositeImpl(start, end, type.ir, null, statements)
|
||||
}
|
||||
|
||||
private fun deserializeDelegatingConstructorCall(proto: KonanIr.IrDelegatingConstructorCall, start: Int, end: Int): IrDelegatingConstructorCall {
|
||||
val descriptor = deserializeDescriptor(proto.descriptor) as ClassConstructorDescriptor
|
||||
val call = IrDelegatingConstructorCallImpl(start, end, IrConstructorSymbolImpl(descriptor.original), descriptor, proto.memberAccess.typeArguments.typeArgumentCount)
|
||||
val call = IrDelegatingConstructorCallImpl(start, end, context.irBuiltIns.unitType, IrConstructorSymbolImpl(descriptor.original), descriptor, proto.memberAccess.typeArguments.typeArgumentCount)
|
||||
|
||||
deserializeMemberAccessCommon(call, proto.memberAccess)
|
||||
return call
|
||||
@@ -879,7 +884,7 @@ internal class IrDeserializer(val context: Context,
|
||||
|
||||
private fun deserializeGetClass(proto: KonanIr.IrGetClass, start: Int, end: Int, type: KotlinType): IrGetClass {
|
||||
val argument = deserializeExpression(proto.argument)
|
||||
return IrGetClassImpl(start, end, type, argument)
|
||||
return IrGetClassImpl(start, end, type.ir, argument)
|
||||
}
|
||||
|
||||
private fun deserializeGetField(proto: KonanIr.IrGetField, start: Int, end: Int): IrGetField {
|
||||
@@ -892,39 +897,39 @@ internal class IrDeserializer(val context: Context,
|
||||
deserializeExpression(access.receiver)
|
||||
} else null
|
||||
|
||||
return IrGetFieldImpl(start, end, IrFieldSymbolImpl(descriptor), receiver, null, createClassSymbolOrNull(superQualifier))
|
||||
return IrGetFieldImpl(start, end, IrFieldSymbolImpl(descriptor), descriptor.type.ir, receiver, null, createClassSymbolOrNull(superQualifier))
|
||||
}
|
||||
|
||||
private fun deserializeGetValue(proto: KonanIr.IrGetValue, start: Int, end: Int): IrGetValue {
|
||||
val descriptor = deserializeDescriptor(proto.descriptor) as ValueDescriptor
|
||||
|
||||
// TODO: origin!
|
||||
return IrGetValueImpl(start, end, createValueSymbol(descriptor), null)
|
||||
return IrGetValueImpl(start, end, descriptor.type.ir, createValueSymbol(descriptor), null)
|
||||
}
|
||||
|
||||
private fun deserializeGetEnumValue(proto: KonanIr.IrGetEnumValue, start: Int, end: Int): IrGetEnumValue {
|
||||
val type = deserializeKotlinType(proto.type)
|
||||
val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor
|
||||
|
||||
return IrGetEnumValueImpl(start, end, type, IrEnumEntrySymbolImpl(descriptor))
|
||||
return IrGetEnumValueImpl(start, end, type.ir, IrEnumEntrySymbolImpl(descriptor))
|
||||
}
|
||||
|
||||
private fun deserializeGetObject(proto: KonanIr.IrGetObject, start: Int, end: Int, type: KotlinType): IrGetObjectValue {
|
||||
val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor
|
||||
return IrGetObjectValueImpl(start, end, type, IrClassSymbolImpl(descriptor))
|
||||
return IrGetObjectValueImpl(start, end, type.ir, IrClassSymbolImpl(descriptor))
|
||||
}
|
||||
|
||||
private fun deserializeInstanceInitializerCall(proto: KonanIr.IrInstanceInitializerCall, start: Int, end: Int): IrInstanceInitializerCall {
|
||||
val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor
|
||||
|
||||
return IrInstanceInitializerCallImpl(start, end, IrClassSymbolImpl(descriptor))
|
||||
return IrInstanceInitializerCallImpl(start, end, IrClassSymbolImpl(descriptor), context.irBuiltIns.unitType)
|
||||
}
|
||||
|
||||
private fun deserializeReturn(proto: KonanIr.IrReturn, start: Int, end: Int, type: KotlinType): IrReturn {
|
||||
val descriptor =
|
||||
deserializeDescriptor(proto.returnTarget) as FunctionDescriptor
|
||||
val value = deserializeExpression(proto.value)
|
||||
return IrReturnImpl(start, end, type, createFunctionSymbol(descriptor), value)
|
||||
return IrReturnImpl(start, end, context.irBuiltIns.nothingType, createFunctionSymbol(descriptor), value)
|
||||
}
|
||||
|
||||
private fun deserializeSetField(proto: KonanIr.IrSetField, start: Int, end: Int): IrSetField {
|
||||
@@ -938,13 +943,13 @@ internal class IrDeserializer(val context: Context,
|
||||
} else null
|
||||
val value = deserializeExpression(proto.value)
|
||||
|
||||
return IrSetFieldImpl(start, end, IrFieldSymbolImpl(descriptor), receiver, value, null, createClassSymbolOrNull(superQualifier))
|
||||
return IrSetFieldImpl(start, end, IrFieldSymbolImpl(descriptor), receiver, value, context.irBuiltIns.unitType, null, createClassSymbolOrNull(superQualifier))
|
||||
}
|
||||
|
||||
private fun deserializeSetVariable(proto: KonanIr.IrSetVariable, start: Int, end: Int): IrSetVariable {
|
||||
val descriptor = deserializeDescriptor(proto.descriptor) as VariableDescriptor
|
||||
val value = deserializeExpression(proto.value)
|
||||
return IrSetVariableImpl(start, end, IrVariableSymbolImpl(descriptor), value, null)
|
||||
return IrSetVariableImpl(start, end, context.irBuiltIns.unitType, IrVariableSymbolImpl(descriptor), value, null)
|
||||
}
|
||||
|
||||
private fun deserializeSpreadElement(proto: KonanIr.IrSpreadElement): IrSpreadElement {
|
||||
@@ -959,11 +964,11 @@ internal class IrDeserializer(val context: Context,
|
||||
argumentProtos.forEach {
|
||||
arguments.add(deserializeExpression(it))
|
||||
}
|
||||
return IrStringConcatenationImpl(start, end, type, arguments)
|
||||
return IrStringConcatenationImpl(start, end, type.ir, arguments)
|
||||
}
|
||||
|
||||
private fun deserializeThrow(proto: KonanIr.IrThrow, start: Int, end: Int, type: KotlinType): IrThrowImpl {
|
||||
return IrThrowImpl(start, end, type, deserializeExpression(proto.value))
|
||||
return IrThrowImpl(start, end, context.irBuiltIns.nothingType, deserializeExpression(proto.value))
|
||||
}
|
||||
|
||||
private fun deserializeTry(proto: KonanIr.IrTry, start: Int, end: Int, type: KotlinType): IrTryImpl {
|
||||
@@ -974,7 +979,7 @@ internal class IrDeserializer(val context: Context,
|
||||
}
|
||||
val finallyExpression =
|
||||
if (proto.hasFinally()) deserializeExpression(proto.getFinally()) else null
|
||||
return IrTryImpl(start, end, type, result, catches, finallyExpression)
|
||||
return IrTryImpl(start, end, type.ir, result, catches, finallyExpression)
|
||||
}
|
||||
|
||||
private fun deserializeTypeOperator(operator: KonanIr.IrTypeOperator): IrTypeOperator {
|
||||
@@ -999,9 +1004,12 @@ internal class IrDeserializer(val context: Context,
|
||||
|
||||
private fun deserializeTypeOp(proto: KonanIr.IrTypeOp, start: Int, end: Int, type: KotlinType) : IrTypeOperatorCall {
|
||||
val operator = deserializeTypeOperator(proto.operator)
|
||||
val operand = deserializeKotlinType(proto.operand)
|
||||
val operand = deserializeKotlinType(proto.operand).brokenIr
|
||||
val argument = deserializeExpression(proto.argument)
|
||||
return IrTypeOperatorCallImpl(start, end, type, operator, operand, argument)
|
||||
return IrTypeOperatorCallImpl(start, end, type.ir, operator, operand).apply {
|
||||
this.argument = argument
|
||||
this.typeOperandClassifier = operand.classifierOrFail
|
||||
}
|
||||
}
|
||||
|
||||
private fun deserializeVararg(proto: KonanIr.IrVararg, start: Int, end: Int, type: KotlinType): IrVararg {
|
||||
@@ -1011,7 +1019,7 @@ internal class IrDeserializer(val context: Context,
|
||||
proto.elementList.forEach {
|
||||
elements.add(deserializeVarargElement(it))
|
||||
}
|
||||
return IrVarargImpl(start, end, type, elementType, elements)
|
||||
return IrVarargImpl(start, end, type.ir, elementType.ir, elements)
|
||||
}
|
||||
|
||||
private fun deserializeVarargElement(element: KonanIr.IrVarargElement): IrVarargElement {
|
||||
@@ -1033,7 +1041,7 @@ internal class IrDeserializer(val context: Context,
|
||||
}
|
||||
|
||||
// TODO: provide some origin!
|
||||
return IrWhenImpl(start, end, type, null, branches)
|
||||
return IrWhenImpl(start, end, type.ir, null, branches)
|
||||
}
|
||||
|
||||
private fun deserializeLoop(proto: KonanIr.Loop, loop: IrLoopBase): IrLoopBase {
|
||||
@@ -1054,7 +1062,7 @@ internal class IrDeserializer(val context: Context,
|
||||
private fun deserializeDoWhile(proto: KonanIr.IrDoWhile, start: Int, end: Int, type: KotlinType): IrDoWhileLoop {
|
||||
// we create the loop before deserializing the body, so that
|
||||
// IrBreak statements have something to put into 'loop' field.
|
||||
val loop = IrDoWhileLoopImpl(start, end, type, null)
|
||||
val loop = IrDoWhileLoopImpl(start, end, type.ir, null)
|
||||
deserializeLoop(proto.loop, loop)
|
||||
return loop
|
||||
}
|
||||
@@ -1062,7 +1070,7 @@ internal class IrDeserializer(val context: Context,
|
||||
private fun deserializeWhile(proto: KonanIr.IrWhile, start: Int, end: Int, type: KotlinType): IrWhileLoop {
|
||||
// we create the loop before deserializing the body, so that
|
||||
// IrBreak statements have something to put into 'loop' field.
|
||||
val loop = IrWhileLoopImpl(start, end, type, null)
|
||||
val loop = IrWhileLoopImpl(start, end, type.ir, null)
|
||||
deserializeLoop(proto.loop, loop)
|
||||
return loop
|
||||
}
|
||||
@@ -1071,7 +1079,7 @@ internal class IrDeserializer(val context: Context,
|
||||
val label = if(proto.hasLabel()) proto.label else null
|
||||
val loopId = proto.loopId
|
||||
val loop = loopIndex[loopId]!!
|
||||
val irBreak = IrBreakImpl(start, end, type, loop)
|
||||
val irBreak = IrBreakImpl(start, end, type.ir, loop)
|
||||
irBreak.label = label
|
||||
|
||||
return irBreak
|
||||
@@ -1081,7 +1089,7 @@ internal class IrDeserializer(val context: Context,
|
||||
val label = if(proto.hasLabel()) proto.label else null
|
||||
val loopId = proto.loopId
|
||||
val loop = loopIndex[loopId]!!
|
||||
val irContinue = IrContinueImpl(start, end, type, loop)
|
||||
val irContinue = IrContinueImpl(start, end, type.ir, loop)
|
||||
irContinue.label = label
|
||||
|
||||
return irContinue
|
||||
@@ -1090,23 +1098,23 @@ internal class IrDeserializer(val context: Context,
|
||||
private fun deserializeConst(proto: KonanIr.IrConst, start: Int, end: Int, type: KotlinType): IrExpression =
|
||||
when(proto.valueCase) {
|
||||
NULL
|
||||
-> IrConstImpl.constNull(start, end, type)
|
||||
-> IrConstImpl.constNull(start, end, type.ir)
|
||||
BOOLEAN
|
||||
-> IrConstImpl.boolean(start, end, type, proto.boolean)
|
||||
-> IrConstImpl.boolean(start, end, type.ir, proto.boolean)
|
||||
BYTE
|
||||
-> IrConstImpl.byte(start, end, type, proto.byte.toByte())
|
||||
-> IrConstImpl.byte(start, end, type.ir, proto.byte.toByte())
|
||||
SHORT
|
||||
-> IrConstImpl.short(start, end, type, proto.short.toShort())
|
||||
-> IrConstImpl.short(start, end, type.ir, proto.short.toShort())
|
||||
INT
|
||||
-> IrConstImpl.int(start, end, type, proto.int)
|
||||
-> IrConstImpl.int(start, end, type.ir, proto.int)
|
||||
LONG
|
||||
-> IrConstImpl.long(start, end, type, proto.long)
|
||||
-> IrConstImpl.long(start, end, type.ir, proto.long)
|
||||
STRING
|
||||
-> IrConstImpl.string(start, end, type, proto.string)
|
||||
-> IrConstImpl.string(start, end, type.ir, proto.string)
|
||||
FLOAT
|
||||
-> IrConstImpl.float(start, end, type, proto.float)
|
||||
-> IrConstImpl.float(start, end, type.ir, proto.float)
|
||||
DOUBLE
|
||||
-> IrConstImpl.double(start, end, type, proto.double)
|
||||
-> IrConstImpl.double(start, end, type.ir, proto.double)
|
||||
else -> {
|
||||
TODO("Not all const types have been implemented")
|
||||
}
|
||||
@@ -1191,9 +1199,10 @@ internal class IrDeserializer(val context: Context,
|
||||
|
||||
val clazz = IrClassImpl(start, end, origin, descriptor, members)
|
||||
|
||||
clazz.createParameterDeclarations()
|
||||
clazz.addFakeOverrides()
|
||||
clazz.setSuperSymbols(context.ir.symbols.symbolTable)
|
||||
val symbolTable = context.ir.symbols.symbolTable
|
||||
clazz.createParameterDeclarations(symbolTable)
|
||||
clazz.addFakeOverrides(symbolTable)
|
||||
clazz.setSuperSymbols(symbolTable)
|
||||
|
||||
return clazz
|
||||
|
||||
@@ -1203,10 +1212,12 @@ internal class IrDeserializer(val context: Context,
|
||||
start: Int, end: Int, origin: IrDeclarationOrigin): IrFunction {
|
||||
|
||||
val body = deserializeStatement(proto.body)
|
||||
val function = IrFunctionImpl(start, end, origin,
|
||||
descriptor, body as IrBody)
|
||||
val function = IrFunctionImpl(start, end, origin, descriptor)
|
||||
|
||||
function.createParameterDeclarations()
|
||||
function.returnType = descriptor.returnType!!.ir
|
||||
function.body = body as IrBody
|
||||
|
||||
function.createParameterDeclarations(context.ir.symbols.symbolTable)
|
||||
function.setOverrides(context.ir.symbols.symbolTable)
|
||||
|
||||
proto.defaultArgumentList.forEach {
|
||||
@@ -1226,7 +1237,7 @@ internal class IrDeserializer(val context: Context,
|
||||
deserializeExpression(proto.initializer)
|
||||
} else null
|
||||
|
||||
return IrVariableImpl(start, end, origin, descriptor, initializer)
|
||||
return IrVariableImpl(start, end, origin, descriptor, descriptor.type.ir, initializer)
|
||||
}
|
||||
|
||||
private fun deserializeIrEnumEntry(proto: KonanIr.IrEnumEntry, descriptor: ClassDescriptor,
|
||||
|
||||
+53
-24
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.ir.util
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
import org.jetbrains.kotlin.backend.common.push
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
@@ -26,6 +28,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
|
||||
@Deprecated("")
|
||||
@@ -47,11 +50,15 @@ internal fun IrModuleFragment.replaceUnboundSymbols(context: Context) {
|
||||
|
||||
val symbolTable = context.ir.symbols.symbolTable
|
||||
|
||||
this.transformChildrenVoid(IrUnboundSymbolReplacer(symbolTable, collector.descriptorToSymbol))
|
||||
this.transformChildrenVoid(IrUnboundSymbolReplacer(symbolTable, collector.descriptorToSymbol, context))
|
||||
|
||||
// Generate missing external stubs:
|
||||
@Suppress("DEPRECATION")
|
||||
ExternalDependenciesGenerator(symbolTable = context.psi2IrGeneratorContext.symbolTable, irBuiltIns = context.irBuiltIns).generateUnboundSymbolsAsDependencies(this)
|
||||
ExternalDependenciesGenerator(
|
||||
context.moduleDescriptor,
|
||||
symbolTable = context.psi2IrGeneratorContext.symbolTable,
|
||||
irBuiltIns = context.irBuiltIns
|
||||
).generateUnboundSymbolsAsDependencies(this)
|
||||
|
||||
// Merge duplicated module and package declarations:
|
||||
this.acceptVoid(object : IrElementVisitorVoid {
|
||||
@@ -111,7 +118,8 @@ private class DeclarationSymbolCollector : IrElementVisitorVoid {
|
||||
|
||||
private class IrUnboundSymbolReplacer(
|
||||
val symbolTable: SymbolTable,
|
||||
val descriptorToSymbol: Map<DeclarationDescriptor, IrSymbol>
|
||||
val descriptorToSymbol: Map<DeclarationDescriptor, IrSymbol>,
|
||||
val context: Context
|
||||
) : IrElementTransformerVoid() {
|
||||
|
||||
private val localDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, MutableList<IrSymbol>>()
|
||||
@@ -163,7 +171,7 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrGetValueImpl(startOffset, endOffset, symbol, origin)
|
||||
IrGetValueImpl(startOffset, endOffset, expression.type, symbol, origin)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +180,7 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrSetVariableImpl(startOffset, endOffset, symbol, value, origin)
|
||||
IrSetVariableImpl(startOffset, endOffset, expression.type, symbol, value, origin)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,17 +210,11 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.descriptor.defaultType)
|
||||
IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.typeWithStarProjections)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
declaration.superClasses.forEachIndexed { index, symbol ->
|
||||
val newSymbol = symbol.replace(SymbolTable::referenceClass)
|
||||
if (newSymbol != null) {
|
||||
declaration.superClasses[index] = newSymbol
|
||||
}
|
||||
}
|
||||
withLocal(declaration.thisReceiver?.symbol) {
|
||||
return super.visitClass(declaration)
|
||||
}
|
||||
@@ -229,7 +231,7 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrGetFieldImpl(startOffset, endOffset, symbol, receiver, origin, superQualifierSymbol)
|
||||
IrGetFieldImpl(startOffset, endOffset, symbol, type, receiver, origin, superQualifierSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,11 +246,13 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, origin, superQualifierSymbol)
|
||||
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, type, origin, superQualifierSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.replaceTypeArguments()
|
||||
|
||||
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: expression.symbol
|
||||
|
||||
val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass)
|
||||
@@ -259,17 +263,21 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid()
|
||||
return with(expression) {
|
||||
IrCallImpl(startOffset, endOffset, symbol, descriptor,
|
||||
getTypeArgumentsMap(),
|
||||
IrCallImpl(startOffset, endOffset, type, symbol, descriptor,
|
||||
typeArgumentsCount,
|
||||
origin, superQualifierSymbol).also {
|
||||
|
||||
it.copyArgumentsFrom(this)
|
||||
it.copyTypeArgumentsFrom(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrMemberAccessExpression.getTypeArgumentsMap() =
|
||||
descriptor.original.typeParameters.associate { it to getTypeArgumentOrDefault(it) }
|
||||
private fun IrMemberAccessExpression.replaceTypeArguments() {
|
||||
repeat(typeArgumentsCount) {
|
||||
putTypeArgument(it, getTypeArgument(it)?.toKotlinType()?.let { context.ir.translateErased(it) })
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrMemberAccessExpressionBase.copyArgumentsFrom(original: IrMemberAccessExpression) {
|
||||
dispatchReceiver = original.dispatchReceiver
|
||||
@@ -284,37 +292,45 @@ private class IrUnboundSymbolReplacer(
|
||||
return super.visitEnumConstructorCall(expression)
|
||||
|
||||
return with(expression) {
|
||||
IrEnumConstructorCallImpl(startOffset, endOffset, symbol, null).also {
|
||||
IrEnumConstructorCallImpl(startOffset, endOffset, expression.type, symbol, 0).also {
|
||||
it.copyArgumentsFrom(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||
expression.replaceTypeArguments()
|
||||
|
||||
val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?:
|
||||
return super.visitDelegatingConstructorCall(expression)
|
||||
|
||||
expression.transformChildrenVoid()
|
||||
return with(expression) {
|
||||
IrDelegatingConstructorCallImpl(startOffset, endOffset, symbol, descriptor, getTypeArgumentsMap()).also {
|
||||
IrDelegatingConstructorCallImpl(startOffset, endOffset, type, symbol, descriptor, typeArgumentsCount).also {
|
||||
it.copyArgumentsFrom(this)
|
||||
it.copyTypeArgumentsFrom(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
expression.replaceTypeArguments()
|
||||
|
||||
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?:
|
||||
return super.visitFunctionReference(expression)
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, getTypeArgumentsMap()).also {
|
||||
IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, 0).also {
|
||||
it.copyArgumentsFrom(this)
|
||||
it.copyTypeArgumentsFrom(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
|
||||
expression.replaceTypeArguments()
|
||||
|
||||
val field = expression.field?.replaceOrSame(SymbolTable::referenceField)
|
||||
val getter = expression.getter?.replace(SymbolTable::referenceFunction) ?: expression.getter
|
||||
val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter
|
||||
@@ -325,13 +341,14 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor,
|
||||
IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor, 0,
|
||||
field,
|
||||
getter,
|
||||
setter,
|
||||
getTypeArgumentsMap(), origin).also {
|
||||
origin).also {
|
||||
|
||||
it.copyArgumentsFrom(this)
|
||||
it.copyTypeArgumentsFrom(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -413,7 +430,19 @@ private class IrUnboundSymbolReplacer(
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
return with(expression) {
|
||||
IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol)
|
||||
IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol, type)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
return with(expression) {
|
||||
val newTypeOperand = context.ir.translateErased(typeOperand.toKotlinType())
|
||||
IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, newTypeOperand).also {
|
||||
it.argument = argument
|
||||
it.typeOperandClassifier = newTypeOperand.classifier
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+424
-73
@@ -17,26 +17,40 @@
|
||||
package org.jetbrains.kotlin.ir.util
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.substitute
|
||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||
import org.jetbrains.kotlin.backend.konan.KonanCompilationException
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.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.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.OverridingStrategy
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||
import java.lang.reflect.Proxy
|
||||
|
||||
//TODO: delete file on next kotlin dependency update
|
||||
@@ -63,25 +77,20 @@ internal fun IrFile.addTopLevelInitializer(expression: IrExpression) {
|
||||
)
|
||||
|
||||
val builtIns = fieldDescriptor.builtIns
|
||||
fieldDescriptor.setType(builtIns.unitType, emptyList(), null, null as KotlinType?)
|
||||
fieldDescriptor.setType(expression.type.toKotlinType(), emptyList(), null, null as KotlinType?)
|
||||
fieldDescriptor.initialize(null, null)
|
||||
|
||||
val irField = IrFieldImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
IrDeclarationOrigin.DEFINED, fieldDescriptor
|
||||
IrDeclarationOrigin.DEFINED, fieldDescriptor, expression.type
|
||||
)
|
||||
|
||||
val initializer = IrTypeOperatorCallImpl(
|
||||
expression.startOffset, expression.endOffset, builtIns.unitType,
|
||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, builtIns.unitType, expression
|
||||
)
|
||||
|
||||
irField.initializer = IrExpressionBodyImpl(expression.startOffset, expression.endOffset, initializer)
|
||||
irField.initializer = IrExpressionBodyImpl(expression.startOffset, expression.endOffset, expression)
|
||||
|
||||
this.addChild(irField)
|
||||
}
|
||||
|
||||
fun IrClass.addFakeOverrides() {
|
||||
fun IrClass.addFakeOverrides(symbolTable: SymbolTable) {
|
||||
|
||||
val startOffset = this.startOffset
|
||||
val endOffset = this.endOffset
|
||||
@@ -90,17 +99,23 @@ fun IrClass.addFakeOverrides() {
|
||||
.filterIsInstance<CallableMemberDescriptor>()
|
||||
.filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
|
||||
.forEach {
|
||||
this.addChild(createFakeOverride(it, startOffset, endOffset))
|
||||
this.addChild(createFakeOverride(it, startOffset, endOffset, symbolTable))
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFakeOverride(descriptor: CallableMemberDescriptor, startOffset: Int, endOffset: Int): IrDeclaration {
|
||||
private fun createFakeOverride(
|
||||
descriptor: CallableMemberDescriptor,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
symbolTable: SymbolTable
|
||||
): IrDeclaration {
|
||||
|
||||
fun FunctionDescriptor.createFunction(): IrFunction = IrFunctionImpl(
|
||||
fun FunctionDescriptor.createFunction(): IrSimpleFunction = IrFunctionImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.FAKE_OVERRIDE, this
|
||||
).apply {
|
||||
createParameterDeclarations()
|
||||
returnType = symbolTable.translateErased(this@createFunction.returnType!!)
|
||||
createParameterDeclarations(symbolTable)
|
||||
}
|
||||
|
||||
return when (descriptor) {
|
||||
@@ -115,11 +130,13 @@ private fun createFakeOverride(descriptor: CallableMemberDescriptor, startOffset
|
||||
}
|
||||
}
|
||||
|
||||
fun IrFunction.createParameterDeclarations() {
|
||||
fun IrFunction.createParameterDeclarations(symbolTable: SymbolTable) {
|
||||
|
||||
fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl(
|
||||
innerStartOffset(this), innerEndOffset(this),
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
this
|
||||
this, symbolTable.translateErased(this.type),
|
||||
(this as? ValueParameterDescriptor)?.varargElementType?.let { symbolTable.translateErased(it) }
|
||||
).also {
|
||||
it.parent = this@createParameterDeclarations
|
||||
}
|
||||
@@ -138,18 +155,84 @@ fun IrFunction.createParameterDeclarations() {
|
||||
it
|
||||
).also { typeParameter ->
|
||||
typeParameter.parent = this
|
||||
typeParameter.descriptor.upperBounds.mapTo(typeParameter.superTypes, symbolTable::translateErased)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
).also {
|
||||
it.returnType = returnType
|
||||
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: SymbolTable) {
|
||||
assert(this.overriddenSymbols.isEmpty())
|
||||
|
||||
this.descriptor.overriddenDescriptors.mapTo(this.overriddenSymbols) {
|
||||
symbolTable.referenceSimpleFunction(it.original)
|
||||
}
|
||||
|
||||
this.typeParameters.forEach { it.setSupers(symbolTable) }
|
||||
}
|
||||
|
||||
fun IrClass.simpleFunctions(): List<IrSimpleFunction> = this.declarations.flatMap {
|
||||
@@ -161,32 +244,56 @@ fun IrClass.simpleFunctions(): List<IrSimpleFunction> = this.declarations.flatMa
|
||||
}
|
||||
|
||||
fun IrClass.createParameterDeclarations() {
|
||||
descriptor.thisAsReceiverParameter.let {
|
||||
thisReceiver = IrValueParameterImpl(
|
||||
innerStartOffset(it), innerEndOffset(it),
|
||||
IrDeclarationOrigin.INSTANCE_RECEIVER,
|
||||
it
|
||||
).also { valueParameter ->
|
||||
valueParameter.parent = this
|
||||
}
|
||||
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())
|
||||
descriptor.declaredTypeParameters.mapTo(typeParameters) {
|
||||
IrTypeParameterImpl(
|
||||
innerStartOffset(it), innerEndOffset(it),
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
it
|
||||
).also { typeParameter ->
|
||||
typeParameter.parent = this
|
||||
}
|
||||
}
|
||||
assert(descriptor.declaredTypeParameters.isEmpty())
|
||||
}
|
||||
|
||||
fun IrClass.setSuperSymbols(supers: List<IrClass>) {
|
||||
fun IrFunction.createDispatchReceiverParameter() {
|
||||
assert(this.dispatchReceiverParameter == null)
|
||||
|
||||
val descriptor = this.descriptor.dispatchReceiverParameter ?: return
|
||||
|
||||
this.dispatchReceiverParameter = IrValueParameterImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
descriptor,
|
||||
(parent as IrClass).defaultType,
|
||||
null
|
||||
).also { it.parent = this }
|
||||
}
|
||||
|
||||
fun IrClass.createParameterDeclarations(symbolTable: SymbolTable) {
|
||||
this.descriptor.declaredTypeParameters.mapTo(this.typeParameters) {
|
||||
IrTypeParameterImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, it).apply {
|
||||
it.upperBounds.mapTo(this.superTypes, symbolTable::translateErased)
|
||||
}
|
||||
}
|
||||
|
||||
this.thisReceiver = IrValueParameterImpl(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
this.descriptor.thisAsReceiverParameter,
|
||||
this.symbol.typeWith(this.typeParameters.map { it.defaultType }),
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
fun IrClass.setSuperSymbols(superTypes: List<IrType>) {
|
||||
val supers = superTypes.map { it.getClass()!! }
|
||||
assert(this.superDescriptors().toSet() == supers.map { it.descriptor }.toSet())
|
||||
assert(this.superClasses.isEmpty())
|
||||
supers.mapTo(this.superClasses) { it.symbol }
|
||||
assert(this.superTypes.isEmpty())
|
||||
this.superTypes += superTypes
|
||||
|
||||
val superMembers = supers.flatMap {
|
||||
it.simpleFunctions()
|
||||
@@ -206,48 +313,38 @@ private fun IrClass.superDescriptors() =
|
||||
this.descriptor.typeConstructor.supertypes.map { it.constructor.declarationDescriptor as ClassDescriptor }
|
||||
|
||||
fun IrClass.setSuperSymbols(symbolTable: SymbolTable) {
|
||||
assert(this.superClasses.isEmpty())
|
||||
this.superDescriptors().mapTo(this.superClasses) { symbolTable.referenceClass(it) }
|
||||
assert(this.superTypes.isEmpty())
|
||||
this.descriptor.typeConstructor.supertypes.mapTo(this.superTypes) { symbolTable.translateErased(it) }
|
||||
|
||||
this.simpleFunctions().forEach {
|
||||
it.setOverrides(symbolTable)
|
||||
}
|
||||
this.typeParameters.forEach {
|
||||
it.setSupers(symbolTable)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrTypeParameter.setSupers(symbolTable: SymbolTable) {
|
||||
assert(this.superClassifiers.isEmpty())
|
||||
this.descriptor.upperBounds.mapNotNullTo(this.superClassifiers) {
|
||||
it.constructor.declarationDescriptor?.let {
|
||||
if (it is TypeParameterDescriptor) {
|
||||
IrTypeParameterSymbolImpl(it) // Workaround for deserialized inline functions
|
||||
} else {
|
||||
symbolTable.referenceClassifier(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun IrClass.setSuperSymbolsAndAddFakeOverrides(supers: List<IrClass>) {
|
||||
fun IrClass.setSuperSymbolsAndAddFakeOverrides(superTypes: List<IrType>) {
|
||||
val overriddenSuperMembers = this.declarations.map { it.descriptor }
|
||||
.filterIsInstance<CallableMemberDescriptor>().flatMap { it.overriddenDescriptors.map { it.original } }
|
||||
.filterIsInstance<CallableMemberDescriptor>().flatMap { it.overriddenDescriptors.map { it.original } }.toSet()
|
||||
|
||||
val unoverriddenSuperMembers = supers.flatMap {
|
||||
it.declarations.mapNotNull {
|
||||
val unoverriddenSuperMembers = superTypes.map { it.getClass()!! }.flatMap {
|
||||
it.declarations.filter { it.descriptor !in overriddenSuperMembers }.mapNotNull {
|
||||
when (it) {
|
||||
is IrSimpleFunction -> it.descriptor
|
||||
is IrProperty -> it.descriptor
|
||||
is IrSimpleFunction -> it.descriptor to it
|
||||
is IrProperty -> it.descriptor to it
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
} - overriddenSuperMembers
|
||||
}.toMap()
|
||||
|
||||
val irClass = this
|
||||
|
||||
val overridingStrategy = object : OverridingStrategy() {
|
||||
override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) {
|
||||
irClass.addChild(createFakeOverride(fakeOverride, startOffset, endOffset))
|
||||
val overriddenDeclarations =
|
||||
fakeOverride.overriddenDescriptors.map { unoverriddenSuperMembers[it]!! }
|
||||
|
||||
assert(overriddenDeclarations.isNotEmpty())
|
||||
|
||||
irClass.declarations.add(createFakeOverride(fakeOverride, overriddenDeclarations, irClass))
|
||||
}
|
||||
|
||||
override fun inheritanceConflict(first: CallableMemberDescriptor, second: CallableMemberDescriptor) {
|
||||
@@ -259,7 +356,7 @@ fun IrClass.setSuperSymbolsAndAddFakeOverrides(supers: List<IrClass>) {
|
||||
}
|
||||
}
|
||||
|
||||
unoverriddenSuperMembers.groupBy { it.name }.forEach { (name, members) ->
|
||||
unoverriddenSuperMembers.keys.groupBy { it.name }.forEach { (name, members) ->
|
||||
OverridingUtil.generateOverridesInFunctionGroup(
|
||||
name,
|
||||
members,
|
||||
@@ -269,7 +366,7 @@ fun IrClass.setSuperSymbolsAndAddFakeOverrides(supers: List<IrClass>) {
|
||||
)
|
||||
}
|
||||
|
||||
this.setSuperSymbols(supers)
|
||||
this.setSuperSymbols(superTypes)
|
||||
}
|
||||
|
||||
private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int =
|
||||
@@ -327,7 +424,7 @@ object CheckDeclarationParentsVisitor : IrElementVisitor<Unit, IrDeclarationPare
|
||||
}
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclarationParent?) {
|
||||
if (declaration !is IrVariable) {
|
||||
if (declaration !is IrVariable && declaration !is IrValueParameter && declaration !is IrTypeParameter) {
|
||||
checkParent(declaration, data)
|
||||
} else {
|
||||
// Don't check IrVariable parent.
|
||||
@@ -376,7 +473,7 @@ internal fun KonanBackendContext.report(declaration: IrDeclaration, message: Str
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.irForceNotNull(expression: IrExpression): IrExpression {
|
||||
if (!TypeUtils.isNullableType(expression.type)) {
|
||||
if (!expression.type.containsNull()) {
|
||||
return expression
|
||||
}
|
||||
|
||||
@@ -384,9 +481,263 @@ fun IrBuilderWithScope.irForceNotNull(expression: IrExpression): IrExpression {
|
||||
val temporary = irTemporaryVar(expression)
|
||||
+irIfNull(
|
||||
expression.type,
|
||||
subject = irGet(temporary.symbol),
|
||||
subject = irGet(temporary),
|
||||
thenPart = irThrowNpe(IrStatementOrigin.EXCLEXCL),
|
||||
elsePart = irGet(temporary.symbol)
|
||||
elsePart = irGet(temporary)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrFunctionAccessExpression.addArguments(args: Map<IrValueParameter, IrExpression>) {
|
||||
val unhandledParameters = args.keys.toMutableSet()
|
||||
fun getArg(parameter: IrValueParameter) = args[parameter]?.also { unhandledParameters -= parameter }
|
||||
|
||||
symbol.owner.dispatchReceiverParameter?.let {
|
||||
val arg = getArg(it)
|
||||
if (arg != null) {
|
||||
this.dispatchReceiver = arg
|
||||
}
|
||||
}
|
||||
|
||||
symbol.owner.extensionReceiverParameter?.let {
|
||||
val arg = getArg(it)
|
||||
if (arg != null) {
|
||||
this.extensionReceiver = arg
|
||||
}
|
||||
}
|
||||
|
||||
symbol.owner.valueParameters.forEach {
|
||||
val arg = getArg(it)
|
||||
if (arg != null) {
|
||||
this.putValueArgument(it.index, arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionDescriptor.substitute(
|
||||
typeArguments: List<IrType>
|
||||
): FunctionDescriptor = if (typeArguments.isEmpty()) {
|
||||
this
|
||||
} else {
|
||||
this.substitute(*typeArguments.map { it.toKotlinType() }.toTypedArray())
|
||||
}
|
||||
|
||||
fun IrType.substitute(map: Map<IrTypeParameterSymbol, IrType>): IrType {
|
||||
if (this !is IrSimpleType) return this
|
||||
|
||||
val classifier = this.classifier
|
||||
return when (classifier) {
|
||||
is IrTypeParameterSymbol ->
|
||||
map[classifier]?.let { if (this.hasQuestionMark) it.makeNullable() else it }
|
||||
?: this
|
||||
|
||||
is IrClassSymbol -> if (this.arguments.isEmpty()) {
|
||||
this // Fast path.
|
||||
} else {
|
||||
val newArguments = this.arguments.map {
|
||||
when (it) {
|
||||
is IrTypeProjection -> makeTypeProjection(it.type.substitute(map), it.variance)
|
||||
is IrStarProjection -> it
|
||||
else -> error(it)
|
||||
}
|
||||
}
|
||||
IrSimpleTypeImpl(classifier, hasQuestionMark, newArguments, annotations)
|
||||
}
|
||||
else -> error(classifier)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun IrFunction.substitutedReturnType(typeArguments: List<IrType>): IrType {
|
||||
val unsubstituted = this.returnType
|
||||
if (typeArguments.isEmpty()) return unsubstituted // Fast path.
|
||||
if (this is IrConstructor) {
|
||||
// Workaround for missing type parameters in constructors. TODO: remove.
|
||||
return this.returnType.classifierOrFail.typeWith(typeArguments)
|
||||
}
|
||||
|
||||
assert(this.typeParameters.size >= typeArguments.size) // TODO: check equality.
|
||||
// TODO: receiver type must also be considered.
|
||||
return unsubstituted.substitute(this.typeParameters.map { it.symbol }.zip(typeArguments).toMap())
|
||||
}
|
||||
|
||||
// TODO: this function must be avoided since it takes symbol's owner implicitly.
|
||||
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: List<IrType> = emptyList()) =
|
||||
irCall(symbol.owner, typeArguments)
|
||||
|
||||
fun IrBuilderWithScope.irCall(
|
||||
irFunction: IrFunction,
|
||||
typeArguments: List<IrType> = emptyList()
|
||||
): IrCall = irCall(this.startOffset, this.endOffset, irFunction, typeArguments)
|
||||
|
||||
internal fun irCall(startOffset: Int, endOffset: Int, irFunction: IrFunction, typeArguments: List<IrType>): IrCall =
|
||||
IrCallImpl(
|
||||
startOffset, endOffset, irFunction.substitutedReturnType(typeArguments),
|
||||
irFunction.symbol, irFunction.descriptor.substitute(typeArguments), typeArguments.size
|
||||
).apply {
|
||||
typeArguments.forEachIndexed { index, irType ->
|
||||
this.putTypeArgument(index, irType)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.irCall(
|
||||
irFunction: IrFunctionSymbol,
|
||||
type: IrType,
|
||||
typeArguments: List<IrType> = emptyList()
|
||||
): IrCall = IrCallImpl(
|
||||
startOffset, endOffset, type,
|
||||
irFunction, irFunction.descriptor.substitute(typeArguments), typeArguments.size
|
||||
).apply {
|
||||
typeArguments.forEachIndexed { index, irType ->
|
||||
this.putTypeArgument(index, irType)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.irCallOp(
|
||||
callee: IrFunction,
|
||||
dispatchReceiver: IrExpression,
|
||||
argument: IrExpression
|
||||
): IrCall =
|
||||
irCall(callee).apply {
|
||||
this.dispatchReceiver = dispatchReceiver
|
||||
putValueArgument(0, argument)
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.irSetVar(variable: IrVariable, value: IrExpression) =
|
||||
irSetVar(variable.symbol, value)
|
||||
|
||||
fun IrBuilderWithScope.irSetField(receiver: IrExpression, irField: IrField, value: IrExpression): IrExpression =
|
||||
IrSetFieldImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
irField.symbol,
|
||||
receiver = receiver,
|
||||
value = value,
|
||||
type = context.irBuiltIns.unitType
|
||||
)
|
||||
|
||||
/**
|
||||
* Binds the arguments explicitly represented in the IR to the parameters of the accessed function.
|
||||
* The arguments are to be evaluated in the same order as they appear in the resulting list.
|
||||
*/
|
||||
fun IrMemberAccessExpression.getArgumentsWithIr(): List<Pair<IrValueParameter, IrExpression>> {
|
||||
val res = mutableListOf<Pair<IrValueParameter, IrExpression>>()
|
||||
val irFunction = when (this) {
|
||||
is IrFunctionAccessExpression -> this.symbol.owner
|
||||
is IrFunctionReference -> this.symbol.owner
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
dispatchReceiver?.let {
|
||||
res += (irFunction.dispatchReceiverParameter!! to it)
|
||||
}
|
||||
|
||||
extensionReceiver?.let {
|
||||
res += (irFunction.extensionReceiverParameter!! to it)
|
||||
}
|
||||
|
||||
irFunction.valueParameters.forEachIndexed { index, it ->
|
||||
val arg = getValueArgument(index)
|
||||
if (arg != null) {
|
||||
res += (it to arg)
|
||||
}
|
||||
}
|
||||
|
||||
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 SymbolTable.translateErased(type: KotlinType): IrSimpleType {
|
||||
val descriptor = TypeUtils.getClassDescriptor(type)
|
||||
if (descriptor == null) return translateErased(type.immediateSupertypes().first())
|
||||
val classSymbol = this.referenceClass(descriptor)
|
||||
|
||||
val nullable = type.isMarkedNullable
|
||||
val arguments = type.arguments.map { IrStarProjectionImpl }
|
||||
|
||||
return classSymbol.createType(nullable, arguments)
|
||||
}
|
||||
|
||||
fun CommonBackendContext.createArrayOfExpression(
|
||||
arrayElementType: IrType,
|
||||
arrayElements: List<IrExpression>,
|
||||
startOffset: Int, endOffset: Int
|
||||
): IrExpression {
|
||||
|
||||
val arrayType = ir.symbols.array.typeWith(arrayElementType)
|
||||
val arg0 = IrVarargImpl(startOffset, endOffset, arrayType, arrayElementType, arrayElements)
|
||||
|
||||
return irCall(startOffset, endOffset, ir.symbols.arrayOf.owner, listOf(arrayElementType)).apply {
|
||||
putValueArgument(0, arg0)
|
||||
}
|
||||
}
|
||||
|
||||
fun createField(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: IrType,
|
||||
name: Name,
|
||||
isMutable: Boolean,
|
||||
origin: IrDeclarationOrigin,
|
||||
owner: ClassDescriptor
|
||||
): IrField {
|
||||
val descriptor = PropertyDescriptorImpl.create(
|
||||
/* containingDeclaration = */ owner,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PRIVATE,
|
||||
/* isVar = */ isMutable,
|
||||
/* name = */ name,
|
||||
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/* source = */ SourceElement.NO_SOURCE,
|
||||
/* lateInit = */ false,
|
||||
/* isConst = */ false,
|
||||
/* isExpect = */ false,
|
||||
/* isActual = */ false,
|
||||
/* isExternal = */ false,
|
||||
/* isDelegated = */ false
|
||||
).apply {
|
||||
initialize(null, null)
|
||||
|
||||
val receiverType: KotlinType? = null
|
||||
setType(type.toKotlinType(), emptyList(), owner.thisAsReceiverParameter, receiverType)
|
||||
}
|
||||
|
||||
return IrFieldImpl(startOffset, endOffset, origin, descriptor, type)
|
||||
}
|
||||
|
||||
fun IrValueParameter.copy(newDescriptor: ParameterDescriptor): IrValueParameter {
|
||||
assert(this.descriptor.type == newDescriptor.type)
|
||||
|
||||
return IrValueParameterImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
newDescriptor,
|
||||
type,
|
||||
varargElementType
|
||||
)
|
||||
}
|
||||
|
||||
val IrTypeArgument.typeOrNull: IrType? get() = (this as? IrTypeProjection)?.type
|
||||
|
||||
val IrType.isSimpleTypeWithQuestionMark: Boolean
|
||||
get() = this is IrSimpleType && this.hasQuestionMark
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
//For KT-6020
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
|
||||
@@ -47,7 +47,7 @@ class Worker(val id: WorkerId) {
|
||||
* until all scheduled jobs processed, or terminate immediately.
|
||||
*/
|
||||
fun requestTermination(processScheduledJobs: Boolean = true) =
|
||||
Future<FutureId>(requestTerminationInternal(id, processScheduledJobs))
|
||||
Future<Nothing?>(requestTerminationInternal(id, processScheduledJobs))
|
||||
|
||||
/**
|
||||
* Schedule a job for further execution in the worker. Schedule is a two-phase operation,
|
||||
|
||||
Reference in New Issue
Block a user