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
|
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.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
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.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.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.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
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.
|
* 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.useAsStatement(): IrExpression = this
|
||||||
|
|
||||||
protected open fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: KotlinType): IrExpression =
|
protected open fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: IrType): IrExpression =
|
||||||
this
|
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 =
|
protected open fun IrExpression.useAsArgument(parameter: ParameterDescriptor): IrExpression =
|
||||||
this.useAsValue(parameter)
|
this.useAsValue(parameter)
|
||||||
|
|
||||||
protected open fun IrExpression.useAsDispatchReceiver(expression: IrMemberAccessExpression): IrExpression =
|
protected open fun IrExpression.useAsDispatchReceiver(expression: IrFunctionAccessExpression): IrExpression =
|
||||||
this.useAsArgument(expression.descriptor.dispatchReceiverParameter!!)
|
this.useAsArgument(expression.symbol.owner.dispatchReceiverParameter!!)
|
||||||
|
|
||||||
protected open fun IrExpression.useAsExtensionReceiver(expression: IrMemberAccessExpression): IrExpression =
|
protected open fun IrExpression.useAsExtensionReceiver(expression: IrFunctionAccessExpression): IrExpression =
|
||||||
this.useAsArgument(expression.descriptor.extensionReceiverParameter!!)
|
this.useAsArgument(expression.symbol.owner.extensionReceiverParameter!!)
|
||||||
|
|
||||||
protected open fun IrExpression.useAsValueArgument(expression: IrMemberAccessExpression,
|
protected open fun IrExpression.useAsValueArgument(expression: IrFunctionAccessExpression,
|
||||||
parameter: ValueParameterDescriptor): IrExpression =
|
parameter: ValueParameterDescriptor): IrExpression =
|
||||||
this.useAsArgument(parameter)
|
this.useAsArgument(parameter)
|
||||||
|
|
||||||
protected open fun IrExpression.useForVariable(variable: VariableDescriptor): IrExpression =
|
private fun IrExpression.useForVariable(variable: VariableDescriptor): IrExpression =
|
||||||
this.useAsValue(variable)
|
this.useAsValue(variable)
|
||||||
|
|
||||||
protected open fun IrExpression.useForField(field: PropertyDescriptor): IrExpression =
|
private fun IrExpression.useForField(field: IrField): IrExpression =
|
||||||
this.useForVariable(field)
|
this.useAs(field.type)
|
||||||
|
|
||||||
protected open fun IrExpression.useAsReturnValue(returnTarget: CallableDescriptor): IrExpression {
|
protected open fun IrExpression.useAsReturnValue(returnTarget: IrReturnTargetSymbol): IrExpression =
|
||||||
val returnType = returnTarget.returnType ?: return this
|
when (returnTarget) {
|
||||||
return this.useAs(returnType)
|
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 =
|
protected open fun IrExpression.useAsResult(enclosing: IrExpression): IrExpression =
|
||||||
this.useAs(enclosing.type)
|
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)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
with(expression) {
|
with(expression) {
|
||||||
@@ -86,7 +109,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
extensionReceiver = extensionReceiver?.useAsExtensionReceiver(expression)
|
extensionReceiver = extensionReceiver?.useAsExtensionReceiver(expression)
|
||||||
for (index in descriptor.valueParameters.indices) {
|
for (index in descriptor.valueParameters.indices) {
|
||||||
val argument = getValueArgument(index) ?: continue
|
val argument = getValueArgument(index) ?: continue
|
||||||
val parameter = descriptor.valueParameters[index]
|
val parameter = symbol.owner.valueParameters[index]
|
||||||
putValueArgument(index, argument.useAsValueArgument(expression, parameter))
|
putValueArgument(index, argument.useAsValueArgument(expression, parameter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,7 +153,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
expression.value = expression.value.useAsReturnValue(expression.returnTarget)
|
expression.value = expression.value.useAsReturnValue(expression.returnTargetSymbol)
|
||||||
|
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
@@ -138,7 +161,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
override fun visitSetVariable(expression: IrSetVariable): IrExpression {
|
override fun visitSetVariable(expression: IrSetVariable): IrExpression {
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
expression.value = expression.value.useForVariable(expression.descriptor)
|
expression.value = expression.value.useForVariable(expression.symbol.owner)
|
||||||
|
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
@@ -146,7 +169,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
override fun visitSetField(expression: IrSetField): IrExpression {
|
override fun visitSetField(expression: IrSetField): IrExpression {
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
expression.value = expression.value.useForField(expression.descriptor)
|
expression.value = expression.value.useForField(expression.symbol.owner)
|
||||||
|
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
@@ -155,7 +178,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
declaration.transformChildrenVoid(this)
|
declaration.transformChildrenVoid(this)
|
||||||
|
|
||||||
declaration.initializer?.let {
|
declaration.initializer?.let {
|
||||||
it.expression = it.expression.useForField(declaration.descriptor)
|
it.expression = it.expression.useForField(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
return declaration
|
return declaration
|
||||||
@@ -164,7 +187,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
override fun visitVariable(declaration: IrVariable): IrVariable {
|
override fun visitVariable(declaration: IrVariable): IrVariable {
|
||||||
declaration.transformChildrenVoid(this)
|
declaration.transformChildrenVoid(this)
|
||||||
|
|
||||||
declaration.initializer = declaration.initializer?.useForVariable(declaration.descriptor)
|
declaration.initializer = declaration.initializer?.useForVariable(declaration)
|
||||||
|
|
||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
@@ -173,7 +196,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
for (irBranch in expression.branches) {
|
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)
|
irBranch.result = irBranch.result.useAsResult(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +206,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
override fun visitLoop(loop: IrLoop): IrExpression {
|
override fun visitLoop(loop: IrLoop): IrExpression {
|
||||||
loop.transformChildrenVoid(this)
|
loop.transformChildrenVoid(this)
|
||||||
|
|
||||||
loop.condition = loop.condition.useAs(builtIns.booleanType)
|
loop.condition = loop.condition.useAs(irBuiltIns.booleanType)
|
||||||
|
|
||||||
loop.body = loop.body?.useAsStatement()
|
loop.body = loop.body?.useAsStatement()
|
||||||
|
|
||||||
@@ -193,7 +216,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
override fun visitThrow(expression: IrThrow): IrExpression {
|
override fun visitThrow(expression: IrThrow): IrExpression {
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
expression.value = expression.value.useAs(builtIns.throwable.defaultType)
|
expression.value = expression.value.useAs(symbols.throwable.owner.defaultType)
|
||||||
|
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
@@ -238,8 +261,8 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||||
declaration.transformChildrenVoid(this)
|
declaration.transformChildrenVoid(this)
|
||||||
|
|
||||||
declaration.descriptor.valueParameters.forEach { parameter ->
|
declaration.valueParameters.forEach { parameter ->
|
||||||
val defaultValue = declaration.getDefault(parameter)
|
val defaultValue = parameter.defaultValue
|
||||||
if (defaultValue is IrExpressionBody) {
|
if (defaultValue is IrExpressionBody) {
|
||||||
defaultValue.expression = defaultValue.expression.useAsArgument(parameter)
|
defaultValue.expression = defaultValue.expression.useAsArgument(parameter)
|
||||||
}
|
}
|
||||||
@@ -247,7 +270,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
|
|
||||||
declaration.body?.let {
|
declaration.body?.let {
|
||||||
if (it is IrExpressionBody) {
|
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.ir.KonanSymbols
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
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.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
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) =
|
internal fun KonanSymbols.getTypeConversion(actualType: KotlinType, expectedType: KotlinType) =
|
||||||
getTypeConversion(actualType.correspondingValueType, expectedType.correspondingValueType)
|
getTypeConversion(actualType.correspondingValueType, expectedType.correspondingValueType)
|
||||||
|
|
||||||
|
internal fun KonanSymbols.getTypeConversion(actualType: IrType, expectedType: IrType) =
|
||||||
|
getTypeConversion(actualType.correspondingValueType, expectedType.correspondingValueType)
|
||||||
|
|
||||||
internal fun KonanSymbols.getTypeConversion(
|
internal fun KonanSymbols.getTypeConversion(
|
||||||
actualValueType: ValueType?,
|
actualValueType: ValueType?,
|
||||||
expectedValueType: ValueType?
|
expectedValueType: ValueType?
|
||||||
|
|||||||
+140
-89
@@ -18,18 +18,16 @@ package org.jetbrains.kotlin.backend.konan
|
|||||||
|
|
||||||
import llvm.LLVMDumpModule
|
import llvm.LLVMDumpModule
|
||||||
import llvm.LLVMModuleRef
|
import llvm.LLVMModuleRef
|
||||||
|
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
|
||||||
import org.jetbrains.kotlin.backend.common.ReflectionTypes
|
import org.jetbrains.kotlin.backend.common.ReflectionTypes
|
||||||
import org.jetbrains.kotlin.backend.common.validateIrModule
|
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.konan.descriptors.*
|
||||||
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
|
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.DescriptorsFactory
|
import org.jetbrains.kotlin.backend.common.descriptors.DescriptorsFactory
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIr
|
import org.jetbrains.kotlin.backend.konan.ir.KonanIr
|
||||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter
|
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter
|
||||||
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD
|
import org.jetbrains.kotlin.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.backend.konan.optimizations.DataFlowIR
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
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.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.util.endOffsetOrUndefined
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.util.startOffsetOrUndefined
|
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.IrElementVisitor
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
|
||||||
import org.jetbrains.kotlin.metadata.KonanLinkData
|
import org.jetbrains.kotlin.metadata.KonanLinkData
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import java.lang.System.out
|
import java.lang.System.out
|
||||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||||
|
|
||||||
@@ -66,72 +64,49 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
|||||||
private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) }
|
private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) }
|
||||||
private val outerThisFields = mutableMapOf<ClassDescriptor, IrField>()
|
private val outerThisFields = mutableMapOf<ClassDescriptor, IrField>()
|
||||||
private val bridgesDescriptors = mutableMapOf<Pair<IrSimpleFunction, BridgeDirections>, IrSimpleFunction>()
|
private val bridgesDescriptors = mutableMapOf<Pair<IrSimpleFunction, BridgeDirections>, IrSimpleFunction>()
|
||||||
private val loweredEnums = mutableMapOf<ClassDescriptor, LoweredEnum>()
|
private val loweredEnums = mutableMapOf<IrClass, LoweredEnum>()
|
||||||
private val ordinals = mutableMapOf<IrClass, Map<ClassDescriptor, Int>>()
|
private val ordinals = mutableMapOf<ClassDescriptor, Map<ClassDescriptor, Int>>()
|
||||||
|
|
||||||
object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
|
object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
|
||||||
IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
||||||
|
|
||||||
fun getOuterThisField(innerClassDescriptor: ClassDescriptor): IrField =
|
fun getOuterThisField(innerClass: IrClass): IrField =
|
||||||
if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor")
|
if (!innerClass.descriptor.isInner) throw AssertionError("Class is not inner: ${innerClass.descriptor}")
|
||||||
else outerThisFields.getOrPut(innerClassDescriptor) {
|
else outerThisFields.getOrPut(innerClass.descriptor) {
|
||||||
val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) ?:
|
val outerClass = innerClass.parent as? IrClass
|
||||||
throw AssertionError("No containing class for inner class $innerClassDescriptor")
|
?: 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(
|
val descriptor = PropertyDescriptorImpl.create(
|
||||||
innerClassDescriptor, Annotations.EMPTY, Modality.FINAL,
|
innerClass.descriptor, Annotations.EMPTY, Modality.FINAL,
|
||||||
Visibilities.PRIVATE, false, "this$0".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED,
|
Visibilities.PRIVATE, false, "this$0".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
SourceElement.NO_SOURCE, false, false, false, false, false, false
|
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(
|
IrFieldImpl(
|
||||||
innerClassDescriptor.startOffsetOrUndefined,
|
innerClass.descriptor.startOffsetOrUndefined,
|
||||||
innerClassDescriptor.endOffsetOrUndefined,
|
innerClass.descriptor.endOffsetOrUndefined,
|
||||||
DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS,
|
DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS,
|
||||||
descriptor
|
descriptor,
|
||||||
|
outerClass.defaultType
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): IrSimpleFunction {
|
fun getLoweredEnum(enumClass: IrClass): LoweredEnum {
|
||||||
val irFunction = overriddenFunctionDescriptor.descriptor
|
assert(enumClass.kind == ClassKind.ENUM_CLASS, { "Expected enum class but was: ${enumClass.descriptor}" })
|
||||||
val descriptor = irFunction.descriptor
|
return loweredEnums.getOrPut(enumClass) {
|
||||||
assert(overriddenFunctionDescriptor.needBridge,
|
enumSpecialDeclarationsFactory.createLoweredEnum(enumClass)
|
||||||
{ "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(enumClassDescriptor: ClassDescriptor): LoweredEnum {
|
private fun assignOrdinalsToEnumEntries(classDescriptor: ClassDescriptor): Map<ClassDescriptor, Int> {
|
||||||
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> {
|
|
||||||
val enumEntryOrdinals = mutableMapOf<ClassDescriptor, Int>()
|
val enumEntryOrdinals = mutableMapOf<ClassDescriptor, Int>()
|
||||||
irClass.declarations.filterIsInstance<IrEnumEntry>().forEachIndexed { index, entry ->
|
classDescriptor.enumEntries.forEachIndexed { index, entry ->
|
||||||
enumEntryOrdinals[entry.descriptor] = index
|
enumEntryOrdinals[entry] = index
|
||||||
}
|
}
|
||||||
return enumEntryOrdinals
|
return enumEntryOrdinals
|
||||||
}
|
}
|
||||||
@@ -145,54 +120,130 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
|||||||
.first { entryDescriptor.name == enumClassDescriptor.c.nameResolver.getName(it.name) }
|
.first { entryDescriptor.name == enumClassDescriptor.c.nameResolver.getName(it.name) }
|
||||||
.getExtension(KonanLinkData.enumEntryOrdinal)
|
.getExtension(KonanLinkData.enumEntryOrdinal)
|
||||||
}
|
}
|
||||||
val enumClass = context.ir.getEnum(enumClassDescriptor)
|
return ordinals.getOrPut(enumClassDescriptor) { assignOrdinalsToEnumEntries(enumClassDescriptor) }[entryDescriptor]!!
|
||||||
return ordinals.getOrPut(enumClass) { assignOrdinalsToEnumEntries(enumClass) }[entryDescriptor]!!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initializeBridgeDescriptor(bridgeDescriptor: SimpleFunctionDescriptorImpl,
|
fun getBridge(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): IrSimpleFunction {
|
||||||
descriptor: FunctionDescriptor,
|
val irFunction = overriddenFunctionDescriptor.descriptor
|
||||||
bridgeDirections: Array<BridgeDirection>) {
|
assert(overriddenFunctionDescriptor.needBridge,
|
||||||
val returnType = when (bridgeDirections[0]) {
|
{ "Function ${irFunction.descriptor} is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor.descriptor}" })
|
||||||
BridgeDirection.TO_VALUE_TYPE -> descriptor.returnType!!
|
val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections
|
||||||
BridgeDirection.NOT_NEEDED -> descriptor.returnType
|
return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) {
|
||||||
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.nullableAnyType
|
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]) {
|
val extensionReceiverType = when (bridgeDirections.array[1]) {
|
||||||
BridgeDirection.TO_VALUE_TYPE -> descriptor.extensionReceiverParameter!!.type
|
BridgeDirection.TO_VALUE_TYPE -> function.extensionReceiverParameter!!.type
|
||||||
BridgeDirection.NOT_NEEDED -> descriptor.extensionReceiverParameter?.type
|
BridgeDirection.NOT_NEEDED -> function.extensionReceiverParameter?.type
|
||||||
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.nullableAnyType
|
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 valueParameters = descriptor.valueParameters.mapIndexed { index, valueParameterDescriptor ->
|
||||||
val outType = when (bridgeDirections[index + 2]) {
|
ValueParameterDescriptorImpl(
|
||||||
BridgeDirection.TO_VALUE_TYPE -> valueParameterDescriptor.type
|
|
||||||
BridgeDirection.NOT_NEEDED -> valueParameterDescriptor.type
|
|
||||||
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.nullableAnyType
|
|
||||||
}
|
|
||||||
ValueParameterDescriptorImpl(
|
|
||||||
containingDeclaration = valueParameterDescriptor.containingDeclaration,
|
containingDeclaration = valueParameterDescriptor.containingDeclaration,
|
||||||
original = null,
|
original = null,
|
||||||
index = index,
|
index = index,
|
||||||
annotations = Annotations.EMPTY,
|
annotations = Annotations.EMPTY,
|
||||||
name = valueParameterDescriptor.name,
|
name = valueParameterDescriptor.name,
|
||||||
outType = outType,
|
outType = valueParameterTypes[index].toKotlinType(),
|
||||||
declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(),
|
declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(),
|
||||||
isCrossinline = valueParameterDescriptor.isCrossinline,
|
isCrossinline = valueParameterDescriptor.isCrossinline,
|
||||||
isNoinline = valueParameterDescriptor.isNoinline,
|
isNoinline = valueParameterDescriptor.isNoinline,
|
||||||
varargElementType = valueParameterDescriptor.varargElementType,
|
varargElementType = valueParameterDescriptor.varargElementType,
|
||||||
source = SourceElement.NO_SOURCE)
|
source = SourceElement.NO_SOURCE)
|
||||||
}
|
}
|
||||||
bridgeDescriptor.initialize(
|
bridgeDescriptor.initialize(
|
||||||
/* receiverParameterType = */ extensionReceiverType,
|
/* receiverParameterType = */ extensionReceiverType?.toKotlinType(),
|
||||||
/* dispatchReceiverParameter = */ descriptor.dispatchReceiverParameter,
|
/* dispatchReceiverParameter = */ descriptor.dispatchReceiverParameter,
|
||||||
/* typeParameters = */ descriptor.typeParameters,
|
/* typeParameters = */ descriptor.typeParameters,
|
||||||
/* unsubstitutedValueParameters = */ valueParameters,
|
/* unsubstitutedValueParameters = */ valueParameters,
|
||||||
/* unsubstitutedReturnType = */ returnType,
|
/* unsubstitutedReturnType = */ returnType.toKotlinType(),
|
||||||
/* modality = */ descriptor.modality,
|
/* modality = */ descriptor.modality,
|
||||||
/* visibility = */ descriptor.visibility).apply {
|
/* visibility = */ descriptor.visibility).apply {
|
||||||
isSuspend = descriptor.isSuspend
|
isSuspend = descriptor.isSuspend
|
||||||
}
|
}
|
||||||
|
return bridgeDescriptor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+33
-22
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan
|
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.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.descriptors.enumEntries
|
||||||
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.*
|
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.MemberScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
|
||||||
import org.jetbrains.kotlin.types.Variance
|
|
||||||
import org.jetbrains.kotlin.types.replace
|
|
||||||
|
|
||||||
|
|
||||||
internal object DECLARATION_ORIGIN_ENUM :
|
internal object DECLARATION_ORIGIN_ENUM :
|
||||||
@@ -48,36 +45,45 @@ internal data class LoweredEnum(val implObject: IrClass,
|
|||||||
val entriesMap: Map<Name, Int>)
|
val entriesMap: Map<Name, Int>)
|
||||||
|
|
||||||
internal class EnumSpecialDeclarationsFactory(val context: Context) {
|
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 startOffset = enumClass.startOffset
|
||||||
val endOffset = enumClassDescriptor.endOffsetOrUndefined
|
val endOffset = enumClass.endOffset
|
||||||
|
|
||||||
val implObjectDescriptor = ClassDescriptorImpl(enumClassDescriptor, "OBJECT".synthesizedName, Modality.FINAL,
|
val implObjectDescriptor = ClassDescriptorImpl(enumClassDescriptor, "OBJECT".synthesizedName, Modality.FINAL,
|
||||||
ClassKind.OBJECT, listOf(context.builtIns.anyType), SourceElement.NO_SOURCE, false, LockBasedStorageManager.NO_LOCKS)
|
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 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 valuesGetterDescriptor = createValuesGetterDescriptor(enumClassDescriptor, implObjectDescriptor)
|
||||||
val valuesGetter = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesGetterDescriptor).apply {
|
val valuesGetter = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesGetterDescriptor).also {
|
||||||
createParameterDeclarations()
|
it.returnType = valuesType
|
||||||
|
it.parent = implObject
|
||||||
|
it.createDispatchReceiverParameter()
|
||||||
}
|
}
|
||||||
|
|
||||||
val memberScope = MemberScope.Empty
|
val memberScope = MemberScope.Empty
|
||||||
|
|
||||||
val constructorOfAny = context.builtIns.any.constructors.first()
|
val constructorOfAny = context.irBuiltIns.anyClass.owner.constructors.first()
|
||||||
// TODO: why primary?
|
// 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)
|
implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor)
|
||||||
val implObject = IrClassImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, implObjectDescriptor).apply {
|
implObject.setSuperSymbolsAndAddFakeOverrides(listOf(context.irBuiltIns.anyType))
|
||||||
createParameterDeclarations()
|
implObject.parent = enumClass
|
||||||
addFakeOverrides()
|
|
||||||
setSuperSymbols(listOf(context.ir.symbols.any.owner))
|
|
||||||
}
|
|
||||||
implObject.parent = context.ir.getEnum(enumClassDescriptor)
|
|
||||||
valuesGetter.parent = implObject
|
|
||||||
valuesField.parent = implObject
|
valuesField.parent = implObject
|
||||||
|
|
||||||
val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor)
|
val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor)
|
||||||
@@ -115,7 +121,12 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) {
|
|||||||
val receiver = ReceiverParameterDescriptorImpl(implObjectDescriptor, ImplicitClassReceiver(implObjectDescriptor))
|
val receiver = ReceiverParameterDescriptorImpl(implObjectDescriptor, ImplicitClassReceiver(implObjectDescriptor))
|
||||||
return PropertyDescriptorImpl.create(implObjectDescriptor, Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC,
|
return PropertyDescriptorImpl.create(implObjectDescriptor, Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC,
|
||||||
false, "VALUES".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE,
|
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
|
private val genericArrayType = context.ir.symbols.array.descriptor
|
||||||
|
|||||||
+1
-1
@@ -79,7 +79,7 @@ fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironme
|
|||||||
context.irModule = module
|
context.irModule = module
|
||||||
context.ir.symbols = symbols
|
context.ir.symbols = symbols
|
||||||
|
|
||||||
validateIrModule(context, module)
|
// validateIrModule(context, module)
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.SERIALIZER) {
|
phaser.phase(KonanPhase.SERIALIZER) {
|
||||||
markBackingFields(context)
|
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.runOnFilePostfix
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
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.*
|
||||||
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.InitializersLowering
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.LateinitLowering
|
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.backend.konan.lower.SharedVariablesLowering
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
@@ -83,12 +79,10 @@ internal class KonanLower(val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val symbolTable = context.ir.symbols.symbolTable
|
val symbolTable = context.ir.symbols.symbolTable
|
||||||
irModule.referenceAllTypeExternalClassifiers(symbolTable)
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
irModule.replaceUnboundSymbols(context)
|
irModule.replaceUnboundSymbols(context)
|
||||||
irModule.referenceAllTypeExternalClassifiers(symbolTable)
|
|
||||||
} while (symbolTable.unboundClasses.isNotEmpty())
|
} while (symbolTable.unboundClasses.isNotEmpty())
|
||||||
|
|
||||||
irModule.patchDeclarationParents()
|
irModule.patchDeclarationParents()
|
||||||
|
|||||||
+73
@@ -17,7 +17,14 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan
|
package org.jetbrains.kotlin.backend.konan
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
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.name.FqNameUnsafe
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,3 +103,69 @@ val KotlinType.correspondingValueType: ValueType?
|
|||||||
get() = ValueType.values().firstOrNull {
|
get() = ValueType.values().firstOrNull {
|
||||||
isRepresentedAs(it)
|
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 {
|
} else {
|
||||||
descriptor
|
descriptor
|
||||||
}
|
}
|
||||||
context.specialDeclarationsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor))
|
context.specialDeclarationsFactory.getBridge(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor))
|
||||||
}
|
}
|
||||||
return if (implementation.modality == Modality.ABSTRACT) null else implementation
|
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.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.ir.types.isUnit
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.types.SimpleType
|
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)
|
* 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.common.descriptors.SharedVariablesManager
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
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.ClassConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
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.IrCompositeImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
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.constructors
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
|
|
||||||
internal class KonanSharedVariablesManager(val context: KonanBackendContext) : SharedVariablesManager {
|
internal class KonanSharedVariablesManager(val context: KonanBackendContext) : SharedVariablesManager {
|
||||||
@@ -55,7 +56,7 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun refType(elementType: KotlinType): KotlinType {
|
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 {
|
private fun getElementPropertyDescriptor(sharedVariableDescriptor: VariableDescriptor): PropertyDescriptor {
|
||||||
@@ -74,18 +75,19 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S
|
|||||||
false, false, variableDescriptor.source
|
false, false, variableDescriptor.source
|
||||||
)
|
)
|
||||||
|
|
||||||
val valueType = originalDeclaration.descriptor.type
|
val valueType = originalDeclaration.type
|
||||||
|
|
||||||
val refConstructorTypeArguments = mapOf(refClassConstructor.descriptor.typeParameters[0] to valueType)
|
|
||||||
|
|
||||||
val refConstructorCall = IrCallImpl(
|
val refConstructorCall = IrCallImpl(
|
||||||
originalDeclaration.startOffset, originalDeclaration.endOffset,
|
originalDeclaration.startOffset, originalDeclaration.endOffset,
|
||||||
refClassConstructor, refConstructor(valueType), refConstructorTypeArguments
|
refClass.typeWith(valueType),
|
||||||
)
|
refClassConstructor, refConstructor(valueType.toKotlinType()), 1
|
||||||
|
).apply {
|
||||||
|
putTypeArgument(0, valueType)
|
||||||
|
}
|
||||||
|
|
||||||
return IrVariableImpl(
|
return IrVariableImpl(
|
||||||
originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin,
|
originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin,
|
||||||
sharedVariableDescriptor
|
sharedVariableDescriptor, refConstructorCall.type
|
||||||
).apply {
|
).apply {
|
||||||
initializer = refConstructorCall
|
initializer = refConstructorCall
|
||||||
}
|
}
|
||||||
@@ -97,16 +99,18 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S
|
|||||||
val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableDeclaration.descriptor)
|
val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableDeclaration.descriptor)
|
||||||
|
|
||||||
val sharedVariableInitialization =
|
val sharedVariableInitialization =
|
||||||
IrCallImpl(initializer.startOffset, initializer.endOffset, elementProperty.setter!!.symbol,
|
IrCallImpl(initializer.startOffset, initializer.endOffset,
|
||||||
|
context.irBuiltIns.unitType, elementProperty.setter!!.symbol,
|
||||||
elementPropertyDescriptor.setter!!)
|
elementPropertyDescriptor.setter!!)
|
||||||
|
|
||||||
sharedVariableInitialization.dispatchReceiver =
|
sharedVariableInitialization.dispatchReceiver =
|
||||||
IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableDeclaration.symbol)
|
IrGetValueImpl(initializer.startOffset, initializer.endOffset,
|
||||||
|
sharedVariableDeclaration.type, sharedVariableDeclaration.symbol)
|
||||||
|
|
||||||
sharedVariableInitialization.putValueArgument(0, initializer)
|
sharedVariableInitialization.putValueArgument(0, initializer)
|
||||||
|
|
||||||
return IrCompositeImpl(
|
return IrCompositeImpl(
|
||||||
originalDeclaration.startOffset, originalDeclaration.endOffset, context.builtIns.unitType, null,
|
originalDeclaration.startOffset, originalDeclaration.endOffset, context.irBuiltIns.unitType, null,
|
||||||
listOf(sharedVariableDeclaration, sharedVariableInitialization)
|
listOf(sharedVariableDeclaration, sharedVariableInitialization)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -115,18 +119,25 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S
|
|||||||
|
|
||||||
val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableSymbol.descriptor)
|
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 {
|
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 {
|
override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetVariable): IrExpression {
|
||||||
val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableSymbol.descriptor)
|
val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableSymbol.descriptor)
|
||||||
|
|
||||||
return IrCallImpl(originalSet.startOffset, originalSet.endOffset, elementProperty.setter!!.symbol,
|
return IrCallImpl(originalSet.startOffset, originalSet.endOffset, context.irBuiltIns.unitType,
|
||||||
elementPropertyDescriptor.setter!!).apply {
|
elementProperty.setter!!.symbol, elementPropertyDescriptor.setter!!).apply {
|
||||||
dispatchReceiver = IrGetValueImpl(originalSet.startOffset, originalSet.endOffset, sharedVariableSymbol)
|
dispatchReceiver = IrGetValueImpl(
|
||||||
|
originalSet.startOffset, originalSet.endOffset,
|
||||||
|
sharedVariableSymbol.owner.type, sharedVariableSymbol
|
||||||
|
)
|
||||||
putValueArgument(0, originalSet.value)
|
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.KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS
|
||||||
import org.jetbrains.kotlin.backend.konan.ValueType
|
import org.jetbrains.kotlin.backend.konan.ValueType
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.konanInternal
|
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.llvm.findMainEntryPoint
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.TestProcessor
|
import org.jetbrains.kotlin.backend.konan.lower.TestProcessor
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
@@ -38,12 +39,19 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.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.SymbolTable
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
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.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
@@ -58,9 +66,6 @@ internal class KonanIr(context: Context, irModule: IrModuleFragment): Ir<Context
|
|||||||
|
|
||||||
override var symbols: KonanSymbols by Delegates.notNull()
|
override var symbols: KonanSymbols by Delegates.notNull()
|
||||||
|
|
||||||
fun getClass(type: KotlinType): IrClass? =
|
|
||||||
(type.constructor.declarationDescriptor as? ClassDescriptor)?.let { get(it) }
|
|
||||||
|
|
||||||
fun get(descriptor: FunctionDescriptor): IrFunction {
|
fun get(descriptor: FunctionDescriptor): IrFunction {
|
||||||
return moduleIndexForCodegen.functions[descriptor]
|
return moduleIndexForCodegen.functions[descriptor]
|
||||||
?: symbols.symbolTable.referenceFunction(descriptor).owner
|
?: symbols.symbolTable.referenceFunction(descriptor).owner
|
||||||
@@ -90,10 +95,35 @@ internal class KonanIr(context: Context, irModule: IrModuleFragment): Ir<Context
|
|||||||
?: symbols.symbolTable.referenceEnumEntry(descriptor).owner
|
?: symbols.symbolTable.referenceEnumEntry(descriptor).owner
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEnum(descriptor: ClassDescriptor): IrClass {
|
fun translateErased(type: KotlinType): IrSimpleType = symbols.symbolTable.translateErased(type)
|
||||||
assert(descriptor.kind == ClassKind.ENUM_CLASS)
|
|
||||||
return originalModuleIndex.classes[descriptor]
|
fun translateBroken(type: KotlinType): IrType {
|
||||||
?: symbols.symbolTable.referenceClass(descriptor).owner
|
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 throwable = symbolTable.referenceClass(builtIns.throwable)
|
||||||
val string = symbolTable.referenceClass(builtIns.string)
|
val string = symbolTable.referenceClass(builtIns.string)
|
||||||
val enum = symbolTable.referenceClass(builtIns.enum)
|
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))
|
val arrayList = symbolTable.referenceClass(getArrayListClassDescriptor(context))
|
||||||
|
|
||||||
@@ -225,19 +257,25 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
|
|||||||
val getProgressionLast = context.getInternalFunctions("getProgressionLast")
|
val getProgressionLast = context.getInternalFunctions("getProgressionLast")
|
||||||
.map { Pair(it.returnType, symbolTable.referenceSimpleFunction(it)) }.toMap()
|
.map { Pair(it.returnType, symbolTable.referenceSimpleFunction(it)) }.toMap()
|
||||||
|
|
||||||
val arrayContentToString = arrayTypes.associateBy({ it }, { findArrayExtension(it, "contentToString") })
|
val arrayContentToString = arrays.associateBy(
|
||||||
val arrayContentHashCode = arrayTypes.associateBy({ it }, { findArrayExtension(it, "contentHashCode") })
|
{ it },
|
||||||
|
{ findArrayExtension(it.descriptor, "contentToString") }
|
||||||
|
)
|
||||||
|
val arrayContentHashCode = arrays.associateBy(
|
||||||
|
{ it },
|
||||||
|
{ findArrayExtension(it.descriptor, "contentHashCode") }
|
||||||
|
)
|
||||||
|
|
||||||
fun findArrayExtension(type: KotlinType, name: String): IrSimpleFunctionSymbol {
|
fun findArrayExtension(descriptor: ClassDescriptor, name: String): IrSimpleFunctionSymbol {
|
||||||
val descriptor = builtInsPackage("kotlin", "collections")
|
val functionDescriptor = builtInsPackage("kotlin", "collections")
|
||||||
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
|
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
|
||||||
.singleOrNull {
|
.singleOrNull {
|
||||||
it.valueParameters.isEmpty()
|
it.valueParameters.isEmpty()
|
||||||
&& (it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.defaultType == type
|
&& it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == descriptor
|
||||||
&& !it.isExpect
|
&& !it.isExpect
|
||||||
}
|
}
|
||||||
?: throw Error(type.toString())
|
?: throw Error(descriptor.toString())
|
||||||
return symbolTable.referenceSimpleFunction(descriptor)
|
return symbolTable.referenceSimpleFunction(functionDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val copyRangeTo = arrays.map { symbol ->
|
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)
|
val kFunctions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS)
|
||||||
.map { symbolTable.referenceClass(context.reflectionTypes.getKFunction(it)) }
|
.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)
|
val suspendFunctions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS)
|
||||||
.map { symbolTable.referenceClass(builtIns.getSuspendFunction(it)) }
|
.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.IrClassifierSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
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.IrElementTransformer
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
import org.jetbrains.kotlin.konan.file.File
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
@@ -148,7 +149,7 @@ interface IrSuspendableExpression : IrExpression {
|
|||||||
var result: 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 suspensionPointIdParameter: IrVariable,
|
||||||
override var result: IrExpression,
|
override var result: IrExpression,
|
||||||
override var resumeResult: 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)
|
override var suspensionPointId: IrExpression, override var result: IrExpression)
|
||||||
: IrExpressionBase(startOffset, endOffset, type), IrSuspendableExpression {
|
: IrExpressionBase(startOffset, endOffset, type), IrSuspendableExpression {
|
||||||
|
|
||||||
@@ -198,7 +199,7 @@ internal interface IrPrivateFunctionCall : IrCall {
|
|||||||
|
|
||||||
internal class IrPrivateFunctionCallImpl(startOffset: Int,
|
internal class IrPrivateFunctionCallImpl(startOffset: Int,
|
||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
type: KotlinType,
|
type: IrType,
|
||||||
override val symbol: IrFunctionSymbol,
|
override val symbol: IrFunctionSymbol,
|
||||||
override val descriptor: FunctionDescriptor,
|
override val descriptor: FunctionDescriptor,
|
||||||
override val virtualCallee: IrCall?,
|
override val virtualCallee: IrCall?,
|
||||||
@@ -235,9 +236,9 @@ internal interface IrPrivateClassReference : IrClassReference {
|
|||||||
|
|
||||||
internal class IrPrivateClassReferenceImpl(startOffset: Int,
|
internal class IrPrivateClassReferenceImpl(startOffset: Int,
|
||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
type: KotlinType,
|
type: IrType,
|
||||||
symbol: IrClassifierSymbol,
|
symbol: IrClassifierSymbol,
|
||||||
override val classType: KotlinType,
|
override val classType: IrType,
|
||||||
override val moduleDescriptor: ModuleDescriptor,
|
override val moduleDescriptor: ModuleDescriptor,
|
||||||
override val totalClasses: Int,
|
override val totalClasses: Int,
|
||||||
override val classIndex: 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.*
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.llvmSymbolOrigin
|
import org.jetbrains.kotlin.backend.konan.llvm.llvmSymbolOrigin
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
|
||||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
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
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
|
||||||
// This file contains some IR utilities which actually use descriptors.
|
// This file contains some IR utilities which actually use descriptors.
|
||||||
// TODO: port this code to IR.
|
// 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 IrDeclaration.isAnonymousObject get() = DescriptorUtils.isAnonymousObject(this.descriptor)
|
||||||
internal val IrFunction.isExternal get() = this.descriptor.isExternal
|
internal val IrFunction.isExternal get() = this.descriptor.isExternal
|
||||||
internal val IrDeclaration.isLocal get() = DescriptorUtils.isLocal(this.descriptor)
|
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 IrFunction.isMain() = MainFunctionDetector.isMain(this.descriptor)
|
||||||
|
|
||||||
internal fun IrTypeOperatorCall.getTypeOperandClass(context: Context): IrClass? =
|
internal fun IrType.isObjCObjectType() = this.toKotlinType().isObjCObjectType()
|
||||||
context.ir.getClass(this.typeOperand)
|
|
||||||
|
|
||||||
internal fun IrCatch.getCatchParameterTypeClass(context: Context): IrClass? =
|
|
||||||
context.ir.getClass(this.catchParameter.type)
|
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -27,5 +27,7 @@ internal typealias ConstructorDescriptor = IrConstructor
|
|||||||
internal typealias ClassConstructorDescriptor = IrConstructor
|
internal typealias ClassConstructorDescriptor = IrConstructor
|
||||||
internal typealias PackageFragmentDescriptor = IrPackageFragment
|
internal typealias PackageFragmentDescriptor = IrPackageFragment
|
||||||
internal typealias VariableDescriptor = IrVariable
|
internal typealias VariableDescriptor = IrVariable
|
||||||
internal typealias ValueDescriptor = IrSymbolDeclaration<IrValueSymbol>
|
internal typealias ValueDescriptor = IrValueDeclaration
|
||||||
internal typealias ParameterDescriptor = IrValueParameter
|
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.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
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.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.getTypeArgumentOrDefault
|
import org.jetbrains.kotlin.ir.util.explicitParameters
|
||||||
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.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.constants.*
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
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
|
val IrConstructor.constructedClass get() = this.parent as IrClass
|
||||||
|
|
||||||
@@ -88,26 +75,6 @@ val IrFunction.allParameters: List<IrValueParameter>
|
|||||||
explicitParameters
|
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 IrValueParameter.isVararg get() = this.varargElementType != null
|
||||||
|
|
||||||
val IrFunction.isSuspend get() = this is IrSimpleFunction && this.isSuspend
|
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()
|
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.getSuperClassNotAny() = this.superClasses.map { it.owner }.atMostOne { !it.isInterface && !it.isAny() }
|
||||||
|
|
||||||
fun IrClass.isAny() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.any.toSafe()
|
fun IrClass.isAny() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.any.toSafe()
|
||||||
@@ -132,7 +100,8 @@ val IrProperty.konanBackingField: IrField?
|
|||||||
this.startOffset,
|
this.startOffset,
|
||||||
this.endOffset,
|
this.endOffset,
|
||||||
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
|
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 {
|
).also {
|
||||||
it.parent = this.parent
|
it.parent = this.parent
|
||||||
}
|
}
|
||||||
@@ -143,9 +112,6 @@ val IrProperty.konanBackingField: IrField?
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val IrClass.defaultType: KotlinType
|
|
||||||
get() = this.thisReceiver!!.type
|
|
||||||
|
|
||||||
val IrField.containingClass get() = this.parent as? IrClass
|
val IrField.containingClass get() = this.parent as? IrClass
|
||||||
|
|
||||||
val IrFunction.isReal get() = this.origin != IrDeclarationOrigin.FAKE_OVERRIDE
|
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()
|
fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing()
|
||||||
|
|
||||||
val IrClass.constructors get() = this.declarations.filterIsInstance<IrConstructor>()
|
|
||||||
|
|
||||||
internal val IrValueParameter.isValueParameter get() = this.index >= 0
|
internal val IrValueParameter.isValueParameter get() = this.index >= 0
|
||||||
|
|
||||||
fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTable) {
|
private val IrCall.annotationClass
|
||||||
val moduleDescriptor = this.descriptor
|
get() = (this.symbol.owner as IrConstructor).constructedClass
|
||||||
|
|
||||||
fun KotlinType.referenceAllClassifiers() {
|
fun List<IrCall>.hasAnnotation(fqName: FqName): Boolean =
|
||||||
TypeUtils.getClassDescriptor(this)?.let {
|
this.any { it.annotationClass.fqNameSafe == fqName }
|
||||||
if (!ErrorUtils.isError(it) && it.module != moduleDescriptor) {
|
|
||||||
if (it.kind == ClassKind.ENUM_ENTRY) {
|
|
||||||
symbolTable.referenceEnumEntry(it)
|
|
||||||
} else {
|
|
||||||
symbolTable.referenceClass(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.constructor.supertypes.forEach {
|
fun IrAnnotationContainer.hasAnnotation(fqName: FqName) =
|
||||||
it.referenceAllClassifiers()
|
this.annotations.hasAnnotation(fqName)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val visitor = object : IrElementVisitorVoid {
|
fun List<IrCall>.findAnnotation(fqName: FqName): IrCall? = this.firstOrNull {
|
||||||
override fun visitElement(element: IrElement) {
|
it.annotationClass.fqNameSafe == fqName
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+20
-23
@@ -17,25 +17,19 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.llvm
|
package org.jetbrains.kotlin.backend.konan.llvm
|
||||||
|
|
||||||
import llvm.LLVMTypeRef
|
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.descriptors.isAbstract
|
||||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||||
import org.jetbrains.kotlin.backend.konan.isValueType
|
import org.jetbrains.kotlin.backend.konan.isValueType
|
||||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
|
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
|
||||||
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
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.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.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.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
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 val inlineExposedAnnotation = FqName("kotlin.internal.InlineExposed")
|
||||||
|
|
||||||
private fun acyclicTypeMangler(visited: MutableSet<TypeParameterDescriptor>, type: KotlinType): String {
|
private fun acyclicTypeMangler(visited: MutableSet<TypeParameterDescriptor>, type: IrType): String {
|
||||||
val descriptor = TypeUtils.getTypeParameterDescriptorOrNull(type)
|
val descriptor = (type.classifierOrNull as? IrTypeParameterSymbol)?.owner
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
val upperBounds = if (visited.contains(descriptor)) "" else {
|
val upperBounds = if (visited.contains(descriptor)) "" else {
|
||||||
|
|
||||||
visited.add(descriptor)
|
visited.add(descriptor)
|
||||||
|
|
||||||
descriptor.upperBounds.map {
|
descriptor.superTypes.map {
|
||||||
val bound = acyclicTypeMangler(visited, it)
|
val bound = acyclicTypeMangler(visited, it)
|
||||||
if (bound == "kotlin.Any?") "" else "_$bound"
|
if (bound == "kotlin.Any?") "" else "_$bound"
|
||||||
}.joinToString("")
|
}.joinToString("")
|
||||||
@@ -143,24 +137,27 @@ private fun acyclicTypeMangler(visited: MutableSet<TypeParameterDescriptor>, typ
|
|||||||
return "#GENERIC" + upperBounds
|
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()) {
|
if (!type.arguments.isEmpty()) {
|
||||||
hashString += "<${type.arguments.map {
|
hashString += "<${type.arguments.map {
|
||||||
if (it.isStarProjection()) {
|
when (it) {
|
||||||
"#STAR"
|
is IrStarProjection -> "#STAR"
|
||||||
} else {
|
is IrTypeProjection -> {
|
||||||
val variance = it.projectionKind.label
|
val variance = it.variance.label
|
||||||
val projection = if (variance == "") "" else "${variance}_"
|
val projection = if (variance == "") "" else "${variance}_"
|
||||||
projection + acyclicTypeMangler(visited, it.type)
|
projection + acyclicTypeMangler(visited, it.type)
|
||||||
|
}
|
||||||
|
else -> error(it)
|
||||||
}
|
}
|
||||||
}.joinToString(",")}>"
|
}.joinToString(",")}>"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.isMarkedNullable) hashString += "?"
|
if (type.hasQuestionMark) hashString += "?"
|
||||||
return hashString
|
return hashString
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun typeToHashString(type: KotlinType)
|
private fun typeToHashString(type: IrType)
|
||||||
= acyclicTypeMangler(mutableSetOf<TypeParameterDescriptor>(), type)
|
= acyclicTypeMangler(mutableSetOf<TypeParameterDescriptor>(), type)
|
||||||
|
|
||||||
private val FunctionDescriptor.signature: String
|
private val FunctionDescriptor.signature: String
|
||||||
@@ -175,7 +172,7 @@ private val FunctionDescriptor.signature: String
|
|||||||
when {
|
when {
|
||||||
this.typeParameters.isNotEmpty() -> "Generic"
|
this.typeParameters.isNotEmpty() -> "Generic"
|
||||||
returnType.isValueType() -> "ValueType"
|
returnType.isValueType() -> "ValueType"
|
||||||
!KotlinBuiltIns.isUnitOrNullableUnit(returnType) -> typeToHashString(returnType)
|
!returnType.isUnitOrNullableUnit() -> typeToHashString(returnType)
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
return "$extensionReceiverPart($argsPart)$signatureSuffix"
|
return "$extensionReceiverPart($argsPart)$signatureSuffix"
|
||||||
@@ -188,7 +185,7 @@ internal val FunctionDescriptor.functionName: String
|
|||||||
this.getObjCMethodInfo()?.let {
|
this.getObjCMethodInfo()?.let {
|
||||||
return buildString {
|
return buildString {
|
||||||
if (extensionReceiverParameter != null) {
|
if (extensionReceiverParameter != null) {
|
||||||
append(TypeUtils.getClassDescriptor(extensionReceiverParameter!!.type)!!.name)
|
append(extensionReceiverParameter!!.type.getClass()!!.name)
|
||||||
append(".")
|
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 {
|
return annotation.allValueArguments.values.ifNotEmpty {
|
||||||
val stringValue = single() as? StringValue
|
val stringValue = single() as? StringValue
|
||||||
stringValue?.value
|
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.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.objc.ObjCDataGenerator
|
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
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
|
||||||
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
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 {
|
fun getEnumEntry(descriptor: IrEnumEntry, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
||||||
val enumClassDescriptor = descriptor.containingDeclaration as ClassDescriptor
|
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 ordinal = loweredEnum.entriesMap[descriptor.name]!!
|
||||||
val values = call(
|
val values = call(
|
||||||
|
|||||||
+5
-8
@@ -20,9 +20,8 @@ import llvm.*
|
|||||||
import org.jetbrains.kotlin.backend.konan.ValueType
|
import org.jetbrains.kotlin.backend.konan.ValueType
|
||||||
import org.jetbrains.kotlin.backend.konan.isRepresentedAs
|
import org.jetbrains.kotlin.backend.konan.isRepresentedAs
|
||||||
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.ir.types.isUnit
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
|
||||||
|
|
||||||
private val valueTypes = ValueType.values().associate {
|
private val valueTypes = ValueType.values().associate {
|
||||||
it to when (it) {
|
it to when (it) {
|
||||||
@@ -41,7 +40,7 @@ private val valueTypes = ValueType.values().associate {
|
|||||||
internal val ValueType.llvmType
|
internal val ValueType.llvmType
|
||||||
get() = valueTypes[this]!!
|
get() = valueTypes[this]!!
|
||||||
|
|
||||||
internal fun RuntimeAware.getLLVMType(type: KotlinType): LLVMTypeRef {
|
internal fun RuntimeAware.getLLVMType(type: IrType): LLVMTypeRef {
|
||||||
for ((valueType, llvmType) in valueTypes) {
|
for ((valueType, llvmType) in valueTypes) {
|
||||||
if (type.isRepresentedAs(valueType)) {
|
if (type.isRepresentedAs(valueType)) {
|
||||||
return llvmType
|
return llvmType
|
||||||
@@ -54,13 +53,11 @@ internal fun RuntimeAware.getLLVMType(type: KotlinType): LLVMTypeRef {
|
|||||||
internal fun RuntimeAware.getLLVMType(type: DataFlowIR.Type) =
|
internal fun RuntimeAware.getLLVMType(type: DataFlowIR.Type) =
|
||||||
type.correspondingValueType?.let { valueTypes[it]!! } ?: this.kObjHeaderPtr
|
type.correspondingValueType?.let { valueTypes[it]!! } ?: this.kObjHeaderPtr
|
||||||
|
|
||||||
internal fun RuntimeAware.getLLVMReturnType(type: KotlinType): LLVMTypeRef {
|
internal fun RuntimeAware.getLLVMReturnType(type: IrType): LLVMTypeRef {
|
||||||
return when {
|
return when {
|
||||||
type.isUnit() -> LLVMVoidType()!!
|
type.isUnit() -> LLVMVoidType()!!
|
||||||
// TODO: stdlib have methods taking Nothing, such as kotlin.collections.EmptySet.contains().
|
// TODO: stdlib have methods taking Nothing, such as kotlin.collections.EmptySet.contains().
|
||||||
// KotlinBuiltIns.isNothing(type) -> LLVMVoidType()
|
// KotlinBuiltIns.isNothing(type) -> LLVMVoidType()
|
||||||
else -> getLLVMType(type)
|
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>
|
internal val FunctionDescriptor.types:List<KotlinType>
|
||||||
get() {
|
get() {
|
||||||
val parameters = valueParameters.map{it.type}
|
val parameters = descriptor.valueParameters.map{it.type}
|
||||||
return listOf(returnType, *parameters.toTypedArray())
|
return listOf(descriptor.returnType!!, *parameters.toTypedArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun KotlinType.size(context:Context) = context.debugInfo.llvmTypeSizes.getOrDefault(this, context.debugInfo.otherTypeSize)
|
internal fun KotlinType.size(context:Context) = context.debugInfo.llvmTypeSizes.getOrDefault(this, context.debugInfo.otherTypeSize)
|
||||||
|
|||||||
+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.irasdescriptors.*
|
||||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||||
import org.jetbrains.kotlin.backend.konan.optimizations.*
|
import org.jetbrains.kotlin.backend.konan.optimizations.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
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.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
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.util.getArguments
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
@@ -43,11 +44,6 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
|||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
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
|
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
|
* Creates new [ContinuationBlock] that receives the value of given Kotlin type
|
||||||
* and generates [code] starting from its beginning.
|
* and generates [code] starting from its beginning.
|
||||||
*/
|
*/
|
||||||
private fun continuationBlock(type: KotlinType,
|
private fun continuationBlock(type: IrType,
|
||||||
locationInfo: LocationInfo?, code: (ContinuationBlock) -> Unit = {}): ContinuationBlock {
|
locationInfo: LocationInfo?, code: (ContinuationBlock) -> Unit = {}): ContinuationBlock {
|
||||||
val entry = functionGenerationContext.basicBlock("continuation_block", locationInfo)
|
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")
|
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.
|
// Note: even if all elements are const, they aren't guaranteed to be statically initialized.
|
||||||
// E.g. an element may be a pointer to lazy-initialized object (aka singleton).
|
// E.g. an element may be a pointer to lazy-initialized object (aka singleton).
|
||||||
@@ -934,7 +930,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
*/
|
*/
|
||||||
private val handler by lazy {
|
private val handler by lazy {
|
||||||
using(outerContext) {
|
using(outerContext) {
|
||||||
continuationBlock(context.builtIns.throwable.defaultType, endLocationInfoFromScope()) {
|
continuationBlock(context.ir.symbols.throwable.owner.defaultType, endLocationInfoFromScope()) {
|
||||||
genHandler(it.value)
|
genHandler(it.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1008,7 +1004,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
genCatchBlock()
|
genCatchBlock()
|
||||||
return // Remaining catch clauses are unreachable.
|
return // Remaining catch clauses are unreachable.
|
||||||
} else {
|
} else {
|
||||||
val isInstance = genInstanceOf(exception, catch.getCatchParameterTypeClass(context)!!)
|
val isInstance = genInstanceOf(exception, catch.catchParameter.type.getClass()!!)
|
||||||
val body = functionGenerationContext.basicBlock("catch", catch.startLocation)
|
val body = functionGenerationContext.basicBlock("catch", catch.startLocation)
|
||||||
val nextCheck = functionGenerationContext.basicBlock("catchCheck", catch.endLocation)
|
val nextCheck = functionGenerationContext.basicBlock("catchCheck", catch.endLocation)
|
||||||
functionGenerationContext.condBr(isInstance, body, nextCheck)
|
functionGenerationContext.condBr(isInstance, body, nextCheck)
|
||||||
@@ -1058,8 +1054,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
private fun evaluateWhen(expression: IrWhen): LLVMValueRef {
|
private fun evaluateWhen(expression: IrWhen): LLVMValueRef {
|
||||||
context.log{"evaluateWhen : ${ir2string(expression)}"}
|
context.log{"evaluateWhen : ${ir2string(expression)}"}
|
||||||
var bbExit: LLVMBasicBlockRef? = null // By default "when" does not have "exit".
|
var bbExit: LLVMBasicBlockRef? = null // By default "when" does not have "exit".
|
||||||
val isUnit = KotlinBuiltIns.isUnit(expression.type)
|
val isUnit = expression.type.isUnit()
|
||||||
val isNothing = KotlinBuiltIns.isNothing(expression.type)
|
val isNothing = expression.type.isNothing()
|
||||||
|
|
||||||
// We may not cover all cases if IrWhen is used as statement.
|
// We may not cover all cases if IrWhen is used as statement.
|
||||||
val coverAllCases = isUnconditional(expression.branches.last())
|
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 {
|
private fun evaluateGetValue(value: IrGetValue): LLVMValueRef {
|
||||||
context.log{"evaluateGetValue : ${ir2string(value)}"}
|
context.log{"evaluateGetValue : ${ir2string(value)}"}
|
||||||
val symbol = value.symbol
|
return currentCodeContext.genGetValue(value.symbol.owner)
|
||||||
val ir: IrSymbolDeclaration<IrValueSymbol> = when (symbol) {
|
|
||||||
is IrVariableSymbol -> symbol.owner
|
|
||||||
is IrValueParameterSymbol -> symbol.owner
|
|
||||||
else -> error(symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentCodeContext.genGetValue(ir)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -1221,11 +1210,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun KotlinType.isPrimitiveInteger(): Boolean {
|
private fun IrType.isPrimitiveInteger(): Boolean {
|
||||||
return isPrimitiveNumberType() &&
|
return this.isPrimitiveType() &&
|
||||||
!KotlinBuiltIns.isFloat(this) &&
|
!this.isBoolean() &&
|
||||||
!KotlinBuiltIns.isDouble(this) &&
|
!this.isFloat() &&
|
||||||
!KotlinBuiltIns.isChar(this)
|
!this.isDouble() &&
|
||||||
|
!this.isChar()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateIntegerCoercion(value: IrTypeOperatorCall): LLVMValueRef {
|
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 {
|
private fun evaluateCast(value: IrTypeOperatorCall): LLVMValueRef {
|
||||||
context.log{"evaluateCast : ${ir2string(value)}"}
|
context.log{"evaluateCast : ${ir2string(value)}"}
|
||||||
val dstDescriptor = value.getTypeOperandClass(context)!!
|
val dstDescriptor = value.typeOperand.getClass()!!
|
||||||
|
|
||||||
assert(!KotlinBuiltIns.isPrimitiveType(dstDescriptor.defaultType) &&
|
assert(!dstDescriptor.defaultType.isValueType() &&
|
||||||
!KotlinBuiltIns.isPrimitiveType(value.argument.type))
|
!value.argument.type.isValueType())
|
||||||
|
|
||||||
val srcArg = evaluateExpression(value.argument) // Evaluate src expression.
|
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.condBr(condition, bbNull, bbInstanceOf)
|
||||||
|
|
||||||
functionGenerationContext.positionAtEnd(bbNull)
|
functionGenerationContext.positionAtEnd(bbNull)
|
||||||
val resultNull = if (TypeUtils.isNullableType(type)) kTrue else kFalse
|
val resultNull = if (type.containsNull()) kTrue else kFalse
|
||||||
functionGenerationContext.br(bbExit)
|
functionGenerationContext.br(bbExit)
|
||||||
|
|
||||||
functionGenerationContext.positionAtEnd(bbInstanceOf)
|
functionGenerationContext.positionAtEnd(bbInstanceOf)
|
||||||
val typeOperandClass = value.getTypeOperandClass(context)
|
val typeOperandClass = value.typeOperand.getClass()
|
||||||
val resultInstanceOf = if (typeOperandClass != null) {
|
val resultInstanceOf = if (typeOperandClass != null) {
|
||||||
genInstanceOf(srcArg, typeOperandClass)
|
genInstanceOf(srcArg, typeOperandClass)
|
||||||
} else {
|
} 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.
|
* 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 {
|
private fun evaluateFunctionReference(expression: IrFunctionReference): LLVMValueRef {
|
||||||
// TODO: consider creating separate IR element for pointer to function.
|
// 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())
|
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 {
|
private fun evaluateIntrinsicCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
val descriptor = callee.descriptor.original
|
val descriptor = callee.descriptor.original
|
||||||
|
val function = callee.symbol.owner
|
||||||
val name = descriptor.fqNameUnsafe.asString()
|
val name = descriptor.fqNameUnsafe.asString()
|
||||||
|
|
||||||
when (name) {
|
when (name) {
|
||||||
@@ -2137,13 +2128,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
interop.nativePointedGetRawPointer, interop.cPointerGetRawValue -> args.single()
|
interop.nativePointedGetRawPointer, interop.cPointerGetRawValue -> args.single()
|
||||||
|
|
||||||
in interop.readPrimitive -> {
|
in interop.readPrimitive -> {
|
||||||
val pointerType = pointerType(codegen.getLLVMType(descriptor.returnType!!))
|
val pointerType = pointerType(codegen.getLLVMType(function.returnType))
|
||||||
val rawPointer = args.last()
|
val rawPointer = args.last()
|
||||||
val pointer = functionGenerationContext.bitcast(pointerType, rawPointer)
|
val pointer = functionGenerationContext.bitcast(pointerType, rawPointer)
|
||||||
functionGenerationContext.load(pointer)
|
functionGenerationContext.load(pointer)
|
||||||
}
|
}
|
||||||
in interop.writePrimitive -> {
|
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 rawPointer = args[1]
|
||||||
val pointer = functionGenerationContext.bitcast(pointerType, rawPointer)
|
val pointer = functionGenerationContext.bitcast(pointerType, rawPointer)
|
||||||
functionGenerationContext.store(args[2], pointer)
|
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
|
interop.getPointerSize -> Int32(LLVMPointerSize(codegen.llvmTargetData)).llvm
|
||||||
context.builtIns.nativePtrToLong -> {
|
context.builtIns.nativePtrToLong -> {
|
||||||
val intPtrValue = functionGenerationContext.ptrToInt(args.single(), codegen.intPtrType)
|
val intPtrValue = functionGenerationContext.ptrToInt(args.single(), codegen.intPtrType)
|
||||||
val resultType = functionGenerationContext.getLLVMType(descriptor.returnType!!)
|
val resultType = functionGenerationContext.getLLVMType(function.returnType)
|
||||||
|
|
||||||
if (resultType == intPtrValue.type) {
|
if (resultType == intPtrValue.type) {
|
||||||
intPtrValue
|
intPtrValue
|
||||||
@@ -2169,7 +2160,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
interop.getObjCClass -> {
|
interop.getObjCClass -> {
|
||||||
val typeArgument = callee.getTypeArgument(descriptor.typeParameters.single())
|
val typeArgument = callee.getTypeArgument(descriptor.typeParameters.single())
|
||||||
val irClass = context.ir.getClass(typeArgument!!)!!
|
val irClass = typeArgument!!.getClass()!!
|
||||||
genGetObjCClass(irClass)
|
genGetObjCClass(irClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2184,8 +2175,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
interop.writeBits -> genWriteBits(args)
|
interop.writeBits -> genWriteBits(args)
|
||||||
|
|
||||||
context.ir.symbols.getClassTypeInfo.descriptor -> {
|
context.ir.symbols.getClassTypeInfo.descriptor -> {
|
||||||
val typeArgument = callee.getTypeArgumentOrDefault(descriptor.typeParameters.single())
|
val typeArgument = callee.getTypeArgument(0)!!
|
||||||
val typeArgumentClass = context.ir.getClass(typeArgument)
|
val typeArgumentClass = typeArgument.getClass()
|
||||||
if (typeArgumentClass == null) {
|
if (typeArgumentClass == null) {
|
||||||
// E.g. for `T::class` in a body of an inline function itself.
|
// E.g. for `T::class` in a body of an inline function itself.
|
||||||
functionGenerationContext.unreachable()
|
functionGenerationContext.unreachable()
|
||||||
@@ -2202,7 +2193,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
context.ir.symbols.createUninitializedInstance.descriptor -> {
|
context.ir.symbols.createUninitializedInstance.descriptor -> {
|
||||||
val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0]
|
val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0]
|
||||||
val enumClass = callee.getTypeArgument(typeParameterT)!!
|
val enumClass = callee.getTypeArgument(typeParameterT)!!
|
||||||
val enumIrClass = context.ir.getClass(enumClass)!!
|
val enumIrClass = enumClass.getClass()!!
|
||||||
functionGenerationContext.allocInstance(enumIrClass, resultLifetime(callee))
|
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.backend.konan.irasdescriptors.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.ir.util.constructors
|
||||||
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
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.backend.konan.irasdescriptors.*
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -140,7 +141,7 @@ private fun Context.getDeclaredFields(classDescriptor: ClassDescriptor): List<Ir
|
|||||||
private fun ContextUtils.createClassBodyType(name: String, fields: List<IrField>): LLVMTypeRef {
|
private fun ContextUtils.createClassBodyType(name: String, fields: List<IrField>): LLVMTypeRef {
|
||||||
val fieldTypes = fields.map {
|
val fieldTypes = fields.map {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
getLLVMType(if (it.isDelegate) context.builtIns.nullableAnyType else it.type)
|
getLLVMType(if (it.isDelegate) context.irBuiltIns.anyNType else it.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
val classType = LLVMStructCreateNamed(LLVMGetModuleContext(context.llvmModule), name)!!
|
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?) {
|
private fun exportTypeInfoIfRequired(classDesc: ClassDescriptor, typeInfoGlobal: LLVMValueRef?) {
|
||||||
val annot = classDesc.descriptor.annotations.findAnnotation(FqName("konan.ExportTypeInfo"))
|
val annot = classDesc.descriptor.annotations.findAnnotation(FqName("konan.ExportTypeInfo"))
|
||||||
if (annot != null) {
|
if (annot != null) {
|
||||||
val nameValue = annot.allValueArguments.values.single() as StringValue
|
val name = getStringValue(annot)!!
|
||||||
// TODO: use LLVMAddAlias?
|
// 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)
|
LLVMSetInitializer(global, typeInfoGlobal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-3
@@ -18,9 +18,6 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
|
||||||
|
|
||||||
interface RuntimeAware {
|
interface RuntimeAware {
|
||||||
val runtime: Runtime
|
val runtime: Runtime
|
||||||
|
|||||||
-1
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides utilities to create static data.
|
* Provides utilities to create static data.
|
||||||
|
|||||||
-3
@@ -20,7 +20,6 @@ import llvm.LLVMLinkage
|
|||||||
import llvm.LLVMSetLinkage
|
import llvm.LLVMSetLinkage
|
||||||
import llvm.LLVMTypeRef
|
import llvm.LLVMTypeRef
|
||||||
import llvm.LLVMValueRef
|
import llvm.LLVMValueRef
|
||||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.defaultType
|
|
||||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe
|
||||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.llvmSymbolOrigin
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.llvmSymbolOrigin
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
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.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.TypeProjection
|
|
||||||
import org.jetbrains.kotlin.types.replace
|
|
||||||
|
|
||||||
|
|
||||||
private fun StaticData.objHeader(typeInfo: ConstPointer): Struct {
|
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)
|
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 llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.CurrentKonanModule
|
import org.jetbrains.kotlin.backend.konan.descriptors.CurrentKonanModule
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
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`.
|
// TODO: consider also overriding methods of `Any`.
|
||||||
|
|
||||||
val numberOfParameters = invokeMethod.valueParameters.size
|
val numberOfParameters = invokeMethod.valueParameters.size
|
||||||
|
|
||||||
val function = generateFunction(
|
val function = generateFunction(
|
||||||
codegen,
|
codegen,
|
||||||
codegen.getLlvmFunctionType(context.ir.get(invokeMethod)),
|
codegen.getLlvmFunctionType(invokeMethod),
|
||||||
"invokeFunction$numberOfParameters"
|
"invokeFunction$numberOfParameters"
|
||||||
) {
|
) {
|
||||||
val args = (0 until numberOfParameters).map { index -> kotlinReferenceToObjC(param(index + 1)) }
|
val args = (0 until numberOfParameters).map { index -> kotlinReferenceToObjC(param(index + 1)) }
|
||||||
|
|||||||
+1
-1
@@ -380,7 +380,7 @@ private fun ObjCExportCodeGenerator.generateKotlinFunctionAdapterToBlock(numberO
|
|||||||
val invokeMethod = irInterface.declarations.filterIsInstance<IrSimpleFunction>()
|
val invokeMethod = irInterface.declarations.filterIsInstance<IrSimpleFunction>()
|
||||||
.single { it.name == OperatorNameConventions.INVOKE }
|
.single { it.name == OperatorNameConventions.INVOKE }
|
||||||
|
|
||||||
val invokeImpl = generateKotlinFunctionImpl(invokeMethod.descriptor)
|
val invokeImpl = generateKotlinFunctionImpl(invokeMethod)
|
||||||
|
|
||||||
return rttiGenerator.generateSyntheticInterfaceImpl(
|
return rttiGenerator.generateSyntheticInterfaceImpl(
|
||||||
irInterface,
|
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.AbstractValueUsageTransformer
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
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.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.target
|
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.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
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.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
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.
|
* 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) {
|
private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTransformer(
|
||||||
|
context.builtIns,
|
||||||
val symbols = context.ir.symbols
|
context.ir.symbols,
|
||||||
|
context.irBuiltIns
|
||||||
|
) {
|
||||||
|
|
||||||
// TODO: should we handle the cases when expression type
|
// TODO: should we handle the cases when expression type
|
||||||
// is not equal to e.g. called function return 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`)
|
* @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 {
|
ValueType.values().forEach {
|
||||||
if (type.notNullableIsRepresentedAs(it)) {
|
if (type.notNullableIsRepresentedAs(it)) {
|
||||||
return getBoxType(it).makeNullableAsSpecified(TypeUtils.isNullableType(type))
|
return getBoxType(it).makeNullableAsSpecified(type.containsNull())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return type
|
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 ||
|
return if (operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT ||
|
||||||
operator == IrTypeOperator.IMPLICIT_INTEGER_COERCION) {
|
operator == IrTypeOperator.IMPLICIT_INTEGER_COERCION) {
|
||||||
this
|
this
|
||||||
} else {
|
} else {
|
||||||
// Codegen expects the argument of type-checking operator to be an object reference:
|
// 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 newTypeOperand = getRuntimeReferenceType(expression.typeOperand)
|
||||||
|
val newTypeOperandClassifier = newTypeOperand.classifierOrFail
|
||||||
|
|
||||||
return when (expression.operator) {
|
return when (expression.operator) {
|
||||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
|
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
|
||||||
@@ -101,7 +107,7 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
|||||||
}
|
}
|
||||||
|
|
||||||
IrTypeOperatorCallImpl(expression.startOffset, expression.endOffset,
|
IrTypeOperatorCallImpl(expression.startOffset, expression.endOffset,
|
||||||
newExpressionType, expression.operator, newTypeOperand,
|
newExpressionType, expression.operator, newTypeOperand, newTypeOperandClassifier,
|
||||||
expression.argument).useAs(expression.type)
|
expression.argument).useAs(expression.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,40 +116,49 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
|||||||
expression
|
expression
|
||||||
} else {
|
} else {
|
||||||
IrTypeOperatorCallImpl(expression.startOffset, expression.endOffset,
|
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 {
|
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||||
currentFunctionDescriptor = declaration.descriptor
|
currentFunctionDescriptor = declaration
|
||||||
val result = super.visitFunction(declaration)
|
val result = super.visitFunction(declaration)
|
||||||
currentFunctionDescriptor = null
|
currentFunctionDescriptor = null
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun IrExpression.useAsReturnValue(returnTarget: CallableDescriptor): IrExpression {
|
override fun IrExpression.useAsReturnValue(returnTarget: IrReturnTargetSymbol): IrExpression = when (returnTarget) {
|
||||||
if (returnTarget.isSuspend && returnTarget == currentFunctionDescriptor)
|
is IrSimpleFunctionSymbol -> if (returnTarget.owner.isSuspend && returnTarget == currentFunctionDescriptor?.symbol) {
|
||||||
return this.useAs(context.builtIns.nullableAnyType)
|
this.useAs(irBuiltIns.anyNType)
|
||||||
val returnType = returnTarget.returnType
|
} else {
|
||||||
?: return this
|
this.useAs(returnTarget.owner.returnType)
|
||||||
return this.useAs(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
|
val interop = context.interopBuiltIns
|
||||||
if (this.isNullConst() && interop.nullableInteropValueTypes.any { type.isRepresentedAs(it) }) {
|
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) {
|
val actualType = when (this) {
|
||||||
is IrCall -> {
|
is IrCall -> {
|
||||||
if (this.descriptor.isSuspend) context.builtIns.nullableAnyType
|
if (this.symbol.owner.isSuspend) irBuiltIns.anyNType
|
||||||
else this.callTarget.returnType ?: this.type
|
else this.callTarget.returnType
|
||||||
}
|
}
|
||||||
is IrGetField -> this.descriptor.original.type
|
is IrGetField -> this.symbol.owner.type
|
||||||
|
|
||||||
is IrTypeOperatorCall -> when (this.operator) {
|
is IrTypeOperatorCall -> when (this.operator) {
|
||||||
IrTypeOperator.IMPLICIT_INTEGER_COERCION ->
|
IrTypeOperator.IMPLICIT_INTEGER_COERCION ->
|
||||||
@@ -159,65 +174,63 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
|||||||
return this.adaptIfNecessary(actualType, type)
|
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 IrCall -> this.callTarget
|
||||||
is IrDelegatingConstructorCall -> this.descriptor.original
|
is IrDelegatingConstructorCall -> this.symbol.owner
|
||||||
else -> TODO(this.render())
|
else -> TODO(this.render())
|
||||||
}
|
}
|
||||||
|
|
||||||
private val IrCall.callTarget: FunctionDescriptor
|
private val IrCall.callTarget: IrFunction
|
||||||
get() = if (superQualifier == null && descriptor.isOverridable) {
|
get() = if (superQualifier == null && symbol.owner.isOverridable) {
|
||||||
// A virtual call.
|
// A virtual call.
|
||||||
descriptor.original
|
symbol.owner
|
||||||
} else {
|
} 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!!)
|
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!!)
|
return this.useAsArgument(expression.target.extensionReceiverParameter!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun IrExpression.useAsValueArgument(expression: IrMemberAccessExpression,
|
override fun IrExpression.useAsValueArgument(expression: IrFunctionAccessExpression,
|
||||||
parameter: ValueParameterDescriptor): IrExpression {
|
parameter: IrValueParameter): IrExpression {
|
||||||
|
|
||||||
return this.useAsArgument(expression.target.valueParameters[parameter.index])
|
return this.useAsArgument(expression.target.valueParameters[parameter.index])
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun IrExpression.useForField(field: PropertyDescriptor): IrExpression {
|
private fun IrExpression.adaptIfNecessary(actualType: IrType, expectedType: IrType): IrExpression {
|
||||||
return this.useForVariable(field.original)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrExpression.adaptIfNecessary(actualType: KotlinType, expectedType: KotlinType): IrExpression {
|
|
||||||
val conversion = symbols.getTypeConversion(actualType, expectedType)
|
val conversion = symbols.getTypeConversion(actualType, expectedType)
|
||||||
return if (conversion == null) {
|
return if (conversion == null) {
|
||||||
this
|
this
|
||||||
} else {
|
} else {
|
||||||
val parameter = conversion.descriptor.explicitParameters.single()
|
val parameter = conversion.owner.explicitParameters.single()
|
||||||
val argument = this.uncheckedCast(parameter.type)
|
val argument = this.uncheckedCast(parameter.type)
|
||||||
|
|
||||||
IrCallImpl(startOffset, endOffset, conversion).apply {
|
IrCallImpl(startOffset, endOffset, conversion.owner.returnType, conversion).apply {
|
||||||
addArguments(listOf(parameter to argument))
|
addArguments(mapOf(parameter to argument))
|
||||||
}.uncheckedCast(this.type) // Try not to bring new type incompatibilities.
|
}.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.
|
* Casts this expression to `type` without changing its representation in generated code.
|
||||||
*/
|
*/
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@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.
|
// TODO: apply some cast if types are incompatible; not required currently.
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
private val ValueType.shortName
|
private fun getBoxType(valueType: ValueType) = symbols.boxClasses[valueType]!!.owner.defaultType
|
||||||
get() = this.classFqName.shortName()
|
|
||||||
|
|
||||||
private fun getBoxType(valueType: ValueType) =
|
|
||||||
context.getInternalClass("${valueType.shortName}Box").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.common.lower.irIfThen
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
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.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.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.simpleFunctions
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
|
|
||||||
internal class WorkersBridgesBuilding(val context: Context) : DeclarationContainerLoweringPass, IrElementTransformerVoid() {
|
internal class WorkersBridgesBuilding(val context: Context) : DeclarationContainerLoweringPass, IrElementTransformerVoid() {
|
||||||
|
|
||||||
@@ -100,7 +101,16 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
|
|||||||
IrDeclarationOrigin.DEFINED,
|
IrDeclarationOrigin.DEFINED,
|
||||||
runtimeJobDescriptor
|
runtimeJobDescriptor
|
||||||
).also {
|
).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)
|
val overriddenJobDescriptor = OverriddenFunctionDescriptor(jobFunction, runtimeJobFunction)
|
||||||
@@ -118,7 +128,7 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
|
|||||||
type = job.type,
|
type = job.type,
|
||||||
symbol = bridge.symbol,
|
symbol = bridge.symbol,
|
||||||
descriptor = bridge.descriptor,
|
descriptor = bridge.descriptor,
|
||||||
typeArguments = null)
|
typeArgumentsCount = 0)
|
||||||
)
|
)
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
@@ -158,7 +168,7 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
|||||||
|
|
||||||
val irBuilder = context.createIrBuilder(declaration.symbol, declaration.startOffset, declaration.endOffset)
|
val irBuilder = context.createIrBuilder(declaration.symbol, declaration.startOffset, declaration.endOffset)
|
||||||
declaration.body = irBuilder.irBlockBody(declaration) {
|
declaration.body = irBuilder.irBlockBody(declaration) {
|
||||||
buildTypeSafeBarrier(declaration, descriptor, typeSafeBarrierDescription)
|
buildTypeSafeBarrier(declaration, declaration, typeSafeBarrierDescription)
|
||||||
body.statements.forEach { +it }
|
body.statements.forEach { +it }
|
||||||
}
|
}
|
||||||
return declaration
|
return declaration
|
||||||
@@ -187,7 +197,7 @@ internal val IrFunction.bridgeTarget: IrFunction?
|
|||||||
get() = (origin as? DECLARATION_ORIGIN_BRIDGE_METHOD)?.bridgeTarget
|
get() = (origin as? DECLARATION_ORIGIN_BRIDGE_METHOD)?.bridgeTarget
|
||||||
|
|
||||||
private fun IrBuilderWithScope.returnIfBadType(value: IrExpression,
|
private fun IrBuilderWithScope.returnIfBadType(value: IrExpression,
|
||||||
type: KotlinType,
|
type: IrType,
|
||||||
returnValueOnFail: IrExpression)
|
returnValueOnFail: IrExpression)
|
||||||
= irIfThen(irNotIs(value, type), irReturn(returnValueOnFail))
|
= irIfThen(irNotIs(value, type), irReturn(returnValueOnFail))
|
||||||
|
|
||||||
@@ -199,18 +209,18 @@ private fun IrBuilderWithScope.irConst(value: Any?) = when (value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction,
|
private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction,
|
||||||
originalDescriptor: FunctionDescriptor,
|
originalFunction: IrFunction,
|
||||||
typeSafeBarrierDescription: BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription) {
|
typeSafeBarrierDescription: BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription) {
|
||||||
val valueParameters = function.valueParameters
|
val valueParameters = function.valueParameters
|
||||||
val originalValueParameters = originalDescriptor.valueParameters
|
val originalValueParameters = originalFunction.valueParameters
|
||||||
for (i in valueParameters.indices) {
|
for (i in valueParameters.indices) {
|
||||||
if (!typeSafeBarrierDescription.checkParameter(i))
|
if (!typeSafeBarrierDescription.checkParameter(i))
|
||||||
continue
|
continue
|
||||||
val type = originalValueParameters[i].type
|
val type = originalValueParameters[i].type
|
||||||
if (type != context.builtIns.nullableAnyType) {
|
if (!type.isNullableAny()) {
|
||||||
+returnIfBadType(irGet(valueParameters[i].symbol), type,
|
+returnIfBadType(irGet(valueParameters[i]), type,
|
||||||
if (typeSafeBarrierDescription == BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT)
|
if (typeSafeBarrierDescription == BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT)
|
||||||
irGet(valueParameters[2].symbol)
|
irGet(valueParameters[2])
|
||||||
else irConst(typeSafeBarrierDescription.defaultValue)
|
else irConst(typeSafeBarrierDescription.defaultValue)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -221,7 +231,7 @@ private fun Context.buildBridge(startOffset: Int, endOffset: Int,
|
|||||||
descriptor: OverriddenFunctionDescriptor, targetSymbol: IrFunctionSymbol,
|
descriptor: OverriddenFunctionDescriptor, targetSymbol: IrFunctionSymbol,
|
||||||
superQualifierSymbol: IrClassSymbol? = null): IrFunction {
|
superQualifierSymbol: IrClassSymbol? = null): IrFunction {
|
||||||
|
|
||||||
val bridge = specialDeclarationsFactory.getBridgeDescriptor(descriptor)
|
val bridge = specialDeclarationsFactory.getBridge(descriptor)
|
||||||
|
|
||||||
if (bridge.modality == Modality.ABSTRACT) {
|
if (bridge.modality == Modality.ABSTRACT) {
|
||||||
return bridge
|
return bridge
|
||||||
@@ -230,23 +240,28 @@ private fun Context.buildBridge(startOffset: Int, endOffset: Int,
|
|||||||
val irBuilder = createIrBuilder(bridge.symbol, startOffset, endOffset)
|
val irBuilder = createIrBuilder(bridge.symbol, startOffset, endOffset)
|
||||||
bridge.body = irBuilder.irBlockBody(bridge) {
|
bridge.body = irBuilder.irBlockBody(bridge) {
|
||||||
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor.descriptor)
|
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 */
|
superQualifierSymbol = superQualifierSymbol /* Call non-virtually */
|
||||||
).apply {
|
).apply {
|
||||||
bridge.dispatchReceiverParameter?.let {
|
bridge.dispatchReceiverParameter?.let {
|
||||||
dispatchReceiver = irGet(it.symbol)
|
dispatchReceiver = irGet(it)
|
||||||
}
|
}
|
||||||
bridge.extensionReceiverParameter?.let {
|
bridge.extensionReceiverParameter?.let {
|
||||||
extensionReceiver = irGet(it.symbol)
|
extensionReceiver = irGet(it)
|
||||||
}
|
}
|
||||||
bridge.valueParameters.forEachIndexed { index, parameter ->
|
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
|
+delegatingCall
|
||||||
else
|
else
|
||||||
+irReturn(delegatingCall)
|
+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.at
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irNot
|
import org.jetbrains.kotlin.backend.common.lower.irNot
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
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.backend.konan.isValueType
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
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.IrTypeOperatorCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
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.util.isNullConst
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
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.
|
* 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.eqeqeq -> lowerEqeqeq(expression)
|
||||||
|
|
||||||
irBuiltins.throwNpe -> IrCallImpl(expression.startOffset, expression.endOffset,
|
irBuiltins.throwNpe -> IrCallImpl(expression.startOffset, expression.endOffset,
|
||||||
|
context.ir.symbols.ThrowNullPointerException.owner.returnType,
|
||||||
context.ir.symbols.ThrowNullPointerException)
|
context.ir.symbols.ThrowNullPointerException)
|
||||||
|
|
||||||
irBuiltins.noWhenBranchMatchedException -> IrCallImpl(expression.startOffset, expression.endOffset,
|
irBuiltins.noWhenBranchMatchedException -> IrCallImpl(expression.startOffset, expression.endOffset,
|
||||||
|
context.ir.symbols.ThrowNoWhenBranchMatchedException.owner.returnType,
|
||||||
context.ir.symbols.ThrowNoWhenBranchMatchedException)
|
context.ir.symbols.ThrowNoWhenBranchMatchedException)
|
||||||
|
|
||||||
else -> expression
|
else -> expression
|
||||||
@@ -148,8 +152,8 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
|||||||
putValueArgument(0, rhs)
|
putValueArgument(0, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
val lhsIsNotNullable = !lhs.type.isNullable()
|
val lhsIsNotNullable = !lhs.type.containsNull()
|
||||||
val rhsIsNotNullable = !rhs.type.isNullable()
|
val rhsIsNotNullable = !rhs.type.containsNull()
|
||||||
|
|
||||||
return if (expression.descriptor in ieee754EqualsDescriptors()) {
|
return if (expression.descriptor in ieee754EqualsDescriptors()) {
|
||||||
if (lhsIsNotNullable && rhsIsNotNullable)
|
if (lhsIsNotNullable && rhsIsNotNullable)
|
||||||
@@ -159,15 +163,15 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
|||||||
val rhsTemp = irTemporary(rhs)
|
val rhsTemp = irTemporary(rhs)
|
||||||
if (lhsIsNotNullable xor rhsIsNotNullable) { // Exactly one nullable.
|
if (lhsIsNotNullable xor rhsIsNotNullable) { // Exactly one nullable.
|
||||||
+irLogicalAnd(
|
+irLogicalAnd(
|
||||||
irIsNotNull(irGet((if (lhsIsNotNullable) rhsTemp else lhsTemp).symbol)),
|
irIsNotNull(irGet(if (lhsIsNotNullable) rhsTemp else lhsTemp)),
|
||||||
callEquals(irGet(lhsTemp.symbol), irGet(rhsTemp.symbol))
|
callEquals(irGet(lhsTemp), irGet(rhsTemp))
|
||||||
)
|
)
|
||||||
} else { // Both are nullable.
|
} else { // Both are nullable.
|
||||||
+irIfThenElse(builtIns.booleanType, irIsNull(irGet(lhsTemp.symbol)),
|
+irIfThenElse(context.irBuiltIns.booleanType, irIsNull(irGet(lhsTemp)),
|
||||||
irIsNull(irGet(rhsTemp.symbol)),
|
irIsNull(irGet(rhsTemp)),
|
||||||
irLogicalAnd(
|
irLogicalAnd(
|
||||||
irIsNotNull(irGet(rhsTemp.symbol)),
|
irIsNotNull(irGet(rhsTemp)),
|
||||||
callEquals(irGet(lhsTemp.symbol), irGet(rhsTemp.symbol))
|
callEquals(irGet(lhsTemp), irGet(rhsTemp))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -179,12 +183,12 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
|
|||||||
irBlock {
|
irBlock {
|
||||||
val lhsTemp = irTemporary(lhs)
|
val lhsTemp = irTemporary(lhs)
|
||||||
if (rhsIsNotNullable)
|
if (rhsIsNotNullable)
|
||||||
+irLogicalAnd(irIsNotNull(irGet(lhsTemp.symbol)), callEquals(irGet(lhsTemp.symbol), rhs))
|
+irLogicalAnd(irIsNotNull(irGet(lhsTemp)), callEquals(irGet(lhsTemp), rhs))
|
||||||
else {
|
else {
|
||||||
val rhsTemp = irTemporary(rhs)
|
val rhsTemp = irTemporary(rhs)
|
||||||
+irIfThenElse(builtIns.booleanType, irIsNull(irGet(lhsTemp.symbol)),
|
+irIfThenElse(irBuiltins.booleanType, irIsNull(irGet(lhsTemp)),
|
||||||
irIsNull(irGet(rhsTemp.symbol)),
|
irIsNull(irGet(rhsTemp)),
|
||||||
callEquals(irGet(lhsTemp.symbol), irGet(rhsTemp.symbol))
|
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 {
|
from.atMostOne {
|
||||||
val leftParamType = it.owner.valueParameters[0].type
|
val leftParamType = it.owner.valueParameters[0].type
|
||||||
val rightParamType = it.owner.valueParameters[1].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.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
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.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
import org.jetbrains.kotlin.backend.common.pop
|
import org.jetbrains.kotlin.backend.common.pop
|
||||||
import org.jetbrains.kotlin.backend.common.push
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.fqNameSafe
|
import org.jetbrains.kotlin.backend.konan.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.backend.konan.llvm.functionName
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
@@ -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.IrDelegatingConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.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.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
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 {
|
internal class CallableReferenceLowering(val context: Context): FileLoweringPass {
|
||||||
|
|
||||||
@@ -161,15 +160,16 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
val parent: IrDeclarationParent,
|
val parent: IrDeclarationParent,
|
||||||
val functionReference: IrFunctionReference) {
|
val functionReference: IrFunctionReference) {
|
||||||
|
|
||||||
private val functionDescriptor = functionReference.descriptor
|
private val functionDescriptor = functionReference.descriptor.original
|
||||||
private val functionParameters = functionDescriptor.explicitParameters
|
private val irFunction = functionReference.symbol.owner
|
||||||
private val boundFunctionParameters = functionReference.getArguments().map { it.first }
|
private val functionParameters = irFunction.explicitParameters
|
||||||
|
private val boundFunctionParameters = functionReference.getArgumentsWithIr().map { it.first }
|
||||||
private val unboundFunctionParameters = functionParameters - boundFunctionParameters
|
private val unboundFunctionParameters = functionParameters - boundFunctionParameters
|
||||||
|
|
||||||
private lateinit var functionReferenceClassDescriptor: ClassDescriptorImpl
|
private lateinit var functionReferenceClassDescriptor: ClassDescriptorImpl
|
||||||
private lateinit var functionReferenceClass: IrClassImpl
|
private lateinit var functionReferenceClass: IrClassImpl
|
||||||
private lateinit var functionReferenceThis: IrValueParameterSymbol
|
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
|
private val kFunctionImplSymbol = context.ir.symbols.kFunctionImpl
|
||||||
|
|
||||||
@@ -177,29 +177,26 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
val startOffset = functionReference.startOffset
|
val startOffset = functionReference.startOffset
|
||||||
val endOffset = functionReference.endOffset
|
val endOffset = functionReference.endOffset
|
||||||
|
|
||||||
val returnType = functionDescriptor.returnType!!
|
val returnType = irFunction.returnType
|
||||||
val superTypes = mutableListOf(
|
val superTypes = mutableListOf(kFunctionImplSymbol.typeWith(returnType))
|
||||||
kFunctionImplSymbol.owner.defaultType.replace(listOf(returnType))
|
|
||||||
)
|
|
||||||
val superClasses = mutableListOf(kFunctionImplSymbol.owner)
|
|
||||||
|
|
||||||
val numberOfParameters = unboundFunctionParameters.size
|
val numberOfParameters = unboundFunctionParameters.size
|
||||||
val functionClassDescriptor = context.reflectionTypes.getKFunction(numberOfParameters)
|
|
||||||
|
val functionIrClass = context.ir.symbols.kFunctions[numberOfParameters].owner
|
||||||
val functionParameterTypes = unboundFunctionParameters.map { it.type }
|
val functionParameterTypes = unboundFunctionParameters.map { it.type }
|
||||||
val functionClassTypeParameters = functionParameterTypes + returnType
|
val functionClassTypeParameters = functionParameterTypes + returnType
|
||||||
superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeParameters)
|
superTypes += functionIrClass.symbol.typeWith(functionClassTypeParameters)
|
||||||
superClasses += context.ir.symbols.kFunctions[numberOfParameters].owner
|
|
||||||
|
|
||||||
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
var suspendFunctionIrClass: IrClass? = null
|
||||||
var suspendFunctionClassTypeParameters: List<KotlinType>? = null
|
var suspendFunctionClassTypeParameters: List<IrType>? = null
|
||||||
val lastParameterType = unboundFunctionParameters.lastOrNull()?.type
|
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.
|
// If the last parameter is Continuation<> inherit from SuspendFunction.
|
||||||
suspendFunctionClassDescriptor = kotlinPackageScope.getContributedClassifier(
|
suspendFunctionIrClass = context.ir.symbols.suspendFunctions[numberOfParameters - 1].owner
|
||||||
Name.identifier("SuspendFunction${numberOfParameters - 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) +
|
||||||
suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) + lastParameterType.arguments.single().type
|
(lastParameterType.arguments.single().typeOrNull ?: context.irBuiltIns.anyNType)
|
||||||
superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeParameters)
|
superTypes += suspendFunctionIrClass.symbol.typeWith(suspendFunctionClassTypeParameters)
|
||||||
superClasses += context.ir.symbols.suspendFunctions[numberOfParameters - 1].owner
|
|
||||||
}
|
}
|
||||||
|
|
||||||
functionReferenceClassDescriptor = object : ClassDescriptorImpl(
|
functionReferenceClassDescriptor = object : ClassDescriptorImpl(
|
||||||
@@ -207,7 +204,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
/* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName,
|
/* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName,
|
||||||
/* modality = */ Modality.FINAL,
|
/* modality = */ Modality.FINAL,
|
||||||
/* kind = */ ClassKind.CLASS,
|
/* kind = */ ClassKind.CLASS,
|
||||||
/* superTypes = */ superTypes,
|
/* superTypes = */ superTypes.map { it.toKotlinType() },
|
||||||
/* source = */ SourceElement.NO_SOURCE,
|
/* source = */ SourceElement.NO_SOURCE,
|
||||||
/* isExternal = */ false,
|
/* isExternal = */ false,
|
||||||
/* storageManager = */ LockBasedStorageManager.NO_LOCKS
|
/* storageManager = */ LockBasedStorageManager.NO_LOCKS
|
||||||
@@ -225,13 +222,15 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
|
|
||||||
val constructorBuilder = createConstructorBuilder()
|
val constructorBuilder = createConstructorBuilder()
|
||||||
|
|
||||||
val invokeFunctionDescriptor = functionClassDescriptor.getFunction("invoke", functionClassTypeParameters)
|
val invokeFunctionSymbol =
|
||||||
val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionDescriptor)
|
functionIrClass.simpleFunctions().single { it.name.asString() == "invoke" }.symbol
|
||||||
|
val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionSymbol, functionReferenceClass)
|
||||||
|
|
||||||
var suspendInvokeMethodBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>? = null
|
var suspendInvokeMethodBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>? = null
|
||||||
if (suspendFunctionClassDescriptor != null) {
|
if (suspendFunctionIrClass != null) {
|
||||||
val suspendInvokeFunctionDescriptor = suspendFunctionClassDescriptor.getFunction("invoke", suspendFunctionClassTypeParameters!!)
|
val suspendInvokeFunctionSymbol =
|
||||||
suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionDescriptor)
|
suspendFunctionIrClass.simpleFunctions().single { it.name.asString() == "invoke" }.symbol
|
||||||
|
suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionSymbol, functionReferenceClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
val memberScope = stub<MemberScope>("callable reference class")
|
val memberScope = stub<MemberScope>("callable reference class")
|
||||||
@@ -253,7 +252,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
functionReferenceClass.addChild(it.ir)
|
functionReferenceClass.addChild(it.ir)
|
||||||
}
|
}
|
||||||
|
|
||||||
functionReferenceClass.setSuperSymbolsAndAddFakeOverrides(superClasses)
|
functionReferenceClass.setSuperSymbolsAndAddFakeOverrides(superTypes)
|
||||||
|
|
||||||
return BuiltFunctionReference(functionReferenceClass, constructorBuilder.ir)
|
return BuiltFunctionReference(functionReferenceClass, constructorBuilder.ir)
|
||||||
}
|
}
|
||||||
@@ -275,15 +274,19 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
override fun doInitialize() {
|
override fun doInitialize() {
|
||||||
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||||
val constructorParameters = boundFunctionParameters.mapIndexed { index, parameter ->
|
val constructorParameters = boundFunctionParameters.mapIndexed { index, parameter ->
|
||||||
parameter.copyAsValueParameter(descriptor, index)
|
parameter.descriptor.copyAsValueParameter(descriptor, index)
|
||||||
}
|
}
|
||||||
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
||||||
descriptor.returnType = functionReferenceClassDescriptor.defaultType
|
descriptor.returnType = functionReferenceClassDescriptor.defaultType
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun buildIr(): IrConstructor {
|
override fun buildIr(): IrConstructor {
|
||||||
|
|
||||||
|
val symbols = this@CallableReferenceLowering.context.ir.symbols
|
||||||
|
val irBuiltIns = context.irBuiltIns
|
||||||
|
|
||||||
argumentToPropertiesMap = boundFunctionParameters.associate {
|
argumentToPropertiesMap = boundFunctionParameters.associate {
|
||||||
it to buildPropertyWithBackingField(it.name, it.type, false)
|
it.descriptor to buildField(it.name, it.type, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
val startOffset = functionReference.startOffset
|
val startOffset = functionReference.startOffset
|
||||||
@@ -294,30 +297,36 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
symbol = symbol).apply {
|
symbol = symbol).apply {
|
||||||
|
|
||||||
|
returnType = functionReferenceClass.defaultType
|
||||||
|
|
||||||
val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset)
|
||||||
|
|
||||||
createParameterDeclarations()
|
boundFunctionParameters.mapIndexedTo(this.valueParameters) { index, parameter ->
|
||||||
|
parameter.copy(descriptor.valueParameters[index])
|
||||||
|
}
|
||||||
|
|
||||||
body = irBuilder.irBlockBody {
|
body = irBuilder.irBlockBody {
|
||||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||||
kFunctionImplConstructorSymbol, kFunctionImplConstructorSymbol.descriptor).apply {
|
context.irBuiltIns.unitType,
|
||||||
val name = IrConstImpl(startOffset, endOffset, context.builtIns.stringType,
|
kFunctionImplConstructorSymbol, kFunctionImplConstructorSymbol.descriptor, 0).apply {
|
||||||
|
val stringType = irBuiltIns.stringType
|
||||||
|
val name = IrConstImpl(startOffset, endOffset, stringType,
|
||||||
IrConstKind.String, functionDescriptor.name.asString())
|
IrConstKind.String, functionDescriptor.name.asString())
|
||||||
putValueArgument(0, name)
|
putValueArgument(0, name)
|
||||||
val fqName = IrConstImpl(startOffset, endOffset, context.builtIns.stringType, IrConstKind.String,
|
val fqName = IrConstImpl(startOffset, endOffset, stringType, IrConstKind.String,
|
||||||
(functionReference.symbol.owner).fullName)
|
(functionReference.symbol.owner).fullName)
|
||||||
putValueArgument(1, fqName)
|
putValueArgument(1, fqName)
|
||||||
val bound = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType,
|
val bound = IrConstImpl.boolean(startOffset, endOffset, context.irBuiltIns.booleanType,
|
||||||
boundFunctionParameters.isNotEmpty())
|
boundFunctionParameters.isNotEmpty())
|
||||||
putValueArgument(2, bound)
|
putValueArgument(2, bound)
|
||||||
val needReceiver = boundFunctionParameters.singleOrNull() is ReceiverParameterDescriptor
|
val needReceiver = boundFunctionParameters.singleOrNull()?.descriptor is ReceiverParameterDescriptor
|
||||||
val receiver = if (needReceiver) irGet(valueParameters.single().symbol) else irNull()
|
val receiver = if (needReceiver) irGet(valueParameters.single()) else irNull()
|
||||||
putValueArgument(3, receiver)
|
putValueArgument(3, receiver)
|
||||||
}
|
}
|
||||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol)
|
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, irBuiltIns.unitType)
|
||||||
// Save all arguments to fields.
|
// Save all arguments to fields.
|
||||||
boundFunctionParameters.forEachIndexed { index, parameter ->
|
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
|
private val IrFunction.fullName: String
|
||||||
get() = parent.fqNameSafe.child(Name.identifier(functionName)).asString()
|
get() = parent.fqNameSafe.child(Name.identifier(functionName)).asString()
|
||||||
|
|
||||||
private fun createInvokeMethodBuilder(superFunctionDescriptor: FunctionDescriptor)
|
private fun createInvokeMethodBuilder(superFunctionSymbol: IrSimpleFunctionSymbol, parent: IrClass)
|
||||||
= object : SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
= object : SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||||
|
|
||||||
|
val superFunctionDescriptor: FunctionDescriptor = superFunctionSymbol.descriptor
|
||||||
|
|
||||||
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||||
SimpleFunctionDescriptorImpl.create(
|
SimpleFunctionDescriptorImpl.create(
|
||||||
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||||
@@ -368,10 +379,18 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
symbol = ourSymbol).apply {
|
symbol = ourSymbol).apply {
|
||||||
|
|
||||||
|
returnType = superFunctionSymbol.owner.returnType // FIXME: substitute
|
||||||
|
|
||||||
val function = this
|
val function = this
|
||||||
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
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) {
|
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||||
+irReturn(
|
+irReturn(
|
||||||
@@ -383,21 +402,21 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
if (!unboundArgsSet.contains(it))
|
if (!unboundArgsSet.contains(it))
|
||||||
// Bound parameter - read from field.
|
// Bound parameter - read from field.
|
||||||
irGetField(
|
irGetField(
|
||||||
irGet(function.dispatchReceiverParameter!!.symbol),
|
irGet(function.dispatchReceiverParameter!!),
|
||||||
argumentToPropertiesMap[it]!!
|
argumentToPropertiesMap[it.descriptor]!!
|
||||||
)
|
)
|
||||||
else {
|
else {
|
||||||
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
|
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
|
||||||
// For suspend functions the last argument is continuation and it is implicit.
|
// For suspend functions the last argument is continuation and it is implicit.
|
||||||
irCall(getContinuationSymbol,
|
irCall(getContinuationSymbol.owner,
|
||||||
listOf(ourSymbol.descriptor.returnType!!))
|
listOf(returnType))
|
||||||
else
|
else
|
||||||
irGet(valueParameters[unboundIndex++].symbol)
|
irGet(valueParameters[unboundIndex++])
|
||||||
}
|
}
|
||||||
when (it) {
|
when (it) {
|
||||||
functionDescriptor.dispatchReceiverParameter -> dispatchReceiver = argument
|
irFunction.dispatchReceiverParameter -> dispatchReceiver = argument
|
||||||
functionDescriptor.extensionReceiverParameter -> extensionReceiver = argument
|
irFunction.extensionReceiverParameter -> extensionReceiver = argument
|
||||||
else -> putValueArgument((it as ValueParameterDescriptor).index, argument)
|
else -> putValueArgument(it.index, argument)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(unboundIndex == valueParameters.size, { "Not all arguments of <invoke> are used" })
|
assert(unboundIndex == valueParameters.size, { "Not all arguments of <invoke> are used" })
|
||||||
@@ -408,21 +427,17 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildPropertyWithBackingField(name: Name, type: KotlinType, isMutable: Boolean): IrFieldSymbol {
|
private fun buildField(name: Name, type: IrType, isMutable: Boolean): IrField = createField(
|
||||||
val propertyBuilder = context.createPropertyWithBackingFieldBuilder(
|
functionReference.startOffset,
|
||||||
startOffset = functionReference.startOffset,
|
functionReference.endOffset,
|
||||||
endOffset = functionReference.endOffset,
|
type,
|
||||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
name,
|
||||||
owner = functionReferenceClassDescriptor,
|
isMutable,
|
||||||
name = name,
|
DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
type = type,
|
functionReferenceClassDescriptor
|
||||||
isMutable = isMutable).apply {
|
).also {
|
||||||
initialize()
|
functionReferenceClass.addChild(it)
|
||||||
}
|
|
||||||
|
|
||||||
functionReferenceClass.addChild(propertyBuilder.ir)
|
|
||||||
return propertyBuilder.ir.backingField!!.symbol
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+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.IrBuildingTransformer
|
||||||
import org.jetbrains.kotlin.backend.common.lower.at
|
import org.jetbrains.kotlin.backend.common.lower.at
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
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.builders.irCall
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
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.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
|
||||||
@@ -29,14 +30,14 @@ internal class CompileTimeEvaluateLowering(val context: Context): FileLoweringPa
|
|||||||
// TODO: refer functions more reliably.
|
// TODO: refer functions more reliably.
|
||||||
|
|
||||||
if (elementsArr.elements.any { it is IrSpreadElement }
|
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
|
return expression
|
||||||
|
|
||||||
|
|
||||||
builder.at(expression)
|
builder.at(expression)
|
||||||
|
|
||||||
val typeArguments = descriptor.typeParameters.map { expression.getTypeArgument(it)!! }
|
val typeArgument = expression.getTypeArgument(0)!!
|
||||||
return builder.irCall(context.ir.symbols.listOfInternal, typeArguments).apply {
|
return builder.irCall(context.ir.symbols.listOfInternal.owner, listOf(typeArgument)).apply {
|
||||||
putValueArgument(0, elementsArr)
|
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.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
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 {
|
internal class DataClassOperatorsLowering(val context: Context): FunctionLoweringPass {
|
||||||
|
|
||||||
@@ -45,40 +45,37 @@ internal class DataClassOperatorsLowering(val context: Context): FunctionLowerin
|
|||||||
return expression
|
return expression
|
||||||
|
|
||||||
val argument = expression.getValueArgument(0)!!
|
val argument = expression.getValueArgument(0)!!
|
||||||
val argumentType = argument.type.makeNotNullable()
|
val argumentClassifier = argument.type.classifierOrFail
|
||||||
val genericType =
|
|
||||||
if (argumentType.arguments.isEmpty())
|
val isToString = expression.symbol == irBuiltins.dataClassArrayMemberToStringSymbol
|
||||||
argumentType
|
val newCalleeSymbol = if (isToString)
|
||||||
else
|
context.ir.symbols.arrayContentToString[argumentClassifier]!!
|
||||||
(argumentType.constructor.declarationDescriptor as ClassDescriptor).defaultType
|
|
||||||
val isToString = descriptor == irBuiltins.dataClassArrayMemberToString
|
|
||||||
val newSymbol = if (isToString)
|
|
||||||
context.ir.symbols.arrayContentToString[genericType]!!
|
|
||||||
else
|
else
|
||||||
context.ir.symbols.arrayContentHashCode[genericType]!!
|
context.ir.symbols.arrayContentHashCode[argumentClassifier]!!
|
||||||
|
|
||||||
|
val newCallee = newCalleeSymbol.owner
|
||||||
|
|
||||||
val startOffset = expression.startOffset
|
val startOffset = expression.startOffset
|
||||||
val endOffset = expression.endOffset
|
val endOffset = expression.endOffset
|
||||||
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
||||||
|
|
||||||
return irBuilder.run {
|
return irBuilder.run {
|
||||||
val typeArguments =
|
// TODO: use more precise type arguments.
|
||||||
if (argumentType.arguments.isEmpty())
|
val typeArguments = (0 until newCallee.typeParameters.size).map { irBuiltins.anyNType }
|
||||||
emptyList<KotlinType>()
|
|
||||||
else argumentType.arguments.map { it.type }
|
if (!argument.type.isSimpleTypeWithQuestionMark) {
|
||||||
if (!argument.type.isMarkedNullable) {
|
irCall(newCallee, typeArguments).apply {
|
||||||
irCall(newSymbol, typeArguments).apply {
|
|
||||||
extensionReceiver = argument
|
extensionReceiver = argument
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val tmp = scope.createTemporaryVariable(argument)
|
val tmp = scope.createTemporaryVariable(argument)
|
||||||
val call = irCall(newSymbol, typeArguments).apply {
|
val call = irCall(newCallee, typeArguments).apply {
|
||||||
extensionReceiver = irGet(tmp.symbol)
|
extensionReceiver = irGet(tmp)
|
||||||
}
|
}
|
||||||
irBlock(argument) {
|
irBlock(argument) {
|
||||||
+tmp
|
+tmp
|
||||||
+irIfThenElse(call.type,
|
+irIfThenElse(call.type,
|
||||||
irEqeqeq(irGet(tmp.symbol), irNull()),
|
irEqeqeq(irGet(tmp), irNull()),
|
||||||
if (isToString)
|
if (isToString)
|
||||||
irString("null")
|
irString("null")
|
||||||
else
|
else
|
||||||
|
|||||||
+147
-24
@@ -24,14 +24,17 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.*
|
import org.jetbrains.kotlin.descriptors.impl.*
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.createClassSymbolOrNull
|
import org.jetbrains.kotlin.ir.symbols.impl.createClassSymbolOrNull
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol
|
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.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
@@ -46,7 +49,6 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
|
||||||
|
|
||||||
internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor,
|
internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor,
|
||||||
val parentDescriptor: DeclarationDescriptor,
|
val parentDescriptor: DeclarationDescriptor,
|
||||||
@@ -484,7 +486,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
|||||||
return IrCallImpl(
|
return IrCallImpl(
|
||||||
startOffset = expression.startOffset,
|
startOffset = expression.startOffset,
|
||||||
endOffset = expression.endOffset,
|
endOffset = expression.endOffset,
|
||||||
type = newDescriptor.returnType!!,
|
type = context.ir.translateErased(newDescriptor.returnType!!),
|
||||||
descriptor = newDescriptor,
|
descriptor = newDescriptor,
|
||||||
typeArgumentsCount = expression.typeArgumentsCount,
|
typeArgumentsCount = expression.typeArgumentsCount,
|
||||||
origin = expression.origin,
|
origin = expression.origin,
|
||||||
@@ -497,19 +499,100 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
|||||||
|
|
||||||
//---------------------------------------------------------------------//
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction): IrFunction =
|
override fun visitSimpleFunction(declaration: IrSimpleFunction): IrFunction {
|
||||||
IrFunctionImpl(
|
val descriptor = mapFunctionDeclaration(declaration.descriptor)
|
||||||
startOffset = declaration.startOffset,
|
return IrFunctionImpl(
|
||||||
endOffset = declaration.endOffset,
|
startOffset = declaration.startOffset,
|
||||||
origin = mapDeclarationOrigin(declaration.origin),
|
endOffset = declaration.endOffset,
|
||||||
descriptor = mapFunctionDeclaration(declaration.descriptor),
|
origin = mapDeclarationOrigin(declaration.origin),
|
||||||
body = declaration.body?.transform(this, null)
|
descriptor = descriptor
|
||||||
).also {
|
).also {
|
||||||
|
it.returnType = context.ir.translateErased(descriptor.returnType!!)
|
||||||
|
it.body = declaration.body?.transform(this, null)
|
||||||
|
|
||||||
it.setOverrides(context.ir.symbols.symbolTable)
|
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 {
|
private fun <T : IrFunction> T.transformDefaults(original: T): T {
|
||||||
for (originalValueParameter in original.descriptor.valueParameters) {
|
for (originalValueParameter in original.descriptor.valueParameters) {
|
||||||
val valueParameter = descriptor.valueParameters[originalValueParameter.index]
|
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) {
|
return when (operator) {
|
||||||
IrTypeOperator.CAST,
|
IrTypeOperator.CAST,
|
||||||
IrTypeOperator.IMPLICIT_CAST,
|
IrTypeOperator.IMPLICIT_CAST,
|
||||||
@@ -531,22 +614,24 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
|||||||
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type
|
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type
|
||||||
IrTypeOperator.SAFE_CAST -> type.makeNullable()
|
IrTypeOperator.SAFE_CAST -> type.makeNullable()
|
||||||
IrTypeOperator.INSTANCEOF,
|
IrTypeOperator.INSTANCEOF,
|
||||||
IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType
|
IrTypeOperator.NOT_INSTANCEOF -> context.irBuiltIns.booleanType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------//
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrTypeOperatorCall {
|
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrTypeOperatorCall {
|
||||||
val typeOperand = substituteType(expression.typeOperand)!!
|
val erasedTypeOperand = substituteAndEraseType(expression.typeOperand)!!
|
||||||
val returnType = getTypeOperatorReturnType(expression.operator, typeOperand)
|
val typeOperand = substituteAndBreakType(expression.typeOperand)
|
||||||
|
val returnType = getTypeOperatorReturnType(expression.operator, erasedTypeOperand)
|
||||||
return IrTypeOperatorCallImpl(
|
return IrTypeOperatorCallImpl(
|
||||||
startOffset = expression.startOffset,
|
startOffset = expression.startOffset,
|
||||||
endOffset = expression.endOffset,
|
endOffset = expression.endOffset,
|
||||||
type = returnType,
|
type = returnType,
|
||||||
operator = expression.operator,
|
operator = expression.operator,
|
||||||
typeOperand = typeOperand,
|
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(
|
IrReturnImpl(
|
||||||
startOffset = expression.startOffset,
|
startOffset = expression.startOffset,
|
||||||
endOffset = expression.endOffset,
|
endOffset = expression.endOffset,
|
||||||
type = substituteType(expression.type)!!,
|
type = substituteAndEraseType(expression.type)!!,
|
||||||
returnTargetDescriptor = mapReturnTarget(expression.returnTarget),
|
returnTargetDescriptor = mapReturnTarget(expression.returnTarget),
|
||||||
value = expression.value.transform(this, null)
|
value = expression.value.transform(this, null)
|
||||||
)
|
)
|
||||||
@@ -577,7 +662,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
|||||||
} else {
|
} else {
|
||||||
IrBlockImpl(
|
IrBlockImpl(
|
||||||
expression.startOffset, expression.endOffset,
|
expression.startOffset, expression.endOffset,
|
||||||
substituteType(expression.type)!!,
|
substituteAndEraseType(expression.type)!!,
|
||||||
mapStatementOrigin(expression.origin),
|
mapStatementOrigin(expression.origin),
|
||||||
expression.statements.map { it.transform(this, null) }
|
expression.statements.map { it.transform(this, null) }
|
||||||
)
|
)
|
||||||
@@ -587,7 +672,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
override fun visitClassReference(expression: IrClassReference): IrClassReference {
|
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 newDescriptorType = substituteType(expression.descriptor.defaultType)!! // Substituted type of referenced class.
|
||||||
val classDescriptor = newDescriptorType.constructor.declarationDescriptor!! // Get ClassifierDescriptor of the referenced class.
|
val classDescriptor = newDescriptorType.constructor.declarationDescriptor!! // Get ClassifierDescriptor of the referenced class.
|
||||||
return IrClassReferenceImpl(
|
return IrClassReferenceImpl(
|
||||||
@@ -602,7 +687,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
override fun visitGetClass(expression: IrGetClass): IrGetClass {
|
override fun visitGetClass(expression: IrGetClass): IrGetClass {
|
||||||
val type = substituteType(expression.type)!!
|
val type = substituteAndEraseType(expression.type)!!
|
||||||
return IrGetClassImpl(
|
return IrGetClassImpl(
|
||||||
startOffset = expression.startOffset,
|
startOffset = expression.startOffset,
|
||||||
endOffset = expression.endOffset,
|
endOffset = expression.endOffset,
|
||||||
@@ -616,6 +701,27 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
|||||||
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
|
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
|
||||||
return 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
|
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) {
|
private fun IrMemberAccessExpression.substituteTypeArguments(original: IrMemberAccessExpression) {
|
||||||
for (index in 0 until original.typeArgumentsCount) {
|
for (index in 0 until original.typeArgumentsCount) {
|
||||||
val originalTypeArgument = original.getTypeArgument(index)
|
val originalTypeArgument = original.getTypeArgument(index)
|
||||||
val newTypeArgument = substituteType(originalTypeArgument)!!
|
val newTypeArgument = substituteAndBreakType(originalTypeArgument!!)
|
||||||
this.putTypeArgument(index, newTypeArgument)
|
this.putTypeArgument(index, newTypeArgument)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -649,7 +767,10 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
|||||||
|
|
||||||
class SubstitutedDescriptor(val inlinedFunction: FunctionDescriptor, val descriptor: DeclarationDescriptor)
|
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() {
|
: IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
private val variableSubstituteMap = mutableMapOf<VariableDescriptor, VariableDescriptor>()
|
private val variableSubstituteMap = mutableMapOf<VariableDescriptor, VariableDescriptor>()
|
||||||
@@ -710,6 +831,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
|
|||||||
endOffset = declaration.endOffset,
|
endOffset = declaration.endOffset,
|
||||||
origin = declaration.origin,
|
origin = declaration.origin,
|
||||||
descriptor = newDescriptor,
|
descriptor = newDescriptor,
|
||||||
|
type = context.ir.translateErased(newDescriptor.type),
|
||||||
initializer = declaration.initializer
|
initializer = declaration.initializer
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -725,6 +847,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
|
|||||||
return IrGetValueImpl(
|
return IrGetValueImpl(
|
||||||
startOffset = expression.startOffset,
|
startOffset = expression.startOffset,
|
||||||
endOffset = expression.endOffset,
|
endOffset = expression.endOffset,
|
||||||
|
type = context.ir.translateErased(newDescriptor.type),
|
||||||
origin = expression.origin,
|
origin = expression.origin,
|
||||||
symbol = createValueSymbol(newDescriptor)
|
symbol = createValueSymbol(newDescriptor)
|
||||||
)
|
)
|
||||||
@@ -743,7 +866,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
|
|||||||
return IrCallImpl(
|
return IrCallImpl(
|
||||||
startOffset = oldExpression.startOffset,
|
startOffset = oldExpression.startOffset,
|
||||||
endOffset = oldExpression.endOffset,
|
endOffset = oldExpression.endOffset,
|
||||||
type = newDescriptor.returnType!!,
|
type = context.ir.translateErased(newDescriptor.returnType!!),
|
||||||
symbol = createFunctionSymbol(newDescriptor),
|
symbol = createFunctionSymbol(newDescriptor),
|
||||||
descriptor = newDescriptor,
|
descriptor = newDescriptor,
|
||||||
typeArgumentsCount = oldExpression.typeArgumentsCount,
|
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
|
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.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||||
import org.jetbrains.kotlin.backend.jvm.descriptors.initialize
|
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
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.KonanBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||||
@@ -35,15 +33,14 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrLocalDelegatedProperty
|
import org.jetbrains.kotlin.ir.declarations.IrLocalDelegatedProperty
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
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.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrLocalDelegatedPropertyReference
|
import org.jetbrains.kotlin.ir.expressions.IrLocalDelegatedPropertyReference
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.addChild
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.ir.util.functions
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -55,10 +52,10 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
|||||||
private val reflectionTypes = context.reflectionTypes
|
private val reflectionTypes = context.reflectionTypes
|
||||||
private var tempIndex = 0
|
private var tempIndex = 0
|
||||||
|
|
||||||
private fun getKPropertyImplConstructor(receiverTypes: List<KotlinType>,
|
private fun getKPropertyImplConstructor(receiverTypes: List<IrType>,
|
||||||
returnType: KotlinType,
|
returnType: IrType,
|
||||||
isLocal: Boolean,
|
isLocal: Boolean,
|
||||||
isMutable: Boolean) : Pair<IrConstructorSymbol, Map<TypeParameterDescriptor, KotlinType>> {
|
isMutable: Boolean) : Pair<IrConstructorSymbol, List<IrType>> {
|
||||||
|
|
||||||
val symbols = context.ir.symbols
|
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))
|
val arguments = (receiverTypes + listOf(returnType))
|
||||||
.mapIndexed { index, type -> typeParameters[index] to type }
|
|
||||||
.toMap()
|
|
||||||
|
|
||||||
return classSymbol.constructors.single() to arguments
|
return classSymbol.constructors.single() to arguments
|
||||||
}
|
}
|
||||||
@@ -102,17 +96,21 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
|||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
val kProperties = mutableMapOf<VariableDescriptorWithAccessors, Pair<IrExpression, Int>>()
|
val kProperties = mutableMapOf<VariableDescriptorWithAccessors, Pair<IrExpression, Int>>()
|
||||||
|
|
||||||
val arrayClass = context.ir.symbols.array
|
val arrayClass = context.ir.symbols.array.owner
|
||||||
|
|
||||||
val arrayItemGetter = arrayClass.functions.single { it.descriptor.name == Name.identifier("get") }
|
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,
|
val kPropertiesField = IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION,
|
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION,
|
||||||
createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor,
|
createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor,
|
||||||
context.builtIns.array.replace(kPropertyImplType)
|
kPropertiesFieldType.toKotlinType()
|
||||||
)
|
),
|
||||||
|
kPropertiesFieldType
|
||||||
)
|
)
|
||||||
|
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||||
@@ -148,11 +146,9 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
|||||||
createKProperty(expression, this) to kProperties.size
|
createKProperty(expression, this) to kProperties.size
|
||||||
}
|
}
|
||||||
|
|
||||||
return irCall(arrayItemGetter, typeArguments = listOf(kPropertyImplType)).apply {
|
return irCall(arrayItemGetter).apply {
|
||||||
dispatchReceiver =
|
dispatchReceiver = irGetField(null, kPropertiesField)
|
||||||
IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField.symbol)
|
putValueArgument(0, irInt(field.second))
|
||||||
|
|
||||||
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,14 +169,16 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
|||||||
else { // Cache KProperties with no arguments.
|
else { // Cache KProperties with no arguments.
|
||||||
// TODO: what about `receiversCount == 1` case?
|
// TODO: what about `receiversCount == 1` case?
|
||||||
val field = kProperties.getOrPut(propertyDescriptor) {
|
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 {
|
return irCall(arrayItemGetter).apply {
|
||||||
dispatchReceiver =
|
dispatchReceiver = irGetField(null, kPropertiesField)
|
||||||
IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField.symbol)
|
putValueArgument(0, irInt(field.second))
|
||||||
|
|
||||||
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,23 +201,23 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
|||||||
val startOffset = expression.startOffset
|
val startOffset = expression.startOffset
|
||||||
val endOffset = expression.endOffset
|
val endOffset = expression.endOffset
|
||||||
return irBuilder.irBlock(expression) {
|
return irBuilder.irBlock(expression) {
|
||||||
val receiverTypes = mutableListOf<KotlinType>()
|
val receiverTypes = mutableListOf<IrType>()
|
||||||
val dispatchReceiver = expression.dispatchReceiver.let {
|
val dispatchReceiver = expression.dispatchReceiver.let {
|
||||||
if (it == null)
|
if (it == null)
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
irTemporary(value = it, nameHint = "\$dispatchReceiver${tempIndex++}").symbol
|
irTemporary(value = it, nameHint = "\$dispatchReceiver${tempIndex++}")
|
||||||
}
|
}
|
||||||
val extensionReceiver = expression.extensionReceiver.let {
|
val extensionReceiver = expression.extensionReceiver.let {
|
||||||
if (it == null)
|
if (it == null)
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
irTemporary(value = it, nameHint = "\$extensionReceiver${tempIndex++}").symbol
|
irTemporary(value = it, nameHint = "\$extensionReceiver${tempIndex++}")
|
||||||
}
|
}
|
||||||
val propertyDescriptor = expression.descriptor
|
val propertyDescriptor = expression.descriptor
|
||||||
|
val returnType = expression.getter?.owner?.returnType ?: expression.field!!.owner.type
|
||||||
|
|
||||||
val returnType = propertyDescriptor.type
|
val getterCallableReference = expression.getter?.owner?.let { getter ->
|
||||||
val getterCallableReference = propertyDescriptor.getter?.let { getter ->
|
|
||||||
getter.extensionReceiverParameter.let {
|
getter.extensionReceiverParameter.let {
|
||||||
if (it != null && expression.extensionReceiver == null)
|
if (it != null && expression.extensionReceiver == null)
|
||||||
receiverTypes.add(it.type)
|
receiverTypes.add(it.type)
|
||||||
@@ -228,39 +226,37 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
|||||||
if (it != null && expression.dispatchReceiver == null)
|
if (it != null && expression.dispatchReceiver == null)
|
||||||
receiverTypes.add(it.type)
|
receiverTypes.add(it.type)
|
||||||
}
|
}
|
||||||
val getterKFunctionType = reflectionTypes.getKFunctionType(
|
val getterKFunctionType = this@PropertyDelegationLowering.context.ir.symbols.getKFunctionType(
|
||||||
annotations = Annotations.EMPTY,
|
returnType,
|
||||||
receiverType = receiverTypes.firstOrNull(),
|
receiverTypes
|
||||||
parameterTypes = if (receiverTypes.size < 2) listOf() else listOf(receiverTypes[1]),
|
)
|
||||||
returnType = returnType)
|
|
||||||
IrFunctionReferenceImpl(
|
IrFunctionReferenceImpl(
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
type = getterKFunctionType,
|
type = getterKFunctionType,
|
||||||
symbol = expression.getter!!,
|
symbol = expression.getter!!,
|
||||||
descriptor = getter,
|
descriptor = getter.descriptor,
|
||||||
typeArguments = null
|
typeArgumentsCount = 0
|
||||||
).apply {
|
).apply {
|
||||||
this.dispatchReceiver = dispatchReceiver?.let { irGet(it) }
|
this.dispatchReceiver = dispatchReceiver?.let { irGet(it) }
|
||||||
this.extensionReceiver = extensionReceiver?.let { irGet(it) }
|
this.extensionReceiver = extensionReceiver?.let { irGet(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val setterCallableReference = propertyDescriptor.setter?.let {
|
val setterCallableReference = expression.setter?.owner?.let {
|
||||||
if (!isKMutablePropertyType(expression.type)) null
|
if (!isKMutablePropertyType(expression.type.toKotlinType())) null
|
||||||
else {
|
else {
|
||||||
val setterKFunctionType = reflectionTypes.getKFunctionType(
|
val setterKFunctionType = this@PropertyDelegationLowering.context.ir.symbols.getKFunctionType(
|
||||||
annotations = Annotations.EMPTY,
|
context.irBuiltIns.unitType,
|
||||||
receiverType = receiverTypes.firstOrNull(),
|
receiverTypes + returnType
|
||||||
parameterTypes = if (receiverTypes.size < 2) listOf(returnType) else listOf(receiverTypes[1], returnType),
|
)
|
||||||
returnType = context.builtIns.unitType)
|
|
||||||
IrFunctionReferenceImpl(
|
IrFunctionReferenceImpl(
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
type = setterKFunctionType,
|
type = setterKFunctionType,
|
||||||
symbol = expression.setter!!,
|
symbol = expression.setter!!,
|
||||||
descriptor = it,
|
descriptor = it.descriptor,
|
||||||
typeArguments = null
|
typeArgumentsCount = 0
|
||||||
).apply {
|
).apply {
|
||||||
this.dispatchReceiver = dispatchReceiver?.let { irGet(it) }
|
this.dispatchReceiver = dispatchReceiver?.let { irGet(it) }
|
||||||
this.extensionReceiver = extensionReceiver?.let { irGet(it) }
|
this.extensionReceiver = extensionReceiver?.let { irGet(it) }
|
||||||
@@ -273,7 +269,7 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
|||||||
returnType = returnType,
|
returnType = returnType,
|
||||||
isLocal = false,
|
isLocal = false,
|
||||||
isMutable = setterCallableReference != null)
|
isMutable = setterCallableReference != null)
|
||||||
val initializer = irCall(symbol, constructorTypeArguments).apply {
|
val initializer = irCall(symbol.owner, constructorTypeArguments).apply {
|
||||||
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
||||||
if (getterCallableReference != null)
|
if (getterCallableReference != null)
|
||||||
putValueArgument(1, getterCallableReference)
|
putValueArgument(1, getterCallableReference)
|
||||||
@@ -285,16 +281,15 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createLocalKProperty(propertyDescriptor: VariableDescriptorWithAccessors,
|
private fun createLocalKProperty(propertyDescriptor: VariableDescriptorWithAccessors,
|
||||||
|
propertyType: IrType,
|
||||||
irBuilder: IrBuilderWithScope): IrExpression {
|
irBuilder: IrBuilderWithScope): IrExpression {
|
||||||
irBuilder.run {
|
irBuilder.run {
|
||||||
val returnType = propertyDescriptor.type
|
|
||||||
|
|
||||||
val (symbol, constructorTypeArguments) = getKPropertyImplConstructor(
|
val (symbol, constructorTypeArguments) = getKPropertyImplConstructor(
|
||||||
receiverTypes = emptyList(),
|
receiverTypes = emptyList(),
|
||||||
returnType = returnType,
|
returnType = propertyType,
|
||||||
isLocal = true,
|
isLocal = true,
|
||||||
isMutable = false)
|
isMutable = false)
|
||||||
val initializer = irCall(symbol, constructorTypeArguments).apply {
|
val initializer = irCall(symbol.owner, constructorTypeArguments).apply {
|
||||||
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
||||||
}
|
}
|
||||||
return initializer
|
return initializer
|
||||||
@@ -316,10 +311,15 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi
|
|||||||
private object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION :
|
private object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION :
|
||||||
IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION")
|
IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION")
|
||||||
|
|
||||||
private fun createKPropertiesFieldDescriptor(containingDeclaration: DeclarationDescriptor, fieldType: SimpleType): PropertyDescriptorImpl {
|
private fun createKPropertiesFieldDescriptor(containingDeclaration: DeclarationDescriptor, fieldType: KotlinType): PropertyDescriptorImpl {
|
||||||
return PropertyDescriptorImpl.create(containingDeclaration, Annotations.EMPTY, Modality.FINAL, Visibilities.PRIVATE,
|
return PropertyDescriptorImpl.create(containingDeclaration, Annotations.EMPTY, Modality.FINAL, Visibilities.PRIVATE,
|
||||||
false, "KPROPERTIES".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE,
|
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.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
|
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
|
||||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||||
import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter
|
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM
|
import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor
|
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.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
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.*
|
||||||
|
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.ClassConstructorDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
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.declarations.impl.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
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.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.types.*
|
|
||||||
|
|
||||||
|
|
||||||
internal class EnumSyntheticFunctionsBuilder(val context: Context) {
|
internal class EnumSyntheticFunctionsBuilder(val context: Context) {
|
||||||
fun buildValuesExpression(startOffset: Int, endOffset: Int,
|
fun buildValuesExpression(startOffset: Int, endOffset: Int,
|
||||||
enumClassDescriptor: ClassDescriptor): IrExpression {
|
enumClass: IrClass): IrExpression {
|
||||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
|
|
||||||
|
|
||||||
val typeParameterT = genericValuesDescriptor.typeParameters[0]
|
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass)
|
||||||
val enumClassType = enumClassDescriptor.defaultType
|
|
||||||
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType)))
|
|
||||||
val substitutedValueOf = genericValuesDescriptor.substitute(typeSubstitutor)!!
|
|
||||||
|
|
||||||
return IrCallImpl(startOffset, endOffset,
|
return irCall(startOffset, endOffset, genericValuesSymbol.owner, listOf(enumClass.defaultType))
|
||||||
genericValuesSymbol, substitutedValueOf, mapOf(typeParameterT to enumClassType))
|
|
||||||
.apply {
|
.apply {
|
||||||
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
||||||
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
loweredEnum.implObject.defaultType,
|
||||||
putValueArgument(0, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver))
|
loweredEnum.implObject.symbol)
|
||||||
|
putValueArgument(0, IrGetFieldImpl(
|
||||||
|
startOffset,
|
||||||
|
endOffset,
|
||||||
|
loweredEnum.valuesField.symbol,
|
||||||
|
loweredEnum.valuesField.type,
|
||||||
|
receiver
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildValueOfExpression(startOffset: Int, endOffset: Int,
|
fun buildValueOfExpression(startOffset: Int, endOffset: Int,
|
||||||
enumClassDescriptor: ClassDescriptor,
|
enumClass: IrClass,
|
||||||
value: IrExpression): IrExpression {
|
value: IrExpression): IrExpression {
|
||||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
|
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass)
|
||||||
|
|
||||||
val typeParameterT = genericValueOfDescriptor.typeParameters[0]
|
return irCall(startOffset, endOffset, genericValueOfSymbol.owner, listOf(enumClass.defaultType))
|
||||||
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))
|
|
||||||
.apply {
|
.apply {
|
||||||
putValueArgument(0, value)
|
putValueArgument(0, value)
|
||||||
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
||||||
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
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 genericValueOfSymbol = context.ir.symbols.valueOfForEnum
|
||||||
private val genericValueOfDescriptor = genericValueOfSymbol.descriptor
|
|
||||||
|
|
||||||
private val genericValuesSymbol = context.ir.symbols.valuesForEnum
|
private val genericValuesSymbol = context.ir.symbols.valuesForEnum
|
||||||
private val genericValuesDescriptor = genericValuesSymbol.descriptor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class EnumUsageLowering(val context: Context)
|
internal class EnumUsageLowering(val context: Context)
|
||||||
@@ -105,16 +107,13 @@ internal class EnumUsageLowering(val context: Context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression {
|
override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression {
|
||||||
val enumClassDescriptor = expression.descriptor.containingDeclaration as ClassDescriptor
|
val entry = expression.symbol.owner
|
||||||
return loadEnumEntry(expression.startOffset, expression.endOffset, enumClassDescriptor, expression.descriptor.name)
|
return loadEnumEntry(
|
||||||
}
|
expression.startOffset,
|
||||||
|
expression.endOffset,
|
||||||
// TODO: remove as soon IR is fixed (there should no be any enum get with GET_OBJECT operation).
|
entry.parentAsClass,
|
||||||
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
entry.name
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
@@ -125,18 +124,20 @@ internal class EnumUsageLowering(val context: Context)
|
|||||||
if (descriptor.original != enumValuesDescriptor && descriptor.original != enumValueOfDescriptor)
|
if (descriptor.original != enumValuesDescriptor && descriptor.original != enumValueOfDescriptor)
|
||||||
return expression
|
return expression
|
||||||
|
|
||||||
val genericT = descriptor.original.typeParameters[0]
|
val irClassSymbol = expression.getTypeArgument(0)!!.classifierOrNull as? IrClassSymbol
|
||||||
val substitutedT = expression.getTypeArgument(genericT)!!
|
|
||||||
val classDescriptor = substitutedT.constructor.declarationDescriptor as? ClassDescriptor
|
|
||||||
?: return expression // Type parameter.
|
?: 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) {
|
return if (descriptor.original == enumValuesDescriptor) {
|
||||||
enumSyntheticFunctionsBuilder.buildValuesExpression(expression.startOffset, expression.endOffset, classDescriptor)
|
enumSyntheticFunctionsBuilder.buildValuesExpression(expression.startOffset, expression.endOffset, irClass)
|
||||||
} else {
|
} else {
|
||||||
val value = expression.getValueArgument(0)!!
|
val value = expression.getValueArgument(0)!!
|
||||||
enumSyntheticFunctionsBuilder.buildValueOfExpression(expression.startOffset, expression.endOffset, 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 enumValuesSymbol = context.ir.symbols.enumValues
|
||||||
private val enumValuesDescriptor = enumValuesSymbol.descriptor
|
private val enumValuesDescriptor = enumValuesSymbol.descriptor
|
||||||
|
|
||||||
private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClassDescriptor: ClassDescriptor, name: Name): IrExpression {
|
private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClass: IrClass, name: Name): IrExpression {
|
||||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
|
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass)
|
||||||
val ordinal = loweredEnum.entriesMap[name]!!
|
val ordinal = loweredEnum.entriesMap[name]!!
|
||||||
return IrCallImpl(startOffset, endOffset, loweredEnum.itemGetterSymbol, loweredEnum.itemGetterDescriptor).apply {
|
return irCall(startOffset, endOffset, loweredEnum.itemGetterSymbol.owner, emptyList()).apply {
|
||||||
dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol)
|
dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter.returnType, loweredEnum.valuesGetter.symbol)
|
||||||
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, enumClassDescriptor.module.builtIns.intType, ordinal))
|
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 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 loweredEnumConstructors = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
||||||
private val descriptorToIrConstructorWithDefaultArguments = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
private val descriptorToIrConstructorWithDefaultArguments = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
||||||
private val defaultEnumEntryConstructors = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
private val defaultEnumEntryConstructors = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
||||||
@@ -212,7 +213,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
blockBody.statements.transformFlat {
|
blockBody.statements.transformFlat {
|
||||||
if (it is IrEnumConstructorCall)
|
if (it is IrEnumConstructorCall)
|
||||||
listOf(it, IrInstanceInitializerCallImpl(declaration.startOffset, declaration.startOffset,
|
listOf(it, IrInstanceInitializerCallImpl(declaration.startOffset, declaration.startOffset,
|
||||||
irClass.symbol))
|
irClass.symbol, context.irBuiltIns.unitType))
|
||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,17 +246,22 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
val defaultClassDescriptor = ClassDescriptorImpl(descriptor, "DEFAULT".synthesizedName, Modality.FINAL,
|
val defaultClassDescriptor = ClassDescriptorImpl(descriptor, "DEFAULT".synthesizedName, Modality.FINAL,
|
||||||
ClassKind.CLASS, listOf(descriptor.defaultType), SourceElement.NO_SOURCE, false, LockBasedStorageManager.NO_LOCKS)
|
ClassKind.CLASS, listOf(descriptor.defaultType), SourceElement.NO_SOURCE, false, LockBasedStorageManager.NO_LOCKS)
|
||||||
val defaultClass = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, defaultClassDescriptor)
|
val defaultClass = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, defaultClassDescriptor)
|
||||||
|
defaultClass.createParameterDeclarations()
|
||||||
|
|
||||||
|
|
||||||
val constructors = mutableSetOf<ClassConstructorDescriptor>()
|
val constructors = mutableSetOf<ClassConstructorDescriptor>()
|
||||||
|
|
||||||
descriptor.constructors.forEach {
|
descriptor.constructors.forEach {
|
||||||
val loweredEnumConstructorSymbol = loweredEnumConstructors[it]!!.symbol
|
val loweredEnumIrConstructor = loweredEnumConstructors[it]!!
|
||||||
val loweredEnumConstructor = loweredEnumConstructorSymbol.descriptor
|
val loweredEnumConstructor = loweredEnumIrConstructor.descriptor
|
||||||
val constructorDescriptor = defaultClassDescriptor.createSimpleDelegatingConstructorDescriptor(loweredEnumConstructor)
|
|
||||||
val constructor = defaultClass.addSimpleDelegatingConstructor(
|
val constructor = defaultClass.addSimpleDelegatingConstructor(
|
||||||
loweredEnumConstructorSymbol, constructorDescriptor,
|
loweredEnumIrConstructor,
|
||||||
DECLARATION_ORIGIN_ENUM)
|
context.irBuiltIns,
|
||||||
|
DECLARATION_ORIGIN_ENUM
|
||||||
|
)
|
||||||
|
|
||||||
|
val constructorDescriptor = constructor.descriptor
|
||||||
constructors.add(constructorDescriptor)
|
constructors.add(constructorDescriptor)
|
||||||
defaultEnumEntryConstructors.put(loweredEnumConstructor, constructor)
|
defaultEnumEntryConstructors.put(loweredEnumConstructor, constructor)
|
||||||
|
|
||||||
@@ -273,8 +279,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
val memberScope = stub<MemberScope>("enum default class")
|
val memberScope = stub<MemberScope>("enum default class")
|
||||||
defaultClassDescriptor.initialize(memberScope, constructors, null)
|
defaultClassDescriptor.initialize(memberScope, constructors, null)
|
||||||
|
|
||||||
defaultClass.createParameterDeclarations()
|
defaultClass.setSuperSymbolsAndAddFakeOverrides(listOf(irClass.defaultType))
|
||||||
defaultClass.setSuperSymbolsAndAddFakeOverrides(listOf(irClass))
|
|
||||||
|
|
||||||
return defaultClass
|
return defaultClass
|
||||||
}
|
}
|
||||||
@@ -310,12 +315,6 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
++i
|
++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(createSyntheticValuesPropertyDeclaration(enumEntries))
|
||||||
implObject.addChild(createValuesPropertyInitializer(enumEntries))
|
implObject.addChild(createValuesPropertyInitializer(enumEntries))
|
||||||
|
|
||||||
@@ -329,17 +328,19 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
val startOffset = irClass.startOffset
|
val startOffset = irClass.startOffset
|
||||||
val endOffset = irClass.endOffset
|
val endOffset = irClass.endOffset
|
||||||
|
|
||||||
val irValuesInitializer = context.createArrayOfExpression(irClass.descriptor.defaultType,
|
val irValuesInitializer = context.createArrayOfExpression(irClass.defaultType,
|
||||||
enumEntries
|
enumEntries
|
||||||
.sortedBy { it.descriptor.name }
|
.sortedBy { it.descriptor.name }
|
||||||
.map {
|
.map {
|
||||||
val enumEntryClass = ((it.initializerExpression!! as IrCall).descriptor as ConstructorDescriptor).constructedClass
|
val entryConstructorCall = it.initializerExpression!! as IrCall
|
||||||
val typeParameterT = genericCreateUninitializedInstanceDescriptor.typeParameters[0]
|
val entryConstructor = entryConstructorCall.symbol.owner as IrConstructor
|
||||||
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumEntryClass.defaultType)))
|
val entryClass = entryConstructor.constructedClass
|
||||||
val substitutedCreateUninitializedInstance = genericCreateUninitializedInstanceDescriptor.substitute(typeSubstitutor)!!
|
|
||||||
IrCallImpl(startOffset, endOffset,
|
irCall(startOffset, endOffset,
|
||||||
genericCreateUninitializedInstanceSymbol, substitutedCreateUninitializedInstance, mapOf(typeParameterT to enumEntryClass.defaultType)
|
genericCreateUninitializedInstanceSymbol.owner,
|
||||||
|
listOf(entryClass.defaultType)
|
||||||
)
|
)
|
||||||
|
|
||||||
}, startOffset, endOffset)
|
}, startOffset, endOffset)
|
||||||
val irField = loweredEnum.valuesField.apply {
|
val irField = loweredEnum.valuesField.apply {
|
||||||
initializer = IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer)
|
initializer = IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer)
|
||||||
@@ -349,8 +350,20 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
|
|
||||||
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
||||||
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
||||||
val value = IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver)
|
val value = IrGetFieldImpl(
|
||||||
val returnStatement = IrReturnImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol, value)
|
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))
|
getter.body = IrBlockBodyImpl(startOffset, endOffset, listOf(returnStatement))
|
||||||
|
|
||||||
return IrPropertyImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM,
|
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 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 {
|
private fun createValuesPropertyInitializer(enumEntries: List<IrEnumEntry>): IrAnonymousInitializerImpl {
|
||||||
val startOffset = irClass.startOffset
|
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 {
|
return IrAnonymousInitializerImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, loweredEnum.implObject.descriptor).apply {
|
||||||
body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody(irClass) {
|
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
|
enumEntries
|
||||||
.sortedBy { it.descriptor.name }
|
.sortedBy { it.descriptor.name }
|
||||||
.withIndex()
|
.withIndex()
|
||||||
.forEach {
|
.forEach {
|
||||||
val instance = irCall(arrayGetSymbol).apply {
|
val instance = irCall(arrayGetSymbol).apply {
|
||||||
dispatchReceiver = irGet(instances.symbol)
|
dispatchReceiver = irGet(instances)
|
||||||
putValueArgument(0, irInt(it.index))
|
putValueArgument(0, irInt(it.index))
|
||||||
}
|
}
|
||||||
val initializer = it.value.initializerExpression!! as IrCall
|
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 {
|
+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 {
|
private fun createSyntheticValuesMethodBody(declaration: IrFunction): IrBody {
|
||||||
val startOffset = irClass.startOffset
|
val startOffset = irClass.startOffset
|
||||||
val endOffset = irClass.endOffset
|
val endOffset = irClass.endOffset
|
||||||
val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass.descriptor)
|
val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass)
|
||||||
|
|
||||||
return IrBlockBodyImpl(startOffset, endOffset,
|
return IrBlockBodyImpl(startOffset, endOffset).apply {
|
||||||
listOf(IrReturnImpl(startOffset, endOffset, declaration.symbol, valuesExpression))
|
statements += IrReturnImpl(
|
||||||
)
|
startOffset,
|
||||||
|
endOffset,
|
||||||
|
context.irBuiltIns.nothingType,
|
||||||
|
declaration.symbol,
|
||||||
|
valuesExpression
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSyntheticValueOfMethodBody(declaration: IrFunction): IrBody {
|
private fun createSyntheticValueOfMethodBody(declaration: IrFunction): IrBody {
|
||||||
val startOffset = irClass.startOffset
|
val startOffset = irClass.startOffset
|
||||||
val endOffset = irClass.endOffset
|
val endOffset = irClass.endOffset
|
||||||
val value = IrGetValueImpl(startOffset, endOffset, declaration.valueParameters[0].symbol)
|
val parameter = declaration.valueParameters[0]
|
||||||
val valueOfExpression = enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass.descriptor, value)
|
val value = IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol)
|
||||||
|
val valueOfExpression = enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass, value)
|
||||||
|
|
||||||
return IrBlockBodyImpl(
|
return IrBlockBodyImpl(startOffset, endOffset).apply {
|
||||||
startOffset, endOffset,
|
statements += IrReturnImpl(
|
||||||
listOf(IrReturnImpl(startOffset, endOffset, declaration.symbol, valueOfExpression))
|
startOffset,
|
||||||
)
|
endOffset,
|
||||||
|
context.irBuiltIns.nothingType,
|
||||||
|
declaration.symbol,
|
||||||
|
valueOfExpression
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lowerEnumConstructors(irClass: IrClass) {
|
private fun lowerEnumConstructors(irClass: IrClass) {
|
||||||
@@ -423,18 +448,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun transformEnumConstructor(enumConstructor: IrConstructor): IrConstructor {
|
private fun transformEnumConstructor(enumConstructor: IrConstructor): IrConstructor {
|
||||||
val constructorDescriptor = enumConstructor.descriptor
|
val loweredEnumConstructor = lowerEnumConstructor(enumConstructor)
|
||||||
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()
|
|
||||||
|
|
||||||
enumConstructor.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach {
|
enumConstructor.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach {
|
||||||
val body = enumConstructor.getDefault(it)!!
|
val body = enumConstructor.getDefault(it)!!
|
||||||
@@ -443,54 +457,75 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
val descriptor = expression.descriptor
|
val descriptor = expression.descriptor
|
||||||
when (descriptor) {
|
when (descriptor) {
|
||||||
is ValueParameterDescriptor -> {
|
is ValueParameterDescriptor -> {
|
||||||
|
val parameter = loweredEnumConstructor.valueParameters[descriptor.loweredIndex()]
|
||||||
return IrGetValueImpl(expression.startOffset,
|
return IrGetValueImpl(expression.startOffset,
|
||||||
expression.endOffset,
|
expression.endOffset,
|
||||||
loweredEnumConstructor.valueParameters[descriptor.loweredIndex()].symbol)
|
parameter.type,
|
||||||
|
parameter.symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
loweredEnumConstructor.putDefault(loweredConstructorDescriptor.valueParameters[it.loweredIndex()], body)
|
loweredEnumConstructor.valueParameters[it.loweredIndex()].defaultValue = body
|
||||||
descriptorToIrConstructorWithDefaultArguments[loweredConstructorDescriptor] = loweredEnumConstructor
|
descriptorToIrConstructorWithDefaultArguments[loweredEnumConstructor.descriptor] = loweredEnumConstructor
|
||||||
}
|
}
|
||||||
return loweredEnumConstructor
|
return loweredEnumConstructor
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lowerEnumConstructor(constructorDescriptor: ClassConstructorDescriptor): ClassConstructorDescriptor {
|
private fun lowerEnumConstructor(enumConstructor: IrConstructor): IrConstructorImpl {
|
||||||
val loweredConstructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
|
val loweredConstructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
|
||||||
constructorDescriptor.containingDeclaration,
|
enumConstructor.descriptor.containingDeclaration,
|
||||||
constructorDescriptor.annotations,
|
enumConstructor.descriptor.annotations,
|
||||||
constructorDescriptor.isPrimary,
|
enumConstructor.descriptor.isPrimary,
|
||||||
constructorDescriptor.source
|
enumConstructor.descriptor.source
|
||||||
)
|
)
|
||||||
|
|
||||||
val valueParameters =
|
val valueParameters =
|
||||||
listOf(
|
listOf(
|
||||||
loweredConstructorDescriptor.createValueParameter(0, "name", context.builtIns.stringType),
|
loweredConstructorDescriptor.createValueParameter(
|
||||||
loweredConstructorDescriptor.createValueParameter(1, "ordinal", context.builtIns.intType)
|
0,
|
||||||
|
"name",
|
||||||
|
context.irBuiltIns.stringType,
|
||||||
|
enumConstructor.startOffset,
|
||||||
|
enumConstructor.endOffset
|
||||||
|
),
|
||||||
|
loweredConstructorDescriptor.createValueParameter(
|
||||||
|
1,
|
||||||
|
"ordinal",
|
||||||
|
context.irBuiltIns.intType,
|
||||||
|
enumConstructor.startOffset,
|
||||||
|
enumConstructor.endOffset
|
||||||
|
)
|
||||||
) +
|
) +
|
||||||
constructorDescriptor.valueParameters.map {
|
enumConstructor.valueParameters.map {
|
||||||
lowerConstructorValueParameter(loweredConstructorDescriptor, it)
|
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
|
loweredConstructorDescriptor.initialize(
|
||||||
|
valueParameters.map { it.descriptor as ValueParameterDescriptor },
|
||||||
return loweredConstructorDescriptor
|
Visibilities.PROTECTED
|
||||||
}
|
|
||||||
|
|
||||||
private fun lowerConstructorValueParameter(
|
|
||||||
loweredConstructorDescriptor: ClassConstructorDescriptor,
|
|
||||||
valueParameterDescriptor: ValueParameterDescriptor
|
|
||||||
): ValueParameterDescriptor {
|
|
||||||
val loweredValueParameterDescriptor = valueParameterDescriptor.copy(
|
|
||||||
loweredConstructorDescriptor,
|
|
||||||
valueParameterDescriptor.name,
|
|
||||||
valueParameterDescriptor.loweredIndex()
|
|
||||||
)
|
)
|
||||||
loweredEnumConstructorParameters[valueParameterDescriptor] = loweredValueParameterDescriptor
|
loweredConstructorDescriptor.returnType = enumConstructor.descriptor.returnType
|
||||||
return loweredValueParameterDescriptor
|
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() {
|
private fun lowerEnumClassBody() {
|
||||||
@@ -505,7 +540,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
val origin = enumConstructorCall.origin
|
val origin = enumConstructorCall.origin
|
||||||
|
|
||||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||||
enumConstructorCall.symbol, enumConstructorCall.descriptor)
|
context.irBuiltIns.unitType,
|
||||||
|
enumConstructorCall.symbol, enumConstructorCall.descriptor, enumConstructorCall.typeArgumentsCount)
|
||||||
|
|
||||||
assert(result.descriptor.valueParameters.size == 2) {
|
assert(result.descriptor.valueParameters.size == 2) {
|
||||||
"Enum(String, Int) constructor call expected:\n${result.dump()}"
|
"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")
|
throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor")
|
||||||
}
|
}
|
||||||
|
|
||||||
result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, nameParameter.symbol, origin))
|
result.putValueArgument(0,
|
||||||
result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, ordinalParameter.symbol, origin))
|
IrGetValueImpl(startOffset, endOffset, nameParameter.type, nameParameter.symbol, origin)
|
||||||
|
)
|
||||||
|
result.putValueArgument(1,
|
||||||
|
IrGetValueImpl(startOffset, endOffset, ordinalParameter.type, ordinalParameter.symbol, origin)
|
||||||
|
)
|
||||||
|
|
||||||
return result
|
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")
|
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor")
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType,
|
||||||
loweredDelegatedConstructor.symbol, loweredDelegatedConstructor.descriptor)
|
loweredDelegatedConstructor.symbol, loweredDelegatedConstructor.descriptor, 0)
|
||||||
|
|
||||||
|
val firstParameter = enumClassConstructor.valueParameters[0]
|
||||||
result.putValueArgument(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,
|
result.putValueArgument(1,
|
||||||
IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[1].symbol))
|
IrGetValueImpl(startOffset, endOffset, secondParameter.type, secondParameter.symbol))
|
||||||
|
|
||||||
descriptor.valueParameters.forEach { valueParameter ->
|
descriptor.valueParameters.forEach { valueParameter ->
|
||||||
result.putValueArgument(valueParameter.loweredIndex(), delegatingConstructorCall.getValueArgument(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)
|
val result = createConstructorCall(startOffset, endOffset, loweredConstructor.symbol)
|
||||||
|
|
||||||
result.putValueArgument(0, IrConstImpl.string(startOffset, endOffset, context.builtIns.stringType, name))
|
result.putValueArgument(0,
|
||||||
result.putValueArgument(1, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, ordinal))
|
IrConstImpl.string(startOffset, endOffset, context.irBuiltIns.stringType, name))
|
||||||
|
result.putValueArgument(1,
|
||||||
|
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal))
|
||||||
|
|
||||||
descriptor.valueParameters.forEach { valueParameter ->
|
descriptor.valueParameters.forEach { valueParameter ->
|
||||||
val i = valueParameter.index
|
val i = valueParameter.index
|
||||||
@@ -584,14 +628,25 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private inner class InEnumEntryClassConstructor(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
private inner class InEnumEntryClassConstructor(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
||||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol)
|
override fun createConstructorCall(
|
||||||
= IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor, loweredConstructor.descriptor)
|
startOffset: Int,
|
||||||
|
endOffset: Int,
|
||||||
|
loweredConstructor: IrConstructorSymbol
|
||||||
|
) = IrDelegatingConstructorCallImpl(
|
||||||
|
startOffset,
|
||||||
|
endOffset,
|
||||||
|
context.irBuiltIns.unitType,
|
||||||
|
loweredConstructor,
|
||||||
|
loweredConstructor.descriptor,
|
||||||
|
0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
||||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrCall {
|
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrCall {
|
||||||
return IrCallImpl(startOffset, endOffset,
|
val irConstructorSymbol = defaultEnumEntryConstructors[loweredConstructor.descriptor]?.symbol
|
||||||
defaultEnumEntryConstructors[loweredConstructor.descriptor]?.symbol ?: loweredConstructor)
|
?: 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 loweredEnumConstructor = loweredEnumConstructors[expression.descriptor.containingDeclaration]!!
|
||||||
val loweredIrParameter = loweredEnumConstructor.valueParameters[loweredParameter.index]
|
val loweredIrParameter = loweredEnumConstructor.valueParameters[loweredParameter.index]
|
||||||
assert(loweredIrParameter.descriptor == loweredParameter)
|
assert(loweredIrParameter.descriptor == loweredParameter)
|
||||||
return IrGetValueImpl(expression.startOffset, expression.endOffset,
|
return IrGetValueImpl(expression.startOffset, expression.endOffset, loweredIrParameter.type,
|
||||||
loweredIrParameter.symbol, expression.origin)
|
loweredIrParameter.symbol, expression.origin)
|
||||||
} else {
|
} else {
|
||||||
return expression
|
return expression
|
||||||
@@ -685,9 +740,11 @@ private class ParameterMapper(val originalConstructor: IrConstructor) : IrElemen
|
|||||||
val descriptor = expression.descriptor
|
val descriptor = expression.descriptor
|
||||||
when (descriptor) {
|
when (descriptor) {
|
||||||
is ValueParameterDescriptor -> {
|
is ValueParameterDescriptor -> {
|
||||||
|
val parameter = originalConstructor.valueParameters[descriptor.index]
|
||||||
return IrGetValueImpl(expression.startOffset,
|
return IrGetValueImpl(expression.startOffset,
|
||||||
expression.endOffset,
|
expression.endOffset,
|
||||||
originalConstructor.valueParameters[descriptor.index].symbol)
|
parameter.type,
|
||||||
|
parameter.symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return expression
|
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.pop
|
||||||
import org.jetbrains.kotlin.backend.common.push
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.containsNull
|
||||||
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.getClass
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
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.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
import org.jetbrains.kotlin.ir.util.getArguments
|
||||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
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
|
val subject = irBlock.statements[0] as IrVariable
|
||||||
// Subject should not be nullable because we will access the `ordinal` property.
|
// Subject should not be nullable because we will access the `ordinal` property.
|
||||||
if (subject.type.isNullable()) {
|
if (subject.type.containsNull()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Check that subject is enum entry.
|
// Check that subject is enum entry.
|
||||||
val enumClass = subject.type.constructor.declarationDescriptor as? ClassDescriptor
|
val enumClass = subject.type.getClass()
|
||||||
?: return false
|
?: return false
|
||||||
return enumClass.kind == ClassKind.ENUM_CLASS
|
return enumClass.kind == ClassKind.ENUM_CLASS
|
||||||
}
|
}
|
||||||
@@ -83,14 +86,22 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo
|
|||||||
|
|
||||||
private fun createEnumOrdinalVariable(enumVariable: IrVariable): IrVariable {
|
private fun createEnumOrdinalVariable(enumVariable: IrVariable): IrVariable {
|
||||||
val ordinalPropertyGetter = context.ir.symbols.enum.getPropertyGetter("ordinal")!!
|
val ordinalPropertyGetter = context.ir.symbols.enum.getPropertyGetter("ordinal")!!
|
||||||
val getOrdinal = IrCallImpl(enumVariable.startOffset, enumVariable.endOffset, ordinalPropertyGetter).apply {
|
val getOrdinal = IrCallImpl(
|
||||||
dispatchReceiver = IrGetValueImpl(enumVariable.startOffset, enumVariable.endOffset, enumVariable.symbol)
|
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.
|
// Create temporary variable for subject's ordinal.
|
||||||
val ordinalDescriptor = IrTemporaryVariableDescriptorImpl(enumVariable.descriptor.containingDeclaration,
|
val ordinalDescriptor = IrTemporaryVariableDescriptorImpl(enumVariable.descriptor.containingDeclaration,
|
||||||
Name.identifier(enumVariable.name.asString() + "_ordinal"), context.builtIns.intType)
|
Name.identifier(enumVariable.name.asString() + "_ordinal"), context.builtIns.intType)
|
||||||
return IrVariableImpl(enumVariable.startOffset, enumVariable.endOffset,
|
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 {
|
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 {
|
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.
|
// 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 lhs = callArgs[0].second
|
||||||
val rhs = callArgs[1].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.
|
// If there is nothing on stack then nothing we can do.
|
||||||
val (topmostSubject, topmostOrdinalProvider) = subjectWithOrdinalStack.peek()
|
val (topmostSubject, topmostOrdinalProvider) = subjectWithOrdinalStack.peek()
|
||||||
?: return call
|
?: 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 entryOrdinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(rhs.descriptor)
|
||||||
val subjectOrdinal = topmostOrdinalProvider.value
|
val subjectOrdinal = topmostOrdinalProvider.value
|
||||||
return IrCallImpl(call.startOffset, call.endOffset, areEqualByValue).apply {
|
return IrCallImpl(call.startOffset, call.endOffset, areEqualByValue.owner.returnType, areEqualByValue).apply {
|
||||||
putValueArgument(0, IrGetValueImpl(lhs.startOffset, lhs.endOffset, subjectOrdinal.symbol))
|
putValueArgument(0,
|
||||||
putValueArgument(1, IrConstImpl.int(rhs.startOffset, rhs.endOffset, context.builtIns.intType, entryOrdinal))
|
IrGetValueImpl(lhs.startOffset, lhs.endOffset, subjectOrdinal.type, subjectOrdinal.symbol))
|
||||||
|
putValueArgument(1,
|
||||||
|
IrConstImpl.int(rhs.startOffset, rhs.endOffset, context.irBuiltIns.intType, entryOrdinal))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return call
|
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.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember
|
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.MemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
@@ -79,20 +76,21 @@ internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPa
|
|||||||
|
|
||||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
val newSymbol = remapExpectValueSymbol(expression.symbol)
|
val newValue = remapExpectValue(expression.symbol)
|
||||||
?: return expression
|
?: return expression
|
||||||
|
|
||||||
return IrGetValueImpl(
|
return IrGetValueImpl(
|
||||||
expression.startOffset,
|
expression.startOffset,
|
||||||
expression.endOffset,
|
expression.endOffset,
|
||||||
newSymbol,
|
newValue.type,
|
||||||
|
newValue.symbol,
|
||||||
expression.origin
|
expression.origin
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}, data = null)
|
}, data = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun remapExpectValueSymbol(symbol: IrValueSymbol): IrValueParameterSymbol? {
|
private fun remapExpectValue(symbol: IrValueSymbol): IrValueParameter? {
|
||||||
if (symbol !is IrValueParameterSymbol) {
|
if (symbol !is IrValueParameterSymbol) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -120,6 +118,6 @@ internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPa
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> error(parent)
|
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.IrReturnTargetSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
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.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
|
||||||
internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, IrElementTransformerVoidWithContext() {
|
internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
|
private val symbols get() = context.ir.symbols
|
||||||
|
|
||||||
private interface HighLevelJump {
|
private interface HighLevelJump {
|
||||||
fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression): IrExpression
|
fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression): IrExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class Return(val target: IrReturnTargetSymbol): HighLevelJump {
|
private data class Return(val target: IrReturnTargetSymbol): HighLevelJump {
|
||||||
override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression)
|
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 {
|
private data class Break(val loop: IrLoop): HighLevelJump {
|
||||||
override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression)
|
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(
|
statements = listOf(
|
||||||
value,
|
value,
|
||||||
IrBreakImpl(startOffset, endOffset, context.builtIns.nothingType, loop)
|
IrBreakImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class Continue(val loop: IrLoop): HighLevelJump {
|
private data class Continue(val loop: IrLoop): HighLevelJump {
|
||||||
override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression)
|
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(
|
statements = listOf(
|
||||||
value,
|
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]
|
val currentTryScope = tryScopes[index]
|
||||||
currentTryScope.jumps.getOrPut(jump) {
|
currentTryScope.jumps.getOrPut(jump) {
|
||||||
val symbol = getIrReturnableBlockSymbol(jump.toString(), value.type)
|
val type = value.type
|
||||||
|
val symbol = getIrReturnableBlockSymbol(jump.toString(), type)
|
||||||
with(currentTryScope) {
|
with(currentTryScope) {
|
||||||
irBuilder.run {
|
irBuilder.run {
|
||||||
val inlinedFinally = irInlineFinally(symbol, expression, finallyExpression)
|
val inlinedFinally = irInlineFinally(symbol, type, expression, finallyExpression)
|
||||||
expression = performHighLevelJump(
|
expression = performHighLevelJump(
|
||||||
tryScopes = tryScopes,
|
tryScopes = tryScopes,
|
||||||
index = index + 1,
|
index = index + 1,
|
||||||
@@ -201,7 +207,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
|||||||
return IrReturnImpl(
|
return IrReturnImpl(
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
type = context.builtIns.nothingType,
|
type = context.irBuiltIns.nothingType,
|
||||||
returnTargetSymbol = it,
|
returnTargetSymbol = it,
|
||||||
value = value)
|
value = value)
|
||||||
}
|
}
|
||||||
@@ -219,7 +225,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
|||||||
val transformedTry = IrTryImpl(
|
val transformedTry = IrTryImpl(
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
type = context.builtIns.nothingType
|
type = context.irBuiltIns.nothingType
|
||||||
)
|
)
|
||||||
val transformedFinallyExpression = finallyExpression.transform(transformer, null)
|
val transformedFinallyExpression = finallyExpression.transform(transformer, null)
|
||||||
val parameter = IrTemporaryVariableDescriptorImpl(
|
val parameter = IrTemporaryVariableDescriptorImpl(
|
||||||
@@ -228,24 +234,26 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
|||||||
outType = context.builtIns.throwable.defaultType
|
outType = context.builtIns.throwable.defaultType
|
||||||
)
|
)
|
||||||
val catchParameter = IrVariableImpl(
|
val catchParameter = IrVariableImpl(
|
||||||
startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter)
|
startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter,
|
||||||
|
symbols.throwable.owner.defaultType)
|
||||||
|
|
||||||
val syntheticTry = IrTryImpl(
|
val syntheticTry = IrTryImpl(
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
type = context.builtIns.nothingType,
|
type = context.irBuiltIns.nothingType,
|
||||||
tryResult = transformedTry,
|
tryResult = transformedTry,
|
||||||
catches = listOf(
|
catches = listOf(
|
||||||
irCatch(catchParameter).apply {
|
irCatch(catchParameter).apply {
|
||||||
result = irBlock {
|
result = irBlock {
|
||||||
+finallyExpression.copy()
|
+finallyExpression.copy()
|
||||||
+irThrow(irGet(catchParameter.symbol))
|
+irThrow(irGet(catchParameter))
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
finallyExpression = null
|
finallyExpression = null
|
||||||
)
|
)
|
||||||
using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
|
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)
|
val transformedResult = aTry.tryResult.transform(transformer, null)
|
||||||
transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult)
|
transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult)
|
||||||
for (aCatch in aTry.catches) {
|
for (aCatch in aTry.catches) {
|
||||||
@@ -253,28 +261,28 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
|||||||
transformedCatch.result = irReturn(fallThroughSymbol, transformedCatch.result)
|
transformedCatch.result = irReturn(fallThroughSymbol, transformedCatch.result)
|
||||||
transformedTry.catches.add(transformedCatch)
|
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,
|
value: IrExpression,
|
||||||
finallyExpression: IrExpression): IrExpression {
|
finallyExpression: IrExpression): IrExpression {
|
||||||
val returnType = symbol.descriptor.returnType!!
|
val returnType = symbol.descriptor.returnType!!
|
||||||
return when {
|
return when {
|
||||||
returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, returnType) {
|
returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, type) {
|
||||||
+irReturnableBlock(symbol) {
|
+irReturnableBlock(symbol, type) {
|
||||||
+value
|
+value
|
||||||
}
|
}
|
||||||
+finallyExpression.copy()
|
+finallyExpression.copy()
|
||||||
}
|
}
|
||||||
else -> irBlock(value, null, returnType) {
|
else -> irBlock(value, null, type) {
|
||||||
val tmp = irTemporary(irReturnableBlock(symbol) {
|
val tmp = irTemporary(irReturnableBlock(symbol, type) {
|
||||||
+irReturn(symbol, value)
|
+irReturn(symbol, value)
|
||||||
})
|
})
|
||||||
+finallyExpression.copy()
|
+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)
|
initialize(null, null, emptyList(), emptyList(), returnType, Modality.ABSTRACT, Visibilities.PRIVATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getIrReturnableBlockSymbol(name: String, returnType: KotlinType): IrReturnableBlockSymbol =
|
private fun getIrReturnableBlockSymbol(name: String, returnType: IrType): IrReturnableBlockSymbol =
|
||||||
IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType))
|
IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType.toKotlinType()))
|
||||||
|
|
||||||
private inline fun <reified T : IrElement> T.copy() = this.deepCopyWithVariables()
|
private inline fun <reified T : IrElement> T.copy() = this.deepCopyWithVariables()
|
||||||
|
|
||||||
fun IrBuilderWithScope.irReturn(target: IrReturnTargetSymbol, value: IrExpression) =
|
fun IrBuilderWithScope.irReturn(target: IrReturnTargetSymbol, value: IrExpression) =
|
||||||
IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, target, value)
|
IrReturnImpl(startOffset, endOffset, context.irBuiltIns.nothingType, target, value)
|
||||||
|
|
||||||
inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, body: IrBlockBuilder.() -> Unit) =
|
inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, type: IrType, body: IrBlockBuilder.() -> Unit) =
|
||||||
IrReturnableBlockImpl(startOffset, endOffset, symbol.descriptor.returnType!!, symbol, null,
|
IrReturnableBlockImpl(startOffset, endOffset, type, symbol, null,
|
||||||
IrBlockBuilder(context, scope, startOffset, endOffset, null, symbol.descriptor.returnType!!)
|
IrBlockBuilder(context, scope, startOffset, endOffset, null, type)
|
||||||
.block(body).statements)
|
.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.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
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.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
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.ir.visitors.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -134,36 +138,40 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
|||||||
|
|
||||||
//region Util methods ==============================================================================================
|
//region Util methods ==============================================================================================
|
||||||
private fun IrExpression.castIfNecessary(progressionType: ProgressionType): IrExpression {
|
private fun IrExpression.castIfNecessary(progressionType: ProgressionType): IrExpression {
|
||||||
|
val type = this.type.toKotlinType()
|
||||||
assert(type in progressionElementClassesTypes || type in progressionElementClassesNullableTypes)
|
assert(type in progressionElementClassesTypes || type in progressionElementClassesNullableTypes)
|
||||||
return if (type == progressionType.elementType) {
|
return if (type == progressionType.elementType) {
|
||||||
this
|
this
|
||||||
} else {
|
} 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 }
|
.apply { dispatchReceiver = this@castIfNecessary }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DeclarationIrBuilder.ensureNotNullable(expression: IrExpression): IrExpression {
|
private fun DeclarationIrBuilder.ensureNotNullable(expression: IrExpression): IrExpression {
|
||||||
return if (expression.type.isMarkedNullable) {
|
return if (expression.type.isSimpleTypeWithQuestionMark) {
|
||||||
irImplicitCast(expression, expression.type.makeNotNullable())
|
irImplicitCast(expression, expression.type.makeNotNull())
|
||||||
} else {
|
} else {
|
||||||
expression
|
expression
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrExpression.unaryMinus(): IrExpression =
|
private fun IrExpression.unaryMinus(): IrExpression {
|
||||||
IrCallImpl(startOffset, endOffset, symbols.getUnaryOperator(OperatorNameConventions.UNARY_MINUS, type)).apply {
|
val unaryOperator = symbols.getUnaryOperator(OperatorNameConventions.UNARY_MINUS, type.toKotlinType())
|
||||||
dispatchReceiver = this@unaryMinus
|
return IrCallImpl(startOffset, endOffset, unaryOperator.owner.returnType, unaryOperator).apply {
|
||||||
}
|
dispatchReceiver = this@unaryMinus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun ProgressionInfo.defaultStep(startOffset: Int, endOffset: Int): IrExpression =
|
private fun ProgressionInfo.defaultStep(startOffset: Int, endOffset: Int): IrExpression =
|
||||||
progressionType.elementType.let { type ->
|
progressionType.elementType.let { type ->
|
||||||
val step = if (increasing) 1 else -1
|
val step = if (increasing) 1 else -1
|
||||||
when {
|
when {
|
||||||
KotlinBuiltIns.isInt(type) || KotlinBuiltIns.isChar(type) ->
|
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) ->
|
KotlinBuiltIns.isLong(type) ->
|
||||||
IrConstImpl.long(startOffset, endOffset, context.builtIns.longType, step.toLong())
|
IrConstImpl.long(startOffset, endOffset, context.irBuiltIns.longType, step.toLong())
|
||||||
else -> throw IllegalArgumentException()
|
else -> throw IllegalArgumentException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,9 +186,9 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
|||||||
// Used only by the assert.
|
// Used only by the assert.
|
||||||
private fun stepHasRightType(step: IrExpression, progressionType: ProgressionType) =
|
private fun stepHasRightType(step: IrExpression, progressionType: ProgressionType) =
|
||||||
((progressionType.isCharProgression() || progressionType.isIntProgression()) &&
|
((progressionType.isCharProgression() || progressionType.isIntProgression()) &&
|
||||||
KotlinBuiltIns.isInt(step.type.makeNotNullable())) ||
|
KotlinBuiltIns.isInt(step.type.toKotlinType().makeNotNullable())) ||
|
||||||
(progressionType.isLongProgression() &&
|
(progressionType.isLongProgression() &&
|
||||||
KotlinBuiltIns.isLong(step.type.makeNotNullable()))
|
KotlinBuiltIns.isLong(step.type.toKotlinType().makeNotNullable()))
|
||||||
|
|
||||||
private fun irCheckProgressionStep(progressionType: ProgressionType,
|
private fun irCheckProgressionStep(progressionType: ProgressionType,
|
||||||
step: IrExpression): Pair<IrExpression, Boolean> {
|
step: IrExpression): Pair<IrExpression, Boolean> {
|
||||||
@@ -193,25 +201,25 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
|||||||
// so there is no need to cast it.
|
// so there is no need to cast it.
|
||||||
assert(stepHasRightType(step, progressionType))
|
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}")
|
?: 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)
|
putValueArgument(0, step)
|
||||||
} to true
|
} to true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun irGetProgressionLast(progressionType: ProgressionType,
|
private fun irGetProgressionLast(progressionType: ProgressionType,
|
||||||
first: IrVariableSymbol,
|
first: IrVariable,
|
||||||
lastExpression: IrExpression,
|
lastExpression: IrExpression,
|
||||||
step: IrVariableSymbol): IrExpression {
|
step: IrVariable): IrExpression {
|
||||||
val symbol = symbols.getProgressionLast[progressionType.elementType]
|
val symbol = symbols.getProgressionLast[progressionType.elementType]
|
||||||
?: throw IllegalArgumentException("Unknown progression element type: ${lastExpression.type}")
|
?: throw IllegalArgumentException("Unknown progression element type: ${lastExpression.type}")
|
||||||
val startOffset = lastExpression.startOffset
|
val startOffset = lastExpression.startOffset
|
||||||
val endOffset = lastExpression.endOffset
|
val endOffset = lastExpression.endOffset
|
||||||
return IrCallImpl(startOffset, lastExpression.endOffset, symbol).apply {
|
return IrCallImpl(startOffset, lastExpression.endOffset, symbol.owner.returnType, symbol).apply {
|
||||||
putValueArgument(0, IrGetValueImpl(startOffset, endOffset, first))
|
putValueArgument(0, IrGetValueImpl(startOffset, endOffset, first.type, first.symbol))
|
||||||
putValueArgument(1, lastExpression.castIfNecessary(progressionType))
|
putValueArgument(1, lastExpression.castIfNecessary(progressionType))
|
||||||
putValueArgument(2, IrGetValueImpl(startOffset, endOffset, step))
|
putValueArgument(2, IrGetValueImpl(startOffset, endOffset, step.type, step.symbol))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
@@ -236,11 +244,11 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
|||||||
/** Contains information about variables used in the loop. */
|
/** Contains information about variables used in the loop. */
|
||||||
private data class ForLoopInfo(
|
private data class ForLoopInfo(
|
||||||
val progressionInfo: ProgressionInfo,
|
val progressionInfo: ProgressionInfo,
|
||||||
val inductionVariable: IrVariableSymbol,
|
val inductionVariable: IrVariable,
|
||||||
val bound: IrVariableSymbol,
|
val bound: IrVariable,
|
||||||
val last: IrVariableSymbol,
|
val last: IrVariable,
|
||||||
val step: IrVariableSymbol,
|
val step: IrVariable,
|
||||||
var loopVariable: IrVariableSymbol? = null)
|
var loopVariable: IrVariable? = null)
|
||||||
|
|
||||||
private inner class ProgressionInfoBuilder : IrElementVisitor<ProgressionInfo?, Nothing?> {
|
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 visitElement(element: IrElement, data: Nothing?): ProgressionInfo? = null
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall, data: Nothing?): ProgressionInfo? {
|
override fun visitCall(expression: IrCall, data: Nothing?): ProgressionInfo? {
|
||||||
val type = expression.type
|
val type = expression.type.toKotlinType()
|
||||||
val progressionType = when {
|
val progressionType = when {
|
||||||
type.isSubtypeOf(symbols.charProgression.descriptor.defaultType) -> CHAR_PROGRESSION
|
type.isSubtypeOf(symbols.charProgression.descriptor.defaultType) -> CHAR_PROGRESSION
|
||||||
type.isSubtypeOf(symbols.intProgression.descriptor.defaultType) -> INT_PROGRESSION
|
type.isSubtypeOf(symbols.intProgression.descriptor.defaultType) -> INT_PROGRESSION
|
||||||
@@ -362,15 +370,15 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
|||||||
var lastExpression: IrExpression? = null
|
var lastExpression: IrExpression? = null
|
||||||
if (!closed) {
|
if (!closed) {
|
||||||
val decrementSymbol = symbols.getUnaryOperator(OperatorNameConventions.DEC, boundValue.descriptor.type)
|
val decrementSymbol = symbols.getUnaryOperator(OperatorNameConventions.DEC, boundValue.descriptor.type)
|
||||||
lastExpression = irCall(decrementSymbol).apply {
|
lastExpression = irCall(decrementSymbol.owner).apply {
|
||||||
dispatchReceiver = irGet(boundValue.symbol)
|
dispatchReceiver = irGet(boundValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (needLastCalculation) {
|
if (needLastCalculation) {
|
||||||
lastExpression = irGetProgressionLast(progressionType,
|
lastExpression = irGetProgressionLast(progressionType,
|
||||||
inductionVariable.symbol,
|
inductionVariable,
|
||||||
lastExpression ?: irGet(boundValue.symbol),
|
lastExpression ?: irGet(boundValue),
|
||||||
stepValue.symbol)
|
stepValue)
|
||||||
}
|
}
|
||||||
val lastValue = if (lastExpression != null) {
|
val lastValue = if (lastExpression != null) {
|
||||||
scope.createTemporaryVariable(lastExpression,
|
scope.createTemporaryVariable(lastExpression,
|
||||||
@@ -383,12 +391,12 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
|||||||
}
|
}
|
||||||
|
|
||||||
iteratorToLoopInfo[symbol] = ForLoopInfo(progressionInfo,
|
iteratorToLoopInfo[symbol] = ForLoopInfo(progressionInfo,
|
||||||
inductionVariable.symbol,
|
inductionVariable,
|
||||||
boundValue.symbol,
|
boundValue,
|
||||||
lastValue.symbol,
|
lastValue,
|
||||||
stepValue.symbol)
|
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.inductionVariable.descriptor.type,
|
||||||
forLoopInfo.step.descriptor.type
|
forLoopInfo.step.descriptor.type
|
||||||
)
|
)
|
||||||
forLoopInfo.loopVariable = variable.symbol
|
forLoopInfo.loopVariable = variable
|
||||||
|
|
||||||
with(builder) {
|
with(builder) {
|
||||||
variable.initializer = irGet(forLoopInfo.inductionVariable)
|
variable.initializer = irGet(forLoopInfo.inductionVariable)
|
||||||
val increment = irSetVar(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,
|
return IrCompositeImpl(variable.startOffset,
|
||||||
variable.endOffset,
|
variable.endOffset,
|
||||||
context.irBuiltIns.unit,
|
context.irBuiltIns.unitType,
|
||||||
IrStatementOrigin.FOR_LOOP_NEXT,
|
IrStatementOrigin.FOR_LOOP_NEXT,
|
||||||
listOf(variable, increment))
|
listOf(variable, increment))
|
||||||
}
|
}
|
||||||
@@ -427,16 +435,16 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
|||||||
return irCall(context.irBuiltIns.greaterFunByOperandType[context.irBuiltIns.int]?.symbol!!).apply {
|
return irCall(context.irBuiltIns.greaterFunByOperandType[context.irBuiltIns.int]?.symbol!!).apply {
|
||||||
val minConst = when {
|
val minConst = when {
|
||||||
progressionType.isIntProgression() -> IrConstImpl
|
progressionType.isIntProgression() -> IrConstImpl
|
||||||
.int(startOffset, endOffset, context.builtIns.intType, Int.MIN_VALUE)
|
.int(startOffset, endOffset, context.irBuiltIns.intType, Int.MIN_VALUE)
|
||||||
progressionType.isCharProgression() -> IrConstImpl
|
progressionType.isCharProgression() -> IrConstImpl
|
||||||
.char(startOffset, endOffset, context.builtIns.charType, 0.toChar())
|
.char(startOffset, endOffset, context.irBuiltIns.charType, 0.toChar())
|
||||||
progressionType.isLongProgression() -> IrConstImpl
|
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")
|
else -> throw IllegalArgumentException("Unknown progression type")
|
||||||
}
|
}
|
||||||
val compareToCall = irCall(symbols.getBinaryOperator(OperatorNameConventions.COMPARE_TO,
|
val compareToCall = irCall(symbols.getBinaryOperator(OperatorNameConventions.COMPARE_TO,
|
||||||
forLoopInfo.bound.descriptor.type,
|
forLoopInfo.bound.descriptor.type,
|
||||||
minConst.type)).apply {
|
minConst.type.toKotlinType())).apply {
|
||||||
dispatchReceiver = irGet(forLoopInfo.bound)
|
dispatchReceiver = irGet(forLoopInfo.bound)
|
||||||
putValueArgument(0, minConst)
|
putValueArgument(0, minConst)
|
||||||
}
|
}
|
||||||
@@ -458,7 +466,7 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo
|
|||||||
forLoopInfo.last.descriptor.type)
|
forLoopInfo.last.descriptor.type)
|
||||||
|
|
||||||
val check: IrExpression = irCall(comparingBuiltIn!!).apply {
|
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))
|
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.IrReturnableBlockImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
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.getArguments
|
||||||
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -66,7 +67,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
|||||||
|
|
||||||
fun inline(irModule: IrModuleFragment): IrElement {
|
fun inline(irModule: IrModuleFragment): IrElement {
|
||||||
val transformedModule = irModule.accept(this, null)
|
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
|
return transformedModule
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,8 +158,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
|
||||||
irBuilder.run {
|
irBuilder.run {
|
||||||
val constructorDescriptor = delegatingConstructorCall.descriptor.original
|
val constructorDescriptor = delegatingConstructorCall.descriptor.original
|
||||||
val constructorCall = irCall(delegatingConstructorCall.symbol,
|
val constructorCall = irCall(delegatingConstructorCall.symbol, callee.type,
|
||||||
constructorDescriptor.typeParameters.associate { it to delegatingConstructorCall.getTypeArgument(it)!! }).apply {
|
constructorDescriptor.typeParameters.map { delegatingConstructorCall.getTypeArgument(it)!! }).apply {
|
||||||
constructorDescriptor.valueParameters.forEach { putValueArgument(it, delegatingConstructorCall.getValueArgument(it)) }
|
constructorDescriptor.valueParameters.forEach { putValueArgument(it, delegatingConstructorCall.getValueArgument(it)) }
|
||||||
}
|
}
|
||||||
val oldThis = delegatingConstructorCall.descriptor.constructedClass.thisAsReceiverParameter
|
val oldThis = delegatingConstructorCall.descriptor.constructedClass.thisAsReceiverParameter
|
||||||
@@ -167,12 +168,12 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
nameHint = delegatingConstructorCall.descriptor.fqNameSafe.toString() + ".this"
|
nameHint = delegatingConstructorCall.descriptor.fqNameSafe.toString() + ".this"
|
||||||
)
|
)
|
||||||
statements[0] = newThis
|
statements[0] = newThis
|
||||||
substituteMap[oldThis] = irGet(newThis.symbol)
|
substituteMap[oldThis] = irGet(newThis)
|
||||||
statements.add(irReturn(irGet(newThis.symbol)))
|
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 sourceFileName = context.ir.originalModuleIndex.declarationToFile[caller.descriptor.original]?:""
|
||||||
val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call".
|
val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call".
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
@@ -235,6 +236,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
val immediateCall = IrCallImpl(
|
val immediateCall = IrCallImpl(
|
||||||
startOffset = expression.startOffset,
|
startOffset = expression.startOffset,
|
||||||
endOffset = expression.endOffset,
|
endOffset = expression.endOffset,
|
||||||
|
type = expression.type,
|
||||||
symbol = functionArgument.symbol,
|
symbol = functionArgument.symbol,
|
||||||
descriptor = functionArgument.descriptor).apply {
|
descriptor = functionArgument.descriptor).apply {
|
||||||
functionParameters.forEach {
|
functionParameters.forEach {
|
||||||
@@ -290,7 +292,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
val substitutionContext = mutableMapOf<TypeConstructor, TypeProjection>()
|
val substitutionContext = mutableMapOf<TypeConstructor, TypeProjection>()
|
||||||
for (index in 0 until irCall.typeArgumentsCount) {
|
for (index in 0 until irCall.typeArgumentsCount) {
|
||||||
val typeArgument = irCall.getTypeArgument(index) ?: continue
|
val typeArgument = irCall.getTypeArgument(index) ?: continue
|
||||||
substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument)
|
substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument.toKotlinType())
|
||||||
}
|
}
|
||||||
return TypeSubstitutor.create(substitutionContext)
|
return TypeSubstitutor.create(substitutionContext)
|
||||||
}
|
}
|
||||||
@@ -359,8 +361,9 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
val parametersWithDefaultToArgument = mutableListOf<ParameterToArgument>()
|
val parametersWithDefaultToArgument = mutableListOf<ParameterToArgument>()
|
||||||
functionDescriptor.valueParameters.forEach { parameterDescriptor -> // Iterate value parameter descriptors.
|
irFunction.valueParameters.forEach { parameter -> // Iterate value parameters.
|
||||||
val argument = valueArguments[parameterDescriptor.index] // Get appropriate argument from call site.
|
val parameterDescriptor = parameter.descriptor as ValueParameterDescriptor
|
||||||
|
val argument = valueArguments[parameterDescriptor.index] // Get appropriate argument from call site.
|
||||||
when {
|
when {
|
||||||
argument != null -> { // Argument is good enough.
|
argument != null -> { // Argument is good enough.
|
||||||
parameterToArgument += ParameterToArgument( // Associate current parameter with the argument.
|
parameterToArgument += ParameterToArgument( // Associate current parameter with the argument.
|
||||||
@@ -381,8 +384,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
val emptyArray = IrVarargImpl(
|
val emptyArray = IrVarargImpl(
|
||||||
startOffset = irCall.startOffset,
|
startOffset = irCall.startOffset,
|
||||||
endOffset = irCall.endOffset,
|
endOffset = irCall.endOffset,
|
||||||
type = parameterDescriptor.type,
|
type = parameter.type,
|
||||||
varargElementType = parameterDescriptor.varargElementType!!
|
varargElementType = parameter.varargElementType!!
|
||||||
)
|
)
|
||||||
parameterToArgument += ParameterToArgument(
|
parameterToArgument += ParameterToArgument(
|
||||||
parameterDescriptor = parameterDescriptor,
|
parameterDescriptor = parameterDescriptor,
|
||||||
@@ -432,7 +435,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
val getVal = IrGetValueImpl( // Create new expression, representing access the new variable.
|
val getVal = IrGetValueImpl( // Create new expression, representing access the new variable.
|
||||||
startOffset = currentScope.irElement.startOffset,
|
startOffset = currentScope.irElement.startOffset,
|
||||||
endOffset = currentScope.irElement.endOffset,
|
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.
|
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.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.addChild
|
import org.jetbrains.kotlin.ir.util.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.util.transformFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
@@ -64,7 +64,7 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
|||||||
|
|
||||||
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement {
|
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement {
|
||||||
initializers.add(IrBlockImpl(declaration.startOffset, declaration.endOffset,
|
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
|
return declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,11 +72,16 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
|||||||
val initializer = declaration.initializer ?: return declaration
|
val initializer = declaration.initializer ?: return declaration
|
||||||
val startOffset = initializer.startOffset
|
val startOffset = initializer.startOffset
|
||||||
val endOffset = initializer.endOffset
|
val endOffset = initializer.endOffset
|
||||||
initializers.add(IrBlockImpl(startOffset, endOffset, context.builtIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER,
|
initializers.add(IrBlockImpl(startOffset, endOffset, context.irBuiltIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER,
|
||||||
listOf(
|
listOf(
|
||||||
IrSetFieldImpl(startOffset, endOffset, declaration.symbol,
|
IrSetFieldImpl(startOffset, endOffset, declaration.symbol,
|
||||||
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
|
IrGetValueImpl(
|
||||||
initializer.expression, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER))))
|
startOffset, endOffset,
|
||||||
|
irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol
|
||||||
|
),
|
||||||
|
initializer.expression,
|
||||||
|
context.irBuiltIns.unitType,
|
||||||
|
STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER))))
|
||||||
declaration.initializer = null
|
declaration.initializer = null
|
||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
@@ -109,9 +114,13 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
|||||||
val startOffset = irClass.startOffset
|
val startOffset = irClass.startOffset
|
||||||
val endOffset = irClass.endOffset
|
val endOffset = irClass.endOffset
|
||||||
val initializer = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ANONYMOUS_INITIALIZER,
|
val 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 {
|
initializers.forEach {
|
||||||
it.transformChildrenVoid(object : IrElementTransformerVoid() {
|
it.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
@@ -120,6 +129,7 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
|||||||
return IrGetValueImpl(
|
return IrGetValueImpl(
|
||||||
expression.startOffset,
|
expression.startOffset,
|
||||||
expression.endOffset,
|
expression.endOffset,
|
||||||
|
initializer.dispatchReceiverParameter!!.type,
|
||||||
initializer.dispatchReceiverParameter!!.symbol
|
initializer.dispatchReceiverParameter!!.symbol
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -129,7 +139,7 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
irClass.addChild(initializer)
|
irClass.declarations.add(initializer)
|
||||||
|
|
||||||
return initializer.symbol
|
return initializer.symbol
|
||||||
}
|
}
|
||||||
@@ -156,8 +166,13 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
|||||||
} else {
|
} else {
|
||||||
val startOffset = it.startOffset
|
val startOffset = it.startOffset
|
||||||
val endOffset = it.endOffset
|
val endOffset = it.endOffset
|
||||||
listOf(IrCallImpl(startOffset, endOffset, initializerMethodSymbol).apply {
|
listOf(IrCallImpl(startOffset, endOffset,
|
||||||
dispatchReceiver = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol)
|
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.addChild
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||||
|
|
||||||
internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||||
@@ -57,7 +56,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createOuterThisField() {
|
private fun createOuterThisField() {
|
||||||
val field = context.specialDeclarationsFactory.getOuterThisField(classDescriptor)
|
val field = context.specialDeclarationsFactory.getOuterThisField(irClass)
|
||||||
outerThisFieldSymbol = field.symbol
|
outerThisFieldSymbol = field.symbol
|
||||||
irClass.addChild(field)
|
irClass.addChild(field)
|
||||||
}
|
}
|
||||||
@@ -78,12 +77,15 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}")
|
?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}")
|
||||||
val startOffset = irConstructor.startOffset
|
val startOffset = irConstructor.startOffset
|
||||||
val endOffset = irConstructor.endOffset
|
val endOffset = irConstructor.endOffset
|
||||||
|
val thisReceiver = irClass.thisReceiver!!
|
||||||
|
val outerReceiver = irConstructor.dispatchReceiverParameter!!
|
||||||
blockBody.statements.add(
|
blockBody.statements.add(
|
||||||
0,
|
0,
|
||||||
IrSetFieldImpl(
|
IrSetFieldImpl(
|
||||||
startOffset, endOffset, outerThisFieldSymbol,
|
startOffset, endOffset, outerThisFieldSymbol,
|
||||||
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
|
IrGetValueImpl(startOffset, endOffset, thisReceiver.type, thisReceiver.symbol),
|
||||||
IrGetValueImpl(startOffset, endOffset, irConstructor.dispatchReceiverParameter!!.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
|
val origin = expression.origin
|
||||||
|
|
||||||
var irThis: IrExpression
|
var irThis: IrExpression
|
||||||
var innerClass: ClassDescriptor
|
var innerClass: IrClass
|
||||||
if (constructorSymbol == null || constructorSymbol.descriptor.constructedClass != classDescriptor) {
|
if (constructorSymbol == null || constructorSymbol.descriptor.constructedClass != classDescriptor) {
|
||||||
innerClass = classDescriptor
|
innerClass = irClass
|
||||||
val currentIrFunction = currentFunction!!.scope.scopeOwnerSymbol.owner as IrFunction
|
val currentIrFunction = currentFunction!!.scope.scopeOwnerSymbol.owner as IrFunction
|
||||||
|
|
||||||
val currentFunctionReceiver = currentIrFunction.dispatchReceiverParameter
|
val currentFunctionReceiver = currentIrFunction.dispatchReceiverParameter
|
||||||
val thisSymbol = if (currentFunctionReceiver?.descriptor == irClass.thisReceiver!!.descriptor) {
|
val thisParameter = if (currentFunctionReceiver?.descriptor == irClass.thisReceiver!!.descriptor) {
|
||||||
currentFunctionReceiver
|
currentFunctionReceiver
|
||||||
} else {
|
} else {
|
||||||
irClass.thisReceiver!!
|
irClass.thisReceiver!!
|
||||||
}.symbol
|
}
|
||||||
|
|
||||||
irThis = IrGetValueImpl(startOffset, endOffset, thisSymbol, origin)
|
irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin)
|
||||||
} else {
|
} else {
|
||||||
// For constructor we have outer class as dispatchReceiverParameter.
|
// For constructor we have outer class as dispatchReceiverParameter.
|
||||||
innerClass = DescriptorUtils.getContainingClass(classDescriptor) ?:
|
innerClass = irClass.parent as? IrClass ?:
|
||||||
throw AssertionError("No containing class for inner class $classDescriptor")
|
throw AssertionError("No containing class for inner class $classDescriptor")
|
||||||
irThis = IrGetValueImpl(startOffset, endOffset,
|
val thisParameter = constructorSymbol.owner.dispatchReceiverParameter!!
|
||||||
constructorSymbol.owner.dispatchReceiverParameter!!.symbol, origin)
|
irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (innerClass != implicitThisClass) {
|
while (innerClass.descriptor != implicitThisClass) {
|
||||||
if (!innerClass.isInner) {
|
if (!innerClass.isInner) {
|
||||||
// Captured 'this' unrelated to inner classes nesting hierarchy, leave it as is -
|
// Captured 'this' unrelated to inner classes nesting hierarchy, leave it as is -
|
||||||
// should be transformed by closures conversion.
|
// should be transformed by closures conversion.
|
||||||
@@ -137,11 +139,16 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val outerThisField = context.specialDeclarationsFactory.getOuterThisField(innerClass)
|
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
|
val outer = innerClass.parent
|
||||||
innerClass = outer as? ClassDescriptor ?:
|
innerClass = outer as? IrClass ?:
|
||||||
throw AssertionError("Unexpected containing declaration for inner class $innerClass: $outer")
|
throw AssertionError("Unexpected containing declaration for inner class ${innerClass.descriptor}: $outer")
|
||||||
}
|
}
|
||||||
|
|
||||||
return irThis
|
return irThis
|
||||||
|
|||||||
+129
-101
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.lower
|
package org.jetbrains.kotlin.backend.konan.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.common.peek
|
import org.jetbrains.kotlin.backend.common.peek
|
||||||
import org.jetbrains.kotlin.backend.common.pop
|
import org.jetbrains.kotlin.backend.common.pop
|
||||||
@@ -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.allOverriddenDescriptors
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructors
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||||
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.descriptors.*
|
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.AnnotationDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
|
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.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
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.constants.StringValue
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.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 {
|
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 {
|
private fun IrBuilderWithScope.getObjCClass(classSymbol: IrClassSymbol): IrExpression {
|
||||||
val classDescriptor = classSymbol.descriptor
|
val classDescriptor = classSymbol.descriptor
|
||||||
assert(!classDescriptor.isObjCMetaClass())
|
assert(!classDescriptor.isObjCMetaClass())
|
||||||
return irCall(symbols.interopGetObjCClass, listOf(classDescriptor.defaultType))
|
return irCall(symbols.interopGetObjCClass, symbols.nativePtrType, listOf(classSymbol.typeWithStarProjections))
|
||||||
}
|
}
|
||||||
|
|
||||||
private val outerClasses = mutableListOf<IrClass>()
|
private val outerClasses = mutableListOf<IrClass>()
|
||||||
@@ -131,7 +129,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
val superClass = irClass.getSuperClassNotAny()!!
|
val superClass = irClass.getSuperClassNotAny()!!
|
||||||
val superConstructors = superClass.constructors.filter {
|
val superConstructors = superClass.constructors.filter {
|
||||||
constructor.overridesConstructor(it)
|
constructor.overridesConstructor(it)
|
||||||
}
|
}.toList()
|
||||||
|
|
||||||
val superConstructor = superConstructors.singleOrNull() ?: run {
|
val superConstructor = superConstructors.singleOrNull() ?: run {
|
||||||
val annotation = context.interopBuiltIns.objCOverrideInit.name
|
val annotation = context.interopBuiltIns.objCOverrideInit.name
|
||||||
@@ -179,38 +177,42 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
initMethod.name,
|
initMethod.name,
|
||||||
CallableMemberDescriptor.Kind.DECLARATION,
|
CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
SourceElement.NO_SOURCE
|
SourceElement.NO_SOURCE
|
||||||
).apply {
|
)
|
||||||
val valueParameters = initMethod.valueParameters.map {
|
|
||||||
ValueParameterDescriptorImpl(
|
val valueParameters = initMethod.valueParameters.map {
|
||||||
this,
|
val descriptor = ValueParameterDescriptorImpl(
|
||||||
null,
|
resultDescriptor,
|
||||||
it.index,
|
|
||||||
Annotations.EMPTY,
|
|
||||||
it.name,
|
|
||||||
it.type,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
it.varargElementType,
|
|
||||||
SourceElement.NO_SOURCE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
initialize(
|
|
||||||
null,
|
null,
|
||||||
irClass.descriptor.thisAsReceiverParameter,
|
it.index,
|
||||||
emptyList<TypeParameterDescriptor>(),
|
Annotations.EMPTY,
|
||||||
valueParameters,
|
it.name,
|
||||||
irClass.defaultType,
|
it.descriptor.type,
|
||||||
Modality.OPEN,
|
false,
|
||||||
Visibilities.PUBLIC
|
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(
|
return IrFunctionImpl(
|
||||||
constructor.startOffset, constructor.endOffset, OVERRIDING_INITIALIZER_BY_CONSTRUCTOR,
|
constructor.startOffset, constructor.endOffset, OVERRIDING_INITIALIZER_BY_CONSTRUCTOR,
|
||||||
resultDescriptor
|
resultDescriptor
|
||||||
).also { result ->
|
).also { result ->
|
||||||
result.createParameterDeclarations()
|
result.returnType = irClass.defaultType
|
||||||
|
result.parent = irClass
|
||||||
|
result.createDispatchReceiverParameter()
|
||||||
|
result.valueParameters += valueParameters
|
||||||
|
|
||||||
result.overriddenSymbols.add(initMethod.symbol)
|
result.overriddenSymbols.add(initMethod.symbol)
|
||||||
result.descriptor.overriddenDescriptors = listOf(initMethod.descriptor)
|
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) {
|
result.body = context.createIrBuilder(result.symbol).irBlockBody(result) {
|
||||||
+irReturn(
|
+irReturn(
|
||||||
irCall(symbols.interopObjCObjectInitBy, listOf(irClass.defaultType)).apply {
|
irCall(symbols.interopObjCObjectInitBy, listOf(irClass.defaultType)).apply {
|
||||||
extensionReceiver = irGet(result.dispatchReceiverParameter!!.symbol)
|
extensionReceiver = irGet(result.dispatchReceiverParameter!!)
|
||||||
putValueArgument(0, irCall(constructor.symbol).also {
|
putValueArgument(0, irCall(constructor).also {
|
||||||
result.valueParameters.forEach { parameter ->
|
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")
|
IrDeclarationOriginImpl("OVERRIDING_INITIALIZER_BY_CONSTRUCTOR")
|
||||||
|
|
||||||
private fun IrConstructor.overridesConstructor(other: IrConstructor): Boolean {
|
private fun IrConstructor.overridesConstructor(other: IrConstructor): Boolean {
|
||||||
return this.valueParameters.size == other.valueParameters.size &&
|
return this.descriptor.valueParameters.size == other.descriptor.valueParameters.size &&
|
||||||
this.valueParameters.all {
|
this.descriptor.valueParameters.all {
|
||||||
val otherParameter = other.valueParameters[it.index]
|
val otherParameter = other.descriptor.valueParameters[it.index]
|
||||||
it.name == otherParameter.name && it.type == otherParameter.type
|
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()) {
|
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",
|
"Only 'Unit' is supported here",
|
||||||
currentFile, function
|
currentFile, function
|
||||||
)
|
)
|
||||||
@@ -303,7 +305,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
private fun getMethodSignatureEncoding(function: IrFunction): String {
|
private fun getMethodSignatureEncoding(function: IrFunction): String {
|
||||||
assert(function.extensionReceiverParameter == null)
|
assert(function.extensionReceiverParameter == null)
|
||||||
assert(function.valueParameters.all { it.type.isObjCObjectType() })
|
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.
|
// Note: these values are valid for x86_64 and arm64.
|
||||||
return when (function.valueParameters.size) {
|
return when (function.valueParameters.size) {
|
||||||
@@ -319,10 +321,10 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
private fun generateFunctionImp(selector: String, function: IrFunction): IrSimpleFunction {
|
private fun generateFunctionImp(selector: String, function: IrFunction): IrSimpleFunction {
|
||||||
val signatureEncoding = getMethodSignatureEncoding(function)
|
val signatureEncoding = getMethodSignatureEncoding(function)
|
||||||
|
|
||||||
val returnType = function.descriptor.returnType!!
|
val returnType = function.returnType
|
||||||
assert(returnType.isUnit())
|
assert(returnType.isUnit())
|
||||||
|
|
||||||
val nativePtrType = context.builtIns.nativePtr.defaultType
|
val nativePtrType = context.ir.symbols.nativePtrType
|
||||||
|
|
||||||
val parameterTypes = mutableListOf(nativePtrType) // id self
|
val parameterTypes = mutableListOf(nativePtrType) // id self
|
||||||
|
|
||||||
@@ -353,7 +355,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
index,
|
index,
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
Name.identifier("p$index"),
|
Name.identifier("p$index"),
|
||||||
it,
|
it.toKotlinType(),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
@@ -366,7 +368,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
null, null,
|
null, null,
|
||||||
emptyList(),
|
emptyList(),
|
||||||
valueParameters,
|
valueParameters,
|
||||||
returnType,
|
function.descriptor.returnType,
|
||||||
Modality.FINAL,
|
Modality.FINAL,
|
||||||
Visibilities.PRIVATE
|
Visibilities.PRIVATE
|
||||||
)
|
)
|
||||||
@@ -375,20 +377,33 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
function.startOffset, function.endOffset,
|
function.startOffset, function.endOffset,
|
||||||
IrDeclarationOrigin.DEFINED,
|
IrDeclarationOrigin.DEFINED,
|
||||||
newDescriptor
|
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)
|
val builder = context.createIrBuilder(newFunction.symbol)
|
||||||
newFunction.body = builder.irBlockBody(newFunction) {
|
newFunction.body = builder.irBlockBody(newFunction) {
|
||||||
+irCall(function.symbol).apply {
|
+irCall(function).apply {
|
||||||
dispatchReceiver = interpretObjCPointer(
|
dispatchReceiver = interpretObjCPointer(
|
||||||
irGet(newFunction.valueParameters[0].symbol),
|
irGet(newFunction.valueParameters[0]),
|
||||||
function.dispatchReceiverParameter!!.type
|
function.dispatchReceiverParameter!!.type
|
||||||
)
|
)
|
||||||
|
|
||||||
function.valueParameters.forEachIndexed { index, parameter ->
|
function.valueParameters.forEachIndexed { index, parameter ->
|
||||||
putValueArgument(index,
|
putValueArgument(index,
|
||||||
interpretObjCPointer(
|
interpretObjCPointer(
|
||||||
irGet(newFunction.valueParameters[index + 2].symbol),
|
irGet(newFunction.valueParameters[index + 2]),
|
||||||
parameter.type
|
parameter.type
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -399,8 +414,8 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
return newFunction
|
return newFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.interpretObjCPointer(expression: IrExpression, type: KotlinType): IrExpression {
|
private fun IrBuilderWithScope.interpretObjCPointer(expression: IrExpression, type: IrType): IrExpression {
|
||||||
val callee: IrFunctionSymbol = if (TypeUtils.isNullableType(type)) {
|
val callee: IrFunctionSymbol = if (type.containsNull()) {
|
||||||
symbols.interopInterpretObjCPointerOrNull
|
symbols.interopInterpretObjCPointerOrNull
|
||||||
} else {
|
} else {
|
||||||
symbols.interopInterpretObjCPointer
|
symbols.interopInterpretObjCPointer
|
||||||
@@ -534,7 +549,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
val initCall = builder.genLoweredObjCMethodCall(
|
val initCall = builder.genLoweredObjCMethodCall(
|
||||||
initMethodInfo,
|
initMethodInfo,
|
||||||
superQualifier = symbolTable.referenceClass(expression.descriptor.constructedClass),
|
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)!! }
|
arguments = initMethod.valueParameters.map { expression.getValueArgument(it)!! }
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -544,10 +559,17 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
|
|
||||||
return builder.irBlock(expression) {
|
return builder.irBlock(expression) {
|
||||||
// Required for the IR to be valid, will be ignored in codegen:
|
// 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 {
|
+irCall(symbols.interopObjCObjectSuperInitCheck).apply {
|
||||||
extensionReceiver = irGet(constructedClass.thisReceiver!!.symbol)
|
extensionReceiver = irGet(constructedClass.thisReceiver!!)
|
||||||
putValueArgument(0, initCall)
|
putValueArgument(0, initCall)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -560,10 +582,10 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
receiver: IrExpression, arguments: List<IrExpression>): IrExpression {
|
receiver: IrExpression, arguments: List<IrExpression>): IrExpression {
|
||||||
|
|
||||||
val superClass = superQualifier?.let { getObjCClass(it) } ?:
|
val superClass = superQualifier?.let { getObjCClass(it) } ?:
|
||||||
irCall(symbols.getNativeNullPtr)
|
irCall(symbols.getNativeNullPtr, symbols.nativePtrType)
|
||||||
|
|
||||||
val bridge = symbolTable.referenceSimpleFunction(info.bridge)
|
val bridge = symbolTable.referenceSimpleFunction(info.bridge)
|
||||||
return irCall(bridge).apply {
|
return irCall(bridge, symbolTable.translateErased(info.bridge.returnType!!)).apply {
|
||||||
putValueArgument(0, superClass)
|
putValueArgument(0, superClass)
|
||||||
putValueArgument(1, receiver)
|
putValueArgument(1, receiver)
|
||||||
|
|
||||||
@@ -646,18 +668,16 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
return when (descriptor) {
|
return when (descriptor) {
|
||||||
context.interopBuiltIns.typeOf -> {
|
context.interopBuiltIns.typeOf -> {
|
||||||
val typeArgument = expression.getSingleTypeArgument()
|
val typeArgument = expression.getSingleTypeArgument()
|
||||||
val classDescriptor = TypeUtils.getClassDescriptor(typeArgument)
|
val classSymbol = typeArgument.classifierOrNull as? IrClassSymbol
|
||||||
|
|
||||||
if (classDescriptor == null) {
|
if (classSymbol == null) {
|
||||||
expression
|
expression
|
||||||
} else {
|
} else {
|
||||||
val companionObjectDescriptor = classDescriptor.companionObjectDescriptor ?:
|
val classDescriptor = classSymbol.descriptor
|
||||||
|
val companionObject = classDescriptor.companionObjectDescriptor ?:
|
||||||
error("native variable class $classDescriptor must have the companion object")
|
error("native variable class $classDescriptor must have the companion object")
|
||||||
|
|
||||||
IrGetObjectValueImpl(
|
builder.at(expression).irGetObject(symbolTable.referenceClass(companionObject))
|
||||||
expression.startOffset, expression.endOffset, companionObjectDescriptor.defaultType,
|
|
||||||
symbolTable.referenceClass(companionObjectDescriptor)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> expression
|
else -> expression
|
||||||
@@ -674,14 +694,14 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
|||||||
val initCall = genLoweredObjCMethodCall(
|
val initCall = genLoweredObjCMethodCall(
|
||||||
initMethodInfo,
|
initMethodInfo,
|
||||||
superQualifier = null,
|
superQualifier = null,
|
||||||
receiver = irGet(allocated.symbol),
|
receiver = irGet(allocated),
|
||||||
arguments = arguments
|
arguments = arguments
|
||||||
)
|
)
|
||||||
|
|
||||||
+IrTryImpl(startOffset, endOffset, initCall.type).apply {
|
+IrTryImpl(startOffset, endOffset, initCall.type).apply {
|
||||||
tryResult = initCall
|
tryResult = initCall
|
||||||
finallyExpression = irCall(symbols.interopObjCRelease).apply {
|
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 targetSymbol = irCallableReference.symbol
|
||||||
val target = targetSymbol.descriptor
|
val target = targetSymbol.owner
|
||||||
val signatureTypes = target.allParameters.map { it.type } + target.returnType!!
|
val signatureTypes = target.allParameters.map { it.type } + target.returnType
|
||||||
|
|
||||||
signatureTypes.forEachIndexed { index, type ->
|
signatureTypes.forEachIndexed { index, type ->
|
||||||
type.ensureSupportedInCallbacks(
|
type.ensureSupportedInCallbacks(
|
||||||
@@ -781,9 +801,10 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
}
|
}
|
||||||
|
|
||||||
descriptor.typeParameters.forEachIndexed { index, typeParameterDescriptor ->
|
descriptor.typeParameters.forEachIndexed { index, typeParameterDescriptor ->
|
||||||
val typeArgument = expression.getTypeArgument(typeParameterDescriptor)!!
|
val typeArgument = expression.getTypeArgument(typeParameterDescriptor)!!.toKotlinType()
|
||||||
val signatureType = signatureTypes[index]
|
val signatureType = signatureTypes[index].toKotlinType()
|
||||||
if (typeArgument != signatureType) {
|
if (typeArgument.constructor != signatureType.constructor ||
|
||||||
|
typeArgument.isMarkedNullable != signatureType.isMarkedNullable) {
|
||||||
context.reportCompilationError(
|
context.reportCompilationError(
|
||||||
"C function signature element mismatch: expected '$signatureType', got '$typeArgument'",
|
"C function signature element mismatch: expected '$signatureType', got '$typeArgument'",
|
||||||
irFile, expression
|
irFile, expression
|
||||||
@@ -794,8 +815,8 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
IrFunctionReferenceImpl(
|
IrFunctionReferenceImpl(
|
||||||
builder.startOffset, builder.endOffset,
|
builder.startOffset, builder.endOffset,
|
||||||
expression.type,
|
expression.type,
|
||||||
targetSymbol, target,
|
targetSymbol, target.descriptor,
|
||||||
typeArguments = null)
|
typeArgumentsCount = 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
interop.scheduleFunction -> {
|
interop.scheduleFunction -> {
|
||||||
@@ -812,9 +833,9 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
val target = targetSymbol.descriptor
|
val target = targetSymbol.descriptor
|
||||||
val jobPointer = IrFunctionReferenceImpl(
|
val jobPointer = IrFunctionReferenceImpl(
|
||||||
builder.startOffset, builder.endOffset,
|
builder.startOffset, builder.endOffset,
|
||||||
interop.cPointer.defaultType,
|
symbols.scheduleImpl.owner.valueParameters[3].type,
|
||||||
targetSymbol, target,
|
targetSymbol, target,
|
||||||
typeArguments = null)
|
typeArgumentsCount = 0)
|
||||||
|
|
||||||
builder.irCall(symbols.scheduleImpl).apply {
|
builder.irCall(symbols.scheduleImpl).apply {
|
||||||
putValueArgument(0, expression.dispatchReceiver)
|
putValueArgument(0, expression.dispatchReceiver)
|
||||||
@@ -827,33 +848,36 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
interop.signExtend, interop.narrow -> {
|
interop.signExtend, interop.narrow -> {
|
||||||
|
|
||||||
val integerTypePredicates = arrayOf(
|
val integerTypePredicates = arrayOf(
|
||||||
KotlinBuiltIns::isByte, KotlinBuiltIns::isShort, KotlinBuiltIns::isInt, KotlinBuiltIns::isLong
|
IrType::isByte, IrType::isShort, IrType::isInt, IrType::isLong
|
||||||
)
|
)
|
||||||
|
|
||||||
val receiver = expression.extensionReceiver!!
|
val receiver = expression.extensionReceiver!!
|
||||||
val typeOperand = expression.getSingleTypeArgument()
|
val typeOperand = expression.getSingleTypeArgument()
|
||||||
|
val kotlinTypeOperand = typeOperand.toKotlinType()
|
||||||
|
|
||||||
val receiverTypeIndex = integerTypePredicates.indexOfFirst { it(receiver.type) }
|
val receiverTypeIndex = integerTypePredicates.indexOfFirst { it(receiver.type) }
|
||||||
val typeOperandIndex = integerTypePredicates.indexOfFirst { it(typeOperand) }
|
val typeOperandIndex = integerTypePredicates.indexOfFirst { it(typeOperand) }
|
||||||
|
|
||||||
|
val receiverKotlinType = receiver.type.toKotlinType()
|
||||||
|
|
||||||
if (receiverTypeIndex == -1) {
|
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)
|
irFile, receiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeOperandIndex == -1) {
|
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)
|
irFile, expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
when (descriptor) {
|
when (descriptor) {
|
||||||
interop.signExtend -> if (receiverTypeIndex > typeOperandIndex) {
|
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)
|
irFile, expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
interop.narrow -> if (receiverTypeIndex < typeOperandIndex) {
|
interop.narrow -> if (receiverTypeIndex < typeOperandIndex) {
|
||||||
context.reportCompilationError("unable to narrow ${receiver.type} to $typeOperand",
|
context.reportCompilationError("unable to narrow $receiverKotlinType to $kotlinTypeOperand",
|
||||||
irFile, expression)
|
irFile, expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -863,8 +887,12 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
val receiverClass = symbols.integerClasses.single {
|
val receiverClass = symbols.integerClasses.single {
|
||||||
receiver.type.isSubtypeOf(it.owner.defaultType)
|
receiver.type.isSubtypeOf(it.owner.defaultType)
|
||||||
}
|
}
|
||||||
|
val targetClass = symbols.integerClasses.single {
|
||||||
|
typeOperand.isSubtypeOf(it.owner.defaultType)
|
||||||
|
}
|
||||||
|
|
||||||
val conversionSymbol = receiverClass.functions.single {
|
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 {
|
builder.irCall(conversionSymbol).apply {
|
||||||
@@ -880,16 +908,16 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
|
|
||||||
returnType.checkCTypeNullability(::reportError)
|
returnType.checkCTypeNullability(::reportError)
|
||||||
|
|
||||||
val invokeImpl = symbols.interopInvokeImpls[TypeUtils.getClassDescriptor(returnType)] ?:
|
val invokeImpl = symbols.interopInvokeImpls[returnType.getClass()?.descriptor] ?:
|
||||||
context.reportCompilationError(
|
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
|
irFile, expression
|
||||||
)
|
)
|
||||||
|
|
||||||
builder.irCall(invokeImpl).apply {
|
builder.irCall(invokeImpl).apply {
|
||||||
putValueArgument(0, expression.extensionReceiver)
|
putValueArgument(0, expression.extensionReceiver)
|
||||||
|
|
||||||
val varargParameter = invokeImpl.descriptor.valueParameters[1]
|
val varargParameter = invokeImpl.owner.valueParameters[1]
|
||||||
val varargArgument = IrVarargImpl(
|
val varargArgument = IrVarargImpl(
|
||||||
startOffset, endOffset, varargParameter.type, varargParameter.varargElementType!!
|
startOffset, endOffset, varargParameter.type, varargParameter.varargElementType!!
|
||||||
).apply {
|
).apply {
|
||||||
@@ -897,7 +925,7 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
this.addElement(expression.getValueArgument(it)!!)
|
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)
|
this.checkCTypeNullability(reportError)
|
||||||
|
|
||||||
if (isReturnType && KotlinBuiltIns.isUnit(this)) {
|
if (isReturnType && this.isUnit()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KotlinBuiltIns.isPrimitiveType(this)) {
|
if (this.isPrimitiveType()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TypeUtils.getClassDescriptor(this) == interop.cPointer) {
|
if (this.getClass()?.descriptor == interop.cPointer) {
|
||||||
return
|
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) {
|
private fun IrType.checkCTypeNullability(reportError: (String) -> Nothing) {
|
||||||
if (KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType(this) && this.isMarkedNullable) {
|
if (this.isNullablePrimitiveType()) {
|
||||||
reportError("Type $this must not be nullable when used in C function signature")
|
reportError("Type ${this.toKotlinType()} must not be nullable when used in C function signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TypeUtils.getClassDescriptor(this) == interop.cPointer && !this.isMarkedNullable) {
|
if (this.getClass() == interop.cPointer && !this.isSimpleTypeWithQuestionMark) {
|
||||||
reportError("Type $this must be nullable when used in C function signature")
|
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()
|
val typeParameter = descriptor.original.typeParameters.single()
|
||||||
return getTypeArgument(typeParameter)!!
|
return getTypeArgument(typeParameter)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilder.irFloat(value: Float) =
|
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) =
|
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)
|
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.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
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.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
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.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
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.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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||||
@@ -59,6 +59,21 @@ internal class LateinitLowering(
|
|||||||
private val isInitializedGetterDescriptor = isInitializedPropertyDescriptor.getter!!
|
private val isInitializedGetterDescriptor = isInitializedPropertyDescriptor.getter!!
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
|
val lateinitPropertyToField = mutableMapOf<PropertyDescriptor, IrField>()
|
||||||
|
irFile.acceptVoid(object : IrElementVisitorVoid {
|
||||||
|
override fun visitElement(element: IrElement) {
|
||||||
|
element.acceptChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitProperty(declaration: IrProperty) {
|
||||||
|
super.visitProperty(declaration)
|
||||||
|
|
||||||
|
if (declaration.isLateinit && declaration.descriptor.kind.isReal) {
|
||||||
|
lateinitPropertyToField[declaration.descriptor] = declaration.backingField!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) {
|
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) {
|
||||||
|
|
||||||
override fun visitVariable(declaration: IrVariable): IrStatement {
|
override fun visitVariable(declaration: IrVariable): IrStatement {
|
||||||
@@ -85,10 +100,10 @@ internal class LateinitLowering(
|
|||||||
return irBlock(expression) {
|
return irBlock(expression) {
|
||||||
// TODO: do data flow analysis to check if value is proved to be not-null.
|
// TODO: do data flow analysis to check if value is proved to be not-null.
|
||||||
+irIfThen(
|
+irIfThen(
|
||||||
irEqualsNull(irGet(symbol)),
|
irEqualsNull(irGet(expression.type, symbol)),
|
||||||
throwUninitializedPropertyAccessException(symbol)
|
throwUninitializedPropertyAccessException(symbol)
|
||||||
)
|
)
|
||||||
+irGet(symbol)
|
+irGet(expression.type, symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,19 +116,13 @@ internal class LateinitLowering(
|
|||||||
|
|
||||||
val propertyReference = expression.extensionReceiver!! as IrPropertyReference
|
val propertyReference = expression.extensionReceiver!! as IrPropertyReference
|
||||||
assert(propertyReference.extensionReceiver == null, { "'lateinit' modifier is not allowed on extension properties" })
|
assert(propertyReference.extensionReceiver == null, { "'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 propertyDescriptor = propertyReference.descriptor.resolveFakeOverride().original
|
||||||
|
|
||||||
val type = propertyDescriptor.type
|
val type = propertyDescriptor.type
|
||||||
assert(!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" })
|
assert(!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" })
|
||||||
builder.at(expression).run {
|
builder.at(expression).run {
|
||||||
@Suppress("DEPRECATION")
|
val field = lateinitPropertyToField[propertyDescriptor]!!
|
||||||
val fieldValue = IrGetFieldImpl(
|
val fieldValue = irGetField(propertyReference.dispatchReceiver, field)
|
||||||
expression.startOffset,
|
|
||||||
expression.endOffset,
|
|
||||||
propertyDescriptor,
|
|
||||||
propertyReference.dispatchReceiver
|
|
||||||
)
|
|
||||||
return irNotEquals(fieldValue, irNull())
|
return irNotEquals(fieldValue, irNull())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,7 +134,7 @@ internal class LateinitLowering(
|
|||||||
return declaration
|
return declaration
|
||||||
|
|
||||||
val backingField = declaration.backingField!!
|
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" })
|
assert(backingField.initializer == null, { "'lateinit' modifier is not allowed for properties with initializer" })
|
||||||
val irBuilder = context.createIrBuilder(backingField.symbol, declaration.startOffset, declaration.endOffset)
|
val irBuilder = context.createIrBuilder(backingField.symbol, declaration.startOffset, declaration.endOffset)
|
||||||
@@ -136,20 +145,20 @@ internal class LateinitLowering(
|
|||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformGetter(backingFieldSymbol: IrFieldSymbol, getter: IrFunction) {
|
private fun transformGetter(backingField: IrField, getter: IrFunction) {
|
||||||
val type = backingFieldSymbol.descriptor.type
|
val type = backingField.descriptor.type
|
||||||
assert(!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" })
|
assert(!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" })
|
||||||
val irBuilder = context.createIrBuilder(getter.symbol, getter.startOffset, getter.endOffset)
|
val irBuilder = context.createIrBuilder(getter.symbol, getter.startOffset, getter.endOffset)
|
||||||
irBuilder.run {
|
irBuilder.run {
|
||||||
getter.body = irBlockBody {
|
getter.body = irBlockBody {
|
||||||
val resultVar = irTemporary(
|
val resultVar = irTemporary(
|
||||||
irGetField(getter.dispatchReceiverParameter?.let { irGet(it.symbol) }, backingFieldSymbol)
|
irGetField(getter.dispatchReceiverParameter?.let { irGet(it) }, backingField)
|
||||||
)
|
)
|
||||||
+irIfThenElse(
|
+irIfThenElse(
|
||||||
context.builtIns.nothingType,
|
context.irBuiltIns.nothingType,
|
||||||
irNotEquals(irGet(resultVar.symbol), irNull()),
|
irNotEquals(irGet(resultVar), irNull()),
|
||||||
irReturn(irGet(resultVar.symbol)),
|
irReturn(irGet(resultVar)),
|
||||||
throwUninitializedPropertyAccessException(backingFieldSymbol)
|
throwUninitializedPropertyAccessException(backingField.symbol)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,14 +167,14 @@ internal class LateinitLowering(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.throwUninitializedPropertyAccessException(backingFieldSymbol: IrSymbol) =
|
private fun IrBuilderWithScope.throwUninitializedPropertyAccessException(backingFieldSymbol: IrSymbol) =
|
||||||
irCall(throwErrorFunction).apply {
|
irCall(throwErrorFunction, context.irBuiltIns.nothingType).apply {
|
||||||
if (generateParameterNameInAssertion) {
|
if (generateParameterNameInAssertion) {
|
||||||
putValueArgument(
|
putValueArgument(
|
||||||
0,
|
0,
|
||||||
IrConstImpl.string(
|
IrConstImpl.string(
|
||||||
startOffset,
|
startOffset,
|
||||||
endOffset,
|
endOffset,
|
||||||
context.builtIns.stringType,
|
context.irBuiltIns.stringType,
|
||||||
backingFieldSymbol.descriptor.name.asString()
|
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.IrBuildingTransformer
|
||||||
import org.jetbrains.kotlin.backend.common.lower.at
|
import org.jetbrains.kotlin.backend.common.lower.at
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
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.backend.konan.reportCompilationError
|
||||||
import org.jetbrains.kotlin.ir.builders.irCall
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,7 +46,7 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
|||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
builder.at(expression)
|
builder.at(expression)
|
||||||
|
|
||||||
val typeArgument = expression.descriptor.defaultType
|
val typeArgument = expression.symbol.typeWithStarProjections
|
||||||
|
|
||||||
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
|
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
|
||||||
putValueArgument(0, builder.irCall(symbols.getClassTypeInfo, listOf(typeArgument)))
|
putValueArgument(0, builder.irCall(symbols.getClassTypeInfo, listOf(typeArgument)))
|
||||||
@@ -54,7 +57,7 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
|||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
builder.at(expression)
|
builder.at(expression)
|
||||||
|
|
||||||
val typeArgument = expression.type.arguments.single().type
|
val typeArgument = expression.argument.type
|
||||||
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
|
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
|
||||||
val typeInfo = builder.irCall(symbols.getObjectTypeInfo).apply {
|
val typeInfo = builder.irCall(symbols.getObjectTypeInfo).apply {
|
||||||
putValueArgument(0, expression.argument)
|
putValueArgument(0, expression.argument)
|
||||||
@@ -95,7 +98,7 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
|||||||
}
|
}
|
||||||
expression.putValueArgument(0, IrConstImpl<String>(
|
expression.putValueArgument(0, IrConstImpl<String>(
|
||||||
expression.startOffset, expression.endOffset,
|
expression.startOffset, expression.endOffset,
|
||||||
context.ir.symbols.immutableBinaryBlob.descriptor.defaultType,
|
context.ir.symbols.immutableBinaryBlob.typeWithoutArguments,
|
||||||
IrConstKind.String, builder.toString()))
|
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.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
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.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This pass runs before inlining and performs the following additional transformations over some operations:
|
* 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
|
package org.jetbrains.kotlin.backend.konan.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.*
|
import org.jetbrains.kotlin.backend.common.*
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.getFunction
|
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.ir.createOverriddenDescriptor
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
@@ -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.IrSuspendableExpressionImpl
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.IrSuspensionPoint
|
import org.jetbrains.kotlin.backend.konan.ir.IrSuspensionPoint
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.IrSuspensionPointImpl
|
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.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
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.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||||
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.descriptors.IrTemporaryVariableDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
@@ -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.IrConstructorSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
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.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
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 {
|
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 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 val returnIfSuspendedDescriptor = context.getInternalFunctions("returnIfSuspended").single()
|
||||||
|
|
||||||
private fun removeReturnIfSuspendedCallAndSimplifyDelegatingCall(irFunction: IrFunction, delegatingCall: IrCall) {
|
private fun removeReturnIfSuspendedCallAndSimplifyDelegatingCall(irFunction: IrFunction, delegatingCall: IrCall) {
|
||||||
@@ -245,7 +240,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
putValueArgument(index, irGet(argument))
|
putValueArgument(index, irGet(argument))
|
||||||
}
|
}
|
||||||
putValueArgument(functionParameters.size,
|
putValueArgument(functionParameters.size,
|
||||||
irCall(getContinuationSymbol, listOf(descriptor.returnType!!)))
|
irCall(getContinuation, listOf(irFunction.returnType)))
|
||||||
}
|
}
|
||||||
putValueArgument(0, irGetObject(symbols.unit)) // value
|
putValueArgument(0, irGetObject(symbols.unit)) // value
|
||||||
putValueArgument(1, irNull()) // exception
|
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 coroutinesScope = context.irModule!!.descriptor.getPackage(COROUTINES_FQ_NAME).memberScope
|
||||||
private val kotlinPackageScope = context.irModule!!.descriptor.getPackage(KOTLIN_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 inner class CoroutineBuilder(val irFunction: IrFunction, val functionReference: IrFunctionReference?) {
|
||||||
|
|
||||||
private val functionParameters = irFunction.descriptor.explicitParameters
|
private val functionParameters = irFunction.explicitParameters
|
||||||
private val boundFunctionParameters = functionReference?.getArguments()?.map { it.first }
|
private val boundFunctionParameters = functionReference?.getArgumentsWithIr()?.map { it.first }
|
||||||
private val unboundFunctionParameters = boundFunctionParameters?.let { functionParameters - it }
|
private val unboundFunctionParameters = boundFunctionParameters?.let { functionParameters - it }
|
||||||
|
|
||||||
private var tempIndex = 0
|
private var tempIndex = 0
|
||||||
private var suspensionPointIdIndex = 0
|
private var suspensionPointIdIndex = 0
|
||||||
private lateinit var suspendResult: IrVariableSymbol
|
private lateinit var suspendResult: IrVariable
|
||||||
private lateinit var dataArgument: IrValueParameterSymbol
|
private lateinit var dataArgument: IrValueParameter
|
||||||
private lateinit var exceptionArgument: IrValueParameterSymbol
|
private lateinit var exceptionArgument: IrValueParameter
|
||||||
private lateinit var coroutineClassDescriptor: ClassDescriptorImpl
|
private lateinit var coroutineClassDescriptor: ClassDescriptorImpl
|
||||||
private lateinit var coroutineClass: IrClassImpl
|
private lateinit var coroutineClass: IrClassImpl
|
||||||
private lateinit var coroutineClassThis: IrValueParameterSymbol
|
private lateinit var coroutineClassThis: IrValueParameter
|
||||||
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrFieldSymbol>
|
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrField>
|
||||||
|
|
||||||
private val coroutineImplSymbol = symbols.coroutineImpl
|
private val coroutineImplSymbol = symbols.coroutineImpl
|
||||||
private val coroutineImplConstructorSymbol = coroutineImplSymbol.constructors.single()
|
private val coroutineImplConstructorSymbol = coroutineImplSymbol.constructors.single()
|
||||||
private val coroutineImplClassDescriptor = coroutineImplSymbol.descriptor
|
private val coroutineImplClassDescriptor = coroutineImplSymbol.descriptor
|
||||||
private val create1FunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
private val create1Function = coroutineImplSymbol.owner.simpleFunctions()
|
||||||
.getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND)
|
.single { it.name.asString() == "create" && it.valueParameters.size == 1 }
|
||||||
.single { it.valueParameters.size == 1 }
|
private val create1CompletionParameter = create1Function.valueParameters[0]
|
||||||
private val create1CompletionParameter = create1FunctionDescriptor.valueParameters[0]
|
|
||||||
|
|
||||||
private val coroutineImplLabelGetterSymbol = coroutineImplSymbol.getPropertyGetter("label")!!
|
private val coroutineImplLabelGetterSymbol = coroutineImplSymbol.getPropertyGetter("label")!!
|
||||||
private val coroutineImplLabelSetterSymbol = coroutineImplSymbol.getPropertySetter("label")!!
|
private val coroutineImplLabelSetterSymbol = coroutineImplSymbol.getPropertySetter("label")!!
|
||||||
|
|
||||||
fun build(): BuiltCoroutine {
|
fun build(): BuiltCoroutine {
|
||||||
val superTypes = mutableListOf<KotlinType>(coroutineImplClassDescriptor.defaultType)
|
val superTypes = mutableListOf<IrType>(coroutineImplSymbol.owner.defaultType)
|
||||||
val superClasses = mutableListOf<IrClass>(coroutineImplSymbol.owner)
|
var suspendFunctionClass: IrClass? = null
|
||||||
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
var functionClass: IrClass? = null
|
||||||
var functionClassDescriptor: ClassDescriptor? = null
|
var suspendFunctionClassTypeArguments: List<IrType>? = null
|
||||||
var suspendFunctionClassTypeArguments: List<KotlinType>? = null
|
var functionClassTypeArguments: List<IrType>? = null
|
||||||
var functionClassTypeArguments: List<KotlinType>? = null
|
|
||||||
if (unboundFunctionParameters != null) {
|
if (unboundFunctionParameters != null) {
|
||||||
// Suspend lambda inherits SuspendFunction.
|
// Suspend lambda inherits SuspendFunction.
|
||||||
val numberOfParameters = unboundFunctionParameters.size
|
val numberOfParameters = unboundFunctionParameters.size
|
||||||
suspendFunctionClassDescriptor = kotlinPackageScope.getContributedClassifier(
|
suspendFunctionClass = context.ir.symbols.suspendFunctions[numberOfParameters].owner
|
||||||
Name.identifier("SuspendFunction$numberOfParameters"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
|
||||||
val unboundParameterTypes = unboundFunctionParameters.map { it.type }
|
val unboundParameterTypes = unboundFunctionParameters.map { it.type }
|
||||||
suspendFunctionClassTypeArguments = unboundParameterTypes + irFunction.descriptor.returnType!!
|
suspendFunctionClassTypeArguments = unboundParameterTypes + irFunction.returnType
|
||||||
superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeArguments)
|
superTypes += suspendFunctionClass.typeWith(suspendFunctionClassTypeArguments)
|
||||||
superClasses += context.ir.symbols.suspendFunctions[numberOfParameters].owner
|
|
||||||
|
|
||||||
functionClassDescriptor = kotlinPackageScope.getContributedClassifier(
|
functionClass = context.ir.symbols.functions[numberOfParameters + 1].owner
|
||||||
Name.identifier("Function${numberOfParameters + 1}"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
val continuationType = continuationClassSymbol.typeWith(irFunction.returnType)
|
||||||
val continuationType = continuationClassDescriptor.defaultType.replace(listOf(irFunction.descriptor.returnType!!))
|
functionClassTypeArguments = unboundParameterTypes + continuationType + context.irBuiltIns.anyNType
|
||||||
functionClassTypeArguments = unboundParameterTypes + continuationType + context.builtIns.nullableAnyType
|
superTypes += functionClass.typeWith(functionClassTypeArguments)
|
||||||
superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeArguments)
|
|
||||||
superClasses += context.ir.symbols.functions[numberOfParameters + 1].owner
|
|
||||||
|
|
||||||
}
|
}
|
||||||
coroutineClassDescriptor = ClassDescriptorImpl(
|
coroutineClassDescriptor = ClassDescriptorImpl(
|
||||||
@@ -328,11 +314,13 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
/* name = */ "${irFunction.descriptor.name}\$${coroutineId++}".synthesizedName,
|
/* name = */ "${irFunction.descriptor.name}\$${coroutineId++}".synthesizedName,
|
||||||
/* modality = */ Modality.FINAL,
|
/* modality = */ Modality.FINAL,
|
||||||
/* kind = */ ClassKind.CLASS,
|
/* kind = */ ClassKind.CLASS,
|
||||||
/* superTypes = */ superTypes,
|
/* superTypes = */ superTypes.map { it.toKotlinType() },
|
||||||
/* source = */ SourceElement.NO_SOURCE,
|
/* source = */ SourceElement.NO_SOURCE,
|
||||||
/* isExternal = */ false,
|
/* isExternal = */ false,
|
||||||
/* storageManager = */ LockBasedStorageManager.NO_LOCKS
|
/* storageManager = */ LockBasedStorageManager.NO_LOCKS
|
||||||
)
|
).also {
|
||||||
|
it.initialize(stub("coroutine class"), stub("coroutine class constructors"), null)
|
||||||
|
}
|
||||||
coroutineClass = IrClassImpl(
|
coroutineClass = IrClassImpl(
|
||||||
startOffset = irFunction.startOffset,
|
startOffset = irFunction.startOffset,
|
||||||
endOffset = irFunction.endOffset,
|
endOffset = irFunction.endOffset,
|
||||||
@@ -340,17 +328,19 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
descriptor = coroutineClassDescriptor
|
descriptor = coroutineClassDescriptor
|
||||||
)
|
)
|
||||||
coroutineClass.parent = irFunction.parent
|
coroutineClass.parent = irFunction.parent
|
||||||
|
coroutineClass.createParameterDeclarations()
|
||||||
|
coroutineClassThis = coroutineClass.thisReceiver!!
|
||||||
|
|
||||||
|
|
||||||
val overriddenMap = mutableMapOf<CallableMemberDescriptor, CallableMemberDescriptor>()
|
val overriddenMap = mutableMapOf<CallableMemberDescriptor, CallableMemberDescriptor>()
|
||||||
val constructors = mutableSetOf<ClassConstructorDescriptor>()
|
|
||||||
val coroutineConstructorBuilder = createConstructorBuilder()
|
val coroutineConstructorBuilder = createConstructorBuilder()
|
||||||
constructors.add(coroutineConstructorBuilder.symbol.descriptor)
|
coroutineConstructorBuilder.initialize()
|
||||||
|
|
||||||
val doResumeFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
val doResumeFunction = coroutineImplSymbol.owner.simpleFunctions()
|
||||||
.getContributedFunctions(Name.identifier("doResume"), NoLookupLocation.FROM_BACKEND).single()
|
.single { it.name.asString() == "doResume" }
|
||||||
val doResumeMethodBuilder = createDoResumeMethodBuilder(doResumeFunctionDescriptor)
|
val doResumeMethodBuilder = createDoResumeMethodBuilder(doResumeFunction, coroutineClass)
|
||||||
overriddenMap += doResumeFunctionDescriptor to doResumeMethodBuilder.symbol.descriptor
|
doResumeMethodBuilder.initialize()
|
||||||
|
overriddenMap += doResumeFunction.descriptor to doResumeMethodBuilder.symbol.descriptor
|
||||||
|
|
||||||
var coroutineFactoryConstructorBuilder: SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>? = null
|
var coroutineFactoryConstructorBuilder: SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>? = null
|
||||||
var createMethodBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>? = null
|
var createMethodBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>? = null
|
||||||
@@ -358,7 +348,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
if (functionReference != null) {
|
if (functionReference != null) {
|
||||||
// Suspend lambda - create factory methods.
|
// Suspend lambda - create factory methods.
|
||||||
coroutineFactoryConstructorBuilder = createFactoryConstructorBuilder(boundFunctionParameters!!)
|
coroutineFactoryConstructorBuilder = createFactoryConstructorBuilder(boundFunctionParameters!!)
|
||||||
constructors.add(coroutineFactoryConstructorBuilder.symbol.descriptor)
|
|
||||||
|
|
||||||
val createFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
val createFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
||||||
.getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND)
|
.getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND)
|
||||||
@@ -366,27 +355,24 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
createMethodBuilder = createCreateMethodBuilder(
|
createMethodBuilder = createCreateMethodBuilder(
|
||||||
unboundArgs = unboundFunctionParameters!!,
|
unboundArgs = unboundFunctionParameters!!,
|
||||||
superFunctionDescriptor = createFunctionDescriptor,
|
superFunctionDescriptor = createFunctionDescriptor,
|
||||||
coroutineConstructorSymbol = coroutineConstructorBuilder.symbol)
|
coroutineConstructor = coroutineConstructorBuilder.ir,
|
||||||
|
coroutineClass = coroutineClass)
|
||||||
|
createMethodBuilder.initialize()
|
||||||
if (createFunctionDescriptor != null)
|
if (createFunctionDescriptor != null)
|
||||||
overriddenMap += createFunctionDescriptor to createMethodBuilder.symbol.descriptor
|
overriddenMap += createFunctionDescriptor to createMethodBuilder.symbol.descriptor
|
||||||
|
|
||||||
val invokeFunctionDescriptor = functionClassDescriptor!!.getFunction("invoke", functionClassTypeArguments!!)
|
val invokeFunctionDescriptor = functionClass!!.descriptor
|
||||||
val suspendInvokeFunctionDescriptor = suspendFunctionClassDescriptor!!.getFunction("invoke", suspendFunctionClassTypeArguments!!)
|
.getFunction("invoke", functionClassTypeArguments!!.map { it.toKotlinType() })
|
||||||
|
val suspendInvokeFunctionDescriptor = suspendFunctionClass!!.descriptor
|
||||||
|
.getFunction("invoke", suspendFunctionClassTypeArguments!!.map { it.toKotlinType() })
|
||||||
invokeMethodBuilder = createInvokeMethodBuilder(
|
invokeMethodBuilder = createInvokeMethodBuilder(
|
||||||
suspendFunctionInvokeFunctionDescriptor = suspendInvokeFunctionDescriptor,
|
suspendFunctionInvokeFunctionDescriptor = suspendInvokeFunctionDescriptor,
|
||||||
functionInvokeFunctionDescriptor = invokeFunctionDescriptor,
|
functionInvokeFunctionDescriptor = invokeFunctionDescriptor,
|
||||||
createFunctionSymbol = createMethodBuilder.symbol,
|
createFunction = createMethodBuilder.ir,
|
||||||
doResumeFunctionSymbol = doResumeMethodBuilder.symbol)
|
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)
|
coroutineClass.addChild(coroutineConstructorBuilder.ir)
|
||||||
|
|
||||||
coroutineFactoryConstructorBuilder?.let {
|
coroutineFactoryConstructorBuilder?.let {
|
||||||
@@ -395,7 +381,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
}
|
}
|
||||||
|
|
||||||
createMethodBuilder?.let {
|
createMethodBuilder?.let {
|
||||||
it.initialize()
|
|
||||||
coroutineClass.addChild(it.ir)
|
coroutineClass.addChild(it.ir)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,10 +389,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
coroutineClass.addChild(it.ir)
|
coroutineClass.addChild(it.ir)
|
||||||
}
|
}
|
||||||
|
|
||||||
doResumeMethodBuilder.initialize()
|
|
||||||
coroutineClass.addChild(doResumeMethodBuilder.ir)
|
coroutineClass.addChild(doResumeMethodBuilder.ir)
|
||||||
|
|
||||||
coroutineClass.setSuperSymbolsAndAddFakeOverrides(superClasses)
|
coroutineClass.setSuperSymbolsAndAddFakeOverrides(superTypes)
|
||||||
|
|
||||||
return BuiltCoroutine(
|
return BuiltCoroutine(
|
||||||
coroutineClass = coroutineClass,
|
coroutineClass = coroutineClass,
|
||||||
@@ -428,21 +412,30 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private lateinit var constructorParameters: List<IrValueParameter>
|
||||||
|
|
||||||
override fun doInitialize() {
|
override fun doInitialize() {
|
||||||
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||||
val constructorParameters = (
|
constructorParameters = (
|
||||||
functionParameters
|
functionParameters
|
||||||
+ coroutineImplConstructorSymbol.descriptor.valueParameters[0] // completion.
|
+ coroutineImplConstructorSymbol.owner.valueParameters[0] // completion.
|
||||||
).mapIndexed { index, parameter -> parameter.copyAsValueParameter(descriptor, index) }
|
).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
|
descriptor.returnType = coroutineClassDescriptor.defaultType
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun buildIr(): IrConstructor {
|
override fun buildIr(): IrConstructor {
|
||||||
// Save all arguments to fields.
|
// Save all arguments to fields.
|
||||||
argumentToPropertiesMap = functionParameters.associate {
|
argumentToPropertiesMap = functionParameters.associate {
|
||||||
it to buildPropertyWithBackingField(it.name, it.type, false)
|
it.descriptor to addField(it.name, it.type, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
val startOffset = irFunction.startOffset
|
val startOffset = irFunction.startOffset
|
||||||
@@ -453,25 +446,32 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||||
symbol = symbol).apply {
|
symbol = symbol).apply {
|
||||||
|
|
||||||
createParameterDeclarations()
|
returnType = coroutineClass.defaultType
|
||||||
|
|
||||||
|
this.valueParameters += constructorParameters
|
||||||
|
|
||||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||||
body = irBuilder.irBlockBody {
|
body = irBuilder.irBlockBody {
|
||||||
val completionParameter = valueParameters.last()
|
val completionParameter = valueParameters.last()
|
||||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||||
|
context.irBuiltIns.unitType,
|
||||||
coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply {
|
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 ->
|
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>() {
|
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
||||||
|
|
||||||
override fun buildSymbol() = IrConstructorSymbolImpl(
|
override fun buildSymbol() = IrConstructorSymbolImpl(
|
||||||
@@ -483,12 +483,18 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
lateinit var constructorParameters: List<IrValueParameter>
|
||||||
|
|
||||||
override fun doInitialize() {
|
override fun doInitialize() {
|
||||||
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||||
val constructorParameters = boundParams.mapIndexed { index, parameter ->
|
constructorParameters = boundParams.mapIndexed { index, parameter ->
|
||||||
parameter.copyAsValueParameter(descriptor, index)
|
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
|
descriptor.returnType = coroutineClassDescriptor.defaultType
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,27 +507,32 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||||
symbol = symbol).apply {
|
symbol = symbol).apply {
|
||||||
|
|
||||||
createParameterDeclarations()
|
returnType = coroutineClass.defaultType
|
||||||
|
|
||||||
|
this.valueParameters += constructorParameters
|
||||||
|
|
||||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||||
body = irBuilder.irBlockBody {
|
body = irBuilder.irBlockBody {
|
||||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
+IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType,
|
||||||
coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply {
|
coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply {
|
||||||
putValueArgument(0, irNull()) // Completion.
|
putValueArgument(0, irNull()) // Completion.
|
||||||
}
|
}
|
||||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol)
|
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol,
|
||||||
|
context.irBuiltIns.unitType)
|
||||||
// Save all arguments to fields.
|
// Save all arguments to fields.
|
||||||
boundParams.forEachIndexed { index, parameter ->
|
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?,
|
superFunctionDescriptor: FunctionDescriptor?,
|
||||||
coroutineConstructorSymbol: IrConstructorSymbol)
|
coroutineConstructor: IrConstructor,
|
||||||
|
coroutineClass: IrClass)
|
||||||
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||||
|
|
||||||
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||||
@@ -534,19 +545,21 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
lateinit var parameters: List<IrValueParameter>
|
||||||
|
|
||||||
override fun doInitialize() {
|
override fun doInitialize() {
|
||||||
val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl
|
val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl
|
||||||
val valueParameters = (
|
parameters = (
|
||||||
unboundArgs + create1CompletionParameter
|
unboundArgs + create1CompletionParameter
|
||||||
).mapIndexed { index, parameter ->
|
).mapIndexed { index, parameter ->
|
||||||
parameter.copyAsValueParameter(descriptor, index)
|
parameter.copy(parameter.descriptor.copyAsValueParameter(descriptor, index))
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor.initialize(
|
descriptor.initialize(
|
||||||
/* receiverParameterType = */ null,
|
/* receiverParameterType = */ null,
|
||||||
/* dispatchReceiverParameter = */ coroutineClassDescriptor.thisAsReceiverParameter,
|
/* dispatchReceiverParameter = */ coroutineClassDescriptor.thisAsReceiverParameter,
|
||||||
/* typeParameters = */ emptyList(),
|
/* typeParameters = */ emptyList(),
|
||||||
/* unsubstitutedValueParameters = */ valueParameters,
|
/* unsubstitutedValueParameters = */ parameters.map { it.descriptor as ValueParameterDescriptor },
|
||||||
/* unsubstitutedReturnType = */ coroutineClassDescriptor.defaultType,
|
/* unsubstitutedReturnType = */ coroutineClassDescriptor.defaultType,
|
||||||
/* modality = */ Modality.FINAL,
|
/* modality = */ Modality.FINAL,
|
||||||
/* visibility = */ Visibilities.PRIVATE).apply {
|
/* visibility = */ Visibilities.PRIVATE).apply {
|
||||||
@@ -566,25 +579,29 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||||
symbol = symbol).apply {
|
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)
|
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||||
+irReturn(
|
+irReturn(
|
||||||
irCall(coroutineConstructorSymbol).apply {
|
irCall(coroutineConstructor).apply {
|
||||||
var unboundIndex = 0
|
var unboundIndex = 0
|
||||||
val unboundArgsSet = unboundArgs.toSet()
|
val unboundArgsSet = unboundArgs.toSet()
|
||||||
functionParameters.map {
|
functionParameters.map {
|
||||||
if (unboundArgsSet.contains(it))
|
if (unboundArgsSet.contains(it))
|
||||||
irGet(valueParameters[unboundIndex++].symbol)
|
irGet(valueParameters[unboundIndex++])
|
||||||
else
|
else
|
||||||
irGetField(irGet(thisReceiver), argumentToPropertiesMap[it]!!)
|
irGetField(irGet(thisReceiver), argumentToPropertiesMap[it.descriptor]!!)
|
||||||
}.forEachIndexed { index, argument ->
|
}.forEachIndexed { index, argument ->
|
||||||
putValueArgument(index, argument)
|
putValueArgument(index, argument)
|
||||||
}
|
}
|
||||||
putValueArgument(functionParameters.size, irGet(valueParameters[unboundIndex].symbol))
|
putValueArgument(functionParameters.size, irGet(valueParameters[unboundIndex]))
|
||||||
assert(unboundIndex == valueParameters.size - 1,
|
assert(unboundIndex == valueParameters.size - 1,
|
||||||
{ "Not all arguments of <create> are used" })
|
{ "Not all arguments of <create> are used" })
|
||||||
})
|
})
|
||||||
@@ -595,8 +612,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
|
|
||||||
private fun createInvokeMethodBuilder(suspendFunctionInvokeFunctionDescriptor: FunctionDescriptor,
|
private fun createInvokeMethodBuilder(suspendFunctionInvokeFunctionDescriptor: FunctionDescriptor,
|
||||||
functionInvokeFunctionDescriptor: FunctionDescriptor,
|
functionInvokeFunctionDescriptor: FunctionDescriptor,
|
||||||
createFunctionSymbol: IrFunctionSymbol,
|
createFunction: IrFunction,
|
||||||
doResumeFunctionSymbol: IrFunctionSymbol)
|
doResumeFunction: IrFunction,
|
||||||
|
coroutineClass: IrClass)
|
||||||
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||||
|
|
||||||
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||||
@@ -609,18 +627,20 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
lateinit var parameters: List<IrValueParameter>
|
||||||
|
|
||||||
override fun doInitialize() {
|
override fun doInitialize() {
|
||||||
val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl
|
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.
|
// Skip completion - invoke() already has it implicitly as a suspend function.
|
||||||
.take(createFunctionSymbol.descriptor.valueParameters.size - 1)
|
.take(createFunction.valueParameters.size - 1)
|
||||||
.map { it.copyAsValueParameter(descriptor, it.index) }
|
.map { it.copy(it.descriptor.copyAsValueParameter(descriptor, it.index)) }
|
||||||
|
|
||||||
descriptor.initialize(
|
descriptor.initialize(
|
||||||
/* receiverParameterType = */ null,
|
/* receiverParameterType = */ null,
|
||||||
/* dispatchReceiverParameter = */ coroutineClassDescriptor.thisAsReceiverParameter,
|
/* dispatchReceiverParameter = */ coroutineClassDescriptor.thisAsReceiverParameter,
|
||||||
/* typeParameters = */ emptyList(),
|
/* typeParameters = */ emptyList(),
|
||||||
/* unsubstitutedValueParameters = */ valueParameters,
|
/* unsubstitutedValueParameters = */ parameters.map { it.descriptor as ValueParameterDescriptor },
|
||||||
/* unsubstitutedReturnType = */ irFunction.descriptor.returnType,
|
/* unsubstitutedReturnType = */ irFunction.descriptor.returnType,
|
||||||
/* modality = */ Modality.FINAL,
|
/* modality = */ Modality.FINAL,
|
||||||
/* visibility = */ Visibilities.PRIVATE).apply {
|
/* visibility = */ Visibilities.PRIVATE).apply {
|
||||||
@@ -639,21 +659,25 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||||
symbol = symbol).apply {
|
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)
|
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||||
+irReturn(
|
+irReturn(
|
||||||
irCall(doResumeFunctionSymbol).apply {
|
irCall(doResumeFunction).apply {
|
||||||
dispatchReceiver = irCall(createFunctionSymbol).apply {
|
dispatchReceiver = irCall(createFunction).apply {
|
||||||
dispatchReceiver = irGet(thisReceiver)
|
dispatchReceiver = irGet(thisReceiver)
|
||||||
valueParameters.forEachIndexed { index, parameter ->
|
valueParameters.forEachIndexed { index, parameter ->
|
||||||
putValueArgument(index, irGet(parameter.symbol))
|
putValueArgument(index, irGet(parameter))
|
||||||
}
|
}
|
||||||
putValueArgument(valueParameters.size,
|
putValueArgument(valueParameters.size,
|
||||||
irCall(getContinuationSymbol, listOf(symbol.descriptor.returnType!!)))
|
irCall(getContinuation, listOf(returnType)))
|
||||||
}
|
}
|
||||||
putValueArgument(0, irGetObject(symbols.unit)) // value
|
putValueArgument(0, irGetObject(symbols.unit)) // value
|
||||||
putValueArgument(1, irNull()) // exception
|
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 {
|
private fun addField(name: Name, type: IrType, isMutable: Boolean): IrField = createField(
|
||||||
val propertyBuilder = context.createPropertyWithBackingFieldBuilder(
|
irFunction.startOffset,
|
||||||
startOffset = irFunction.startOffset,
|
irFunction.endOffset,
|
||||||
endOffset = irFunction.endOffset,
|
type,
|
||||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
name,
|
||||||
owner = coroutineClassDescriptor,
|
isMutable,
|
||||||
name = name,
|
DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||||
type = type,
|
coroutineClassDescriptor
|
||||||
isMutable = isMutable).apply {
|
).also {
|
||||||
initialize()
|
coroutineClass.addChild(it)
|
||||||
}
|
|
||||||
|
|
||||||
coroutineClass.addChild(propertyBuilder.ir)
|
|
||||||
return propertyBuilder.symbol
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createDoResumeMethodBuilder(doResumeFunctionDescriptor: FunctionDescriptor)
|
private fun createDoResumeMethodBuilder(doResumeFunction: IrFunction, coroutineClass: IrClass)
|
||||||
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||||
|
|
||||||
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||||
doResumeFunctionDescriptor.createOverriddenDescriptor(coroutineClassDescriptor)
|
doResumeFunction.descriptor.createOverriddenDescriptor(coroutineClassDescriptor)
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun doInitialize() { }
|
override fun doInitialize() { }
|
||||||
@@ -699,58 +719,76 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
origin = DECLARATION_ORIGIN_COROUTINE_IMPL,
|
||||||
symbol = symbol).apply {
|
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
|
dataArgument = function.valueParameters[0]
|
||||||
exceptionArgument = function.valueParameters[1].symbol
|
exceptionArgument = function.valueParameters[1]
|
||||||
suspendResult = IrVariableSymbolImpl(
|
|
||||||
IrTemporaryVariableDescriptorImpl(
|
val label = coroutineImplSymbol.owner.declarations.filterIsInstance<IrProperty>()
|
||||||
containingDeclaration = irFunction.descriptor,
|
.single { it.name.asString() == "label" }
|
||||||
name = "suspendResult".synthesizedName,
|
|
||||||
outType = context.builtIns.nullableAnyType,
|
|
||||||
isMutable = true)
|
|
||||||
)
|
|
||||||
val label = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
|
||||||
.getContributedVariables(Name.identifier("label"), NoLookupLocation.FROM_BACKEND).single()
|
|
||||||
|
|
||||||
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
||||||
function.body = irBuilder.irBlockBody(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.
|
// 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 liveLocals = computeLivenessAtSuspensionPoints(originalBody)
|
||||||
|
|
||||||
val immutableLiveLocals = liveLocals.values.flatten().filterNot { it.descriptor.isVar }.toSet()
|
val immutableLiveLocals = liveLocals.values.flatten().filterNot { it.descriptor.isVar }.toSet()
|
||||||
val localsMap = immutableLiveLocals.associate {
|
val localsMap = immutableLiveLocals.associate {
|
||||||
// TODO: Remove .descriptor as soon as all symbols are bound.
|
// TODO: Remove .descriptor as soon as all symbols are bound.
|
||||||
it.descriptor to IrVariableSymbolImpl(
|
val symbol = IrVariableSymbolImpl(
|
||||||
IrTemporaryVariableDescriptorImpl(
|
IrTemporaryVariableDescriptorImpl(
|
||||||
containingDeclaration = irFunction.descriptor,
|
containingDeclaration = irFunction.descriptor,
|
||||||
name = it.descriptor.name,
|
name = it.descriptor.name,
|
||||||
outType = it.descriptor.type,
|
outType = it.descriptor.type,
|
||||||
isMutable = true)
|
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())
|
if (localsMap.isNotEmpty())
|
||||||
transformVariables(originalBody, localsMap) // Make variables mutable in order to save/restore them.
|
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.
|
// TODO: optimize by using the same property for different locals.
|
||||||
liveLocals.values.forEach { scope ->
|
liveLocals.values.forEach { scope ->
|
||||||
scope.forEach {
|
scope.forEach {
|
||||||
localToPropertyMap.getOrPut(it) {
|
localToPropertyMap.getOrPut(it.symbol) {
|
||||||
buildPropertyWithBackingField(it.descriptor.name, it.descriptor.type, true)
|
addField(it.descriptor.name, it.type, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
originalBody.transformChildrenVoid(object : IrElementTransformerVoid() {
|
originalBody.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
|
|
||||||
private val thisReceiver = function.dispatchReceiverParameter!!.symbol
|
private val thisReceiver = function.dispatchReceiverParameter!!
|
||||||
|
|
||||||
// Replace returns to refer to the new function.
|
// Replace returns to refer to the new function.
|
||||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||||
@@ -783,23 +821,24 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
when (expression.symbol) {
|
when (expression.symbol) {
|
||||||
saveStateSymbol -> {
|
saveState.symbol -> {
|
||||||
val scope = liveLocals[suspensionPoint]!!
|
val scope = liveLocals[suspensionPoint]!!
|
||||||
return irBlock(expression) {
|
return irBlock(expression) {
|
||||||
scope.forEach {
|
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 {
|
+irCall(coroutineImplLabelSetterSymbol).apply {
|
||||||
dispatchReceiver = irGet(thisReceiver)
|
dispatchReceiver = irGet(thisReceiver)
|
||||||
putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter.symbol))
|
putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
restoreStateSymbol -> {
|
restoreState.symbol -> {
|
||||||
val scope = liveLocals[suspensionPoint]!!
|
val scope = liveLocals[suspensionPoint]!!
|
||||||
return irBlock(expression) {
|
return irBlock(expression) {
|
||||||
scope.forEach {
|
scope.forEach {
|
||||||
+irSetVar(localsMap[it.descriptor] ?: it, irGetField(irGet(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
|
val statements = (originalBody as IrBlockBody).statements
|
||||||
+irVar(suspendResult, null)
|
+suspendResult
|
||||||
+IrSuspendableExpressionImpl(
|
+IrSuspendableExpressionImpl(
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
type = context.builtIns.unitType,
|
type = context.irBuiltIns.unitType,
|
||||||
suspensionPointId = irCall(coroutineImplLabelGetterSymbol).apply {
|
suspensionPointId = irCall(coroutineImplLabelGetterSymbol).apply {
|
||||||
dispatchReceiver = irGet(function.dispatchReceiverParameter!!.symbol)
|
dispatchReceiver = irGet(function.dispatchReceiverParameter!!)
|
||||||
},
|
},
|
||||||
result = irBlock(startOffset, endOffset) {
|
result = irBlock(startOffset, endOffset) {
|
||||||
+irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception.
|
+irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception.
|
||||||
statements.forEach { +it }
|
statements.forEach { +it }
|
||||||
})
|
})
|
||||||
if (irFunction.descriptor.returnType!!.isUnit())
|
if (irFunction.returnType.isUnit())
|
||||||
+irReturn(irGetObject(symbols.unit)) // Insert explicit return for Unit functions.
|
+irReturn(irGetObject(symbols.unit)) // Insert explicit return for Unit functions.
|
||||||
}
|
}
|
||||||
return function
|
return function
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformVariables(element: IrElement, variablesMap: Map<VariableDescriptor, IrVariableSymbol>) {
|
private fun transformVariables(element: IrElement, variablesMap: Map<VariableDescriptor, IrVariable>) {
|
||||||
element.transformChildrenVoid(object: IrElementTransformerVoid() {
|
element.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||||
|
|
||||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||||
@@ -843,7 +882,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
return IrGetValueImpl(
|
return IrGetValueImpl(
|
||||||
startOffset = expression.startOffset,
|
startOffset = expression.startOffset,
|
||||||
endOffset = expression.endOffset,
|
endOffset = expression.endOffset,
|
||||||
symbol = newVariable,
|
type = newVariable.type,
|
||||||
|
symbol = newVariable.symbol,
|
||||||
origin = expression.origin)
|
origin = expression.origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -856,7 +896,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
return IrSetVariableImpl(
|
return IrSetVariableImpl(
|
||||||
startOffset = expression.startOffset,
|
startOffset = expression.startOffset,
|
||||||
endOffset = expression.endOffset,
|
endOffset = expression.endOffset,
|
||||||
symbol = newVariable,
|
type = context.irBuiltIns.unitType,
|
||||||
|
symbol = newVariable.symbol,
|
||||||
value = expression.value,
|
value = expression.value,
|
||||||
origin = expression.origin)
|
origin = expression.origin)
|
||||||
}
|
}
|
||||||
@@ -867,21 +908,17 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
val newVariable = variablesMap[declaration.symbol.descriptor]
|
val newVariable = variablesMap[declaration.symbol.descriptor]
|
||||||
?: return declaration
|
?: return declaration
|
||||||
|
|
||||||
return IrVariableImpl(
|
newVariable.initializer = declaration.initializer
|
||||||
startOffset = declaration.startOffset,
|
|
||||||
endOffset = declaration.endOffset,
|
return newVariable
|
||||||
origin = declaration.origin,
|
|
||||||
symbol = newVariable).apply {
|
|
||||||
initializer = declaration.initializer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeLivenessAtSuspensionPoints(body: IrBody): Map<IrSuspensionPoint, List<IrVariableSymbol>> {
|
private fun computeLivenessAtSuspensionPoints(body: IrBody): Map<IrSuspensionPoint, List<IrVariable>> {
|
||||||
// TODO: data flow analysis.
|
// TODO: data flow analysis.
|
||||||
// Just save all visible for now.
|
// Just save all visible for now.
|
||||||
val result = mutableMapOf<IrSuspensionPoint, List<IrVariableSymbol>>()
|
val result = mutableMapOf<IrSuspensionPoint, List<IrVariable>>()
|
||||||
body.acceptChildrenVoid(object: VariablesScopeTracker() {
|
body.acceptChildrenVoid(object: VariablesScopeTracker() {
|
||||||
|
|
||||||
override fun visitExpression(expression: IrExpression) {
|
override fun visitExpression(expression: IrExpression) {
|
||||||
@@ -894,7 +931,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
suspensionPoint.result.acceptChildrenVoid(this)
|
suspensionPoint.result.acceptChildrenVoid(this)
|
||||||
suspensionPoint.resumeResult.acceptChildrenVoid(this)
|
suspensionPoint.resumeResult.acceptChildrenVoid(this)
|
||||||
|
|
||||||
val visibleVariables = mutableListOf<IrVariableSymbol>()
|
val visibleVariables = mutableListOf<IrVariable>()
|
||||||
scopeStack.forEach { visibleVariables += it }
|
scopeStack.forEach { visibleVariables += it }
|
||||||
result.put(suspensionPoint, visibleVariables)
|
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.
|
// 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(
|
SimpleFunctionDescriptorImpl.create(
|
||||||
irFunction.descriptor,
|
irFunction.descriptor,
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
@@ -912,10 +949,11 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
SourceElement.NO_SOURCE).apply {
|
SourceElement.NO_SOURCE).apply {
|
||||||
initialize(null, null, emptyList(), emptyList(), context.builtIns.unitType, Modality.ABSTRACT, Visibilities.PRIVATE)
|
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(
|
SimpleFunctionDescriptorImpl.create(
|
||||||
irFunction.descriptor,
|
irFunction.descriptor,
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
@@ -923,10 +961,11 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
SourceElement.NO_SOURCE).apply {
|
SourceElement.NO_SOURCE).apply {
|
||||||
initialize(null, null, emptyList(), emptyList(), context.builtIns.unitType, Modality.ABSTRACT, Visibilities.PRIVATE)
|
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.
|
// TODO: optimize - it has square complexity.
|
||||||
|
|
||||||
override fun visitSetField(expression: IrSetField): IrExpression {
|
override fun visitSetField(expression: IrSetField): IrExpression {
|
||||||
@@ -983,13 +1022,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
newChildren[index] = transformedChild
|
newChildren[index] = transformedChild
|
||||||
else {
|
else {
|
||||||
// Save to temporary in order to save execution order.
|
// Save to temporary in order to save execution order.
|
||||||
val tmp = IrVariableSymbolImpl(
|
val tmp = irVar(transformedChild)
|
||||||
IrTemporaryVariableDescriptorImpl(
|
|
||||||
containingDeclaration = irFunction.descriptor,
|
tempStatements += tmp
|
||||||
name = "tmp${tempIndex++}".synthesizedName,
|
|
||||||
outType = transformedChild.type)
|
|
||||||
)
|
|
||||||
tempStatements += irVar(tmp, transformedChild)
|
|
||||||
newChildren[index] = irGet(tmp)
|
newChildren[index] = irGet(tmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1001,7 +1036,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
calledSaveState = true
|
calledSaveState = true
|
||||||
val firstArgument = newChildren[2]!!
|
val firstArgument = newChildren[2]!!
|
||||||
newChildren[2] = irBlock(firstArgument) {
|
newChildren[2] = irBlock(firstArgument) {
|
||||||
+irCall(saveStateSymbol)
|
+irCall(saveState)
|
||||||
+firstArgument
|
+firstArgument
|
||||||
}
|
}
|
||||||
suspendCall = newChildren[2]
|
suspendCall = newChildren[2]
|
||||||
@@ -1014,17 +1049,12 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
newChildren[numberOfChildren - 1] =
|
newChildren[numberOfChildren - 1] =
|
||||||
irBlock(lastChild) {
|
irBlock(lastChild) {
|
||||||
if (lastChild.isPure()) {
|
if (lastChild.isPure()) {
|
||||||
+irCall(saveStateSymbol)
|
+irCall(saveState)
|
||||||
+lastChild
|
+lastChild
|
||||||
} else {
|
} else {
|
||||||
val tmp = IrVariableSymbolImpl(
|
val tmp = irVar(lastChild)
|
||||||
IrTemporaryVariableDescriptorImpl(
|
+tmp
|
||||||
containingDeclaration = irFunction.descriptor,
|
+irCall(saveState)
|
||||||
name = "tmp${tempIndex++}".synthesizedName,
|
|
||||||
outType = lastChild.type)
|
|
||||||
)
|
|
||||||
+irVar(tmp, lastChild)
|
|
||||||
+irCall(saveStateSymbol)
|
|
||||||
+irGet(tmp)
|
+irGet(tmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1053,27 +1083,27 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
val suspensionPointIdParameter = IrTemporaryVariableDescriptorImpl(
|
val suspensionPointIdParameter = IrTemporaryVariableDescriptorImpl(
|
||||||
containingDeclaration = irFunction.descriptor,
|
containingDeclaration = irFunction.descriptor,
|
||||||
name = "suspensionPointId${suspensionPointIdIndex++}".synthesizedName,
|
name = "suspensionPointId${suspensionPointIdIndex++}".synthesizedName,
|
||||||
outType = suspensionPointIdType)
|
outType = suspensionPointIdType.toKotlinType())
|
||||||
val suspensionPoint = IrSuspensionPointImpl(
|
val suspensionPoint = IrSuspensionPointImpl(
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
type = context.builtIns.nullableAnyType,
|
type = context.irBuiltIns.anyNType,
|
||||||
suspensionPointIdParameter = irVar(suspensionPointIdParameter, null),
|
suspensionPointIdParameter = irVar(suspensionPointIdParameter, suspensionPointIdType),
|
||||||
result = irBlock(startOffset, endOffset) {
|
result = irBlock(startOffset, endOffset) {
|
||||||
if (!calledSaveState)
|
if (!calledSaveState)
|
||||||
+irCall(saveStateSymbol)
|
+irCall(saveState)
|
||||||
+irSetVar(suspendResult, suspendCall)
|
+irSetVar(suspendResult.symbol, suspendCall)
|
||||||
+irReturnIfSuspended(suspendResult)
|
+irReturnIfSuspended(suspendResult)
|
||||||
+irGet(suspendResult)
|
+irGet(suspendResult)
|
||||||
},
|
},
|
||||||
resumeResult = irBlock(startOffset, endOffset) {
|
resumeResult = irBlock(startOffset, endOffset) {
|
||||||
+irCall(restoreStateSymbol)
|
+irCall(restoreState)
|
||||||
+irThrowIfNotNull(exceptionArgument)
|
+irThrowIfNotNull(exceptionArgument)
|
||||||
+irGet(dataArgument)
|
+irGet(dataArgument)
|
||||||
})
|
})
|
||||||
val expressionResult = when {
|
val expressionResult = when {
|
||||||
suspendCall.type.isUnit() -> irImplicitCoercionToUnit(suspensionPoint)
|
suspendCall.type.isUnit() -> irImplicitCoercionToUnit(suspensionPoint)
|
||||||
else -> irCast(suspensionPoint, suspendCall.type, suspendCall.type)
|
else -> irAs(suspensionPoint, suspendCall.type)
|
||||||
}
|
}
|
||||||
return irBlock(expression) {
|
return irBlock(expression) {
|
||||||
tempStatements.forEach { +it }
|
tempStatements.forEach { +it }
|
||||||
@@ -1132,27 +1162,31 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
get() = this is IrCall && this.descriptor.original == returnIfSuspendedDescriptor
|
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?) =
|
private fun IrBuilderWithScope.irVar(descriptor: VariableDescriptor, type: IrType) =
|
||||||
IrVariableImpl(startOffset, endOffset, DECLARATION_ORIGIN_COROUTINE_IMPL, descriptor, initializer)
|
IrVariableImpl(startOffset, endOffset, DECLARATION_ORIGIN_COROUTINE_IMPL, descriptor, type)
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irVar(symbol: IrVariableSymbol, initializer: IrExpression?) =
|
private fun IrBuilderWithScope.irReturnIfSuspended(value: IrValueDeclaration) =
|
||||||
IrVariableImpl(startOffset, endOffset, DECLARATION_ORIGIN_COROUTINE_IMPL, symbol).apply {
|
|
||||||
this.initializer = initializer
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irReturnIfSuspended(value: IrValueSymbol) =
|
|
||||||
irIfThen(irEqeqeq(irGet(value), irCall(symbols.coroutineSuspendedGetter)),
|
irIfThen(irEqeqeq(irGet(value), irCall(symbols.coroutineSuspendedGetter)),
|
||||||
irReturn(irGet(value)))
|
irReturn(irGet(value)))
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueSymbol) =
|
private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueDeclaration) =
|
||||||
irIfThen(irNot(irEqeqeq(irGet(exception), irNull())),
|
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 {
|
private open class VariablesScopeTracker: IrElementVisitorVoid {
|
||||||
|
|
||||||
protected val scopeStack = mutableListOf<MutableSet<IrVariableSymbol>>(mutableSetOf())
|
protected val scopeStack = mutableListOf<MutableSet<IrVariable>>(mutableSetOf())
|
||||||
|
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) {
|
||||||
element.acceptChildrenVoid(this)
|
element.acceptChildrenVoid(this)
|
||||||
@@ -1174,7 +1208,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
|
|
||||||
override fun visitVariable(declaration: IrVariable) {
|
override fun visitVariable(declaration: IrVariable) {
|
||||||
super.visitVariable(declaration)
|
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.KonanBackendContext
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections
|
||||||
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithoutArguments
|
||||||
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
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.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
@@ -98,50 +99,50 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
add(TestFunction(function, kind))
|
add(TestFunction(function, kind))
|
||||||
|
|
||||||
private fun <T: IrElement> IrStatementsBuilder<T>.generateFunctionRegistration(
|
private fun <T: IrElement> IrStatementsBuilder<T>.generateFunctionRegistration(
|
||||||
receiver: IrValueSymbol,
|
receiver: IrValueDeclaration,
|
||||||
registerTestCase: IrFunctionSymbol,
|
registerTestCase: IrFunctionSymbol,
|
||||||
registerFunction: IrFunctionSymbol,
|
registerFunction: IrFunctionSymbol,
|
||||||
functions: Collection<TestFunction>) {
|
functions: Collection<TestFunction>) {
|
||||||
functions.forEach {
|
functions.forEach {
|
||||||
if (it.kind == FunctionKind.TEST) {
|
if (it.kind == FunctionKind.TEST) {
|
||||||
// Call registerTestCase(name: String, testFunction: () -> Unit) method.
|
// Call registerTestCase(name: String, testFunction: () -> Unit) method.
|
||||||
+irCall(registerTestCase).apply {
|
+irCall(registerTestCase, registerTestCase.descriptor.returnType!!.toErasedIrType()).apply {
|
||||||
dispatchReceiver = irGet(receiver)
|
dispatchReceiver = irGet(receiver)
|
||||||
putValueArgument(0, IrConstImpl.string(
|
putValueArgument(0, IrConstImpl.string(
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
context.builtIns.stringType,
|
context.irBuiltIns.stringType,
|
||||||
it.function.descriptor.name.identifier)
|
it.function.descriptor.name.identifier)
|
||||||
)
|
)
|
||||||
putValueArgument(1, IrFunctionReferenceImpl(
|
putValueArgument(1, IrFunctionReferenceImpl(
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
descriptor.valueParameters[1].type,
|
descriptor.valueParameters[1].type.toErasedIrType(),
|
||||||
it.function,
|
it.function,
|
||||||
it.function.descriptor, emptyMap()))
|
it.function.descriptor, 0))
|
||||||
putValueArgument(2, IrConstImpl.boolean(
|
putValueArgument(2, IrConstImpl.boolean(
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
context.builtIns.booleanType,
|
context.irBuiltIns.booleanType,
|
||||||
it.ignored
|
it.ignored
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Call registerFunction(kind: TestFunctionKind, () -> Unit) method.
|
// Call registerFunction(kind: TestFunctionKind, () -> Unit) method.
|
||||||
+irCall(registerFunction).apply {
|
+irCall(registerFunction, registerFunction.descriptor.returnType!!.toErasedIrType()).apply {
|
||||||
dispatchReceiver = irGet(receiver)
|
dispatchReceiver = irGet(receiver)
|
||||||
val testKindEntry = it.kind.runtimeKind
|
val testKindEntry = it.kind.runtimeKind
|
||||||
putValueArgument(0, IrGetEnumValueImpl(
|
putValueArgument(0, IrGetEnumValueImpl(
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
testKindEntry.descriptor.defaultType,
|
symbols.testFunctionKind.typeWithoutArguments,
|
||||||
testKindEntry)
|
testKindEntry)
|
||||||
)
|
)
|
||||||
putValueArgument(1, IrFunctionReferenceImpl(UNDEFINED_OFFSET,
|
putValueArgument(1, IrFunctionReferenceImpl(UNDEFINED_OFFSET,
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
descriptor.valueParameters[1].type,
|
descriptor.valueParameters[1].type.toErasedIrType(),
|
||||||
it.function,
|
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
|
//region Symbol and IR builders
|
||||||
|
|
||||||
/** Base class for getters (createInstance and getCompanion). */
|
/** 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 testSuite: IrClassSymbol,
|
||||||
val getterName: Name)
|
val getterName: Name)
|
||||||
: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrFunction>() {
|
: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrFunction>() {
|
||||||
@@ -300,7 +301,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
/* dispatchReceiverParameter = */ testSuite.descriptor.thisAsReceiverParameter,
|
/* dispatchReceiverParameter = */ testSuite.descriptor.thisAsReceiverParameter,
|
||||||
/* typeParameters = */ emptyList(),
|
/* typeParameters = */ emptyList(),
|
||||||
/* unsubstitutedValueParameters = */ emptyList(),
|
/* unsubstitutedValueParameters = */ emptyList(),
|
||||||
/* returnType = */ returnType,
|
/* returnType = */ returnType.toKotlinType(),
|
||||||
/* modality = */ Modality.FINAL,
|
/* modality = */ Modality.FINAL,
|
||||||
/* visibility = */ Visibilities.PROTECTED
|
/* visibility = */ Visibilities.PROTECTED
|
||||||
).apply {
|
).apply {
|
||||||
@@ -324,18 +325,21 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
* returning a reference to an object represented by `[objectSymbol]`.
|
* returning a reference to an object represented by `[objectSymbol]`.
|
||||||
*/
|
*/
|
||||||
private inner class ObjectGetterBuilder(val objectSymbol: IrClassSymbol, testSuite: IrClassSymbol, getterName: Name)
|
private 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(
|
override fun buildIr(): IrFunction = IrFunctionImpl(
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
TEST_SUITE_GENERATED_MEMBER,
|
TEST_SUITE_GENERATED_MEMBER,
|
||||||
symbol).apply {
|
symbol).apply {
|
||||||
|
|
||||||
|
this.returnType = this@ObjectGetterBuilder.returnType
|
||||||
|
|
||||||
val builder = context.createIrBuilder(symbol)
|
val builder = context.createIrBuilder(symbol)
|
||||||
createParameterDeclarations()
|
createParameterDeclarations(context.ir.symbols.symbolTable)
|
||||||
body = builder.irBlockBody {
|
body = builder.irBlockBody {
|
||||||
+irReturn(IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
+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].
|
* returning a new instance of class referenced by [classSymbol].
|
||||||
*/
|
*/
|
||||||
private inner class InstanceGetterBuilder(val classSymbol: IrClassSymbol, testSuite: IrClassSymbol, getterName: Name)
|
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(
|
override fun buildIr() = IrFunctionImpl(
|
||||||
startOffset = UNDEFINED_OFFSET,
|
startOffset = UNDEFINED_OFFSET,
|
||||||
endOffset = UNDEFINED_OFFSET,
|
endOffset = UNDEFINED_OFFSET,
|
||||||
origin = TEST_SUITE_GENERATED_MEMBER,
|
origin = TEST_SUITE_GENERATED_MEMBER,
|
||||||
symbol = symbol).apply {
|
symbol = symbol).apply {
|
||||||
|
|
||||||
|
this.returnType = this@InstanceGetterBuilder.returnType
|
||||||
|
|
||||||
val builder = context.createIrBuilder(symbol)
|
val builder = context.createIrBuilder(symbol)
|
||||||
createParameterDeclarations()
|
createParameterDeclarations(context.ir.symbols.symbolTable)
|
||||||
body = builder.irBlockBody {
|
body = builder.irBlockBody {
|
||||||
val constructor = classSymbol.constructors.single { it.descriptor.valueParameters.isEmpty() }
|
val constructor = classSymbol.owner.constructors.single { it.valueParameters.isEmpty() }
|
||||||
+irReturn(irCall(constructor))
|
+irReturn(irCall(constructor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -385,15 +392,18 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
TEST_SUITE_GENERATED_MEMBER,
|
TEST_SUITE_GENERATED_MEMBER,
|
||||||
symbol).apply {
|
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 &&
|
it.valueParameters.size == 3 &&
|
||||||
KotlinBuiltIns.isString(it.valueParameters[0].type) && // name: String
|
KotlinBuiltIns.isString(it.valueParameters[0].type) && // name: String
|
||||||
it.valueParameters[1].type.isFunctionType && // function: testClassType.() -> Unit
|
it.valueParameters[1].type.isFunctionType && // function: testClassType.() -> Unit
|
||||||
KotlinBuiltIns.isBoolean(it.valueParameters[2].type) // ignored: Boolean
|
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.size == 2 &&
|
||||||
it.valueParameters[0].type == symbols.testFunctionKind.descriptor.defaultType && // kind: TestFunctionKind
|
it.valueParameters[0].type == symbols.testFunctionKind.descriptor.defaultType && // kind: TestFunctionKind
|
||||||
it.valueParameters[1].type.isFunctionType // function: () -> Unit
|
it.valueParameters[1].type.isFunctionType // function: () -> Unit
|
||||||
@@ -404,26 +414,28 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
+IrDelegatingConstructorCallImpl(
|
+IrDelegatingConstructorCallImpl(
|
||||||
startOffset = UNDEFINED_OFFSET,
|
startOffset = UNDEFINED_OFFSET,
|
||||||
endOffset = UNDEFINED_OFFSET,
|
endOffset = UNDEFINED_OFFSET,
|
||||||
|
type = context.irBuiltIns.unitType,
|
||||||
symbol = symbols.symbolTable.referenceConstructor(superConstructor),
|
symbol = symbols.symbolTable.referenceConstructor(superConstructor),
|
||||||
descriptor = superConstructor,
|
descriptor = superConstructor,
|
||||||
typeArgumentsCount = 2
|
typeArgumentsCount = 2
|
||||||
).apply {
|
).apply {
|
||||||
copyTypeArgumentsFrom(mapOf(superConstructor.typeParameters[0] to testClassType,
|
putTypeArgument(0, testClassType.toErasedIrType())
|
||||||
superConstructor.typeParameters[1] to testCompanionType))
|
putTypeArgument(1, testCompanionType.toErasedIrType())
|
||||||
|
|
||||||
putValueArgument(0, IrConstImpl.string(
|
putValueArgument(0, IrConstImpl.string(
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
context.builtIns.stringType,
|
context.irBuiltIns.stringType,
|
||||||
suiteName)
|
suiteName)
|
||||||
)
|
)
|
||||||
putValueArgument(1, IrConstImpl.boolean(
|
putValueArgument(1, IrConstImpl.boolean(
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
context.builtIns.booleanType,
|
context.irBuiltIns.booleanType,
|
||||||
ignored
|
ignored
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
generateFunctionRegistration(testSuite.owner.thisReceiver!!.symbol,
|
generateFunctionRegistration(testSuite.owner.thisReceiver!!,
|
||||||
registerTestCase, registerFunction, functions)
|
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)
|
* Builds a test suite class representing a test class (any class in the original IrFile with method(s)
|
||||||
* annotated with @Test). The test suite class is a subclass of ClassTestSuite<T> where T is the test class.
|
* annotated with @Test). The test suite class is a subclass of ClassTestSuite<T> where T is the test class.
|
||||||
@@ -489,17 +503,17 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun buildIr() = IrClassImpl(
|
override fun buildIr() = symbols.symbolTable.declareClass(
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
TEST_SUITE_CLASS,
|
TEST_SUITE_CLASS,
|
||||||
symbol).apply {
|
symbol.descriptor).apply {
|
||||||
createParameterDeclarations()
|
createParameterDeclarations()
|
||||||
addMember(constructorBuilder.ir)
|
addMember(constructorBuilder.ir)
|
||||||
addMember(instanceGetterBuilder.ir)
|
addMember(instanceGetterBuilder.ir)
|
||||||
companionGetterBuilder?.let { addMember(it.ir) }
|
companionGetterBuilder?.let { addMember(it.ir) }
|
||||||
addFakeOverrides()
|
addFakeOverrides(symbols.symbolTable)
|
||||||
setSuperSymbols(context.ir.symbols.symbolTable)
|
setSuperSymbols(symbols.symbolTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doInitialize() {
|
override fun doInitialize() {
|
||||||
@@ -526,7 +540,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
companionGetterBuilder?.initialize()
|
companionGetterBuilder?.initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun buildSymbol() = IrClassSymbolImpl(
|
override fun buildSymbol() = symbols.symbolTable.referenceClass(
|
||||||
ClassDescriptorImpl(
|
ClassDescriptorImpl(
|
||||||
/* containingDeclaration = */ containingDeclaration,
|
/* containingDeclaration = */ containingDeclaration,
|
||||||
/* name = */ suiteClassName,
|
/* name = */ suiteClassName,
|
||||||
@@ -549,8 +563,9 @@ internal class TestProcessor (val context: KonanBackendContext) {
|
|||||||
testClass.functions)) {
|
testClass.functions)) {
|
||||||
initialize()
|
initialize()
|
||||||
irFile.addChild(ir)
|
irFile.addChild(ir)
|
||||||
|
val irConstructor = ir.constructors.single()
|
||||||
irFile.addTopLevelInitializer(
|
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 {
|
irFile.addTopLevelInitializer(builder.irBlock {
|
||||||
val constructorCall = irCall(symbols.topLevelSuiteConstructor).apply {
|
val constructorCall = irCall(symbols.topLevelSuiteConstructor).apply {
|
||||||
putValueArgument(0, IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
putValueArgument(0, IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
context.builtIns.stringType, suiteName))
|
context.irBuiltIns.stringType, suiteName))
|
||||||
}
|
}
|
||||||
val testSuiteVal = irTemporary(constructorCall, "topLevelTestSuite")
|
val testSuiteVal = irTemporary(constructorCall, "topLevelTestSuite")
|
||||||
generateFunctionRegistration(testSuiteVal.symbol,
|
generateFunctionRegistration(testSuiteVal,
|
||||||
symbols.topLevelSuiteRegisterTestCase,
|
symbols.topLevelSuiteRegisterTestCase,
|
||||||
symbols.topLevelSuiteRegisterFunction,
|
symbols.topLevelSuiteRegisterFunction,
|
||||||
functions)
|
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.at
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
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.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
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.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.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This lowering pass lowers some [IrTypeOperatorCall]s.
|
* This lowering pass lowers some [IrTypeOperatorCall]s.
|
||||||
@@ -60,22 +65,24 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun
|
|||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinType.erasure(): KotlinType {
|
private fun IrType.erasure(): IrType {
|
||||||
val descriptor = this.constructor.declarationDescriptor
|
if (this !is IrSimpleType) return this
|
||||||
return when (descriptor) {
|
|
||||||
is ClassDescriptor -> this
|
|
||||||
is TypeParameterDescriptor -> {
|
|
||||||
val upperBound = descriptor.upperBounds.singleOrNull() ?:
|
|
||||||
TODO("$descriptor : ${descriptor.upperBounds}")
|
|
||||||
|
|
||||||
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?`
|
// `T?`
|
||||||
upperBound.erasure().makeNullable()
|
upperBound.erasure().makeNullable()
|
||||||
} else {
|
} else {
|
||||||
upperBound.erasure()
|
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)
|
builder.at(expression)
|
||||||
val typeOperand = expression.typeOperand.erasure()
|
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.
|
// TODO: consider the case when expression type is wrong e.g. due to generics-related unchecked casts.
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
expression.argument.type.isSubtypeOf(typeOperand) -> expression.argument
|
expression.argument.type.isSubtypeOf(typeOperand) -> expression.argument
|
||||||
|
|
||||||
expression.argument.type.isNullable() -> {
|
expression.argument.type.containsNull() -> {
|
||||||
with (builder) {
|
with (builder) {
|
||||||
irLetS(expression.argument) { argument ->
|
irLetS(expression.argument) { argument ->
|
||||||
irIfThenElse(
|
irIfThenElse(
|
||||||
type = expression.type,
|
type = expression.type,
|
||||||
condition = irEqeqeq(irGet(argument), irNull()),
|
condition = irEqeqeq(irGet(argument.owner), irNull()),
|
||||||
|
|
||||||
thenPart = if (typeOperand.isMarkedNullable)
|
thenPart = if (typeOperand.isSimpleTypeWithQuestionMark)
|
||||||
irNull()
|
irNull()
|
||||||
else
|
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
|
typeOperand == expression.typeOperand -> expression
|
||||||
|
|
||||||
@@ -124,8 +131,8 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun
|
|||||||
return builder.irBlock(expression) {
|
return builder.irBlock(expression) {
|
||||||
+irLetS(expression.argument) { variable ->
|
+irLetS(expression.argument) { variable ->
|
||||||
irIfThenElse(expression.type,
|
irIfThenElse(expression.type,
|
||||||
condition = irIs(irGet(variable), typeOperand),
|
condition = irIs(irGet(variable.owner), typeOperand),
|
||||||
thenPart = irImplicitCast(irGet(variable), typeOperand),
|
thenPart = irImplicitCast(irGet(variable.owner), typeOperand),
|
||||||
elsePart = irNull())
|
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.functionName
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.constructedClass
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
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.getArguments
|
||||||
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
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.
|
* Some primitive types can be null and some can't. Those that can't must be replaced with the corresponding box.
|
||||||
* Int -> Int
|
* Int -> Int
|
||||||
@@ -61,29 +60,29 @@ private fun getClassWithBoxingIncluded(type: KotlinType, ir: KonanIr): ClassDesc
|
|||||||
* CPointer -> CPointer
|
* CPointer -> CPointer
|
||||||
* CPointer? -> CPointer
|
* CPointer? -> CPointer
|
||||||
*/
|
*/
|
||||||
return if (type.correspondingValueType == null && type.makeNotNullable().correspondingValueType != null)
|
return if (type.correspondingValueType == null && type.makeNotNull().correspondingValueType != null)
|
||||||
ir.getClass(ir.symbols.getTypeConversion(type.makeNotNullable(), type)!!.descriptor.returnType!!)!!
|
ir.symbols.getTypeConversion(type.makeNotNull(), type)!!.owner.returnType.getClass()!!
|
||||||
else
|
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)
|
val irClass = getClassWithBoxingIncluded(type, ir)
|
||||||
if (irClass != null) {
|
if (irClass != null) {
|
||||||
erasure += irClass
|
erasure += irClass
|
||||||
} else {
|
} else {
|
||||||
val descriptor = type.constructor.declarationDescriptor
|
val classifier = type.classifierOrFail
|
||||||
if (descriptor is TypeParameterDescriptor) {
|
if (classifier is IrTypeParameterSymbol) {
|
||||||
descriptor.upperBounds.forEach {
|
classifier.owner.superTypes.forEach {
|
||||||
computeErasure(it, ir, erasure)
|
computeErasure(it, ir, erasure)
|
||||||
}
|
}
|
||||||
} else {
|
} 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>()
|
val result = mutableListOf<ClassDescriptor>()
|
||||||
computeErasure(this, context.ir, result)
|
computeErasure(this, context.ir, result)
|
||||||
return result
|
return result
|
||||||
@@ -163,7 +162,7 @@ private class ExpressionValuesExtractor(val context: Context,
|
|||||||
forEachValue(
|
forEachValue(
|
||||||
expression = (expression.statements.last() as? IrExpression)
|
expression = (expression.statements.last() as? IrExpression)
|
||||||
?: IrGetObjectValueImpl(expression.startOffset, expression.endOffset,
|
?: IrGetObjectValueImpl(expression.startOffset, expression.endOffset,
|
||||||
context.builtIns.unitType, context.ir.symbols.unit),
|
context.irBuiltIns.unitType, context.ir.symbols.unit),
|
||||||
block = block
|
block = block
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -187,7 +186,8 @@ private class ExpressionValuesExtractor(val context: Context,
|
|||||||
else { // Propagate cast to sub-values.
|
else { // Propagate cast to sub-values.
|
||||||
forEachValue(expression.argument) { value ->
|
forEachValue(expression.argument) { value ->
|
||||||
with(expression) {
|
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) {
|
override fun visitConstructor(declaration: IrConstructor) {
|
||||||
val body = declaration.body
|
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"
|
"Non-annotation class constructor has empty body"
|
||||||
}
|
}
|
||||||
DEBUG_OUTPUT(0) {
|
DEBUG_OUTPUT(0) {
|
||||||
@@ -280,7 +280,8 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
println("Analysing global field ${declaration.descriptor}")
|
println("Analysing global field ${declaration.descriptor}")
|
||||||
println("IR: ${ir2stringWhole(declaration)}")
|
println("IR: ${ir2stringWhole(declaration)}")
|
||||||
}
|
}
|
||||||
analyze(declaration, 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) {
|
if (expression is IrCall && expression.symbol == scheduleImplSymbol) {
|
||||||
// Producer and job of scheduleImpl are called externally, we need to reflect this somehow.
|
// Producer and job of scheduleImpl are called externally, we need to reflect this somehow.
|
||||||
val producerInvocation = IrCallImpl(expression.startOffset, expression.endOffset,
|
val producerInvocation = IrCallImpl(expression.startOffset, expression.endOffset,
|
||||||
|
scheduleImplProducerInvoke.returnType,
|
||||||
scheduleImplProducerInvoke.symbol, scheduleImplProducerInvoke.descriptor)
|
scheduleImplProducerInvoke.symbol, scheduleImplProducerInvoke.descriptor)
|
||||||
producerInvocation.dispatchReceiver = expression.getValueArgument(2)
|
producerInvocation.dispatchReceiver = expression.getValueArgument(2)
|
||||||
val jobFunctionReference = expression.getValueArgument(3) as? IrFunctionReference
|
val jobFunctionReference = expression.getValueArgument(3) as? IrFunctionReference
|
||||||
?: error("A function reference expected")
|
?: error("A function reference expected")
|
||||||
val jobInvocation = IrCallImpl(expression.startOffset, expression.endOffset,
|
val jobInvocation = IrCallImpl(expression.startOffset, expression.endOffset,
|
||||||
|
jobFunctionReference.symbol.owner.returnType,
|
||||||
jobFunctionReference.symbol, jobFunctionReference.descriptor)
|
jobFunctionReference.symbol, jobFunctionReference.descriptor)
|
||||||
jobInvocation.putValueArgument(0, producerInvocation)
|
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
|
.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "doResume" }.symbol
|
||||||
|
|
||||||
private val getContinuationSymbol = context.ir.symbols.getContinuation
|
private val getContinuationSymbol = context.ir.symbols.getContinuation
|
||||||
|
private val continuationType = getContinuationSymbol.owner.returnType
|
||||||
|
|
||||||
private val arrayGetSymbol = context.ir.symbols.arrayGet
|
private val arrayGetSymbol = context.ir.symbols.arrayGet
|
||||||
private val arraySetSymbol = context.ir.symbols.arraySet
|
private val arraySetSymbol = context.ir.symbols.arraySet
|
||||||
@@ -631,21 +635,27 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
val owner = callee.containingDeclaration as ClassDescriptor
|
val owner = callee.containingDeclaration as ClassDescriptor
|
||||||
val actualReceiverType = value.dispatchReceiver!!.type
|
val actualReceiverType = value.dispatchReceiver!!.type
|
||||||
val receiverType =
|
val receiverType =
|
||||||
if (actualReceiverType.constructor.declarationDescriptor is TypeParameterDescriptor
|
if (actualReceiverType.classifierOrNull is IrTypeParameterSymbol
|
||||||
|| !callee.isReal /* Could be a bridge. */)
|
|| !callee.isReal /* Could be a bridge. */)
|
||||||
symbolTable.mapClass(owner)
|
symbolTable.mapClass(owner)
|
||||||
else {
|
else {
|
||||||
val actualClassAtCallsite = actualReceiverType.constructor.declarationDescriptor as org.jetbrains.kotlin.descriptors.ClassDescriptor
|
val actualClassAtCallsite =
|
||||||
assert (DescriptorUtils.isSubclass(actualClassAtCallsite, owner.descriptor)) {
|
actualReceiverType.classifierOrFail.descriptor
|
||||||
"Expected an inheritor of ${owner.descriptor}, but was $actualClassAtCallsite"
|
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) {
|
if (owner.isInterface) {
|
||||||
val calleeHash = callee.functionName.localHash.value
|
val calleeHash = callee.functionName.localHash.value
|
||||||
@@ -681,8 +691,9 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
}
|
}
|
||||||
|
|
||||||
is IrDelegatingConstructorCall -> {
|
is IrDelegatingConstructorCall -> {
|
||||||
val thiz = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
val thisReceiver = (descriptor as ConstructorDescriptor).constructedClass.thisReceiver!!
|
||||||
(descriptor as ConstructorDescriptor).constructedClass.thisReceiver!!.symbol)
|
val thiz = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, thisReceiver.type,
|
||||||
|
thisReceiver.symbol)
|
||||||
val arguments = listOf(thiz) + value.getArguments().map { it.second }
|
val arguments = listOf(thiz) + value.getArguments().map { it.second }
|
||||||
DataFlowIR.Node.StaticCall(
|
DataFlowIR.Node.StaticCall(
|
||||||
symbolTable.mapFunction(value.symbol.owner),
|
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.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrGetField
|
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.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
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.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.IntValue
|
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 {
|
internal object DataFlowIR {
|
||||||
|
|
||||||
@@ -468,7 +468,7 @@ internal object DataFlowIR {
|
|||||||
private val pointsToOnWhomDescriptor = pointsToAnnotationDescriptor.unsubstitutedPrimaryConstructor!!.valueParameters.single()
|
private val pointsToOnWhomDescriptor = pointsToAnnotationDescriptor.unsubstitutedPrimaryConstructor!!.valueParameters.single()
|
||||||
|
|
||||||
private val getContinuationSymbol = context.ir.symbols.getContinuation
|
private val getContinuationSymbol = context.ir.symbols.getContinuation
|
||||||
private val continuationType = getContinuationSymbol.descriptor.returnType!!
|
private val continuationType = getContinuationSymbol.owner.returnType
|
||||||
|
|
||||||
var privateTypeIndex = 0
|
var privateTypeIndex = 0
|
||||||
var privateFunIndex = 0
|
var privateFunIndex = 0
|
||||||
@@ -524,7 +524,7 @@ internal object DataFlowIR {
|
|||||||
|
|
||||||
classMap[descriptor] = type
|
classMap[descriptor] = type
|
||||||
|
|
||||||
type.superTypes += descriptor.defaultType.immediateSupertypes().map { mapType(it) }
|
type.superTypes += descriptor.superTypes.map { mapType(it) }
|
||||||
if (!isAbstract) {
|
if (!isAbstract) {
|
||||||
val vtableBuilder = context.getVtableBuilder(descriptor)
|
val vtableBuilder = context.getVtableBuilder(descriptor)
|
||||||
type.vtable += vtableBuilder.vtableEntries.map { mapFunction(it.getImplementation(context)!!) }
|
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
|
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.
|
// TODO: use from LlvmDeclarations.
|
||||||
private fun getFqName(descriptor: DeclarationDescriptor): FqName =
|
private fun getFqName(descriptor: DeclarationDescriptor): FqName =
|
||||||
@@ -605,7 +605,7 @@ internal object DataFlowIR {
|
|||||||
.map { mapClass(choosePrimary(it.erasure(context))) }
|
.map { mapClass(choosePrimary(it.erasure(context))) }
|
||||||
.toTypedArray()
|
.toTypedArray()
|
||||||
symbol.returnType = mapType(if (descriptor.isSuspend)
|
symbol.returnType = mapType(if (descriptor.isSuspend)
|
||||||
context.builtIns.anyType
|
context.irBuiltIns.anyType
|
||||||
else
|
else
|
||||||
descriptor.returnType)
|
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.descriptors.isInterface
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.IrPrivateClassReferenceImpl
|
import org.jetbrains.kotlin.backend.konan.ir.IrPrivateClassReferenceImpl
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.IrPrivateFunctionCallImpl
|
import org.jetbrains.kotlin.backend.konan.ir.IrPrivateFunctionCallImpl
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.nullConst
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.getErasedTypeClass
|
||||||
import org.jetbrains.kotlin.backend.konan.objcexport.getErasedTypeClass
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
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.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.getValueArgument
|
import org.jetbrains.kotlin.ir.expressions.getValueArgument
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl
|
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.expressions.impl.IrWhenImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
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.addArguments
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
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.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
@@ -1009,7 +1008,7 @@ internal object Devirtualization {
|
|||||||
|
|
||||||
class PossiblyCoercedValue(val value: IrVariable, val coercion: IrFunctionSymbol?) {
|
class PossiblyCoercedValue(val value: IrVariable, val coercion: IrFunctionSymbol?) {
|
||||||
fun getFullValue(irBuilder: IrBuilderWithScope) = irBuilder.run {
|
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
|
val coercion = expression as IrCall
|
||||||
PossiblyCoercedValue(
|
PossiblyCoercedValue(
|
||||||
irTemporary(irImplicitCast(coercion.getArguments().single().second,
|
irTemporary(irImplicitCast(coercion.getArguments().single().second,
|
||||||
coercion.descriptor.explicitParameters.single().type))
|
coercion.symbol.owner.explicitParameters.single().type))
|
||||||
, coercion.symbol)
|
, coercion.symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1041,12 +1040,12 @@ internal object Devirtualization {
|
|||||||
val coercion = context.ir.symbols.getTypeConversion(type.correspondingValueType, targetType.correspondingValueType)
|
val coercion = context.ir.symbols.getTypeConversion(type.correspondingValueType, targetType.correspondingValueType)
|
||||||
?: return possiblyCoercedValue.getFullValue(this)
|
?: return possiblyCoercedValue.getFullValue(this)
|
||||||
if (prevCoercion == null)
|
if (prevCoercion == null)
|
||||||
return irCoerce(irGet(value.symbol), coercion)
|
return irCoerce(irGet(value), coercion)
|
||||||
assertCoercionsMatch(coercion, prevCoercion)
|
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) =
|
devirtualizedCallee: DataFlowIR.FunctionSymbol.Declared) =
|
||||||
IrPrivateFunctionCallImpl(
|
IrPrivateFunctionCallImpl(
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
@@ -1062,7 +1061,7 @@ internal object Devirtualization {
|
|||||||
virtualCallee = callee
|
virtualCallee = callee
|
||||||
)
|
)
|
||||||
|
|
||||||
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: KotlinType,
|
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: IrType,
|
||||||
actualCallee: DataFlowIR.FunctionSymbol.Declared,
|
actualCallee: DataFlowIR.FunctionSymbol.Declared,
|
||||||
receiver: IrVariable,
|
receiver: IrVariable,
|
||||||
extensionReceiver: PossiblyCoercedValue?,
|
extensionReceiver: PossiblyCoercedValue?,
|
||||||
@@ -1070,7 +1069,7 @@ internal object Devirtualization {
|
|||||||
actualCallee.bridgeTarget.let {
|
actualCallee.bridgeTarget.let {
|
||||||
if (it == null)
|
if (it == null)
|
||||||
irDevirtualizedCall(callee, actualType, actualCallee).apply {
|
irDevirtualizedCall(callee, actualType, actualCallee).apply {
|
||||||
this.dispatchReceiver = irGet(receiver.symbol)
|
this.dispatchReceiver = irGet(receiver)
|
||||||
this.extensionReceiver = extensionReceiver?.getFullValue(this@irDevirtualizedCall)
|
this.extensionReceiver = extensionReceiver?.getFullValue(this@irDevirtualizedCall)
|
||||||
callee.descriptor.valueParameters.forEach {
|
callee.descriptor.valueParameters.forEach {
|
||||||
putValueArgument(it.index, parameters[it]!!.getFullValue(this@irDevirtualizedCall))
|
putValueArgument(it.index, parameters[it]!!.getFullValue(this@irDevirtualizedCall))
|
||||||
@@ -1079,7 +1078,7 @@ internal object Devirtualization {
|
|||||||
else {
|
else {
|
||||||
val bridgeTarget = it.resolved() as DataFlowIR.FunctionSymbol.Declared
|
val bridgeTarget = it.resolved() as DataFlowIR.FunctionSymbol.Declared
|
||||||
val callResult = irDevirtualizedCall(callee, actualType, bridgeTarget).apply {
|
val callResult = irDevirtualizedCall(callee, actualType, bridgeTarget).apply {
|
||||||
this.dispatchReceiver = irGet(receiver.symbol)
|
this.dispatchReceiver = irGet(receiver)
|
||||||
this.extensionReceiver = extensionReceiver?.let {
|
this.extensionReceiver = extensionReceiver?.let {
|
||||||
irCoerceIfNeeded(
|
irCoerceIfNeeded(
|
||||||
type = actualCallee.parameterTypes[1].resolved(),
|
type = actualCallee.parameterTypes[1].resolved(),
|
||||||
@@ -1140,21 +1139,22 @@ internal object Devirtualization {
|
|||||||
val startOffset = expression.startOffset
|
val startOffset = expression.startOffset
|
||||||
val endOffset = expression.endOffset
|
val endOffset = expression.endOffset
|
||||||
val type = if (descriptor.isSuspend)
|
val type = if (descriptor.isSuspend)
|
||||||
context.builtIns.nullableAnyType
|
context.irBuiltIns.anyNType
|
||||||
else descriptor.original.returnType!!
|
else expression.symbol.owner.returnType
|
||||||
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset)
|
||||||
irBuilder.run {
|
irBuilder.run {
|
||||||
val dispatchReceiver = expression.dispatchReceiver!!
|
val dispatchReceiver = expression.dispatchReceiver!!
|
||||||
return when {
|
return when {
|
||||||
possibleCallees.isEmpty() -> irBlock(expression) {
|
possibleCallees.isEmpty() -> irBlock(expression) {
|
||||||
+irCall(context.ir.symbols.throwInvalidReceiverTypeException).apply {
|
val throwExpr = irCall(context.ir.symbols.throwInvalidReceiverTypeException.owner).apply {
|
||||||
putValueArgument(0, irCall(context.ir.symbols.kClassImplConstructor, listOf(dispatchReceiver.type)).apply {
|
putValueArgument(0, irCall(context.ir.symbols.kClassImplConstructor.owner, listOf(dispatchReceiver.type)).apply {
|
||||||
putValueArgument(0, irCall(context.ir.symbols.getObjectTypeInfo).apply {
|
putValueArgument(0, irCall(context.ir.symbols.getObjectTypeInfo.owner).apply {
|
||||||
putValueArgument(0, dispatchReceiver)
|
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.
|
optimize && possibleCallees.size == 1 -> { // Monomorphic callsite.
|
||||||
@@ -1176,7 +1176,7 @@ internal object Devirtualization {
|
|||||||
it to irSplitCoercion(expression.getValueArgument(it)!!)
|
it to irSplitCoercion(expression.getValueArgument(it)!!)
|
||||||
}
|
}
|
||||||
val typeInfo = irTemporary(irCall(context.ir.symbols.getObjectTypeInfo).apply {
|
val typeInfo = irTemporary(irCall(context.ir.symbols.getObjectTypeInfo).apply {
|
||||||
putValueArgument(0, irGet(receiver.symbol))
|
putValueArgument(0, irGet(receiver))
|
||||||
})
|
})
|
||||||
|
|
||||||
val branches = mutableListOf<IrBranchImpl>()
|
val branches = mutableListOf<IrBranchImpl>()
|
||||||
@@ -1186,8 +1186,8 @@ internal object Devirtualization {
|
|||||||
val expectedTypeInfo = IrPrivateClassReferenceImpl(
|
val expectedTypeInfo = IrPrivateClassReferenceImpl(
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
type = nativePtrType,
|
type = context.ir.symbols.nativePtrType,
|
||||||
symbol = IrClassSymbolImpl(dispatchReceiver.type.getErasedTypeClass()),
|
symbol = dispatchReceiver.type.getErasedTypeClass(),
|
||||||
classType = receiver.type,
|
classType = receiver.type,
|
||||||
moduleDescriptor = actualReceiverType.module!!.descriptor,
|
moduleDescriptor = actualReceiverType.module!!.descriptor,
|
||||||
totalClasses = actualReceiverType.module.numberOfClasses,
|
totalClasses = actualReceiverType.module.numberOfClasses,
|
||||||
@@ -1198,7 +1198,7 @@ internal object Devirtualization {
|
|||||||
irTrue() // Don't check last type in optimize mode.
|
irTrue() // Don't check last type in optimize mode.
|
||||||
else
|
else
|
||||||
irCall(nativePtrEqualityOperatorSymbol).apply {
|
irCall(nativePtrEqualityOperatorSymbol).apply {
|
||||||
putValueArgument(0, irGet(typeInfo.symbol))
|
putValueArgument(0, irGet(typeInfo))
|
||||||
putValueArgument(1, expectedTypeInfo)
|
putValueArgument(1, expectedTypeInfo)
|
||||||
}
|
}
|
||||||
IrBranchImpl(
|
IrBranchImpl(
|
||||||
@@ -1218,7 +1218,7 @@ internal object Devirtualization {
|
|||||||
irCall(context.ir.symbols.kClassImplConstructor,
|
irCall(context.ir.symbols.kClassImplConstructor,
|
||||||
listOf(dispatchReceiver.type)
|
listOf(dispatchReceiver.type)
|
||||||
).apply {
|
).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.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.ir.util.addFakeOverrides
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||||
import org.jetbrains.kotlin.ir.util.setOverrides
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.ir.util.setSuperSymbols
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer
|
import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer
|
||||||
import org.jetbrains.kotlin.metadata.KonanIr
|
import org.jetbrains.kotlin.metadata.KonanIr
|
||||||
import org.jetbrains.kotlin.metadata.KonanIr.IrConst.ValueCase.*
|
import org.jetbrains.kotlin.metadata.KonanIr.IrConst.ValueCase.*
|
||||||
@@ -82,6 +82,8 @@ internal class IrSerializer(val context: Context,
|
|||||||
return irDescriptorSerializer.serializeKotlinType(type)
|
return irDescriptorSerializer.serializeKotlinType(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun serializeKotlinType(type: IrType) = serializeKotlinType(type.toKotlinType())
|
||||||
|
|
||||||
private fun serializeDescriptor(descriptor: DeclarationDescriptor): KonanIr.KotlinDescriptor {
|
private fun serializeDescriptor(descriptor: DeclarationDescriptor): KonanIr.KotlinDescriptor {
|
||||||
context.log{"### serializeDescriptor $descriptor"}
|
context.log{"### serializeDescriptor $descriptor"}
|
||||||
|
|
||||||
@@ -719,12 +721,12 @@ internal class IrDeserializer(val context: Context,
|
|||||||
private fun deserializeDescriptor(proto: KonanIr.KotlinDescriptor)
|
private fun deserializeDescriptor(proto: KonanIr.KotlinDescriptor)
|
||||||
= descriptorDeserializer.deserializeDescriptor(proto)
|
= descriptorDeserializer.deserializeDescriptor(proto)
|
||||||
|
|
||||||
private fun deserializeTypeArguments(proto: KonanIr.TypeArguments): List<KotlinType> {
|
private fun deserializeTypeArguments(proto: KonanIr.TypeArguments): List<IrType> {
|
||||||
context.log{"### deserializeTypeArguments"}
|
context.log{"### deserializeTypeArguments"}
|
||||||
val result = mutableListOf<KotlinType>()
|
val result = mutableListOf<IrType>()
|
||||||
proto.typeArgumentList.forEach { type ->
|
proto.typeArgumentList.forEach { type ->
|
||||||
val kotlinType = deserializeKotlinType(type)
|
val kotlinType = deserializeKotlinType(type)
|
||||||
result.add(kotlinType)
|
result.add(kotlinType.brokenIr)
|
||||||
context.log{"$kotlinType"}
|
context.log{"$kotlinType"}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
@@ -782,6 +784,9 @@ internal class IrDeserializer(val context: Context,
|
|||||||
return element
|
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 {
|
private fun deserializeBlock(proto: KonanIr.IrBlock, start: Int, end: Int, type: KotlinType): IrBlock {
|
||||||
val statements = mutableListOf<IrStatement>()
|
val statements = mutableListOf<IrStatement>()
|
||||||
val statementProtos = proto.statementList
|
val statementProtos = proto.statementList
|
||||||
@@ -791,7 +796,7 @@ internal class IrDeserializer(val context: Context,
|
|||||||
|
|
||||||
val isLambdaOrigin = if (proto.isLambdaOrigin) IrStatementOrigin.LAMBDA else null
|
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) {
|
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
|
val descriptor = deserializeDescriptor(proto.classDescriptor) as ClassifierDescriptor
|
||||||
/** TODO: [createClassifierSymbolForClassReference] is internal function */
|
/** TODO: [createClassifierSymbolForClassReference] is internal function */
|
||||||
@Suppress("DEPRECATION")
|
@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 {
|
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) {
|
val call: IrCall = when (proto.kind) {
|
||||||
KonanIr.IrCall.Primitive.NOT_PRIMITIVE ->
|
KonanIr.IrCall.Primitive.NOT_PRIMITIVE ->
|
||||||
// TODO: implement the last three args here.
|
// 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 ->
|
KonanIr.IrCall.Primitive.NULLARY ->
|
||||||
IrNullaryPrimitiveImpl(start, end, null, createFunctionSymbol(descriptor))
|
IrNullaryPrimitiveImpl(start, end, type.ir, null, createFunctionSymbol(descriptor))
|
||||||
KonanIr.IrCall.Primitive.UNARY ->
|
KonanIr.IrCall.Primitive.UNARY ->
|
||||||
IrUnaryPrimitiveImpl(start, end, null, createFunctionSymbol(descriptor))
|
IrUnaryPrimitiveImpl(start, end, type.ir, null, createFunctionSymbol(descriptor))
|
||||||
KonanIr.IrCall.Primitive.BINARY ->
|
KonanIr.IrCall.Primitive.BINARY ->
|
||||||
IrBinaryPrimitiveImpl(start, end, null, createFunctionSymbol(descriptor))
|
IrBinaryPrimitiveImpl(start, end, type.ir, null, createFunctionSymbol(descriptor))
|
||||||
else -> TODO("Unexpected primitive IrCall.")
|
else -> TODO("Unexpected primitive IrCall.")
|
||||||
}
|
}
|
||||||
deserializeMemberAccessCommon(call, proto.memberAccess)
|
deserializeMemberAccessCommon(call, proto.memberAccess)
|
||||||
@@ -850,7 +855,7 @@ internal class IrDeserializer(val context: Context,
|
|||||||
|
|
||||||
val descriptor = deserializeDescriptor(proto.descriptor) as CallableDescriptor
|
val descriptor = deserializeDescriptor(proto.descriptor) as CallableDescriptor
|
||||||
val callable = when (descriptor) {
|
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()
|
else -> TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -866,12 +871,12 @@ internal class IrDeserializer(val context: Context,
|
|||||||
statementProtos.forEach {
|
statementProtos.forEach {
|
||||||
statements.add(deserializeStatement(it) as IrStatement)
|
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 {
|
private fun deserializeDelegatingConstructorCall(proto: KonanIr.IrDelegatingConstructorCall, start: Int, end: Int): IrDelegatingConstructorCall {
|
||||||
val descriptor = deserializeDescriptor(proto.descriptor) as ClassConstructorDescriptor
|
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)
|
deserializeMemberAccessCommon(call, proto.memberAccess)
|
||||||
return call
|
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 {
|
private fun deserializeGetClass(proto: KonanIr.IrGetClass, start: Int, end: Int, type: KotlinType): IrGetClass {
|
||||||
val argument = deserializeExpression(proto.argument)
|
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 {
|
private fun deserializeGetField(proto: KonanIr.IrGetField, start: Int, end: Int): IrGetField {
|
||||||
@@ -892,39 +897,39 @@ internal class IrDeserializer(val context: Context,
|
|||||||
deserializeExpression(access.receiver)
|
deserializeExpression(access.receiver)
|
||||||
} else null
|
} 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 {
|
private fun deserializeGetValue(proto: KonanIr.IrGetValue, start: Int, end: Int): IrGetValue {
|
||||||
val descriptor = deserializeDescriptor(proto.descriptor) as ValueDescriptor
|
val descriptor = deserializeDescriptor(proto.descriptor) as ValueDescriptor
|
||||||
|
|
||||||
// TODO: origin!
|
// 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 {
|
private fun deserializeGetEnumValue(proto: KonanIr.IrGetEnumValue, start: Int, end: Int): IrGetEnumValue {
|
||||||
val type = deserializeKotlinType(proto.type)
|
val type = deserializeKotlinType(proto.type)
|
||||||
val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor
|
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 {
|
private fun deserializeGetObject(proto: KonanIr.IrGetObject, start: Int, end: Int, type: KotlinType): IrGetObjectValue {
|
||||||
val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor
|
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 {
|
private fun deserializeInstanceInitializerCall(proto: KonanIr.IrInstanceInitializerCall, start: Int, end: Int): IrInstanceInitializerCall {
|
||||||
val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor
|
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 {
|
private fun deserializeReturn(proto: KonanIr.IrReturn, start: Int, end: Int, type: KotlinType): IrReturn {
|
||||||
val descriptor =
|
val descriptor =
|
||||||
deserializeDescriptor(proto.returnTarget) as FunctionDescriptor
|
deserializeDescriptor(proto.returnTarget) as FunctionDescriptor
|
||||||
val value = deserializeExpression(proto.value)
|
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 {
|
private fun deserializeSetField(proto: KonanIr.IrSetField, start: Int, end: Int): IrSetField {
|
||||||
@@ -938,13 +943,13 @@ internal class IrDeserializer(val context: Context,
|
|||||||
} else null
|
} else null
|
||||||
val value = deserializeExpression(proto.value)
|
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 {
|
private fun deserializeSetVariable(proto: KonanIr.IrSetVariable, start: Int, end: Int): IrSetVariable {
|
||||||
val descriptor = deserializeDescriptor(proto.descriptor) as VariableDescriptor
|
val descriptor = deserializeDescriptor(proto.descriptor) as VariableDescriptor
|
||||||
val value = deserializeExpression(proto.value)
|
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 {
|
private fun deserializeSpreadElement(proto: KonanIr.IrSpreadElement): IrSpreadElement {
|
||||||
@@ -959,11 +964,11 @@ internal class IrDeserializer(val context: Context,
|
|||||||
argumentProtos.forEach {
|
argumentProtos.forEach {
|
||||||
arguments.add(deserializeExpression(it))
|
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 {
|
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 {
|
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 =
|
val finallyExpression =
|
||||||
if (proto.hasFinally()) deserializeExpression(proto.getFinally()) else null
|
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 {
|
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 {
|
private fun deserializeTypeOp(proto: KonanIr.IrTypeOp, start: Int, end: Int, type: KotlinType) : IrTypeOperatorCall {
|
||||||
val operator = deserializeTypeOperator(proto.operator)
|
val operator = deserializeTypeOperator(proto.operator)
|
||||||
val operand = deserializeKotlinType(proto.operand)
|
val operand = deserializeKotlinType(proto.operand).brokenIr
|
||||||
val argument = deserializeExpression(proto.argument)
|
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 {
|
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 {
|
proto.elementList.forEach {
|
||||||
elements.add(deserializeVarargElement(it))
|
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 {
|
private fun deserializeVarargElement(element: KonanIr.IrVarargElement): IrVarargElement {
|
||||||
@@ -1033,7 +1041,7 @@ internal class IrDeserializer(val context: Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: provide some origin!
|
// 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 {
|
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 {
|
private fun deserializeDoWhile(proto: KonanIr.IrDoWhile, start: Int, end: Int, type: KotlinType): IrDoWhileLoop {
|
||||||
// we create the loop before deserializing the body, so that
|
// we create the loop before deserializing the body, so that
|
||||||
// IrBreak statements have something to put into 'loop' field.
|
// 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)
|
deserializeLoop(proto.loop, loop)
|
||||||
return 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 {
|
private fun deserializeWhile(proto: KonanIr.IrWhile, start: Int, end: Int, type: KotlinType): IrWhileLoop {
|
||||||
// we create the loop before deserializing the body, so that
|
// we create the loop before deserializing the body, so that
|
||||||
// IrBreak statements have something to put into 'loop' field.
|
// 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)
|
deserializeLoop(proto.loop, loop)
|
||||||
return loop
|
return loop
|
||||||
}
|
}
|
||||||
@@ -1071,7 +1079,7 @@ internal class IrDeserializer(val context: Context,
|
|||||||
val label = if(proto.hasLabel()) proto.label else null
|
val label = if(proto.hasLabel()) proto.label else null
|
||||||
val loopId = proto.loopId
|
val loopId = proto.loopId
|
||||||
val loop = loopIndex[loopId]!!
|
val loop = loopIndex[loopId]!!
|
||||||
val irBreak = IrBreakImpl(start, end, type, loop)
|
val irBreak = IrBreakImpl(start, end, type.ir, loop)
|
||||||
irBreak.label = label
|
irBreak.label = label
|
||||||
|
|
||||||
return irBreak
|
return irBreak
|
||||||
@@ -1081,7 +1089,7 @@ internal class IrDeserializer(val context: Context,
|
|||||||
val label = if(proto.hasLabel()) proto.label else null
|
val label = if(proto.hasLabel()) proto.label else null
|
||||||
val loopId = proto.loopId
|
val loopId = proto.loopId
|
||||||
val loop = loopIndex[loopId]!!
|
val loop = loopIndex[loopId]!!
|
||||||
val irContinue = IrContinueImpl(start, end, type, loop)
|
val irContinue = IrContinueImpl(start, end, type.ir, loop)
|
||||||
irContinue.label = label
|
irContinue.label = label
|
||||||
|
|
||||||
return irContinue
|
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 =
|
private fun deserializeConst(proto: KonanIr.IrConst, start: Int, end: Int, type: KotlinType): IrExpression =
|
||||||
when(proto.valueCase) {
|
when(proto.valueCase) {
|
||||||
NULL
|
NULL
|
||||||
-> IrConstImpl.constNull(start, end, type)
|
-> IrConstImpl.constNull(start, end, type.ir)
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
-> IrConstImpl.boolean(start, end, type, proto.boolean)
|
-> IrConstImpl.boolean(start, end, type.ir, proto.boolean)
|
||||||
BYTE
|
BYTE
|
||||||
-> IrConstImpl.byte(start, end, type, proto.byte.toByte())
|
-> IrConstImpl.byte(start, end, type.ir, proto.byte.toByte())
|
||||||
SHORT
|
SHORT
|
||||||
-> IrConstImpl.short(start, end, type, proto.short.toShort())
|
-> IrConstImpl.short(start, end, type.ir, proto.short.toShort())
|
||||||
INT
|
INT
|
||||||
-> IrConstImpl.int(start, end, type, proto.int)
|
-> IrConstImpl.int(start, end, type.ir, proto.int)
|
||||||
LONG
|
LONG
|
||||||
-> IrConstImpl.long(start, end, type, proto.long)
|
-> IrConstImpl.long(start, end, type.ir, proto.long)
|
||||||
STRING
|
STRING
|
||||||
-> IrConstImpl.string(start, end, type, proto.string)
|
-> IrConstImpl.string(start, end, type.ir, proto.string)
|
||||||
FLOAT
|
FLOAT
|
||||||
-> IrConstImpl.float(start, end, type, proto.float)
|
-> IrConstImpl.float(start, end, type.ir, proto.float)
|
||||||
DOUBLE
|
DOUBLE
|
||||||
-> IrConstImpl.double(start, end, type, proto.double)
|
-> IrConstImpl.double(start, end, type.ir, proto.double)
|
||||||
else -> {
|
else -> {
|
||||||
TODO("Not all const types have been implemented")
|
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)
|
val clazz = IrClassImpl(start, end, origin, descriptor, members)
|
||||||
|
|
||||||
clazz.createParameterDeclarations()
|
val symbolTable = context.ir.symbols.symbolTable
|
||||||
clazz.addFakeOverrides()
|
clazz.createParameterDeclarations(symbolTable)
|
||||||
clazz.setSuperSymbols(context.ir.symbols.symbolTable)
|
clazz.addFakeOverrides(symbolTable)
|
||||||
|
clazz.setSuperSymbols(symbolTable)
|
||||||
|
|
||||||
return clazz
|
return clazz
|
||||||
|
|
||||||
@@ -1203,10 +1212,12 @@ internal class IrDeserializer(val context: Context,
|
|||||||
start: Int, end: Int, origin: IrDeclarationOrigin): IrFunction {
|
start: Int, end: Int, origin: IrDeclarationOrigin): IrFunction {
|
||||||
|
|
||||||
val body = deserializeStatement(proto.body)
|
val body = deserializeStatement(proto.body)
|
||||||
val function = IrFunctionImpl(start, end, origin,
|
val function = IrFunctionImpl(start, end, origin, descriptor)
|
||||||
descriptor, body as IrBody)
|
|
||||||
|
|
||||||
function.createParameterDeclarations()
|
function.returnType = descriptor.returnType!!.ir
|
||||||
|
function.body = body as IrBody
|
||||||
|
|
||||||
|
function.createParameterDeclarations(context.ir.symbols.symbolTable)
|
||||||
function.setOverrides(context.ir.symbols.symbolTable)
|
function.setOverrides(context.ir.symbols.symbolTable)
|
||||||
|
|
||||||
proto.defaultArgumentList.forEach {
|
proto.defaultArgumentList.forEach {
|
||||||
@@ -1226,7 +1237,7 @@ internal class IrDeserializer(val context: Context,
|
|||||||
deserializeExpression(proto.initializer)
|
deserializeExpression(proto.initializer)
|
||||||
} else null
|
} 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,
|
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.pop
|
||||||
import org.jetbrains.kotlin.backend.common.push
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWith
|
||||||
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
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.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
|
|
||||||
@Deprecated("")
|
@Deprecated("")
|
||||||
@@ -47,11 +50,15 @@ internal fun IrModuleFragment.replaceUnboundSymbols(context: Context) {
|
|||||||
|
|
||||||
val symbolTable = context.ir.symbols.symbolTable
|
val symbolTable = context.ir.symbols.symbolTable
|
||||||
|
|
||||||
this.transformChildrenVoid(IrUnboundSymbolReplacer(symbolTable, collector.descriptorToSymbol))
|
this.transformChildrenVoid(IrUnboundSymbolReplacer(symbolTable, collector.descriptorToSymbol, context))
|
||||||
|
|
||||||
// Generate missing external stubs:
|
// Generate missing external stubs:
|
||||||
@Suppress("DEPRECATION")
|
@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:
|
// Merge duplicated module and package declarations:
|
||||||
this.acceptVoid(object : IrElementVisitorVoid {
|
this.acceptVoid(object : IrElementVisitorVoid {
|
||||||
@@ -111,7 +118,8 @@ private class DeclarationSymbolCollector : IrElementVisitorVoid {
|
|||||||
|
|
||||||
private class IrUnboundSymbolReplacer(
|
private class IrUnboundSymbolReplacer(
|
||||||
val symbolTable: SymbolTable,
|
val symbolTable: SymbolTable,
|
||||||
val descriptorToSymbol: Map<DeclarationDescriptor, IrSymbol>
|
val descriptorToSymbol: Map<DeclarationDescriptor, IrSymbol>,
|
||||||
|
val context: Context
|
||||||
) : IrElementTransformerVoid() {
|
) : IrElementTransformerVoid() {
|
||||||
|
|
||||||
private val localDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, MutableList<IrSymbol>>()
|
private val localDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, MutableList<IrSymbol>>()
|
||||||
@@ -163,7 +171,7 @@ private class IrUnboundSymbolReplacer(
|
|||||||
|
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
return with(expression) {
|
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)
|
expression.transformChildrenVoid(this)
|
||||||
return with(expression) {
|
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)
|
expression.transformChildrenVoid(this)
|
||||||
return with(expression) {
|
return with(expression) {
|
||||||
IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.descriptor.defaultType)
|
IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.typeWithStarProjections)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass): IrStatement {
|
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) {
|
withLocal(declaration.thisReceiver?.symbol) {
|
||||||
return super.visitClass(declaration)
|
return super.visitClass(declaration)
|
||||||
}
|
}
|
||||||
@@ -229,7 +231,7 @@ private class IrUnboundSymbolReplacer(
|
|||||||
|
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
return with(expression) {
|
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)
|
expression.transformChildrenVoid(this)
|
||||||
return with(expression) {
|
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 {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
expression.replaceTypeArguments()
|
||||||
|
|
||||||
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: expression.symbol
|
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: expression.symbol
|
||||||
|
|
||||||
val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass)
|
val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass)
|
||||||
@@ -259,17 +263,21 @@ private class IrUnboundSymbolReplacer(
|
|||||||
|
|
||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
return with(expression) {
|
return with(expression) {
|
||||||
IrCallImpl(startOffset, endOffset, symbol, descriptor,
|
IrCallImpl(startOffset, endOffset, type, symbol, descriptor,
|
||||||
getTypeArgumentsMap(),
|
typeArgumentsCount,
|
||||||
origin, superQualifierSymbol).also {
|
origin, superQualifierSymbol).also {
|
||||||
|
|
||||||
it.copyArgumentsFrom(this)
|
it.copyArgumentsFrom(this)
|
||||||
|
it.copyTypeArgumentsFrom(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrMemberAccessExpression.getTypeArgumentsMap() =
|
private fun IrMemberAccessExpression.replaceTypeArguments() {
|
||||||
descriptor.original.typeParameters.associate { it to getTypeArgumentOrDefault(it) }
|
repeat(typeArgumentsCount) {
|
||||||
|
putTypeArgument(it, getTypeArgument(it)?.toKotlinType()?.let { context.ir.translateErased(it) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrMemberAccessExpressionBase.copyArgumentsFrom(original: IrMemberAccessExpression) {
|
private fun IrMemberAccessExpressionBase.copyArgumentsFrom(original: IrMemberAccessExpression) {
|
||||||
dispatchReceiver = original.dispatchReceiver
|
dispatchReceiver = original.dispatchReceiver
|
||||||
@@ -284,37 +292,45 @@ private class IrUnboundSymbolReplacer(
|
|||||||
return super.visitEnumConstructorCall(expression)
|
return super.visitEnumConstructorCall(expression)
|
||||||
|
|
||||||
return with(expression) {
|
return with(expression) {
|
||||||
IrEnumConstructorCallImpl(startOffset, endOffset, symbol, null).also {
|
IrEnumConstructorCallImpl(startOffset, endOffset, expression.type, symbol, 0).also {
|
||||||
it.copyArgumentsFrom(this)
|
it.copyArgumentsFrom(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||||
|
expression.replaceTypeArguments()
|
||||||
|
|
||||||
val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?:
|
val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?:
|
||||||
return super.visitDelegatingConstructorCall(expression)
|
return super.visitDelegatingConstructorCall(expression)
|
||||||
|
|
||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
return with(expression) {
|
return with(expression) {
|
||||||
IrDelegatingConstructorCallImpl(startOffset, endOffset, symbol, descriptor, getTypeArgumentsMap()).also {
|
IrDelegatingConstructorCallImpl(startOffset, endOffset, type, symbol, descriptor, typeArgumentsCount).also {
|
||||||
it.copyArgumentsFrom(this)
|
it.copyArgumentsFrom(this)
|
||||||
|
it.copyTypeArgumentsFrom(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||||
|
expression.replaceTypeArguments()
|
||||||
|
|
||||||
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?:
|
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?:
|
||||||
return super.visitFunctionReference(expression)
|
return super.visitFunctionReference(expression)
|
||||||
|
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
return with(expression) {
|
return with(expression) {
|
||||||
IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, getTypeArgumentsMap()).also {
|
IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, 0).also {
|
||||||
it.copyArgumentsFrom(this)
|
it.copyArgumentsFrom(this)
|
||||||
|
it.copyTypeArgumentsFrom(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
|
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
|
||||||
|
expression.replaceTypeArguments()
|
||||||
|
|
||||||
val field = expression.field?.replaceOrSame(SymbolTable::referenceField)
|
val field = expression.field?.replaceOrSame(SymbolTable::referenceField)
|
||||||
val getter = expression.getter?.replace(SymbolTable::referenceFunction) ?: expression.getter
|
val getter = expression.getter?.replace(SymbolTable::referenceFunction) ?: expression.getter
|
||||||
val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter
|
val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter
|
||||||
@@ -325,13 +341,14 @@ private class IrUnboundSymbolReplacer(
|
|||||||
|
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
return with(expression) {
|
return with(expression) {
|
||||||
IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor,
|
IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor, 0,
|
||||||
field,
|
field,
|
||||||
getter,
|
getter,
|
||||||
setter,
|
setter,
|
||||||
getTypeArgumentsMap(), origin).also {
|
origin).also {
|
||||||
|
|
||||||
it.copyArgumentsFrom(this)
|
it.copyArgumentsFrom(this)
|
||||||
|
it.copyTypeArgumentsFrom(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -413,7 +430,19 @@ private class IrUnboundSymbolReplacer(
|
|||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
return with(expression) {
|
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
|
package org.jetbrains.kotlin.ir.util
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.descriptors.substitute
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanCompilationException
|
import org.jetbrains.kotlin.backend.konan.KonanCompilationException
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
|
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
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.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
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.ir.visitors.IrElementVisitor
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.OverridingStrategy
|
import org.jetbrains.kotlin.resolve.OverridingStrategy
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||||
import java.lang.reflect.Proxy
|
import java.lang.reflect.Proxy
|
||||||
|
|
||||||
//TODO: delete file on next kotlin dependency update
|
//TODO: delete file on next kotlin dependency update
|
||||||
@@ -63,25 +77,20 @@ internal fun IrFile.addTopLevelInitializer(expression: IrExpression) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val builtIns = fieldDescriptor.builtIns
|
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)
|
fieldDescriptor.initialize(null, null)
|
||||||
|
|
||||||
val irField = IrFieldImpl(
|
val irField = IrFieldImpl(
|
||||||
expression.startOffset, expression.endOffset,
|
expression.startOffset, expression.endOffset,
|
||||||
IrDeclarationOrigin.DEFINED, fieldDescriptor
|
IrDeclarationOrigin.DEFINED, fieldDescriptor, expression.type
|
||||||
)
|
)
|
||||||
|
|
||||||
val initializer = IrTypeOperatorCallImpl(
|
irField.initializer = IrExpressionBodyImpl(expression.startOffset, expression.endOffset, expression)
|
||||||
expression.startOffset, expression.endOffset, builtIns.unitType,
|
|
||||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, builtIns.unitType, expression
|
|
||||||
)
|
|
||||||
|
|
||||||
irField.initializer = IrExpressionBodyImpl(expression.startOffset, expression.endOffset, initializer)
|
|
||||||
|
|
||||||
this.addChild(irField)
|
this.addChild(irField)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrClass.addFakeOverrides() {
|
fun IrClass.addFakeOverrides(symbolTable: SymbolTable) {
|
||||||
|
|
||||||
val startOffset = this.startOffset
|
val startOffset = this.startOffset
|
||||||
val endOffset = this.endOffset
|
val endOffset = this.endOffset
|
||||||
@@ -90,17 +99,23 @@ fun IrClass.addFakeOverrides() {
|
|||||||
.filterIsInstance<CallableMemberDescriptor>()
|
.filterIsInstance<CallableMemberDescriptor>()
|
||||||
.filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
|
.filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
|
||||||
.forEach {
|
.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,
|
startOffset, endOffset,
|
||||||
IrDeclarationOrigin.FAKE_OVERRIDE, this
|
IrDeclarationOrigin.FAKE_OVERRIDE, this
|
||||||
).apply {
|
).apply {
|
||||||
createParameterDeclarations()
|
returnType = symbolTable.translateErased(this@createFunction.returnType!!)
|
||||||
|
createParameterDeclarations(symbolTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
return when (descriptor) {
|
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(
|
fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl(
|
||||||
innerStartOffset(this), innerEndOffset(this),
|
innerStartOffset(this), innerEndOffset(this),
|
||||||
IrDeclarationOrigin.DEFINED,
|
IrDeclarationOrigin.DEFINED,
|
||||||
this
|
this, symbolTable.translateErased(this.type),
|
||||||
|
(this as? ValueParameterDescriptor)?.varargElementType?.let { symbolTable.translateErased(it) }
|
||||||
).also {
|
).also {
|
||||||
it.parent = this@createParameterDeclarations
|
it.parent = this@createParameterDeclarations
|
||||||
}
|
}
|
||||||
@@ -138,18 +155,84 @@ fun IrFunction.createParameterDeclarations() {
|
|||||||
it
|
it
|
||||||
).also { typeParameter ->
|
).also { typeParameter ->
|
||||||
typeParameter.parent = this
|
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) {
|
fun IrSimpleFunction.setOverrides(symbolTable: SymbolTable) {
|
||||||
assert(this.overriddenSymbols.isEmpty())
|
assert(this.overriddenSymbols.isEmpty())
|
||||||
|
|
||||||
this.descriptor.overriddenDescriptors.mapTo(this.overriddenSymbols) {
|
this.descriptor.overriddenDescriptors.mapTo(this.overriddenSymbols) {
|
||||||
symbolTable.referenceSimpleFunction(it.original)
|
symbolTable.referenceSimpleFunction(it.original)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.typeParameters.forEach { it.setSupers(symbolTable) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrClass.simpleFunctions(): List<IrSimpleFunction> = this.declarations.flatMap {
|
fun IrClass.simpleFunctions(): List<IrSimpleFunction> = this.declarations.flatMap {
|
||||||
@@ -161,32 +244,56 @@ fun IrClass.simpleFunctions(): List<IrSimpleFunction> = this.declarations.flatMa
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun IrClass.createParameterDeclarations() {
|
fun IrClass.createParameterDeclarations() {
|
||||||
descriptor.thisAsReceiverParameter.let {
|
thisReceiver = IrValueParameterImpl(
|
||||||
thisReceiver = IrValueParameterImpl(
|
startOffset, endOffset,
|
||||||
innerStartOffset(it), innerEndOffset(it),
|
IrDeclarationOrigin.INSTANCE_RECEIVER,
|
||||||
IrDeclarationOrigin.INSTANCE_RECEIVER,
|
descriptor.thisAsReceiverParameter,
|
||||||
it
|
this.symbol.typeWith(this.typeParameters.map { it.defaultType }),
|
||||||
).also { valueParameter ->
|
null
|
||||||
valueParameter.parent = this
|
).also { valueParameter ->
|
||||||
}
|
valueParameter.parent = this
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(typeParameters.isEmpty())
|
assert(typeParameters.isEmpty())
|
||||||
descriptor.declaredTypeParameters.mapTo(typeParameters) {
|
assert(descriptor.declaredTypeParameters.isEmpty())
|
||||||
IrTypeParameterImpl(
|
|
||||||
innerStartOffset(it), innerEndOffset(it),
|
|
||||||
IrDeclarationOrigin.DEFINED,
|
|
||||||
it
|
|
||||||
).also { typeParameter ->
|
|
||||||
typeParameter.parent = this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.superDescriptors().toSet() == supers.map { it.descriptor }.toSet())
|
||||||
assert(this.superClasses.isEmpty())
|
assert(this.superTypes.isEmpty())
|
||||||
supers.mapTo(this.superClasses) { it.symbol }
|
this.superTypes += superTypes
|
||||||
|
|
||||||
val superMembers = supers.flatMap {
|
val superMembers = supers.flatMap {
|
||||||
it.simpleFunctions()
|
it.simpleFunctions()
|
||||||
@@ -206,48 +313,38 @@ private fun IrClass.superDescriptors() =
|
|||||||
this.descriptor.typeConstructor.supertypes.map { it.constructor.declarationDescriptor as ClassDescriptor }
|
this.descriptor.typeConstructor.supertypes.map { it.constructor.declarationDescriptor as ClassDescriptor }
|
||||||
|
|
||||||
fun IrClass.setSuperSymbols(symbolTable: SymbolTable) {
|
fun IrClass.setSuperSymbols(symbolTable: SymbolTable) {
|
||||||
assert(this.superClasses.isEmpty())
|
assert(this.superTypes.isEmpty())
|
||||||
this.superDescriptors().mapTo(this.superClasses) { symbolTable.referenceClass(it) }
|
this.descriptor.typeConstructor.supertypes.mapTo(this.superTypes) { symbolTable.translateErased(it) }
|
||||||
|
|
||||||
this.simpleFunctions().forEach {
|
this.simpleFunctions().forEach {
|
||||||
it.setOverrides(symbolTable)
|
it.setOverrides(symbolTable)
|
||||||
}
|
}
|
||||||
this.typeParameters.forEach {
|
|
||||||
it.setSupers(symbolTable)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrTypeParameter.setSupers(symbolTable: SymbolTable) {
|
fun IrClass.setSuperSymbolsAndAddFakeOverrides(superTypes: List<IrType>) {
|
||||||
assert(this.superClassifiers.isEmpty())
|
|
||||||
this.descriptor.upperBounds.mapNotNullTo(this.superClassifiers) {
|
|
||||||
it.constructor.declarationDescriptor?.let {
|
|
||||||
if (it is TypeParameterDescriptor) {
|
|
||||||
IrTypeParameterSymbolImpl(it) // Workaround for deserialized inline functions
|
|
||||||
} else {
|
|
||||||
symbolTable.referenceClassifier(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun IrClass.setSuperSymbolsAndAddFakeOverrides(supers: List<IrClass>) {
|
|
||||||
val overriddenSuperMembers = this.declarations.map { it.descriptor }
|
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 {
|
val unoverriddenSuperMembers = superTypes.map { it.getClass()!! }.flatMap {
|
||||||
it.declarations.mapNotNull {
|
it.declarations.filter { it.descriptor !in overriddenSuperMembers }.mapNotNull {
|
||||||
when (it) {
|
when (it) {
|
||||||
is IrSimpleFunction -> it.descriptor
|
is IrSimpleFunction -> it.descriptor to it
|
||||||
is IrProperty -> it.descriptor
|
is IrProperty -> it.descriptor to it
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} - overriddenSuperMembers
|
}.toMap()
|
||||||
|
|
||||||
val irClass = this
|
val irClass = this
|
||||||
|
|
||||||
val overridingStrategy = object : OverridingStrategy() {
|
val overridingStrategy = object : OverridingStrategy() {
|
||||||
override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) {
|
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) {
|
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(
|
OverridingUtil.generateOverridesInFunctionGroup(
|
||||||
name,
|
name,
|
||||||
members,
|
members,
|
||||||
@@ -269,7 +366,7 @@ fun IrClass.setSuperSymbolsAndAddFakeOverrides(supers: List<IrClass>) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setSuperSymbols(supers)
|
this.setSuperSymbols(superTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int =
|
private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int =
|
||||||
@@ -327,7 +424,7 @@ object CheckDeclarationParentsVisitor : IrElementVisitor<Unit, IrDeclarationPare
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclarationParent?) {
|
override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclarationParent?) {
|
||||||
if (declaration !is IrVariable) {
|
if (declaration !is IrVariable && declaration !is IrValueParameter && declaration !is IrTypeParameter) {
|
||||||
checkParent(declaration, data)
|
checkParent(declaration, data)
|
||||||
} else {
|
} else {
|
||||||
// Don't check IrVariable parent.
|
// Don't check IrVariable parent.
|
||||||
@@ -376,7 +473,7 @@ internal fun KonanBackendContext.report(declaration: IrDeclaration, message: Str
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun IrBuilderWithScope.irForceNotNull(expression: IrExpression): IrExpression {
|
fun IrBuilderWithScope.irForceNotNull(expression: IrExpression): IrExpression {
|
||||||
if (!TypeUtils.isNullableType(expression.type)) {
|
if (!expression.type.containsNull()) {
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,9 +481,263 @@ fun IrBuilderWithScope.irForceNotNull(expression: IrExpression): IrExpression {
|
|||||||
val temporary = irTemporaryVar(expression)
|
val temporary = irTemporaryVar(expression)
|
||||||
+irIfNull(
|
+irIfNull(
|
||||||
expression.type,
|
expression.type,
|
||||||
subject = irGet(temporary.symbol),
|
subject = irGet(temporary),
|
||||||
thenPart = irThrowNpe(IrStatementOrigin.EXCLEXCL),
|
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
|
//For KT-6020
|
||||||
import kotlin.reflect.KProperty1
|
import kotlin.reflect.KProperty1
|
||||||
import kotlin.reflect.KMutableProperty1
|
import kotlin.reflect.KMutableProperty1
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class Worker(val id: WorkerId) {
|
|||||||
* until all scheduled jobs processed, or terminate immediately.
|
* until all scheduled jobs processed, or terminate immediately.
|
||||||
*/
|
*/
|
||||||
fun requestTermination(processScheduledJobs: Boolean = true) =
|
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,
|
* Schedule a job for further execution in the worker. Schedule is a two-phase operation,
|
||||||
|
|||||||
Reference in New Issue
Block a user