diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt index cdd3f90c633..420b625c2b2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt @@ -54,13 +54,14 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl protected open fun IrExpression.useAsArgument(parameter: ParameterDescriptor): IrExpression = this.useAsValue(parameter) - protected open fun IrExpression.useAsDispatchReceiver(function: CallableDescriptor): IrExpression = - this.useAsArgument(function.dispatchReceiverParameter!!) + protected open fun IrExpression.useAsDispatchReceiver(expression: IrMemberAccessExpression): IrExpression = + this.useAsArgument(expression.descriptor.dispatchReceiverParameter!!) - protected open fun IrExpression.useAsExtensionReceiver(function: CallableDescriptor): IrExpression = - this.useAsArgument(function.extensionReceiverParameter!!) + protected open fun IrExpression.useAsExtensionReceiver(expression: IrMemberAccessExpression): IrExpression = + this.useAsArgument(expression.descriptor.extensionReceiverParameter!!) - protected open fun IrExpression.useAsValueArgument(parameter: ValueParameterDescriptor): IrExpression = + protected open fun IrExpression.useAsValueArgument(expression: IrMemberAccessExpression, + parameter: ValueParameterDescriptor): IrExpression = this.useAsArgument(parameter) protected open fun IrExpression.useForVariable(variable: VariableDescriptor): IrExpression = @@ -81,12 +82,12 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl expression.transformChildrenVoid(this) with(expression) { - dispatchReceiver = dispatchReceiver?.useAsDispatchReceiver(descriptor) - extensionReceiver = extensionReceiver?.useAsExtensionReceiver(descriptor) + dispatchReceiver = dispatchReceiver?.useAsDispatchReceiver(expression) + extensionReceiver = extensionReceiver?.useAsExtensionReceiver(expression) for (index in descriptor.valueParameters.indices) { val argument = getValueArgument(index) ?: continue val parameter = descriptor.valueParameters[index] - putValueArgument(index, argument.useAsValueArgument(parameter)) + putValueArgument(index, argument.useAsValueArgument(expression, parameter)) } } @@ -240,7 +241,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl declaration.descriptor.valueParameters.forEach { parameter -> val defaultValue = declaration.getDefault(parameter) if (defaultValue is IrExpressionBody) { - defaultValue.expression = defaultValue.expression.useAsValueArgument(parameter) + defaultValue.expression = defaultValue.expression.useAsArgument(parameter) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt index 528d2b7422a..a7029a86c45 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt @@ -17,8 +17,12 @@ package org.jetbrains.kotlin.backend.common import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.makeNullable @@ -44,6 +48,12 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor } } + private fun IrSymbol.ensureBound(expression: IrExpression) { + if (!this.isBound) { + reportError(expression, "Unbound symbol ${this}") + } + } + override fun visitConst(expression: IrConst) { super.visitConst(expression) @@ -110,6 +120,8 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor } else { expression.ensureTypeIs(returnType) } + + expression.superQualifierSymbol?.ensureBound(expression) } override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) { @@ -128,6 +140,7 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor super.visitInstanceInitializerCall(expression) expression.ensureTypeIs(builtIns.unitType) + expression.classSymbol.ensureBound(expression) } override fun visitTypeOperator(expression: IrTypeOperatorCall) { @@ -173,6 +186,7 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor super.visitReturn(expression) expression.ensureTypeIs(builtIns.nothingType) + expression.returnTargetSymbol.ensureBound(expression) } override fun visitThrow(expression: IrThrow) { @@ -180,4 +194,60 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor expression.ensureTypeIs(builtIns.nothingType) } + + override fun visitClass(declaration: IrClass) { + super.visitClass(declaration) + + if (declaration.descriptor.kind != ClassKind.ANNOTATION_CLASS) { + // Check that all functions and properties from memberScope are present in IR + // (including FAKE_OVERRIDE ones). + + val allDescriptors = declaration.descriptor.unsubstitutedMemberScope + .getContributedDescriptors().filterIsInstance() + + val presentDescriptors = declaration.declarations.map { it.descriptor } + + val missingDescriptors = allDescriptors - presentDescriptors + + if (missingDescriptors.isNotEmpty()) { + reportError(declaration, "Missing declarations for descriptors:\n" + + missingDescriptors.joinToString("\n")) + } + } + } + + override fun visitDeclarationReference(expression: IrDeclarationReference) { + super.visitDeclarationReference(expression) + + expression.symbol.ensureBound(expression) + } + + override fun visitFunctionAccess(expression: IrFunctionAccessExpression) { + super.visitFunctionAccess(expression) + + expression.symbol.ensureBound(expression) + } + + override fun visitFunctionReference(expression: IrFunctionReference) { + super.visitFunctionReference(expression) + + expression.symbol.ensureBound(expression) + } + + override fun visitPropertyReference(expression: IrPropertyReference) { + super.visitPropertyReference(expression) + + expression.field?.ensureBound(expression) + expression.getter?.ensureBound(expression) + expression.setter?.ensureBound(expression) + } + + override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference) { + super.visitLocalDelegatedPropertyReference(expression) + + expression.delegate.ensureBound(expression) + expression.getter.ensureBound(expression) + expression.setter?.ensureBound(expression) + } + } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt index e72cfb196d7..f2dda12fece 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt @@ -16,54 +16,18 @@ package org.jetbrains.kotlin.backend.common -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.backend.konan.ir.DeepCopyKonanIrTreeWithSymbols +import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.declarations.IrVariable -import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrSetVariableImpl -import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl -import org.jetbrains.kotlin.ir.util.DeepCopyIrTree -import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols +import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.util.DeepCopySymbolsRemapper -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.util.DescriptorsRemapper import org.jetbrains.kotlin.ir.visitors.acceptVoid -/** - * Copies IR tree with descriptors of all declarations inside; - * updates the references to these declarations. - */ -@Deprecated("Creates unbound symbols") -open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() { - - private fun DeclarationDescriptor.notSupported(): Nothing = TODO("${this}") - - override fun mapModuleDescriptor(descriptor: ModuleDescriptor) = descriptor.notSupported() - override fun mapPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor) = descriptor.notSupported() - override fun mapClassDeclaration(descriptor: ClassDescriptor) = descriptor.notSupported() - override fun mapTypeAliasDeclaration(descriptor: TypeAliasDescriptor) = descriptor.notSupported() - override fun mapFunctionDeclaration(descriptor: FunctionDescriptor) = descriptor.notSupported() - override fun mapConstructorDeclaration(descriptor: ClassConstructorDescriptor) = descriptor.notSupported() - override fun mapPropertyDeclaration(descriptor: PropertyDescriptor) = descriptor.notSupported() - override fun mapLocalPropertyDeclaration(descriptor: VariableDescriptorWithAccessors) = descriptor.notSupported() - override fun mapEnumEntryDeclaration(descriptor: ClassDescriptor) = descriptor.notSupported() - - val copiedVariables = mutableMapOf() - - override fun mapVariableDeclaration(descriptor: VariableDescriptor): VariableDescriptor { - // TODO: how to ensure that the variable is not visible from outside of the transformed IR? - - if (descriptor is VariableDescriptorWithAccessors && (descriptor.getter != null || descriptor.setter != null)) { - TODO("$descriptor with accessors") - } - - val newDescriptor = LocalVariableDescriptor( +fun IrElement.deepCopyWithVariablesImpl(): IrElement { + val descriptorsRemapper = object : DescriptorsRemapper { + override fun remapDeclaredVariable(descriptor: VariableDescriptor) = LocalVariableDescriptor( /* containingDeclaration = */ descriptor.containingDeclaration, /* annotations = */ descriptor.annotations, /* name = */ descriptor.name, @@ -72,103 +36,19 @@ open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() { /* isDelegated = */ false, /* source = */ descriptor.source ) - - assert (descriptor !in copiedVariables) - copiedVariables[descriptor] = newDescriptor - - return newDescriptor } - // Note: the reference to a variable can be traversed only after the declaration of that variable, - // so it is correct to map only references whose descriptors have copies. - // However such approach can be incorrect when copying functions, classes etc. + val symbolsRemapper = DeepCopySymbolsRemapper(descriptorsRemapper) + acceptVoid(symbolsRemapper) - override fun mapValueReference(descriptor: ValueDescriptor) = - copiedVariables[descriptor] ?: descriptor - - override fun mapVariableReference(descriptor: VariableDescriptor) = - copiedVariables[descriptor] ?: descriptor - - override fun visitBlock(expression: IrBlock): IrBlock { - return if (expression is IrReturnableBlock) { - IrReturnableBlockImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - type = expression.type, - descriptor = expression.descriptor, - origin = mapStatementOrigin(expression.origin), - statements = expression.statements.map { it.transform(this, null) } - ) - } else { - super.visitBlock(expression) - } - } - - override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop { - return irLoop - } -} - -fun IrElement.deepCopyWithVariablesImpl(): IrElement { - // FIXME: support non-transformed loops - - val remapper = DeepCopySymbolsRemapper() - acceptVoid(remapper) - - val variableDescriptorReplacer = object : IrElementTransformerVoid() { - - val copiedVariables = mutableMapOf() - - override fun visitVariable(declaration: IrVariable): IrStatement { - declaration.transformChildrenVoid() - - val descriptor = declaration.descriptor - val newDescriptor = LocalVariableDescriptor( - /* containingDeclaration = */ descriptor.containingDeclaration, - /* annotations = */ descriptor.annotations, - /* name = */ descriptor.name, - /* type = */ descriptor.type, - /* mutable = */ descriptor.isVar, - /* isDelegated = */ false, - /* source = */ descriptor.source - ) - val newSymbol = IrVariableSymbolImpl(newDescriptor) - copiedVariables[declaration.symbol] = newSymbol - - return with(declaration) { - IrVariableImpl(startOffset, endOffset, origin, newSymbol).also { - it.initializer = initializer + return this.transform( + object : DeepCopyKonanIrTreeWithSymbols(symbolsRemapper) { + override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop { + return irLoop } - } - - } - - override fun visitValueAccess(expression: IrValueAccessExpression): IrExpression { - assert(expression.symbol !in copiedVariables) - return super.visitValueAccess(expression) - } - - override fun visitGetValue(expression: IrGetValue): IrExpression { - val newSymbol = copiedVariables[expression.symbol] ?: return super.visitGetValue(expression) - - expression.transformChildrenVoid() - return with(expression) { - IrGetValueImpl(startOffset, endOffset, newSymbol, origin) - } - } - - override fun visitSetVariable(expression: IrSetVariable): IrExpression { - val newSymbol = copiedVariables[expression.symbol] ?: return super.visitSetVariable(expression) - - expression.transformChildrenVoid() - return with(expression) { - IrSetVariableImpl(startOffset, endOffset, newSymbol, value, origin) - } - } - - } - - return this.transform(DeepCopyIrTreeWithSymbols(remapper), null).transform(variableDescriptorReplacer, null) + }, + null + ) } inline fun T.deepCopyWithVariables(): T = diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt index f01e998e957..3e3a4c81e73 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt @@ -86,9 +86,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: DeclarationDe val contributedDescriptors = oldDescriptor.unsubstitutedMemberScope .getContributedDescriptors() .map { - if (it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) - it - else descriptorSubstituteMap[it]!! + descriptorSubstituteMap[it]!! } newDescriptor.initialize( SimpleMemberScope(contributedDescriptors), diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt index 30f17f4b6cb..b73ee248708 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt @@ -16,21 +16,12 @@ package org.jetbrains.kotlin.backend.common -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid -import org.jetbrains.kotlin.resolve.descriptorUtil.module - -fun validateIrFunction(context: BackendContext, irFunction: IrFunction) { - val visitor = IrValidator(context, false) - irFunction.acceptVoid(visitor) -} fun validateIrFile(context: BackendContext, irFile: IrFile) { val visitor = IrValidator(context, false) @@ -41,51 +32,7 @@ fun validateIrModule(context: BackendContext, irModule: IrModuleFragment) { val visitor = IrValidator(context, true) // TODO: consider taking the boolean from settings. irModule.acceptVoid(visitor) - // TODO: investigate and re-enable - val ENABLE_EXTENDED_VALIDATION = false - if (!ENABLE_EXTENDED_VALIDATION) { - return - } - - val moduleDeclarations = visitor.foundDeclarations - - irModule.acceptVoid(object : IrElementVisitorVoid { - lateinit var currentFile: IrFile - - override fun visitFile(declaration: IrFile) { - currentFile = declaration - declaration.acceptChildrenVoid(this) - } - - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitProperty(declaration: IrProperty) { - if (declaration.descriptor.modality == Modality.ABSTRACT) { - return // Workaround TODO - } - - declaration.acceptChildrenVoid(this) - } - - override fun visitDeclarationReference(expression: IrDeclarationReference) { - expression.acceptChildrenVoid(this) - - val declarationDescriptor = expression.irDeclarationDescriptor ?: return - - val declarationModule = declarationDescriptor.module - - if (declarationModule == irModule.descriptor && !moduleDeclarations.hasTarget(expression)) { - context.reportIrValidationError( - "declaration $declarationDescriptor is missing;\n" + - "references from:\n" + - expression.render(), - - currentFile, expression) - } - } - }) + // TODO: also check that all referenced symbol targets are reachable. } private fun BackendContext.reportIrValidationError(message: String, irFile: IrFile, irElement: IrElement) { @@ -98,86 +45,8 @@ private fun BackendContext.reportIrValidationError(message: String, irFile: IrFi // TODO: throw an exception after fixing bugs leading to invalid IR. } -/** - * Descriptor to be found in IR element declaring target of this reference, - * or `null` if it is not supported yet. - */ -private val IrDeclarationReference.irDeclarationDescriptor: DeclarationDescriptor? - get() { - when (this) { - is IrFieldAccessExpression -> return this.descriptor.original - - is IrMemberAccessExpression -> { - val original = this.descriptor.original - if (original is CallableMemberDescriptor && !original.kind.isReal) { - return null - } - - if (original is TypeAliasConstructorDescriptor) { - return original.underlyingConstructorDescriptor - } - - return original - } - - is IrGetValue -> { - if (this.descriptor is ParameterDescriptor) { - return null - } - - return this.descriptor - } - - else -> return this.descriptor - } - } - -private val IrDeclarationReference.declarationKind: IrDeclarationKind - get() = when (this) { - is IrClassReference, is IrGetObjectValue -> IrDeclarationKind.CLASS - is IrFieldAccessExpression -> IrDeclarationKind.FIELD - is IrGetEnumValue -> IrDeclarationKind.ENUM_ENTRY - is IrValueAccessExpression -> IrDeclarationKind.VARIABLE - is IrMemberAccessExpression -> when (this.descriptor) { - is ConstructorDescriptor -> IrDeclarationKind.CONSTRUCTOR - is PropertyDescriptor -> IrDeclarationKind.PROPERTY - is VariableDescriptorWithAccessors -> IrDeclarationKind.LOCAL_PROPERTY - else -> IrDeclarationKind.FUNCTION - } - else -> TODO() - } - -/** - * The collection of IR declarations. - */ -private class Declarations { - private data class DeclarationKey(val descriptor: DeclarationDescriptor, val kind: IrDeclarationKind) - - private val declarations = mutableSetOf() - - private fun createKey(declaration: IrDeclaration) = - DeclarationKey(declaration.descriptor, declaration.declarationKind) - - fun add(declaration: IrDeclaration) { - declarations.add(createKey(declaration)) - } - - fun isAlreadyDeclared(declaration: IrDeclaration): Boolean { - return createKey(declaration) in declarations - } - - fun hasTarget(reference: IrDeclarationReference): Boolean { - val descriptor = reference.irDeclarationDescriptor ?: return false - val kind = reference.declarationKind - - return DeclarationKey(descriptor, kind) in declarations - } -} - private class IrValidator(val context: BackendContext, performHeavyValidations: Boolean) : IrElementVisitorVoid { - val foundDeclarations = Declarations() - val builtIns = context.builtIns lateinit var currentFile: IrFile @@ -200,25 +69,4 @@ private class IrValidator(val context: BackendContext, performHeavyValidations: element.acceptVoid(elementChecker) element.acceptChildrenVoid(this) } - - private fun recordDeclaration(declaration: IrDeclaration) { - if (foundDeclarations.isAlreadyDeclared(declaration)) { - if (declaration !is IrValueParameter && declaration !is IrTypeParameter) { - // TODO: remove the check. - error(declaration, "redeclaration") - } - } else { - foundDeclarations.add(declaration) - } - } - - override fun visitDeclaration(declaration: IrDeclaration) { - recordDeclaration(declaration) - super.visitDeclaration(declaration) - } - - override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) { - // Do not treat anonymous initializers as declarations, because they are not unique. - super.visitDeclaration(declaration) - } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorUtils.kt index a4bd1149e3b..fdee4b38a94 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorUtils.kt @@ -58,20 +58,6 @@ internal val CallableDescriptor.explicitParameters: List return result } -/** - * Returns the parameter in the original function corresponding to given parameter of this function. - * - * Note: `parameter.original` doesn't seem to be always the parameter of `this.original`. - * - * @param parameter must be declared in this function - */ -fun CallableDescriptor.getOriginalParameter(parameter: ParameterDescriptor): ParameterDescriptor = when (parameter) { - is ValueParameterDescriptor -> this.original.valueParameters[parameter.index] - this.dispatchReceiverParameter -> this.original.dispatchReceiverParameter!! - this.extensionReceiverParameter -> this.original.extensionReceiverParameter!! - else -> TODO("$parameter in $this") -} - fun KotlinType.replace(types: List) = this.replace(types.map(::TypeProjectionImpl)) fun FunctionDescriptor.substitute(vararg types: KotlinType): FunctionDescriptor { @@ -83,6 +69,13 @@ fun FunctionDescriptor.substitute(vararg types: KotlinType): FunctionDescriptor return substitute(typeSubstitutor)!! } +fun FunctionDescriptor.substitute(typeArguments: Map): FunctionDescriptor { + val typeSubstitutor = TypeSubstitutor.create( + typeParameters.associateBy({ it.typeConstructor }, { TypeProjectionImpl(typeArguments[it]!!) }) + ) + return substitute(typeSubstitutor)!! +} + fun ClassDescriptor.getFunction(name: String, types: List): FunctionDescriptor { val typeSubstitutor = TypeSubstitutor.create( declaredTypeParameters diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt index b8c1e874dcf..41b9e7ccdf0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin @@ -48,39 +47,16 @@ import org.jetbrains.kotlin.utils.Printer class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContext(backendContext.irBuiltIns) -class DeclarationIrBuilder : IrBuilderWithScope { - - constructor( - backendContext: BackendContext, - symbol: IrSymbol, - startOffset: Int = UNDEFINED_OFFSET, - endOffset: Int = UNDEFINED_OFFSET - ) : super( - IrLoweringContext(backendContext), - Scope(symbol), - startOffset, - endOffset - ) - - @Deprecated("Creates unbound symbol") - constructor( - backendContext: BackendContext, - declarationDescriptor: DeclarationDescriptor, - startOffset: Int = UNDEFINED_OFFSET, - endOffset: Int = UNDEFINED_OFFSET - ) : super( - IrLoweringContext(backendContext), - Scope(declarationDescriptor), - startOffset, - endOffset - ) -} - -@Deprecated("Creates unbound symbol") -fun BackendContext.createIrBuilder(declarationDescriptor: DeclarationDescriptor, - startOffset: Int = UNDEFINED_OFFSET, - endOffset: Int = UNDEFINED_OFFSET) = - DeclarationIrBuilder(this, declarationDescriptor, startOffset, endOffset) +class DeclarationIrBuilder( + backendContext: BackendContext, + symbol: IrSymbol, + startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET +) : IrBuilderWithScope( + IrLoweringContext(backendContext), + Scope(symbol), + startOffset, + endOffset +) fun BackendContext.createIrBuilder(symbol: IrSymbol, startOffset: Int = UNDEFINED_OFFSET, @@ -101,25 +77,9 @@ inline fun IrGeneratorWithScope.irBlock(expression: IrExpression, origin: IrStat inline fun IrGeneratorWithScope.irBlockBody(irElement: IrElement, body: IrBlockBodyBuilder.() -> Unit) = this.irBlockBody(irElement.startOffset, irElement.endOffset, body) - -@Deprecated("Creates unbound symbol") -fun IrBuilderWithScope.irUnit() = - IrGetObjectValueImpl(startOffset, endOffset, context.builtIns.unitType, context.builtIns.unit) - fun IrBuilderWithScope.irIfThen(condition: IrExpression, thenPart: IrExpression) = IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, thenPart, null) -@Deprecated("Creates unbound symbol") -fun IrBuilderWithScope.irGet(descriptor: PropertyDescriptor) = - IrCallImpl(startOffset, endOffset, descriptor.getter!!) - -@Deprecated("Creates unbound symbol") -fun IrBuilderWithScope.irSet(receiver: IrExpression, descriptor: PropertyDescriptor, arg: IrExpression) = - IrCallImpl(startOffset, endOffset, descriptor.setter!!).apply { - dispatchReceiver = receiver - putValueArgument(0, arg) - } - fun IrBuilderWithScope.irNot(arg: IrExpression) = primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL, arg) @@ -139,30 +99,21 @@ fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) = IrTypeOperatorCallImpl(startOffset, endOffset, context.builtIns.unitType, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.builtIns.unitType, arg) -@Deprecated("Creates unbound symbol") -fun IrBuilderWithScope.irGetField(receiver: IrExpression, descriptor: PropertyDescriptor) = - IrGetFieldImpl(startOffset, endOffset, descriptor, receiver) - -@Deprecated("Creates unbound symbol") -fun IrBuilderWithScope.irSetField(receiver: IrExpression, descriptor: PropertyDescriptor, value: IrExpression) = - IrSetFieldImpl(startOffset, endOffset, descriptor, receiver, value) - fun IrBuilderWithScope.irGetField(receiver: IrExpression, symbol: IrFieldSymbol) = IrGetFieldImpl(startOffset, endOffset, symbol, receiver) fun IrBuilderWithScope.irSetField(receiver: IrExpression, symbol: IrFieldSymbol, value: IrExpression) = IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value) -@Deprecated("Creates unbound symbol") open class IrBuildingTransformer(private val context: BackendContext) : IrElementTransformerVoid() { private var currentBuilder: IrBuilderWithScope? = null protected val builder: IrBuilderWithScope get() = currentBuilder!! - private inline fun withBuilder(declarationDescriptor: DeclarationDescriptor, block: () -> T): T { + private inline fun withBuilder(symbol: IrSymbol, block: () -> T): T { val oldBuilder = currentBuilder - currentBuilder = context.createIrBuilder(declarationDescriptor) + currentBuilder = context.createIrBuilder(symbol) return try { block() } finally { @@ -171,20 +122,20 @@ open class IrBuildingTransformer(private val context: BackendContext) : IrElemen } override fun visitFunction(declaration: IrFunction): IrStatement { - withBuilder(declaration.descriptor) { + withBuilder(declaration.symbol) { return super.visitFunction(declaration) } } override fun visitField(declaration: IrField): IrStatement { - withBuilder(declaration.descriptor) { + withBuilder(declaration.symbol) { // Transforms initializer: return super.visitField(declaration) } } override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement { - withBuilder(declaration.descriptor) { + withBuilder(declaration.symbol) { return super.visitAnonymousInitializer(declaration) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt index 7c3ccc2bba6..39fc43f7bae 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt @@ -33,7 +33,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid * This pass lowers tail recursion calls in `tailrec` functions. * * Note: it currently can't handle local functions and classes declared in default arguments. - * See [DeepCopyIrTreeWithDeclarations]. + * See [deepCopyWithVariables]. */ internal class TailrecLowering(val context: BackendContext) : FunctionLoweringPass { override fun lower(irFunction: IrFunction) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt index 3c47631d587..9a51f53abee 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt @@ -25,10 +25,7 @@ import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.util.createParameterDeclarations -import org.jetbrains.kotlin.ir.util.endOffsetOrUndefined -import org.jetbrains.kotlin.ir.util.functions -import org.jetbrains.kotlin.ir.util.startOffsetOrUndefined +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope @@ -75,6 +72,7 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) { implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor) val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor).apply { createParameterDeclarations() + addFakeOverrides() } val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt index bf024d1ac3a..59d928b5d1f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt @@ -16,17 +16,12 @@ package org.jetbrains.kotlin.backend.konan -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.StarProjectionImpl import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.replace -import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf private val cPointerName = "CPointer" private val nativePointedName = "NativePointed" @@ -67,53 +62,12 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns) { TypeUtils.getClassDescriptor(extensionReceiverParameter.type) == nativePointed } - val memberAt = packageScope.getContributedFunctions("memberAt").single() - val interpretNullablePointed = packageScope.getContributedFunctions("interpretNullablePointed").single() val interpretCPointer = packageScope.getContributedFunctions("interpretCPointer").single() - val variableClass = packageScope.getContributedClassifier("CVariable") as ClassDescriptor - - val arrayGetByIntIndex = packageScope.getContributedFunctions("get").single { - KotlinBuiltIns.isInt(it.valueParameters.single().type) && - it.typeParameters.single().upperBounds.single() == variableClass.defaultType - } - - val arrayGetByLongIndex = packageScope.getContributedFunctions("get").single { - KotlinBuiltIns.isLong(it.valueParameters.single().type) && - it.typeParameters.single().upperBounds.single() == variableClass.defaultType - } - - val allocUninitializedArrayWithIntLength = packageScope.getContributedFunctions("allocArray").single { - it.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.valueParameters[0].type) - } - - val allocUninitializedArrayWithLongLength = packageScope.getContributedFunctions("allocArray").single { - it.valueParameters.size == 1 && KotlinBuiltIns.isLong(it.valueParameters[0].type) - } - - val allocVariable = packageScope.getContributedFunctions("alloc").single { - it.valueParameters.size == 0 - } - - val readValue = packageScope.getContributedFunctions("readValue").single { - it.valueParameters.size == 0 - } - - val readValueBySizeAndAlign = packageScope.getContributedFunctions("readValue").single { - it.valueParameters.size == 2 - } - val typeOf = packageScope.getContributedFunctions("typeOf").single() - val variableTypeClass = - variableClass.unsubstitutedInnerClassesScope.getContributedClassifier("Type") as ClassDescriptor - - val variableTypeSize = variableTypeClass.unsubstitutedMemberScope.getContributedVariables("size").single() - - val variableTypeAlign = variableTypeClass.unsubstitutedMemberScope.getContributedVariables("align").single() - val nativeMemUtils = packageScope.getContributedClassifier("nativeMemUtils") as ClassDescriptor private val primitives = listOf( diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt index 7e296bc23cc..3c0634e4b92 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt @@ -19,13 +19,11 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.validateIrFile +import org.jetbrains.kotlin.backend.common.validateIrModule import org.jetbrains.kotlin.backend.konan.lower.* -import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.util.IrSymbolBindingChecker import org.jetbrains.kotlin.ir.util.replaceUnboundSymbols -import org.jetbrains.kotlin.ir.visitors.acceptVoid internal class KonanLower(val context: Context) { @@ -49,9 +47,14 @@ internal class KonanLower(val context: Context) { // Inlining must be run before other phases. phaser.phase(KonanPhase.LOWER_INLINE) { FunctionInlining(context).inline(irModule) - irModule.replaceUnboundSymbols(context) - irModule.checkSymbolsBound() } + + phaser.phase(KonanPhase.LOWER_INTEROP_PART1) { + irModule.files.forEach(InteropLoweringPart1(context)::lower) + } + + irModule.replaceUnboundSymbols(context) + validateIrModule(context, irModule) } fun lowerFile(irFile: IrFile) { @@ -59,31 +62,24 @@ internal class KonanLower(val context: Context) { phaser.phase(KonanPhase.LOWER_STRING_CONCAT) { StringConcatenationLowering(context).lower(irFile) - irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_ENUMS) { EnumClassLowering(context).run(irFile) - irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_INITIALIZERS) { InitializersLowering(context).runOnFilePostfix(irFile) - irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_SHARED_VARIABLES) { SharedVariablesLowering(context).runOnFilePostfix(irFile) - irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_DELEGATION) { PropertyDelegationLowering(context).lower(irFile) - irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_LOCAL_FUNCTIONS) { LocalDeclarationsLowering(context).runOnFilePostfix(irFile) - irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_TAILREC) { TailrecLowering(context).runOnFilePostfix(irFile) - irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_FINALLY) { FinallyBlocksLowering(context).runOnFilePostfix(irFile) @@ -101,8 +97,8 @@ internal class KonanLower(val context: Context) { phaser.phase(KonanPhase.LOWER_INNER_CLASSES) { InnerClassLowering(context).runOnFilePostfix(irFile) } - phaser.phase(KonanPhase.LOWER_INTEROP) { - InteropLowering(context).lower(irFile) + phaser.phase(KonanPhase.LOWER_INTEROP_PART2) { + InteropLoweringPart2(context).lower(irFile) } phaser.phase(KonanPhase.LOWER_CALLABLES) { CallableReferenceLowering(context).runOnFilePostfix(irFile) @@ -118,7 +114,6 @@ internal class KonanLower(val context: Context) { } phaser.phase(KonanPhase.BRIDGES_BUILDING) { BridgesBuilding(context).runOnFilePostfix(irFile) - DirectBridgesCallsLowering(context).runOnFilePostfix(irFile) } phaser.phase(KonanPhase.AUTOBOX) { validateIrFile(context, irFile) @@ -126,9 +121,4 @@ internal class KonanLower(val context: Context) { } } - private fun IrElement.checkSymbolsBound() { - if (context.shouldVerifyIr()) { - this.acceptVoid(IrSymbolBindingChecker()) - } - } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt index c5ef1269159..e7ed6213198 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt @@ -30,13 +30,14 @@ enum class KonanPhase(val description: String, /* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation"), /* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS), /* ... ... ... */ DESERIALIZER("Deserialize inline bodies"), + /* ... ... */ LOWER_INTEROP_PART1("Interop lowering, part 1", LOWER_INLINE), /* ... ... */ LOWER_ENUMS("Enum classes lowering"), /* ... ... */ LOWER_DELEGATION("Delegation lowering"), /* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUMS), /* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", LOWER_INITIALIZERS), /* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering", LOWER_SHARED_VARIABLES), - /* ... ... */ LOWER_INTEROP("Interop lowering", LOWER_LOCAL_FUNCTIONS), - /* ... ... */ LOWER_CALLABLES("Callable references Lowering", LOWER_INTEROP, LOWER_DELEGATION, LOWER_LOCAL_FUNCTIONS), + /* ... ... */ LOWER_INTEROP_PART2("Interop lowering, part 2", LOWER_LOCAL_FUNCTIONS), + /* ... ... */ LOWER_CALLABLES("Callable references Lowering", LOWER_INTEROP_PART2, LOWER_DELEGATION, LOWER_LOCAL_FUNCTIONS), /* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES), /* ... ... */ LOWER_TAILREC("tailrec lowering", LOWER_LOCAL_FUNCTIONS), /* ... ... */ LOWER_FINALLY("Finally blocks lowering", LOWER_INITIALIZERS, LOWER_LOCAL_FUNCTIONS, LOWER_TAILREC), diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index a526a0794d3..dd5489bc052 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -18,23 +18,29 @@ package org.jetbrains.kotlin.backend.konan.ir import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.KonanBuiltIns +import org.jetbrains.kotlin.backend.konan.ValueType import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions +import org.jetbrains.kotlin.backend.konan.descriptors.konanInternal +import org.jetbrains.kotlin.backend.konan.util.atMostOne +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi2ir.generators.SymbolTable +import org.jetbrains.kotlin.util.OperatorNameConventions // This is what Context collects about IR. internal class Ir(val context: Context, val irModule: IrModuleFragment) { val propertiesWithBackingFields = mutableSetOf() - val defaultParameterDescriptorsCache = mutableMapOf() + val defaultParameterDeclarationsCache = mutableMapOf() val originalModuleIndex = ModuleIndex(irModule) @@ -67,13 +73,31 @@ internal class Symbols(val context: Context, val symbolTable: SymbolTable) { val ThrowTypeCastException = symbolTable.referenceSimpleFunction( builtIns.getKonanInternalFunctions("ThrowTypeCastException").single()) + val ThrowUninitializedPropertyAccessException = symbolTable.referenceSimpleFunction( + builtIns.getKonanInternalFunctions("ThrowUninitializedPropertyAccessException").single() + ) + val stringBuilder = symbolTable.referenceClass( builtInsPackage("kotlin", "text").getContributedClassifier( Name.identifier("StringBuilder"), NoLookupLocation.FROM_BACKEND ) as ClassDescriptor ) + val defaultArgumentMarker = symbolTable.referenceClass( + builtIns.konanInternal.getContributedClassifier( + Name.identifier("DefaultArgumentMarker"), NoLookupLocation.FROM_BACKEND + ) as ClassDescriptor + ) + val any = symbolTable.referenceClass(builtIns.any) + val unit = symbolTable.referenceClass(builtIns.unit) + + val byte = symbolTable.referenceClass(builtIns.byte) + val short = symbolTable.referenceClass(builtIns.short) + val int = symbolTable.referenceClass(builtIns.int) + val long = symbolTable.referenceClass(builtIns.long) + + val integerClasses = listOf(byte, short, int, long) val arrayOf = symbolTable.referenceSimpleFunction( builtInsPackage("kotlin").getContributedFunctions( @@ -83,12 +107,86 @@ internal class Symbols(val context: Context, val symbolTable: SymbolTable) { val array = symbolTable.referenceClass(builtIns.array) + private fun primitiveArrayClass(type: PrimitiveType) = + symbolTable.referenceClass(builtIns.getPrimitiveArrayClassDescriptor(type)) + + val byteArray = primitiveArrayClass(PrimitiveType.BYTE) + val charArray = primitiveArrayClass(PrimitiveType.CHAR) + val shortArray = primitiveArrayClass(PrimitiveType.SHORT) + val intArray = primitiveArrayClass(PrimitiveType.INT) + val longArray = primitiveArrayClass(PrimitiveType.LONG) + val floatArray = primitiveArrayClass(PrimitiveType.FLOAT) + val doubleArray = primitiveArrayClass(PrimitiveType.DOUBLE) + val booleanArray = primitiveArrayClass(PrimitiveType.BOOLEAN) + + val arrays = PrimitiveType.values().map { primitiveArrayClass(it) } + array + + val copyRangeTo = arrays.map { symbol -> + val packageViewDescriptor = builtIns.builtInsModule.getPackage(KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME) + val functionDescriptor = packageViewDescriptor.memberScope + .getContributedFunctions(Name.identifier("copyRangeTo"), NoLookupLocation.FROM_BACKEND) + .first { + it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == symbol.descriptor + } + symbol.descriptor to symbolTable.referenceSimpleFunction(functionDescriptor) + }.toMap() + + val intAnd = symbolTable.referenceFunction( + builtIns.intType.memberScope + .getContributedFunctions(OperatorNameConventions.AND, NoLookupLocation.FROM_BACKEND) + .single() + ) + + val intPlusInt = symbolTable.referenceFunction( + builtIns.intType.memberScope + .getContributedFunctions(OperatorNameConventions.PLUS, NoLookupLocation.FROM_BACKEND) + .single { + it.valueParameters.single().type == builtIns.intType + } + ) + + val boxFunctions = ValueType.values().associate { + val boxFunctionName = "box${it.classFqName.shortName()}" + it to symbolTable.referenceSimpleFunction(context.builtIns.getKonanInternalFunctions(boxFunctionName).single()) + } + + val boxClasses = ValueType.values().associate { + it to symbolTable.referenceClass(context.builtIns.getKonanInternalClass("${it.classFqName.shortName()}Box")) + } + + val unboxFunctions = ValueType.values().mapNotNull { + val unboxFunctionName = "unbox${it.classFqName.shortName()}" + context.builtIns.getKonanInternalFunctions(unboxFunctionName).atMostOne()?.let { descriptor -> + it to symbolTable.referenceSimpleFunction(descriptor) + } + }.toMap() + + val interopNativePointedGetRawPointer = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.nativePointedGetRawPointer) + + val interopCPointerGetRawValue = symbolTable.referenceSimpleFunction(context.interopBuiltIns.cPointerGetRawValue) + + val getNativeNullPtr = symbolTable.referenceSimpleFunction(builtIns.getNativeNullPtr) + val valuesForEnum = symbolTable.referenceSimpleFunction( builtIns.getKonanInternalFunctions("valuesForEnum").single()) val valueOfForEnum = symbolTable.referenceSimpleFunction( builtIns.getKonanInternalFunctions("valueOfForEnum").single()) + val getContinuation = symbolTable.referenceSimpleFunction( + context.builtIns.getKonanInternalFunctions("getContinuation").single()) + + val coroutineImpl = symbolTable.referenceClass(context.builtIns.getKonanInternalClass("CoroutineImpl")) + + val coroutineSuspendedGetter = symbolTable.referenceSimpleFunction( + builtInsPackage("kotlin", "coroutines", "experimental", "intrinsics") + .getContributedVariables(Name.identifier("COROUTINE_SUSPENDED"), NoLookupLocation.FROM_BACKEND) + .single().getter!! + ) + + val kFunctionImpl = symbolTable.referenceClass(context.builtIns.getKonanInternalClass("KFunctionImpl")) + val kProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty0Impl) val kProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl) val kProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty2Impl) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt index c696eb2b427..6253a1f0b8a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt @@ -51,6 +51,12 @@ class IrReturnableBlockImpl(startOffset: Int, endOffset: Int, type: KotlinType, override val descriptor = symbol.descriptor + constructor(startOffset: Int, endOffset: Int, type: KotlinType, + symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin?, statements: List) : + this(startOffset, endOffset, type, symbol, origin) { + this.statements.addAll(statements) + } + constructor(startOffset: Int, endOffset: Int, type: KotlinType, descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null) : this(startOffset, endOffset, type, IrReturnableBlockSymbolImpl(descriptor), origin) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIrCopy.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIrCopy.kt new file mode 100644 index 00000000000..a7fb479b74b --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIrCopy.kt @@ -0,0 +1,62 @@ +/* + * 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.ir + +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.expressions.IrBlock +import org.jetbrains.kotlin.ir.expressions.IrReturn +import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl +import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols +import org.jetbrains.kotlin.ir.util.SymbolRemapper + +internal open class DeepCopyKonanIrTreeWithSymbols( + private val symbolRemapper: SymbolRemapper +) : DeepCopyIrTreeWithSymbols(symbolRemapper) { + + private inline fun T.transform() = + transform(this@DeepCopyKonanIrTreeWithSymbols, null) as T + + private val transformedReturnableBlocks = mutableMapOf() + + override fun visitBlock(expression: IrBlock): IrBlock = if (expression is IrReturnableBlock) { + IrReturnableBlockImpl( + expression.startOffset, expression.endOffset, + expression.type, + expression.descriptor, + expression.origin + ).also { + transformedReturnableBlocks.put(expression, it) + it.statements.addAll(expression.statements.map { it.transform() }) + } + } else { + super.visitBlock(expression) + } + + override fun visitReturn(expression: IrReturn): IrReturn { + val returnTargetSymbol = expression.returnTargetSymbol + return if (returnTargetSymbol is IrReturnableBlockSymbol) { + IrReturnImpl( + expression.startOffset, expression.endOffset, + expression.type, + transformedReturnableBlocks.getOrElse(returnTargetSymbol.owner) { returnTargetSymbol.owner }.symbol, + expression.value.transform() + ) + } else { + super.visitReturn(expression) + } + } +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt index f0551b06191..cc35c44e6a3 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt @@ -20,8 +20,8 @@ import org.jetbrains.kotlin.backend.common.AbstractValueUsageTransformer import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.descriptors.isSuspend import org.jetbrains.kotlin.backend.konan.* -import org.jetbrains.kotlin.backend.konan.descriptors.* -import org.jetbrains.kotlin.backend.konan.util.atMostOne +import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass +import org.jetbrains.kotlin.backend.konan.descriptors.target import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrFile @@ -29,7 +29,10 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl +import org.jetbrains.kotlin.ir.util.getPropertyGetter import org.jetbrains.kotlin.ir.util.isNullConst +import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.ir.util.type import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils @@ -50,6 +53,8 @@ internal class Autoboxing(val context: Context) : FileLoweringPass { private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTransformer(context.builtIns) { + val symbols = context.ir.symbols + // TODO: should we handle the cases when expression type // is not equal to e.g. called function return type? @@ -133,13 +138,13 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr override fun IrExpression.useAs(type: KotlinType): IrExpression { val interop = context.interopBuiltIns if (this.isNullConst() && interop.nullableInteropValueTypes.any { type.isRepresentedAs(it) }) { - return IrCallImpl(startOffset, endOffset, context.builtIns.getNativeNullPtr).uncheckedCast(type) + return IrCallImpl(startOffset, endOffset, symbols.getNativeNullPtr).uncheckedCast(type) } val actualType = when (this) { is IrCall -> { if (this.descriptor.isSuspend) context.builtIns.nullableAnyType - else this.descriptor.original.returnType ?: this.type + else this.callTarget.returnType ?: this.type } is IrGetField -> this.descriptor.original.type @@ -157,17 +162,32 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr return this.adaptIfNecessary(actualType, type) } - override fun IrExpression.useAsDispatchReceiver(function: CallableDescriptor): IrExpression { - return this.useAsArgument(function.original.dispatchReceiverParameter!!) + private val IrMemberAccessExpression.target: CallableDescriptor get() = when (this) { + is IrCall -> this.callTarget + is IrDelegatingConstructorCall -> this.descriptor.original + else -> TODO(this.render()) } - override fun IrExpression.useAsExtensionReceiver(function: CallableDescriptor): IrExpression { - return this.useAsArgument(function.original.extensionReceiverParameter!!) + private val IrCall.callTarget: FunctionDescriptor + get() = if (superQualifier == null && descriptor.isOverridable) { + // A virtual call. + descriptor.original + } else { + descriptor.target + } + + override fun IrExpression.useAsDispatchReceiver(expression: IrMemberAccessExpression): IrExpression { + return this.useAsArgument(expression.target.dispatchReceiverParameter!!) } - override fun IrExpression.useAsValueArgument(parameter: ValueParameterDescriptor): IrExpression { - val function = parameter.containingDeclaration - return this.useAsArgument(function.original.valueParameters[parameter.index]) + override fun IrExpression.useAsExtensionReceiver(expression: IrMemberAccessExpression): IrExpression { + return this.useAsArgument(expression.target.extensionReceiverParameter!!) + } + + override fun IrExpression.useAsValueArgument(expression: IrMemberAccessExpression, + parameter: ValueParameterDescriptor): IrExpression { + + return this.useAsArgument(expression.target.valueParameters[parameter.index]) } override fun IrExpression.useForField(field: PropertyDescriptor): IrExpression { @@ -211,9 +231,7 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr context.builtIns.getKonanInternalClass("${valueType.shortName}Box").defaultType private fun IrExpression.box(valueType: ValueType): IrExpression { - val boxFunctionName = "box${valueType.shortName}" - val boxFunction = context.builtIns.getKonanInternalFunctions(boxFunctionName).singleOrNull() ?: - TODO(valueType.toString()) + val boxFunction = symbols.boxFunctions[valueType]!! return IrCallImpl(startOffset, endOffset, boxFunction).apply { putValueArgument(0, this@box) @@ -221,22 +239,16 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr } private fun IrExpression.unbox(valueType: ValueType): IrExpression { - val unboxFunctionName = "unbox${valueType.shortName}" - - context.builtIns.getKonanInternalFunctions(unboxFunctionName).atMostOne()?.let { + symbols.unboxFunctions[valueType]?.let { return IrCallImpl(startOffset, endOffset, it).apply { - putValueArgument(0, this@unbox.uncheckedCast(it.valueParameters[0].type)) + putValueArgument(0, this@unbox.uncheckedCast(it.owner.valueParameters[0].type)) }.uncheckedCast(this.type) } - val boxGetter = getBoxType(valueType) - .memberScope.getContributedDescriptors() - .filterIsInstance() - .single { it.name.asString() == "value" } - .getter!! + val boxGetter = symbols.boxClasses[valueType]!!.getPropertyGetter("value")!! return IrCallImpl(startOffset, endOffset, boxGetter).apply { - dispatchReceiver = this@unbox.uncheckedCast(boxGetter.dispatchReceiverParameter!!.type) + dispatchReceiver = this@unbox.uncheckedCast(boxGetter.descriptor.dispatchReceiverParameter!!.type) }.uncheckedCast(this.type) // Try not to bring new type incompatibilities. } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt index c3d66cfe7e4..903c914d247 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt @@ -16,13 +16,11 @@ package org.jetbrains.kotlin.backend.konan.lower -import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.ValueType import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* @@ -36,6 +34,7 @@ import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.type import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -43,46 +42,6 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature import org.jetbrains.kotlin.types.KotlinType -internal class DirectBridgesCallsLowering(val context: Context) : BodyLoweringPass { - override fun lower(irBody: IrBody) { - irBody.transformChildrenVoid(object : IrElementTransformerVoid() { - override fun visitCall(expression: IrCall): IrExpression { - expression.transformChildrenVoid(this) - val descriptor = expression.descriptor as? FunctionDescriptor ?: return expression - if (descriptor.modality == Modality.ABSTRACT - || (expression.superQualifier == null && descriptor.isOverridable)) { - // A virtual call. boxing/unboxing will be in the corresponding bridge. - return expression - } - - val target = descriptor.target - if (!descriptor.original.needBridgeTo(target)) return expression - - return IrCallImpl(expression.startOffset, expression.endOffset, - target, remapTypeArguments(expression, target), expression.origin, - superQualifierDescriptor = target.containingDeclaration as ClassDescriptor /* Call non-virtually */ - ).apply { - dispatchReceiver = expression.dispatchReceiver - extensionReceiver = expression.extensionReceiver - mapValueParameters { expression.getValueArgument(it)!! } - } - } - - private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: CallableDescriptor) - : Map? { - val oldCallee = oldExpression.descriptor - - return if (oldCallee.typeParameters.isEmpty()) - null - else oldCallee.typeParameters.associateBy( - { newCallee.typeParameters[it.index] }, - { oldExpression.getTypeArgument(it)!! } - ) - } - }) - } -} - internal class BridgesBuilding(val context: Context) : ClassLoweringPass { private fun IrBuilderWithScope.returnIfBadType(value: IrExpression, @@ -162,30 +121,31 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass { private object DECLARATION_ORIGIN_BRIDGE_METHOD : IrDeclarationOriginImpl("BRIDGE_METHOD") - private val ValueType.shortName - get() = this.classFqName.shortName() - - private fun getBoxType(valueType: ValueType) = - context.builtIns.getKonanInternalClass("${valueType.shortName}Box").defaultType - private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) { val bridgeDescriptor = context.specialDeclarationsFactory.getBridgeDescriptor(descriptor) - val target = descriptor.descriptor.target + val bridge = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, DECLARATION_ORIGIN_BRIDGE_METHOD, + bridgeDescriptor).apply { createParameterDeclarations() } + + val target = descriptor.descriptor + + assert(target.containingDeclaration == irClass.descriptor) + val superQualifierSymbol = irClass.symbol + val targetSymbol = irClass.findMember(target) // TODO: optimize val statements = mutableListOf() - val irBuilder = context.createIrBuilder(bridgeDescriptor, irClass.startOffset, irClass.endOffset) + val irBuilder = context.createIrBuilder(bridge.symbol, irClass.startOffset, irClass.endOffset) irBuilder.run { val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor) if (typeSafeBarrierDescription != null) { - val valueParameters = bridgeDescriptor.valueParameters + val valueParameters = bridge.valueParameters for (i in valueParameters.indices) { if (!typeSafeBarrierDescription.checkParameter(i)) continue val type = target.valueParameters[i].type if (type != context.builtIns.nullableAnyType) { - statements += returnIfBadType(irGet(valueParameters[i]), type, + statements += returnIfBadType(irGet(valueParameters[i].symbol), type, if (typeSafeBarrierDescription == BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT) - irGet(valueParameters[2]) + irGet(valueParameters[2].symbol) else irConst(typeSafeBarrierDescription.defaultValue) ) } @@ -193,22 +153,22 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass { } } - val delegatingCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, target, - superQualifierDescriptor = target.containingDeclaration as ClassDescriptor /* Call non-virtually */ + val delegatingCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetSymbol, target, + superQualifierSymbol = superQualifierSymbol /* Call non-virtually */ ).apply { - val dispatchReceiverParameter = bridgeDescriptor.dispatchReceiverParameter + val dispatchReceiverParameter = bridge.dispatchReceiverParameter if (dispatchReceiverParameter != null) - dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchReceiverParameter) - val extensionReceiverParameter = bridgeDescriptor.extensionReceiverParameter + dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchReceiverParameter.symbol) + val extensionReceiverParameter = bridge.extensionReceiverParameter if (extensionReceiverParameter != null) - extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionReceiverParameter) - bridgeDescriptor.valueParameters.forEach { - this.putValueArgument(it.index, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it)) + extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionReceiverParameter.symbol) + bridge.valueParameters.forEachIndexed { index, parameter -> + this.putValueArgument(index, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter.symbol)) } } val bridgeBody = if (bridgeDescriptor.returnType.let { it != null && !KotlinBuiltIns.isUnitOrNullableUnit(it) }) - IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, bridgeDescriptor, delegatingCall) + IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, bridge.symbol, delegatingCall) else delegatingCall statements += bridgeBody @@ -219,3 +179,12 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass { ) } } + +private fun IrClass.findMember(descriptor: FunctionDescriptor): IrFunctionSymbol { + val functions = this.declarations.filterIsInstance().map { it.symbol } + val propertyAccessors = this.declarations + .filterIsInstance() + .flatMap { listOfNotNull(it.getter?.symbol, it.setter?.symbol) } + + return (functions + propertyAccessors).single { it.descriptor == descriptor } +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt index 6bb15b922fb..0773798bb1a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt @@ -20,8 +20,6 @@ import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass -import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionOrKFunctionType import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.ir.createFakeOverrideDescriptor @@ -45,8 +43,6 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl -import org.jetbrains.kotlin.ir.util.createParameterDeclarations -import org.jetbrains.kotlin.ir.util.getArguments import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -54,9 +50,9 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl -import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.backend.common.descriptors.* +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.types.* internal class CallableReferenceLowering(val context: Context): DeclarationContainerLoweringPass { @@ -122,7 +118,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta private val continuationClassDescriptor = coroutinesScope .getContributedClassifier(Name.identifier("Continuation"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor - private val getContinuationDescriptor = context.builtIns.getKonanInternalFunctions("getContinuation").single() + private val getContinuationSymbol = context.ir.symbols.getContinuation private inner class FunctionReferenceBuilder(val containingDeclaration: DeclarationDescriptor, val functionReference: IrFunctionReference) { @@ -137,7 +133,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta private lateinit var functionReferenceThis: IrValueParameterSymbol private lateinit var argumentToPropertiesMap: Map - private val kFunctionImplClassDescriptor = context.builtIns.getKonanInternalClass("KFunctionImpl") + private val kFunctionImplSymbol = context.ir.symbols.kFunctionImpl fun build(): BuiltFunctionReference { val startOffset = functionReference.startOffset @@ -145,7 +141,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta val returnType = functionDescriptor.returnType!! val superTypes = mutableListOf( - kFunctionImplClassDescriptor.defaultType.replace(listOf(returnType)) + kFunctionImplSymbol.owner.defaultType.replace(listOf(returnType)) ) val numberOfParameters = unboundFunctionParameters.size @@ -196,7 +192,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionDescriptor) } - val inheritedKFunctionImpl = kFunctionImplClassDescriptor.unsubstitutedMemberScope + val inheritedKFunctionImpl = kFunctionImplSymbol.descriptor.unsubstitutedMemberScope .getContributedDescriptors() .map { it.createFakeOverrideDescriptor(functionReferenceClassDescriptor) } .filterNotNull() @@ -206,6 +202,8 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta functionReferenceClassDescriptor.initialize( SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.symbol.descriptor), null) + functionReferenceClass.addFakeOverrides() + constructorBuilder.initialize() functionReferenceClass.declarations.add(constructorBuilder.ir) @@ -223,7 +221,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta private fun createConstructorBuilder() = object : SymbolWithIrBuilder() { - private val kFunctionImplConstructorDescriptor = kFunctionImplClassDescriptor.constructors.single() + private val kFunctionImplConstructorSymbol = kFunctionImplSymbol.constructors.single() override fun buildSymbol() = IrConstructorSymbolImpl( ClassConstructorDescriptorImpl.create( @@ -261,7 +259,8 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta createParameterDeclarations() body = irBuilder.irBlockBody { - +IrDelegatingConstructorCallImpl(startOffset, endOffset, kFunctionImplConstructorDescriptor).apply { + +IrDelegatingConstructorCallImpl(startOffset, endOffset, + kFunctionImplConstructorSymbol, kFunctionImplConstructorSymbol.descriptor).apply { val name = IrConstImpl(startOffset, endOffset, context.builtIns.stringType, IrConstKind.String, functionDescriptor.name.asString()) putValueArgument(0, name) @@ -356,7 +355,8 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta else { if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size) // For suspend functions the last argument is continuation and it is implicit. - irCall(getContinuationDescriptor.substitute(ourSymbol.descriptor.returnType!!)) + irCall(getContinuationSymbol, + listOf(ourSymbol.descriptor.returnType!!)) else irGet(valueParameters[unboundIndex++].symbol) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentStubGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentStubGenerator.kt index 48f618b1734..b302133644b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentStubGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DefaultArgumentStubGenerator.kt @@ -21,8 +21,6 @@ import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.KonanBuiltIns -import org.jetbrains.kotlin.backend.konan.descriptors.konanInternal import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.ir.ir2string import org.jetbrains.kotlin.builtins.KotlinBuiltIns @@ -32,7 +30,6 @@ 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.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* @@ -42,8 +39,9 @@ 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.util.createParameterDeclarations -import org.jetbrains.kotlin.ir.util.transformFlat +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 @@ -52,7 +50,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.builtIns -import org.jetbrains.kotlin.util.OperatorNameConventions class DefaultArgumentStubGenerator internal constructor(val context: Context): DeclarationContainerLoweringPass { override fun lower(irDeclarationContainer: IrDeclarationContainer) { @@ -65,8 +62,7 @@ class DefaultArgumentStubGenerator internal constructor(val context: Context): D } - object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER : - IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT") + private val symbols = context.ir.symbols private fun lower(irFunction: IrFunction): List { val functionDescriptor = irFunction.descriptor @@ -81,27 +77,28 @@ class DefaultArgumentStubGenerator internal constructor(val context: Context): D log("detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions") functionDescriptor.overriddenDescriptors.forEach { context.log{"DEFAULT-REPLACER: $it"} } if (bodies.isNotEmpty()) { - val descriptor = functionDescriptor.generateDefaultsDescription(context) + val newIrFunction = functionDescriptor.generateDefaultsFunction(context) + val descriptor = newIrFunction.descriptor log("$functionDescriptor -> $descriptor") - val builder = context.createIrBuilder(descriptor) + val builder = context.createIrBuilder(newIrFunction.symbol) val body = builder.irBlockBody(irFunction) { - val params = mutableListOf() - val variables = mutableMapOf() + val params = mutableListOf() + val variables = mutableMapOf() if (descriptor.extensionReceiverParameter != null) { - variables[functionDescriptor.extensionReceiverParameter!!] = descriptor.extensionReceiverParameter!! + variables[functionDescriptor.extensionReceiverParameter!!] = + newIrFunction.extensionReceiverParameter!!.symbol } for (valueParameter in functionDescriptor.valueParameters) { - val parameterDescriptor = descriptor.valueParameters[valueParameter.index] - val temporaryVariableDescriptor = scope.createTemporaryVariableDescriptor(parameterDescriptor) - params.add(temporaryVariableDescriptor) - variables.put(valueParameter, temporaryVariableDescriptor) + 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 = valueParameter.builtIns.intType.memberScope - .getContributedFunctions(OperatorNameConventions.AND, NoLookupLocation.FROM_BACKEND) - .single() + val kIntAnd = symbols.intAnd val condition = irNotEquals(irCall(kIntAnd).apply { - dispatchReceiver = irGet(maskParameterDescriptor(descriptor, valueParameter.index / 32)) + dispatchReceiver = irGet(maskParameterSymbol(newIrFunction, valueParameter.index / 32)) putValueArgument(0, irInt(1 shl (valueParameter.index % 32))) }, irInt(0)) val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter) @@ -110,51 +107,45 @@ class DefaultArgumentStubGenerator internal constructor(val context: Context): D expressionBody.transformChildrenVoid(object:IrElementTransformerVoid() { override fun visitGetValue(expression: IrGetValue): IrExpression { log("GetValue: ${expression.descriptor}") - val valueDescriptor = variables[expression.descriptor] - return when (valueDescriptor) { - is VariableDescriptor -> irGet(valueDescriptor) - is ReceiverParameterDescriptor -> irGet(valueDescriptor) - null -> expression - else -> TODO("$valueDescriptor") - } - + val valueSymbol = variables[expression.descriptor] ?: return expression + return irGet(valueSymbol) } }) val variableInitialization = irIfThenElse( - type = temporaryVariableDescriptor.type, + type = temporaryVariableSymbol.descriptor.type, condition = condition, thenPart = expressionBody.expression, - elsePart = irGet(parameterDescriptor)) + elsePart = irGet(parameterSymbol)) + scope.createTemporaryVariable( - descriptor = temporaryVariableDescriptor, + symbol = temporaryVariableSymbol, initializer = variableInitialization) /* Mapping calculated values with its origin variables. */ } else { + scope.createTemporaryVariable( - descriptor = temporaryVariableDescriptor, - initializer = irGet(parameterDescriptor)) + symbol = temporaryVariableSymbol, + initializer = irGet(parameterSymbol)) } } - if (functionDescriptor is ClassConstructorDescriptor) { + if (irFunction is IrConstructor) { + IrDelegatingConstructorCallImpl( startOffset = irFunction.startOffset, endOffset = irFunction.endOffset, - constructorDescriptor = functionDescriptor + symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor ).apply { params.forEachIndexed { i, variable -> putValueArgument(i, irGet(variable)) } if (functionDescriptor.dispatchReceiverParameter != null) { - dispatchReceiver = irThis() + dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol) } } } else { - +irReturn(irCall(functionDescriptor).apply { + +irReturn(irCall(irFunction.symbol).apply { if (functionDescriptor.dispatchReceiverParameter != null) { - dispatchReceiver = irThis() + dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol) } if (functionDescriptor.extensionReceiverParameter != null) { - extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!] as ReceiverParameterDescriptor) + extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!]!!) } params.forEachIndexed { i, variable -> putValueArgument(i, irGet(variable)) @@ -188,26 +179,31 @@ class DefaultArgumentStubGenerator internal constructor(val context: Context): D private fun log(msg:String) = context.log{"DEFAULT-REPLACER: $msg"} } -private fun Scope.createTemporaryVariableDescriptor(parameterDescriptor: ValueParameterDescriptor?): VariableDescriptor = +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(descriptor: VariableDescriptor, initializer: IrExpression) = +private fun Scope.createTemporaryVariable(symbol: IrVariableSymbol, initializer: IrExpression) = IrVariableImpl( startOffset = initializer.startOffset, endOffset = initializer.endOffset, origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, - descriptor = descriptor, - initializer = initializer) + symbol = symbol).apply { + + this.initializer = initializer + } private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor):IrExpressionBody { return irFunction.getDefault(valueParameter) as? IrExpressionBody ?: TODO("FIXME!!!") } -private fun maskParameterDescriptor(descriptor: FunctionDescriptor, number:Int)= descriptor.valueParameters.single { it.name == parameterMaskName(number) } +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 } @@ -237,11 +233,12 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL val argumentsCount = argumentCount(expression) if (argumentsCount == descriptor.valueParameters.size) return expression - val (descriptorForCall, params) = parametersForCall(expression) + val (symbolForCall, params) = parametersForCall(expression) return IrDelegatingConstructorCallImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, - constructorDescriptor = descriptorForCall as ClassConstructorDescriptor) + symbol = symbolForCall as IrConstructorSymbol, + descriptor = symbolForCall.descriptor) .apply { params.forEach { log("call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}") @@ -254,7 +251,7 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL override fun visitCall(expression: IrCall): IrExpression { super.visitCall(expression) - val functionDescriptor = expression.descriptor as FunctionDescriptor + val functionDescriptor = expression.descriptor if (!functionDescriptor.needsDefaultArgumentsLowering) return expression @@ -262,13 +259,15 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL val argumentsCount = argumentCount(expression) if (argumentsCount == functionDescriptor.valueParameters.size) return expression - val (descriptor, params) = parametersForCall(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, - calleeDescriptor = descriptor, + symbol = symbol, + descriptor = descriptor, typeArguments = expression.descriptor.typeParameters.map{it to (expression.getTypeArgument(it) ?: it.defaultType) }.toMap()) .apply { params.forEach { @@ -286,13 +285,14 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL } } - private fun parametersForCall(expression: IrMemberAccessExpression): Pair>> { + private fun parametersForCall(expression: IrMemberAccessExpression): Pair>> { val descriptor = expression.descriptor as FunctionDescriptor val keyDescriptor = if (DescriptorUtils.isOverride(descriptor)) DescriptorUtils.getAllOverriddenDescriptors(descriptor).first() else descriptor.original - val realDescriptor = keyDescriptor.generateDefaultsDescription(context) + val realFunction = keyDescriptor.generateDefaultsFunction(context) + val realDescriptor = realFunction.descriptor log("$descriptor -> $realDescriptor") val maskValues = Array(descriptor.valueParameters.size / 32 + 1, {0}) @@ -308,24 +308,24 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL return@mapIndexed pair }) maskValues.forEachIndexed { i, maskValue -> - params += maskParameterDescriptor(realDescriptor, i) to IrConstImpl.int( + 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 = getDefaultArgumentMarkerClassDescriptor(context.builtIns) + val defaultArgumentMarker = context.ir.symbols.defaultArgumentMarker params += markerParameterDescriptor(realDescriptor) to IrGetObjectValueImpl( startOffset = irBody.startOffset, endOffset = irBody.endOffset, - type = defaultArgumentMarker.defaultType, - descriptor = defaultArgumentMarker) + type = defaultArgumentMarker.owner.defaultType, + symbol = defaultArgumentMarker) } params.forEach { log("descriptor::${realDescriptor.name.asString()}#${it.first.index}: ${it.first.name.asString()}") } - return Pair(realDescriptor, params) + return Pair(realFunction.symbol, params) } private fun argumentCount(expression: IrMemberAccessExpression) = @@ -339,8 +339,8 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL private val CallableMemberDescriptor.needsDefaultArgumentsLowering get() = valueParameters.any { it.hasDefaultValue() } && !(this is FunctionDescriptor && isInline) -private fun FunctionDescriptor.generateDefaultsDescription(context: Context): FunctionDescriptor { - return context.ir.defaultParameterDescriptorsCache.getOrPut(this) { +private fun FunctionDescriptor.generateDefaultsFunction(context: Context): IrFunction { + return context.ir.defaultParameterDeclarationsCache.getOrPut(this) { val descriptor = when (this) { is ClassConstructorDescriptor -> ClassConstructorDescriptorImpl.create( @@ -367,7 +367,7 @@ private fun FunctionDescriptor.generateDefaultsDescription(context: Context): Fu if (this is ClassConstructorDescriptor) { syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1, kConstructorMarkerName, - getDefaultArgumentMarkerClassDescriptor(context.builtIns).defaultType) + context.ir.symbols.defaultArgumentMarker.owner.defaultType) } descriptor.initialize( /* receiverParameterType = */ extensionReceiverParameter?.type, @@ -407,10 +407,33 @@ private fun FunctionDescriptor.generateDefaultsDescription(context: Context): Fu /* visibility = */ this.visibility) descriptor.isSuspend = this.isSuspend context.log{"adds to cache[$this] = $descriptor"} - 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, @@ -429,9 +452,4 @@ private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Nam internal val kConstructorMarkerName = "marker".synthesizedName -private fun getDefaultArgumentMarkerClassDescriptor(builtIns: KonanBuiltIns): ClassDescriptor = - builtIns.konanInternal.getContributedClassifier( - Name.identifier("DefaultArgumentMarker"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor - -internal fun IrBuilderWithScope.irGet(descriptor: ReceiverParameterDescriptor):IrGetValue = IrGetValueImpl(startOffset, endOffset, descriptor) private fun parameterMaskName(number: Int) = "mask$number".synthesizedName diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt index afb0cb0c303..c3fbd3f6131 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt @@ -282,6 +282,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { .toList() defaultClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null) + defaultClass.addFakeOverrides() + return defaultClass } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt index d1ebf7288b2..a9d618af710 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt @@ -1,24 +1,25 @@ package org.jetbrains.kotlin.backend.konan.lower -import org.jetbrains.kotlin.backend.common.DeepCopyIrTreeWithDeclarations import org.jetbrains.kotlin.backend.common.FunctionLoweringPass import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl +import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockSymbol +import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockSymbolImpl import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl import org.jetbrains.kotlin.ir.declarations.IrFunction 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.IrFunctionSymbol import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name @@ -32,9 +33,9 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression): IrExpression } - private data class Return(val functionDescriptor: FunctionDescriptor): HighLevelJump { + private data class Return(val target: IrFunctionSymbol): HighLevelJump { override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression) - = IrReturnImpl(startOffset, endOffset, functionDescriptor, value) + = IrReturnImpl(startOffset, endOffset, target, value) } private data class Break(val loop: IrLoop): HighLevelJump { @@ -64,7 +65,7 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass private class TryScope(var expression: IrExpression, val finallyExpression: IrExpression, val irBuilder: IrBuilderWithScope): Scope() { - val jumps = mutableMapOf() + val jumps = mutableMapOf() } private val scopeStack = mutableListOf() @@ -101,26 +102,26 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass override fun visitBreak(jump: IrBreak): IrExpression { val startOffset = jump.startOffset val endOffset = jump.endOffset - val irBuilder = context.createIrBuilder(functionDescriptor, startOffset, endOffset) + val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset) return performHighLevelJump( targetScopePredicate = { it is LoopScope && it.loop == jump.loop }, jump = Break(jump.loop), startOffset = startOffset, endOffset = endOffset, - value = irBuilder.irUnit() + value = irBuilder.irGetObject(context.ir.symbols.unit) ) ?: jump } override fun visitContinue(jump: IrContinue): IrExpression { val startOffset = jump.startOffset val endOffset = jump.endOffset - val irBuilder = context.createIrBuilder(functionDescriptor, startOffset, endOffset) + val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset) return performHighLevelJump( targetScopePredicate = { it is LoopScope && it.loop == jump.loop }, jump = Continue(jump.loop), startOffset = startOffset, endOffset = endOffset, - value = irBuilder.irUnit() + value = irBuilder.irGetObject(context.ir.symbols.unit) ) ?: jump } @@ -129,7 +130,7 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass return performHighLevelJump( targetScopePredicate = { it is ReturnableScope && it.descriptor == expression.returnTarget }, - jump = Return(expression.returnTarget), + jump = Return(expression.returnTargetSymbol), startOffset = expression.startOffset, endOffset = expression.endOffset, value = expression.value @@ -161,10 +162,10 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass val currentTryScope = tryScopes[index] currentTryScope.jumps.getOrPut(jump) { - val descriptor = getFakeFunctionDescriptor(jump.toString(), value.type) + val symbol = getIrReturnableBlockSymbol(jump.toString(), value.type) with(currentTryScope) { irBuilder.run { - val inlinedFinally = irInlineFinally(descriptor, expression, finallyExpression) + val inlinedFinally = irInlineFinally(symbol, expression, finallyExpression) expression = performHighLevelJump( tryScopes = tryScopes, index = index + 1, @@ -174,12 +175,12 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass value = inlinedFinally) } } - descriptor + symbol }.let { return IrReturnImpl( startOffset = startOffset, endOffset = endOffset, - returnTargetDescriptor = it, + returnTargetSymbol = it, value = value) } } @@ -191,7 +192,7 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass val startOffset = aTry.startOffset val endOffset = aTry.endOffset - val irBuilder = context.createIrBuilder(functionDescriptor, startOffset, endOffset) + val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset) val transformer = this irBuilder.run { val transformedTry = IrTryImpl( @@ -223,33 +224,33 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass finallyExpression = null ) using(TryScope(syntheticTry, transformedFinallyExpression, this)) { - val fallThroughDescriptor = getFakeFunctionDescriptor("fallThrough", aTry.type) + val fallThroughSymbol = getIrReturnableBlockSymbol("fallThrough", aTry.type) val transformedResult = aTry.tryResult.transform(transformer, null) - transformedTry.tryResult = irReturn(fallThroughDescriptor, transformedResult) + transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult) for (aCatch in aTry.catches) { val transformedCatch = aCatch.transform(transformer, null) - transformedCatch.result = irReturn(fallThroughDescriptor, transformedCatch.result) + transformedCatch.result = irReturn(fallThroughSymbol, transformedCatch.result) transformedTry.catches.add(transformedCatch) } - return irInlineFinally(fallThroughDescriptor, it.expression, it.finallyExpression) + return irInlineFinally(fallThroughSymbol, it.expression, it.finallyExpression) } } } - private fun IrBuilderWithScope.irInlineFinally(descriptor: FunctionDescriptor, + private fun IrBuilderWithScope.irInlineFinally(symbol: IrReturnableBlockSymbol, value: IrExpression, finallyExpression: IrExpression): IrExpression { - val returnType = descriptor.returnType!! + val returnType = symbol.descriptor.returnType!! return when { returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, returnType) { - +irReturnableBlock(descriptor) { + +irReturnableBlock(symbol) { +value } +finallyExpression.copy() } else -> irBlock(value, null, returnType) { - val tmp = irTemporary(irReturnableBlock(descriptor) { - +irReturn(descriptor, value) + val tmp = irTemporary(irReturnableBlock(symbol) { + +irReturn(symbol, value) }) +finallyExpression.copy() +irGet(tmp.symbol) @@ -268,23 +269,19 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass } } - @Suppress("UNCHECKED_CAST") - private fun T.copy() = this.transform(DeepCopyIrTreeWithDeclarations(), data = null) as T + private fun getIrReturnableBlockSymbol(name: String, returnType: KotlinType): IrReturnableBlockSymbol = + IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType)) + + private inline fun T.copy() = this.deepCopyWithVariables() }) } } - private object DECLARATION_ORIGIN_FINALLY_BLOCK : - IrDeclarationOriginImpl("FINALLY_BLOCK") - - private fun IrBuilderWithScope.irVar(descriptor: VariableDescriptor, initializer: IrExpression?) = - IrVariableImpl(startOffset, endOffset, DECLARATION_ORIGIN_FINALLY_BLOCK, descriptor, initializer) - - fun IrBuilderWithScope.irReturn(target: FunctionDescriptor, value: IrExpression) = + fun IrBuilderWithScope.irReturn(target: IrFunctionSymbol, value: IrExpression) = IrReturnImpl(startOffset, endOffset, target, value) - inline fun IrBuilderWithScope.irReturnableBlock(descriptor: FunctionDescriptor, body: IrBlockBuilder.() -> Unit) = - IrReturnableBlockImpl(startOffset, endOffset, descriptor.returnType!!, descriptor, null, - IrBlockBuilder(context, scope, startOffset, endOffset, null, descriptor.returnType!!) + inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, body: IrBlockBuilder.() -> Unit) = + IrReturnableBlockImpl(startOffset, endOffset, symbol.descriptor.returnType!!, symbol, null, + IrBlockBuilder(context, scope, startOffset, endOffset, null, symbol.descriptor.returnType!!) .block(body).statements) } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt index ae5e4881272..bc6a4040b5f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt @@ -25,32 +25,60 @@ import org.jetbrains.kotlin.backend.konan.ValueType import org.jetbrains.kotlin.backend.konan.isRepresentedAs import org.jetbrains.kotlin.backend.konan.reportCompilationError import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.ir.builders.IrBuilder -import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope import org.jetbrains.kotlin.ir.builders.irCall -import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.getArguments +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.OverridingUtil import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf +internal class InteropLoweringPart1(val context: Context) : IrElementTransformerVoid(), FileLoweringPass { + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(this) + } + + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid() + + return when (expression.descriptor.original) { + context.interopBuiltIns.typeOf -> { + val typeArgument = expression.getSingleTypeArgument() + val classDescriptor = TypeUtils.getClassDescriptor(typeArgument) + + if (classDescriptor == null) { + expression + } else { + val companionObjectDescriptor = classDescriptor.companionObjectDescriptor ?: + error("native variable class $classDescriptor must have the companion object") + + IrGetObjectValueImpl( + expression.startOffset, expression.endOffset, + companionObjectDescriptor.defaultType, companionObjectDescriptor + ) + } + } + else -> expression + } + } +} + /** * Lowers some interop intrinsic calls. */ -internal class InteropLowering(val context: Context) : FileLoweringPass { +internal class InteropLoweringPart2(val context: Context) : FileLoweringPass { override fun lower(irFile: IrFile) { val transformer = InteropTransformer(context, irFile) irFile.transformChildrenVoid(transformer) @@ -60,142 +88,7 @@ internal class InteropLowering(val context: Context) : FileLoweringPass { private class InteropTransformer(val context: Context, val irFile: IrFile) : IrBuildingTransformer(context) { val interop = context.interopBuiltIns - val konanBuiltins = context.builtIns - - private fun MemberScope.getSingleContributedFunction(name: String, - predicate: (SimpleFunctionDescriptor) -> Boolean) = - this.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).single(predicate) - - private fun IrBuilder.irGetObject(descriptor: ClassDescriptor): IrExpression { - return IrGetObjectValueImpl(startOffset, endOffset, descriptor.defaultType, descriptor) - } - - private fun IrBuilder.typeOf(descriptor: ClassDescriptor): IrExpression { - val companionObject = descriptor.companionObjectDescriptor ?: - error("native variable class $descriptor must have the companion object") - // TODO: add more checks and produce the compile error instead of exception. - - return irGetObject(companionObject) - } - - private fun IrBuilder.typeOf(type: KotlinType): IrExpression? { - val descriptor = TypeUtils.getClassDescriptor(type) ?: return null - return typeOf(descriptor) - } - - private fun KotlinType.findOverride(property: PropertyDescriptor): PropertyDescriptor { - val result = this.memberScope.getContributedVariables(property.name, NoLookupLocation.FROM_BACKEND).single() - assert (OverridingUtil.overrides(result, property)) - return result - } - - private fun IrBuilderWithScope.sizeOf(typeObject: IrExpression): IrExpression { - val sizeProperty = typeObject.type.findOverride(interop.variableTypeSize) - return irGet(typeObject, sizeProperty) - } - - private fun IrBuilderWithScope.sizeOf(type: KotlinType): IrExpression? { - val typeObject = typeOf(type) ?: return null - return sizeOf(typeObject) - } - - private fun IrBuilderWithScope.alignOf(typeObject: IrExpression): IrExpression { - val alignProperty = typeObject.type.findOverride(interop.variableTypeAlign) - return irGet(typeObject, alignProperty) - } - - private fun IrBuilderWithScope.alignOf(type: KotlinType): IrExpression? { - val typeObject = typeOf(type) ?: return null - return alignOf(typeObject) - } - - @Suppress("UNUSED_PARAMETER") - private fun IrBuilderWithScope.interpretPointed(expression: IrCall, type: KotlinType): IrExpression = - irCall(interop.interpretNullablePointed).apply { - putValueArgument(0, expression) - } - // TODO: make the result type more correct. - - private fun IrBuilderWithScope.arrayGet(array: IrExpression, index: IrExpression): IrExpression? { - val elementType = array.type.arguments.single().type - val elementSize = sizeOf(elementType) ?: return null - - val resultRawPtr = irCall(konanBuiltins.nativePtrPlusLong).apply { - dispatchReceiver = irCall(interop.cPointerGetRawValue).apply { - extensionReceiver = array - } - putValueArgument(0, times(elementSize, index)) - } - return interpretPointed(resultRawPtr, elementType) - } - - private fun IrBuilderWithScope.times(left: IrExpression, right: IrExpression): IrCall { - val times = left.type.memberScope.getSingleContributedFunction("times") { - right.type.isSubtypeOf(it.valueParameters.single().type) - } - - return irCall(times).apply { - dispatchReceiver = left - putValueArgument(0, right) - } - } - - private fun IrBuilderWithScope.alloc(placement: IrExpression, size: IrExpression, align: IrExpression): IrExpression { - val alloc = placement.type.memberScope.getSingleContributedFunction("alloc") { - size.type.isSubtypeOf(it.valueParameters[0]!!.type) && - align.type.isSubtypeOf(it.valueParameters[1]!!.type) - } - - return irCall(alloc).apply { - dispatchReceiver = placement - putValueArgument(0, size) - putValueArgument(1, align) - } - } - - @Suppress("UNUSED_PARAMETER") - private fun IrBuilderWithScope.nativePointedToCPointer( - expression: IrExpression, pointeeType: KotlinType - ): IrExpression = irCall(interop.interpretCPointer).apply { - putValueArgument(0, irCall(interop.nativePointedGetRawPointer).apply { - extensionReceiver = expression - }) - } - // TODO: make the result type more correct. - - private fun IrBuilderWithScope.allocArray(placement: IrExpression, - elementType: KotlinType, - length: IrExpression - ): IrExpression? { - - val elementSize = sizeOf(elementType) ?: return null - val size = times(elementSize, length) - val align = alignOf(elementType) ?: return null - - return nativePointedToCPointer(alloc(placement, size, align), elementType) - } - - private fun IrBuilderWithScope.alloc(placement: IrExpression, type: KotlinType): IrExpression? { - val size = sizeOf(type) ?: return null - val align = alignOf(type) ?: return null - - return alloc(placement, size, align) - } - - private fun IrBuilderWithScope.readValue(receiver: IrExpression, typeArgument: KotlinType): IrCallImpl? { - val size = sizeOf(typeArgument) ?: return null - val align = alignOf(typeArgument) ?: return null - - val callee = interop.readValueBySizeAndAlign - val typeParameter = callee.typeParameters.single() - val typeArguments = mapOf(typeParameter to typeArgument) - - return irCall(callee, typeArguments).apply { - extensionReceiver = receiver - putValueArgument(0, size) - putValueArgument(1, align) - } - } + val symbols = context.ir.symbols override fun visitCall(expression: IrCall): IrExpression { @@ -214,7 +107,7 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB OverridingUtil.overrides(descriptor, interop.nativePointedRawPtrGetter)) { // Replace by the intrinsic call to be handled by code generator: - return builder.irCall(interop.nativePointedGetRawPointer).apply { + return builder.irCall(symbols.interopNativePointedGetRawPointer).apply { extensionReceiver = expression.dispatchReceiver } } @@ -222,34 +115,10 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB return when (descriptor) { interop.cPointerRawValue.getter -> // Replace by the intrinsic call to be handled by code generator: - builder.irCall(interop.cPointerGetRawValue).apply { + builder.irCall(symbols.interopCPointerGetRawValue).apply { extensionReceiver = expression.dispatchReceiver } - interop.arrayGetByIntIndex, interop.arrayGetByLongIndex -> { - val array = expression.extensionReceiver!! - val index = expression.getValueArgument(0)!! - builder.arrayGet(array, index) ?: expression - } - - interop.allocUninitializedArrayWithIntLength, interop.allocUninitializedArrayWithLongLength -> { - val placement = expression.extensionReceiver!! - val elementType = expression.type.arguments.single().type - val length = expression.getValueArgument(0)!! - builder.allocArray(placement, elementType, length) ?: expression - } - - interop.allocVariable -> { - val placement = expression.extensionReceiver!! - val type = expression.getSingleTypeArgument() - builder.alloc(placement, type) ?: expression - } - - interop.typeOf -> { - val type = expression.getSingleTypeArgument() - builder.typeOf(type) ?: expression - } - interop.bitsToFloat -> { val argument = expression.getValueArgument(0) if (argument is IrConst<*> && argument.kind == IrConstKind.Int) { @@ -270,13 +139,6 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB } } - interop.readValue -> { - val typeArgument = expression.getSingleTypeArgument() - val receiver = expression.extensionReceiver!! - - builder.readValue(receiver, typeArgument) ?: expression - } - in interop.staticCFunction -> { val irCallableReference = unwrapStaticFunctionArgument(expression.getValueArgument(0)!!) @@ -288,7 +150,8 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB // TODO: should probably be reported during analysis. } - val target = irCallableReference.descriptor.original + val targetSymbol = irCallableReference.symbol + val target = targetSymbol.descriptor val signatureTypes = target.allParameters.map { it.type } + target.returnType!! signatureTypes.forEachIndexed { index, type -> @@ -312,7 +175,7 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB IrFunctionReferenceImpl( builder.startOffset, builder.endOffset, expression.type, - target, + targetSymbol, target, typeArguments = null) } @@ -352,10 +215,14 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB else -> throw Error() } - val conversionDescriptor = receiver.type.memberScope.getContributedFunctions( - Name.identifier("to$typeOperand"), NoLookupLocation.FROM_BACKEND).single() + val receiverClass = symbols.integerClasses.single { + receiver.type.isSubtypeOf(it.owner.defaultType) + } + val conversionSymbol = receiverClass.functions.single { + it.descriptor.name == Name.identifier("to$typeOperand") + } - builder.irCall(conversionDescriptor).apply { + builder.irCall(conversionSymbol).apply { dispatchReceiver = receiver } } @@ -415,11 +282,11 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB return argument.statements.last() as? IrFunctionReference } +} - private fun IrCall.getSingleTypeArgument(): KotlinType { - val typeParameter = descriptor.original.typeParameters.single() - return getTypeArgument(typeParameter)!! - } +private fun IrCall.getSingleTypeArgument(): KotlinType { + val typeParameter = descriptor.original.typeParameters.single() + return getTypeArgument(typeParameter)!! } private fun IrBuilder.irFloat(value: Float) = diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt index 5c4eafeccd5..2714748a27e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt @@ -19,19 +19,16 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions import org.jetbrains.kotlin.backend.konan.isValueType -import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.expressions.IrBlock -import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl +import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.types.KotlinType @@ -41,22 +38,24 @@ internal class LateinitLowering(val context: Context): FileLoweringPass { irFile.transformChildrenVoid(object: IrElementTransformerVoid() { override fun visitProperty(declaration: IrProperty): IrStatement { if (declaration.descriptor.isLateInit) - transformGetter(declaration.descriptor, declaration.getter!!) + transformGetter(declaration.backingField!!.symbol, declaration.getter!!) return declaration } - private fun transformGetter(propertyDescriptor: PropertyDescriptor, getter: IrFunction) { - assert (!propertyDescriptor.type.isValueType(), { "'lateinit' modifier is not allowed on value types" }) + private fun transformGetter(backingFieldSymbol: IrFieldSymbol, getter: IrFunction) { + val type = backingFieldSymbol.descriptor.type + assert (!type.isValueType(), { "'lateinit' modifier is not allowed on value types" }) val startOffset = getter.startOffset val endOffset = getter.endOffset - val irBuilder = context.createIrBuilder(getter.descriptor, startOffset, endOffset) + val irBuilder = context.createIrBuilder(getter.symbol, startOffset, endOffset) irBuilder.run { - val block = irBlock(propertyDescriptor.type) - val resultVar = scope.createTemporaryVariable(irGetField(irThis(), propertyDescriptor)) + val block = irBlock(type) + val resultVar = scope.createTemporaryVariable( + irGetField(irGet(getter.dispatchReceiverParameter!!.symbol), backingFieldSymbol)) block.statements.add(resultVar) val throwIfNull = irIfThenElse(context.builtIns.nothingType, - irNotEquals(irGet(resultVar.descriptor), irNull()), - irReturn(irGet(resultVar.descriptor)), + irNotEquals(irGet(resultVar.symbol), irNull()), + irReturn(irGet(resultVar.symbol)), irCall(throwErrorFunction)) block.statements.add(throwIfNull) getter.body = IrExpressionBodyImpl(startOffset, endOffset, block) @@ -65,11 +64,9 @@ internal class LateinitLowering(val context: Context): FileLoweringPass { }) } - private val throwErrorFunction = context.builtIns.getKonanInternalFunctions("ThrowUninitializedPropertyAccessException").single() + private val throwErrorFunction = context.ir.symbols.ThrowUninitializedPropertyAccessException private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock = IrBlockImpl(startOffset, endOffset, type) - private fun IrBuilderWithScope.irGetField(receiver: IrExpression?, property: PropertyDescriptor): IrExpression - = IrGetFieldImpl(startOffset, endOffset, property, receiver) } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt index f446bf2228d..78166e7b8c2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt @@ -21,9 +21,7 @@ import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions -import org.jetbrains.kotlin.backend.konan.descriptors.isSuspendFunctionInvoke import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.util.atMostOne @@ -43,9 +41,6 @@ import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl -import org.jetbrains.kotlin.ir.util.createParameterDeclarations -import org.jetbrains.kotlin.ir.util.getArguments -import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -53,6 +48,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.backend.common.descriptors.* +import org.jetbrains.kotlin.ir.util.* internal class SuspendFunctionsLowering(val context: Context): DeclarationContainerLoweringPass { @@ -67,7 +63,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai else null } transformCallableReferencesToSuspendLambdas(irDeclarationContainer) - transformCallsToExtensionSuspendFunctions(irDeclarationContainer) } private fun markSuspendLambdas(irDeclarationContainer: IrDeclarationContainer) { @@ -116,36 +111,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai } } - private fun transformCallsToExtensionSuspendFunctions(irDeclarationContainer: IrDeclarationContainer) { - irDeclarationContainer.declarations.forEach { - it.transformChildrenVoid(object: IrElementTransformerVoid() { - - override fun visitCall(expression: IrCall): IrExpression { - expression.transformChildrenVoid(this) - - val descriptor = expression.descriptor - - if (!descriptor.isSuspendFunctionInvoke || descriptor.extensionReceiverParameter == null) - return expression - - val invokeFunctionDescriptor = descriptor.dispatchReceiverParameter!!.type.memberScope - .getContributedFunctions(Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND).single() - return IrCallImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - calleeDescriptor = invokeFunctionDescriptor - ).apply { - dispatchReceiver = expression.dispatchReceiver - putValueArgument(0, expression.extensionReceiver) - invokeFunctionDescriptor.valueParameters.drop(1).forEach { - putValueArgument(it.index, expression.getValueArgument(it.index - 1)) - } - } - } - }) - } - } - private enum class SuspendFunctionKind { NO_SUSPEND_CALLS, DELEGATING, @@ -235,7 +200,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai } } - private val getContinuationDescriptor = context.builtIns.getKonanInternalFunctions("getContinuation").single() + private val symbols = context.ir.symbols + private val getContinuationSymbol = symbols.getContinuation private val returnIfSuspendedDescriptor = context.builtIns.getKonanInternalFunctions("returnIfSuspended").single() private fun removeReturnIfSuspendedCall(irFunction: IrFunction) { @@ -262,15 +228,15 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai +irReturn( irCall(coroutine.doResumeFunction.symbol).apply { dispatchReceiver = irCall(coroutine.coroutineConstructor.symbol).apply { - val functionParameters = irFunction.descriptor.explicitParameters + val functionParameters = irFunction.explicitParameters functionParameters.forEachIndexed { index, argument -> putValueArgument(index, irGet(argument)) } putValueArgument(functionParameters.size, - irCall(getContinuationDescriptor.substitute(descriptor.returnType!!))) + irCall(getContinuationSymbol, listOf(descriptor.returnType!!))) } - putValueArgument(0, irUnit()) // value - putValueArgument(1, irNull()) // exception + putValueArgument(0, irGetObject(symbols.unit)) // value + putValueArgument(1, irNull()) // exception }) } } @@ -285,17 +251,13 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai private var coroutineId = 0 private val COROUTINES_FQ_NAME = FqName.fromSegments(listOf("kotlin", "coroutines", "experimental")) - private val COROUTINES_INTRINSICS_FQ_NAME = FqName.fromSegments(listOf("kotlin", "coroutines", "experimental", "intrinsics")) private val KOTLIN_FQ_NAME = FqName("kotlin") private val coroutinesScope = context.irModule!!.descriptor.getPackage(COROUTINES_FQ_NAME).memberScope - private val coroutinesIntrinsicsScope = context.irModule!!.descriptor.getPackage(COROUTINES_INTRINSICS_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 val COROUTINE_SUSPENDED = coroutinesIntrinsicsScope - .getContributedVariables(Name.identifier("COROUTINE_SUSPENDED"), NoLookupLocation.FROM_BACKEND).first() private inner class CoroutineBuilder(val irFunction: IrFunction, val functionReference: IrFunctionReference?) { @@ -313,12 +275,17 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai private lateinit var coroutineClassThis: IrValueParameterSymbol private lateinit var argumentToPropertiesMap: Map - private val coroutineImplClassDescriptor = context.builtIns.getKonanInternalClass("CoroutineImpl") + private val coroutineImplSymbol = symbols.coroutineImpl + private val coroutineImplConstructorSymbol = coroutineImplSymbol.constructors.single() + private val coroutineImplClassDescriptor = coroutineImplSymbol.descriptor private val create1FunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope .getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND) .single { it.valueParameters.size == 1 } private val create1CompletionParameter = create1FunctionDescriptor.valueParameters[0] + private val coroutineImplLabelGetterSymbol = coroutineImplSymbol.getPropertyGetter("label")!! + private val coroutineImplLabelSetterSymbol = coroutineImplSymbol.getPropertySetter("label")!! + fun build(): BuiltCoroutine { val superTypes = mutableListOf(coroutineImplClassDescriptor.defaultType) var suspendFunctionClassDescriptor: ClassDescriptor? = null @@ -406,6 +373,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai ).filterNotNull().toList() coroutineClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null) + coroutineClass.addFakeOverrides() + coroutineConstructorBuilder.initialize() coroutineClass.declarations.add(coroutineConstructorBuilder.ir) @@ -437,8 +406,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai private fun createConstructorBuilder() = object : SymbolWithIrBuilder() { - private val coroutineImplConstructorDescriptor = coroutineImplClassDescriptor.constructors.single() - override fun buildSymbol() = IrConstructorSymbolImpl( ClassConstructorDescriptorImpl.create( /* containingDeclaration = */ coroutineClassDescriptor, @@ -452,7 +419,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl val constructorParameters = ( functionParameters - + coroutineImplConstructorDescriptor.valueParameters[0] // completion. + + coroutineImplConstructorSymbol.descriptor.valueParameters[0] // completion. ).mapIndexed { index, parameter -> parameter.copyAsValueParameter(descriptor, index) } descriptor.initialize(constructorParameters, Visibilities.PUBLIC) @@ -478,7 +445,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) body = irBuilder.irBlockBody { val completionParameter = valueParameters.last() - +IrDelegatingConstructorCallImpl(startOffset, endOffset, coroutineImplConstructorDescriptor).apply { + +IrDelegatingConstructorCallImpl(startOffset, endOffset, + coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply { putValueArgument(0, irGet(completionParameter.symbol)) } +IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol) @@ -493,8 +461,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai private fun createFactoryConstructorBuilder(boundParams: List) = object : SymbolWithIrBuilder() { - private val coroutineImplConstructorDescriptor = coroutineImplClassDescriptor.constructors.single() - override fun buildSymbol() = IrConstructorSymbolImpl( ClassConstructorDescriptorImpl.create( /* containingDeclaration = */ coroutineClassDescriptor, @@ -526,7 +492,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) body = irBuilder.irBlockBody { - +IrDelegatingConstructorCallImpl(startOffset, endOffset, coroutineImplConstructorDescriptor).apply { + +IrDelegatingConstructorCallImpl(startOffset, endOffset, + coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply { putValueArgument(0, irNull()) // Completion. } +IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol) @@ -669,9 +636,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai putValueArgument(index, irGet(parameter.symbol)) } putValueArgument(valueParameters.size, - irCall(getContinuationDescriptor.substitute(symbol.descriptor.returnType!!))) + irCall(getContinuationSymbol, listOf(symbol.descriptor.returnType!!))) } - putValueArgument(0, irUnit()) // value + putValueArgument(0, irGetObject(symbols.unit)) // value putValueArgument(1, irNull()) // exception } ) @@ -803,7 +770,10 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai scope.forEach { +irSetField(irGet(coroutineClassThis), localToPropertyMap[it]!!, irGet(localsMap[it.descriptor] ?: it)) } - +irSet(irGet(coroutineClassThis), label, irGet(suspensionPoint.suspensionPointIdParameter.symbol)) + +irCall(coroutineImplLabelSetterSymbol).apply { + dispatchReceiver = irGet(coroutineClassThis) + putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter.symbol)) + } } } restoreStateSymbol -> { @@ -828,13 +798,15 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai startOffset = startOffset, endOffset = endOffset, type = context.builtIns.unitType, - suspensionPointId = irGet(irGet(coroutineClassThis), label), + suspensionPointId = irCall(coroutineImplLabelGetterSymbol).apply { + dispatchReceiver = irGet(coroutineClassThis) + }, result = irBlock(startOffset, endOffset) { +irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception. statements.forEach { +it } }) if (irFunction.descriptor.returnType!!.isUnit()) - +irReturn(irUnit()) // Insert explicit return for Unit functions. + +irReturn(irGetObject(symbols.unit)) // Insert explicit return for Unit functions. } return function } @@ -1156,7 +1128,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai } private fun IrBuilderWithScope.irReturnIfSuspended(value: IrValueSymbol) = - irIfThen(irEqeqeq(irGet(value), irGet(COROUTINE_SUSPENDED)), + irIfThen(irEqeqeq(irGet(value), irCall(symbols.coroutineSuspendedGetter)), irReturn(irGet(value))) private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueSymbol) = diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt index fb083cc67b0..06603f329b9 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt @@ -23,47 +23,50 @@ import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedString import org.jetbrains.kotlin.backend.konan.ir.ir2string import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.PrimitiveType -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope -import org.jetbrains.kotlin.ir.builders.Scope -import org.jetbrains.kotlin.ir.builders.irGet -import org.jetbrains.kotlin.ir.builders.irSetVar +import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.functions +import org.jetbrains.kotlin.ir.util.getPropertyGetter import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.util.OperatorNameConventions class VarargInjectionLowering internal constructor(val context: Context): DeclarationContainerLoweringPass { override fun lower(irDeclarationContainer: IrDeclarationContainer) { irDeclarationContainer.declarations.forEach{ when (it) { - is IrField -> lower(it.descriptor, it.initializer) - is IrFunction -> lower(it.descriptor, it.body) + is IrField -> lower(it.symbol, it.initializer) + is IrFunction -> lower(it.symbol, it.body) is IrProperty -> { - lower(it.descriptor, it.backingField) - if (it.getter != null) - lower(it.getter!!.descriptor, it.getter) - if (it.setter != null) - lower(it.setter!!.descriptor, it.setter) + it.backingField?.let { field -> + lower(field.symbol, field) + } + it.getter?.let { getter -> + lower(getter.symbol, getter) + } + it.setter?.let { setter -> + lower(setter.symbol, setter) + } } } } } - private fun lower(owner:DeclarationDescriptor, element: IrElement?) { + private fun lower(owner: IrSymbol, element: IrElement?) { element?.transformChildrenVoid(object: IrElementTransformerVoid() { val transformer = this @@ -107,11 +110,13 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar val type = expression.varargElementType log("$expression: array type:$type, is array of primitives ${!KotlinBuiltIns.isArray(expression.type)}") val arrayHandle = arrayType(expression.type) - val arrayConstructor = arrayHandle.arrayDescriptor.constructors.find { it.valueParameters.size == 1 }!! - val block = irBlock(arrayHandle.arrayDescriptor.defaultType) - val arrayConstructorCall = irCall( - descriptor = arrayConstructor, - typeArguments = typeArgument(arrayConstructor, type)) + val arrayConstructor = arrayHandle.arraySymbol.constructors.find { it.owner.valueParameters.size == 1 }!! + val block = irBlock(arrayHandle.arraySymbol.owner.defaultType) + val arrayConstructorCall = if (arrayConstructor.owner.typeParameters.isEmpty()) { + irCall(arrayConstructor) + } else { + irCall(arrayConstructor, listOf(type)) + } val vars = expression.elements.map { @@ -135,10 +140,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar log("element:$i> ${ir2string(element)}") val dst = vars[element]!! if (element !is IrSpreadElement) { - val setArrayElementCall = irCall( - descriptor = arrayHandle.setMethodDescriptor, - typeArguments = null - ) + val setArrayElementCall = irCall(arrayHandle.setMethodSymbol) setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.symbol) setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.symbol) else irConstInt(i)) setArrayElementCall.putValueArgument(1, irGet(dst.symbol)) @@ -149,7 +151,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar } else { val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst.symbol)), "length".synthesizedString) block.statements.add(arraySizeVariable) - val copyCall = irCall(arrayHandle.copyRangeToDescriptor, null).apply { + val copyCall = irCall(arrayHandle.copyRangeToSymbol).apply { extensionReceiver = irGet(dst.symbol) putValueArgument(0, irGet(arrayTmpVariable.symbol)) /* destination */ putValueArgument(1, kIntZero) /* fromIndex */ @@ -170,13 +172,8 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar }) } - - private fun typeArgument(arrayConstructor: ClassConstructorDescriptor, type: KotlinType):Map? { - return if (!arrayConstructor.typeParameters.isEmpty()) - mapOf(arrayConstructor.typeParameters.first() to type) - else - null - } + private val symbols = context.ir.symbols + private val intPlusInt = symbols.intPlusInt private fun arrayType(type: KotlinType): ArrayHandle = when { KotlinBuiltIns.isPrimitiveArray(type) -> { @@ -196,7 +193,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar else -> kArrayHandler } - private fun IrBuilderWithScope.intPlus() = irCall(kIntPlusDescriptor, null) + private fun IrBuilderWithScope.intPlus() = irCall(intPlusInt) private fun IrBuilderWithScope.increment(expression: IrExpression, value: IrExpression): IrExpression { return intPlus().apply { dispatchReceiver = expression @@ -211,7 +208,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar }) } private fun calculateArraySize(arrayHandle: ArrayHandle, hasSpreadElement: Boolean, scope:Scope, expression: IrVararg, vars: Map): IrExpression? { - context.createIrBuilder(scope.scopeOwner, expression.startOffset, expression.endOffset).run { + context.createIrBuilder(scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset).run { if (!hasSpreadElement) return irConstInt(expression.elements.size) val notSpreadElementCount = expression.elements.filter { it !is IrSpreadElement}.size @@ -224,7 +221,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar } private fun IrBuilderWithScope.irArraySize(arrayHandle: ArrayHandle, expression: IrExpression): IrExpression { - val arraySize = irCall((arrayHandle.sizeDescriptor as PropertyDescriptor).getter as FunctionDescriptor, null).apply { + val arraySize = irCall(arrayHandle.sizeGetterSymbol).apply { dispatchReceiver = expression } return arraySize @@ -237,48 +234,31 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar context.log{"VARARG-INJECTOR: $msg"} } - data class ArrayHandle(val arrayDescriptor:ClassDescriptor, - val setMethodDescriptor: FunctionDescriptor, - val sizeDescriptor:DeclarationDescriptor, - val copyRangeToDescriptor:FunctionDescriptor) - val kKotlinPackage = context.builtIns.builtInsModule.getPackage(FqName("kotlin")) - val kByteArrayHandler = handle(arrayClassDescriptor("ByteArray")) - val kCharArrayHandler = handle(arrayClassDescriptor("CharArray")) - val kShortArrayHandler = handle(arrayClassDescriptor("ShortArray")) - val kIntArrayHandler = handle(arrayClassDescriptor("IntArray")) - val kLongArrayHandler = handle(arrayClassDescriptor("LongArray")) - val kFloatArrayHandler = handle(arrayClassDescriptor("FloatArray")) - val kDoubleArrayHandler = handle(arrayClassDescriptor("DoubleArray")) - val kBooleanArrayHandler = handle(arrayClassDescriptor("BooleanArray")) - val kArrayHandler = handle(context.builtIns.array) + data class ArrayHandle(val arraySymbol: IrClassSymbol, + val setMethodSymbol: IrFunctionSymbol, + val sizeGetterSymbol: IrFunctionSymbol, + val copyRangeToSymbol: IrFunctionSymbol) - val kInt = context.builtIns.int - val kIntType = context.builtIns.intType - val kIntPlusDescriptor = DescriptorUtils.getAllDescriptors(kInt.unsubstitutedMemberScope).find { - it.name.asString() == "plus" - && (it as FunctionDescriptor).valueParameters[0].type == kIntType} as FunctionDescriptor + val kByteArrayHandler = handle(symbols.byteArray) + val kCharArrayHandler = handle(symbols.charArray) + val kShortArrayHandler = handle(symbols.shortArray) + val kIntArrayHandler = handle(symbols.intArray) + val kLongArrayHandler = handle(symbols.longArray) + val kFloatArrayHandler = handle(symbols.floatArray) + val kDoubleArrayHandler = handle(symbols.doubleArray) + val kBooleanArrayHandler = handle(symbols.booleanArray) + val kArrayHandler = handle(symbols.array) - private fun handle(descriptor:ClassDescriptor) = ArrayHandle( - arrayDescriptor = descriptor, - setMethodDescriptor = setMethodDescriptor(descriptor), - sizeDescriptor = sizeMethodDescriptor(descriptor)!!, - copyRangeToDescriptor = copyRangeToFunctionDescriptor(descriptor)) + private fun handle(symbol: IrClassSymbol) = ArrayHandle( + arraySymbol = symbol, + setMethodSymbol = symbol.functions.single { it.descriptor.name == OperatorNameConventions.SET }, + sizeGetterSymbol = symbol.getPropertyGetter("size")!!, + copyRangeToSymbol = symbols.copyRangeTo[symbol.descriptor]!! + ) - private fun copyRangeToFunctionDescriptor(descriptor: ClassDescriptor): FunctionDescriptor { - val packageViewDescriptor = descriptor.module.getPackage(KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME) - return packageViewDescriptor.memberScope.getContributedFunctions(Name.identifier("copyRangeTo"), NoLookupLocation.FROM_BACKEND).first { - it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == descriptor - } - } - private fun setMethodDescriptor(descriptor:ClassDescriptor) = methodDescriptor(descriptor, "set") - private fun sizeMethodDescriptor(descriptor:ClassDescriptor) = descriptor(descriptor, "size") - private fun methodDescriptor(descriptor:ClassDescriptor, methodName:String) = DescriptorUtils.getFunctionByName(descriptor.unsubstitutedMemberScope, Name.identifier(methodName)) - private fun arrayClassDescriptor(name:String) = kKotlinPackage.memberScope.getContributedClassifier(Name.identifier(name), NoLookupLocation.FROM_BACKEND) as ClassDescriptor - private fun descriptor(descriptor: ClassDescriptor, name:String) = DescriptorUtils.getAllDescriptors(descriptor.unsubstitutedMemberScope).find{it.name.asString() == name} } private fun IrBuilderWithScope.irConstInt(value: Int): IrConst = IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, value) private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock = IrBlockImpl(startOffset, endOffset, type) -private fun IrBuilderWithScope.irCall(descriptor: FunctionDescriptor, typeArguments: Map?): IrCall = IrCallImpl(startOffset, endOffset, descriptor, typeArguments) private val IrBuilderWithScope.kIntZero get() = irConstInt(0) private val IrBuilderWithScope.kIntOne get() = irConstInt(1) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt index 76c6329a50d..e53943ee963 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol +import org.jetbrains.kotlin.ir.util.addFakeOverrides import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer import org.jetbrains.kotlin.serialization.KonanIr @@ -1057,6 +1058,7 @@ internal class IrDeserializer(val context: Context, val clazz = IrClassImpl(start, end, origin, descriptor, members) clazz.createParameterDeclarations() + clazz.addFakeOverrides() return clazz diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializerVisitor.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializerVisitor.kt index cee36cb5f8a..eb811ec4447 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializerVisitor.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializerVisitor.kt @@ -35,7 +35,6 @@ import org.jetbrains.kotlin.backend.konan.PhaseManager import org.jetbrains.kotlin.backend.konan.KonanPhase import org.jetbrains.kotlin.serialization.MutableTypeTable import org.jetbrains.kotlin.serialization.KonanLinkData -import org.jetbrains.kotlin.backend.common.validateIrFunction internal class DeserializerDriver(val context: Context) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt index 489ae76e1fd..0b4636086f7 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt @@ -16,33 +16,17 @@ package org.jetbrains.kotlin.ir.builders -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.backend.common.descriptors.substitute +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeProjectionImpl -import org.jetbrains.kotlin.types.TypeSubstitutor - -inline fun IrBuilderWithScope.irLetSequence( - value: IrExpression, - nameHint: String? = null, - startOffset: Int = this.startOffset, - endOffset: Int = this.endOffset, - origin: IrStatementOrigin? = null, - resultType: KotlinType? = null, - body: IrBlockBuilder.(VariableDescriptor) -> Unit -): IrExpression = irBlock(startOffset, endOffset, origin, resultType) { - val irTemporary = defineTemporary(value, nameHint) - this.body(irTemporary) -} fun IrBuilderWithScope.irWhile(origin: IrStatementOrigin? = null) = IrWhileLoopImpl(startOffset, endOffset, context.builtIns.unitType, origin) @@ -57,46 +41,18 @@ fun IrBuilderWithScope.irTrue() = IrConstImpl.boolean(startOffset, endOffset, co fun IrBuilderWithScope.irFalse() = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType, false) -@Deprecated("Creates unbound symbol") -fun IrBuilderWithScope.irGet(value: ValueDescriptor) = - IrGetValueImpl(startOffset, endOffset, value) - -@Deprecated("Creates unbound symbol") -fun IrBuilderWithScope.irGet(receiver: IrExpression?, property: PropertyDescriptor): IrCall = - IrCallImpl(startOffset, endOffset, property.getter!!).apply { - dispatchReceiver = receiver - } - -@Deprecated("Creates unbound symbol") -fun IrBuilderWithScope.irThis() = - scope.classOwner().let { classOwner -> - IrGetValueImpl(startOffset, endOffset, classOwner.thisAsReceiverParameter) - } - -@Deprecated("Creates unbound symbol") -fun IrBuilderWithScope.irSetVar(variable: VariableDescriptor, value: IrExpression) = - IrSetVariableImpl(startOffset, endOffset, variable, value, IrStatementOrigin.EQ) - -@Deprecated("Creates unbound symbol") -fun IrBuilderWithScope.irCall(descriptor: FunctionDescriptor): IrCallImpl { - return IrCallImpl(this.startOffset, this.endOffset, descriptor) -} - fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol): IrCallImpl { return IrCallImpl(this.startOffset, this.endOffset, symbol) } -@Deprecated("Creates unbound symbol") -fun IrBuilderWithScope.irCall( - callee: FunctionDescriptor, - typeArguments: Map -): IrCallImpl { - val substitutionContext = typeArguments.map { (typeParameter, typeArgument) -> - typeParameter.typeConstructor to TypeProjectionImpl(typeArgument) - }.toMap() +fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: Map) = + IrCallImpl(this.startOffset, this.endOffset, symbol, symbol.descriptor.substitute(typeArguments), typeArguments) - val substitutor = TypeSubstitutor.create(substitutionContext) - val substitutedCallee = callee.substitute(substitutor)!! +fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: List) = + irCall(symbol, symbol.descriptor.typeParameters.zip(typeArguments).toMap()) - return IrCallImpl(this.startOffset, this.endOffset, substitutedCallee, typeArguments) -} \ No newline at end of file +fun IrBuilderWithScope.irGetObject(classSymbol: IrClassSymbol) = + IrGetObjectValueImpl(startOffset, endOffset, classSymbol.owner.defaultType, classSymbol) + +fun IrBuilderWithScope.irGetField(receiver: IrExpression?, symbol: IrFieldSymbol) = + IrGetFieldImpl(startOffset, endOffset, symbol, receiver) \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index b6ebeea365d..547405f3d16 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -16,20 +16,19 @@ package org.jetbrains.kotlin.ir.util +import org.jetbrains.kotlin.backend.konan.util.atMostOne import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation -import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource -import org.jetbrains.kotlin.descriptors.ParameterDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.symbols.* -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.Name import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.source.PsiSourceElement @@ -175,6 +174,35 @@ fun IrClass.createParameterDeclarations() { } } +fun IrClass.addFakeOverrides() { + + val startOffset = this.startOffset + val endOffset = this.endOffset + + fun FunctionDescriptor.createFunction(): IrFunction = IrFunctionImpl( + startOffset, endOffset, + IrDeclarationOrigin.FAKE_OVERRIDE, this + ).apply { + createParameterDeclarations() + } + + descriptor.unsubstitutedMemberScope.getContributedDescriptors() + .filterIsInstance() + .filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE } + .mapTo(this.declarations) { + when (it) { + is FunctionDescriptor -> it.createFunction() + is PropertyDescriptor -> + IrPropertyImpl(startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, it).apply { + // TODO: add field if getter is missing? + getter = it.getter?.createFunction() + setter = it.setter?.createFunction() + } + else -> TODO(it.toString()) + } + } +} + private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int = descriptor.startOffset ?: this.startOffset @@ -193,6 +221,16 @@ val IrClassSymbol.functions: Sequence val IrClassSymbol.constructors: Sequence get() = this.owner.declarations.asSequence().filterIsInstance().map { it.symbol } +private fun IrClassSymbol.getPropertyDeclaration(name: String) = + this.owner.declarations.filterIsInstance() + .atMostOne { it.descriptor.name == Name.identifier(name) } + +fun IrClassSymbol.getPropertyGetter(name: String): IrFunctionSymbol? = + this.getPropertyDeclaration(name)?.getter?.symbol + +fun IrClassSymbol.getPropertySetter(name: String): IrFunctionSymbol? = + this.getPropertyDeclaration(name)?.setter?.symbol + val IrFunction.explicitParameters: List get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).map { it.symbol } @@ -201,68 +239,3 @@ val IrValueParameter.type: KotlinType val IrClass.defaultType: KotlinType get() = this.descriptor.defaultType - -class IrSymbolBindingChecker : IrElementVisitorVoid { - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitDeclarationReference(expression: IrDeclarationReference) { - super.visitDeclarationReference(expression) - - expression.symbol.ensureBound(expression) - } - - override fun visitFunctionAccess(expression: IrFunctionAccessExpression) { - super.visitFunctionAccess(expression) - - expression.symbol.ensureBound(expression) - } - - override fun visitFunctionReference(expression: IrFunctionReference) { - super.visitFunctionReference(expression) - - expression.symbol.ensureBound(expression) - } - - override fun visitCall(expression: IrCall) { - super.visitCall(expression) - - expression.superQualifierSymbol?.ensureBound(expression) - } - - override fun visitPropertyReference(expression: IrPropertyReference) { - super.visitPropertyReference(expression) - - expression.field?.ensureBound(expression) - expression.getter?.ensureBound(expression) - expression.setter?.ensureBound(expression) - } - - override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference) { - super.visitLocalDelegatedPropertyReference(expression) - - expression.delegate.ensureBound(expression) - expression.getter.ensureBound(expression) - expression.setter?.ensureBound(expression) - } - - override fun visitReturn(expression: IrReturn) { - super.visitReturn(expression) - - expression.returnTargetSymbol.ensureBound(expression) - } - - override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) { - super.visitInstanceInitializerCall(expression) - - expression.classSymbol.ensureBound(expression) - } - - private fun IrSymbol.ensureBound(expression: IrExpression) { - if (!this.isBound) { - throw Error("Unbound symbol ${this} found in ${expression.render()}") - } - } - -} diff --git a/gradle.properties b/gradle.properties index 6f864962c22..3e2094ab81b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,5 +24,5 @@ testDataVersion=1067176:id kotlinCompilerRepo=http://dl.bintray.com/jetbrains/kotlin-native-dependencies #kotlinCompilerRepo=http://oss.sonatype.org/content/repositories/snapshots #kotlinCompilerRepo=http://dl.bintray.com/kotlin/kotlin-dev -kotlinCompilerModule=org.jetbrains.kotlin:kotlin-compiler:1.1-20170519.065155-538 +kotlinCompilerModule=org.jetbrains.kotlin:kotlin-compiler:1.1-20170521.012435-545 konanVersion=0.2