diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/BackendContext.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/BackendContext.kt index 6ed6e84c329..2aaf9b4ab3d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/BackendContext.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/BackendContext.kt @@ -16,9 +16,9 @@ package org.jetbrains.kotlin.backend.common -import org.jetbrains.kotlin.backend.common.descriptors.DescriptorsFactory -import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager +import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory import org.jetbrains.kotlin.backend.common.ir.Ir +import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns @@ -27,5 +27,5 @@ interface BackendContext { val builtIns: KotlinBuiltIns val irBuiltIns: IrBuiltIns val sharedVariablesManager: SharedVariablesManager - val descriptorsFactory: DescriptorsFactory + val declarationFactory: DeclarationFactory } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/TailRecursionCallsCollector.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/TailRecursionCallsCollector.kt index 66e1e4e3e6f..a74e058f17e 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/TailRecursionCallsCollector.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/TailRecursionCallsCollector.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.common import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.util.usesDefaultArguments import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -35,7 +36,7 @@ import org.jetbrains.kotlin.types.typeUtil.isUnit * However any returned call can be correctly optimized as tail recursion. */ fun collectTailRecursionCalls(irFunction: IrFunction): Set { - if (!irFunction.descriptor.isTailrec) { + if ((irFunction as? IrSimpleFunction)?.isTailrec != true) { return emptySet() } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorsFactory.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorsFactory.kt deleted file mode 100644 index 0ed28d0af02..00000000000 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorsFactory.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.backend.common.descriptors - -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol -import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol - -interface DescriptorsFactory { - fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol - fun getOuterThisFieldSymbol(innerClass: IrClass): IrFieldSymbol - fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructorSymbol - fun getSymbolForObjectInstance(singleton: IrClassSymbol): IrFieldSymbol -} \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt new file mode 100644 index 00000000000..12ab804f273 --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt @@ -0,0 +1,568 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.common.descriptors + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.types.toKotlinType +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.constants.ConstantValue +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver +import org.jetbrains.kotlin.types.* + + +abstract class WrappedDeclarationDescriptor(override val annotations: Annotations) : DeclarationDescriptor { + lateinit var owner: T + fun bind(declaration: T) { owner = declaration } +} + +abstract class WrappedCallableDescriptor( + annotations: Annotations, + private val sourceElement: SourceElement +) : CallableDescriptor, WrappedDeclarationDescriptor(annotations) { + override fun getOriginal() = this + + override fun substitute(substitutor: TypeSubstitutor): CallableDescriptor { + TODO("not implemented") + } + + override fun getOverriddenDescriptors(): Collection { + TODO("not implemented") + } + + override fun getSource() = sourceElement + + override fun getExtensionReceiverParameter(): ReceiverParameterDescriptor? = null + + override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null + + override fun getTypeParameters(): List { + TODO("not implemented") + } + + override fun getReturnType(): KotlinType? { + TODO("not implemented") + } + + override fun getValueParameters(): MutableList { + TODO("not implemented") + } + + override fun hasStableParameterNames(): Boolean { + TODO("not implemented") + } + + override fun hasSynthesizedParameterNames() = false + + override fun getVisibility(): Visibility { + TODO("not implemented") + } + + override fun accept(visitor: DeclarationDescriptorVisitor?, data: D): R { + TODO("not implemented") + } + + override fun acceptVoid(visitor: DeclarationDescriptorVisitor?) { + TODO("not implemented") + } +} + +open class WrappedValueParameterDescriptor( + annotations: Annotations = Annotations.EMPTY, + sourceElement: SourceElement = SourceElement.NO_SOURCE +) : ValueParameterDescriptor, WrappedCallableDescriptor(annotations, sourceElement) { + + override val index get() = owner.index + override val isCrossinline get() = owner.isCrossinline + override val isNoinline get() = owner.isNoinline + override val varargElementType get() = owner.varargElementType?.toKotlinType() + override fun isConst() = false + override fun isVar() = false + + override fun getContainingDeclaration() = (owner.parent as IrFunction).descriptor + override fun getType() = owner.type.toKotlinType() + override fun getName() = owner.name + override fun declaresDefaultValue() = owner.defaultValue != null + override fun getCompileTimeInitializer(): ConstantValue<*>? = null + + override fun copy(newOwner: CallableDescriptor, newName: Name, newIndex: Int) = object : WrappedValueParameterDescriptor() { + override fun getContainingDeclaration() = newOwner as FunctionDescriptor + override fun getName() = newName + override val index = newIndex + }.also { it.bind(owner) } + + + override fun getOverriddenDescriptors(): Collection = emptyList() + + override fun getOriginal() = this + + override fun substitute(substitutor: TypeSubstitutor): ValueParameterDescriptor { + TODO("") + } + + override fun getReturnType(): KotlinType? = owner.type.toKotlinType() + + override fun accept(visitor: DeclarationDescriptorVisitor?, data: D) = + visitor!!.visitValueParameterDescriptor(this, data)!! + + override fun acceptVoid(visitor: DeclarationDescriptorVisitor?) { + visitor!!.visitValueParameterDescriptor(this, null) + } +} + +open class WrappedTypeParameterDescriptor( + annotations: Annotations = Annotations.EMPTY, + sourceElement: SourceElement = SourceElement.NO_SOURCE +) : TypeParameterDescriptor, WrappedCallableDescriptor(annotations, sourceElement) { + override fun getName() = owner.name + + override fun isReified() = owner.isReified + + override fun getVariance() = owner.variance + + override fun getUpperBounds() = owner.superTypes.map { it.toKotlinType() } + + override fun getTypeConstructor(): TypeConstructor { + return object : TypeConstructor { + override fun getParameters(): List { + TODO("not implemented") + } + + override fun getSupertypes() = upperBounds + + override fun isFinal() = false + + override fun isDenotable() = false + + override fun getDeclarationDescriptor() = owner.descriptor + + override fun getBuiltIns(): KotlinBuiltIns { + TODO("not implemented") + } + + } + } + + override fun getOriginal() = this + + override fun getIndex() = owner.index + + override fun isCapturedFromOuterDeclaration() = false + + override fun getDefaultType(): SimpleType { + TODO("not implemented") + } + + override fun getContainingDeclaration() = (owner.parent as IrDeclaration).descriptor + + override fun accept(visitor: DeclarationDescriptorVisitor?, data: D): R = + visitor!!.visitTypeParameterDescriptor(this, data) + + override fun acceptVoid(visitor: DeclarationDescriptorVisitor?) { + visitor!!.visitTypeParameterDescriptor(this, null) + } + +} + +open class WrappedVariableDescriptor( + annotations: Annotations = Annotations.EMPTY, + sourceElement: SourceElement = SourceElement.NO_SOURCE +) : VariableDescriptor, WrappedCallableDescriptor(annotations, sourceElement) { + + override fun getContainingDeclaration() = (owner.parent as IrFunction).descriptor + override fun getType() = owner.type.toKotlinType() + override fun getName() = owner.name + override fun isConst() = owner.isConst + override fun isVar() = owner.isVar + override fun isLateInit() = owner.isLateinit + + override fun getCompileTimeInitializer(): ConstantValue<*>? { + TODO("") + } + + override fun getOverriddenDescriptors(): Collection { + TODO("Not Implemented") + } + + override fun getOriginal() = this + + override fun substitute(substitutor: TypeSubstitutor): VariableDescriptor { + TODO("") + } + + override fun accept(visitor: DeclarationDescriptorVisitor?, data: D): R = + visitor!!.visitVariableDescriptor(this, data) + override fun acceptVoid(visitor: DeclarationDescriptorVisitor?) { + visitor!!.visitVariableDescriptor(this, null) + } +} + +open class WrappedSimpleFunctionDescriptor( + annotations: Annotations = Annotations.EMPTY, + sourceElement: SourceElement = SourceElement.NO_SOURCE +) : SimpleFunctionDescriptor, WrappedCallableDescriptor(annotations, sourceElement) { + override fun getOverriddenDescriptors() = owner.overriddenSymbols.map { it.descriptor } + override fun getContainingDeclaration() = (owner.parent as IrSymbolOwner).symbol.descriptor + override fun getModality() = owner.modality + override fun getName() = owner.name + override fun getVisibility() = owner.visibility + override fun getReturnType() = owner.returnType.toKotlinType() + + override fun getDispatchReceiverParameter() = owner.dispatchReceiverParameter?.run { + (containingDeclaration as ClassDescriptor).thisAsReceiverParameter + } + + val extensionReceiver by lazy { + owner.extensionReceiverParameter?.let { + ReceiverParameterDescriptorImpl(this, ExtensionReceiver(it.descriptor, it.type.toKotlinType(), null)) + } + } + + override fun getExtensionReceiverParameter() = extensionReceiver + override fun getTypeParameters() = owner.typeParameters.map { it.descriptor } + override fun getValueParameters() = owner.valueParameters + .asSequence() + .mapNotNull { it.descriptor as? ValueParameterDescriptor } + .toMutableList() + override fun isExternal() = owner.isExternal + override fun isSuspend() = owner.isSuspend + override fun isTailrec() = owner.isTailrec + override fun isInline() = owner.isInline + + override fun isExpect() = false + override fun isActual() = false + override fun isInfix() = false + override fun isOperator() = false + + override fun getOriginal() = this + override fun substitute(substitutor: TypeSubstitutor): SimpleFunctionDescriptor { + TODO("") + } + + override fun setOverriddenDescriptors(overriddenDescriptors: MutableCollection) { + TODO("not implemented") + } + + override fun getKind() = + if (owner.origin == IrDeclarationOrigin.FAKE_OVERRIDE) CallableMemberDescriptor.Kind.FAKE_OVERRIDE + else CallableMemberDescriptor.Kind.SYNTHESIZED + + override fun isHiddenToOvercomeSignatureClash(): Boolean { + TODO("not implemented") + } + + override fun copy( + newOwner: DeclarationDescriptor?, + modality: Modality?, + visibility: Visibility?, + kind: CallableMemberDescriptor.Kind?, + copyOverrides: Boolean + ): SimpleFunctionDescriptor { + TODO("not implemented") + } + + override fun isHiddenForResolutionEverywhereBesideSupercalls(): Boolean { + TODO("not implemented") + } + + override fun getInitialSignatureDescriptor() = null + + override fun getUserData(key: FunctionDescriptor.UserDataKey?): V? = null + + override fun newCopyBuilder(): FunctionDescriptor.CopyBuilder { + TODO("not implemented") + } + + override fun accept(visitor: DeclarationDescriptorVisitor?, data: D) = + visitor!!.visitFunctionDescriptor(this, data) + + override fun acceptVoid(visitor: DeclarationDescriptorVisitor?) { + visitor!!.visitFunctionDescriptor(this, null) + } +} + +open class WrappedClassConstructorDescriptor( + annotations: Annotations = Annotations.EMPTY, + sourceElement: SourceElement = SourceElement.NO_SOURCE +) : ClassConstructorDescriptor, WrappedCallableDescriptor(annotations, sourceElement) { + override fun getContainingDeclaration() = (owner.parent as IrClass).descriptor + + override fun getTypeParameters() = owner.typeParameters.map { it.descriptor } + override fun getValueParameters() = owner.valueParameters.asSequence() + .mapNotNull { it.descriptor as? ValueParameterDescriptor } + .toMutableList() + + override fun getOriginal() = this + + override fun substitute(substitutor: TypeSubstitutor): ClassConstructorDescriptor { + TODO("not implemented") + } + + override fun copy( + newOwner: DeclarationDescriptor, + modality: Modality, + visibility: Visibility, + kind: CallableMemberDescriptor.Kind, + copyOverrides: Boolean + ): ClassConstructorDescriptor { + TODO("not implemented") + } + + override fun getModality() = Modality.FINAL + + + override fun setOverriddenDescriptors(overriddenDescriptors: MutableCollection) { + TODO("not implemented") + } + + override fun getKind() = CallableMemberDescriptor.Kind.SYNTHESIZED + + override fun getConstructedClass() = (owner.parent as IrClass).descriptor + + override fun getName() = owner.name + + override fun getOverriddenDescriptors(): MutableCollection = mutableListOf() + + override fun getInitialSignatureDescriptor(): FunctionDescriptor? = null + + override fun getVisibility() = owner.visibility + + override fun isHiddenToOvercomeSignatureClash(): Boolean { + TODO("not implemented") + } + + override fun isOperator() = false + + override fun isInline() = owner.isInline + + override fun isHiddenForResolutionEverywhereBesideSupercalls(): Boolean { + TODO("not implemented") + } + + override fun getReturnType() = owner.returnType.toKotlinType() + + override fun isPrimary() = owner.isPrimary + + override fun isExpect() = false + + override fun isTailrec() = false + + override fun isActual() = false + + override fun isInfix() = false + + override fun isSuspend() = false + + override fun getUserData(key: FunctionDescriptor.UserDataKey?): V? = null + + override fun isExternal() = owner.isExternal + + override fun newCopyBuilder(): FunctionDescriptor.CopyBuilder { + TODO("not implemented") + } + + override fun accept(visitor: DeclarationDescriptorVisitor?, data: D): R = + visitor!!.visitConstructorDescriptor(this, data) + + override fun acceptVoid(visitor: DeclarationDescriptorVisitor?) { + visitor!!.visitConstructorDescriptor(this, null) + } +} + +open class WrappedClassDescriptor( + annotations: Annotations = Annotations.EMPTY, + private val sourceElement: SourceElement = SourceElement.NO_SOURCE +) : ClassDescriptor, WrappedDeclarationDescriptor(annotations) { + override fun getName() = owner.name + + override fun getMemberScope(typeArguments: MutableList): MemberScope { + TODO("not implemented") + } + + override fun getMemberScope(typeSubstitution: TypeSubstitution): MemberScope { + TODO("not implemented") + } + + override fun getUnsubstitutedMemberScope(): MemberScope { + TODO("not implemented") + } + + override fun getUnsubstitutedInnerClassesScope(): MemberScope { + TODO("not implemented") + } + + override fun getStaticScope(): MemberScope { + TODO("not implemented") + } + + override fun getSource() = sourceElement + + override fun getConstructors() = owner.declarations.asSequence().filterIsInstance().map { it.descriptor }.toList() + + override fun getContainingDeclaration() = (owner.parent as IrSymbolOwner).symbol.descriptor + + override fun getDefaultType(): SimpleType { + TODO("not implemented") + } + + override fun getKind() = owner.kind + + override fun getModality() = owner.modality + + override fun getCompanionObjectDescriptor() = owner.declarations.filterIsInstance().firstOrNull { it.isCompanion }?.descriptor + + override fun getVisibility() = owner.visibility + + override fun isCompanionObject() = owner.isCompanion + + override fun isData() = owner.isData + + override fun isInline() = owner.isInline + + override fun getThisAsReceiverParameter() = owner.thisReceiver?.descriptor as ReceiverParameterDescriptor + + override fun getUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor? { + TODO("not implemented") + } + + override fun getDeclaredTypeParameters() = owner.typeParameters.map { it.descriptor } + + override fun getSealedSubclasses(): Collection { + TODO("not implemented") + } + + override fun getOriginal() = this + + override fun isExpect() = false + + override fun substitute(substitutor: TypeSubstitutor): ClassifierDescriptorWithTypeParameters { + TODO("not implemented") + } + + override fun isActual() = false + + override fun getTypeConstructor(): TypeConstructor { + TODO("not implemented") + } + + override fun isInner() = owner.isInner + + override fun isExternal() = owner.isExternal + + override fun accept(visitor: DeclarationDescriptorVisitor?, data: D): R = + visitor!!.visitClassDescriptor(this, data) + + override fun acceptVoid(visitor: DeclarationDescriptorVisitor?) { + visitor!!.visitClassDescriptor(this, null) + } +} + + +open class WrappedPropertyDescriptor( + annotations: Annotations = Annotations.EMPTY, + private val sourceElement: SourceElement = SourceElement.NO_SOURCE +) : PropertyDescriptor, WrappedDeclarationDescriptor(annotations) { + override fun getModality() = if (owner.isFinal) Modality.FINAL else Modality.OPEN + + override fun setOverriddenDescriptors(overriddenDescriptors: MutableCollection) { + TODO("not implemented") + } + + override fun getKind() = CallableMemberDescriptor.Kind.SYNTHESIZED + + override fun getName() = owner.name + + override fun getSource() = sourceElement + + override fun hasSynthesizedParameterNames(): Boolean { + TODO("not implemented") + } + + override fun getOverriddenDescriptors(): MutableCollection = mutableListOf() + + override fun copy( + newOwner: DeclarationDescriptor?, + modality: Modality?, + visibility: Visibility?, + kind: CallableMemberDescriptor.Kind?, + copyOverrides: Boolean + ): CallableMemberDescriptor { + TODO("not implemented") + } + + override fun getValueParameters(): MutableList = mutableListOf() + + override fun getCompileTimeInitializer(): ConstantValue<*>? { + TODO("not implemented") + } + + override fun isSetterProjectedOut(): Boolean { + TODO("not implemented") + } + + override fun getAccessors(): MutableList = mutableListOf() + + override fun getTypeParameters() = emptyList() + + override fun getVisibility() = owner.visibility + + override val setter: PropertySetterDescriptor? get() = null + + override fun getOriginal() = this + + override fun isExpect() = false + + override fun substitute(substitutor: TypeSubstitutor): PropertyDescriptor { + TODO("not implemented") + } + + override fun isActual() = false + + override fun getReturnType() = owner.type.toKotlinType() + + override fun hasStableParameterNames(): Boolean { + TODO("not implemented") + } + + override fun getType(): KotlinType = owner.type.toKotlinType() + + override fun isVar() = owner.isFinal + + override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? { + TODO("not implemented") + } + + override fun isConst() = false + + override fun getContainingDeclaration() = (owner.parent as IrSymbolOwner).symbol.descriptor + + override fun isLateInit() = false + + override fun getExtensionReceiverParameter(): ReceiverParameterDescriptor? { + TODO("not implemented") + } + + override fun isExternal() = owner.isExternal + + override fun accept(visitor: DeclarationDescriptorVisitor?, data: D) = + visitor!!.visitPropertyDescriptor(this, data) + + override fun acceptVoid(visitor: DeclarationDescriptorVisitor?) { + visitor!!.visitPropertyDescriptor(this, null) + } + + override val getter: PropertyGetterDescriptor? get() = null + + override fun newCopyBuilder(): CallableMemberDescriptor.CopyBuilder { + TODO("not implemented") + } + + override val isDelegated get() = false +} \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/DeclarationFactory.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/DeclarationFactory.kt new file mode 100644 index 00000000000..02b12bc1d57 --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/DeclarationFactory.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.common.ir + +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.types.IrType + +interface DeclarationFactory { + object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS") + + fun getFieldForEnumEntry(enumEntry: IrEnumEntry, type: IrType): IrField + fun getOuterThisField(innerClass: IrClass): IrField + fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructor + fun getFieldForObjectInstance(singleton: IrClass): IrField +} \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt index 2b434e4a057..062abfd899d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt @@ -25,7 +25,7 @@ abstract class Ir(val context: T, val irModule: Ir abstract val symbols: Symbols - val defaultParameterDeclarationsCache = mutableMapOf() + val defaultParameterDeclarationsCache = mutableMapOf() open fun shouldGenerateHandlerParameterForDefaultBodyFun() = false } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt index c5e50daf98a..20f43012e92 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt @@ -17,18 +17,25 @@ package org.jetbrains.kotlin.backend.common.ir import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl -import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor import org.jetbrains.kotlin.ir.util.defaultType import java.io.StringWriter @@ -133,3 +140,40 @@ fun IrClass.addSimpleDelegatingConstructor( this.declarations.add(constructor) } } + +val IrCall.isSuspend get() = (symbol.owner as? IrSimpleFunction)?.isSuspend == true +val IrFunctionReference.isSuspend get() = (symbol.owner as? IrSimpleFunction)?.isSuspend == true + + +fun IrValueParameter.copyTo(irFunction: IrFunction, shift: Int = 0): IrValueParameter { + val descriptor = WrappedValueParameterDescriptor(symbol.descriptor.annotations, symbol.descriptor.source) + val symbol = IrValueParameterSymbolImpl(descriptor) + return IrValueParameterImpl( + startOffset, endOffset, origin, symbol, + name, shift + index, type, varargElementType, isCrossinline, isNoinline + ).also { + descriptor.bind(it) + it.parent = irFunction + } +} + +fun IrTypeParameter.copyTo(irFunction: IrFunction, shift: Int = 0): IrTypeParameter { + val descriptor = WrappedTypeParameterDescriptor(symbol.descriptor.annotations, symbol.descriptor.source) + val symbol = IrTypeParameterSymbolImpl(descriptor) + return IrTypeParameterImpl(startOffset, endOffset, origin, symbol, name, shift + index, isReified, variance).also { + descriptor.bind(it) + it.parent = irFunction + } +} + +fun IrFunction.copyParameterDeclarationsFrom(from: IrFunction) { + + dispatchReceiverParameter = from.dispatchReceiverParameter?.copyTo(this) + extensionReceiverParameter = from.extensionReceiverParameter?.copyTo(this) + + val shift = valueParameters.size + valueParameters += from.valueParameters.map { it.copyTo(this, shift) } + + assert(typeParameters.isEmpty()) + from.typeParameters.mapTo(typeParameters) { it.copyTo(this) } +} diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/SharedVariablesManager.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/SharedVariablesManager.kt similarity index 53% rename from compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/SharedVariablesManager.kt rename to compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/SharedVariablesManager.kt index 5f92f7aa2d5..7ca691c399d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/SharedVariablesManager.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/SharedVariablesManager.kt @@ -1,20 +1,9 @@ /* - * 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. + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. */ -package org.jetbrains.kotlin.backend.common.descriptors +package org.jetbrains.kotlin.backend.common.ir import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrVariable diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt index 6ce9890e07d..31498588eba 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt @@ -16,13 +16,12 @@ package org.jetbrains.kotlin.backend.common.lower -import org.jetbrains.kotlin.backend.common.* -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.backend.common.peek +import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.IrCatch -import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression -import org.jetbrains.kotlin.ir.expressions.IrValueAccessExpression +import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -33,27 +32,27 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils // TODO: rename the file. class Closure(val capturedValues: List = emptyList()) -class ClosureAnnotator { - private val closureBuilders = mutableMapOf() +class ClosureAnnotator(declaration: IrDeclaration) { + private val closureBuilders = mutableMapOf() - constructor(declaration: IrDeclaration) { + init { // Collect all closures for classes and functions. Collect call graph declaration.acceptChildrenVoid(ClosureCollectorVisitor()) } - fun getFunctionClosure(descriptor: FunctionDescriptor) = getClosure(descriptor) - fun getClassClosure(descriptor: ClassDescriptor) = getClosure(descriptor) + fun getFunctionClosure(declaration: IrFunction) = getClosure(declaration) + fun getClassClosure(declaration: IrClass) = getClosure(declaration) - private fun getClosure(descriptor: DeclarationDescriptor) : Closure { + private fun getClosure(declaration: IrDeclaration): Closure { closureBuilders.values.forEach { it.processed = false } return closureBuilders - .getOrElse(descriptor) { throw AssertionError("No closure builder for passed descriptor.") } - .buildClosure() + .getOrElse(declaration) { throw AssertionError("No closure builder for passed descriptor.") } + .buildClosure() } - private class ClosureBuilder(val owner: DeclarationDescriptor) { + private class ClosureBuilder(val owner: IrDeclaration) { val capturedValues = mutableSetOf() - private val declaredValues = mutableSetOf() + private val declaredValues = mutableSetOf() private val includes = mutableSetOf() var processed = false @@ -65,10 +64,10 @@ class ClosureAnnotator { */ fun buildClosure(): Closure { val result = mutableSetOf().apply { addAll(capturedValues) } - includes.forEach { - if (!it.processed) { - it.processed = true - it.buildClosure().capturedValues.filterTo(result) { isExternal(it.descriptor) } + includes.forEach { builder -> + if (!builder.processed) { + builder.processed = true + builder.buildClosure().capturedValues.filterTo(result) { isExternal(it.owner) } } } // TODO: We can save the closure and reuse it. @@ -80,20 +79,19 @@ class ClosureAnnotator { includes.add(includingBuilder) } - fun declareVariable(valueDescriptor: ValueDescriptor?) { - if (valueDescriptor != null) - declaredValues.add(valueDescriptor) + fun declareVariable(valueDeclaration: IrValueDeclaration?) { + if (valueDeclaration != null) + declaredValues.add(valueDeclaration) } fun seeVariable(value: IrValueSymbol) { - if (isExternal(value.descriptor)) + if (isExternal(value.owner)) capturedValues.add(value) } - fun isExternal(valueDescriptor: ValueDescriptor): Boolean { - return !declaredValues.contains(valueDescriptor) + fun isExternal(valueDeclaration: IrValueDeclaration): Boolean { + return !declaredValues.contains(valueDeclaration) } - } private inner class ClosureCollectorVisitor : IrElementVisitorVoid { @@ -104,7 +102,7 @@ class ClosureAnnotator { // We don't include functions or classes in a parent function when they are declared. // Instead we will include them when are is used (use = call for a function or constructor call for a class). val parentBuilder = closuresStack.peek() - if (parentBuilder != null && parentBuilder.owner !is FunctionDescriptor) { + if (parentBuilder != null && parentBuilder.owner !is IrFunction) { parentBuilder.include(builder) } } @@ -114,18 +112,18 @@ class ClosureAnnotator { } override fun visitClass(declaration: IrClass) { - val classDescriptor = declaration.descriptor - val closureBuilder = ClosureBuilder(classDescriptor) - closureBuilders[declaration.descriptor] = closureBuilder + val closureBuilder = ClosureBuilder(declaration) + closureBuilders[declaration] = closureBuilder - closureBuilder.declareVariable(classDescriptor.thisAsReceiverParameter) + closureBuilder.declareVariable(declaration.thisReceiver) if (declaration.isInner) { - closureBuilder.declareVariable((classDescriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter) + closureBuilder.declareVariable((declaration.parent as IrClass).thisReceiver) includeInParent(closureBuilder) } - classDescriptor.unsubstitutedPrimaryConstructor?.valueParameters?.forEach { - closureBuilder.declareVariable(it) + declaration.declarations.firstOrNull { it is IrConstructor && it.isPrimary }?.let { + val constructor = it as IrConstructor + constructor.valueParameters.forEach { v -> closureBuilder.declareVariable(v) } } closuresStack.push(closureBuilder) @@ -134,23 +132,26 @@ class ClosureAnnotator { } override fun visitFunction(declaration: IrFunction) { - val functionDescriptor = declaration.descriptor - val closureBuilder = ClosureBuilder(functionDescriptor) - closureBuilders[functionDescriptor] = closureBuilder + val closureBuilder = ClosureBuilder(declaration) + closureBuilders[declaration] = closureBuilder + + declaration.valueParameters.forEach { closureBuilder.declareVariable(it) } + closureBuilder.declareVariable(declaration.dispatchReceiverParameter) + closureBuilder.declareVariable(declaration.extensionReceiverParameter) + + if (declaration is IrConstructor) { + val constructedClass = (declaration.parent as IrClass) + closureBuilder.declareVariable(constructedClass.thisReceiver) - functionDescriptor.valueParameters.forEach { closureBuilder.declareVariable(it) } - closureBuilder.declareVariable(functionDescriptor.dispatchReceiverParameter) - closureBuilder.declareVariable(functionDescriptor.extensionReceiverParameter) - if (functionDescriptor is ConstructorDescriptor) { - closureBuilder.declareVariable(functionDescriptor.constructedClass.thisAsReceiverParameter) // Include closure of the class in the constructor closure. val classBuilder = closuresStack.peek() classBuilder?.let { - assert(classBuilder.owner == functionDescriptor.constructedClass) + assert(classBuilder.owner == constructedClass) closureBuilder.include(classBuilder) } } + closuresStack.push(closureBuilder) declaration.acceptChildrenVoid(this) closuresStack.pop() @@ -169,21 +170,40 @@ class ClosureAnnotator { } override fun visitVariable(declaration: IrVariable) { - closuresStack.peek()?.declareVariable(declaration.descriptor) + closuresStack.peek()?.declareVariable(declaration) super.visitVariable(declaration) } override fun visitCatch(aCatch: IrCatch) { - closuresStack.peek()?.declareVariable(aCatch.parameter) + closuresStack.peek()?.declareVariable(aCatch.catchParameter) super.visitCatch(aCatch) } - // Process delegating constructor calls, enum constructor calls, calls and callable references. - override fun visitMemberAccess(expression: IrMemberAccessExpression) { + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) { expression.acceptChildrenVoid(this) - val descriptor = expression.descriptor - if (DescriptorUtils.isLocal(descriptor)) { - val builder = closureBuilders[descriptor] + processMemberAccess(expression.symbol.owner) + } + + override fun visitCall(expression: IrCall) { + expression.acceptChildrenVoid(this) + processMemberAccess(expression.symbol.owner) + } + + override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) { + expression.acceptChildrenVoid(this) + processMemberAccess(expression.symbol.owner) + } + + override fun visitFunctionReference(expression: IrFunctionReference) { + expression.acceptChildrenVoid(this) + processMemberAccess(expression.symbol.owner) + } + +// override fun visitPropertyReference(expression: IrPropertyReference) = processMemberAccess(expression.) + + private fun processMemberAccess(declaration: IrDeclaration) { + if (DescriptorUtils.isLocal(declaration.descriptor)) { + val builder = closureBuilders[declaration] builder?.let { closuresStack.peek()?.include(builder) } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt index ddc1fe5824b..c80c82bf298 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt @@ -8,20 +8,18 @@ package org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass +import org.jetbrains.kotlin.backend.common.FunctionLoweringPass +import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.ir2string -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl @@ -30,13 +28,18 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue -import org.jetbrains.kotlin.resolve.calls.components.isVararg + +// TODO: fix expect/actual default parameters open class DefaultArgumentStubGenerator constructor(val context: CommonBackendContext, private val skipInlineMethods: Boolean = true) : DeclarationContainerLoweringPass { @@ -53,71 +56,70 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo private val symbols = context.ir.symbols private fun lower(irFunction: IrFunction): List { - val functionDescriptor = irFunction.descriptor - - if (!functionDescriptor.needsDefaultArgumentsLowering(skipInlineMethods)) + if (!irFunction.needsDefaultArgumentsLowering(skipInlineMethods)) return listOf(irFunction) - val bodies = functionDescriptor.valueParameters - .mapNotNull { irFunction.getDefault(it) } + val bodies = irFunction.valueParameters.mapNotNull { it.defaultValue } - log { "detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions" } - functionDescriptor.overriddenDescriptors.forEach { context.log { "DEFAULT-REPLACER: $it" } } + log { "detected ${irFunction.name.asString()} has got #${bodies.size} default expressions" } + if (bodies.isNotEmpty()) { + val newIrFunction = irFunction.generateDefaultsFunction(context) newIrFunction.parent = irFunction.parent - val descriptor = newIrFunction.descriptor - log { "$functionDescriptor -> $descriptor" } + + log { "$irFunction -> $newIrFunction" } val builder = context.createIrBuilder(newIrFunction.symbol) + newIrFunction.body = builder.irBlockBody(newIrFunction) { val params = mutableListOf() - val variables = mutableMapOf() + val variables = mutableMapOf() irFunction.dispatchReceiverParameter?.let { - variables[it.descriptor] = newIrFunction.dispatchReceiverParameter!! + variables[it] = newIrFunction.dispatchReceiverParameter!! } - if (descriptor.extensionReceiverParameter != null) { - variables[functionDescriptor.extensionReceiverParameter!!] = - newIrFunction.extensionReceiverParameter!! + irFunction.extensionReceiverParameter?.let { + variables[it] = newIrFunction.extensionReceiverParameter!! } - for (valueParameter in functionDescriptor.valueParameters) { + for (valueParameter in irFunction.valueParameters) { val parameter = newIrFunction.valueParameters[valueParameter.index] - val argument = if (valueParameter.hasDefaultValue()) { + val argument = if (valueParameter.defaultValue != null) { val kIntAnd = symbols.intAnd.owner val condition = irNotEquals(irCall(kIntAnd).apply { dispatchReceiver = irGet(maskParameter(newIrFunction, valueParameter.index / 32)) putValueArgument(0, irInt(1 shl (valueParameter.index % 32))) }, irInt(0)) - val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter) - /* Use previously calculated values in next expression. */ + val expressionBody = valueParameter.defaultValue!! + expressionBody.transformChildrenVoid(object : IrElementTransformerVoid() { override fun visitGetValue(expression: IrGetValue): IrExpression { - log { "GetValue: ${expression.descriptor}" } - val valueSymbol = variables[expression.descriptor] ?: return expression + log { "GetValue: ${expression.symbol.owner}" } + val valueSymbol = variables[expression.symbol.owner] ?: return expression return irGet(valueSymbol) } }) + irIfThenElse( type = parameter.type, condition = condition, thenPart = expressionBody.expression, elsePart = irGet(parameter) ) - - /* Mapping calculated values with its origin variables. */ } else { irGet(parameter) } + val temporaryVariable = irTemporary(argument, nameHint = parameter.name.asString()) params.add(temporaryVariable) - variables.put(valueParameter, temporaryVariable) + variables[valueParameter] = temporaryVariable } + if (irFunction is IrConstructor) { +IrDelegatingConstructorCallImpl( startOffset = irFunction.startOffset, @@ -126,31 +128,23 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor, typeArgumentsCount = irFunction.typeParameters.size ).apply { - params.forEachIndexed { i, variable -> - putValueArgument(i, irGet(variable)) - } - if (functionDescriptor.dispatchReceiverParameter != null) { - dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!) - } + dispatchReceiver = newIrFunction.dispatchReceiverParameter?.let { irGet(it) } + + params.forEachIndexed { i, variable -> putValueArgument(i, irGet(variable)) } } } else { +irReturn(irCall(irFunction).apply { - if (functionDescriptor.dispatchReceiverParameter != null) { - dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!) - } - if (functionDescriptor.extensionReceiverParameter != null) { - extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!]!!) - } - params.forEachIndexed { i, variable -> - putValueArgument(i, irGet(variable)) - } + dispatchReceiver = newIrFunction.dispatchReceiverParameter?.let { irGet(it) } + extensionReceiver = newIrFunction.extensionReceiverParameter?.let { irGet(it) } + + params.forEachIndexed { i, variable -> putValueArgument(i, irGet(variable)) } }) } } // Remove default argument initializers. - irFunction.valueParameters.forEach { - it.defaultValue = null - } +// irFunction.valueParameters.forEach { +// it.defaultValue = null +// } return listOf(irFunction, newIrFunction) } @@ -161,18 +155,14 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" } } -private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor): IrExpressionBody { - return irFunction.getDefault(valueParameter) ?: TODO("FIXME!!!") -} - -private fun maskParameterDescriptor(function: IrFunction, number: Int) = - maskParameter(function, number).descriptor as ValueParameterDescriptor +private fun maskParameterDeclaration(function: IrFunction, number: Int) = + maskParameter(function, number) private fun maskParameter(function: IrFunction, number: Int) = - function.valueParameters.single { it.descriptor.name == parameterMaskName(number) } + function.valueParameters.single { it.name == parameterMaskName(number) } -private fun markerParameterDescriptor(descriptor: FunctionDescriptor) = - descriptor.valueParameters.single { it.name == kConstructorMarkerName } +private fun markerParameterDeclaration(function: IrFunction) = + function.valueParameters.single { it.name == kConstructorMarkerName } open class DefaultParameterInjector constructor( val context: CommonBackendContext, @@ -183,12 +173,17 @@ open class DefaultParameterInjector constructor( irBody.transformChildrenVoid(object : IrElementTransformerVoid() { override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { super.visitDelegatingConstructorCall(expression) - val descriptor = expression.descriptor - if (!descriptor.needsDefaultArgumentsLowering(skipInline)) + + val declaration = expression.symbol.owner as IrFunction + + if (!declaration.needsDefaultArgumentsLowering(skipInline)) return expression + val argumentsCount = argumentCount(expression) - if (argumentsCount == descriptor.valueParameters.size) + + if (argumentsCount == declaration.valueParameters.size) return expression + val (symbolForCall, params) = parametersForCall(expression) symbolForCall as IrConstructorSymbol return IrDelegatingConstructorCallImpl( @@ -211,18 +206,24 @@ open class DefaultParameterInjector constructor( override fun visitCall(expression: IrCall): IrExpression { super.visitCall(expression) - val functionDescriptor = expression.descriptor + val functionDeclaration = expression.symbol.owner - if (!functionDescriptor.needsDefaultArgumentsLowering(skipInline)) + if (!functionDeclaration.needsDefaultArgumentsLowering(skipInline)) return expression val argumentsCount = argumentCount(expression) - if (argumentsCount == functionDescriptor.valueParameters.size) + if (argumentsCount == functionDeclaration.valueParameters.size) return expression + val (symbol, params) = parametersForCall(expression) val descriptor = symbol.descriptor - descriptor.typeParameters.forEach { log { "$descriptor [${it.index}]: $it" } } - descriptor.original.typeParameters.forEach { log { "${descriptor.original}[${it.index}] : $it" } } + val declaration = symbol.owner + + for (i in 0 until expression.typeArgumentsCount) { + log { "$descriptor [$i]: $expression.getTypeArgument(i)" } + } + declaration.typeParameters.forEach { log { "$declaration[${it.index}] : $it" } } + return IrCallImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, @@ -238,81 +239,86 @@ open class DefaultParameterInjector constructor( log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" } putValueArgument(it.first.index, it.second) } - expression.extensionReceiver?.apply { - extensionReceiver = expression.extensionReceiver - } - expression.dispatchReceiver?.apply { - dispatchReceiver = expression.dispatchReceiver - } + + dispatchReceiver = expression.dispatchReceiver + extensionReceiver = expression.extensionReceiver + log { "call::extension@: ${ir2string(expression.extensionReceiver)}" } log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" } } } private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? { - if (!this.descriptor.needsDefaultArgumentsLowering(skipInline)) return null + if (!needsDefaultArgumentsLowering(skipInline)) return null if (this !is IrSimpleFunction) return this - this.overriddenSymbols.forEach { - it.owner.findSuperMethodWithDefaultArguments()?.let { return it } + for (s in overriddenSymbols) { + s.owner.findSuperMethodWithDefaultArguments()?.let { return it } } return this } - private fun parametersForCall(expression: IrFunctionAccessExpression): Pair>> { - val descriptor = expression.descriptor - val keyFunction = expression.symbol.owner.findSuperMethodWithDefaultArguments()!! - val realFunction = keyFunction.generateDefaultsFunction(context) - realFunction.parent = keyFunction.parent - val realDescriptor = realFunction.descriptor + private fun parametersForCall(expression: IrFunctionAccessExpression): Pair>> { + val declaration = expression.symbol.owner - log { "$descriptor -> $realDescriptor" } - val maskValues = Array((descriptor.valueParameters.size + 31) / 32, { 0 }) - val params = mutableListOf>() - params.addAll(descriptor.valueParameters.mapIndexed { i, _ -> + val keyFunction = declaration.findSuperMethodWithDefaultArguments()!! + val realFunction = keyFunction.generateDefaultsFunction(context) + + realFunction.parent = keyFunction.parent + + log { "$declaration -> $realFunction" } + val maskValues = Array((declaration.valueParameters.size + 31) / 32) { 0 } + val params = mutableListOf>() + params += declaration.valueParameters.mapIndexed { i, _ -> val valueArgument = expression.getValueArgument(i) if (valueArgument == null) { val maskIndex = i / 32 maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (i % 32)) } - val valueParameterDescriptor = realDescriptor.valueParameters[i] - val defaultValueArgument = if (valueParameterDescriptor.isVararg) { + val valueParameterDeclaration = realFunction.valueParameters[i] + val defaultValueArgument = if (valueParameterDeclaration.varargElementType != null) { null } else { nullConst(expression, realFunction.valueParameters[i].type) } - valueParameterDescriptor to (valueArgument ?: defaultValueArgument) - }) + valueParameterDeclaration to (valueArgument ?: defaultValueArgument) + } + maskValues.forEachIndexed { i, maskValue -> - params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int( + params += maskParameterDeclaration(realFunction, i) to IrConstImpl.int( startOffset = irBody.startOffset, endOffset = irBody.endOffset, type = context.irBuiltIns.intType, value = maskValue ) } - if (expression.descriptor is ClassConstructorDescriptor) { + if (expression.symbol is IrConstructorSymbol) { val defaultArgumentMarker = context.ir.symbols.defaultConstructorMarker - params += markerParameterDescriptor(realDescriptor) to IrGetObjectValueImpl( + params += markerParameterDeclaration(realFunction) to IrGetObjectValueImpl( startOffset = irBody.startOffset, endOffset = irBody.endOffset, type = defaultArgumentMarker.owner.defaultType, symbol = defaultArgumentMarker ) } else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { - params += realDescriptor.valueParameters.last() to + params += realFunction.valueParameters.last() to IrConstImpl.constNull(irBody.startOffset, irBody.endOffset, context.irBuiltIns.nothingNType) } params.forEach { - log { "descriptor::${realDescriptor.name.asString()}#${it.first.index}: ${it.first.name.asString()}" } + log { "descriptor::${realFunction.name.asString()}#${it.first.index}: ${it.first.name.asString()}" } } return Pair(realFunction.symbol, params) } - private fun argumentCount(expression: IrMemberAccessExpression) = - expression.descriptor.valueParameters.count { expression.getValueArgument(it) != null } + private fun argumentCount(expression: IrMemberAccessExpression): Int { + var result = 0 + for (i in 0 until expression.valueArgumentsCount) { + expression.getValueArgument(i)?.run { ++result } + } + return result + } }) } @@ -331,169 +337,126 @@ open class DefaultParameterInjector constructor( private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" } } -private fun CallableMemberDescriptor.needsDefaultArgumentsLowering(skipInlineMethods: Boolean) = - valueParameters.any { it.hasDefaultValue() } && !(this is FunctionDescriptor && isInline && skipInlineMethods) - -private fun IrFunction.generateDefaultsFunction(context: CommonBackendContext): IrFunction = with(this.descriptor) { - return context.ir.defaultParameterDeclarationsCache.getOrPut(this) { - val descriptor = when (this) { - is ClassConstructorDescriptor -> - ClassConstructorDescriptorImpl.create( - /* containingDeclaration = */ containingDeclaration, - /* annotations = */ annotations, - /* isPrimary = */ false, - /* source = */ source - ) - else -> { - val name = Name.identifier("$name\$default") - - SimpleFunctionDescriptorImpl.create( - /* containingDeclaration = */ containingDeclaration, - /* annotations = */ annotations, - /* name = */ name, - /* kind = */ CallableMemberDescriptor.Kind.SYNTHESIZED, - /* source = */ source - ) - } - } - - val function = this@generateDefaultsFunction - - val syntheticParameters = MutableList((valueParameters.size + 31) / 32) { i -> - valueParameter(descriptor, valueParameters.size + i, parameterMaskName(i), context.irBuiltIns.intType) - } - if (this is ClassConstructorDescriptor) { - syntheticParameters += valueParameter( - descriptor, syntheticParameters.last().index + 1, - kConstructorMarkerName, - context.ir.symbols.defaultConstructorMarker.owner.defaultType - ) - } else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { - syntheticParameters += valueParameter( - descriptor, syntheticParameters.last().index + 1, - "handler".synthesizedName, - context.irBuiltIns.anyType - ) - } - - val newValueParameters = function.valueParameters.map { - val parameterDescriptor = ValueParameterDescriptorImpl( - containingDeclaration = descriptor, - original = null, /* ValueParameterDescriptorImpl::copy do not save original. */ - index = it.index, - annotations = it.descriptor.annotations, - name = it.name, - outType = it.descriptor.type, - declaresDefaultValue = false, - isCrossinline = it.isCrossinline, - isNoinline = it.isNoinline, - varargElementType = (it.descriptor as ValueParameterDescriptor).varargElementType, - source = it.descriptor.source - ) - - it.copy(parameterDescriptor) - - } + syntheticParameters - - descriptor.initialize( - /* receiverParameterType = */ extensionReceiverParameter, - /* dispatchReceiverParameter = */ dispatchReceiverParameter, - /* typeParameters = */ typeParameters.map { - TypeParameterDescriptorImpl.createForFurtherModification( - /* containingDeclaration = */ descriptor, - /* annotations = */ it.annotations, - /* reified = */ it.isReified, - /* variance = */ it.variance, - /* name = */ it.name, - /* index = */ it.index, - /* source = */ it.source, - /* reportCycleError = */ null, - /* supertypeLoopsChecker = */ SupertypeLoopChecker.EMPTY - ).apply { - it.upperBounds.forEach { addUpperBound(it) } - setInitialized() - } - }, - /* unsubstitutedValueParameters = */ newValueParameters.map { it.descriptor as ValueParameterDescriptor }, - /* unsubstitutedReturnType = */ returnType, - /* modality = */ Modality.FINAL, - /* visibility = */ this.visibility - ) - descriptor.isSuspend = this.isSuspend - context.log { "adds to cache[$this] = $descriptor" } - - val startOffset = this.startOffsetOrUndefined - val endOffset = this.endOffsetOrUndefined - - val result: IrFunction = when (descriptor) { - is ClassConstructorDescriptor -> IrConstructorImpl( - startOffset, endOffset, - DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, - descriptor - ) - - else -> IrFunctionImpl( - startOffset, endOffset, - DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, - descriptor - ) - } - - result.returnType = function.returnType - - function.typeParameters.mapTo(result.typeParameters) { - assert(function.descriptor.typeParameters[it.index] == it.descriptor) - IrTypeParameterImpl( - startOffset, endOffset, origin, descriptor.typeParameters[it.index] - ).apply { this.superTypes += it.superTypes } - } - result.parent = function.parent - result.createDispatchReceiverParameter() - - function.extensionReceiverParameter?.let { - result.extensionReceiverParameter = IrValueParameterImpl( - it.startOffset, - it.endOffset, - it.origin, - descriptor.extensionReceiverParameter!!, - it.type, - it.varargElementType - ).apply { parent = result } - } - - result.valueParameters += newValueParameters.also { it.forEach { it.parent = result } } - - function.annotations.mapTo(result.annotations) { it.deepCopyWithSymbols() } - - result +class DefaultParameterCleaner constructor(val context: CommonBackendContext) : FunctionLoweringPass { + override fun lower(irFunction: IrFunction) { + irFunction.valueParameters.forEach { it.defaultValue = null } } } +private fun IrFunction.needsDefaultArgumentsLowering(skipInlineMethods: Boolean): Boolean { + if (isInline && skipInlineMethods) return false + if (valueParameters.any { it.defaultValue != null }) return true + + if (this !is IrSimpleFunction) return false + + return overriddenSymbols.any { it.owner.needsDefaultArgumentsLowering(skipInlineMethods) } +} + +private fun IrFunction.generateDefaultsFunctionImpl(context: CommonBackendContext): IrFunction { + val newFunction = buildFunctionDeclaration(this) + + val syntheticParameters = MutableList((valueParameters.size + 31) / 32) { i -> + valueParameter(valueParameters.size + i, parameterMaskName(i), context.irBuiltIns.intType) + } + + if (this is IrConstructor) { + syntheticParameters += newFunction.valueParameter( + syntheticParameters.last().index + 1, + kConstructorMarkerName, + context.ir.symbols.defaultConstructorMarker.owner.defaultType + ) + } else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { + syntheticParameters += newFunction.valueParameter( + syntheticParameters.last().index + 1, + "handler".synthesizedName, + context.irBuiltIns.anyType + ) + } + + val newValueParameters = valueParameters.map { it.copyTo(newFunction) } + syntheticParameters + val newTypeParameters = typeParameters.map { it.copyTo(newFunction) } + + newFunction.returnType = returnType + newFunction.dispatchReceiverParameter = dispatchReceiverParameter?.copyTo(newFunction) + newFunction.extensionReceiverParameter = extensionReceiverParameter?.copyTo(newFunction) + newFunction.valueParameters += newValueParameters + newFunction.typeParameters += newTypeParameters + + annotations.mapTo(newFunction.annotations) { it.deepCopyWithSymbols() } + + return newFunction +} + +private fun buildFunctionDeclaration(irFunction: IrFunction): IrFunction { + when (irFunction) { + is IrConstructor -> { + val descriptor = WrappedClassConstructorDescriptor(irFunction.descriptor.annotations, irFunction.descriptor.source) + return IrConstructorImpl( + irFunction.startOffset, + irFunction.endOffset, + DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, + IrConstructorSymbolImpl(descriptor), + irFunction.name, + irFunction.visibility, + irFunction.isInline, + irFunction.isExternal, + false + ).also { + descriptor.bind(it) + it.parent = irFunction.parent + } + } + is IrSimpleFunction -> { + val descriptor = WrappedSimpleFunctionDescriptor(irFunction.descriptor.annotations, irFunction.descriptor.source) + val name = Name.identifier("${irFunction.name}\$default") + + return IrFunctionImpl( + irFunction.startOffset, + irFunction.endOffset, + DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, + IrSimpleFunctionSymbolImpl(descriptor), + name, + irFunction.visibility, + irFunction.modality, + irFunction.isInline, + irFunction.isExternal, + irFunction.isTailrec, + irFunction.isSuspend + ).also { + descriptor.bind(it) + it.parent = irFunction.parent + } + } + else -> throw IllegalStateException("Unknown function type") + } +} + +private fun IrFunction.generateDefaultsFunction(context: CommonBackendContext): IrFunction = + context.ir.defaultParameterDeclarationsCache.getOrPut(this) { + generateDefaultsFunctionImpl(context) + } + object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER : IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT") -private fun IrFunction.valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: IrType): IrValueParameter { - val parameterDescriptor = ValueParameterDescriptorImpl( - containingDeclaration = descriptor, - original = null, - index = index, - annotations = Annotations.EMPTY, - name = name, - outType = type.toKotlinType(), - declaresDefaultValue = false, - isCrossinline = false, - isNoinline = false, - varargElementType = null, - source = SourceElement.NO_SOURCE - ) +private fun IrFunction.valueParameter(index: Int, name: Name, type: IrType): IrValueParameter { + val parameterDescriptor = WrappedValueParameterDescriptor() + return IrValueParameterImpl( startOffset, endOffset, IrDeclarationOrigin.DEFINED, - parameterDescriptor, + IrValueParameterSymbolImpl(parameterDescriptor), + name, + index, type, - null - ) + null, + false, + false + ).also { + parameterDescriptor.bind(it) + it.parent = this + } } internal val kConstructorMarkerName = "marker".synthesizedName diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt index 4ce29daf084..f9cf2f99111 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt @@ -15,11 +15,10 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.IrField +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.expressions.IrBlock import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl @@ -94,8 +93,8 @@ class InitializersLowering( fun transformInstanceInitializerCallsInConstructors(irClass: IrClass) { irClass.transformChildrenVoid(object : IrElementTransformerVoid() { override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression { - return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, - instanceInitializerStatements.map { it.copy(irClass) }) + val copiedBlock = IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.unitType, null, instanceInitializerStatements).copy(irClass) as IrBlock + return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, copiedBlock.statements) } }) } @@ -125,7 +124,7 @@ class InitializersLowering( companion object { val clinitName = Name.special("") - fun IrStatement.copy(containingDeclaration: IrClass) = deepCopyWithSymbols(containingDeclaration) - fun IrExpression.copy(containingDeclaration: IrClass) = deepCopyWithSymbols(containingDeclaration) + fun IrStatement.copy(containingDeclaration: IrDeclarationParent) = deepCopyWithSymbols(containingDeclaration) + fun IrExpression.copy(containingDeclaration: IrDeclarationParent) = deepCopyWithSymbols(containingDeclaration) } } \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt index cada6420299..1640f7773eb 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt @@ -8,29 +8,25 @@ package org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor -import org.jetbrains.kotlin.descriptors.ValueDescriptor -import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol -import org.jetbrains.kotlin.ir.util.createParameterDeclarations +import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.transformFlat -import org.jetbrains.kotlin.ir.visitors.* -import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import java.util.* class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { - object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS") - override fun lower(irClass: IrClass) { InnerClassTransformer(irClass).lowerInnerClass() } @@ -38,12 +34,10 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { private inner class InnerClassTransformer(val irClass: IrClass) { lateinit var outerThisField: IrField - val oldConstructorParameterToNew = HashMap() - val class2Symbol = HashMap() + val oldConstructorParameterToNew = HashMap() fun lowerInnerClass() { if (!irClass.isInner) return - rememberClassSymbols() createOuterThisField() lowerConstructors() @@ -51,36 +45,10 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { lowerOuterThisReferences() } - //TODO: rewrite: this methods is required to 'getClassForImplicitThis' method - private fun rememberClassSymbols() { - var current = irClass.parent as? IrClass - while (current != null) { - class2Symbol[current.descriptor] = current - current = current.parent as? IrClass - } - irClass.acceptVoid(object : IrElementVisitorVoid { - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitClass(declaration: IrClass) { - return super.visitClass(declaration).also { class2Symbol[declaration.descriptor] = declaration } - } - }) - } - private fun createOuterThisField() { - val fieldSymbol = context.descriptorsFactory.getOuterThisFieldSymbol(irClass) - irClass.declarations.add( - IrFieldImpl( - irClass.startOffset, irClass.endOffset, - FIELD_FOR_OUTER_THIS, - fieldSymbol, - irClass.defaultType - ).also { - outerThisField = it - } - ) + val field = context.declarationFactory.getOuterThisField(irClass) + outerThisField = field + irClass.declarations += field } private fun lowerConstructors() { @@ -96,42 +64,31 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { val startOffset = irConstructor.startOffset val endOffset = irConstructor.endOffset - val newSymbol = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(irConstructor) - val loweredConstructor = IrConstructorImpl( - startOffset, endOffset, - irConstructor.origin, // TODO special origin for lowered inner class constructors? - newSymbol, - null - ).apply { - parent = irConstructor.parent - returnType = irConstructor.returnType - } - - loweredConstructor.createParameterDeclarations() + val loweredConstructor = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(irConstructor) val outerThisValueParameter = loweredConstructor.valueParameters[0].symbol - irConstructor.descriptor.valueParameters.forEach { oldValueParameter -> - oldConstructorParameterToNew[oldValueParameter] = loweredConstructor.valueParameters[oldValueParameter.index + 1] + irConstructor.valueParameters.forEach { old -> + oldConstructorParameterToNew[old] = loweredConstructor.valueParameters[old.index + 1] } val blockBody = irConstructor.body as? IrBlockBody ?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}") val instanceInitializerIndex = blockBody.statements.indexOfFirst { it is IrInstanceInitializerCall } - if (instanceInitializerIndex >= 0) { - // Initializing constructor: initialize 'this.this$0' with '$outer' - blockBody.statements.add( - instanceInitializerIndex, - IrSetFieldImpl( - startOffset, endOffset, outerThisField.symbol, - IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol), - IrGetValueImpl(startOffset, endOffset, outerThisValueParameter), - context.irBuiltIns.unitType - ) + + // Initializing constructor: initialize 'this.this$0' with '$outer' + blockBody.statements.add( + 0, + IrSetFieldImpl( + startOffset, endOffset, outerThisField.symbol, + IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol), + IrGetValueImpl(startOffset, endOffset, outerThisValueParameter), + context.irBuiltIns.unitType ) - } else { + ) + if (instanceInitializerIndex < 0) { // Delegating constructor: invoke old constructor with dispatch receiver '$outer' val delegatingConstructorCall = (blockBody.statements.find { it is IrDelegatingConstructorCall } - ?: throw AssertionError("Delegating constructor call expected: ${irConstructor.dump()}") + ?: throw AssertionError("Delegating constructor call expected: ${irConstructor.dump()}") ) as IrDelegatingConstructorCall delegatingConstructorCall.dispatchReceiver = IrGetValueImpl( delegatingConstructorCall.startOffset, delegatingConstructorCall.endOffset, outerThisValueParameter @@ -175,8 +132,15 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { return expression } - val outerThisField = context.descriptorsFactory.getOuterThisFieldSymbol(innerClass) - irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, innerClass.defaultType, irThis, origin) + val outerThisField = context.declarationFactory.getOuterThisField(innerClass) + irThis = IrGetFieldImpl( + startOffset, + endOffset, + outerThisField.symbol, + innerClass.defaultType, + irThis, + origin + ) val outer = innerClass.parent innerClass = outer as? IrClass ?: @@ -189,11 +153,13 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { } private fun IrValueSymbol.getClassForImplicitThis(): IrClass? { - val descriptor1 = this.descriptor - if (descriptor1 is ReceiverParameterDescriptor) { - val receiverValue = descriptor1.value - if (receiverValue is ImplicitClassReceiver) { - return class2Symbol[receiverValue.classDescriptor] + //TODO: is it correct way to get class + if (this is IrValueParameterSymbol) { + val declaration = owner + if (declaration.index == -1) { // means value is either IMPLICIT or EXTENSION receiver + if (declaration.name.isSpecial) { // whether name is + return owner.type.classifierOrNull?.owner as IrClass + } } } return null @@ -212,15 +178,15 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe val parent = callee.owner.parent as? IrClass ?: return expression if (!parent.isInner) return expression - val newCallee = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(callee.owner) + val newCallee = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(callee.owner) val newCall = IrCallImpl( - expression.startOffset, expression.endOffset, expression.type, newCallee, newCallee.descriptor, + expression.startOffset, expression.endOffset, expression.type, newCallee.symbol, newCallee.descriptor, 0, // TODO type arguments map expression.origin ) newCall.putValueArgument(0, dispatchReceiver) - for (i in 1..newCallee.descriptor.valueParameters.lastIndex) { + for (i in 1..newCallee.valueParameters.lastIndex) { newCall.putValueArgument(i, expression.getValueArgument(i - 1)) } @@ -234,14 +200,14 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe val classConstructor = expression.symbol.owner if (!(classConstructor.parent as IrClass).isInner) return expression - val newCallee = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(classConstructor) + val newCallee = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(classConstructor) val newCall = IrDelegatingConstructorCallImpl( - expression.startOffset, expression.endOffset, context.irBuiltIns.unitType, newCallee, newCallee.descriptor, + expression.startOffset, expression.endOffset, context.irBuiltIns.unitType, newCallee.symbol, newCallee.descriptor, classConstructor.typeParameters.size ).apply { copyTypeArgumentsFrom(expression) } newCall.putValueArgument(0, dispatchReceiver) - for (i in 1..newCallee.descriptor.valueParameters.lastIndex) { + for (i in 1..newCallee.valueParameters.lastIndex) { newCall.putValueArgument(i, expression.getValueArgument(i - 1)) } @@ -255,9 +221,19 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe val parent = callee.owner.parent as? IrClass ?: return expression if (!parent.isInner) return expression - val newCallee = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(callee.owner) + val newCallee = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(callee.owner) - val newReference = expression.run { IrFunctionReferenceImpl(startOffset, endOffset, type, newCallee, newCallee.descriptor, typeArgumentsCount, origin) } + val newReference = expression.run { + IrFunctionReferenceImpl( + startOffset, + endOffset, + type, + newCallee.symbol, + newCallee.descriptor, + typeArgumentsCount, + origin + ) + } newReference.let { it.dispatchReceiver = expression.dispatchReceiver diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt index 219e4717d42..da63924928c 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.FileLoweringPass -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* @@ -31,7 +30,6 @@ import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.isPrimitiveType import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.types.KotlinType class LateinitLowering( val context: CommonBackendContext, diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index fab2fc412b4..1bacc8cff0a 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -7,20 +7,26 @@ package org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass -import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.common.descriptors.* +import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.* +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrValueSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid @@ -28,7 +34,6 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.parents -import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf import java.util.* interface LocalNameProvider { @@ -40,27 +45,39 @@ interface LocalNameProvider { } } +val IrDeclaration.parentsWithSelf: Sequence + get() = generateSequence(this as? IrDeclarationParent) { (it as? IrDeclaration)?.parent } + +val IrDeclaration.parents: Sequence + get() = parentsWithSelf.drop(1) + class LocalDeclarationsLowering( val context: BackendContext, val localNameProvider: LocalNameProvider = LocalNameProvider.DEFAULT, - val loweredConstructorVisibility: Visibility = Visibilities.PRIVATE + val loweredConstructorVisibility: Visibility = Visibilities.PRIVATE, + private val isJVM: Boolean = false ) : DeclarationContainerLoweringPass { private object DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE : - IrDeclarationOriginImpl("FIELD_FOR_CAPTURED_VALUE") {} + IrDeclarationOriginImpl("FIELD_FOR_CAPTURED_VALUE") private object STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE : - IrStatementOriginImpl("INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE") {} + IrStatementOriginImpl("INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE") override fun lower(irDeclarationContainer: IrDeclarationContainer) { - if (irDeclarationContainer is IrDeclaration && - irDeclarationContainer.descriptor.parents.any { it is CallableDescriptor } - ) { + if (irDeclarationContainer is IrDeclaration) { - // Lowering of non-local declarations handles all local declarations inside. - // This declaration is local and shouldn't be considered. - return + // TODO: in case of `crossinline` lambda the @containingDeclaration and @parent points to completely different locations +// val parentsDecl = irDeclarationContainer.parents + val parentsDesc = irDeclarationContainer.descriptor.parents + + if (parentsDesc.any { it is CallableDescriptor }) { + + // Lowering of non-local declarations handles all local declarations inside. + // This declaration is local and shouldn't be considered. + return + } } // Continuous numbering across all declarations in the container. @@ -73,7 +90,7 @@ class LocalDeclarationsLowering( is IrProperty -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() is IrField -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() is IrAnonymousInitializer -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() - // TODO: visit children as well + // TODO: visit children as well else -> null } } @@ -83,24 +100,20 @@ class LocalDeclarationsLowering( private abstract class LocalContext { /** - * @return the expression to get the value for given descriptor, or `null` if [IrGetValue] should be used. + * @return the expression to get the value for given declaration, or `null` if [IrGetValue] should be used. */ - abstract fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? + abstract fun irGet(startOffset: Int, endOffset: Int, valueDeclaration: IrValueDeclaration): IrExpression? } private abstract class LocalContextWithClosureAsParameters : LocalContext() { abstract val declaration: IrFunction - open val descriptor: FunctionDescriptor - get() = declaration.descriptor - - abstract val transformedDescriptor: FunctionDescriptor abstract val transformedDeclaration: IrFunction - val capturedValueToParameter: MutableMap = HashMap() + val capturedValueToParameter: MutableMap = HashMap() - override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { - val parameter = capturedValueToParameter[descriptor] ?: return null + override fun irGet(startOffset: Int, endOffset: Int, valueDeclaration: IrValueDeclaration): IrExpression? { + val parameter = capturedValueToParameter[valueDeclaration] ?: return null return IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol) } @@ -109,36 +122,22 @@ class LocalDeclarationsLowering( private class LocalFunctionContext(override val declaration: IrFunction) : LocalContextWithClosureAsParameters() { lateinit var closure: Closure - override lateinit var transformedDescriptor: FunctionDescriptor override lateinit var transformedDeclaration: IrSimpleFunction var index: Int = -1 - - override fun toString(): String = - "LocalFunctionContext for $descriptor" } private class LocalClassConstructorContext(override val declaration: IrConstructor) : LocalContextWithClosureAsParameters() { - override val descriptor: ClassConstructorDescriptor - get() = declaration.descriptor - - override lateinit var transformedDescriptor: ClassConstructorDescriptor override lateinit var transformedDeclaration: IrConstructor - - override fun toString(): String = - "LocalClassConstructorContext for $descriptor" } private class LocalClassContext(val declaration: IrClass) : LocalContext() { - val descriptor: ClassDescriptor - get() = declaration.descriptor - lateinit var closure: Closure - val capturedValueToField: MutableMap = HashMap() + val capturedValueToField: MutableMap = HashMap() - override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { - val field = capturedValueToField[descriptor] ?: return null + override fun irGet(startOffset: Int, endOffset: Int, valueDeclaration: IrValueDeclaration): IrExpression? { + val field = capturedValueToField[valueDeclaration] ?: return null val receiver = declaration.thisReceiver!! return IrGetFieldImpl( @@ -146,14 +145,11 @@ class LocalDeclarationsLowering( receiver = IrGetValueImpl(startOffset, endOffset, receiver.type, receiver.symbol) ) } - - override fun toString(): String = - "LocalClassContext for $descriptor" } private class LocalClassMemberContext(val member: IrFunction, val classContext: LocalClassContext) : LocalContext() { - override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { - val field = classContext.capturedValueToField[descriptor] ?: return null + override fun irGet(startOffset: Int, endOffset: Int, valueDeclaration: IrValueDeclaration): IrExpression? { + val field = classContext.capturedValueToField[valueDeclaration] ?: return null val receiver = member.dispatchReceiverParameter!! return IrGetFieldImpl( @@ -165,18 +161,18 @@ class LocalDeclarationsLowering( } private inner class LocalDeclarationsTransformer(val memberDeclaration: IrDeclaration) { - val localFunctions: MutableMap = LinkedHashMap() - val localClasses: MutableMap = LinkedHashMap() - val localClassConstructors: MutableMap = LinkedHashMap() + val localFunctions: MutableMap = LinkedHashMap() + val localClasses: MutableMap = LinkedHashMap() + val localClassConstructors: MutableMap = LinkedHashMap() - val transformedDeclarations = mutableMapOf() + val transformedDeclarations = mutableMapOf() - val FunctionDescriptor.transformed: IrFunction? + val IrFunction.transformed: IrFunction? get() = transformedDeclarations[this] as IrFunction? - val oldParameterToNew: MutableMap = HashMap() - val newParameterToOld: MutableMap = HashMap() - val newParameterToCaptured: MutableMap = HashMap() + val newParameterToOld: MutableMap = mutableMapOf() + val oldParameterToNew: MutableMap = mutableMapOf() + val newParameterToCaptured: MutableMap = mutableMapOf() fun lowerLocalDeclarations(): List? { collectLocalDeclarations() @@ -184,12 +180,11 @@ class LocalDeclarationsLowering( collectClosures() - transformDescriptors() + transformDeclarations() rewriteDeclarations() - val result = collectRewrittenDeclarations() - return result + return collectRewrittenDeclarations() } private fun collectRewrittenDeclarations(): ArrayList = @@ -199,8 +194,8 @@ class LocalDeclarationsLowering( it.transformedDeclaration.apply { this.body = original.body - original.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> - val body = original.getDefault(argument)!! + original.valueParameters.filter { v -> v.defaultValue != null }.forEach { argument -> + val body = argument.defaultValue oldParameterToNew[argument]!!.defaultValue = body } } @@ -216,27 +211,25 @@ class LocalDeclarationsLowering( private inner class FunctionBodiesRewriter(val localContext: LocalContext?) : IrElementTransformerVoid() { - override fun visitClass(declaration: IrClass): IrStatement { - if (declaration.descriptor in localClasses) { - // Replace local class definition with an empty composite. - return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.irBuiltIns.unitType) - } else { - return super.visitClass(declaration) - } + override fun visitClass(declaration: IrClass) = if (declaration in localClasses) { + // Replace local class definition with an empty composite. + IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.irBuiltIns.unitType) + } else { + super.visitClass(declaration) } override fun visitFunction(declaration: IrFunction): IrStatement { - if (declaration.descriptor in localFunctions) { + return if (declaration in localFunctions) { // Replace local function definition with an empty composite. - return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.irBuiltIns.unitType) + IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.irBuiltIns.unitType) } else { if (localContext is LocalClassContext && declaration.parent == localContext.declaration) { - return declaration.apply { + declaration.apply { val classMemberLocalContext = LocalClassMemberContext(declaration, localContext) transformChildrenVoid(FunctionBodiesRewriter(classMemberLocalContext)) } } else { - return super.visitFunction(declaration) + super.visitFunction(declaration) } } } @@ -244,29 +237,24 @@ class LocalDeclarationsLowering( override fun visitConstructor(declaration: IrConstructor): IrStatement { // Body is transformed separately. See loop over constructors in rewriteDeclarations(). - val constructorContext = localClassConstructors[declaration.descriptor] - if (constructorContext != null) { - return constructorContext.transformedDeclaration.apply { - this.body = declaration.body!! + val constructorContext = localClassConstructors[declaration] + return constructorContext?.transformedDeclaration?.apply { + this.body = declaration.body!! - declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> - val body = declaration.getDefault(argument)!! - oldParameterToNew[argument]!!.defaultValue = body - } + declaration.valueParameters.filter { it.defaultValue != null }.forEach { argument -> + oldParameterToNew[argument]!!.defaultValue = argument.defaultValue } - } else { - return super.visitConstructor(declaration) - } + } ?: super.visitConstructor(declaration) } override fun visitGetValue(expression: IrGetValue): IrExpression { - val descriptor = expression.descriptor + val declaration = expression.symbol.owner - localContext?.irGet(expression.startOffset, expression.endOffset, descriptor)?.let { + localContext?.irGet(expression.startOffset, expression.endOffset, declaration)?.let { return it } - oldParameterToNew[descriptor]?.let { + oldParameterToNew[declaration]?.let { return IrGetValueImpl(expression.startOffset, expression.endOffset, it.type, it.symbol) } @@ -276,18 +264,16 @@ class LocalDeclarationsLowering( override fun visitCall(expression: IrCall): IrExpression { expression.transformChildrenVoid(this) - val oldCallee = expression.descriptor.original + val oldCallee = expression.symbol.owner val newCallee = oldCallee.transformed ?: return expression - val newCall = createNewCall(expression, newCallee).fillArguments(expression) - - return newCall + return createNewCall(expression, newCallee).fillArguments2(expression, newCallee) } override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { expression.transformChildrenVoid(this) - val oldCallee = expression.descriptor.original + val oldCallee = expression.symbol.owner val newCallee = transformedDeclarations[oldCallee] as IrConstructor? ?: return expression return IrDelegatingConstructorCallImpl( @@ -297,33 +283,39 @@ class LocalDeclarationsLowering( newCallee.descriptor, expression.typeArgumentsCount ).also { - it.fillArguments(expression) + it.fillArguments2(expression, newCallee) it.copyTypeArgumentsFrom(expression) } } - private fun T.fillArguments(oldExpression: IrMemberAccessExpression): T { + inline fun T.mapValueParameters( + newTarget: IrFunction, + transform: (IrValueParameter) -> IrExpression? + ): T = + apply { + for (p in newTarget.valueParameters) { + putValueArgument(p.index, transform(p)) + } + } - mapValueParameters { newValueParameterDescriptor -> - val oldParameter = newParameterToOld[newValueParameterDescriptor] + private fun T.fillArguments2(oldExpression: IrMemberAccessExpression, newTarget: IrFunction): T { + + mapValueParameters(newTarget) { newValueParameterDeclaration -> + val oldParameter = newParameterToOld[newValueParameterDeclaration] if (oldParameter != null) { - oldExpression.getValueArgument(oldParameter as ValueParameterDescriptor) + oldExpression.getValueArgument(oldParameter.index) } else { // The callee expects captured value as argument. val capturedValueSymbol = - newParameterToCaptured[newValueParameterDescriptor] - ?: throw AssertionError("Non-mapped parameter $newValueParameterDescriptor") + newParameterToCaptured[newValueParameterDeclaration] + ?: throw AssertionError("Non-mapped parameter $newValueParameterDeclaration") val capturedValue = capturedValueSymbol.owner - val capturedValueDescriptor = capturedValueSymbol.descriptor - localContext?.irGet( - oldExpression.startOffset, oldExpression.endOffset, - capturedValueDescriptor - ) ?: run { + localContext?.irGet(oldExpression.startOffset, oldExpression.endOffset, capturedValue) ?: run { // Captured value is directly available for the caller. - val value = oldParameterToNew[capturedValueDescriptor] ?: capturedValue + val value = oldParameterToNew[capturedValue] ?: capturedValue IrGetValueImpl(oldExpression.startOffset, oldExpression.endOffset, value.symbol) } } @@ -339,10 +331,10 @@ class LocalDeclarationsLowering( override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { expression.transformChildrenVoid(this) - val oldCallee = expression.descriptor.original + val oldCallee = expression.symbol.owner val newCallee = oldCallee.transformed ?: return expression - val newCallableReference = IrFunctionReferenceImpl( + return IrFunctionReferenceImpl( expression.startOffset, expression.endOffset, expression.type, // TODO functional type for transformed descriptor newCallee.symbol, @@ -350,17 +342,15 @@ class LocalDeclarationsLowering( expression.typeArgumentsCount, expression.origin ).also { - it.fillArguments(expression) + it.fillArguments2(expression, newCallee) it.copyTypeArgumentsFrom(expression) } - - return newCallableReference } override fun visitReturn(expression: IrReturn): IrExpression { expression.transformChildrenVoid(this) - val oldReturnTarget = expression.returnTarget + val oldReturnTarget = expression.returnTargetSymbol.owner as IrFunction val newReturnTarget = oldReturnTarget.transformed ?: return expression return IrReturnImpl( @@ -371,14 +361,14 @@ class LocalDeclarationsLowering( } override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression { - if (expression.descriptor in transformedDeclarations) { + if (expression.symbol.owner in transformedDeclarations) { TODO() } return super.visitDeclarationReference(expression) } override fun visitDeclaration(declaration: IrDeclaration): IrStatement { - if (declaration.descriptor in transformedDeclarations) { + if (declaration in transformedDeclarations) { TODO() } return super.visitDeclaration(declaration) @@ -390,13 +380,17 @@ class LocalDeclarationsLowering( } private fun rewriteClassMembers(irClass: IrClass, localClassContext: LocalClassContext) { + val constructors = irClass.declarations.filterIsInstance() + irClass.transformChildrenVoid(FunctionBodiesRewriter(localClassContext)) - val classDescriptor = irClass.descriptor - val constructorsCallingSuper = classDescriptor.constructors + val constructorsCallingSuper = constructors + .asSequence() .map { localClassConstructors[it]!! } - .filter { it.declaration.callsSuper() } - assert(constructorsCallingSuper.any(), { "Expected at least one constructor calling super; class: $classDescriptor" }) + .filter { it.declaration.callsSuper(context.irBuiltIns) } + .toList() + + assert(constructorsCallingSuper.any()) { "Expected at least one constructor calling super; class: $irClass" } localClassContext.capturedValueToField.forEach { capturedValue, field -> val startOffset = irClass.startOffset @@ -405,7 +399,7 @@ class LocalDeclarationsLowering( for (constructorContext in constructorsCallingSuper) { val blockBody = constructorContext.declaration.body as? IrBlockBody - ?: throw AssertionError("Unexpected constructor body: ${constructorContext.declaration.body}") + ?: throw AssertionError("Unexpected constructor body: ${constructorContext.declaration.body}") val capturedValueExpression = constructorContext.irGet(startOffset, endOffset, capturedValue)!! blockBody.statements.add( 0, @@ -452,9 +446,9 @@ class LocalDeclarationsLowering( it.copyTypeArgumentsFrom(oldCall) } - private fun transformDescriptors() { + private fun transformDeclarations() { localFunctions.values.forEach { - createLiftedDescriptor(it) + createLiftedDeclaration(it) } localClasses.values.forEach { @@ -462,149 +456,118 @@ class LocalDeclarationsLowering( } localClassConstructors.values.forEach { - createTransformedConstructorDescriptor(it) + createTransformedConstructorDeclaration(it) } } - private fun suggestLocalName(descriptor: DeclarationDescriptor): String { - localFunctions[descriptor]?.let { + private fun suggestLocalName(declaration: IrDeclaration): String { + localFunctions[declaration]?.let { if (it.index >= 0) return "lambda-${it.index}" } - return localNameProvider.localName(descriptor) + return localNameProvider.localName(declaration.descriptor) } private fun generateNameForLiftedDeclaration( - descriptor: DeclarationDescriptor, - newOwner: DeclarationDescriptor + declaration: IrDeclaration, + newOwner: IrDeclarationParent ): Name = Name.identifier( - descriptor.parentsWithSelf + declaration.parentsWithSelf .takeWhile { it != newOwner } - .toList().reversed() - .map { suggestLocalName(it) } - .joinToString(separator = "$") + .toList().reversed().joinToString(separator = "$") { suggestLocalName(it as IrDeclaration) } ) - private fun createLiftedDescriptor(localFunctionContext: LocalFunctionContext) { - val oldDescriptor = localFunctionContext.descriptor + private fun createLiftedDeclaration(localFunctionContext: LocalFunctionContext) { + val oldDeclaration = localFunctionContext.declaration as IrSimpleFunction - val memberOwner = memberDeclaration.descriptor.containingDeclaration!! - val newDescriptor = SimpleFunctionDescriptorImpl.create( - memberOwner, - oldDescriptor.annotations, - generateNameForLiftedDeclaration(oldDescriptor, memberOwner), - CallableMemberDescriptor.Kind.SYNTHESIZED, - oldDescriptor.source - ).apply { - isTailrec = oldDescriptor.isTailrec - isSuspend = oldDescriptor.isSuspend - // TODO: copy other properties or consider using `FunctionDescriptor.CopyBuilder`. - } + val memberOwner = memberDeclaration.parent + val newDescriptor = WrappedSimpleFunctionDescriptor(oldDeclaration.descriptor.annotations, oldDeclaration.descriptor.source) + val newSymbol = IrSimpleFunctionSymbolImpl(newDescriptor) + val newName = generateNameForLiftedDeclaration(oldDeclaration, memberOwner) - localFunctionContext.transformedDescriptor = newDescriptor - - if (oldDescriptor.dispatchReceiverParameter != null) { + if (oldDeclaration.dispatchReceiverParameter != null) { throw AssertionError("local functions must not have dispatch receiver") } val newDispatchReceiverParameter = null - // Do not substitute type parameters for now. - val newTypeParameters = oldDescriptor.typeParameters - // TODO: consider using fields to access the closure of enclosing class. val capturedValues = localFunctionContext.closure.capturedValues - val newValueParameters = createTransformedValueParameters(localFunctionContext, capturedValues) - - newDescriptor.initialize( - oldDescriptor.extensionReceiverParameter?.copy(newDescriptor), - newDispatchReceiverParameter, - newTypeParameters, - newValueParameters.map { it.descriptor as ValueParameterDescriptor }, - oldDescriptor.returnType, + val newDeclaration = IrFunctionImpl( + oldDeclaration.startOffset, + oldDeclaration.endOffset, + oldDeclaration.origin, + newSymbol, + newName, + // TODO: change to PRIVATE when issue with CallableReferenceLowering in Jvm BE is fixed + Visibilities.PUBLIC, Modality.FINAL, - Visibilities.PRIVATE + oldDeclaration.isInline, + oldDeclaration.isExternal, + oldDeclaration.isTailrec, + oldDeclaration.isSuspend ) + newDescriptor.bind(newDeclaration) - oldDescriptor.extensionReceiverParameter?.let { - newParameterToOld.putAbsentOrSame(newDescriptor.extensionReceiverParameter!!, it) + localFunctionContext.transformedDeclaration = newDeclaration + + newDeclaration.parent = memberOwner + newDeclaration.returnType = oldDeclaration.returnType + newDeclaration.dispatchReceiverParameter = newDispatchReceiverParameter + newDeclaration.extensionReceiverParameter = oldDeclaration.extensionReceiverParameter?.run { + copyTo(newDeclaration).also { + newParameterToOld.putAbsentOrSame(it, this) + } + } + oldDeclaration.typeParameters.mapTo(newDeclaration.typeParameters) { + it.copyTo(newDeclaration).also { p -> p.superTypes += it.superTypes } } - localFunctionContext.transformedDeclaration = with(localFunctionContext.declaration) { - IrFunctionImpl(startOffset, endOffset, origin, newDescriptor) - }.apply { - parent = memberDeclaration.parent - returnType = localFunctionContext.declaration.returnType + newDeclaration.valueParameters += createTransformedValueParameters(capturedValues, oldDeclaration, newDeclaration) + newDeclaration.recordTransformedValueParameters(localFunctionContext) - localFunctionContext.declaration.typeParameters.mapTo(this.typeParameters) { - IrTypeParameterImpl(it.startOffset, it.endOffset, it.origin, it.descriptor) - .apply { superTypes += it.superTypes } - } - - localFunctionContext.declaration.extensionReceiverParameter?.let { - this.extensionReceiverParameter = IrValueParameterImpl( - it.startOffset, - it.endOffset, - it.origin, - descriptor.extensionReceiverParameter!!, - it.type, - null - ) - } - this.valueParameters += newValueParameters - recordTransformedValueParameters(localFunctionContext) - transformedDeclarations[oldDescriptor] = this - } + transformedDeclarations[oldDeclaration] = newDeclaration } private fun createTransformedValueParameters( - localContext: LocalContextWithClosureAsParameters, - capturedValues: List - ) - : List { - - val oldDescriptor = localContext.descriptor - val newDescriptor = localContext.transformedDescriptor - - val closureParametersCount = capturedValues.size - val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size - - val newValueParameters = ArrayList(newValueParametersCount).apply { - capturedValues.mapIndexedTo(this) { i, capturedValue -> - val parameterDescriptor = createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply { - newParameterToCaptured[this] = capturedValue - } - capturedValue.owner.copy(parameterDescriptor) - } - - localContext.declaration.valueParameters.mapIndexedTo(this) { i, oldValueParameter -> - val parameterDescriptor = createUnsubstitutedParameter( - newDescriptor, - oldValueParameter.descriptor as ValueParameterDescriptor, - closureParametersCount + i - ).apply { - newParameterToOld.putAbsentOrSame(this, oldValueParameter.descriptor) - } - oldValueParameter.copy(parameterDescriptor) + capturedValues: List, + oldDeclaration: IrFunction, + newDeclaration: IrFunction + ) = ArrayList(capturedValues.size + oldDeclaration.valueParameters.size).apply { + capturedValues.mapIndexedTo(this) { i, capturedValue -> + val parameterDescriptor = WrappedValueParameterDescriptor() + val p = capturedValue.owner + IrValueParameterImpl( + p.startOffset, p.endOffset, p.origin, IrValueParameterSymbolImpl(parameterDescriptor), + suggestNameForCapturedValue(p), i, p.type, null, false, false + ).also { + parameterDescriptor.bind(it) + it.parent = newDeclaration + newParameterToCaptured[it] = capturedValue + } + } + + oldDeclaration.valueParameters.mapTo(this) { v -> + v.copyTo(newDeclaration, capturedValues.size).also { + newParameterToOld.putAbsentOrSame(it, v) } } - return newValueParameters } private fun IrFunction.recordTransformedValueParameters(localContext: LocalContextWithClosureAsParameters) { valueParameters.forEach { - val capturedValue = newParameterToCaptured[it.descriptor] + val capturedValue = newParameterToCaptured[it] if (capturedValue != null) { - localContext.capturedValueToParameter[capturedValue.descriptor] = it + localContext.capturedValueToParameter[capturedValue.owner] = it } } (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).forEach { - val oldParameter = newParameterToOld[it.descriptor] + val oldParameter = newParameterToOld[it] if (oldParameter != null) { oldParameterToNew.putAbsentOrSame(oldParameter, it) } @@ -612,145 +575,156 @@ class LocalDeclarationsLowering( } - private fun createTransformedConstructorDescriptor(constructorContext: LocalClassConstructorContext) { - val oldDescriptor = constructorContext.descriptor - val localClassContext = localClasses[oldDescriptor.containingDeclaration]!! - val newDescriptor = ClassConstructorDescriptorImpl.create( - localClassContext.descriptor, - Annotations.EMPTY, oldDescriptor.isPrimary, oldDescriptor.source + private fun createTransformedConstructorDeclaration(constructorContext: LocalClassConstructorContext) { + val oldDeclaration = constructorContext.declaration + + val localClassContext = localClasses[oldDeclaration.parent]!! + val capturedValues = localClassContext.closure.capturedValues + + val newDescriptor = WrappedClassConstructorDescriptor(oldDeclaration.descriptor.annotations, oldDeclaration.descriptor.source) + val newSymbol = IrConstructorSymbolImpl(newDescriptor) + + val newDeclaration = IrConstructorImpl( + oldDeclaration.startOffset, oldDeclaration.endOffset, oldDeclaration.origin, + newSymbol, oldDeclaration.name, loweredConstructorVisibility, oldDeclaration.isInline, + oldDeclaration.isExternal, oldDeclaration.isPrimary ) - constructorContext.transformedDescriptor = newDescriptor + newDescriptor.bind(newDeclaration) - // Do not substitute type parameters for now. - val newTypeParameters = oldDescriptor.typeParameters + constructorContext.transformedDeclaration = newDeclaration - val capturedValues = localClasses[oldDescriptor.containingDeclaration]!!.closure.capturedValues - - val newValueParameters = createTransformedValueParameters(constructorContext, capturedValues) - - newDescriptor.initialize( - newValueParameters.map { it.descriptor as ValueParameterDescriptor }, - loweredConstructorVisibility, - newTypeParameters - ) - newDescriptor.returnType = oldDescriptor.returnType - - oldDescriptor.dispatchReceiverParameter?.let { - newParameterToOld.putAbsentOrSame(newDescriptor.dispatchReceiverParameter!!, it) + newDeclaration.parent = localClassContext.declaration + newDeclaration.returnType = oldDeclaration.returnType + newDeclaration.dispatchReceiverParameter = oldDeclaration.dispatchReceiverParameter?.run { + copyTo(newDeclaration).also { + newParameterToOld.putAbsentOrSame(it, this) + } } - - oldDescriptor.extensionReceiverParameter?.let { + newDeclaration.extensionReceiverParameter = oldDeclaration.extensionReceiverParameter?.run { throw AssertionError("constructors can't have extension receiver") } - constructorContext.transformedDeclaration = with(constructorContext.declaration) { - IrConstructorImpl(startOffset, endOffset, origin, newDescriptor).also { it.returnType = returnType } - }.apply { - parent = constructorContext.declaration.parent - constructorContext.declaration.dispatchReceiverParameter?.let { - this.dispatchReceiverParameter = IrValueParameterImpl( - it.startOffset, - it.endOffset, - it.origin, - descriptor.dispatchReceiverParameter!!, - it.type, - null - ) - } + oldDeclaration.typeParameters.mapTo(newDeclaration.typeParameters) { + it.copyTo(newDeclaration).also { p -> p.superTypes += it.superTypes } + } - this.valueParameters += newValueParameters - recordTransformedValueParameters(constructorContext) - transformedDeclarations[oldDescriptor] = this + newDeclaration.valueParameters += createTransformedValueParameters(capturedValues, oldDeclaration, newDeclaration) + newDeclaration.recordTransformedValueParameters(constructorContext) + transformedDeclarations[oldDeclaration] = newDeclaration + } + + private fun createPropertyWithBackingField( + startOffset: Int, + endOffset: Int, + name: Name, + visibility: Visibility, + parent: IrClass, + fieldType: IrType + ): IrField { + val descriptor = WrappedPropertyDescriptor() + val symbol = IrFieldSymbolImpl(descriptor) + return IrFieldImpl( + startOffset, + endOffset, + DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE, + symbol, + name, + fieldType, + visibility, + true, + false, + false + ).also { + descriptor.bind(it) + it.parent = parent } } private fun createFieldsForCapturedValues(localClassContext: LocalClassContext) { - val classDescriptor = localClassContext.descriptor + val classDeclaration = localClassContext.declaration localClassContext.closure.capturedValues.forEach { capturedValue -> - val fieldDescriptor = PropertyDescriptorImpl.create( - classDescriptor, - Annotations.EMPTY, - Modality.FINAL, - Visibilities.PRIVATE, - /* isVar = */ false, - suggestNameForCapturedValue(capturedValue.descriptor), - CallableMemberDescriptor.Kind.SYNTHESIZED, - SourceElement.NO_SOURCE, - /* lateInit = */ false, - /* isConst = */ false, - /* isExpect = */ false, - /* isActual = */ false, - /* isExternal = */ false, - /* isDelegated = */ false - ) - fieldDescriptor.initialize(/* getter = */ null, /* setter = */ null) + if (isJVM) { - val extensionReceiverParameter: ReceiverParameterDescriptor? = null + // TODO: JVM Warkaround + val classDescriptor = classDeclaration.descriptor + val fieldDescriptor = PropertyDescriptorImpl.create( + classDescriptor, + Annotations.EMPTY, + Modality.FINAL, + Visibilities.PRIVATE, + /* isVar = */ false, + suggestNameForCapturedValue(capturedValue.owner), + CallableMemberDescriptor.Kind.SYNTHESIZED, + SourceElement.NO_SOURCE, + /* lateInit = */ false, + /* isConst = */ false, + /* isExpect = */ false, + /* isActual = */ false, + /* isExternal = */ false, + /* isDelegated = */ false + ) - fieldDescriptor.setType( - capturedValue.descriptor.type, - emptyList(), - classDescriptor.thisAsReceiverParameter, - extensionReceiverParameter - ) + fieldDescriptor.initialize(/* getter = */ null, /* setter = */ null) - localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl( - localClassContext.declaration.startOffset, localClassContext.declaration.endOffset, - DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE, - fieldDescriptor, capturedValue.owner.type - ).apply { - parent = localClassContext.declaration + val extensionReceiverParameter: ReceiverParameterDescriptor? = null + + fieldDescriptor.setType( + capturedValue.descriptor.type, + emptyList(), + classDescriptor.thisAsReceiverParameter, + extensionReceiverParameter + ) + + localClassContext.capturedValueToField[capturedValue.owner] = IrFieldImpl( + localClassContext.declaration.startOffset, localClassContext.declaration.endOffset, + DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE, + fieldDescriptor, capturedValue.owner.type + ).apply { + parent = localClassContext.declaration + } + } else { + val irField = createPropertyWithBackingField( + classDeclaration.startOffset, + classDeclaration.endOffset, + suggestNameForCapturedValue(capturedValue.owner), + Visibilities.PRIVATE, + classDeclaration, + capturedValue.owner.type + ) + + localClassContext.capturedValueToField[capturedValue.owner] = irField } } } private fun MutableMap.putAbsentOrSame(key: K, value: V) { - val current = this.getOrPut(key, { value }) + val current = this.getOrPut(key) { value } if (current != value) { error("$current != $value") } } - private fun suggestNameForCapturedValue(valueDescriptor: ValueDescriptor): Name = - if (valueDescriptor.name.isSpecial) { - val oldNameStr = valueDescriptor.name.asString() + private fun suggestNameForCapturedValue(declaration: IrValueDeclaration): Name = + if (declaration.name.isSpecial) { + val oldNameStr = declaration.name.asString() oldNameStr.substring(1, oldNameStr.length - 1).synthesizedName } else - valueDescriptor.name - - private fun createUnsubstitutedCapturedValueParameter( - newParameterOwner: CallableMemberDescriptor, - valueDescriptor: ValueDescriptor, - index: Int - ): ValueParameterDescriptor = - ValueParameterDescriptorImpl( - newParameterOwner, null, index, - valueDescriptor.annotations, - suggestNameForCapturedValue(valueDescriptor), - valueDescriptor.type, - false, false, false, null, valueDescriptor.source - ) - - private fun createUnsubstitutedParameter( - newParameterOwner: CallableMemberDescriptor, - valueParameterDescriptor: ValueParameterDescriptor, - newIndex: Int - ): ValueParameterDescriptor = - valueParameterDescriptor.copy(newParameterOwner, valueParameterDescriptor.name, newIndex) + declaration.name private fun collectClosures() { val annotator = ClosureAnnotator(memberDeclaration) - localFunctions.forEach { descriptor, context -> - context.closure = annotator.getFunctionClosure(descriptor) + + localFunctions.forEach { declaration, context -> + context.closure = annotator.getFunctionClosure(declaration) } - localClasses.forEach { descriptor, context -> - context.closure = annotator.getClassClosure(descriptor) + localClasses.forEach { declaration, context -> + context.closure = annotator.getClassClosure(declaration) } } @@ -761,65 +735,40 @@ class LocalDeclarationsLowering( element.acceptChildrenVoid(this) } - private fun ClassDescriptor.declaredInFunction() = when (this.containingDeclaration) { - is CallableDescriptor -> true - is ClassDescriptor -> false - is PackageFragmentDescriptor -> false - else -> TODO(this.toString() + "\n" + this.containingDeclaration.toString()) - } - override fun visitFunction(declaration: IrFunction) { declaration.acceptChildrenVoid(this) - val descriptor = declaration.descriptor - - if (descriptor.visibility == Visibilities.LOCAL) { + if (declaration.visibility == Visibilities.LOCAL) { val localFunctionContext = LocalFunctionContext(declaration) - localFunctions[descriptor] = localFunctionContext + localFunctions[declaration] = localFunctionContext - if (descriptor.name.isSpecial) { + if (declaration.name.isSpecial) { localFunctionContext.index = lambdasCount++ } } - } override fun visitConstructor(declaration: IrConstructor) { declaration.acceptChildrenVoid(this) - val descriptor = declaration.descriptor assert(declaration.visibility != Visibilities.LOCAL) if ((declaration.parent as IrClass).isInner) return - localClassConstructors[descriptor] = LocalClassConstructorContext(declaration) + localClassConstructors[declaration] = LocalClassConstructorContext(declaration) } override fun visitClass(declaration: IrClass) { declaration.acceptChildrenVoid(this) - val descriptor = declaration.descriptor - if (declaration.isInner) return - // Local nested classes can only be inner. - assert(descriptor.declaredInFunction()) - val localClassContext = LocalClassContext(declaration) - localClasses[descriptor] = localClassContext + localClasses[declaration] = localClassContext } }) } } -} - -private fun IrValueDeclaration.copy(newDescriptor: ParameterDescriptor): IrValueParameter = IrValueParameterImpl( - startOffset, - endOffset, - IrDeclarationOrigin.DEFINED, - newDescriptor, - type, - (this as? IrValueParameter)?.varargElementType -) +} \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt index 0a916b1d850..2a54611b044 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt @@ -26,17 +26,17 @@ 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.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy -import org.jetbrains.kotlin.resolve.OverridingUtil -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl import org.jetbrains.kotlin.utils.Printer @@ -55,16 +55,16 @@ class DeclarationIrBuilder( ) abstract class AbstractVariableRemapper : IrElementTransformerVoid() { - protected abstract fun remapVariable(value: ValueDescriptor): IrValueParameter? + protected abstract fun remapVariable(value: IrValueDeclaration): IrValueParameter? override fun visitGetValue(expression: IrGetValue): IrExpression = - remapVariable(expression.descriptor)?.let { + remapVariable(expression.symbol.owner)?.let { IrGetValueImpl(expression.startOffset, expression.endOffset, it.type, it.symbol, expression.origin) } ?: expression } -class VariableRemapper(val mapping: Map) : AbstractVariableRemapper() { - override fun remapVariable(value: ValueDescriptor): IrValueParameter? = +class VariableRemapper(val mapping: Map) : AbstractVariableRemapper() { + override fun remapVariable(value: IrValueDeclaration): IrValueParameter? = mapping[value] } @@ -157,35 +157,6 @@ open class IrBuildingTransformer(private val context: BackendContext) : IrElemen } } -fun computeOverrides(current: ClassDescriptor, functionsFromCurrent: List): List { - - val result = mutableListOf() - - val allSuperDescriptors = current.typeConstructor.supertypes - .flatMap { it.memberScope.getContributedDescriptors() } - .filterIsInstance() - - for ((name, group) in allSuperDescriptors.groupBy { it.name }) { - OverridingUtil.generateOverridesInFunctionGroup( - name, - /* membersFromSupertypes = */ group, - /* membersFromCurrent = */ functionsFromCurrent.filter { it.name == name }, - current, - object : NonReportingOverrideStrategy() { - override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) { - result.add(fakeOverride) - } - - override fun conflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) { - error("Conflict in scope of $current: $fromSuper vs $fromCurrent") - } - } - ) - } - - return result -} - class SimpleMemberScope(val members: List) : MemberScopeImpl() { override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = @@ -207,12 +178,14 @@ class SimpleMemberScope(val members: List) : MemberScopeI members.filter { kindFilter.accepts(it) && nameFilter(it.name) } override fun printScopeStructure(p: Printer) = TODO("not implemented") - } -fun IrConstructor.callsSuper(): Boolean { - val constructedClass = descriptor.constructedClass - val superClass = constructedClass.getSuperClassOrAny() +fun IrConstructor.callsSuper(irBuiltIns: IrBuiltIns): Boolean { + val constructedClass = parent as IrClass + val superClass = constructedClass.superTypes + .mapNotNull { it as? IrSimpleType } + .firstOrNull { (it.classifier.owner as IrClass).run { kind == ClassKind.CLASS || kind == ClassKind.ANNOTATION_CLASS || kind == ClassKind.ANNOTATION_CLASS } } + ?: irBuiltIns.anyType var callsSuper = false var numberOfCalls = 0 acceptChildrenVoid(object : IrElementVisitorVoid { @@ -225,17 +198,18 @@ fun IrConstructor.callsSuper(): Boolean { } override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) { - assert(++numberOfCalls == 1, { "More than one delegating constructor call: $descriptor" }) - if (expression.descriptor.constructedClass == superClass) + assert(++numberOfCalls == 1) { "More than one delegating constructor call: ${symbol.owner}" } + val delegatingClass = expression.symbol.owner.parent as IrClass + if (delegatingClass == superClass.classifierOrFail.owner) callsSuper = true - else if (expression.descriptor.constructedClass != constructedClass) + else if (delegatingClass != constructedClass) throw AssertionError( "Expected either call to another constructor of the class being constructed or" + - " call to super class constructor. But was: ${expression.descriptor.constructedClass}" + " call to super class constructor. But was: $delegatingClass" ) } }) - assert(numberOfCalls == 1, { "Expected exactly one delegating constructor call but none encountered: $descriptor" }) + assert(numberOfCalls == 1) { "Expected exactly one delegating constructor call but none encountered: ${symbol.owner}" } return callsSuper } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt index cba3cf8c73d..84aeb730f41 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt @@ -73,7 +73,7 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower it.valueParameters.size == 0 && it.name == nameToString } private val defaultAppendFunction = stringBuilder.functions.single { - it.descriptor.name == nameAppend && + it.name == nameAppend && it.valueParameters.size == 1 && it.valueParameters.single().type.isNullableAny() } @@ -82,7 +82,7 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower private val appendFunctions: Map = typesWithSpecialAppendFunction.map { type -> type to stringBuilder.functions.toList().atMostOne { - it.descriptor.name == nameAppend && + it.name == nameAppend && it.valueParameters.size == 1 && it.valueParameters.single().type.toKotlinType() == type } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/utils/kotlinTypeBasedUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/utils/kotlinTypeBasedUtils.kt index a40fdb51d31..ec48e8ab634 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/utils/kotlinTypeBasedUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/utils/kotlinTypeBasedUtils.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.backend.common.utils import org.jetbrains.kotlin.backend.common.descriptors.isFunctionOrKFunctionType import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype -import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.toIrType @@ -20,24 +19,34 @@ import org.jetbrains.kotlin.types.typeUtil.isInterface import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.isTypeParameter +// TODO: implement pure Ir-based function (see IrTypeUtils.kt) + +@Deprecated("Use pure Ir helper") fun IrType.isNullable() = toKotlinType().isNullable() +@Deprecated("Use pure Ir helper") fun IrType.isInterface() = toKotlinType().isInterface() +@Deprecated("Use pure Ir helper") fun IrType.isPrimitiveArray() = KotlinBuiltIns.isPrimitiveArray(toKotlinType()) +@Deprecated("Use pure Ir helper") fun IrType.getPrimitiveArrayElementType() = KotlinBuiltIns.getPrimitiveArrayElementType(toKotlinType()) +@Deprecated("Use pure Ir helper") fun IrType.isTypeParameter() = toKotlinType().isTypeParameter() +@Deprecated("Use pure Ir helper") fun IrType.isFunctionOrKFunction() = toKotlinType().isFunctionOrKFunctionType -fun IrType.isFunctionTypeOrSubtype() = toKotlinType().isFunctionTypeOrSubtype - +@Deprecated("Use pure Ir helper") fun List.commonSupertype() = CommonSupertypes.commonSupertype(map(IrType::toKotlinType)).toIrType()!! +@Deprecated("Use pure Ir helper") fun IrType.isSubtypeOf(superType: IrType) = toKotlinType().isSubtypeOf(superType.toKotlinType()) +@Deprecated("Use pure Ir helper") fun IrType.isSubtypeOfClass(superClass: IrClassSymbol) = DescriptorUtils.isSubtypeOfClass(toKotlinType(), superClass.descriptor) +@Deprecated("Use pure Ir helper") fun IrType.isBuiltinFunctionalTypeOrSubtype() = toKotlinType().isBuiltinFunctionalTypeOrSubtype \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt new file mode 100644 index 00000000000..1cc9889c60a --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.util + +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrPackageFragment +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classifierOrNull +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.utils.DFS + + +fun IrType.isFunctionTypeOrSubtype(): Boolean { + + val kotlinPackageFqn = FqName.fromSegments(listOf("kotlin")) + fun checkType(irType: IrType): Boolean { + val classifier = irType.classifierOrNull ?: return false + val name = classifier.descriptor.name.asString() + if (!name.startsWith("Function")) return false + val declaration = classifier.owner as IrDeclaration + val parent = declaration.parent as? IrPackageFragment ?: return false + + return parent.fqName == kotlinPackageFqn + } + + fun superTypes(irType: IrType): List { + val classifier = irType.classifierOrNull?.owner ?: return emptyList() + return when(classifier) { + is IrClass -> classifier.superTypes + is IrTypeParameter -> classifier.superTypes + else -> throw IllegalStateException() + } + } + + return DFS.ifAny(listOf(this), ::superTypes, ::checkType) +} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt index 8c79d980d8f..8fca9a55867 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt @@ -13,4 +13,5 @@ object JsLoweredDeclarationOrigin : IrDeclarationOrigin { object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER") object JS_INTRINSICS_STUB : IrDeclarationOriginImpl("JS_INTRINSICS_STUB") object JS_CLOSURE_BOX_CLASS : IrStatementOriginImpl("JS_CLOSURE_BOX_CLASS") + object JS_CLOSURE_BOX_CLASS_DECLARATION : IrDeclarationOriginImpl("JS_CLOSURE_BOX_CLASS_DECLARATION") } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDeclarationFactory.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDeclarationFactory.kt new file mode 100644 index 00000000000..d31707d6c5b --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDeclarationFactory.kt @@ -0,0 +1,136 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.js + +import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedPropertyDescriptor +import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder +import org.jetbrains.kotlin.ir.backend.js.utils.Namer +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.dump +import org.jetbrains.kotlin.name.Name +import java.util.* + +class JsDeclarationFactory : DeclarationFactory { + private val singletonFieldDescriptors = HashMap() + private val outerThisFieldSymbols = HashMap() + private val innerClassConstructors = HashMap() + + override fun getFieldForEnumEntry(enumEntry: IrEnumEntry, type: IrType): IrField = TODO() + + override fun getOuterThisField(innerClass: IrClass): IrField = + if (!innerClass.isInner) throw AssertionError("Class is not inner: ${innerClass.dump()}") + else { + outerThisFieldSymbols.getOrPut(innerClass) { + val outerClass = innerClass.parent as? IrClass + ?: throw AssertionError("No containing class for inner class ${innerClass.dump()}") + + + val name = Name.identifier("\$this") + val fieldType = outerClass.defaultType + val visibility = Visibilities.PROTECTED + + createPropertyWithBackingField(name, visibility, innerClass, fieldType, DeclarationFactory.FIELD_FOR_OUTER_THIS) + } + } + + private fun createPropertyWithBackingField(name: Name, visibility: Visibility, parent: IrClass, fieldType: IrType, origin: IrDeclarationOrigin): IrField { + val descriptor = WrappedPropertyDescriptor() + val symbol = IrFieldSymbolImpl(descriptor) + + return IrFieldImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + origin, + symbol, + name, + fieldType, + visibility, + true, + false, + false + ).also { + descriptor.bind(it) + it.parent = parent + } + } + + + override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructor { + val innerClass = innerClassConstructor.parent as IrClass + assert(innerClass.isInner) { "Class is not inner: $innerClass" } + + return innerClassConstructors.getOrPut(innerClassConstructor) { + createInnerClassConstructorWithOuterThisParameter(innerClassConstructor) + } + } + + private fun createInnerClassConstructorWithOuterThisParameter(oldConstructor: IrConstructor): IrConstructor { + val irClass = oldConstructor.parent as IrClass + val outerThisType = (irClass.parent as IrClass).defaultType + + val descriptor = WrappedClassConstructorDescriptor(oldConstructor.descriptor.annotations, oldConstructor.descriptor.source) + val symbol = IrConstructorSymbolImpl(descriptor) + + val newConstructor = IrConstructorImpl( + oldConstructor.startOffset, + oldConstructor.endOffset, + oldConstructor.origin, + symbol, + oldConstructor.name, + oldConstructor.visibility, + oldConstructor.isInline, + oldConstructor.isExternal, + oldConstructor.isPrimary + ).also { + descriptor.bind(it) + it.parent = oldConstructor.parent + it.returnType = oldConstructor.returnType + } + + val outerThisValueParameter = + JsIrBuilder.buildValueParameter(Namer.OUTER_NAME, 0, outerThisType).also { it.parent = newConstructor } + + val newValueParameters = mutableListOf(outerThisValueParameter) + + for (p in oldConstructor.valueParameters) { + newValueParameters += p.copyTo(newConstructor, 1) + } + + for (p in oldConstructor.typeParameters) { + newConstructor.typeParameters += p.copyTo(newConstructor) + } + + newConstructor.valueParameters += newValueParameters + + return newConstructor + } + + override fun getFieldForObjectInstance(singleton: IrClass): IrField = + singletonFieldDescriptors.getOrPut(singleton) { + createObjectInstanceFieldDescriptor(singleton, JsIrBuilder.SYNTHESIZED_DECLARATION) + } + + private fun createObjectInstanceFieldDescriptor(singleton: IrClass, origin: IrDeclarationOrigin): IrField { + assert(singleton.kind == ClassKind.OBJECT) { "Should be an object: $singleton" } + + val name = Name.identifier("INSTANCE") + + return createPropertyWithBackingField(name, Visibilities.PUBLIC, singleton, singleton.defaultType, origin) + } +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt deleted file mode 100644 index 76125f0e237..00000000000 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.backend.js - -import org.jetbrains.kotlin.backend.common.descriptors.DescriptorsFactory -import org.jetbrains.kotlin.builtins.CompanionObjectMapping.isMappedIntrinsicCompanionObject -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl -import org.jetbrains.kotlin.ir.backend.js.utils.Namer -import org.jetbrains.kotlin.ir.backend.js.utils.createValueParameter -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl -import org.jetbrains.kotlin.ir.types.toKotlinType -import org.jetbrains.kotlin.ir.util.defaultType -import org.jetbrains.kotlin.ir.util.dump -import org.jetbrains.kotlin.name.Name -import java.util.* - -class JsDescriptorsFactory : DescriptorsFactory { - private val singletonFieldDescriptors = HashMap, IrFieldSymbol>() - private val outerThisFieldSymbols = HashMap() - private val innerClassConstructors = HashMap() - - override fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol = TODO() - - override fun getOuterThisFieldSymbol(innerClass: IrClass): IrFieldSymbol = - if (!innerClass.isInner) throw AssertionError("Class is not inner: ${innerClass.dump()}") - else outerThisFieldSymbols.getOrPut(innerClass) { - val outerClass = innerClass.parent as? IrClass - ?: throw AssertionError("No containing class for inner class ${innerClass.dump()}") - - IrFieldSymbolImpl(PropertyDescriptorImpl.create( - innerClass.descriptor, - Annotations.EMPTY, - Modality.FINAL, - Visibilities.PROTECTED, - false, - Name.identifier("\$this"), - CallableMemberDescriptor.Kind.SYNTHESIZED, - SourceElement.NO_SOURCE, - false, - true, - false, - false, - false, - false - ).apply { - setType(outerClass.defaultType.toKotlinType(), emptyList(), innerClass.descriptor.thisAsReceiverParameter, null) - initialize(null, null) - }) - } - - override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructorSymbol { - val innerClass = innerClassConstructor.parent as IrClass - assert(innerClass.isInner) { "Class is not inner: $innerClass" } - - return innerClassConstructors.getOrPut(innerClassConstructor.symbol) { - createInnerClassConstructorWithOuterThisParameter(innerClassConstructor.descriptor) - } - } - - private fun createInnerClassConstructorWithOuterThisParameter(oldDescriptor: ClassConstructorDescriptor): IrConstructorSymbol { - val classDescriptor = oldDescriptor.containingDeclaration - val outerThisType = (classDescriptor.containingDeclaration as ClassDescriptor).defaultType - - val newDescriptor = ClassConstructorDescriptorImpl.createSynthesized( - classDescriptor, oldDescriptor.annotations, oldDescriptor.isPrimary, oldDescriptor.source - ) - - val outerThisValueParameter = createValueParameter(newDescriptor, 0, Namer.OUTER_NAME, outerThisType) - - val newValueParameters = - listOf(outerThisValueParameter) + - oldDescriptor.valueParameters.map { it.copy(newDescriptor, it.name, it.index + 1) } - newDescriptor.initialize(newValueParameters, oldDescriptor.visibility) - newDescriptor.returnType = oldDescriptor.returnType - return IrConstructorSymbolImpl(newDescriptor) - } - - override fun getSymbolForObjectInstance(singleton: IrClassSymbol): IrFieldSymbol = - singletonFieldDescriptors.getOrPut(singleton) { - IrFieldSymbolImpl(createObjectInstanceFieldDescriptor(singleton.descriptor)) - } - - private fun createObjectInstanceFieldDescriptor(objectDescriptor: ClassDescriptor): PropertyDescriptor { - assert(objectDescriptor.kind == ClassKind.OBJECT) { "Should be an object: $objectDescriptor" } - - val isNotMappedCompanion = objectDescriptor.isCompanionObject && !isMappedIntrinsicCompanionObject(objectDescriptor) - val name = if (isNotMappedCompanion) objectDescriptor.name else Name.identifier("INSTANCE") - val containingDeclaration = if (isNotMappedCompanion) objectDescriptor.containingDeclaration else objectDescriptor - return PropertyDescriptorImpl.create( - containingDeclaration, - Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC, false, - name, - CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, /* lateInit = */ false, /* isConst = */ false, - /* isExpect = */ false, /* isActual = */ false, /* isExternal = */ false, /* isDelegated = */ false - ).apply { - setType(objectDescriptor.defaultType, emptyList(), null, null) - initialize(null, null) - } - } -} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt index f49f28d2681..c1e1083a014 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt @@ -7,31 +7,20 @@ package org.jetbrains.kotlin.ir.backend.js import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.PrimitiveType -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl -import org.jetbrains.kotlin.ir.backend.js.utils.createValueParameter -import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder +import org.jetbrains.kotlin.ir.backend.js.utils.Namer +import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns -import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator -import org.jetbrains.kotlin.js.resolve.JsPlatform.builtIns +import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi2ir.findSingleFunction import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.KotlinTypeFactory -import org.jetbrains.kotlin.types.Variance -class JsIntrinsics( - private val module: ModuleDescriptor, - private val irBuiltIns: IrBuiltIns, - val context: JsIrBackendContext -) { +class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendContext) { - private val stubBuilder = DeclarationStubGenerator( - module, context.symbolTable, JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB, irBuiltIns.languageVersionSettings - ) + private val externalPackageFragmentSymbol = IrExternalPackageFragmentSymbolImpl(context.internalPackageFragmentDescriptor) + private val externalPackageFragment = IrExternalPackageFragmentImpl(externalPackageFragmentSymbol) // Equality operations: @@ -172,6 +161,11 @@ class JsIntrinsics( val charConstructor = context.symbolTable.referenceConstructor(context.getClass(KotlinBuiltIns.FQ_NAMES._char.toSafe()).constructors.single()) + val unreachable = defineUnreachableIntrinsic() + + val returnIfSuspended = getInternalFunction("returnIfSuspended") + val getContinuation = getInternalFunction("getContinuation") + // Helpers: private fun getInternalFunction(name: String) = @@ -180,53 +174,35 @@ class JsIntrinsics( private fun getInternalWithoutPackage(name: String) = context.symbolTable.referenceSimpleFunction(context.getFunctions(FqName(name)).single()) - // TODO: unify how we create intrinsic symbols - private fun defineObjectCreateIntrinsic(): IrSimpleFunction { - - val typeParam = TypeParameterDescriptorImpl.createWithDefaultBound( - builtIns.any, - Annotations.EMPTY, - true, - Variance.INVARIANT, - Name.identifier("T"), - 0 - ) - - val returnType = KotlinTypeFactory.simpleType(Annotations.EMPTY, typeParam.typeConstructor, emptyList(), false) - - val desc = SimpleFunctionDescriptorImpl.create( - module, - Annotations.EMPTY, - Name.identifier("Object\$create"), - CallableMemberDescriptor.Kind.SYNTHESIZED, - SourceElement.NO_SOURCE - ).apply { - initialize(null, null, listOf(typeParam), emptyList(), returnType, Modality.FINAL, Visibilities.PUBLIC) - isInline = true + private fun defineObjectCreateIntrinsic() = + JsIrBuilder.buildFunction("Object\$create", isInline = true, origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB).also { + val typeParameter = JsIrBuilder.buildTypeParameter(Name.identifier("T"), 0, true) + val anyType = irBuiltIns.anyType + typeParameter.parent = it + typeParameter.superTypes += anyType + it.typeParameters += typeParameter + it.returnType = anyType + it.parent = externalPackageFragment + externalPackageFragment.declarations += it } - return stubBuilder.generateFunctionStub(desc) - } - - private fun defineSetJSPropertyIntrinsic(): IrSimpleFunction { - val returnType = irBuiltIns.unit - - val desc = SimpleFunctionDescriptorImpl.create( - module, - Annotations.EMPTY, - Name.identifier("\$setJSProperty\$"), - CallableMemberDescriptor.Kind.SYNTHESIZED, - SourceElement.NO_SOURCE - ).apply { - - val parameterDescriptors = listOf("receiver", "fieldName", "fieldValue") - .mapIndexed { i, name -> createValueParameter(this, i, name, irBuiltIns.any) } - initialize(null, null, emptyList(), parameterDescriptors, returnType, Modality.FINAL, Visibilities.PUBLIC) + private fun defineSetJSPropertyIntrinsic() = + JsIrBuilder.buildFunction("\$setJSProperty\$", origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB).also { + it.returnType = irBuiltIns.unitType + listOf("receiver", "fieldName", "fieldValue").mapIndexedTo(it.valueParameters) { i, p -> + JsIrBuilder.buildValueParameter(p, i, irBuiltIns.anyType).also { v -> v.parent = it } + } + it.parent = externalPackageFragment + externalPackageFragment.declarations += it } - return stubBuilder.generateFunctionStub(desc) - } + private fun defineUnreachableIntrinsic() = + JsIrBuilder.buildFunction(Namer.UNREACHABLE_NAME, origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB).also { + it.returnType = irBuiltIns.nothingType + it.parent = externalPackageFragment + externalPackageFragment.declarations += it + } private fun unOp(name: String, returnType: KotlinType = irBuiltIns.anyN) = irBuiltIns.run { defineOperator(name, returnType, listOf(anyN)) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index 9d95d13fdf2..78f6bebc29d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -10,19 +10,23 @@ import org.jetbrains.kotlin.backend.common.ReflectionTypes import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Symbols -import org.jetbrains.kotlin.backend.js.JsDescriptorsFactory +import org.jetbrains.kotlin.backend.js.JsDeclarationFactory import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.SourceManager +import org.jetbrains.kotlin.ir.SourceRangeInfo +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.lower.inline.ModuleIndex import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol @@ -46,9 +50,23 @@ class JsIrBackendContext( override val builtIns = module.builtIns + val internalPackageFragmentDescriptor = KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal")) + val implicitDeclarationFile = IrFileImpl(object : SourceManager.FileEntry { + override val name = "" + override val maxOffset = UNDEFINED_OFFSET + + override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int) = + SourceRangeInfo("", UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET) + + override fun getLineNumber(offset: Int) = UNDEFINED_OFFSET + override fun getColumnNumber(offset: Int) = UNDEFINED_OFFSET + }, internalPackageFragmentDescriptor).also { + irModuleFragment.files += it + } + override val sharedVariablesManager = - JsSharedVariablesManager(builtIns, KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal"))) - override val descriptorsFactory = JsDescriptorsFactory() + JsSharedVariablesManager(irBuiltIns, implicitDeclarationFile) + override val declarationFactory = JsDeclarationFactory() override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) { // TODO ReflectionTypes(module, FqName("kotlin.reflect")) @@ -98,7 +116,7 @@ class JsIrBackendContext( return vars.single() } - val intrinsics = JsIntrinsics(module, irBuiltIns, this) + val intrinsics = JsIntrinsics(irBuiltIns, this) private val operatorMap = referenceOperators() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt index 1289677a1e4..34403f16bec 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt @@ -5,101 +5,97 @@ package org.jetbrains.kotlin.ir.backend.js -import org.jetbrains.kotlin.backend.common.descriptors.KnownClassDescriptor -import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor -import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl -import org.jetbrains.kotlin.ir.backend.js.utils.createValueParameter -import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedPropertyDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor +import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory +import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.IrSetVariable import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.KotlinTypeFactory -import org.jetbrains.kotlin.types.TypeProjectionImpl -import org.jetbrains.kotlin.types.Variance -class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPackage: PackageFragmentDescriptor) : SharedVariablesManager { +class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclarationsFile: IrFile) : SharedVariablesManager { override fun declareSharedVariable(originalDeclaration: IrVariable): IrVariable { - val variableDescriptor = originalDeclaration.descriptor - val sharedVariableDescriptor = LocalVariableDescriptor( - variableDescriptor.containingDeclaration, variableDescriptor.annotations, variableDescriptor.name, - getSharedVariableType(variableDescriptor.type), - false, false, variableDescriptor.isLateInit, variableDescriptor.source - ) - val valueType = originalDeclaration.type - val boxConstructor = closureBoxConstructorTypeDescriptor - val boxConstructorSymbol = closureBoxConstructorTypeSymbol val initializer = originalDeclaration.initializer ?: IrConstImpl.constNull( originalDeclaration.startOffset, originalDeclaration.endOffset, valueType ) - // TODO use buildCall? - val constructorCall = IrCallImpl( - originalDeclaration.startOffset, - originalDeclaration.endOffset, - // TODO wrong type - originalDeclaration.type, - boxConstructorSymbol, - boxConstructor, - 1, - JsLoweredDeclarationOrigin.JS_CLOSURE_BOX_CLASS - ).apply { - putTypeArgument(0, valueType) + + val constructorSymbol = closureBoxConstructorDeclaration.symbol + + val irCall = IrCallImpl(initializer.startOffset, initializer.endOffset, closureBoxType, constructorSymbol).apply { putValueArgument(0, initializer) } - + val descriptor = WrappedVariableDescriptor() return IrVariableImpl( originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin, - sharedVariableDescriptor, - // TODO wrong type ? - originalDeclaration.type, - constructorCall - ) + IrVariableSymbolImpl(descriptor), + originalDeclaration.name, + irCall.type, + false, + false, + false + ).also { + descriptor.bind(it) + it.parent = originalDeclaration.parent + it.initializer = irCall + } } override fun defineSharedValue(originalDeclaration: IrVariable, sharedVariableDeclaration: IrVariable) = sharedVariableDeclaration - override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue): IrExpression = - IrGetFieldImpl( - originalGet.startOffset, originalGet.endOffset, - closureBoxFieldSymbol, - originalGet.type, - IrGetValueImpl( - originalGet.startOffset, - originalGet.endOffset, - originalGet.type, - sharedVariableSymbol - ), + override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue) = IrGetFieldImpl( + originalGet.startOffset, originalGet.endOffset, + closureBoxFieldDeclaration.symbol, + originalGet.type, + IrGetValueImpl( + originalGet.startOffset, + originalGet.endOffset, + closureBoxType, + sharedVariableSymbol, originalGet.origin - ) + ), + originalGet.origin + ) override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetVariable): IrExpression = IrSetFieldImpl( - originalSet.startOffset, originalSet.endOffset, - closureBoxFieldSymbol, + originalSet.startOffset, + originalSet.endOffset, + closureBoxFieldDeclaration.symbol, IrGetValueImpl( originalSet.startOffset, originalSet.endOffset, - originalSet.type, - sharedVariableSymbol + closureBoxType, + sharedVariableSymbol, + originalSet.origin ), originalSet.value, originalSet.type, @@ -108,84 +104,93 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack private val boxTypeName = "\$closureBox\$" - private val closureBoxTypeDescriptor = createClosureBoxClass() - private val closureBoxConstructorTypeDescriptor = createClosureBoxClassConstructor() - private val closureBoxFieldDescriptor = createClosureBoxField() + private val closureBoxClassDeclaration by lazy { + createClosureBoxClassDeclaration() + } - val closureBoxConstructorTypeSymbol = createFunctionSymbol(closureBoxConstructorTypeDescriptor) - private val closureBoxFieldSymbol = IrFieldSymbolImpl(closureBoxFieldDescriptor) + private val closureBoxConstructorDeclaration by lazy { + createClosureBoxConstructorDeclaration() + } + private val closureBoxFieldDeclaration by lazy { + closureBoxPropertyDeclaration + } - private fun createClosureBoxClass(): ClassDescriptor = - KnownClassDescriptor.createClassWithTypeParameters( - Name.identifier(boxTypeName), jsInterinalPackage, listOf(builtIns.anyType), listOf( - Name.identifier("T") - ) + private val closureBoxPropertyDeclaration by lazy { + createClosureBoxPropertyDeclaration() + } + + private lateinit var closureBoxType: IrType + + private fun createClosureBoxClassDeclaration(): IrClass { + val descriptor = WrappedClassDescriptor() + val declaration = IrClassImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, JsLoweredDeclarationOrigin.JS_CLOSURE_BOX_CLASS_DECLARATION, IrClassSymbolImpl(descriptor), + Name.identifier(boxTypeName), ClassKind.CLASS, Visibilities.PUBLIC, Modality.FINAL, false, false, false, false, false ) - private fun createClosureBoxClassConstructor(): ClassConstructorDescriptor = - ClassConstructorDescriptorImpl.create( - closureBoxTypeDescriptor, - Annotations.EMPTY, - true, - SourceElement.NO_SOURCE - ).apply { - val typeParameter = constructedClass.declaredTypeParameters[0] - val typeParameterType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( - Annotations.EMPTY, - typeParameter.typeConstructor, - listOf(), - false, - MemberScope.Empty - ) + descriptor.bind(declaration) + declaration.parent = implicitDeclarationsFile + closureBoxType = IrSimpleTypeImpl(declaration.symbol, false, emptyList(), emptyList()) + declaration.thisReceiver = + JsIrBuilder.buildValueParameter(Name.special(""), -1, closureBoxType, IrDeclarationOrigin.INSTANCE_RECEIVER) + implicitDeclarationsFile.declarations += declaration - val parameterType = KotlinTypeFactory.simpleType( - Annotations.EMPTY, - typeParameter.typeConstructor, - listOf(), true - ) + return declaration + } - val paramDesc = createValueParameter(this, 0, "v", parameterType) - - initialize(listOf(paramDesc), Visibilities.PUBLIC) - returnType = KotlinTypeFactory.simpleNotNullType( - Annotations.EMPTY, - closureBoxTypeDescriptor, - listOf(TypeProjectionImpl(Variance.INVARIANT, typeParameterType)) - ) - } - - private fun createClosureBoxField(): PropertyDescriptor { - val desc = PropertyDescriptorImpl.create( - closureBoxTypeDescriptor, - Annotations.EMPTY, - Modality.FINAL, + private fun createClosureBoxPropertyDeclaration(): IrField { + val descriptor = WrappedPropertyDescriptor() + val symbol = IrFieldSymbolImpl(descriptor) + val fieldName = Name.identifier("v") + return IrFieldImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + DeclarationFactory.FIELD_FOR_OUTER_THIS, + symbol, + fieldName, + builtIns.anyNType, Visibilities.PUBLIC, - true, - Name.identifier("v"), - CallableMemberDescriptor.Kind.DECLARATION, - SourceElement.NO_SOURCE, - false, - false, - false, false, false, false - ) - - desc.setType(builtIns.anyType, emptyList(), closureBoxTypeDescriptor.thisAsReceiverParameter, null) - desc.initialize(null, null) - - return desc + ).also { + descriptor.bind(it) + it.parent = closureBoxClassDeclaration + closureBoxClassDeclaration.declarations += it + } } - private fun getRefType(valueType: KotlinType) = - KotlinTypeFactory.simpleNotNullType( - Annotations.EMPTY, - closureBoxTypeDescriptor, - listOf(TypeProjectionImpl(Variance.INVARIANT, valueType)) + private fun createClosureBoxConstructorDeclaration(): IrConstructor { + val descriptor = WrappedClassConstructorDescriptor() + val symbol = IrConstructorSymbolImpl(descriptor) + + val declaration = IrConstructorImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, JsLoweredDeclarationOrigin.JS_CLOSURE_BOX_CLASS_DECLARATION, symbol, + Name.special(""), Visibilities.PUBLIC, false, false, true ) - private fun getSharedVariableType(type: KotlinType) = getRefType(type) + descriptor.bind(declaration) + declaration.parent = closureBoxClassDeclaration + val parameterDeclaration = createClosureBoxConstructorParameterDeclaration(declaration) + + declaration.valueParameters += parameterDeclaration + + val receiver = JsIrBuilder.buildGetValue(closureBoxClassDeclaration.thisReceiver!!.symbol) + val value = JsIrBuilder.buildGetValue(parameterDeclaration.symbol) + + val setField = JsIrBuilder.buildSetField(closureBoxFieldDeclaration.symbol, receiver, value, closureBoxFieldDeclaration.type) + + declaration.body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(setField)) + + closureBoxClassDeclaration.declarations += declaration + return declaration + } + + private fun createClosureBoxConstructorParameterDeclaration(irConstructor: IrConstructor): IrValueParameter { + return JsIrBuilder.buildValueParameter("p", 0, closureBoxPropertyDeclaration.type).also { + it.parent = irConstructor + } + } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index e2472dd1be3..a33bfc247b7 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -93,6 +93,7 @@ private fun JsIrBackendContext.lower(moduleFragment: IrModuleFragment) { moduleFragment.files.forEach(LateinitLowering(this, true)::lower) moduleFragment.files.forEach(DefaultArgumentStubGenerator(this)::runOnFilePostfix) moduleFragment.files.forEach(DefaultParameterInjector(this)::runOnFilePostfix) + moduleFragment.files.forEach(DefaultParameterCleaner(this)::runOnFilePostfix) moduleFragment.files.forEach(SharedVariablesLowering(this)::runOnFilePostfix) moduleFragment.files.forEach(EnumClassLowering(this)::runOnFilePostfix) moduleFragment.files.forEach(EnumUsageLowering(this)::lower) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrBuilder.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrBuilder.kt index 6b63fd17a89..262b1af7c67 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrBuilder.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrBuilder.kt @@ -5,31 +5,32 @@ package org.jetbrains.kotlin.ir.backend.js.ir -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.types.createType -import org.jetbrains.kotlin.ir.types.getClass -import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl -import org.jetbrains.kotlin.ir.util.SymbolTable -import org.jetbrains.kotlin.ir.util.createDispatchReceiverParameter -import org.jetbrains.kotlin.ir.util.endOffset -import org.jetbrains.kotlin.ir.util.startOffset import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -import org.jetbrains.kotlin.resolve.OverridingStrategy -import org.jetbrains.kotlin.resolve.OverridingUtil -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes -import java.lang.reflect.Proxy +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.Variance object JsIrBuilder { @@ -57,27 +58,108 @@ object JsIrBuilder { fun buildThrow(type: IrType, value: IrExpression) = IrThrowImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, value) - fun buildValueParameter(symbol: IrValueParameterSymbol, type: IrType? = null) = - IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol, type ?: symbol.owner.type, null) + fun buildValueParameter(name: String = "tmp", index: Int, type: IrType) = buildValueParameter(Name.identifier(name), index, type) - fun buildFunction(symbol: IrSimpleFunctionSymbol, returnType: IrType) = - IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol).apply { - this.returnType = returnType + fun buildValueParameter(name: Name, index: Int, type: IrType, origin: IrDeclarationOrigin = SYNTHESIZED_DECLARATION): IrValueParameter { + val descriptor = WrappedValueParameterDescriptor() + return IrValueParameterImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + origin, + IrValueParameterSymbolImpl(descriptor), + name, + index, + type, + null, + false, + false + ).also { + descriptor.bind(it) } + } + + fun buildTypeParameter(name: Name, index: Int, isReified: Boolean, variance: Variance = Variance.INVARIANT): IrTypeParameter { + val descriptor = WrappedTypeParameterDescriptor() + return IrTypeParameterImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + SYNTHESIZED_DECLARATION, + IrTypeParameterSymbolImpl(descriptor), + name, + index, + isReified, + variance + ).also { + descriptor.bind(it) + } + } + + fun buildFunction( + name: String, + visibility: Visibility = Visibilities.PUBLIC, + modality: Modality = Modality.FINAL, + isInline: Boolean = false, + isExternal: Boolean = false, + isTailrec: Boolean = false, + isSuspend: Boolean = false, + origin: IrDeclarationOrigin = SYNTHESIZED_DECLARATION + ) = JsIrBuilder.buildFunction(Name.identifier(name), visibility, modality, isInline, isExternal, isTailrec, isSuspend, origin) + + fun buildFunction( + name: Name, + visibility: Visibility = Visibilities.PUBLIC, + modality: Modality = Modality.FINAL, + isInline: Boolean = false, + isExternal: Boolean = false, + isTailrec: Boolean = false, + isSuspend: Boolean = false, + origin: IrDeclarationOrigin = SYNTHESIZED_DECLARATION + ): IrSimpleFunction { + val descriptor = WrappedSimpleFunctionDescriptor() + return IrFunctionImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + origin, + IrSimpleFunctionSymbolImpl(descriptor), + name, + visibility, + modality, + isInline, + isExternal, + isTailrec, + isSuspend + ).also { descriptor.bind(it) } + } fun buildGetObjectValue(type: IrType, classSymbol: IrClassSymbol) = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, classSymbol) fun buildGetClass(expression: IrExpression, type: IrType) = IrGetClassImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, expression) - fun buildGetValue(symbol: IrValueSymbol) = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol.owner.type, symbol, SYNTHESIZED_STATEMENT) + fun buildGetValue(symbol: IrValueSymbol) = + IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol.owner.type, symbol, SYNTHESIZED_STATEMENT) + fun buildSetVariable(symbol: IrVariableSymbol, value: IrExpression, type: IrType) = IrSetVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, value, SYNTHESIZED_STATEMENT) fun buildGetField(symbol: IrFieldSymbol, receiver: IrExpression?, superQualifierSymbol: IrClassSymbol? = null, type: IrType? = null) = - IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, type ?: symbol.owner.type, receiver, SYNTHESIZED_STATEMENT, superQualifierSymbol) + IrGetFieldImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + symbol, + type ?: symbol.owner.type, + receiver, + SYNTHESIZED_STATEMENT, + superQualifierSymbol + ) - fun buildSetField(symbol: IrFieldSymbol, receiver: IrExpression?, value: IrExpression, type: IrType, superQualifierSymbol: IrClassSymbol? = null) = + fun buildSetField( + symbol: IrFieldSymbol, + receiver: IrExpression?, + value: IrExpression, + type: IrType, + superQualifierSymbol: IrClassSymbol? = null + ) = IrSetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, receiver, value, type, SYNTHESIZED_STATEMENT, superQualifierSymbol) fun buildBlockBody(statements: List) = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, statements) @@ -92,9 +174,30 @@ object JsIrBuilder { fun buildFunctionReference(type: IrType, symbol: IrFunctionSymbol) = IrFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, symbol.descriptor, 0, null) - fun buildVar(symbol: IrVariableSymbol, initializer: IrExpression? = null, type: IrType) = - IrVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol, type) - .apply { this.initializer = initializer } + fun buildVar( + type: IrType, + name: String = "tmp", + isVar: Boolean = false, + isConst: Boolean = false, + isLateinit: Boolean = false, + initializer: IrExpression? = null + ): IrVariable { + val descriptor = WrappedVariableDescriptor() + return IrVariableImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + SYNTHESIZED_DECLARATION, + IrVariableSymbolImpl(descriptor), + Name.identifier(name), + type, + isVar, + isConst, + isLateinit + ).also { + descriptor.bind(it) + it.initializer = initializer + } + } fun buildBreak(type: IrType, loop: IrLoop) = IrBreakImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop) fun buildContinue(type: IrType, loop: IrLoop) = IrContinueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop) @@ -135,7 +238,6 @@ object JsIrBuilder { fun buildCatch(ex: IrVariable, block: IrBlockImpl) = IrCatchImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, ex, block) } - object SetDeclarationsParentVisitor : IrElementVisitor { override fun visitElement(element: IrElement, data: IrDeclarationParent) { if (element !is IrDeclarationParent) { @@ -149,21 +251,6 @@ object SetDeclarationsParentVisitor : IrElementVisitor) { - declarations.forEach { this.addChild(it) } -} - fun IrDeclarationContainer.addChild(declaration: IrDeclaration) { this.declarations += declaration declaration.accept(SetDeclarationsParentVisitor, this) @@ -172,236 +259,9 @@ fun IrDeclarationContainer.addChild(declaration: IrDeclaration) { fun IrClass.simpleFunctions(): List = this.declarations.flatMap { when (it) { is IrSimpleFunction -> listOf(it) - is IrProperty -> listOfNotNull(it.getter as IrSimpleFunction?, it.setter as IrSimpleFunction?) + is IrProperty -> listOfNotNull(it.getter, it.setter) else -> emptyList() } } -fun IrClass.setSuperSymbols(superTypes: List) { - val supers = superTypes.map { it.getClass()!! } - assert(this.superDescriptors().toSet() == supers.map { it.descriptor }.toSet()) - assert(this.superTypes.isEmpty()) - this.superTypes += superTypes - val superMembers = supers.flatMap { - it.simpleFunctions() - }.associateBy { it.descriptor } - - this.simpleFunctions().forEach { - assert(it.overriddenSymbols.isEmpty()) - - it.descriptor.overriddenDescriptors.mapTo(it.overriddenSymbols) { - val superMember = superMembers[it.original] ?: error(it.original) - superMember.symbol - } - } -} - -fun IrSimpleFunction.setOverrides(symbolTable: SymbolTable) { - assert(this.overriddenSymbols.isEmpty()) - - this.descriptor.overriddenDescriptors.mapTo(this.overriddenSymbols) { - symbolTable.referenceSimpleFunction(it.original) - } -} - - -private fun IrClass.superDescriptors() = - this.descriptor.typeConstructor.supertypes.map { it.constructor.declarationDescriptor as ClassDescriptor } - -fun IrClass.setSuperSymbols(symbolTable: SymbolTable) { - assert(this.superTypes.isEmpty()) - this.descriptor.typeConstructor.supertypes.mapTo(this.superTypes) { symbolTable.translateErased(it) } - - this.simpleFunctions().forEach { - it.setOverrides(symbolTable) - } -} - -private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int = - descriptor.startOffset ?: this.startOffset - -private fun IrElement.innerEndOffset(descriptor: DeclarationDescriptorWithSource): Int = - descriptor.endOffset ?: this.endOffset - -fun IrFunction.createParameterDeclarations(symbolTable: SymbolTable) { - - fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl( - innerStartOffset(this), innerEndOffset(this), - IrDeclarationOrigin.DEFINED, - this, symbolTable.translateErased(this.type), - (this as? ValueParameterDescriptor)?.varargElementType?.let { symbolTable.translateErased(it) } - ).also { - it.parent = this@createParameterDeclarations - } - - dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.irValueParameter() - extensionReceiverParameter = descriptor.extensionReceiverParameter?.irValueParameter() - - assert(valueParameters.isEmpty()) - descriptor.valueParameters.mapTo(valueParameters) { it.irValueParameter() } - - assert(typeParameters.isEmpty()) - descriptor.typeParameters.mapTo(typeParameters) { - IrTypeParameterImpl( - innerStartOffset(it), innerEndOffset(it), - IrDeclarationOrigin.DEFINED, - it - ).also { typeParameter -> - typeParameter.parent = this - typeParameter.descriptor.upperBounds.mapTo(typeParameter.superTypes, symbolTable::translateErased) - } - } -} - -private fun createFakeOverride( - descriptor: CallableMemberDescriptor, - startOffset: Int, - endOffset: Int, - symbolTable: SymbolTable -): IrDeclaration { - - fun FunctionDescriptor.createFunction(): IrSimpleFunction = IrFunctionImpl( - startOffset, endOffset, - IrDeclarationOrigin.FAKE_OVERRIDE, this - ).apply { - returnType = symbolTable.translateErased(this@createFunction.returnType!!) - createParameterDeclarations(symbolTable) - } - - return when (descriptor) { - is FunctionDescriptor -> descriptor.createFunction() - is PropertyDescriptor -> - IrPropertyImpl(startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, descriptor).apply { - // TODO: add field if getter is missing? - getter = descriptor.getter?.createFunction() as IrSimpleFunction? - setter = descriptor.setter?.createFunction() as IrSimpleFunction? - } - else -> TODO(descriptor.toString()) - } -} - -private fun createFakeOverride( - descriptor: CallableMemberDescriptor, - overriddenDeclarations: List, - irClass: IrClass -): IrDeclaration { - - // TODO: this function doesn't substitute types. - fun IrSimpleFunction.copyFake(descriptor: FunctionDescriptor): IrSimpleFunction = IrFunctionImpl( - irClass.startOffset, irClass.endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, descriptor - ).also { - it.returnType = returnType - it.parent = irClass - it.createDispatchReceiverParameter() - - it.extensionReceiverParameter = this.extensionReceiverParameter?.let { - IrValueParameterImpl( - it.startOffset, - it.endOffset, - IrDeclarationOrigin.DEFINED, - it.descriptor.extensionReceiverParameter!!, - it.type, - null - ) - } - - this.valueParameters.mapTo(it.valueParameters) { oldParameter -> - IrValueParameterImpl( - oldParameter.startOffset, - oldParameter.endOffset, - IrDeclarationOrigin.DEFINED, - it.descriptor.valueParameters[oldParameter.index], - oldParameter.type, - (oldParameter as? IrValueParameter)?.varargElementType - ) - } - - this.typeParameters.mapTo(it.typeParameters) { oldParameter -> - IrTypeParameterImpl( - irClass.startOffset, - irClass.endOffset, - IrDeclarationOrigin.DEFINED, - it.descriptor.typeParameters[oldParameter.index] - ).apply { - superTypes += oldParameter.superTypes - } - } - } - - val copiedDeclaration = overriddenDeclarations.first() - - return when (copiedDeclaration) { - is IrSimpleFunction -> copiedDeclaration.copyFake(descriptor as FunctionDescriptor) - is IrProperty -> IrPropertyImpl( - irClass.startOffset, - irClass.endOffset, - IrDeclarationOrigin.FAKE_OVERRIDE, - descriptor as PropertyDescriptor - ).apply { - parent = irClass - getter = copiedDeclaration.getter?.copyFake(descriptor.getter!!) - setter = copiedDeclaration.setter?.copyFake(descriptor.setter!!) - } - else -> error(copiedDeclaration) - } -} - -fun IrClass.setSuperSymbolsAndAddFakeOverrides(superTypes: List) { - val overriddenSuperMembers = this.declarations.map { it.descriptor } - .filterIsInstance().flatMap { it.overriddenDescriptors.map { it.original } }.toSet() - - val unoverriddenSuperMembers = superTypes.map { it.getClass()!! }.flatMap { - it.declarations.filter { it.descriptor !in overriddenSuperMembers }.mapNotNull { - when (it) { - is IrSimpleFunction -> it.descriptor to it - is IrProperty -> it.descriptor to it - else -> null - } - } - }.toMap() - - val irClass = this - - val overridingStrategy = object : OverridingStrategy() { - override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) { - val overriddenDeclarations = - fakeOverride.overriddenDescriptors.map { unoverriddenSuperMembers[it]!! } - - assert(overriddenDeclarations.isNotEmpty()) - - irClass.declarations.add(createFakeOverride(fakeOverride, overriddenDeclarations, irClass)) - } - - override fun inheritanceConflict(first: CallableMemberDescriptor, second: CallableMemberDescriptor) { - error("inheritance conflict in synthesized class ${irClass.descriptor}:\n $first\n $second") - } - - override fun overrideConflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) { - error("override conflict in synthesized class ${irClass.descriptor}:\n $fromSuper\n $fromCurrent") - } - } - - unoverriddenSuperMembers.keys.groupBy { it.name }.forEach { (name, members) -> - OverridingUtil.generateOverridesInFunctionGroup( - name, - members, - emptyList(), - this.descriptor, - overridingStrategy - ) - } - - this.setSuperSymbols(superTypes) -} - -inline fun stub(name: String): T { - return Proxy.newProxyInstance(T::class.java.classLoader, arrayOf(T::class.java)) { - _ /* proxy */, method, _ /* methodArgs */ -> - if (method.name == "toString" && method.parameterCount == 0) { - "${T::class.simpleName} stub for $name" - } else { - error("${T::class.simpleName}.${method.name} is not supported for $name") - } - } as T -} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt index 73dc54c3101..1fe81f8e871 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt @@ -10,9 +10,6 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder -import org.jetbrains.kotlin.ir.backend.js.symbols.initialize -import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* @@ -47,27 +44,24 @@ class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContaine fun lower(irField: IrField, container: IrDeclarationContainer): List { irField.initializer?.apply { - val initFnSymbol = JsSymbolBuilder.buildSimpleFunction( - (container as IrSymbolOwner).symbol.descriptor, - irField.name.asString() + "\$init\$" - ).initialize(returnType = expression.type) + val initFunction = JsIrBuilder.buildFunction(irField.name.asString() + "\$init\$", irField.visibility).also { + it.parent = container + it.returnType = expression.type + } - - val returnStatement = JsIrBuilder.buildReturn(initFnSymbol, expression, nothingType) + val returnStatement = JsIrBuilder.buildReturn(initFunction.symbol, expression, nothingType) val newBody = IrBlockBodyImpl(expression.startOffset, expression.endOffset).apply { statements += returnStatement } - val initFn = JsIrBuilder.buildFunction(initFnSymbol, expression.type).apply { - body = newBody - } + initFunction.body = newBody - lower(initFn) + lower(initFunction) val lastStatement = newBody.statements.last() if (lastStatement != returnStatement || (lastStatement as IrReturn).value != expression) { - expression = JsIrBuilder.buildCall(initFnSymbol, expression.type) - return listOf(initFn, irField) + expression = JsIrBuilder.buildCall(initFunction.symbol, expression.type) + return listOf(initFunction, irField) } } @@ -89,8 +83,7 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo private val unitType = context.irBuiltIns.unitType private val unitValue = JsIrBuilder.buildGetObjectValue(unitType, context.symbolTable.referenceClass(context.builtIns.unit)) - private val unreachableFunction = - JsSymbolBuilder.buildSimpleFunction(context.module, Namer.UNREACHABLE_NAME).initialize(returnType = nothingType) + private val unreachableFunction = context.intrinsics.unreachable private val booleanNotSymbol = context.irBuiltIns.booleanNotSymbol override fun visitFunction(declaration: IrFunction): IrStatement { @@ -107,8 +100,8 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo } } - private fun makeTempVar(type: IrType) = - JsSymbolBuilder.buildTempVar(function.symbol, type, "tmp\$dcms\$${tmpVarCounter++}", true) + private fun makeTempVar(type: IrType, init: IrExpression? = null) = + JsIrBuilder.buildVar(type, initializer = init, isVar = true).also { it.parent = function } private fun makeLoopLabel() = "\$l\$${tmpVarCounter++}" @@ -184,8 +177,7 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo if (receiverResult != null && valueResult != null) { val result = IrCompositeImpl(receiverResult.startOffset, expression.endOffset, unitType) val receiverValue = receiverResult.statements.last() as IrExpression - val tmp = makeTempVar(receiverResult.type) - val irVar = JsIrBuilder.buildVar(tmp, receiverValue, receiverResult.type) + val irVar = makeTempVar(receiverValue.type, receiverValue) val setValue = valueResult.statements.last() as IrExpression result.statements += receiverResult.statements.run { subList(0, lastIndex) } result.statements += irVar @@ -195,7 +187,7 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo startOffset, endOffset, symbol, - JsIrBuilder.buildGetValue(tmp), + JsIrBuilder.buildGetValue(irVar.symbol), setValue, type, origin, @@ -216,10 +208,9 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo assert(valueResult != null) val receiver = expression.receiver?.let { - val tmp = makeTempVar(it.type) - val irVar = JsIrBuilder.buildVar(tmp, it, it.type) + val irVar = makeTempVar(it.type, it) valueResult!!.statements.add(0, irVar) - JsIrBuilder.buildGetValue(tmp) + JsIrBuilder.buildGetValue(irVar.symbol) } return materializeLastExpression(valueResult!!) { @@ -420,11 +411,11 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo override fun visitSetField(expression: IrSetField) = expression.asExpression(unitValue) - override fun visitBreakContinue(jump: IrBreakContinue) = jump.asExpression(JsIrBuilder.buildCall(unreachableFunction, nothingType)) + override fun visitBreakContinue(jump: IrBreakContinue) = jump.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType)) - override fun visitThrow(expression: IrThrow) = expression.asExpression(JsIrBuilder.buildCall(unreachableFunction, nothingType)) + override fun visitThrow(expression: IrThrow) = expression.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType)) - override fun visitReturn(expression: IrReturn) = expression.asExpression(JsIrBuilder.buildCall(unreachableFunction, nothingType)) + override fun visitReturn(expression: IrReturn) = expression.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType)) override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression { expression.transformChildrenVoid(expressionTransformer) @@ -458,9 +449,9 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo val newArg = if (compositesLeft != 0) { if (value != null) { // TODO: do not wrap if value is pure (const, variable, etc) - val tmp = makeTempVar(value.type) - newStatements += JsIrBuilder.buildVar(tmp, value, value.type) - JsIrBuilder.buildGetValue(tmp) + val irVar = makeTempVar(value.type, value) + newStatements += irVar + JsIrBuilder.buildGetValue(irVar.symbol) } else value } else value @@ -568,18 +559,18 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo // tmp // ] override fun visitTry(aTry: IrTry): IrExpression { - val tmp = makeTempVar(aTry.type) + val irVar = makeTempVar(aTry.type) - val newTryResult = wrap(aTry.tryResult, tmp) + val newTryResult = wrap(aTry.tryResult, irVar.symbol) val newCatches = aTry.catches.map { - val newCatchBody = wrap(it.result, tmp) + val newCatchBody = wrap(it.result, irVar.symbol) IrCatchImpl(it.startOffset, it.endOffset, it.catchParameter, newCatchBody) } val newTry = aTry.run { IrTryImpl(startOffset, endOffset, unitType, newTryResult, newCatches, finallyExpression) } newTry.transformChildrenVoid(statementTransformer) - val newStatements = listOf(JsIrBuilder.buildVar(tmp, type = aTry.type), newTry, JsIrBuilder.buildGetValue(tmp)) + val newStatements = listOf(irVar, newTry, JsIrBuilder.buildGetValue(irVar.symbol)) return JsIrBuilder.buildComposite(aTry.type, newStatements) } @@ -616,22 +607,21 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo } if (hasComposites) { - val tmp = makeTempVar(expression.type) + val irVar = makeTempVar(expression.type) val newBranches = decomposedResults.map { (branch, condition, result) -> - val newResult = wrap(result, tmp) + val newResult = wrap(result, irVar.symbol) when (branch) { is IrElseBranch -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, newResult) else /* IrBranch */ -> IrBranchImpl(branch.startOffset, branch.endOffset, condition, newResult) } } - val irVar = JsIrBuilder.buildVar(tmp, type = expression.type) val newWhen = expression.run { IrWhenImpl(startOffset, endOffset, unitType, origin, newBranches) } .transform(statementTransformer, null) // deconstruct into `if-else` chain - return JsIrBuilder.buildComposite(expression.type, listOf(irVar, newWhen, JsIrBuilder.buildGetValue(tmp))) + return JsIrBuilder.buildComposite(expression.type, listOf(irVar, newWhen, JsIrBuilder.buildGetValue(irVar.symbol))) } else { val newBranches = decomposedResults.map { (branch, condition, result) -> when (branch) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt index 36c51015cf7..3f2b1fa82d0 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt @@ -19,25 +19,22 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.bridges.FunctionHandle import org.jetbrains.kotlin.backend.common.bridges.generateBridges +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.isSuspend import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.isStatic import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.types.toKotlinType -import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.isInterface import org.jetbrains.kotlin.ir.util.isReal import org.jetbrains.kotlin.ir.util.parentAsClass @@ -49,29 +46,28 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils // Example: for given class hierarchy // // class C { -// fun foo(t: T) = ... // bridge +// fun foo(t: T) = ... // } // // class D : C { -// override fun foo(t: Int) = impl // delegate to -// } -// -// class E : D { -// fun foo(t: Int) // function +// override fun foo(t: Int) = impl // } // // it adds method D that delegates generic calls to implementation: // -// class E : D { -// fun foo(t: Any?) = foo(t as Int) // bridgeDescriptorForIrFunction +// class D : C { +// override fun foo(t: Int) = impl +// fun foo(t: Any?) = foo(t as Int) // Constructed bridge // } // class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) { irClass.declarations + .asSequence() .filterIsInstance() .filter { !it.isStatic } + .toList() .forEach { generateBridges(it, irClass) } irClass.declarations @@ -112,29 +108,27 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass { bridge: IrSimpleFunction, delegateTo: IrSimpleFunction ): IrFunction { - val containingClass = function.parentAsClass.descriptor - - val bridgeDescriptorForIrFunction = SimpleFunctionDescriptorImpl.create( - containingClass, - Annotations.EMPTY, // TODO: Should we copy annotations? - bridge.name, - CallableMemberDescriptor.Kind.SYNTHESIZED, - function.descriptor.source - ) - - bridgeDescriptorForIrFunction.initialize( - bridge.descriptor.extensionReceiverParameter?.copy(bridge.descriptor), containingClass.thisAsReceiverParameter, - bridge.descriptor.typeParameters, - bridge.descriptor.valueParameters.map { it.copy(bridgeDescriptorForIrFunction, it.name, it.index) }, - bridge.descriptor.returnType, bridge.descriptor.modality, function.visibility - ) - - bridgeDescriptorForIrFunction.isSuspend = bridge.descriptor.isSuspend // TODO: Support offsets for debug info - val irFunction = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, bridgeDescriptorForIrFunction) - irFunction.createParameterDeclarations() - irFunction.returnType = bridge.returnType + val irFunction = JsIrBuilder.buildFunction( + bridge.name, + bridge.visibility, + bridge.modality, // TODO: should copy modality? + bridge.isInline, + bridge.isExternal, + bridge.isTailrec, + bridge.isSuspend, + IrDeclarationOrigin.BRIDGE + ).apply { + + dispatchReceiverParameter = bridge.dispatchReceiverParameter?.copyTo(this) + extensionReceiverParameter = bridge.extensionReceiverParameter?.copyTo(this) + typeParameters += bridge.typeParameters + valueParameters += bridge.valueParameters.map { p -> p.copyTo(this) } + annotations += bridge.annotations + returnType = bridge.returnType + parent = delegateTo.parent + } context.createIrBuilder(irFunction.symbol).irBlockBody(irFunction) { val call = irCall(delegateTo.symbol) @@ -143,7 +137,7 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass { call.extensionReceiver = irCastIfNeeded(irGet(it), delegateTo.extensionReceiverParameter!!.type) } - val toTake = irFunction.valueParameters.size - if (call.descriptor.isSuspend xor irFunction.descriptor.isSuspend) 1 else 0 + val toTake = irFunction.valueParameters.size - if (call.isSuspend xor irFunction.isSuspend) 1 else 0 irFunction.valueParameters.subList(0, toTake).mapIndexed { i, valueParameter -> call.putValueArgument(i, irCastIfNeeded(irGet(valueParameter), delegateTo.valueParameters[i].type)) @@ -191,6 +185,7 @@ class FunctionAndSignature(val function: IrSimpleFunction) { private val signature = Signature( function.name, + // TODO: should kotlinTypes be used here? function.extensionReceiverParameter?.type?.toKotlinType()?.toString(), function.valueParameters.map { it.type.toKotlinType().toString() } ) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt index a0c7c44e3f3..cdb356f1ab8 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt @@ -6,29 +6,23 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass -import org.jetbrains.kotlin.backend.common.lower.copyAsValueParameter -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder -import org.jetbrains.kotlin.ir.backend.js.symbols.initialize import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.toIrType import org.jetbrains.kotlin.ir.visitors.* -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe // TODO: generate $metadata$ property and fill it with corresponding KFunction/KProperty interface class CallableReferenceLowering(val context: JsIrBackendContext) { @@ -39,7 +33,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { val hasExtensionReceiver: Boolean ) - private val callableToGetterFunction = mutableMapOf() + private val callableToGetterFunction = mutableMapOf() private val collectedReferenceMap = mutableMapOf() private val callableNameConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KCALLABLE_NAME) @@ -83,7 +77,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { } override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference) { - collectedReferenceMap[makeCallableKey(expression.getter!!.owner, expression)] = expression + collectedReferenceMap[makeCallableKey(expression.getter.owner, expression)] = expression } override fun visitElement(element: IrElement) { @@ -138,9 +132,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { } override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression { - return callableToGetterFunction[makeCallableKey(expression.getter!!.owner, expression)]!!.let { - redirectToFunction(expression, it) - } + return redirectToFunction(expression, callableToGetterFunction[makeCallableKey(expression.getter.owner, expression)]!!) } private fun redirectToFunction(callable: IrCallableReference, newTarget: IrFunction) = @@ -164,28 +156,37 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { } } - private fun createFunctionClosureGetterName(descriptor: CallableDescriptor) = createHelperFunctionName(descriptor, "KReferenceGet") - private fun createPropertyClosureGetterName(descriptor: CallableDescriptor) = createHelperFunctionName(descriptor, "KPropertyGet") - private fun createClosureInstanceName(descriptor: CallableDescriptor) = createHelperFunctionName(descriptor, "KReferenceClosure") + private fun createFunctionClosureGetterName(declaration: IrDeclaration) = createHelperFunctionName(declaration, "KReferenceGet") + private fun createPropertyClosureGetterName(declaration: IrDeclaration) = createHelperFunctionName(declaration, "KPropertyGet") + private fun createClosureInstanceName(declaration: IrDeclaration) = createHelperFunctionName(declaration, "KReferenceClosure") - private fun createHelperFunctionName(descriptor: CallableDescriptor, suffix: String): String { + private fun createHelperFunctionName(declaration: IrDeclaration, suffix: String): String { val nameBuilder = StringBuilder() - if (descriptor is ClassConstructorDescriptor) { - nameBuilder.append(descriptor.constructedClass.fqNameSafe) + if (declaration is IrConstructor) { + val klass = declaration.parent as IrClass + nameBuilder.append(klass.name.asString()) nameBuilder.append('_') } - nameBuilder.append(descriptor.name) + + when (declaration) { + is IrFunction -> nameBuilder.append(declaration.name) + is IrProperty -> nameBuilder.append(declaration.name) + is IrVariable -> nameBuilder.append(declaration.name) + else -> TODO("Unexpected declaration type") + } + nameBuilder.append('_') nameBuilder.append(suffix) return nameBuilder.toString() } - private fun getReferenceName(descriptor: CallableDescriptor): String { - if (descriptor is ClassConstructorDescriptor) { - return descriptor.constructedClass.name.identifier - } - return descriptor.name.identifier + private fun getReferenceName(declaration: IrDeclaration) = when (declaration) { + is IrConstructor -> (declaration.parent as IrClass).name.identifier + is IrProperty -> declaration.name.identifier + is IrSimpleFunction -> declaration.name.asString() + is IrVariable -> declaration.name.asString().replace("\$delegate", "") + else -> TODO("Unexpected declaration type") } private fun lowerKFunctionReference(declaration: IrFunction, functionReference: IrFunctionReference): List { @@ -203,21 +204,23 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { // KFunctionN, arguments.size = N + 1 - val refGetFunction = buildGetFunction(declaration, functionReference, createFunctionClosureGetterName(declaration.descriptor)) + val refGetFunction = buildGetFunction(declaration, functionReference, createFunctionClosureGetterName(declaration)) val refClosureFunction = buildClosureFunction(declaration, refGetFunction, functionReference) val additionalDeclarations = generateGetterBodyWithGuard(refGetFunction) { val irClosureReference = JsIrBuilder.buildFunctionReference(functionReference.type, refClosureFunction.symbol) - val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, irClosureReference.type) - val irVar = JsIrBuilder.buildVar(irVarSymbol, irClosureReference, type = irClosureReference.type) + + val irVar = JsIrBuilder.buildVar(irClosureReference.type, initializer = irClosureReference).also { + it.parent = refGetFunction + } // TODO: fill other fields of callable reference (returnType, parameters, isFinal, etc.) val irSetName = JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { - putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) + putValueArgument(0, JsIrBuilder.buildGetValue(irVar.symbol)) putValueArgument(1, callableNameConst) - putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(declaration.descriptor))) + putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(declaration))) } - Pair(listOf(irVar, irSetName), irVarSymbol) + Pair(listOf(irVar, irSetName), irVar.symbol) } @@ -226,7 +229,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { return additionalDeclarations + listOf(refGetFunction) } - private fun lowerKPropertyReference(getterDeclaration: IrFunction, propertyReference: IrPropertyReference): List { + private fun lowerKPropertyReference(getterDeclaration: IrSimpleFunction, propertyReference: IrPropertyReference): List { // transform // x = Foo::bar -> // x = Foo_bar_KreferenceGet() : KPropertyN { @@ -246,7 +249,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { // return $cache$ // } - val getterName = createPropertyClosureGetterName(propertyReference.descriptor) + val getterName = createPropertyClosureGetterName(getterDeclaration.correspondingProperty!!) val refGetFunction = buildGetFunction(propertyReference.getter!!.owner, propertyReference, getterName) val getterFunction = propertyReference.getter?.let { buildClosureFunction(it.owner, refGetFunction, propertyReference) }!! @@ -256,23 +259,26 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { val statements = mutableListOf() val getterFunctionType = context.builtIns.getFunction(getterFunction.valueParameters.size + 1) - val type = getterFunctionType.toIrType() + val type = getterFunctionType.toIrType(symbolTable = context.symbolTable) val irGetReference = JsIrBuilder.buildFunctionReference(type, getterFunction.symbol) - val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, type) + val irVar = JsIrBuilder.buildVar(type, initializer = irGetReference).also { it.parent = refGetFunction } - statements += JsIrBuilder.buildVar(irVarSymbol, irGetReference, type = type) + statements += irVar statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { - putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) + putValueArgument(0, JsIrBuilder.buildGetValue(irVar.symbol)) putValueArgument(1, getterConst) - putValueArgument(2, JsIrBuilder.buildGetValue(irVarSymbol)) + putValueArgument(2, JsIrBuilder.buildGetValue(irVar.symbol)) } if (setterFunction != null) { val setterFunctionType = context.builtIns.getFunction(setterFunction.valueParameters.size + 1) - val irSetReference = JsIrBuilder.buildFunctionReference(setterFunctionType.toIrType(), setterFunction.symbol) + val irSetReference = JsIrBuilder.buildFunctionReference( + setterFunctionType.toIrType(symbolTable = context.symbolTable), + setterFunction.symbol + ) statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { - putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) + putValueArgument(0, JsIrBuilder.buildGetValue(irVar.symbol)) putValueArgument(1, setterConst) putValueArgument(2, irSetReference) } @@ -280,12 +286,18 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { // TODO: fill other fields of callable reference (returnType, parameters, isFinal, etc.) statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { - putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) + putValueArgument(0, JsIrBuilder.buildGetValue(irVar.symbol)) putValueArgument(1, callableNameConst) - putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(propertyReference.descriptor))) + putValueArgument( + 2, + JsIrBuilder.buildString( + context.irBuiltIns.stringType, + getReferenceName(getterDeclaration.correspondingProperty!!) + ) + ) } - Pair(statements, irVarSymbol) + Pair(statements, irVar.symbol) } callableToGetterFunction[makeCallableKey(getterDeclaration, propertyReference)] = refGetFunction @@ -308,7 +320,8 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { // return $cache$ // } - val getterName = createPropertyClosureGetterName(propertyReference.descriptor) + val declaration = propertyReference.delegate.owner + val getterName = createPropertyClosureGetterName(declaration) val refGetFunction = buildGetFunction(propertyReference.getter.owner, propertyReference, getterName) val getterFunction = buildClosureFunction(context.irBuiltIns.throwIseFun, refGetFunction, propertyReference) @@ -316,11 +329,12 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { val statements = mutableListOf() val getterFunctionType = context.builtIns.getFunction(getterFunction.valueParameters.size + 1) - val type = getterFunctionType.toIrType() + val type = getterFunctionType.toIrType(symbolTable = context.symbolTable) val irGetReference = JsIrBuilder.buildFunctionReference(type, getterFunction.symbol) - val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, type) + val irVar = JsIrBuilder.buildVar(type = type, initializer = irGetReference).also { it.parent = refGetFunction } + val irVarSymbol = irVar.symbol - statements += JsIrBuilder.buildVar(irVarSymbol, irGetReference, type = type) + statements += irVar statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) @@ -331,7 +345,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) putValueArgument(1, callableNameConst) - putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(propertyReference.descriptor))) + putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(declaration))) } Pair(statements, irVarSymbol) @@ -359,16 +373,18 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { // val cacheName = "${getterFunction.name}_${Namer.KCALLABLE_CACHE_SUFFIX}" val type = getterFunction.returnType - val cacheVarSymbol = - JsSymbolBuilder.buildVar(getterFunction.descriptor.containingDeclaration, type, cacheName, true) val irNull = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType) - val irCacheDeclaration = JsIrBuilder.buildVar(cacheVarSymbol, irNull, type = type) - val irCacheValue = JsIrBuilder.buildGetValue(cacheVarSymbol) + val cacheVar = JsIrBuilder.buildVar(type, cacheName, true, initializer = irNull).also { + it.parent = getterFunction.parent + } + + val irCacheValue = JsIrBuilder.buildGetValue(cacheVar.symbol) val irIfCondition = JsIrBuilder.buildCall(context.irBuiltIns.eqeqSymbol).apply { putValueArgument(0, irCacheValue) putValueArgument(1, irNull) } - val irSetCache = JsIrBuilder.buildSetVariable(cacheVarSymbol, JsIrBuilder.buildGetValue(varSymbol), context.irBuiltIns.unitType) + val irSetCache = + JsIrBuilder.buildSetVariable(cacheVar.symbol, JsIrBuilder.buildGetValue(varSymbol), context.irBuiltIns.unitType) val thenStatements = mutableListOf().apply { addAll(bodyStatements) add(irSetCache) @@ -377,7 +393,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { val irIfNode = JsIrBuilder.buildIfElse(context.irBuiltIns.unitType, irIfCondition, irThenBranch) statements += irIfNode returnValue = irCacheValue - returnStatements = listOf(irCacheDeclaration) + returnStatements = listOf(cacheVar) } else { statements += bodyStatements returnValue = JsIrBuilder.buildGetValue(varSymbol) @@ -393,23 +409,25 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { private fun generateSignatureForClosure( callable: IrFunction, getter: IrFunction, - closure: IrSimpleFunctionSymbol, + closure: IrSimpleFunction, reference: IrCallableReference - ): List { - val result = mutableListOf() + ): List { + val result = mutableListOf() if (callable.dispatchReceiverParameter != null && reference.dispatchReceiver == null) { - result.add(JsSymbolBuilder.buildValueParameter(closure, result.size, callable.dispatchReceiverParameter!!.type)) + val dispatch = callable.dispatchReceiverParameter!! + result.add(JsIrBuilder.buildValueParameter(dispatch.name, result.size, dispatch.type).also { it.parent = closure }) } if (callable.extensionReceiverParameter != null && reference.extensionReceiver == null) { - result.add(JsSymbolBuilder.buildValueParameter(closure, result.size, callable.extensionReceiverParameter!!.type)) + val ext = callable.extensionReceiverParameter!! + result.add(JsIrBuilder.buildValueParameter(ext.name, result.size, ext.type).also { it.parent = closure }) } for (i in getter.valueParameters.size until callable.valueParameters.size) { val param = callable.valueParameters[i] - val paramName = param.name.run { if (!isSpecial) identifier else null } - result += JsSymbolBuilder.buildValueParameter(closure, result.size, param.type, paramName) + val paramName = param.name.run { if (!isSpecial) identifier else "p$i" } + result += JsIrBuilder.buildValueParameter(paramName, result.size, param.type).also { it.parent = closure } } return result @@ -433,36 +451,44 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { // The `getter` function takes only closure parameters val receivers = mutableListOf() if (reference.dispatchReceiver != null) { - receivers += declaration.dispatchReceiverParameter!! + if (declaration.dispatchReceiverParameter != null) { + receivers += declaration.dispatchReceiverParameter!! + } } if (reference.extensionReceiver != null) { - receivers += declaration.extensionReceiverParameter!! + if (declaration.extensionReceiverParameter != null) { + receivers += declaration.extensionReceiverParameter!! + } } val getterValueParameters = receivers + declaration.valueParameters.dropLast(kFunctionValueParamsCount) - val refGetSymbol = JsSymbolBuilder.buildSimpleFunction(declaration.descriptor.containingDeclaration, getterName).apply { - initialize( - valueParameters = getterValueParameters.mapIndexed { i, p -> p.descriptor.copyAsValueParameter(descriptor, i) }, - returnType = callableType - ) - } + val refGetDeclaration = JsIrBuilder.buildFunction(getterName, declaration.visibility) - return JsIrBuilder.buildFunction(refGetSymbol, callableType).apply { - for (i in 0 until getterValueParameters.size) { - val p = getterValueParameters[i] - valueParameters += - IrValueParameterImpl( - p.startOffset, - p.endOffset, - p.origin, - refGetSymbol.descriptor.valueParameters[i], - p.type, - p.varargElementType - ) + refGetDeclaration.parent = declaration.parent + refGetDeclaration.returnType = callableType + + for ((i, p) in getterValueParameters.withIndex()) { + val descriptor = WrappedValueParameterDescriptor() + refGetDeclaration.valueParameters += IrValueParameterImpl( + p.startOffset, + p.endOffset, + p.origin, + IrValueParameterSymbolImpl(descriptor), + p.name, + i, + p.type, + p.varargElementType, + p.isCrossinline, + p.isNoinline + ).also { + descriptor.bind(it) + it.parent = refGetDeclaration } } + + return refGetDeclaration } private fun buildClosureFunction( @@ -470,23 +496,16 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { refGetFunction: IrSimpleFunction, reference: IrCallableReference ): IrFunction { - val closureName = createClosureInstanceName(declaration.descriptor) - val refClosureSymbol = JsSymbolBuilder.buildSimpleFunction(refGetFunction.descriptor, closureName) + val closureName = createClosureInstanceName(declaration) + val refClosureDeclaration = JsIrBuilder.buildFunction(closureName, Visibilities.LOCAL).also { it.parent = refGetFunction } // the params which are passed to closure - val closureParamSymbols = generateSignatureForClosure(declaration, refGetFunction, refClosureSymbol, reference) - val closureParamDescriptors = closureParamSymbols.map { it.descriptor as ValueParameterDescriptor } - + val closureParamDeclarations = generateSignatureForClosure(declaration, refGetFunction, refClosureDeclaration, reference) + val closureParamSymbols = closureParamDeclarations.map { it.symbol } val returnType = declaration.returnType - refClosureSymbol.initialize(valueParameters = closureParamDescriptors, returnType = returnType) - val closureFunction = JsIrBuilder.buildFunction(refClosureSymbol, returnType) - - for (param in closureParamSymbols) { - // TODO always take type from param - val type = if (param.isBound) param.owner.type else context.irBuiltIns.anyType - closureFunction.valueParameters += JsIrBuilder.buildValueParameter(param, type) - } + refClosureDeclaration.valueParameters += closureParamDeclarations + refClosureDeclaration.returnType = returnType val irCall = JsIrBuilder.buildCall(declaration.symbol, type = returnType) @@ -515,10 +534,10 @@ class CallableReferenceLowering(val context: JsIrBackendContext) { irCall.putValueArgument(j++, JsIrBuilder.buildGetValue(closureParamSymbols[i])) } - val irClosureReturn = JsIrBuilder.buildReturn(closureFunction.symbol, irCall, context.irBuiltIns.nothingType) + val irClosureReturn = JsIrBuilder.buildReturn(refClosureDeclaration.symbol, irCall, context.irBuiltIns.nothingType) - closureFunction.body = JsIrBuilder.buildBlockBody(listOf(irClosureReturn)) + refClosureDeclaration.body = JsIrBuilder.buildBlockBody(listOf(irClosureReturn)) - return closureFunction + return refClosureDeclaration } } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/EnumClassLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/EnumClassLowering.kt index 911d44e1b8e..17fee69e38d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/EnumClassLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/EnumClassLowering.kt @@ -7,20 +7,16 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor +import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom 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.descriptors.Visibilities -import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder -import org.jetbrains.kotlin.ir.backend.js.symbols.initialize -import org.jetbrains.kotlin.ir.backend.js.utils.createValueParameter import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol @@ -207,7 +203,7 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass: } private fun createGetEntryInstanceFuns( - initEntryInstancesFun: IrFunctionImpl, + initEntryInstancesFun: IrSimpleFunction, entryInstances: List ) = enumEntries.mapIndexed { index, enumEntry -> buildFunction( @@ -305,41 +301,31 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass: } private fun transformEnumConstructor(enumConstructor: IrConstructor, enumClass: IrClass): IrConstructor { - val loweredConstructorSymbol = lowerEnumConstructor(enumConstructor) + val loweredConstructorDescriptor = WrappedClassConstructorDescriptor() + val loweredConstructorSymbol = IrConstructorSymbolImpl(loweredConstructorDescriptor) + return IrConstructorImpl( - enumConstructor.startOffset, enumConstructor.endOffset, enumConstructor.origin, + enumConstructor.startOffset, + enumConstructor.endOffset, + enumConstructor.origin, loweredConstructorSymbol, - enumConstructor.body // will be transformed later + enumConstructor.name, + enumConstructor.visibility, + enumConstructor.isInline, + enumConstructor.isExternal, + enumConstructor.isPrimary ).apply { + loweredConstructorDescriptor.bind(this) parent = enumClass returnType = enumConstructor.returnType - createParameterDeclarations() + valueParameters += JsIrBuilder.buildValueParameter("name", 0, context.irBuiltIns.stringType).also { it.parent = this } + valueParameters += JsIrBuilder.buildValueParameter("ordinal", 1, context.irBuiltIns.intType).also { it.parent = this } + copyParameterDeclarationsFrom(enumConstructor) + body = enumConstructor.body loweredEnumConstructors[enumConstructor.symbol] = this } } - private fun lowerEnumConstructor(enumConstructor: IrConstructor): IrConstructorSymbol { - val constructorDescriptor = enumConstructor.descriptor - val loweredConstructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized( - constructorDescriptor.containingDeclaration, - constructorDescriptor.annotations, - constructorDescriptor.isPrimary, - constructorDescriptor.source - ) - - val valueParameters = - listOf( - createValueParameter(loweredConstructorDescriptor, 0, "name", context.builtIns.stringType), - createValueParameter(loweredConstructorDescriptor, 1, "ordinal", context.builtIns.intType) - ) + constructorDescriptor.valueParameters.map { - it.copy(loweredConstructorDescriptor, it.name, it.index + 2) - } - - loweredConstructorDescriptor.initialize(valueParameters, Visibilities.PROTECTED) - loweredConstructorDescriptor.returnType = constructorDescriptor.returnType - return IrConstructorSymbolImpl(loweredConstructorDescriptor) - } - private fun findFunctionDescriptorForMemberWithSyntheticBodyKind(kind: IrSyntheticBodyKind): IrFunction = irClass.declarations.asSequence().filterIsInstance() .first { @@ -352,12 +338,10 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass: name: String, returnType: IrType = context.irBuiltIns.unitType, bodyBuilder: IrBlockBodyBuilder.() -> Unit - ) = JsIrBuilder.buildFunction( - symbol = JsSymbolBuilder.buildSimpleFunction(irClass.descriptor.containingDeclaration, name) - .initialize(returnType = returnType), - returnType = returnType - ).apply { - body = context.createIrBuilder(this.symbol).irBlockBody(this, bodyBuilder) + ) = JsIrBuilder.buildFunction(name).also { + it.returnType = returnType + it.parent = irClass + it.body = context.createIrBuilder(it.symbol).irBlockBody(it, bodyBuilder) } private fun IrEnumEntry.getNameExpression() = builder.irString(this.name.identifier) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt index a6dc3451a8e..616fe675ece 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt @@ -12,7 +12,9 @@ import org.jetbrains.kotlin.backend.common.utils.isSubtypeOfClass import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.utils.* +import org.jetbrains.kotlin.ir.backend.js.utils.ConversionNames +import org.jetbrains.kotlin.ir.backend.js.utils.Namer +import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFunction @@ -21,10 +23,9 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.originalKotlinType -import org.jetbrains.kotlin.ir.util.isNullConst +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.SimpleType @@ -226,7 +227,7 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL } put(Name.identifier("hashCode")) { call -> - if (call.symbol.owner.descriptor.isFakeOverriddenFromAny()) { + if (call.symbol.owner.isFakeOverriddenFromAny()) { if (call.isSuperToAny()) { irCall(call, intrinsics.jsGetObjectHashCode, dispatchReceiverAsFirstArgument = true) } else { @@ -315,25 +316,32 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL if (call is IrCall) { val symbol = call.symbol + val declaration = symbol.owner - if (symbol.isDynamic() || symbol.isEffectivelyExternal()) { + if (declaration.isDynamic || declaration.isEffectivelyExternal()) { when (call.origin) { IrStatementOrigin.GET_PROPERTY -> { - val fieldSymbol = IrFieldSymbolImpl((symbol.descriptor as PropertyAccessorDescriptor).correspondingProperty) + val fieldSymbol = context.symbolTable.lazyWrapper.referenceField( + (symbol.descriptor as PropertyAccessorDescriptor).correspondingProperty + ) return JsIrBuilder.buildGetField(fieldSymbol, call.dispatchReceiver, type = call.type) } // assignment to a property IrStatementOrigin.EQ -> { if (symbol.descriptor is PropertyAccessorDescriptor) { - val fieldSymbol = IrFieldSymbolImpl((symbol.descriptor as PropertyAccessorDescriptor).correspondingProperty) - return JsIrBuilder.buildSetField(fieldSymbol, call.dispatchReceiver, call.getValueArgument(0)!!, call.type) + val fieldSymbol = context.symbolTable.lazyWrapper.referenceField( + (symbol.descriptor as PropertyAccessorDescriptor).correspondingProperty + ) + return call.run { + JsIrBuilder.buildSetField(fieldSymbol, dispatchReceiver, getValueArgument(0)!!, type) + } } } } } - if (symbol.isDynamic()) { + if (declaration.isDynamic) { dynamicCallOriginToIrFunction[call.origin]?.let { return irCall(call, it.symbol, dispatchReceiverAsFirstArgument = true) } @@ -343,20 +351,16 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL return it(call) } - // TODO: get rid of unbound symbols - if (symbol.isBound) { - - (symbol.owner as? IrFunction)?.dispatchReceiverParameter?.let { - val key = SimpleMemberKey(it.type, symbol.owner.name) - memberToTransformer[key]?.let { - return it(call) - } - } - - nameToTransformer[symbol.owner.name]?.let { + (symbol.owner as? IrFunction)?.dispatchReceiverParameter?.let { + val key = SimpleMemberKey(it.type, symbol.owner.name) + memberToTransformer[key]?.let { return it(call) } } + + nameToTransformer[symbol.owner.name]?.let { + return it(call) + } } return call @@ -407,14 +411,13 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL private fun IrType.findEqualsMethod(rhs: IrType): IrSimpleFunction? { val classifier = classifierOrNull ?: return null - if (!classifier.isBound) return null return ((classifier.owner as? IrClass) ?: return null).declarations .filterIsInstance() .filter { it.name == Name.identifier("equals") && it.valueParameters.size == 1 && rhs.isSubtypeOf(it.valueParameters[0].type) - && !it.descriptor.isFakeOverriddenFromAny() + && !it./*descriptor.*/isFakeOverriddenFromAny() } .maxWith( // Find the most specific function Comparator { f1, f2 -> @@ -481,7 +484,6 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL private fun transformEqualsMethodCall(call: IrCall): IrExpression { val symbol = call.symbol - if (!symbol.isBound) return call val function = (symbol.owner as? IrFunction) ?: return call val lhs = function.dispatchReceiverParameter ?: function.extensionReceiverParameter ?: return call val rhs = call.getValueArgument(0) ?: return call @@ -489,7 +491,7 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL is IdentityOperator -> irCall(call, intrinsics.jsEqeqeq.symbol) is EqualityOperator -> irCall(call, intrinsics.jsEqeq.symbol) is RuntimeFunctionCall -> irCall(call, intrinsics.jsEquals, true) - is RuntimeOrMethodCall -> if (symbol.owner.descriptor.isFakeOverriddenFromAny()) { + is RuntimeOrMethodCall -> if (symbol.owner.isFakeOverriddenFromAny()) { if (call.isSuperToAny()) { irCall(call, intrinsics.jsEqeqeq.symbol, dispatchReceiverAsFirstArgument = true) } else { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveExternalDeclarationsToSeparatePlace.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveExternalDeclarationsToSeparatePlace.kt index 1f667da83b9..d5aa1f2d50b 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveExternalDeclarationsToSeparatePlace.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveExternalDeclarationsToSeparatePlace.kt @@ -8,11 +8,11 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.ir.backend.js.lower.inline.addChild -import org.jetbrains.kotlin.ir.backend.js.utils.isEffectivelyExternal import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol +import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.name.FqName class MoveExternalDeclarationsToSeparatePlace : FileLoweringPass { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt index b5530b1c497..c6826fb36be 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt @@ -8,18 +8,19 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.utils.commonSupertype import org.jetbrains.kotlin.backend.common.utils.isSubtypeOf -import org.jetbrains.kotlin.descriptors.VariableDescriptor +import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder -import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCatchImpl import org.jetbrains.kotlin.ir.expressions.impl.IrElseBranchImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.types.IrDynamicType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrNull @@ -55,21 +56,21 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas val nothingType = context.irBuiltIns.nothingType override fun lower(irFile: IrFile) { - irFile.transformChildren(object : IrElementTransformer { + irFile.transformChildren(object : IrElementTransformer { - override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclaration?) = - super.visitDeclaration(declaration, declaration) + override fun visitFunction(declaration: IrFunction, data: IrDeclarationParent): IrStatement { + return super.visitFunction(declaration, declaration) + } - override fun visitTry(aTry: IrTry, data: IrDeclaration?): IrExpression { + override fun visitTry(aTry: IrTry, data: IrDeclarationParent): IrExpression { aTry.transformChildren(this, data) if (aTry.catches.isEmpty()) return aTry.apply { assert(finallyExpression != null) } val commonType = mergeTypes(aTry.catches.map { it.catchParameter.type }) - val pendingExceptionSymbol = JsSymbolBuilder.buildVar(data!!.descriptor, commonType, "\$p", false) - val pendingExceptionDeclaration = JsIrBuilder.buildVar(pendingExceptionSymbol, type = commonType) - val pendingException = JsIrBuilder.buildGetValue(pendingExceptionSymbol) + val pendingExceptionDeclaration = JsIrBuilder.buildVar(commonType, "\$p").apply { parent = data } + val pendingException = JsIrBuilder.buildGetValue(pendingExceptionDeclaration.symbol) val branches = mutableListOf() @@ -82,13 +83,13 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas buildImplicitCast(pendingException, type, typeSymbol!!) else pendingException - val catchBody = catch.result.transform(object : IrElementTransformer { - override fun visitGetValue(expression: IrGetValue, data: VariableDescriptor) = - if (expression.descriptor == data) + val catchBody = catch.result.transform(object : IrElementTransformer { + override fun visitGetValue(expression: IrGetValue, data: IrValueSymbol) = + if (expression.symbol == data) castedPendingException else expression - }, catch.parameter) + }, catch.catchParameter.symbol) if (type is IrDynamicType) { branches += IrElseBranchImpl(catch.startOffset, catch.endOffset, litTrue, catchBody) @@ -124,6 +125,6 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas assert(it.isSubtypeOf(context.irBuiltIns.throwableType) || it is IrDynamicType) } - }, null) + }, irFile) } } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt index 5b772650fae..1e836d8ded4 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt @@ -6,17 +6,14 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass +import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.runOnFilePostfix -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor -import org.jetbrains.kotlin.descriptors.impl.LazyClassReceiverParameterDescriptor +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder -import org.jetbrains.kotlin.ir.backend.js.symbols.initialize import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl @@ -24,9 +21,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrValueSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.IrElementTransformer @@ -102,11 +98,12 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) { private class ThisUsageReplaceTransformer( val function: IrFunctionSymbol, - val newThisSymbol: IrValueSymbol, - val oldThisSymbol: IrValueSymbol? + val symbolMapping: Map ) : IrElementTransformerVoid() { + val newThisSymbol = symbolMapping.values.last().symbol + override fun visitReturn(expression: IrReturn): IrExpression = IrReturnImpl( expression.startOffset, expression.endOffset, @@ -116,11 +113,11 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) { ) override fun visitGetValue(expression: IrGetValue): IrExpression = - if (expression.symbol == oldThisSymbol) IrGetValueImpl( + if (expression.symbol.owner in symbolMapping) IrGetValueImpl( expression.startOffset, expression.endOffset, expression.type, - newThisSymbol, + symbolMapping[expression.symbol.owner]!!.symbol, expression.origin ) else { expression @@ -132,86 +129,81 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) { klass: IrClass, name: String, type: IrType - ): IrSimpleFunction = - JsSymbolBuilder.copyFunctionSymbol(declaration.symbol, "${name}_\$Init\$").let { + ): IrSimpleFunction { - val thisSymbol = - JsSymbolBuilder.buildValueParameter(it, declaration.valueParameters.size, type, "\$this") + val thisParam = JsIrBuilder.buildValueParameter("\$this", declaration.valueParameters.size, type) + val oldThisReceiver = klass.thisReceiver!! + val functionName = "${name}_\$Init\$" - it.initialize( - dispatchParameterDescriptor = declaration.descriptor.dispatchReceiverParameter, - typeParameters = declaration.descriptor.typeParameters, - valueParameters = declaration.descriptor.valueParameters + thisSymbol.descriptor as ValueParameterDescriptor, - returnType = type, - modality = declaration.descriptor.modality, - visibility = declaration.descriptor.visibility - ) + return JsIrBuilder.buildFunction( + functionName, + declaration.visibility, + Modality.FINAL, + declaration.isInline, + declaration.isExternal + ).also { + thisParam.run { parent = it } + val retStmt = JsIrBuilder.buildReturn(it.symbol, JsIrBuilder.buildGetValue(thisParam.symbol), context.irBuiltIns.nothingType) + val statements = (declaration.body!!.deepCopyWithSymbols(it) as IrStatementContainer).statements - val thisParam = JsIrBuilder.buildValueParameter(thisSymbol, type) - val oldThisReceiver = klass.thisReceiver?.symbol + val newValueParameters = declaration.valueParameters.map { p -> p.copyTo(it) } - return IrFunctionImpl( - declaration.startOffset, declaration.endOffset, - declaration.origin, it - ).apply { - val retStmt = JsIrBuilder.buildReturn(it, JsIrBuilder.buildGetValue(thisSymbol), context.irBuiltIns.nothingType) - val statements = (declaration.body as IrStatementContainer).statements + it.valueParameters += (newValueParameters + thisParam) - valueParameters += (declaration.valueParameters + thisParam) - typeParameters += declaration.typeParameters -// parent = declaration.parent - body = JsIrBuilder.buildBlockBody(statements + retStmt).apply { - transformChildrenVoid(ThisUsageReplaceTransformer(it, thisSymbol, oldThisReceiver)) - } + it.typeParameters += declaration.typeParameters.map { p -> p.copyTo(it) } + + it.returnType = type + it.parent = declaration.parent + + val oldValueParameters = declaration.valueParameters + oldThisReceiver + + // TODO: replace parameters as well + it.body = JsIrBuilder.buildBlockBody(statements + retStmt).apply { + transformChildrenVoid(ThisUsageReplaceTransformer(it.symbol, oldValueParameters.zip(it.valueParameters).toMap())) } - } + } + private fun createCreateConstructor( + declaration: IrConstructor, + ctorImpl: IrSimpleFunction, + name: String, + type: IrType + ): IrSimpleFunction { - private fun createCreateConstructor(ctorOrig: IrConstructor, ctorImpl: IrSimpleFunction, name: String, type: IrType): IrSimpleFunction = - JsSymbolBuilder.copyFunctionSymbol(ctorOrig.symbol, "${name}_\$Create\$").let { - it.initialize( - dispatchParameterDescriptor = ctorOrig.descriptor.dispatchReceiverParameter, - typeParameters = ctorOrig.descriptor.typeParameters, - valueParameters = ctorOrig.descriptor.valueParameters, - returnType = type, - modality = ctorOrig.descriptor.modality, - visibility = ctorOrig.visibility - ) + val functionName = "${name}_\$Create\$" - return IrFunctionImpl( - ctorOrig.startOffset, ctorOrig.endOffset, - ctorOrig.origin, it - ).apply { + return JsIrBuilder.buildFunction( + functionName, + declaration.visibility, + Modality.FINAL, + declaration.isInline, + declaration.isExternal + ).also { + it.valueParameters += declaration.valueParameters.map { p -> p.copyTo(it) } + it.typeParameters += declaration.typeParameters.map { p -> p.copyTo(it) } + it.parent = declaration.parent - valueParameters += ctorOrig.valueParameters - typeParameters += ctorOrig.typeParameters -// parent = ctorOrig.parent + it.returnType = type - returnType = type - val createFunctionIntrinsic = context.intrinsics.jsObjectCreate - val irCreateCall = JsIrBuilder.buildCall( - createFunctionIntrinsic.symbol, - returnType, - listOf(returnType) - ) - val irDelegateCall = JsIrBuilder.buildCall(ctorImpl.symbol, type).also { - for (i in 0 until valueParameters.size) { - it.putValueArgument(i, JsIrBuilder.buildGetValue(valueParameters[i].symbol)) - } + val createFunctionIntrinsic = context.intrinsics.jsObjectCreate + val irCreateCall = JsIrBuilder.buildCall(createFunctionIntrinsic.symbol, type, listOf(type)) + val irDelegateCall = JsIrBuilder.buildCall(ctorImpl.symbol, type).also { call -> + for (i in 0 until it.valueParameters.size) { + call.putValueArgument(i, JsIrBuilder.buildGetValue(it.valueParameters[i].symbol)) + } // valueParameters.forEachIndexed { i, p -> it.putValueArgument(i, JsIrBuilder.buildGetValue(p.symbol)) } - it.putValueArgument(ctorOrig.valueParameters.size, irCreateCall) + call.putValueArgument(declaration.valueParameters.size, irCreateCall) // typeParameters.mapIndexed { i, t -> ctorImpl.typeParameters[i].descriptor -> } - } - val irReturn = JsIrBuilder.buildReturn(it, irDelegateCall, context.irBuiltIns.nothingType) - - - body = JsIrBuilder.buildBlockBody(listOf(irReturn)) } - } + val irReturn = JsIrBuilder.buildReturn(it.symbol, irDelegateCall, context.irBuiltIns.nothingType) + it.body = JsIrBuilder.buildBlockBody(listOf(irReturn)) + } + } + inner class CallsiteRedirectionTransformer : IrElementTransformer { override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = super.visitFunction(declaration, declaration) @@ -219,17 +211,13 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) { override fun visitCall(expression: IrCall, data: IrFunction?): IrElement { super.visitCall(expression, data) - // TODO: figure out the reason why symbol is not bound - if (expression.symbol.isBound) { + val target = expression.symbol.owner - val target = expression.symbol.owner - - if (target is IrConstructor) { - if (!target.descriptor.isPrimary) { - val ctor = oldCtorToNewMap[target.symbol] - if (ctor != null) { - return redirectCall(expression, ctor.stub) - } + if (target is IrConstructor) { + if (!target.isPrimary) { + val ctor = oldCtorToNewMap[target.symbol] + if (ctor != null) { + return redirectCall(expression, ctor.stub) } } } @@ -252,12 +240,9 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) { val newCall = redirectCall(expression, ctor.delegate) val readThis = if (fromPrimary) { - IrGetValueImpl( - expression.startOffset, - expression.endOffset, - expression.type, - IrValueParameterSymbolImpl(LazyClassReceiverParameterDescriptor(target.descriptor.containingDeclaration)) - ) + val thisKlass = expression.symbol.owner.parent as IrClass + val thisSymbol = thisKlass.thisReceiver!!.symbol + IrGetValueImpl(expression.startOffset, expression.endOffset, expression.type, thisSymbol) } else { IrGetValueImpl(expression.startOffset, expression.endOffset, expression.type, data.valueParameters.last().symbol) } @@ -278,6 +263,5 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) { putValueArgument(i, call.getValueArgument(i)) } } - } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt index 597cd5572c3..73a18d617ad 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt @@ -7,15 +7,14 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.utils.* -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder -import org.jetbrains.kotlin.ir.backend.js.utils.isReified -import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall @@ -45,7 +44,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { private val isInterfaceSymbol get() = context.intrinsics.isInterfaceSymbol private val isArraySymbol get() = context.intrinsics.isArraySymbol -// private val isCharSymbol get() = context.intrinsics.isCharSymbol + // private val isCharSymbol get() = context.intrinsics.isCharSymbol private val isObjectSymbol get() = context.intrinsics.isObjectSymbol private val instanceOfIntrinsicSymbol = context.intrinsics.jsInstanceOf.symbol @@ -61,12 +60,15 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { private val litNull: IrExpression = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType) override fun lower(irFile: IrFile) { - // TODO: get rid of descriptors - irFile.transformChildren(object : IrElementTransformer { - override fun visitDeclaration(declaration: IrDeclaration, data: DeclarationDescriptor) = - super.visitDeclaration(declaration, declaration.descriptor) + irFile.transformChildren(object : IrElementTransformer { + override fun visitFunction(declaration: IrFunction, data: IrDeclarationParent) = + super.visitFunction(declaration, declaration) - override fun visitTypeOperator(expression: IrTypeOperatorCall, data: DeclarationDescriptor): IrExpression { + override fun visitClass(declaration: IrClass, data: IrDeclarationParent): IrStatement { + return super.visitClass(declaration, declaration) + } + + override fun visitTypeOperator(expression: IrTypeOperatorCall, data: IrDeclarationParent): IrExpression { super.visitTypeOperator(expression, data) return when (expression.operator) { @@ -81,13 +83,13 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { } } - private fun lowerImplicitNotNull(expression: IrTypeOperatorCall, containingDeclaration: DeclarationDescriptor): IrExpression { + private fun lowerImplicitNotNull(expression: IrTypeOperatorCall, declaration: IrDeclarationParent): IrExpression { assert(expression.operator == IrTypeOperator.IMPLICIT_NOTNULL) assert(expression.typeOperand.isNullable() xor expression.argument.type.isNullable()) val newStatements = mutableListOf() - val argument = cacheValue(expression.argument, newStatements, containingDeclaration) + val argument = cacheValue(expression.argument, newStatements, declaration) val irNullCheck = nullCheck(argument) newStatements += JsIrBuilder.buildIfElse(expression.typeOperand, irNullCheck, JsIrBuilder.buildCall(throwNPE), argument) @@ -97,7 +99,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { private fun lowerCast( expression: IrTypeOperatorCall, - containingDeclaration: DeclarationDescriptor, + declaration: IrDeclarationParent, isSafe: Boolean ): IrExpression { assert(expression.operator == IrTypeOperator.CAST || expression.operator == IrTypeOperator.SAFE_CAST) @@ -108,7 +110,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { val newStatements = mutableListOf() - val argument = cacheValue(expression.argument, newStatements, containingDeclaration) + val argument = cacheValue(expression.argument, newStatements, declaration) val check = generateTypeCheck(argument, toType) @@ -141,7 +143,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { fun lowerInstanceOf( expression: IrTypeOperatorCall, - containingDeclaration: DeclarationDescriptor, + declaration: IrDeclarationParent, inverted: Boolean ): IrExpression { assert(expression.operator == IrTypeOperator.INSTANCEOF || expression.operator == IrTypeOperator.NOT_INSTANCEOF) @@ -152,7 +154,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { val newStatements = mutableListOf() val argument = - if (isCopyRequired) cacheValue(expression.argument, newStatements, containingDeclaration) else expression.argument + if (isCopyRequired) cacheValue(expression.argument, newStatements, declaration) else expression.argument val check = generateTypeCheck(argument, toType) val result = if (inverted) calculator.not(check) else check @@ -167,10 +169,14 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { putValueArgument(1, litNull) } - private fun cacheValue(value: IrExpression, newStatements: MutableList, cd: DeclarationDescriptor): IrExpression { - val varSymbol = JsSymbolBuilder.buildTempVar(cd, value.type, mutable = false) - newStatements += JsIrBuilder.buildVar(varSymbol, value, value.type) - return JsIrBuilder.buildGetValue(varSymbol) + private fun cacheValue( + value: IrExpression, + newStatements: MutableList, + declaration: IrDeclarationParent + ): IrExpression { + val varDeclaration = JsIrBuilder.buildVar(value.type, initializer = value).apply { parent = declaration } + newStatements += varDeclaration + return JsIrBuilder.buildGetValue(varDeclaration.symbol) } private fun generateTypeCheck(argument: IrExpression, toType: IrType): IrExpression { @@ -272,7 +278,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { return expression.run { IrCompositeImpl(startOffset, endOffset, unit, null, listOf(argument, unitValue)) } } - private fun lowerIntegerCoercion(expression: IrTypeOperatorCall, containingDeclaration: DeclarationDescriptor): IrExpression { + private fun lowerIntegerCoercion(expression: IrTypeOperatorCall, declaration: IrDeclarationParent): IrExpression { assert(expression.operator === IrTypeOperator.IMPLICIT_INTEGER_COERCION) assert(expression.argument.type.isInt()) @@ -286,7 +292,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { val newStatements = mutableListOf() val argument = - if (isNullable) cacheValue(expression.argument, newStatements, containingDeclaration) else expression.argument + if (isNullable) cacheValue(expression.argument, newStatements, declaration) else expression.argument val casted = when { toType.isByte() -> maskOp(argument, byteMask, lit24) @@ -299,6 +305,6 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { return expression.run { IrCompositeImpl(startOffset, endOffset, toType, null, newStatements) } } - }, irFile.packageFragmentDescriptor) + }, irFile) } } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/StateMachineBuilder.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/StateMachineBuilder.kt index d949c1c8353..be32d34c741 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/StateMachineBuilder.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/StateMachineBuilder.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower.coroutines +import org.jetbrains.kotlin.backend.common.ir.isSuspend import org.jetbrains.kotlin.backend.common.peek import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push @@ -13,7 +14,6 @@ import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* @@ -75,8 +75,7 @@ class StateMachineBuilder( val entryState = SuspendState(unit) val rootExceptionTrap = buildExceptionTrapState() - private val globalExceptionSymbol = - JsSymbolBuilder.buildTempVar(function, exceptionSymbol.owner.type, "e") + private val globalExceptionVar = JsIrBuilder.buildVar(exceptionSymbol.owner.type, "e").also { it.parent = function.owner } lateinit var globalCatch: IrCatch fun finalizeStateMachine() { @@ -93,8 +92,8 @@ class StateMachineBuilder( private fun buildGlobalCatch(): IrCatch { - val catchVariable = - JsIrBuilder.buildVar(globalExceptionSymbol, type = exceptionSymbol.owner.type) + val catchVariable = globalExceptionVar + val globalExceptionSymbol = globalExceptionVar.symbol val block = JsIrBuilder.buildBlock(unit) if (hasExceptions) { val thenBlock = JsIrBuilder.buildBlock(unit) @@ -253,9 +252,9 @@ class StateMachineBuilder( val exitState = SuspendState(unit) val resultVariable = if (hasResultingValue(expression)) { - val symbol = tempVar(expression.type, "RETURNABLE_BLOCK") - addStatement(JsIrBuilder.buildVar(symbol, null, expression.type)) - symbol + val irVar = tempVar(expression.type, "RETURNABLE_BLOCK") + addStatement(irVar) + irVar.symbol } else null returnableBlockMap[expression.symbol] = Pair(exitState, resultVariable) @@ -282,7 +281,7 @@ class StateMachineBuilder( override fun visitCall(expression: IrCall) { super.visitCall(expression) - if (expression.descriptor.isSuspend) { + if (expression.isSuspend) { val result = lastExpression() val continueState = SuspendState(unit) val dispatch = IrDispatchPoint(continueState) @@ -331,8 +330,9 @@ class StateMachineBuilder( val branches: List if (hasResultingValue(expression)) { - varSymbol = tempVar(expression.type, "WHEN_RESULT") - addStatement(JsIrBuilder.buildVar(varSymbol, type = expression.type)) + val irVar = tempVar(expression.type, "WHEN_RESULT") + varSymbol = irVar.symbol + addStatement(irVar) branches = expression.branches.map { val wrapped = wrap(it.result, varSymbol) @@ -340,18 +340,8 @@ class StateMachineBuilder( suspendableNodes += wrapped } when (it) { - is IrElseBranch -> IrElseBranchImpl( - it.startOffset, - it.endOffset, - it.condition, - wrapped - ) - else /* IrBranch */ -> IrBranchImpl( - it.startOffset, - it.endOffset, - it.condition, - wrapped - ) + is IrElseBranch -> IrElseBranchImpl(it.startOffset, it.endOffset, it.condition, wrapped) + else /* IrBranch */ -> IrBranchImpl(it.startOffset, it.endOffset, it.condition, wrapped) } } } else { @@ -440,9 +430,11 @@ class StateMachineBuilder( newArguments[i] = if (arg != null && suspendableCount > 0) { if (arg in suspendableNodes) suspendableCount-- arg.acceptVoid(this) - val tmp = tempVar(arg.type, "ARGUMENT") - transformLastExpression { JsIrBuilder.buildVar(tmp, it, it.type) } - JsIrBuilder.buildGetValue(tmp) + val irVar = tempVar(arg.type, "ARGUMENT") + transformLastExpression { + irVar.apply { initializer = it } + } + JsIrBuilder.buildGetValue(irVar.symbol) } else arg } @@ -554,28 +546,24 @@ class StateMachineBuilder( catchBlockStack.push(tryState.catchState) - val finallyStateVarSymbol = tempVar(int, "FINALLY_STATE") + val finallyStateVar = tempVar(int, "FINALLY_STATE") val exitState = SuspendState(unit) val varSymbol = if (hasResultingValue(aTry)) tempVar(aTry.type, "TRY_RESULT") else null if (aTry.finallyExpression != null) { - addStatement( - JsIrBuilder.buildVar( - finallyStateVarSymbol, - IrDispatchPoint(exitState), int - ) - ) + finallyStateVar.initializer = IrDispatchPoint(exitState) + addStatement(finallyStateVar) } if (varSymbol != null) { - addStatement(JsIrBuilder.buildVar(varSymbol, type = aTry.type)) + addStatement(varSymbol) } // TODO: refact it with exception table, see coroutinesInternal.kt setupExceptionState(tryState.catchState) val tryResult = if (varSymbol != null) { - JsIrBuilder.buildSetVariable(varSymbol, aTry.tryResult, unit).also { + JsIrBuilder.buildSetVariable(varSymbol.symbol, aTry.tryResult, unit).also { if (it.value in suspendableNodes) suspendableNodes += it } } else aTry.tryResult @@ -610,7 +598,7 @@ class StateMachineBuilder( it.initializer = initializer } val catchResult = if (varSymbol != null) { - JsIrBuilder.buildSetVariable(varSymbol, catch.result, unit).also { + JsIrBuilder.buildSetVariable(varSymbol.symbol, catch.result, unit).also { if (it.value in suspendableNodes) suspendableNodes += it } } else catch.result @@ -661,7 +649,7 @@ class StateMachineBuilder( tryState.tryState.successors += finallyState.fromThrow addStatement( JsIrBuilder.buildSetVariable( - finallyStateVarSymbol, + finallyStateVar.symbol, IrDispatchPoint(throwExitState), int ) ) @@ -677,7 +665,7 @@ class StateMachineBuilder( stateSymbol, thisReceiver, JsIrBuilder.buildGetValue( - finallyStateVarSymbol + finallyStateVar.symbol ), unit ) @@ -691,7 +679,7 @@ class StateMachineBuilder( updateState(exitState) if (varSymbol != null) { - addStatement(JsIrBuilder.buildGetValue(varSymbol)) + addStatement(JsIrBuilder.buildGetValue(varSymbol.symbol)) } } @@ -730,6 +718,6 @@ class StateMachineBuilder( toType.classifierOrNull!! ) - private fun tempVar(type: IrType, name: String? = null) = - JsSymbolBuilder.buildTempVar(function, type, name) + private fun tempVar(type: IrType, name: String = "tmp") = + JsIrBuilder.buildVar(type, name).also { it.parent = function.owner } } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt index af9fbe99a60..0805069ed6a 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt @@ -6,42 +6,41 @@ package org.jetbrains.kotlin.ir.backend.js.lower.coroutines import org.jetbrains.kotlin.backend.common.* -import org.jetbrains.kotlin.backend.common.descriptors.getFunction -import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName -import org.jetbrains.kotlin.backend.common.ir.createOverriddenDescriptor +import org.jetbrains.kotlin.backend.common.descriptors.* +import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom +import org.jetbrains.kotlin.backend.common.ir.isSuspend import org.jetbrains.kotlin.backend.common.lower.SymbolWithIrBuilder -import org.jetbrains.kotlin.backend.common.lower.copyAsValueParameter import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl -import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext -import org.jetbrains.kotlin.ir.backend.js.ir.* +import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder +import org.jetbrains.kotlin.ir.backend.js.ir.addChild +import org.jetbrains.kotlin.ir.backend.js.ir.simpleFunctions import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrFail -import org.jetbrains.kotlin.ir.types.toKotlinType +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.utils.DFS internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLoweringPass { @@ -49,8 +48,8 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo private object STATEMENT_ORIGIN_COROUTINE_IMPL : IrStatementOriginImpl("COROUTINE_IMPL") private object DECLARATION_ORIGIN_COROUTINE_IMPL : IrDeclarationOriginImpl("COROUTINE_IMPL") - private val builtCoroutines = mutableMapOf() - private val suspendLambdas = mutableMapOf() + private val builtCoroutines = mutableMapOf() + private val suspendLambdas = mutableMapOf() override fun lower(irFile: IrFile) { markSuspendLambdas(irFile) @@ -60,7 +59,7 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo private fun buildCoroutines(irFile: IrFile) { irFile.declarations.transformFlat(::tryTransformSuspendFunction) - irFile.acceptVoid(object: IrElementVisitorVoid { + irFile.acceptVoid(object : IrElementVisitorVoid { override fun visitElement(element: IrElement) { element.acceptChildrenVoid(this) } @@ -73,9 +72,9 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo } private fun tryTransformSuspendFunction(element: IrElement) = - if (element is IrFunction && element.descriptor.isSuspend && element.descriptor.modality != Modality.ABSTRACT) - transformSuspendFunction(element, suspendLambdas[element.descriptor]) - else null + if (element is IrSimpleFunction && element.isSuspend && element.modality != Modality.ABSTRACT) + transformSuspendFunction(element, suspendLambdas[element]) + else null private fun markSuspendLambdas(irElement: IrElement) { irElement.acceptChildrenVoid(object : IrElementVisitorVoid { @@ -86,9 +85,9 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo override fun visitFunctionReference(expression: IrFunctionReference) { expression.acceptChildrenVoid(this) - val descriptor = expression.descriptor - if (descriptor.isSuspend) - suspendLambdas.put(descriptor, expression) + if (expression.isSuspend) { + suspendLambdas[expression.symbol.owner] = expression + } } }) } @@ -99,15 +98,15 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { expression.transformChildrenVoid(this) - val descriptor = expression.descriptor - if (!descriptor.isSuspend) + if (!expression.isSuspend) return expression - val coroutine = builtCoroutines[descriptor] - ?: throw Error("Non-local callable reference to suspend lambda: $descriptor") + val coroutine = builtCoroutines[expression.symbol.owner] + ?: throw Error("Non-local callable reference to suspend lambda: $expression") val constructorParameters = coroutine.coroutineConstructor.valueParameters val expressionArguments = expression.getArguments().map { it.second } - assert(constructorParameters.size == expressionArguments.size, - { "Inconsistency between callable reference to suspend lambda and the corresponding coroutine" }) + assert(constructorParameters.size == expressionArguments.size) { + "Inconsistency between callable reference to suspend lambda and the corresponding coroutine" + } val irBuilder = context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset) irBuilder.run { return irCall(coroutine.coroutineConstructor.symbol).apply { @@ -126,7 +125,7 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo object NEEDS_STATE_MACHINE : SuspendFunctionKind() } - private fun transformSuspendFunction(irFunction: IrFunction, functionReference: IrFunctionReference?): List? { + private fun transformSuspendFunction(irFunction: IrSimpleFunction, functionReference: IrFunctionReference?): List? { val suspendFunctionKind = getSuspendFunctionKind(irFunction) return when (suspendFunctionKind) { is SuspendFunctionKind.NO_SUSPEND_CALLS -> { @@ -134,41 +133,35 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo } is SuspendFunctionKind.DELEGATING -> { // Calls another suspend function at the end. - removeReturnIfSuspendedCallAndSimplifyDelegatingCall( - irFunction, suspendFunctionKind.delegatingCall) + removeReturnIfSuspendedCallAndSimplifyDelegatingCall(irFunction, suspendFunctionKind.delegatingCall) null // No need in state machine. } is SuspendFunctionKind.NEEDS_STATE_MACHINE -> { val coroutine = buildCoroutine(irFunction, functionReference) // Coroutine implementation. - if (suspendLambdas.contains(irFunction.descriptor)) // Suspend lambdas are called through factory method , + if (irFunction in suspendLambdas) // Suspend lambdas are called through factory method , listOf(coroutine) // thus we can eliminate original body. else - listOf( - coroutine, - irFunction - ) + listOf(coroutine, irFunction) } } } - private fun getSuspendFunctionKind(irFunction: IrFunction): SuspendFunctionKind { - if (suspendLambdas.contains(irFunction.descriptor)) + private fun getSuspendFunctionKind(irFunction: IrSimpleFunction): SuspendFunctionKind { + if (irFunction in suspendLambdas) return SuspendFunctionKind.NEEDS_STATE_MACHINE // Suspend lambdas always need coroutine implementation. - val body = irFunction.body - ?: return SuspendFunctionKind.NO_SUSPEND_CALLS + val body = irFunction.body ?: return SuspendFunctionKind.NO_SUSPEND_CALLS var numberOfSuspendCalls = 0 - body.acceptVoid(object: IrElementVisitorVoid { + body.acceptVoid(object : IrElementVisitorVoid { override fun visitElement(element: IrElement) { element.acceptChildrenVoid(this) } override fun visitCall(expression: IrCall) { expression.acceptChildrenVoid(this) - - if (expression.descriptor.isSuspend) + if (expression.isSuspend) ++numberOfSuspendCalls } }) @@ -189,10 +182,10 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo * } * } */ - loop@while (true) { - when { - value is IrBlock && value.statements.size == 1 -> value = value.statements.first() - value is IrReturn -> value = value.value + loop@ while (true) { + value = when { + value is IrBlock && value.statements.size == 1 -> value.statements.first() + value is IrReturn -> value.value else -> break@loop } } @@ -200,71 +193,69 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo } else -> null } - val suspendCallAtEnd = lastCall != null && lastCall.descriptor.isSuspend // Suspend call. + + val suspendCallAtEnd = lastCall != null && lastCall.isSuspend // Suspend call. return when { - numberOfSuspendCalls == 0 -> SuspendFunctionKind.NO_SUSPEND_CALLS + numberOfSuspendCalls == 0 -> SuspendFunctionKind.NO_SUSPEND_CALLS numberOfSuspendCalls == 1 - && suspendCallAtEnd -> SuspendFunctionKind.DELEGATING( - lastCall!! - ) - else -> SuspendFunctionKind.NEEDS_STATE_MACHINE + && suspendCallAtEnd -> SuspendFunctionKind.DELEGATING(lastCall!!) + else -> SuspendFunctionKind.NEEDS_STATE_MACHINE } } private val symbols = context.ir.symbols private val unit = context.run { symbolTable.referenceClass(builtIns.unit) } - private val getContinuationSymbol = - context.run { - val f = getInternalFunctions("getContinuation") - symbolTable.referenceSimpleFunction(f.single()) - } + private val getContinuationSymbol = context.intrinsics.getContinuation private val continuationClassSymbol = getContinuationSymbol.owner.returnType.classifierOrFail as IrClassSymbol - private val returnIfSuspendedDescriptor = context.getInternalFunctions("returnIfSuspended").single() + private val returnIfSuspended = context.intrinsics.returnIfSuspended private fun removeReturnIfSuspendedCallAndSimplifyDelegatingCall(irFunction: IrFunction, delegatingCall: IrCall) { val returnValue = - if (delegatingCall.descriptor.original == returnIfSuspendedDescriptor) - delegatingCall.getValueArgument(0)!! - else delegatingCall + if (delegatingCall.descriptor.original == returnIfSuspended.descriptor) + delegatingCall.getValueArgument(0)!! + else delegatingCall context.createIrBuilder(irFunction.symbol).run { val statements = (irFunction.body as IrBlockBody).statements val lastStatement = statements.last() - assert (lastStatement == delegatingCall || lastStatement is IrReturn) { "Unexpected statement $lastStatement" } - statements[statements.size - 1] = irReturn(returnValue) + assert(lastStatement == delegatingCall || lastStatement is IrReturn) { "Unexpected statement $lastStatement" } + statements[statements.lastIndex] = irReturn(returnValue) } } - private fun buildCoroutine(irFunction: IrFunction, functionReference: IrFunctionReference?): IrClass { - val descriptor = irFunction.descriptor + private fun buildCoroutine(irFunction: IrSimpleFunction, functionReference: IrFunctionReference?): IrClass { val coroutine = CoroutineBuilder(irFunction, functionReference).build() - builtCoroutines.put(descriptor, coroutine) + builtCoroutines[irFunction] = coroutine if (functionReference == null) { // It is not a lambda - replace original function with a call to constructor of the built coroutine. val irBuilder = context.createIrBuilder(irFunction.symbol, irFunction.startOffset, irFunction.endOffset) irFunction.body = irBuilder.irBlockBody(irFunction) { +irReturn( - irCall(coroutine.doResumeFunction.symbol).apply { - dispatchReceiver = irCall(coroutine.coroutineConstructor.symbol).apply { - val functionParameters = irFunction.explicitParameters - functionParameters.forEachIndexed { index, argument -> - putValueArgument(index, irGet(argument)) - } - putValueArgument(functionParameters.size, - irCall(getContinuationSymbol, getContinuationSymbol.owner.returnType, listOf(irFunction.returnType))) + irCall(coroutine.doResumeFunction.symbol).apply { + dispatchReceiver = irCall(coroutine.coroutineConstructor.symbol).apply { + val functionParameters = irFunction.explicitParameters + functionParameters.forEachIndexed { index, argument -> + putValueArgument(index, irGet(argument)) } - putValueArgument(0, irGetObject(unit)) // value - putValueArgument(1, irNull()) // exception - }) + putValueArgument( + functionParameters.size, + irCall(getContinuationSymbol, getContinuationSymbol.owner.returnType, listOf(irFunction.returnType)) + ) + } + putValueArgument(0, irGetObject(unit)) // value + putValueArgument(1, irNull()) // exception + }) } } return coroutine.coroutineClass } - private class BuiltCoroutine(val coroutineClass: IrClass, - val coroutineConstructor: IrConstructor, - val doResumeFunction: IrFunction) + private class BuiltCoroutine( + val coroutineClass: IrClass, + val coroutineConstructor: IrConstructor, + val doResumeFunction: IrFunction + ) private var coroutineId = 0 @@ -278,21 +269,18 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo private lateinit var suspendState: IrVariable private lateinit var dataArgument: IrValueParameter private lateinit var exceptionArgument: IrValueParameter - private lateinit var coroutineClassDescriptor: ClassDescriptorImpl private lateinit var coroutineClass: IrClassImpl private lateinit var coroutineClassThis: IrValueParameter - private lateinit var argumentToPropertiesMap: Map + private lateinit var argumentToPropertiesMap: Map private val coroutineImplSymbol = symbols.coroutineImpl private val coroutineImplConstructorSymbol = coroutineImplSymbol.constructors.single() - private val coroutineImplClassDescriptor = coroutineImplSymbol.descriptor private val create1Function = coroutineImplSymbol.owner.simpleFunctions() .single { it.name.asString() == "create" && it.valueParameters.size == 1 } private val create1CompletionParameter = create1Function.valueParameters[0] private val coroutineImplLabelFieldSymbol = coroutineImplSymbol.getPropertyField("label")!! -// private val coroutineImplResultFieldSymbol = coroutineImplSymbol.getPropertyField("pendingResult")!! private val coroutineImplExceptionFieldSymbol = coroutineImplSymbol.getPropertyField("pendingException")!! private val coroutineImplExceptionStateFieldSymbol = coroutineImplSymbol.getPropertyField("exceptionState")!! @@ -300,11 +288,11 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo private var exceptionTrapId = -1 fun build(): BuiltCoroutine { - val superTypes = mutableListOf(coroutineImplSymbol.owner.defaultType) + val superTypes = mutableListOf(coroutineImplSymbol.owner.defaultType) var suspendFunctionClass: IrClass? = null var functionClass: IrClass? = null - var suspendFunctionClassTypeArguments: List? = null - var functionClassTypeArguments: List? = null + val suspendFunctionClassTypeArguments: List? + val functionClassTypeArguments: List? if (unboundFunctionParameters != null) { // Suspend lambda inherits SuspendFunction. val numberOfParameters = unboundFunctionParameters.size @@ -319,71 +307,80 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo superTypes += functionClass.typeWith(functionClassTypeArguments) } - coroutineClassDescriptor = ClassDescriptorImpl( - /* containingDeclaration = */ irFunction.descriptor.containingDeclaration, - /* name = */ "${irFunction.descriptor.name}\$${coroutineId++}".synthesizedName, - /* modality = */ Modality.FINAL, - /* kind = */ ClassKind.CLASS, - /* superTypes = */ superTypes.map { it.toKotlinType() }, - /* source = */ SourceElement.NO_SOURCE, - /* isExternal = */ false, - /* storageManager = */ LockBasedStorageManager.NO_LOCKS - ).also { - it.initialize(stub("coroutine class"), stub("coroutine class constructors"), null) - } + + val coroutineClassDescriptor = WrappedClassDescriptor() + val coroutineClassSymbol = IrClassSymbolImpl(coroutineClassDescriptor) + coroutineClass = IrClassImpl( - startOffset = irFunction.startOffset, - endOffset = irFunction.endOffset, - origin = DECLARATION_ORIGIN_COROUTINE_IMPL, - descriptor = coroutineClassDescriptor + irFunction.startOffset, + irFunction.endOffset, + DECLARATION_ORIGIN_COROUTINE_IMPL, + coroutineClassSymbol, + "${irFunction.name}\$${coroutineId++}".synthesizedName, + ClassKind.CLASS, + irFunction.visibility, + Modality.FINAL, + false, + false, + false, + false, + false ) + coroutineClassDescriptor.bind(coroutineClass) + coroutineClass.parent = irFunction.parent - coroutineClass.createParameterDeclarations() - coroutineClassThis = coroutineClass.thisReceiver!! + coroutineClass.superTypes += superTypes + val thisType = IrSimpleTypeImpl(coroutineClassSymbol, false, emptyList(), emptyList()) + coroutineClassThis = + JsIrBuilder.buildValueParameter(Name.special(""), -1, thisType, IrDeclarationOrigin.INSTANCE_RECEIVER) + coroutineClass.thisReceiver = coroutineClassThis - - val overriddenMap = mutableMapOf() - val constructors = mutableSetOf() + val overriddenMap = mutableMapOf() + val constructors = mutableSetOf() val coroutineConstructorBuilder = createConstructorBuilder() - constructors.add(coroutineConstructorBuilder.symbol.descriptor) coroutineConstructorBuilder.initialize() + constructors.add(coroutineConstructorBuilder.ir) - val doResumeFunction = coroutineImplSymbol.owner.simpleFunctions() - .single { it.name.asString() == "doResume" } + val doResumeFunction = coroutineImplSymbol.owner.simpleFunctions().single { it.name.asString() == "doResume" } val doResumeMethodBuilder = createDoResumeMethodBuilder(doResumeFunction, coroutineClass) doResumeMethodBuilder.initialize() - overriddenMap += doResumeFunction.descriptor to doResumeMethodBuilder.symbol.descriptor + overriddenMap += doResumeFunction to doResumeMethodBuilder.symbol var coroutineFactoryConstructorBuilder: SymbolWithIrBuilder? = null var createMethodBuilder: SymbolWithIrBuilder? = null var invokeMethodBuilder: SymbolWithIrBuilder? = null if (functionReference != null) { // Suspend lambda - create factory methods. - coroutineFactoryConstructorBuilder = createFactoryConstructorBuilder(boundFunctionParameters!!) - constructors.add(coroutineFactoryConstructorBuilder.symbol.descriptor) + coroutineFactoryConstructorBuilder = createFactoryConstructorBuilder(boundFunctionParameters!!).also { it.initialize() } + constructors.add(coroutineFactoryConstructorBuilder.ir) + + val createFunctionDeclaration = coroutineImplSymbol.owner.simpleFunctions() + .asSequence() + .filter { it.name == Name.identifier("create") } + .toList() + .atMostOne { it.valueParameters.size == unboundFunctionParameters!!.size + 1 } - val createFunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope - .getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND) - .atMostOne { it.valueParameters.size == unboundFunctionParameters!!.size + 1 } createMethodBuilder = createCreateMethodBuilder( - unboundArgs = unboundFunctionParameters!!, - superFunctionDescriptor = createFunctionDescriptor, - coroutineConstructor = coroutineConstructorBuilder.ir, - coroutineClass = coroutineClass) + unboundArgs = unboundFunctionParameters!!, + superFunctionDeclaration = createFunctionDeclaration, + coroutineConstructor = coroutineConstructorBuilder.ir, + coroutineClass = coroutineClass) createMethodBuilder.initialize() - if (createFunctionDescriptor != null) - overriddenMap += createFunctionDescriptor to createMethodBuilder.symbol.descriptor - val invokeFunctionDescriptor = functionClass!!.descriptor - .getFunction("invoke", functionClassTypeArguments!!.map { it.toKotlinType() }) - val suspendInvokeFunctionDescriptor = suspendFunctionClass!!.descriptor - .getFunction("invoke", suspendFunctionClassTypeArguments!!.map { it.toKotlinType() }) + if (createFunctionDeclaration != null) + overriddenMap += createFunctionDeclaration to createMethodBuilder.symbol + + val invokeFunctionDeclaration = functionClass!!.simpleFunctions() + .atMostOne { it.name == Name.identifier("invoke") }!! + val suspendInvokeFunctionDeclaration = suspendFunctionClass!!.simpleFunctions() + .atMostOne { it.name == Name.identifier("invoke") }!! invokeMethodBuilder = createInvokeMethodBuilder( - suspendFunctionInvokeFunctionDescriptor = suspendInvokeFunctionDescriptor, - functionInvokeFunctionDescriptor = invokeFunctionDescriptor, - createFunction = createMethodBuilder.ir, - doResumeFunction = doResumeMethodBuilder.ir, - coroutineClass = coroutineClass) + suspendFunctionInvokeFunctionDeclaration = suspendInvokeFunctionDeclaration, + functionInvokeFunctionDeclaration = invokeFunctionDeclaration, + createFunction = createMethodBuilder.ir, + doResumeFunction = doResumeMethodBuilder.ir, + coroutineClass = coroutineClass + ) } coroutineClass.addChild(coroutineConstructorBuilder.ir) @@ -412,380 +409,412 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo return BuiltCoroutine( coroutineClass = coroutineClass, - coroutineConstructor = coroutineFactoryConstructorBuilder?.ir - ?: coroutineConstructorBuilder.ir, + coroutineConstructor = coroutineFactoryConstructorBuilder?.ir ?: coroutineConstructorBuilder.ir, doResumeFunction = doResumeMethodBuilder.ir ) } - private fun createConstructorBuilder() - = object : SymbolWithIrBuilder() { + fun IrClass.setSuperSymbolsAndAddFakeOverrides(superTypes: List) { - override fun buildSymbol() = IrConstructorSymbolImpl( - ClassConstructorDescriptorImpl.create( - /* containingDeclaration = */ coroutineClassDescriptor, - /* annotations = */ Annotations.EMPTY, - /* isPrimary = */ false, - /* source = */ SourceElement.NO_SOURCE - ) - ) - - private lateinit var constructorParameters: List - - override fun doInitialize() { - val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl - constructorParameters = ( - functionParameters - + coroutineImplConstructorSymbol.owner.valueParameters[0] // completion. - ).mapIndexed { index, parameter -> - - val parameterDescriptor = parameter.descriptor.copyAsValueParameter(descriptor, index) - parameter.copy(parameterDescriptor) - } - - descriptor.initialize( - constructorParameters.map { it.descriptor as ValueParameterDescriptor }, - Visibilities.PUBLIC - ) - descriptor.returnType = coroutineClassDescriptor.defaultType + fun IrDeclaration.toList() = when (this) { + is IrSimpleFunction -> listOf(this) +// is IrProperty -> listOfNotNull(getter, setter) + else -> emptyList() } + val overriddenMembers = declarations.flatMap { it.toList() }.flatMap { it.overriddenSymbols.map(IrSimpleFunctionSymbol::owner) } + + val unoverriddenSuperMembers = superTypes.map { it.getClass()!! }.flatMap { irClass -> + irClass.declarations.flatMap { it.toList() }.filter { it !in overriddenMembers } + } + + fun createFakeOverride(irFunction: IrSimpleFunction) = JsIrBuilder.buildFunction( + irFunction.name, + irFunction.visibility, + Modality.FINAL, + irFunction.isInline, + irFunction.isExternal, + irFunction.isTailrec, + irFunction.isSuspend, + IrDeclarationOrigin.FAKE_OVERRIDE + ).apply { + returnType = irFunction.returnType + overriddenSymbols += irFunction.symbol + copyParameterDeclarationsFrom(irFunction) + } + + for (sm in unoverriddenSuperMembers) { + val fakeOverride = createFakeOverride(sm).also { it.parent = this } + declarations += fakeOverride + } + + /* + + return when (descriptor) { + is FunctionDescriptor -> descriptor.createFunction() + is PropertyDescriptor -> + IrPropertyImpl(startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, descriptor).apply { + // TODO: add field if getter is missing? + getter = descriptor.getter?.createFunction() as IrSimpleFunction? + setter = descriptor.setter?.createFunction() as IrSimpleFunction? + } + else -> TODO(descriptor.toString()) + } + */ + + } + + private fun createConstructorBuilder() = object : SymbolWithIrBuilder() { + + private val descriptor = WrappedClassConstructorDescriptor() + + override fun buildSymbol(): IrConstructorSymbol = IrConstructorSymbolImpl(descriptor) + + override fun doInitialize() {} + override fun buildIr(): IrConstructor { // Save all arguments to fields. argumentToPropertiesMap = functionParameters.associate { - it.descriptor to addField(it.name, it.type, false) + it to addField(it.name, it.type, false) } - val startOffset = irFunction.startOffset - val endOffset = irFunction.endOffset - return IrConstructorImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = DECLARATION_ORIGIN_COROUTINE_IMPL, - symbol = symbol).apply { + val completion = coroutineImplConstructorSymbol.owner.valueParameters[0] - parent = coroutineClass - returnType = coroutineClass.defaultType + val declaration = IrConstructorImpl( + irFunction.startOffset, + irFunction.endOffset, + DECLARATION_ORIGIN_COROUTINE_IMPL, + symbol, + Name.special(""), + irFunction.visibility, + false, + false, + false + ) - this.valueParameters += constructorParameters + descriptor.bind(declaration) + declaration.parent = coroutineClass + declaration.returnType = coroutineClass.defaultType - val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) - body = irBuilder.irBlockBody { - val completionParameter = valueParameters.last() - +IrDelegatingConstructorCallImpl(startOffset, endOffset, - context.irBuiltIns.unitType, - coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply { - putValueArgument(0, irGet(completionParameter)) + declaration.valueParameters += functionParameters.map { + JsIrBuilder.buildValueParameter(it.name, it.index, it.type, it.origin).also { p -> p.parent = declaration } + } + declaration.valueParameters += JsIrBuilder.buildValueParameter( + completion.name, + functionParameters.size, + completion.type, + completion.origin + ).also { + it.parent = declaration + } + + val irBuilder = context.createIrBuilder(symbol, irFunction.startOffset, irFunction.endOffset) + + declaration.body = irBuilder.irBlockBody { + val completionParameter = declaration.valueParameters.last() + +IrDelegatingConstructorCallImpl( + irFunction.startOffset, irFunction.endOffset, + context.irBuiltIns.unitType, + coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor + ).apply { + putValueArgument(0, irGet(completionParameter)) + } + +IrInstanceInitializerCallImpl( + irFunction.startOffset, + irFunction.endOffset, + coroutineClass.symbol, + context.irBuiltIns.unitType + ) + functionParameters.forEachIndexed { index, parameter -> + +irSetField( + irGet(coroutineClassThis), + argumentToPropertiesMap[parameter]!!, + irGet(declaration.valueParameters[index]) + ) + } + } + + return declaration + } + } + + private fun createFactoryConstructorBuilder(boundParams: List) = + object : SymbolWithIrBuilder() { + + private val descriptor = WrappedClassConstructorDescriptor() + + override fun buildSymbol() = IrConstructorSymbolImpl(descriptor) + + override fun doInitialize() {} + + override fun buildIr(): IrConstructor { + + val declaration = IrConstructorImpl( + irFunction.startOffset, + irFunction.endOffset, + DECLARATION_ORIGIN_COROUTINE_IMPL, + symbol, + Name.special(""), + irFunction.visibility, + false, + false, + false + ) + + descriptor.bind(declaration) + declaration.parent = coroutineClass + declaration.returnType = coroutineClass.defaultType + + boundParams.mapIndexedTo(declaration.valueParameters) { i, p -> + JsIrBuilder.buildValueParameter(p.name, i, p.type, p.origin).also { it.parent = declaration } + } + + val irBuilder = context.createIrBuilder(symbol, irFunction.startOffset, irFunction.endOffset) + declaration.body = irBuilder.irBlockBody { + +IrDelegatingConstructorCallImpl( + irFunction.startOffset, irFunction.endOffset, context.irBuiltIns.unitType, + coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor + ).apply { + putValueArgument(0, irNull()) // Completion. } - +IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol, context.irBuiltIns.unitType) - functionParameters.forEachIndexed { index, parameter -> + +IrInstanceInitializerCallImpl( + irFunction.startOffset, irFunction.endOffset, coroutineClass.symbol, + context.irBuiltIns.unitType + ) + // Save all arguments to fields. + boundParams.forEachIndexed { index, parameter -> +irSetField( - irGet(coroutineClassThis), - argumentToPropertiesMap[parameter.descriptor]!!, - irGet(valueParameters[index]) + irGet(coroutineClassThis), argumentToPropertiesMap[parameter]!!, + irGet(declaration.valueParameters[index]) ) } } + + return declaration } } - } - private fun createFactoryConstructorBuilder(boundParams: List) - = object : SymbolWithIrBuilder() { + private fun createCreateMethodBuilder( + unboundArgs: List, + superFunctionDeclaration: IrSimpleFunction?, + coroutineConstructor: IrConstructor, + coroutineClass: IrClass + ) = object : SymbolWithIrBuilder() { - override fun buildSymbol() = IrConstructorSymbolImpl( - ClassConstructorDescriptorImpl.create( - /* containingDeclaration = */ coroutineClassDescriptor, - /* annotations = */ Annotations.EMPTY, - /* isPrimary = */ false, - /* source = */ SourceElement.NO_SOURCE - ) - ) + private val descriptor = WrappedSimpleFunctionDescriptor() - lateinit var constructorParameters: List + override fun buildSymbol() = IrSimpleFunctionSymbolImpl(descriptor) - override fun doInitialize() { - val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl - constructorParameters = boundParams.mapIndexed { index, parameter -> - val parameterDescriptor = parameter.descriptor.copyAsValueParameter(descriptor, index) - parameter.copy(parameterDescriptor) - } - descriptor.initialize( - constructorParameters.map { it.descriptor as ValueParameterDescriptor }, - Visibilities.PUBLIC + override fun doInitialize() {} + + override fun buildIr(): IrSimpleFunction { + val declaration = IrFunctionImpl( + irFunction.startOffset, + irFunction.endOffset, + DECLARATION_ORIGIN_COROUTINE_IMPL, + symbol, + Name.identifier("create"), + Visibilities.PRIVATE, + Modality.FINAL, + false, + false, + false, + false ) - descriptor.returnType = coroutineClassDescriptor.defaultType - } - override fun buildIr(): IrConstructor { - val startOffset = irFunction.startOffset - val endOffset = irFunction.endOffset - return IrConstructorImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = DECLARATION_ORIGIN_COROUTINE_IMPL, - symbol = symbol).apply { + descriptor.bind(declaration) + declaration.parent = coroutineClass + declaration.returnType = coroutineClass.defaultType + declaration.dispatchReceiverParameter = coroutineClassThis - parent = coroutineClass - returnType = coroutineClass.defaultType - - this.valueParameters += constructorParameters - - val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) - body = irBuilder.irBlockBody { - +IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType, - coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply { - putValueArgument(0, irNull()) // Completion. - } - +IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol, - context.irBuiltIns.unitType) - // Save all arguments to fields. - boundParams.forEachIndexed { index, parameter -> - +irSetField(irGet(coroutineClassThis), argumentToPropertiesMap[parameter.descriptor]!!, - irGet(valueParameters[index])) - } - } + unboundArgs.mapIndexedTo(declaration.valueParameters) { i, p -> + JsIrBuilder.buildValueParameter(p.name, i, p.type, p.origin).also { it.parent = declaration } } + + declaration.valueParameters += JsIrBuilder.buildValueParameter( + create1CompletionParameter.name, + unboundArgs.size, + create1CompletionParameter.type, + create1CompletionParameter.origin + ).also { it.parent = declaration } + + + if (superFunctionDeclaration != null) { + declaration.overriddenSymbols += superFunctionDeclaration.overriddenSymbols + declaration.overriddenSymbols += superFunctionDeclaration.symbol + } + + val thisReceiver = coroutineClassThis + val irBuilder = context.createIrBuilder(symbol, irFunction.startOffset, irFunction.endOffset) + declaration.body = irBuilder.irBlockBody(irFunction.startOffset, irFunction.endOffset) { + +irReturn( + irCall(coroutineConstructor).apply { + var unboundIndex = 0 + val unboundArgsSet = unboundArgs.toSet() + functionParameters.map { + if (unboundArgsSet.contains(it)) + irGet(declaration.valueParameters[unboundIndex++]) + else + irGetField(irGet(thisReceiver), argumentToPropertiesMap[it]!!) + }.forEachIndexed { index, argument -> + putValueArgument(index, argument) + } + putValueArgument(functionParameters.size, irGet(declaration.valueParameters[unboundIndex])) + assert(unboundIndex == declaration.valueParameters.size - 1) { "Not all arguments of are used" } + }) + } + + return declaration } } - private fun createCreateMethodBuilder(unboundArgs: List, - superFunctionDescriptor: FunctionDescriptor?, - coroutineConstructor: IrConstructor, - coroutineClass: IrClass) - = object: SymbolWithIrBuilder() { + private fun createInvokeMethodBuilder( + suspendFunctionInvokeFunctionDeclaration: IrSimpleFunction, + functionInvokeFunctionDeclaration: IrSimpleFunction, + createFunction: IrFunction, + doResumeFunction: IrFunction, + coroutineClass: IrClass + ) = object : SymbolWithIrBuilder() { - override fun buildSymbol() = IrSimpleFunctionSymbolImpl( - SimpleFunctionDescriptorImpl.create( - /* containingDeclaration = */ coroutineClassDescriptor, - /* annotations = */ Annotations.EMPTY, - /* name = */ Name.identifier("create"), - /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, - /* source = */ SourceElement.NO_SOURCE - ) - ) + private val descriptor = WrappedSimpleFunctionDescriptor() - lateinit var parameters: List + override fun buildSymbol() = IrSimpleFunctionSymbolImpl(descriptor) - override fun doInitialize() { - val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl - parameters = ( - unboundArgs + create1CompletionParameter - ).mapIndexed { index, parameter -> - parameter.copy(parameter.descriptor.copyAsValueParameter(descriptor, index)) - } - - descriptor.initialize( - /* receiverParameterType = */ null, - /* dispatchReceiverParameter = */ coroutineClassDescriptor.thisAsReceiverParameter, - /* typeParameters = */ emptyList(), - /* unsubstitutedValueParameters = */ parameters.map { it.descriptor as ValueParameterDescriptor }, - /* unsubstitutedReturnType = */ coroutineClassDescriptor.defaultType, - /* modality = */ Modality.FINAL, - /* visibility = */ Visibilities.PRIVATE).apply { - if (superFunctionDescriptor != null) { - overriddenDescriptors += superFunctionDescriptor.overriddenDescriptors - overriddenDescriptors += superFunctionDescriptor - } - } - } + override fun doInitialize() {} override fun buildIr(): IrSimpleFunction { - val startOffset = irFunction.startOffset - val endOffset = irFunction.endOffset - return IrFunctionImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = DECLARATION_ORIGIN_COROUTINE_IMPL, - symbol = symbol).apply { - returnType = coroutineClass.defaultType - parent = coroutineClass + val declaration = IrFunctionImpl( + irFunction.startOffset, + irFunction.endOffset, + DECLARATION_ORIGIN_COROUTINE_IMPL, + symbol, + Name.identifier("invoke"), + Visibilities.PRIVATE, + Modality.FINAL, + false, + false, + false, + true + ) - this.valueParameters += parameters - this.createDispatchReceiverParameter() + descriptor.bind(declaration) + declaration.parent = coroutineClass + declaration.returnType = irFunction.returnType + declaration.dispatchReceiverParameter = coroutineClassThis - val thisReceiver = this.dispatchReceiverParameter!! + declaration.overriddenSymbols += suspendFunctionInvokeFunctionDeclaration.symbol + declaration.overriddenSymbols += functionInvokeFunctionDeclaration.symbol - val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) - body = irBuilder.irBlockBody(startOffset, endOffset) { - +irReturn( - irCall(coroutineConstructor).apply { - var unboundIndex = 0 - val unboundArgsSet = unboundArgs.toSet() - functionParameters.map { - if (unboundArgsSet.contains(it)) - irGet(valueParameters[unboundIndex++]) - else - irGetField(irGet(thisReceiver), argumentToPropertiesMap[it.descriptor]!!) - }.forEachIndexed { index, argument -> - putValueArgument(index, argument) - } - putValueArgument(functionParameters.size, irGet(valueParameters[unboundIndex])) - assert(unboundIndex == valueParameters.size - 1, - { "Not all arguments of are used" }) - }) - } + createFunction.valueParameters.dropLast(1).mapTo(declaration.valueParameters) { p -> + JsIrBuilder.buildValueParameter(p.name, p.index, p.type, p.origin).also { it.parent = declaration } } - } - } - private fun createInvokeMethodBuilder(suspendFunctionInvokeFunctionDescriptor: FunctionDescriptor, - functionInvokeFunctionDescriptor: FunctionDescriptor, - createFunction: IrFunction, - doResumeFunction: IrFunction, - coroutineClass: IrClass) - = object: SymbolWithIrBuilder() { - - override fun buildSymbol() = IrSimpleFunctionSymbolImpl( - SimpleFunctionDescriptorImpl.create( - /* containingDeclaration = */ coroutineClassDescriptor, - /* annotations = */ Annotations.EMPTY, - /* name = */ Name.identifier("invoke"), - /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, - /* source = */ SourceElement.NO_SOURCE - ) - ) - - lateinit var parameters: List - - override fun doInitialize() { - val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl - parameters = createFunction.valueParameters - // Skip completion - invoke() already has it implicitly as a suspend function. - .take(createFunction.valueParameters.size - 1) - .map { it.copy(it.descriptor.copyAsValueParameter(descriptor, it.index)) } - - descriptor.initialize( - /* receiverParameterType = */ null, - /* dispatchReceiverParameter = */ coroutineClassDescriptor.thisAsReceiverParameter, - /* typeParameters = */ emptyList(), - /* unsubstitutedValueParameters = */ parameters.map { it.descriptor as ValueParameterDescriptor }, - /* unsubstitutedReturnType = */ irFunction.descriptor.returnType, - /* modality = */ Modality.FINAL, - /* visibility = */ Visibilities.PRIVATE).apply { - overriddenDescriptors += suspendFunctionInvokeFunctionDescriptor - overriddenDescriptors += functionInvokeFunctionDescriptor - isSuspend = true - } - } - - override fun buildIr(): IrSimpleFunction { - val startOffset = irFunction.startOffset - val endOffset = irFunction.endOffset - return IrFunctionImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = DECLARATION_ORIGIN_COROUTINE_IMPL, - symbol = symbol).apply { - - returnType = irFunction.returnType - parent = coroutineClass - - valueParameters += parameters - this.createDispatchReceiverParameter() - - val thisReceiver = this.dispatchReceiverParameter!! - - val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset) - body = irBuilder.irBlockBody(startOffset, endOffset) { - +irReturn( - irCall(doResumeFunction).apply { - dispatchReceiver = irCall(createFunction).apply { - dispatchReceiver = irGet(thisReceiver) - valueParameters.forEachIndexed { index, parameter -> - putValueArgument(index, irGet(parameter)) - } - putValueArgument(valueParameters.size, - irCall(getContinuationSymbol, getContinuationSymbol.owner.returnType, listOf(returnType))) - } - putValueArgument(0, irGetObject(symbols.unit)) // value - putValueArgument(1, irNull()) // exception + val thisReceiver = coroutineClassThis + val irBuilder = context.createIrBuilder(symbol, irFunction.startOffset, irFunction.endOffset) + declaration.body = irBuilder.irBlockBody(irFunction.startOffset, irFunction.endOffset) { + +irReturn( + irCall(doResumeFunction).apply { + dispatchReceiver = irCall(createFunction).apply { + dispatchReceiver = irGet(thisReceiver) + declaration.valueParameters.forEachIndexed { index, parameter -> + putValueArgument(index, irGet(parameter)) } - ) - } + putValueArgument( + declaration.valueParameters.size, + irCall(getContinuationSymbol, getContinuationSymbol.owner.returnType, listOf(declaration.returnType)) + ) + } + putValueArgument(0, irGetObject(symbols.unit)) // value + putValueArgument(1, irNull()) // exception + } + ) } + + return declaration } } - private fun addField(name: Name, type: IrType, isMutable: Boolean): IrField = createField( - irFunction.startOffset, - irFunction.endOffset, - type, - name, - isMutable, - DECLARATION_ORIGIN_COROUTINE_IMPL, - coroutineClassDescriptor - ).also { - coroutineClass.addChild(it) - } - - private fun createDoResumeMethodBuilder(doResumeFunction: IrFunction, coroutineClass: IrClass) - = object: SymbolWithIrBuilder() { - - override fun buildSymbol() = IrSimpleFunctionSymbolImpl( - doResumeFunction.descriptor.createOverriddenDescriptor(coroutineClassDescriptor) - ) - - override fun doInitialize() { } - - override fun buildIr(): IrSimpleFunction { - val originalBody = irFunction.body!! - val startOffset = irFunction.startOffset - val endOffset = irFunction.endOffset - val function = IrFunctionImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = DECLARATION_ORIGIN_COROUTINE_IMPL, - symbol = symbol).apply { - - returnType = context.irBuiltIns.anyNType - parent = coroutineClass - - this.createDispatchReceiverParameter() - - doResumeFunction.valueParameters.mapIndexedTo(this.valueParameters) { index, it -> - it.copy(descriptor.valueParameters[index]) - } - - } - - dataArgument = function.valueParameters[0] - exceptionArgument = function.valueParameters[1] - suspendResult = JsIrBuilder.buildVar(IrVariableSymbolImpl( - IrTemporaryVariableDescriptorImpl( - containingDeclaration = irFunction.descriptor, - name = "suspendResult".synthesizedName, - outType = context.builtIns.nullableAnyType, - isMutable = true - ) - ), JsIrBuilder.buildGetValue(dataArgument.symbol), context.irBuiltIns.anyNType) - suspendState = JsIrBuilder.buildVar(IrVariableSymbolImpl( - IrTemporaryVariableDescriptorImpl( - containingDeclaration = irFunction.descriptor, - name = "suspendState".synthesizedName, - outType = coroutineImplLabelFieldSymbol.owner.type.toKotlinType(), - isMutable = true - ) - ), type = coroutineImplLabelFieldSymbol.owner.type) - - val body = - (originalBody as IrBlockBody).run { - IrBlockImpl( - startOffset, - endOffset, - context.irBuiltIns.unitType, - STATEMENT_ORIGIN_COROUTINE_IMPL, - statements - ) - } - - buildStateMachine(body, function) - - return function + private fun addField(name: Name, type: IrType, isMutable: Boolean): IrField { + val descriptor = WrappedPropertyDescriptor() + val symbol = IrFieldSymbolImpl(descriptor) + return IrFieldImpl( + irFunction.startOffset, + irFunction.endOffset, + DECLARATION_ORIGIN_COROUTINE_IMPL, + symbol, + name, + type, + Visibilities.PRIVATE, + !isMutable, + false, + false + ).also { + descriptor.bind(it) + it.parent = coroutineClass + coroutineClass.addChild(it) } } + private fun createDoResumeMethodBuilder(doResumeFunction: IrSimpleFunction, coroutineClass: IrClass) = + object : SymbolWithIrBuilder() { + + private val descriptor = WrappedSimpleFunctionDescriptor() + + override fun buildSymbol() = IrSimpleFunctionSymbolImpl(descriptor) + + override fun doInitialize() {} + + override fun buildIr(): IrSimpleFunction { + val originalBody = irFunction.body!! + val function = IrFunctionImpl( + irFunction.startOffset, irFunction.endOffset, DECLARATION_ORIGIN_COROUTINE_IMPL, symbol, + doResumeFunction.name, + doResumeFunction.visibility, + Modality.FINAL, + doResumeFunction.isInline, + doResumeFunction.isExternal, + doResumeFunction.isTailrec, + doResumeFunction.isSuspend + ) + + descriptor.bind(function) + function.overriddenSymbols += doResumeFunction.symbol + function.parent = coroutineClass + function.returnType = context.irBuiltIns.anyNType + function.dispatchReceiverParameter = coroutineClassThis + doResumeFunction.valueParameters.mapTo(function.valueParameters) { + JsIrBuilder.buildValueParameter(it.name, it.index, it.type, it.origin).also { p -> p.parent = function } + } + + dataArgument = function.valueParameters[0] + exceptionArgument = function.valueParameters[1] + suspendResult = JsIrBuilder.buildVar(context.irBuiltIns.anyNType, "suspendResult", true).also { + it.parent = function + it.initializer = JsIrBuilder.buildGetValue(dataArgument.symbol) + } + + suspendState = JsIrBuilder.buildVar(coroutineImplLabelFieldSymbol.owner.type, "suspendState", true).also { + it.parent = function + } + + val body = + (originalBody as IrBlockBody).run { + IrBlockImpl( + irFunction.startOffset, + irFunction.endOffset, + context.irBuiltIns.unitType, + STATEMENT_ORIGIN_COROUTINE_IMPL, + statements + ) + } + + buildStateMachine(body, function) + + return function + } + } + private fun setupExceptionState() { for (it in coroutineConstructors) { (it.body as? IrBlockBody)?.run { @@ -799,12 +828,8 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo private fun buildStateMachine(body: IrBlock, function: IrFunction) { val unit = context.irBuiltIns.unitType - val switch = IrWhenImpl(body.startOffset, body.endOffset, unit, - COROUTINE_SWITCH - ) - val rootTry = IrTryImpl(body.startOffset, body.endOffset, unit).apply { - tryResult = switch - } + val switch = IrWhenImpl(body.startOffset, body.endOffset, unit, COROUTINE_SWITCH) + val rootTry = IrTryImpl(body.startOffset, body.endOffset, unit).apply { tryResult = switch } val rootLoop = IrDoWhileLoopImpl( body.startOffset, body.endOffset, @@ -882,18 +907,11 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo } irFunction.explicitParameters.forEach { localToPropertyMap.getOrPut(it.symbol) { - argumentToPropertiesMap.getValue(it.descriptor).symbol + argumentToPropertiesMap.getValue(it).symbol } } - function.transform( - LiveLocalsTransformer( - localToPropertyMap, - JsIrBuilder.buildGetValue( - thisReceiver - ), - unit - ), null) + function.transform(LiveLocalsTransformer(localToPropertyMap, JsIrBuilder.buildGetValue(thisReceiver), unit), null) } private fun computeLivenessAtSuspensionPoints(body: IrBody): Map> { @@ -902,12 +920,12 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo val result = mutableMapOf>() body.acceptChildrenVoid(object : VariablesScopeTracker() { override fun visitCall(expression: IrCall) { - if (!expression.descriptor.isSuspend) return super.visitCall(expression) + if (!expression.isSuspend) return super.visitCall(expression) expression.acceptChildrenVoid(this) val visibleVariables = mutableListOf() scopeStack.forEach { visibleVariables += it } - result.put(expression, visibleVariables) + result[expression] = visibleVariables } }) @@ -915,7 +933,7 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo } } - private open class VariablesScopeTracker: IrElementVisitorVoid { + private open class VariablesScopeTracker : IrElementVisitorVoid { protected val scopeStack = mutableListOf>(mutableSetOf()) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendLoweringUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendLoweringUtils.kt index 0d2ee1b9ca9..007232a56f2 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendLoweringUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendLoweringUtils.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower.coroutines +import org.jetbrains.kotlin.backend.common.ir.isSuspend import org.jetbrains.kotlin.backend.common.lower.FinallyBlocksLowering import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push @@ -44,7 +45,7 @@ open class SuspendableNodesCollector(protected val suspendableNodes: MutableSet< override fun visitCall(expression: IrCall) { super.visitCall(expression) - if (expression.descriptor.isSuspend) { + if (expression.isSuspend) { suspendableNodes += expression hasSuspendableChildren = true } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/DeepCopyIrTreeWithDescriptors.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/DeepCopyIrTreeWithDescriptors.kt index 268a612656f..b069d12e1e1 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/DeepCopyIrTreeWithDescriptors.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/DeepCopyIrTreeWithDescriptors.kt @@ -493,7 +493,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr return IrCallImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, - type = newDescriptor.returnType?.toIrType()!!, + type = newDescriptor.returnType?.toIrType(context.symbolTable)!!, descriptor = newDescriptor, typeArgumentsCount = expression.typeArgumentsCount, origin = expression.origin, @@ -625,7 +625,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr //-------------------------------------------------------------------------// - private fun substituteType(oldType: IrType?): IrType? = substituteType(oldType?.toKotlinType())?.toIrType() + private fun substituteType(oldType: IrType?): IrType? = substituteType(oldType?.toKotlinType())?.toIrType(context.symbolTable) private fun substituteType(oldType: KotlinType?): KotlinType? { if (typeSubstitutor == null) return oldType diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt index 478527f4f85..af2c7d5477c 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt @@ -15,7 +15,6 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext -import org.jetbrains.kotlin.ir.backend.js.utils.propertyIfAccessor import org.jetbrains.kotlin.ir.builders.irCall import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.builders.irReturn diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUnboundSymbolReplacer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUnboundSymbolReplacer.kt index 08f4e0bfbdc..07fdcd1bcde 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUnboundSymbolReplacer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUnboundSymbolReplacer.kt @@ -171,7 +171,7 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { - IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.descriptor.toIrType()) + IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.descriptor.toIrType(symbolTable = symbolTable)) } } @@ -293,8 +293,8 @@ private class IrUnboundSymbolReplacer( expression.replaceTypeArguments() val field = expression.field?.replaceOrSame(SymbolTable::referenceField) - val getter = expression.getter?.replace(SymbolTable::referenceFunction) ?: expression.getter - val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter + val getter = expression.getter?.replace(SymbolTable::referenceSimpleFunction) ?: expression.getter + val setter = expression.setter?.replace(SymbolTable::referenceSimpleFunction) ?: expression.setter if (field == expression.field && getter == expression.getter && setter == expression.setter) { return super.visitPropertyReference(expression) @@ -316,8 +316,8 @@ private class IrUnboundSymbolReplacer( override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression { val delegate = expression.delegate.replaceOrSame(SymbolTable::referenceVariable) - val getter = expression.getter.replace(SymbolTable::referenceFunction) ?: expression.getter - val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter + val getter = expression.getter.replace(SymbolTable::referenceSimpleFunction) ?: expression.getter + val setter = expression.setter?.replace(SymbolTable::referenceSimpleFunction) ?: expression.setter if (delegate == expression.delegate && getter == expression.getter && setter == expression.setter) { return super.visitLocalDelegatedPropertyReference(expression) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUtils2.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUtils2.kt index 93c97f26fee..39a97c3d0f5 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUtils2.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUtils2.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.ir.backend.js.lower.inline +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer @@ -43,3 +45,9 @@ object SetDeclarationsParentVisitor : IrElementVisitor IrExpression>() } @@ -91,7 +90,7 @@ private class ReturnableBlockTransformer( } override fun visitDeclaration(declaration: IrDeclaration, data: ReturnableBlockLoweringContext): IrStatement { - if (declaration is IrSymbolOwner) { + if (declaration is IrDeclarationParent) { declaration.transformChildren(this, ReturnableBlockLoweringContext(declaration)) } return super.visitDeclaration(declaration, data) @@ -103,12 +102,8 @@ private class ReturnableBlockTransformer( if (expression !is IrReturnableBlock) return super.visitContainerExpression(expression, data) val variable by lazy { - JsSymbolBuilder.buildTempVar( - data.containingDeclaration.symbol, - expression.type, - "tmp\$ret\$${data.labelCnt++}", - true - ) + JsIrBuilder.buildVar(expression.type, "tmp\$ret\$${data.labelCnt++}", true) + .also { it.parent = data.containingDeclaration } } val loop by lazy { @@ -133,7 +128,7 @@ private class ReturnableBlockTransformer( returnExpression.endOffset, context.irBuiltIns.unitType ).apply { - statements += JsIrBuilder.buildSetVariable(variable, returnExpression.value, context.irBuiltIns.unitType) + statements += JsIrBuilder.buildSetVariable(variable.symbol, returnExpression.value, context.irBuiltIns.unitType) statements += JsIrBuilder.buildBreak(context.irBuiltIns.unitType, loop) } } @@ -142,7 +137,7 @@ private class ReturnableBlockTransformer( if (i == expression.statements.lastIndex && s is IrReturn && s.returnTargetSymbol == expression.symbol) { s.transformChildren(this, data) if (!hasReturned) s.value else { - JsIrBuilder.buildSetVariable(variable, s.value, context.irBuiltIns.unitType) + JsIrBuilder.buildSetVariable(variable.symbol, s.value, context.irBuiltIns.unitType) } } else { s.transform(this, data) @@ -174,9 +169,9 @@ private class ReturnableBlockTransformer( expression.type, expression.origin ).apply { - statements += JsIrBuilder.buildVar(variable, type = expression.type) + statements += variable statements += loop - statements += JsIrBuilder.buildGetValue(variable) + statements += JsIrBuilder.buildGetValue(variable.symbol) } } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/symbols/SymbolBuilder.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/symbols/SymbolBuilder.kt deleted file mode 100644 index 8a0e5b646ea..00000000000 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/symbols/SymbolBuilder.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.ir.backend.js.symbols - -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl -import org.jetbrains.kotlin.ir.backend.js.utils.createValueParameter -import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl -import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.types.toKotlinType -import org.jetbrains.kotlin.name.Name - -object JsSymbolBuilder { - fun buildValueParameter(containingSymbol: IrSimpleFunctionSymbol, index: Int, type: IrType, name: String? = null) = - IrValueParameterSymbolImpl(createValueParameter(containingSymbol.descriptor, index, name ?: "param$index", type.toKotlinType())) - - fun buildSimpleFunction( - containingDeclaration: DeclarationDescriptor, - name: String, - annotations: Annotations = Annotations.EMPTY, - kind: CallableMemberDescriptor.Kind = CallableMemberDescriptor.Kind.SYNTHESIZED, - source: SourceElement = SourceElement.NO_SOURCE - ) = IrSimpleFunctionSymbolImpl( - SimpleFunctionDescriptorImpl.create( - containingDeclaration, - annotations, - Name.identifier(name), - kind, - source - ) - ) - - fun copyFunctionSymbol(symbol: IrFunctionSymbol, newName: String) = IrSimpleFunctionSymbolImpl( - SimpleFunctionDescriptorImpl.create( - symbol.descriptor.containingDeclaration, - symbol.descriptor.annotations, - Name.identifier(newName), - symbol.descriptor.kind, - symbol.descriptor.source - ) - ) - - fun buildVar( - containingDeclaration: DeclarationDescriptor, - type: IrType, - name: String, - mutable: Boolean = false - ) = IrVariableSymbolImpl( - LocalVariableDescriptor( - containingDeclaration, - Annotations.EMPTY, - Name.identifier(name), - type.toKotlinType(), - mutable, - false, - SourceElement.NO_SOURCE - ) - ) - - fun buildTempVar(containingSymbol: IrSymbol, type: IrType, name: String? = null, mutable: Boolean = false) = - buildTempVar(containingSymbol.descriptor, type, name, mutable) - - fun buildTempVar(containingDeclaration: DeclarationDescriptor, type: IrType, name: String? = null, mutable: Boolean = false) = - IrVariableSymbolImpl( - IrTemporaryVariableDescriptorImpl( - containingDeclaration, - Name.identifier(name ?: "tmp"), - type.toKotlinType(), mutable - ) - ) -} - - -fun IrSimpleFunctionSymbol.initialize( - extensionReceiverParameter: ReceiverParameterDescriptor? = null, - dispatchParameterDescriptor: ReceiverParameterDescriptor? = null, - typeParameters: List = emptyList(), - valueParameters: List = emptyList(), - returnType: IrType? = null, - modality: Modality = Modality.FINAL, - visibility: Visibility = Visibilities.LOCAL -) = this.apply { - (descriptor as FunctionDescriptorImpl).initialize( - extensionReceiverParameter, - dispatchParameterDescriptor, - typeParameters, - valueParameters, - returnType?.toKotlinType(), - modality, - visibility - ) -} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrDeclarationToJsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrDeclarationToJsTransformer.kt index 56245a3c34f..e55327f7344 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrDeclarationToJsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrDeclarationToJsTransformer.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.js.backend.ast.JsEmpty import org.jetbrains.kotlin.js.backend.ast.JsStatement import org.jetbrains.kotlin.js.backend.ast.JsVars @@ -27,6 +28,8 @@ class IrDeclarationToJsTransformer : BaseIrElementToJsNodeTransformer { +class IrModuleToJsTransformer(private val backendContext: JsIrBackendContext) : BaseIrElementToJsNodeTransformer { override fun visitModuleFragment(declaration: IrModuleFragment, data: Nothing?): JsNode { val program = JsProgram() val rootContext = JsGenerationContext(JsRootScope(program), backendContext) // TODO: fix it up with new name generator - val symbolTable = backendContext.symbolTable - - val anySymbol = symbolTable.referenceClass(backendContext.builtIns.any) - val throwableSymbol = symbolTable.referenceClass(backendContext.builtIns.throwable) - val anyName = rootContext.getNameForSymbol(anySymbol) - val throwableName = rootContext.getNameForSymbol(throwableSymbol) + val anyName = rootContext.getNameForSymbol(backendContext.irBuiltIns.anyClass) + val throwableName = rootContext.getNameForSymbol(backendContext.irBuiltIns.throwableClass) program.globalBlock.statements += JsVars(JsVars.JsVar(anyName, Namer.JS_OBJECT)) program.globalBlock.statements += JsVars(JsVars.JsVar(throwableName, Namer.JS_ERROR)) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt index 15f00569c03..0d5701c7a3e 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt @@ -6,19 +6,11 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs import org.jetbrains.kotlin.backend.common.onlyIf -import org.jetbrains.kotlin.backend.common.utils.isBuiltinFunctionalTypeOrSubtype -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.Namer -import org.jetbrains.kotlin.ir.backend.js.utils.isEffectivelyExternal -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction -import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.isAny import org.jetbrains.kotlin.ir.util.* @@ -29,7 +21,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo private val className = context.getNameForSymbol(irClass.symbol) private val classNameRef = className.makeRef() private val baseClass = irClass.superTypes.firstOrNull { !it.classifierOrFail.isInterface } - private val baseClassName = baseClass?.let { context.getNameForSymbol(it.classifierOrFail) } + private val baseClassName = baseClass?.let { context.getNameForType(it) } private val classPrototypeRef = prototypeOf(classNameRef) private val classBlock = JsGlobalBlock() private val classModel = JsClassModel(className, baseClassName) @@ -83,10 +75,10 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo // II.prototype.foo = I.prototype.foo if (!irClass.isInterface) { declaration.resolveFakeOverride()?.let { - val implClassDesc = it.descriptor.containingDeclaration as ClassDescriptor - if (!KotlinBuiltIns.isAny(implClassDesc) && !it.isEffectivelyExternal()) { + val implClassDeclaration = it.parent as IrClass + if (!implClassDeclaration.defaultType.isAny() && !it.isEffectivelyExternal()) { val implMethodName = context.getNameForSymbol(it.symbol) - val implClassName = context.getNameForSymbol(IrClassSymbolImpl(implClassDesc)) + val implClassName = context.getNameForSymbol(implClassDeclaration.symbol) val implClassPrototype = prototypeOf(implClassName.makeRef()) val implMemberRef = JsNameRef(implMethodName, implClassPrototype) @@ -167,16 +159,22 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo return jsAssignment(JsNameRef(Namer.METADATA, classNameRef), metadataLiteral).makeStmt() } - private fun generateSuperClasses(): JsPropertyInitializer = JsPropertyInitializer( - JsNameRef(Namer.METADATA_INTERFACES), - JsArrayLiteral( - irClass.superTypes.mapNotNull { - val symbol = it.classifierOrFail - // TODO: make sure that there is a test which breaks when isExternal is used here instead of isEffectivelyExternal - if (symbol.isInterface && !irClass.defaultType.isBuiltinFunctionalTypeOrSubtype() && !symbol.isEffectivelyExternal()) JsNameRef(context.getNameForSymbol(symbol)) else null - } + private fun generateSuperClasses(): JsPropertyInitializer { + val functionTypeOrSubtype = irClass.defaultType.isFunctionTypeOrSubtype() + return JsPropertyInitializer( + JsNameRef(Namer.METADATA_INTERFACES), + JsArrayLiteral( + irClass.superTypes.mapNotNull { + val symbol = it.classifierOrFail + // TODO: make sure that there is a test which breaks when isExternal is used here instead of isEffectivelyExternal + if (symbol.isInterface && !functionTypeOrSubtype && !symbol.isEffectivelyExternal) { + JsNameRef(context.getNameForSymbol(symbol)) + } else null + } + ) ) - ) + } } -private val IrClassifierSymbol.isInterface get() = (owner as? IrClass)?.isInterface == true \ No newline at end of file +private val IrClassifierSymbol.isInterface get() = (owner as? IrClass)?.isInterface == true +private val IrClassifierSymbol.isEffectivelyExternal get() = (owner as? IrDeclaration)?.isEffectivelyExternal() == true \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt index 4aed1bb5d9d..706793b7db8 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt @@ -95,13 +95,6 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { typeName.makeRef() } - add(backendContext.sharedVariablesManager.closureBoxConstructorTypeSymbol) { call, context -> - val args = translateCallArguments(call, context) - val initializer = args[0] - val propertyInit = JsPropertyInitializer(JsNameRef("v"), initializer) - JsObjectLiteral(listOf(propertyInit)) - } - addIfNotNull(intrinsics.jsCode) { call, context -> val jsCode = translateJsCode(call, context.currentScope) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt index 9bdf4059b71..fc07009ded3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.js.backend.ast.* class JsGenerationContext { @@ -44,6 +45,8 @@ class JsGenerationContext { } fun getNameForSymbol(symbol: IrSymbol): JsName = staticContext.getNameForSymbol(symbol, this) + fun getNameForType(type: IrType): JsName = staticContext.getNameForType(type, this) +// fun getNameForReceiver(symbol: IrValueSymbol, isExt: Boolean): JsName = staticContext.getNameForReceiver(symbol, isExt, this) fun getNameForLoop(loop: IrLoop): JsName? = staticContext.getNameForLoop(loop, this) val continuation diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt index 22055b03c8e..77abbed9b3c 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIntrinsicTransfo import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.js.backend.ast.JsClassModel import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock import org.jetbrains.kotlin.js.backend.ast.JsName @@ -17,10 +18,10 @@ import org.jetbrains.kotlin.js.backend.ast.JsRootScope class JsStaticContext( - private val rootScope: JsRootScope, + val rootScope: JsRootScope, private val globalBlock: JsGlobalBlock, private val nameGenerator: NameGenerator, - backendContext: JsIrBackendContext + val backendContext: JsIrBackendContext ) { val intrinsics = JsIntrinsicTransformers(backendContext) // TODO: use IrSymbol instead of JsName @@ -32,5 +33,6 @@ class JsStaticContext( val initializerBlock = JsGlobalBlock() fun getNameForSymbol(irSymbol: IrSymbol, context: JsGenerationContext) = nameGenerator.getNameForSymbol(irSymbol, context) + fun getNameForType(type: IrType, context: JsGenerationContext) = nameGenerator.getNameForType(type, context) fun getNameForLoop(loop: IrLoop, context: JsGenerationContext) = nameGenerator.getNameForLoop(loop, context) } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameGenerator.kt index 981c691af12..0b7d219cbbc 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameGenerator.kt @@ -7,9 +7,11 @@ package org.jetbrains.kotlin.ir.backend.js.utils import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.js.backend.ast.JsName interface NameGenerator { fun getNameForSymbol(symbol: IrSymbol, context: JsGenerationContext): JsName + fun getNameForType(type: IrType, context: JsGenerationContext): JsName fun getNameForLoop(loop: IrLoop, context: JsGenerationContext): JsName? } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt index 25ae5c3ab3e..5cf697f441e 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt @@ -6,118 +6,175 @@ package org.jetbrains.kotlin.ir.backend.js.utils import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.util.isDynamic +import org.jetbrains.kotlin.ir.util.isEffectivelyExternal +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.js.backend.ast.JsName import org.jetbrains.kotlin.js.naming.isES5IdentifierPart import org.jetbrains.kotlin.js.naming.isES5IdentifierStart import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal -import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver -import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty +// TODO: this class has to be reimplemented soon class SimpleNameGenerator : NameGenerator { - private val nameCache = mutableMapOf() + private val nameCache = mutableMapOf() private val loopCache = mutableMapOf() - override fun getNameForSymbol(symbol: IrSymbol, context: JsGenerationContext): JsName = getNameForDescriptor(symbol.descriptor, context) + override fun getNameForSymbol(symbol: IrSymbol, context: JsGenerationContext): JsName = + if (symbol.isBound) getNameForDeclaration(symbol.owner as IrDeclaration, context) else + declareDynamic(symbol.descriptor, context) + override fun getNameForLoop(loop: IrLoop, context: JsGenerationContext): JsName? = loop.label?.let { loopCache.getOrPut(loop) { context.currentScope.declareFreshName(sanitizeName(loop.label!!)) } } + override fun getNameForType(type: IrType, context: JsGenerationContext) = + getNameForDeclaration(type.classifierOrFail.owner as IrDeclaration, context) - private fun getNameForDescriptor(descriptor: DeclarationDescriptor, context: JsGenerationContext): JsName = - nameCache.getOrPut(descriptor) { + @Deprecated("Descriptors-based code is deprecated") + private fun declareDynamic(descriptor: DeclarationDescriptor, context: JsGenerationContext): JsName { + if (descriptor.isDynamic()) { + return context.currentScope.declareName(descriptor.name.asString()) + } + + if (descriptor is MemberDescriptor && descriptor.isEffectivelyExternal()) { + val descriptorForName = when (descriptor) { + is ConstructorDescriptor -> descriptor.constructedClass + is PropertyAccessorDescriptor -> descriptor.correspondingProperty + else -> descriptor + } + return context.currentScope.declareName(descriptorForName.name.asString()) + } + + throw IllegalStateException("Unbound non-dynamic symbol") + } + + private val RESERVED_IDENTIFIERS = setOf( + // keywords + "await", "break", "case", "catch", "continue", "debugger", "default", "delete", "do", "else", "finally", "for", "function", "if", + "in", "instanceof", "new", "return", "switch", "throw", "try", "typeof", "var", "void", "while", "with", + + // future reserved words + "class", "const", "enum", "export", "extends", "import", "super", + + // as future reserved words in strict mode + "implements", "interface", "let", "package", "private", "protected", "public", "static", "yield", + + // additional reserved words + // "null", "true", "false", + + // disallowed as variable names in strict mode + "eval", "arguments", + + // global identifiers usually declared in a typical JS interpreter + "NaN", "isNaN", "Infinity", "undefined", + + "Error", "Object", "Number", + + // "Math", "String", "Boolean", "Date", "Array", "RegExp", "JSON", + + // global identifiers usually declared in know environments (node.js, browser, require.js, WebWorkers, etc) + // "require", "define", "module", "window", "self", + + // the special Kotlin object + "Kotlin" + ) + + private fun getNameForDeclaration(declaration: IrDeclaration, context: JsGenerationContext): JsName = + nameCache.getOrPut(declaration) { var nameDeclarator: (String) -> JsName = context.currentScope::declareName + val nameBuilder = StringBuilder() - if (descriptor.isDynamic()) { - return@getOrPut nameDeclarator(descriptor.name.asString()) + val descriptor = declaration.descriptor + + if (declaration.isDynamic) { + return@getOrPut nameDeclarator(declaration.descriptor.name.asString()) } - if (descriptor is MemberDescriptor && descriptor.isEffectivelyExternal()) { + if (declaration.isEffectivelyExternal()) { + // TODO: descriptors are still used here due to the corresponding declaration doesn't have enough information yet val descriptorForName = when (descriptor) { is ConstructorDescriptor -> descriptor.constructedClass is PropertyAccessorDescriptor -> descriptor.correspondingProperty else -> descriptor } - return@getOrPut nameDeclarator(descriptorForName.name.asString()) + return@getOrPut context.staticContext.rootScope.declareName(descriptorForName.name.asString()) } - val nameBuilder = StringBuilder() - when (descriptor) { - is ReceiverParameterDescriptor -> { - when (descriptor.value) { - is ExtensionReceiver -> nameBuilder.append(Namer.EXTENSION_RECEIVER_NAME) - is ImplicitClassReceiver -> nameBuilder.append(Namer.IMPLICIT_RECEIVER_NAME) - else -> TODO("name for $descriptor") - } - } - is ValueParameterDescriptor -> { - val declaredName = descriptor.name.asString() - nameBuilder.append(declaredName) - nameDeclarator = context.currentScope::declareFreshName - } - is PropertyDescriptor -> { - nameBuilder.append(descriptor.name.asString()) - if (descriptor.visibility == Visibilities.PRIVATE || descriptor.modality != Modality.FINAL) { - nameBuilder.append('$') - nameBuilder.append(getNameForDescriptor(descriptor.containingDeclaration, context)) - } - } - is PropertyAccessorDescriptor -> { - when (descriptor) { - is PropertyGetterDescriptor -> nameBuilder.append(Namer.GETTER_PREFIX) - is PropertySetterDescriptor -> nameBuilder.append(Namer.SETTER_PREFIX) - } - - nameBuilder.append(descriptor.correspondingProperty.name.asString()) - - descriptor.extensionReceiverParameter?.let { - nameBuilder.append("_r$${it.type}") - } - - if (descriptor.visibility == Visibilities.PRIVATE) { - nameBuilder.append('$') - nameBuilder.append(getNameForDescriptor(descriptor.containingDeclaration, context)) - } - } - is ClassDescriptor -> { - if (descriptor.name.isSpecial) { - nameBuilder.append(descriptor.name.asString().let { - it.substring(1, it.length - 1) + "${descriptor.hashCode()}" - }) + when (declaration) { + is IrValueParameter -> { + if ((context.currentFunction is IrConstructor && declaration.origin == IrDeclarationOrigin.INSTANCE_RECEIVER && declaration.name.isSpecial) || + declaration == context.currentFunction?.dispatchReceiverParameter + ) + nameBuilder.append(Namer.IMPLICIT_RECEIVER_NAME) + else if (declaration == context.currentFunction?.extensionReceiverParameter) { + nameBuilder.append(Namer.EXTENSION_RECEIVER_NAME) } else { - nameBuilder.append(descriptor.fqNameSafe.asString().replace('.', '$')) + val declaredName = declaration.name.asString() + nameBuilder.append(declaredName) + if (declaredName.startsWith("\$")) { + nameBuilder.append('.') + nameBuilder.append(declaration.index) + } + nameDeclarator = context.currentScope::declareFreshName } } - is ConstructorDescriptor -> { - nameBuilder.append(getNameForDescriptor(descriptor.constructedClass, context)) + is IrField -> { + nameBuilder.append(declaration.name.asString()) + if (declaration.parent is IrDeclaration) { + nameBuilder.append('.') + nameBuilder.append(getNameForDeclaration(declaration.parent as IrDeclaration, context)) + } } - is VariableDescriptor -> { - nameBuilder.append(descriptor.name.identifier) + is IrClass -> { + if (declaration.isCompanion) { + nameBuilder.append(getNameForDeclaration(declaration.parent as IrDeclaration, context)) + nameBuilder.append('.') + } + + nameBuilder.append(declaration.name.asString()) + + (declaration.parent as? IrClass)?.let { + nameBuilder.append("$") + nameBuilder.append(getNameForDeclaration(it, context)) + } + + + if (declaration.kind == ClassKind.OBJECT || declaration.name.isSpecial || declaration.visibility == Visibilities.LOCAL) { + nameDeclarator = context.staticContext.rootScope::declareFreshName + } + } + is IrConstructor -> { + nameBuilder.append(getNameForDeclaration(declaration.parent as IrClass, context)) + } + is IrVariable -> { + nameBuilder.append(declaration.name.identifier) nameDeclarator = context.currentScope::declareFreshName } - is CallableDescriptor -> { - nameBuilder.append(descriptor.name.asString()) - descriptor.typeParameters.ifNotEmpty { - nameBuilder.append("_\$t") - joinTo(nameBuilder, "") { "_${it.name}" } - } - descriptor.extensionReceiverParameter?.let { - nameBuilder.append("_r$${it.type}") - } - descriptor.valueParameters.ifNotEmpty { - joinTo(nameBuilder, "") { "_${it.type}" } - } + is IrSimpleFunction -> { + nameBuilder.append(declaration.name.asString()) + declaration.extensionReceiverParameter?.let { nameBuilder.append("_\$${it.type.render()}") } + declaration.typeParameters.forEach { nameBuilder.append("_${it.name.asString()}") } + declaration.valueParameters.forEach { nameBuilder.append("_${it.type.render()}") } } } + + if (nameBuilder.toString() in RESERVED_IDENTIFIERS) { + nameBuilder.append(0) + nameDeclarator = context.currentScope::declareFreshName + } + nameDeclarator(sanitizeName(nameBuilder.toString())) } + private fun sanitizeName(name: String): String { if (name.isEmpty()) return "_" diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/descriptorBasedUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/descriptorBasedUtils.kt deleted file mode 100644 index d208791a45b..00000000000 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/descriptorBasedUtils.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.ir.backend.js.utils - -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl -import org.jetbrains.kotlin.ir.declarations.IrDeclaration -import org.jetbrains.kotlin.ir.declarations.IrTypeParameter -import org.jetbrains.kotlin.ir.expressions.IrCall -import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic -import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal -import org.jetbrains.kotlin.types.KotlinType - -val IrConstructorSymbol.constructedClass get() = descriptor.constructedClass - -fun createValueParameter(containingDeclaration: CallableDescriptor, index: Int, name: String, type: KotlinType): ValueParameterDescriptor { - return ValueParameterDescriptorImpl( - containingDeclaration = containingDeclaration, - original = null, - index = index, - annotations = Annotations.EMPTY, - name = Name.identifier(name), - outType = type, - declaresDefaultValue = false, - isCrossinline = false, - isNoinline = false, - varargElementType = null, - source = SourceElement.NO_SOURCE - ) -} -val CallableMemberDescriptor.propertyIfAccessor - get() = if (this is PropertyAccessorDescriptor) - this.correspondingProperty - else this - -val IrTypeParameter.isReified - get() = descriptor.isReified - -// Return is method has no real implementation except fake overrides from Any -fun CallableMemberDescriptor.isFakeOverriddenFromAny(): Boolean { - if (kind.isReal) { - return (containingDeclaration is ClassDescriptor) && KotlinBuiltIns.isAny(containingDeclaration as ClassDescriptor) - } - return overriddenDescriptors.all { it.isFakeOverriddenFromAny() } -} - -fun IrDeclaration.isEffectivelyExternal() = descriptor.isEffectivelyExternal() - -fun IrSymbol.isEffectivelyExternal() = descriptor.isEffectivelyExternal() - -fun IrSymbol.isDynamic() = descriptor.isDynamic() - -fun IrCall.isSuperToAny() = - superQualifier?.let { this.symbol.owner.descriptor.isFakeOverriddenFromAny() } ?: false - diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index 48928b0d6be..92c6a274d36 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.ReflectionTypes import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Symbols -import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDescriptorsFactory +import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDeclarationFactory import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -34,7 +34,7 @@ class JvmBackendContext( irModuleFragment: IrModuleFragment, symbolTable: SymbolTable ) : CommonBackendContext { override val builtIns = state.module.builtIns - override val descriptorsFactory: JvmDescriptorsFactory = JvmDescriptorsFactory(psiSourceManager, builtIns) + override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(psiSourceManager, builtIns) override val sharedVariablesManager = JvmSharedVariablesManager(builtIns, irBuiltIns) override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 5f467b29258..802e17f0980 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -53,7 +53,8 @@ class JvmLower(val context: JvmBackendContext) { override fun localName(descriptor: DeclarationDescriptor): String = NameUtils.sanitizeAsJavaIdentifier(super.localName(descriptor)) }, - Visibilities.PUBLIC //TODO properly figure out visibility + Visibilities.PUBLIC, //TODO properly figure out visibility + true ).runOnFilePostfix(irFile) CallableReferenceLowering(context).lower(irFile) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDescriptorsFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDeclarationFactory.kt similarity index 63% rename from compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDescriptorsFactory.kt rename to compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDeclarationFactory.kt index 69fe51f1af8..564c57029c1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDescriptorsFactory.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDeclarationFactory.kt @@ -5,7 +5,8 @@ package org.jetbrains.kotlin.backend.jvm.descriptors -import org.jetbrains.kotlin.backend.common.descriptors.DescriptorsFactory +import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.builtins.CompanionObjectMapping.isMappedIntrinsicCompanionObject import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.codegen.descriptors.FileClassDescriptor @@ -15,11 +16,16 @@ import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.ir.SourceManager -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.toIrType import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.dump @@ -30,17 +36,24 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.org.objectweb.asm.Opcodes import java.util.* -class JvmDescriptorsFactory( +class JvmDeclarationFactory( private val psiSourceManager: PsiSourceManager, private val builtIns: KotlinBuiltIns -) : DescriptorsFactory { - private val singletonFieldDescriptors = HashMap, IrFieldSymbol>() - private val outerThisDescriptors = HashMap() - private val innerClassConstructors = HashMap() +) : DeclarationFactory { + private val singletonFieldDeclarations = HashMap() + private val outerThisDeclarations = HashMap() + private val innerClassConstructors = HashMap() - override fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol = - singletonFieldDescriptors.getOrPut(enumEntry) { - IrFieldSymbolImpl(createEnumEntryFieldDescriptor(enumEntry.descriptor)) + override fun getFieldForEnumEntry(enumEntry: IrEnumEntry, type: IrType): IrField = + singletonFieldDeclarations.getOrPut(enumEntry) { + val symbol = IrFieldSymbolImpl(createEnumEntryFieldDescriptor(enumEntry.descriptor)) + IrFieldImpl( + enumEntry.startOffset, + enumEntry.endOffset, + JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_ENTRY, + symbol, + type + ) } fun createFileClassDescriptor(fileEntry: SourceManager.FileEntry, packageFragment: PackageFragmentDescriptor): FileClassDescriptor { @@ -56,29 +69,33 @@ class JvmDescriptorsFactory( ) } - override fun getOuterThisFieldSymbol(innerClass: IrClass): IrFieldSymbol = + override fun getOuterThisField(innerClass: IrClass): IrField = if (!innerClass.isInner) throw AssertionError("Class is not inner: ${innerClass.dump()}") - else outerThisDescriptors.getOrPut(innerClass) { + else outerThisDeclarations.getOrPut(innerClass) { val outerClass = innerClass.parent as? IrClass ?: throw AssertionError("No containing class for inner class ${innerClass.dump()}") - IrFieldSymbolImpl( + val symbol = IrFieldSymbolImpl( JvmPropertyDescriptorImpl.createFinalField( Name.identifier("this$0"), outerClass.defaultType.toKotlinType(), innerClass.descriptor, Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE ) ) + + IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, DeclarationFactory.FIELD_FOR_OUTER_THIS, symbol, outerClass.defaultType).also { + it.parent = innerClass + } } - override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructorSymbol { + override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructor { assert((innerClassConstructor.parent as IrClass).isInner) { "Class is not inner: ${(innerClassConstructor.parent as IrClass).dump()}" } - return innerClassConstructors.getOrPut(innerClassConstructor.symbol) { + return innerClassConstructors.getOrPut(innerClassConstructor) { createInnerClassConstructorWithOuterThisParameter(innerClassConstructor) } } - private fun createInnerClassConstructorWithOuterThisParameter(oldConstructor: IrConstructor): IrConstructorSymbol { + private fun createInnerClassConstructorWithOuterThisParameter(oldConstructor: IrConstructor): IrConstructor { val oldDescriptor = oldConstructor.descriptor val classDescriptor = oldDescriptor.containingDeclaration val outerThisType = (classDescriptor.containingDeclaration as ClassDescriptor).defaultType @@ -102,7 +119,26 @@ class JvmDescriptorsFactory( oldDescriptor.returnType, oldDescriptor.modality, oldDescriptor.visibility) - return IrConstructorSymbolImpl(newDescriptor) + val symbol = IrConstructorSymbolImpl(newDescriptor) + return IrConstructorImpl(oldConstructor.startOffset, oldConstructor.endOffset, oldConstructor.origin, symbol).also { constructor -> + newValueParameters.mapIndexedTo(constructor.valueParameters) { i, v -> + constructor.parent = oldConstructor.parent + constructor.returnType = oldConstructor.returnType + if (i == 0) { + IrValueParameterImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + JvmLoweredDeclarationOrigin.FIELD_FOR_OUTER_THIS, IrValueParameterSymbolImpl(v), outerThisType.toIrType()!!, null) + } else { + val oldParameter = oldConstructor.valueParameters[i - 1] + IrValueParameterImpl( + oldParameter.startOffset, oldParameter.endOffset, oldParameter.origin, + IrValueParameterSymbolImpl(v), oldParameter.type, oldParameter.varargElementType + ).also { + it.defaultValue = oldParameter.defaultValue + } + } + } + } } @@ -124,9 +160,16 @@ class JvmDescriptorsFactory( ) } - override fun getSymbolForObjectInstance(singleton: IrClassSymbol): IrFieldSymbol = - singletonFieldDescriptors.getOrPut(singleton) { - IrFieldSymbolImpl(createObjectInstanceFieldDescriptor(singleton.descriptor)) + override fun getFieldForObjectInstance(singleton: IrClass): IrField = + singletonFieldDeclarations.getOrPut(singleton) { + val symbol = IrFieldSymbolImpl(createObjectInstanceFieldDescriptor(singleton.descriptor)) + return IrFieldImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + JvmLoweredDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE, + symbol, + singleton.defaultType + ) } private fun createObjectInstanceFieldDescriptor(objectDescriptor: ClassDescriptor): PropertyDescriptor { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/SharedVariablesManager.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/SharedVariablesManager.kt index eb630b16eb2..83bf97ea2c8 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/SharedVariablesManager.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/SharedVariablesManager.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.descriptors import org.jetbrains.kotlin.backend.common.descriptors.KnownClassDescriptor import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor -import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager +import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.descriptors.* @@ -16,20 +16,32 @@ import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.IrSetVariable import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol import org.jetbrains.kotlin.ir.types.toIrType import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.* +private val SHARED_VARIABLE_ORIGIN = object : IrDeclarationOriginImpl("SHARED_VARIABLE_ORIGIN") {} + class JvmSharedVariablesManager( val builtIns: KotlinBuiltIns, val irBuiltIns: IrBuiltIns @@ -47,6 +59,8 @@ class JvmSharedVariablesManager( returnType = refType } + val refConstructorSymbol = IrConstructorSymbolImpl(refConstructor) + val elementField: PropertyDescriptor = PropertyDescriptorImpl.create( refClass, Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC, true, @@ -54,6 +68,10 @@ class JvmSharedVariablesManager( /* lateInit = */ false, /* isConst = */ false, /* isExpect = */ false, /* isActual = */ false, /* isExternal = */ false, /* isDelegated = */ false ).initialize(type, dispatchReceiverParameter = refClass.thisAsReceiverParameter) + + val elementFieldSymbol = IrFieldSymbolImpl(elementField) + val elementFieldDeclaration = + IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SHARED_VARIABLE_ORIGIN, elementFieldSymbol, type.toIrType()!!) } private val primitiveRefDescriptorProviders: Map = @@ -111,6 +129,11 @@ class JvmSharedVariablesManager( dispatchReceiverParameter = genericRefClass.thisAsReceiverParameter ) + val genericElementFieldSymbol = IrFieldSymbolImpl(genericElementField) + val elementFieldDeclaration = + IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SHARED_VARIABLE_ORIGIN, genericElementFieldSymbol, irBuiltIns.anyType) + + fun getRefType(valueType: KotlinType) = KotlinTypeFactory.simpleNotNullType( Annotations.EMPTY, @@ -128,6 +151,7 @@ class JvmSharedVariablesManager( getSharedVariableType(variableDescriptor.type), false, false, variableDescriptor.isLateInit, variableDescriptor.source ) + val sharedVariableSymbol = IrVariableSymbolImpl(sharedVariableDescriptor) val valueType = originalDeclaration.descriptor.type val primitiveRefDescriptorsProvider = primitiveRefDescriptorProviders[getPrimitiveType(valueType)] @@ -135,6 +159,12 @@ class JvmSharedVariablesManager( val refConstructor = primitiveRefDescriptorsProvider?.refConstructor ?: objectRefDescriptorsProvider.getSubstitutedRefConstructor(valueType) + val refConstructorSymbol = + primitiveRefDescriptorsProvider?.refConstructorSymbol ?: createFunctionSymbol(refConstructor) as IrConstructorSymbol + + val refConstructorDeclaration = if (refConstructorSymbol.isBound) refConstructorSymbol.owner else + IrConstructorImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SHARED_VARIABLE_ORIGIN, refConstructorSymbol) + val refConstructorTypeArguments = if (primitiveRefDescriptorsProvider != null) null else mapOf(objectRefDescriptorsProvider.constructorTypeParameter to valueType) @@ -143,11 +173,12 @@ class JvmSharedVariablesManager( val refConstructorCall = IrCallImpl( originalDeclaration.startOffset, originalDeclaration.endOffset, refConstructor.constructedClass.defaultType.toIrType()!!, - refConstructor, refConstructorTypeArguments?.size ?: 0 + refConstructorSymbol, refConstructor, + refConstructorTypeArguments?.size ?: 0 ) return IrVariableImpl( originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin, - sharedVariableDescriptor, sharedVariableDescriptor.type.toIrType()!!, refConstructorCall + sharedVariableSymbol, sharedVariableDescriptor.type.toIrType()!!, refConstructorCall ) } @@ -160,12 +191,12 @@ class JvmSharedVariablesManager( val valueType = originalDeclaration.descriptor.type val primitiveRefDescriptorsProvider = primitiveRefDescriptorProviders[getPrimitiveType(valueType)] - val elementPropertyDescriptor = - primitiveRefDescriptorsProvider?.elementField ?: objectRefDescriptorsProvider.genericElementField + val elementPropertySymbol = + primitiveRefDescriptorsProvider?.elementFieldSymbol ?: objectRefDescriptorsProvider.genericElementFieldSymbol val sharedVariableInitialization = IrSetFieldImpl( initializer.startOffset, initializer.endOffset, - elementPropertyDescriptor, + elementPropertySymbol, IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableDeclaration.symbol), initializer, originalDeclaration.type @@ -177,34 +208,26 @@ class JvmSharedVariablesManager( ) } - private fun getElementFieldDescriptor(valueType: KotlinType): PropertyDescriptor { + private fun getElementFieldSymbol(valueType: KotlinType): IrFieldSymbol { val primitiveRefDescriptorsProvider = primitiveRefDescriptorProviders[getPrimitiveType(valueType)] - return primitiveRefDescriptorsProvider?.elementField ?: objectRefDescriptorsProvider.genericElementField + return primitiveRefDescriptorsProvider?.elementFieldSymbol ?: objectRefDescriptorsProvider.genericElementFieldSymbol } override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue): IrExpression = IrGetFieldImpl( originalGet.startOffset, originalGet.endOffset, - getElementFieldDescriptor(originalGet.descriptor.type), - IrGetValueImpl( - originalGet.startOffset, - originalGet.endOffset, - sharedVariableSymbol - ), + getElementFieldSymbol(originalGet.descriptor.type), originalGet.type, + IrGetValueImpl(originalGet.startOffset, originalGet.endOffset, sharedVariableSymbol), originalGet.origin ) override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetVariable): IrExpression = IrSetFieldImpl( originalSet.startOffset, originalSet.endOffset, - getElementFieldDescriptor(originalSet.descriptor.type), - IrGetValueImpl( - originalSet.startOffset, - originalSet.endOffset, - sharedVariableSymbol - ), + getElementFieldSymbol(originalSet.descriptor.type), + IrGetValueImpl(originalSet.startOffset, originalSet.endOffset, sharedVariableSymbol), originalSet.value, originalSet.type, originalSet.origin diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt index c0c0fcc620e..01071fa950b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt @@ -186,18 +186,12 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass { return enumEntryClass } - private fun createFieldForEnumEntry(enumEntry: IrEnumEntry): IrField { - val fieldSymbol = context.descriptorsFactory.getSymbolForEnumEntry(enumEntry.symbol) - - return IrFieldImpl( - enumEntry.startOffset, enumEntry.endOffset, JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_ENTRY, - fieldSymbol, enumEntry.initializerExpression!!.type - ).also { + private fun createFieldForEnumEntry(enumEntry: IrEnumEntry) = + context.declarationFactory.getFieldForEnumEntry(enumEntry, enumEntry.initializerExpression!!.type).also { it.initializer = IrExpressionBodyImpl(enumEntry.initializerExpression!!) enumEntryFields.add(it) enumEntriesByField[it] = enumEntry } - } private fun setupSynthesizedEnumClassMembers() { val irField = createSyntheticValuesFieldDeclaration() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt index 83d7a1c1e79..5643eb798c1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt @@ -39,7 +39,7 @@ class FileClassLowering(val context: JvmBackendContext) : FileLoweringPass { if (fileClassMembers.isEmpty()) return - val fileClassDescriptor = context.descriptorsFactory.createFileClassDescriptor(irFile.fileEntry, irFile.packageFragmentDescriptor) + val fileClassDescriptor = context.declarationFactory.createFileClassDescriptor(irFile.fileEntry, irFile.packageFragmentDescriptor) val irFileClass = IrClassImpl(0, irFile.fileEntry.maxOffset, IrDeclarationOrigin.DEFINED, fileClassDescriptor, fileClassMembers) classes.add(irFileClass) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt index e44bd1e8b2a..879dbdae793 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt @@ -142,12 +142,11 @@ internal fun FunctionDescriptor.createFunctionAndMapVariables( visibility = visibility ).apply { body = oldFunction.body + returnType = oldFunction.returnType createParameterDeclarations() - val mapping: Map = - ( - listOfNotNull(oldFunction.descriptor.dispatchReceiverParameter!!, oldFunction.descriptor.extensionReceiverParameter) + - oldFunction.descriptor.valueParameters - ).zip(valueParameters).toMap() + val mapping: Map = + (listOfNotNull(oldFunction.dispatchReceiverParameter!!, oldFunction.extensionReceiverParameter) + oldFunction.valueParameters) + .zip(valueParameters).toMap() body?.transform(VariableRemapper(mapping), null) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt index c48463b0f19..5e7076bc642 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt @@ -106,7 +106,8 @@ private class CompanionObjectJvmStaticLowering(val context: JvmBackendContext) : } private fun createProxyBody(target: IrFunction, proxy: IrFunction, companion: IrClass): IrBody { - val companionInstanceFieldSymbol = context.descriptorsFactory.getSymbolForObjectInstance(companion.symbol) + val companionInstanceField = context.declarationFactory.getFieldForObjectInstance(companion) + val companionInstanceFieldSymbol = companionInstanceField.symbol val call = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, target.returnType, target.symbol) call.dispatchReceiver = IrGetFieldImpl( @@ -147,9 +148,9 @@ private class SingletonObjectJvmStaticLowering( irClass.declarations.filter(::isJvmStaticFunction).forEach { val jvmStaticFunction = it as IrSimpleFunction - val oldDispatchReceiverParemeter = jvmStaticFunction.dispatchReceiverParameter!! + val oldDispatchReceiverParameter = jvmStaticFunction.dispatchReceiverParameter!! jvmStaticFunction.dispatchReceiverParameter = null - modifyBody(jvmStaticFunction, irClass, oldDispatchReceiverParemeter) + modifyBody(jvmStaticFunction, irClass, oldDispatchReceiverParameter) functionsMadeStatic.add(jvmStaticFunction.symbol) } } @@ -165,17 +166,16 @@ private class ReplaceThisByStaticReference( val oldThisReceiverParameter: IrValueParameter ) : IrElementTransformer { override fun visitGetValue(expression: IrGetValue, data: Nothing?): IrExpression { - val irGetValue = expression - if (irGetValue.symbol == oldThisReceiverParameter.symbol) { - val instanceSymbol = context.descriptorsFactory.getSymbolForObjectInstance(irClass.symbol) + if (expression.symbol == oldThisReceiverParameter.symbol) { + val instanceField = context.declarationFactory.getFieldForObjectInstance(irClass) return IrGetFieldImpl( expression.startOffset, expression.endOffset, - instanceSymbol, + instanceField.symbol, irClass.defaultType ) } - return super.visitGetValue(irGetValue, data) + return super.visitGetValue(expression, data) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt index 35f12aa2acb..c7d0f05dc26 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt @@ -47,7 +47,7 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer private fun process(irClass: IrClass) { if (!irClass.isObject) return - val publicInstance = context.descriptorsFactory.getSymbolForObjectInstance(irClass.symbol) + val publicInstanceField = context.declarationFactory.getFieldForObjectInstance(irClass) val constructor = irClass.descriptor.unsubstitutedPrimaryConstructor ?: throw AssertionError("Object should have a primary constructor: ${irClass.descriptor}") @@ -55,7 +55,7 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer val publicInstanceOwner = if (irClass.descriptor.isCompanionObject) parentScope!!.irElement as IrDeclarationContainer else irClass if (isCompanionObjectInInterfaceNotIntrinsic(irClass.descriptor)) { // TODO rename to $$INSTANCE - val privateInstance = publicInstance.descriptor.copy( + val privateInstance = publicInstanceField.descriptor.copy( irClass.descriptor, Modality.FINAL, Visibilities.PROTECTED/*TODO package local*/, @@ -64,15 +64,15 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer ) as PropertyDescriptor privateInstance.name val field = createInstanceFieldWithInitializer(IrFieldSymbolImpl(privateInstance), constructor, irClass, irClass.defaultType) - createFieldWithCustomInitializer( - publicInstance, - IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, field.symbol, irClass.defaultType), - publicInstanceOwner, - irClass.defaultType - ) + publicInstanceField.initializer = + IrExpressionBodyImpl(IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, field.symbol, irClass.defaultType)) } else { - createInstanceFieldWithInitializer(publicInstance, constructor, publicInstanceOwner, irClass.defaultType) + val constructorCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irClass.defaultType, constructor, 0) + publicInstanceField.initializer = IrExpressionBodyImpl(constructorCall) } + + publicInstanceField.parent = publicInstanceOwner + pendingTransformations.add { publicInstanceOwner.declarations.add(publicInstanceField) } } private fun createInstanceFieldWithInitializer( @@ -99,6 +99,7 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer fieldSymbol, objectType ).also { it.initializer = IrExpressionBodyImpl(instanceInitializer) + it.parent = instanceOwner pendingTransformations.add { instanceOwner.declarations.add(it) } } } \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SingletonReferencesLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SingletonReferencesLowering.kt index 5b2a13b10d0..10ed9136f83 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SingletonReferencesLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SingletonReferencesLowering.kt @@ -21,12 +21,12 @@ class SingletonReferencesLowering(val context: JvmBackendContext) : BodyLowering } override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression { - val entrySymbol = context.descriptorsFactory.getSymbolForEnumEntry(expression.symbol) - return IrGetFieldImpl(expression.startOffset, expression.endOffset, entrySymbol, expression.type) + val entrySymbol = context.declarationFactory.getFieldForEnumEntry(expression.symbol.owner, expression.type) + return IrGetFieldImpl(expression.startOffset, expression.endOffset, entrySymbol.symbol, expression.type) } override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression { - val instanceField = context.descriptorsFactory.getSymbolForObjectInstance(expression.symbol) - return IrGetFieldImpl(expression.startOffset, expression.endOffset, instanceField, expression.type) + val instanceField = context.declarationFactory.getFieldForObjectInstance(expression.symbol.owner) + return IrGetFieldImpl(expression.startOffset, expression.endOffset, instanceField.symbol, expression.type) } } \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt index 53c077269e2..eb6e14da600 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt @@ -38,8 +38,9 @@ class StaticDefaultFunctionLowering(val state: GenerationState) : IrElementTrans declaration.descriptor.containingDeclaration as ClassDescriptor, declaration.descriptor.name, declaration.descriptor, - declaration.descriptor.dispatchReceiverParameter!!.type + declaration.dispatchReceiverParameter!!.descriptor.type ) + // NOTE: Fix it newFunction.createFunctionAndMapVariables(declaration, Visibilities.PUBLIC) } else { super.visitFunction(declaration) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt index 8f17c62fe8b..4c67ca79c80 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt @@ -242,6 +242,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio ktConstructorElement.pureStartOffset, ktConstructorElement.pureEndOffset, IrDeclarationOrigin.DEFINED, constructorDescriptor ).buildWithScope { irConstructor -> + declarationGenerator.generateScopedTypeParameterDeclarations(irConstructor, constructorDescriptor.typeParameters) generateValueParameterDeclarations(irConstructor, ktParametersElement, null) irConstructor.body = createBodyGenerator(irConstructor.symbol).generateBody() irConstructor.returnType = constructorDescriptor.returnType.toIrType() diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt index 729ae49552d..3297bfd445a 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ReflectionReferencesGenerator.kt @@ -118,8 +118,8 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St variableDescriptor.getter ?: throw AssertionError("Local delegated property should have a getter: $variableDescriptor") val setterDescriptor = variableDescriptor.setter - val getterSymbol = context.symbolTable.referenceFunction(getterDescriptor) - val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it) } + val getterSymbol = context.symbolTable.referenceSimpleFunction(getterDescriptor) + val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceSimpleFunction(it) } return IrLocalDelegatedPropertyReferenceImpl( startOffset, endOffset, type.toIrType(), @@ -141,8 +141,8 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St val setterDescriptor = propertyDescriptor.setter val fieldSymbol = if (getterDescriptor == null) context.symbolTable.referenceField(propertyDescriptor) else null - val getterSymbol = getterDescriptor?.let { context.symbolTable.referenceFunction(it.original) } - val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it.original) } + val getterSymbol = getterDescriptor?.let { context.symbolTable.referenceSimpleFunction(it.original) } + val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceSimpleFunction(it.original) } return IrPropertyReferenceImpl( startOffset, endOffset, type.toIrType(), diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrTypeParameter.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrTypeParameter.kt index a90e37e8ce9..d0e9ce3323b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrTypeParameter.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrTypeParameter.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.ir.declarations import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.visitors.IrElementTransformer @@ -30,6 +29,7 @@ interface IrTypeParameter : IrSymbolDeclaration { val name: Name val variance: Variance val index: Int + val isReified: Boolean val superTypes: MutableList override fun transform(transformer: IrElementTransformer, data: D): IrTypeParameter diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrTypeParameterImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrTypeParameterImpl.kt index 595540ff470..fb02cc06593 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrTypeParameterImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrTypeParameterImpl.kt @@ -35,6 +35,7 @@ class IrTypeParameterImpl( override val symbol: IrTypeParameterSymbol, override val name: Name, override val index: Int, + override val isReified: Boolean, override val variance: Variance ) : IrDeclarationBase(startOffset, endOffset, origin), @@ -50,9 +51,21 @@ class IrTypeParameterImpl( startOffset, endOffset, origin, symbol, symbol.descriptor.name, symbol.descriptor.index, + symbol.descriptor.isReified, symbol.descriptor.variance ) + constructor( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + symbol: IrTypeParameterSymbol, + name: Name, + index: Int, + variance: Variance + ) : this(startOffset, endOffset, origin, symbol, name, index, symbol.descriptor.isReified, variance) + + @Deprecated("Use constructor which takes symbol instead of descriptor") constructor( startOffset: Int, endOffset: Int, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrVariableImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrVariableImpl.kt index 7fccef108aa..1f54f795cc4 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrVariableImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrVariableImpl.kt @@ -55,6 +55,24 @@ class IrVariableImpl( isLateinit = symbol.descriptor.isLateInit ) + constructor( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + symbol: IrVariableSymbol, + type: IrType, + initializer: IrExpression? + ) : this( + startOffset, endOffset, origin, symbol, + symbol.descriptor.name, type, + isVar = symbol.descriptor.isVar, + isConst = symbol.descriptor.isConst, + isLateinit = symbol.descriptor.isLateInit + ) { + this.initializer = initializer + } + + @Deprecated("Use constructor which takes symbol instead of descriptor") constructor( startOffset: Int, endOffset: Int, @@ -63,6 +81,7 @@ class IrVariableImpl( type: IrType ) : this(startOffset, endOffset, origin, IrVariableSymbolImpl(descriptor), type) + @Deprecated("Use constructor which takes symbol instead of descriptor") constructor( startOffset: Int, endOffset: Int, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazySymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazySymbolTable.kt index f6a8b79eaee..a34aacaa19b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazySymbolTable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazySymbolTable.kt @@ -5,9 +5,14 @@ package org.jetbrains.kotlin.ir.declarations.lazy -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator +import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable +import org.jetbrains.kotlin.ir.util.SymbolTable class IrLazySymbolTable(private val originalTable: SymbolTable) : ReferenceSymbolTable by originalTable { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt index 8d297160228..83d6ee49a6b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt @@ -25,6 +25,7 @@ class IrLazyTypeParameter( override val symbol: IrTypeParameterSymbol, override val name: Name, override val index: Int, + override val isReified: Boolean, override val variance: Variance, stubGenerator: DeclarationStubGenerator, typeTranslator: TypeTranslator @@ -44,6 +45,7 @@ class IrLazyTypeParameter( startOffset, endOffset, origin, symbol, symbol.descriptor.name, symbol.descriptor.index, + symbol.descriptor.isReified, symbol.descriptor.variance, stubGenerator, TypeTranslator ) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallableReference.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallableReference.kt index c171e9f760b..dc916cf5c2b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallableReference.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallableReference.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol interface IrCallableReference : IrMemberAccessExpression { @@ -36,13 +37,13 @@ interface IrFunctionReference : IrCallableReference { interface IrPropertyReference : IrCallableReference { override val descriptor: PropertyDescriptor val field: IrFieldSymbol? - val getter: IrFunctionSymbol? - val setter: IrFunctionSymbol? + val getter: IrSimpleFunctionSymbol? + val setter: IrSimpleFunctionSymbol? } interface IrLocalDelegatedPropertyReference : IrCallableReference { override val descriptor: VariableDescriptorWithAccessors val delegate: IrVariableSymbol - val getter: IrFunctionSymbol - val setter: IrFunctionSymbol? + val getter: IrSimpleFunctionSymbol + val setter: IrSimpleFunctionSymbol? } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrLocalDelegatedPropertyReferenceImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrLocalDelegatedPropertyReferenceImpl.kt index 79aeca9f243..00a3368a870 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrLocalDelegatedPropertyReferenceImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrLocalDelegatedPropertyReferenceImpl.kt @@ -19,7 +19,7 @@ package org.jetbrains.kotlin.ir.expressions.impl import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors import org.jetbrains.kotlin.ir.expressions.IrLocalDelegatedPropertyReference import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -30,8 +30,8 @@ class IrLocalDelegatedPropertyReferenceImpl( type: IrType, override val descriptor: VariableDescriptorWithAccessors, override val delegate: IrVariableSymbol, - override val getter: IrFunctionSymbol, - override val setter: IrFunctionSymbol?, + override val getter: IrSimpleFunctionSymbol, + override val setter: IrSimpleFunctionSymbol?, origin: IrStatementOrigin? = null ) : IrNoArgumentsCallableReferenceBase(startOffset, endOffset, type, 0, origin), diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrPropertyReferenceImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrPropertyReferenceImpl.kt index c3c2d217cf2..8c2cc11eaad 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrPropertyReferenceImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrPropertyReferenceImpl.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.ir.expressions.IrPropertyReference import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -31,8 +31,8 @@ class IrPropertyReferenceImpl( override val descriptor: PropertyDescriptor, typeArgumentsCount: Int, override val field: IrFieldSymbol?, - override val getter: IrFunctionSymbol?, - override val setter: IrFunctionSymbol?, + override val getter: IrSimpleFunctionSymbol?, + override val setter: IrSimpleFunctionSymbol?, origin: IrStatementOrigin? = null ) : IrNoArgumentsCallableReferenceBase(startOffset, endOffset, type, typeArgumentsCount, origin), diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt index ca485759513..1c7f42be0bd 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrSymbolBase.kt @@ -26,9 +26,9 @@ abstract class IrSymbolBase(override val descript abstract class IrBindableSymbolBase(descriptor: D) : IrBindableSymbol, IrSymbolBase(descriptor) { init { - assert(isOriginalDescriptor(descriptor)) { - "Substituted descriptor $descriptor for ${descriptor.original}" - } +// assert(isOriginalDescriptor(descriptor)) { +// "Substituted descriptor $descriptor for ${descriptor.original}" +// } } private fun isOriginalDescriptor(descriptor: DeclarationDescriptor): Boolean = diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt index 5620b7406b8..b437e73d535 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl import org.jetbrains.kotlin.ir.types.impl.* +import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -104,8 +105,8 @@ private fun makeKotlinType( return classifier.descriptor.defaultType.replace(newArguments = kotlinTypeArguments).makeNullableAsSpecified(hasQuestionMark) } -fun ClassifierDescriptor.toIrType(hasQuestionMark: Boolean = false): IrType { - val symbol = getSymbol() +fun ClassifierDescriptor.toIrType(hasQuestionMark: Boolean = false, symbolTable: SymbolTable? = null): IrType { + val symbol = getSymbol(symbolTable) return IrSimpleTypeImpl(defaultType, symbol, hasQuestionMark, listOf(), listOf()) } @@ -123,14 +124,14 @@ fun IrClassifierSymbol.typeWith(arguments: List): IrSimpleType = fun IrClass.typeWith(arguments: List) = this.symbol.typeWith(arguments) -fun KotlinType.toIrType(): IrType? { +fun KotlinType.toIrType(symbolTable: SymbolTable? = null): IrType? { if (isDynamic()) return IrDynamicTypeImpl(this, listOf(), Variance.INVARIANT) - val symbol = constructor.declarationDescriptor?.getSymbol() ?: return null + val symbol = constructor.declarationDescriptor?.getSymbol(symbolTable) ?: return null - val arguments = this.arguments.mapIndexed { i, projection -> + val arguments = this.arguments.map { projection -> when (projection) { - is TypeProjectionImpl -> IrTypeProjectionImpl(projection.type.toIrType()!!, projection.projectionKind) + is TypeProjectionImpl -> IrTypeProjectionImpl(projection.type.toIrType(symbolTable)!!, projection.projectionKind) is StarProjectionImpl -> IrStarProjectionImpl else -> error(projection) } @@ -142,8 +143,8 @@ fun KotlinType.toIrType(): IrType? { } // TODO: this function creates unbound symbol which is the great source of problems -private fun ClassifierDescriptor.getSymbol(): IrClassifierSymbol = when (this) { - is ClassDescriptor -> IrClassSymbolImpl(this) - is TypeParameterDescriptor -> IrTypeParameterSymbolImpl(this) +private fun ClassifierDescriptor.getSymbol(symbolTable: SymbolTable?): IrClassifierSymbol = when (this) { + is ClassDescriptor -> symbolTable?.referenceClass(this) ?: IrClassSymbolImpl(this) + is TypeParameterDescriptor -> /*symbolTable?.referenceTypeParameter(this) ?: */IrTypeParameterSymbolImpl(this) else -> TODO() } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt index dc2a11996e7..b03d489deeb 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt @@ -478,8 +478,8 @@ open class DeepCopyIrTreeWithSymbols( expression.descriptor, expression.typeArgumentsCount, expression.field?.let { symbolRemapper.getReferencedField(it) }, - expression.getter?.let { symbolRemapper.getReferencedFunction(it) }, - expression.setter?.let { symbolRemapper.getReferencedFunction(it) }, + expression.getter?.let { symbolRemapper.getReferencedSimpleFunction(it) }, + expression.setter?.let { symbolRemapper.getReferencedSimpleFunction(it) }, mapStatementOrigin(expression.origin) ).apply { copyRemappedTypeArgumentsFrom(expression) @@ -492,8 +492,8 @@ open class DeepCopyIrTreeWithSymbols( expression.type.remapType(), expression.descriptor, symbolRemapper.getReferencedVariable(expression.delegate), - symbolRemapper.getReferencedFunction(expression.getter), - expression.setter?.let { symbolRemapper.getReferencedFunction(it) }, + symbolRemapper.getReferencedSimpleFunction(expression.getter), + expression.setter?.let { symbolRemapper.getReferencedSimpleFunction(it) }, mapStatementOrigin(expression.origin) ) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopySymbolRemapper.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopySymbolRemapper.kt index 642521ddf75..bc70967d0ed 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopySymbolRemapper.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopySymbolRemapper.kt @@ -157,6 +157,7 @@ open class DeepCopySymbolRemapper( override fun getReferencedVariable(symbol: IrVariableSymbol): IrVariableSymbol = variables.getReferenced(symbol) override fun getReferencedField(symbol: IrFieldSymbol): IrFieldSymbol = fields.getReferenced(symbol) override fun getReferencedConstructor(symbol: IrConstructorSymbol): IrConstructorSymbol = constructors.getReferenced(symbol) + override fun getReferencedSimpleFunction(symbol: IrSimpleFunctionSymbol): IrSimpleFunctionSymbol = functions.getReferenced(symbol) override fun getReferencedValue(symbol: IrValueSymbol): IrValueSymbol = when (symbol) { is IrValueParameterSymbol -> valueParameters.getReferenced(symbol) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index 10d10835680..462b66173ad 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -158,6 +158,7 @@ fun IrFunction.createParameterDeclarations() { assert(valueParameters.isEmpty()) descriptor.valueParameters.mapTo(valueParameters) { it.irValueParameter() } +// valueParameters.mapTo(valueParameters) { it.descriptor.irValueParameter() } assert(typeParameters.isEmpty()) descriptor.typeParameters.mapTo(typeParameters) { @@ -316,6 +317,30 @@ fun IrAnnotationContainer.hasAnnotation(name: FqName) = it.symbol.owner.parentAsClass.descriptor.fqNameSafe == name } +val IrConstructor.constructedClassType get() = (parent as IrClass).thisReceiver?.type!! + +fun IrFunction.isFakeOverriddenFromAny(): Boolean { + if (origin != IrDeclarationOrigin.FAKE_OVERRIDE) { + return (parent as? IrClass)?.thisReceiver?.type?.isAny() ?: false + } + + return (this as IrSimpleFunction).overriddenSymbols.all { it.owner.isFakeOverriddenFromAny() } +} + +fun IrCall.isSuperToAny() = superQualifier?.let { this.symbol.owner.isFakeOverriddenFromAny() } ?: false + +fun IrDeclaration.isEffectivelyExternal(): Boolean { + return when (this) { + is IrConstructor -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal() + is IrFunction -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal() + is IrField -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal() + is IrClass -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal() + else -> false + } +} + +val IrDeclaration.isDynamic get() = this is IrFunction && dispatchReceiverParameter?.type is IrDynamicType + fun IrValueParameter.copy(newDescriptor: ParameterDescriptor): IrValueParameter { assert(this.descriptor.type == newDescriptor.type) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolRemapper.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolRemapper.kt index 9be589422db..2143996b4a4 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolRemapper.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolRemapper.kt @@ -37,6 +37,7 @@ interface SymbolRemapper { fun getReferencedConstructor(symbol: IrConstructorSymbol): IrConstructorSymbol fun getReferencedValue(symbol: IrValueSymbol): IrValueSymbol fun getReferencedFunction(symbol: IrFunctionSymbol): IrFunctionSymbol + fun getReferencedSimpleFunction(symbol: IrSimpleFunctionSymbol): IrSimpleFunctionSymbol fun getReferencedReturnableBlock(symbol: IrReturnableBlockSymbol): IrReturnableBlockSymbol fun getReferencedClassifier(symbol: IrClassifierSymbol): IrClassifierSymbol } \ No newline at end of file diff --git a/compiler/testData/codegen/box/closures/closureInsideConstrucor.kt b/compiler/testData/codegen/box/closures/closureInsideConstrucor.kt index 749b74acbde..38192dd47b0 100644 --- a/compiler/testData/codegen/box/closures/closureInsideConstrucor.kt +++ b/compiler/testData/codegen/box/closures/closureInsideConstrucor.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR //adopted snippet from kdoc open class KModel { val sourcesInfo: String diff --git a/compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt b/compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt index 9e721bd8064..5f294911561 100644 --- a/compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt +++ b/compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR class Test { val property:Int diff --git a/js/js.translator/testData/box/native/inheritanceFromNativeTrait.kt b/js/js.translator/testData/box/native/inheritanceFromNativeTrait.kt index 75cbc379a95..41deab8acfb 100644 --- a/js/js.translator/testData/box/native/inheritanceFromNativeTrait.kt +++ b/js/js.translator/testData/box/native/inheritanceFromNativeTrait.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1129 package foo diff --git a/js/js.translator/testData/test.html b/js/js.translator/testData/test.html index b87165d6617..6352b6ea666 100644 --- a/js/js.translator/testData/test.html +++ b/js/js.translator/testData/test.html @@ -2,11 +2,12 @@ - - + + + diff --git a/libraries/stdlib/js/irRuntime/core.kt b/libraries/stdlib/js/irRuntime/core.kt index 09159bbc7f5..83f200c0d00 100644 --- a/libraries/stdlib/js/irRuntime/core.kt +++ b/libraries/stdlib/js/irRuntime/core.kt @@ -14,8 +14,8 @@ fun equals(obj1: dynamic, obj2: dynamic): Boolean { } return js(""" - if (typeof obj1 === "object" && typeof obj1.equals_Any_ === "function") { - return obj1.equals_Any_(obj2); + if (typeof obj1 === "object" && typeof obj1.equals_kotlin_Any_ === "function") { + return obj1.equals_kotlin_Any_(obj2); } if (obj1 !== obj1) {