From d1621b80cceadbb3ce3981c26a51e11e8949cff0 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Wed, 25 Jul 2018 23:03:09 +0300 Subject: [PATCH] Fake wrapped descriptors first working draft get rid of descriptors in Bridge and Enum lowerings Replace property accessors function type with IrSimpleFunction because they couldn't be constructors get rid of descriptors in Callable reference lowering refactored descriptor factory and inner class lowering Add isReified property to IrTypeParameter declaration keep getting rid of descriptors Get rid of descriptors in Shared Variable Manager LocalDeclarationLowering also uses no descriptors Fix psi2ir Fix nested classes names Fix outer reference in inner classes Fix name generator get rid of descriptors in coroutines - something is working Fix name generator Fix unbound symbols in JVM BE Rename DeclarationFactory members --- .../kotlin/backend/common/BackendContext.kt | 6 +- .../common/TailRecursionCallsCollector.kt | 3 +- .../common/descriptors/DescriptorsFactory.kt | 20 - .../common/descriptors/WrappedDescriptors.kt | 568 ++++++++++ .../backend/common/ir/DeclarationFactory.kt | 18 + .../jetbrains/kotlin/backend/common/ir/Ir.kt | 2 +- .../kotlin/backend/common/ir/IrUtils.kt | 52 +- .../SharedVariablesManager.kt | 17 +- .../common/lower/AbstractClosureAnnotator.kt | 120 ++- .../lower/DefaultArgumentStubGenerator.kt | 463 ++++----- .../common/lower/InitializersLowering.kt | 15 +- .../common/lower/InnerClassesLowering.kt | 146 ++- .../backend/common/lower/LateinitLowering.kt | 2 - .../common/lower/LocalDeclarationsLowering.kt | 643 ++++++------ .../kotlin/backend/common/lower/LowerUtils.kt | 64 +- .../lower/StringConcatenationLowering.kt | 4 +- .../common/utils/kotlinTypeBasedUtils.kt | 15 +- .../jetbrains/kotlin/ir/util/IrTypeUtils.kt | 41 + .../ir/backend/js/DeclarationOrigins.kt | 1 + .../ir/backend/js/JsDeclarationFactory.kt | 136 +++ .../ir/backend/js/JsDescriptorsFactory.kt | 110 -- .../kotlin/ir/backend/js/JsIntrinsics.kt | 96 +- .../ir/backend/js/JsIrBackendContext.kt | 26 +- .../ir/backend/js/JsSharedVariablesManager.kt | 253 ++--- .../kotlin/ir/backend/js/compiler.kt | 1 + .../kotlin/ir/backend/js/ir/IrBuilder.kt | 402 +++----- .../js/lower/BlockDecomposerLowering.kt | 68 +- .../backend/js/lower/BridgesConstruction.kt | 67 +- .../js/lower/CallableReferenceLowering.kt | 215 ++-- .../ir/backend/js/lower/EnumClassLowering.kt | 62 +- .../js/lower/IntrinsicifyCallsLowering.kt | 50 +- ...MoveExternalDeclarationsToSeparatePlace.kt | 2 +- .../js/lower/MultipleCatchesLowering.kt | 31 +- .../backend/js/lower/SecondaryCtorLowering.kt | 164 ++- .../backend/js/lower/TypeOperatorLowering.kt | 52 +- .../lower/coroutines/StateMachineBuilder.kt | 70 +- .../coroutines/SuspendFunctionsLowering.kt | 968 +++++++++--------- .../lower/coroutines/SuspendLoweringUtils.kt | 3 +- .../inline/DeepCopyIrTreeWithDescriptors.kt | 4 +- .../js/lower/inline/FunctionInlining.kt | 1 - .../lower/inline/IrUnboundSymbolReplacer.kt | 10 +- .../ir/backend/js/lower/inline/IrUtils2.kt | 8 + ...ctionsWithReifiedTypeParametersLowering.kt | 2 - .../lower/inline/ReturnableBlockLowering.kt | 23 +- .../ir/backend/js/symbols/SymbolBuilder.kt | 104 -- .../irToJs/IrDeclarationToJsTransformer.kt | 3 + .../IrElementToJsExpressionTransformer.kt | 8 +- .../IrElementToJsStatementTransformer.kt | 6 +- .../irToJs/IrModuleToJsTransformer.kt | 10 +- .../transformers/irToJs/JsClassGenerator.kt | 44 +- .../irToJs/JsIntrinsicTransformers.kt | 7 - .../backend/js/utils/JsGenerationContext.kt | 3 + .../ir/backend/js/utils/JsStaticContext.kt | 6 +- .../ir/backend/js/utils/NameGenerator.kt | 2 + .../backend/js/utils/SimpleNameGenerator.kt | 201 ++-- .../backend/js/utils/descriptorBasedUtils.kt | 63 -- .../kotlin/backend/jvm/JvmBackendContext.kt | 4 +- .../jetbrains/kotlin/backend/jvm/JvmLower.kt | 3 +- ...orsFactory.kt => JvmDeclarationFactory.kt} | 87 +- .../jvm/descriptors/SharedVariablesManager.kt | 63 +- .../backend/jvm/lower/EnumClassLowering.kt | 10 +- .../backend/jvm/lower/FileClassLowering.kt | 2 +- .../backend/jvm/lower/InterfaceLowering.kt | 9 +- .../jvm/lower/JvmStaticAnnotationLowering.kt | 16 +- .../backend/jvm/lower/ObjectClassLowering.kt | 19 +- .../jvm/lower/SingletonReferencesLowering.kt | 8 +- .../lower/StaticDefaultFunctionLowering.kt | 3 +- .../psi2ir/generators/FunctionGenerator.kt | 1 + .../ReflectionReferencesGenerator.kt | 8 +- .../kotlin/ir/declarations/IrTypeParameter.kt | 2 +- .../declarations/impl/IrTypeParameterImpl.kt | 13 + .../ir/declarations/impl/IrVariableImpl.kt | 19 + .../ir/declarations/lazy/IrLazySymbolTable.kt | 9 +- .../declarations/lazy/IrLazyTypeParameter.kt | 2 + .../ir/expressions/IrCallableReference.kt | 9 +- .../IrLocalDelegatedPropertyReferenceImpl.kt | 6 +- .../impl/IrPropertyReferenceImpl.kt | 6 +- .../kotlin/ir/symbols/impl/IrSymbolBase.kt | 6 +- .../org/jetbrains/kotlin/ir/types/irTypes.kt | 19 +- .../ir/util/DeepCopyIrTreeWithSymbols.kt | 8 +- .../kotlin/ir/util/DeepCopySymbolRemapper.kt | 1 + .../org/jetbrains/kotlin/ir/util/IrUtils.kt | 25 + .../kotlin/ir/util/SymbolRemapper.kt | 1 + .../box/closures/closureInsideConstrucor.kt | 1 - .../localFunctionInConstructor.kt | 1 - .../box/native/inheritanceFromNativeTrait.kt | 1 - js/js.translator/testData/test.html | 7 +- libraries/stdlib/js/irRuntime/core.kt | 4 +- 88 files changed, 3138 insertions(+), 2716 deletions(-) delete mode 100644 compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorsFactory.kt create mode 100644 compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt create mode 100644 compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/DeclarationFactory.kt rename compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/{descriptors => ir}/SharedVariablesManager.kt (53%) create mode 100644 compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt create mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDeclarationFactory.kt delete mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt delete mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/symbols/SymbolBuilder.kt delete mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/descriptorBasedUtils.kt rename compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/{JvmDescriptorsFactory.kt => JvmDeclarationFactory.kt} (63%) 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) {