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 74ef23ff690..65b856c485e 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 @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames +import org.jetbrains.kotlin.ir.backend.js.lower.inline.ModuleIndex import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment @@ -60,6 +61,8 @@ class JsIrBackendContext( fun getOperatorByName(name: Name, type: KotlinType) = operatorMap[name]?.get(type) + val originalModuleIndex = ModuleIndex(irModuleFragment) + override val ir = object : Ir(this, irModuleFragment) { override val symbols = object : Symbols(this@JsIrBackendContext, symbolTable) { 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 19031cc9b36..eb92e8657de 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 @@ -10,9 +10,15 @@ import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.ir.backend.js.lower.* +import org.jetbrains.kotlin.ir.backend.js.lower.inline.FunctionInlining +import org.jetbrains.kotlin.ir.backend.js.lower.inline.ReturnableBlockLowering +import org.jetbrains.kotlin.ir.backend.js.lower.inline.referenceAllTypeExternalClassifiers +import org.jetbrains.kotlin.ir.backend.js.lower.inline.replaceUnboundSymbols import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator +import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus @@ -33,7 +39,7 @@ fun compile( val psi2IrTranslator = Psi2IrTranslator() val psi2IrContext = psi2IrTranslator.createGeneratorContext(analysisResult.moduleDescriptor, analysisResult.bindingContext) - val moduleFragment = psi2IrTranslator.generateModuleFragment(psi2IrContext, files) + val moduleFragment = psi2IrTranslator.generateModuleFragment(psi2IrContext, files).removeDuplicates() val context = JsIrBackendContext( analysisResult.moduleDescriptor, @@ -44,6 +50,8 @@ fun compile( ExternalDependenciesGenerator(psi2IrContext.symbolTable, psi2IrContext.irBuiltIns).generateUnboundSymbolsAsDependencies(moduleFragment) + context.performInlining(moduleFragment) + moduleFragment.files.forEach { context.lower(it) } val transformer = SecondaryCtorLowering.CallsiteRedirectionTransformer(context) moduleFragment.files.forEach { it.accept(transformer, null) } @@ -53,10 +61,25 @@ fun compile( return program.toString() } +fun JsIrBackendContext.performInlining(moduleFragment: IrModuleFragment) { + FunctionInlining(this).inline(moduleFragment) + + moduleFragment.referenceAllTypeExternalClassifiers(symbolTable) + + do { + @Suppress("DEPRECATION") + moduleFragment.replaceUnboundSymbols(this) + moduleFragment.referenceAllTypeExternalClassifiers(symbolTable) + } while (symbolTable.unboundClasses.isNotEmpty()) + + moduleFragment.patchDeclarationParents() +} + fun JsIrBackendContext.lower(file: IrFile) { LateinitLowering(this, true).lower(file) DefaultArgumentStubGenerator(this).runOnFilePostfix(file) SharedVariablesLowering(this).runOnFilePostfix(file) + ReturnableBlockLowering(this).lower(file) LocalDeclarationsLowering(this).runOnFilePostfix(file) InnerClassesLowering(this).runOnFilePostfix(file) InnerClassConstructorCallsLowering(this).runOnFilePostfix(file) @@ -67,4 +90,19 @@ fun JsIrBackendContext.lower(file: IrFile) { SecondaryCtorLowering(this).runOnFilePostfix(file) CallableReferenceLowering(this).lower(file) IntrinsicifyCallsLowering(this).lower(file) +} + +// TODO find out why duplicates occur +private fun IrModuleFragment.removeDuplicates(): IrModuleFragment { + + fun MutableList.removeDuplicates() { + val tmp = toSet() + clear() + addAll(tmp) + } + + dependencyModules.removeDuplicates() + dependencyModules.forEach { it.externalPackageFragments.removeDuplicates() } + + return this } \ 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 0022b4a32e2..8293a384918 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 @@ -18,8 +18,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.util.transformFlat -import org.jetbrains.kotlin.ir.visitors.IrElementTransformer -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.types.KotlinType private typealias VisitData = Nothing? @@ -153,7 +152,9 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont private fun processStatement(statement: IrStatement, data: VisitData): List? { val result = statement.accept(this, data) - if (result == KeptResult) return null + if (result == KeptResult) { + return if (statement is IrComposite) statement.statements else null + } return result.statements } @@ -436,7 +437,11 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont resultValue } collectingList += JsIrBuilder.buildSetVariable(variable, result) - DecomposedResult(mutableListOf(varDeclaration, body), JsIrBuilder.buildGetValue(variable)) + if (body is IrComposite) { + DecomposedResult(mutableListOf(varDeclaration, *collectingList.toTypedArray()) , JsIrBuilder.buildGetValue(variable)) + } else { + DecomposedResult(mutableListOf(varDeclaration, body as IrStatement), JsIrBuilder.buildGetValue(variable)) + } } else { // do not allow variable to be uninitialized DecomposedResult(mutableListOf(), unitValue) @@ -658,6 +663,19 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont return DecomposedResult(jump, JsIrBuilder.buildCall(unreachableFunction)) } + override fun visitLoop(loop: IrLoop, data: VisitData): VisitResult { + val result = loop.accept(statementVisitor, data) + return if (result.status == VisitStatus.KEPT) { + DecomposedResult(loop, unitValue) + } else result + } + + override fun visitSetField(expression: IrSetField, data: VisitData): VisitResult { + val result = expression.accept(statementVisitor, data) + return if (result.status == VisitStatus.KEPT) { + DecomposedResult(expression, unitValue) + } else result + } } fun makeTempVar(type: KotlinType) = 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 new file mode 100644 index 00000000000..cde7546716d --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/DeepCopyIrTreeWithDescriptors.kt @@ -0,0 +1,766 @@ +/* + * 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.lower.inline + +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext +import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.impl.createClassSymbolOrNull +import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol +import org.jetbrains.kotlin.ir.util.DeepCopyIrTree +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +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.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces +import org.jetbrains.kotlin.storage.LockBasedStorageManager +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.typeUtil.makeNullable + + +// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt +internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor, + val parentDescriptor: DeclarationDescriptor, + val context: JsIrBackendContext) { + + private val descriptorSubstituteMap: MutableMap = mutableMapOf() + private var typeSubstitutor: TypeSubstitutor? = null + private var nameIndex = 0 + + //-------------------------------------------------------------------------// + + fun copy(irElement: IrElement, typeSubstitutor: TypeSubstitutor?): IrElement { + this.typeSubstitutor = typeSubstitutor + // Create all class descriptors and all necessary descriptors in order to create KotlinTypes. + irElement.acceptChildrenVoid(DescriptorCollectorCreatePhase()) + // Initialize all created descriptors possibly using previously created types. + irElement.acceptChildrenVoid(DescriptorCollectorInitPhase()) + return irElement.accept(InlineCopyIr(), null) + } + + inner class DescriptorCollectorCreatePhase : IrElementVisitorVoidWithContext() { + + override fun visitElement(element: IrElement) { + element.acceptChildren(this, null) + } + + //---------------------------------------------------------------------// + + override fun visitClassNew(declaration: IrClass) { + val oldDescriptor = declaration.descriptor + val newDescriptor = copyClassDescriptor(oldDescriptor) + descriptorSubstituteMap[oldDescriptor] = newDescriptor + descriptorSubstituteMap[oldDescriptor.thisAsReceiverParameter] = newDescriptor.thisAsReceiverParameter + + super.visitClassNew(declaration) + + val constructors = oldDescriptor.constructors.map { oldConstructorDescriptor -> + descriptorSubstituteMap[oldConstructorDescriptor] as ClassConstructorDescriptor + }.toSet() + + val oldPrimaryConstructor = oldDescriptor.unsubstitutedPrimaryConstructor + val primaryConstructor = oldPrimaryConstructor?.let { descriptorSubstituteMap[it] as ClassConstructorDescriptor } + + val contributedDescriptors = oldDescriptor.unsubstitutedMemberScope + .getContributedDescriptors() + .map { descriptorSubstituteMap[it]!! } + newDescriptor.initialize( + SimpleMemberScope(contributedDescriptors), + constructors, + primaryConstructor + ) + } + + //---------------------------------------------------------------------// + + override fun visitPropertyNew(declaration: IrProperty) { + copyPropertyOrField(declaration.descriptor) + super.visitPropertyNew(declaration) + } + + //---------------------------------------------------------------------// + + override fun visitFieldNew(declaration: IrField) { + val oldDescriptor = declaration.descriptor + if (descriptorSubstituteMap[oldDescriptor] == null) { + copyPropertyOrField(oldDescriptor) // A field without a property or a field of a delegated property. + } + super.visitFieldNew(declaration) + } + + //---------------------------------------------------------------------// + + override fun visitFunctionNew(declaration: IrFunction) { + val oldDescriptor = declaration.descriptor + if (oldDescriptor !is PropertyAccessorDescriptor) { // Property accessors are copied along with their property. + val oldContainingDeclaration = + if (oldDescriptor.visibility == Visibilities.LOCAL) + parentDescriptor + else + oldDescriptor.containingDeclaration + descriptorSubstituteMap[oldDescriptor] = copyFunctionDescriptor(oldDescriptor, oldContainingDeclaration) + } + super.visitFunctionNew(declaration) + } + + //--- Copy descriptors ------------------------------------------------// + + private fun generateCopyName(name: Name): Name { + val declarationName = name.toString() // Name of declaration + val indexStr = (nameIndex++).toString() // Unique for inline target index + return Name.identifier(declarationName /*+ "_" + indexStr*/) + } + + //---------------------------------------------------------------------// + + private fun copyFunctionDescriptor(oldDescriptor: CallableDescriptor, oldContainingDeclaration: DeclarationDescriptor) = + when (oldDescriptor) { + is ConstructorDescriptor -> copyConstructorDescriptor(oldDescriptor) + is SimpleFunctionDescriptor -> copySimpleFunctionDescriptor(oldDescriptor, oldContainingDeclaration) + else -> TODO("Unsupported FunctionDescriptor subtype: $oldDescriptor") + } + + //---------------------------------------------------------------------// + + private fun copySimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor, oldContainingDeclaration: DeclarationDescriptor) : FunctionDescriptor { + val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) + return SimpleFunctionDescriptorImpl.create( + /* containingDeclaration = */ newContainingDeclaration, + /* annotations = */ oldDescriptor.annotations, + /* name = */ generateCopyName(oldDescriptor.name), + /* kind = */ oldDescriptor.kind, + /* source = */ oldDescriptor.source + ) + } + + //---------------------------------------------------------------------// + + private fun copyConstructorDescriptor(oldDescriptor: ConstructorDescriptor) : FunctionDescriptor { + val oldContainingDeclaration = oldDescriptor.containingDeclaration + val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) + return ClassConstructorDescriptorImpl.create( + /* containingDeclaration = */ newContainingDeclaration as ClassDescriptor, + /* annotations = */ oldDescriptor.annotations, + /* isPrimary = */ oldDescriptor.isPrimary, + /* source = */ oldDescriptor.source + ) + } + + //---------------------------------------------------------------------// + + private fun copyPropertyOrField(oldDescriptor: PropertyDescriptor) { + val oldContainingDeclaration = oldDescriptor.containingDeclaration + val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) as ClassDescriptor + @Suppress("DEPRECATION") + val newDescriptor = PropertyDescriptorImpl.create( + /* containingDeclaration = */ newContainingDeclaration, + /* annotations = */ oldDescriptor.annotations, + /* modality = */ oldDescriptor.modality, + /* visibility = */ oldDescriptor.visibility, + /* isVar = */ oldDescriptor.isVar, + /* name = */ oldDescriptor.name, + /* kind = */ oldDescriptor.kind, + /* source = */ oldDescriptor.source, + /* lateInit = */ oldDescriptor.isLateInit, + /* isConst = */ oldDescriptor.isConst, + /* isExpect = */ oldDescriptor.isExpect, + /* isActual = */ oldDescriptor.isActual, + /* isExternal = */ oldDescriptor.isExternal, + /* isDelegated = */ oldDescriptor.isDelegated + ) + descriptorSubstituteMap[oldDescriptor] = newDescriptor + } + + //---------------------------------------------------------------------// + + private fun copyClassDescriptor(oldDescriptor: ClassDescriptor): ClassDescriptorImpl { + val oldSuperClass = oldDescriptor.getSuperClassOrAny() + val newSuperClass = descriptorSubstituteMap.getOrDefault(oldSuperClass, oldSuperClass) as ClassDescriptor + val oldInterfaces = oldDescriptor.getSuperInterfaces() + val newInterfaces = oldInterfaces.map { descriptorSubstituteMap.getOrDefault(it, it) as ClassDescriptor } + val oldContainingDeclaration = oldDescriptor.containingDeclaration + val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) + val newName = if (DescriptorUtils.isAnonymousObject(oldDescriptor)) // Anonymous objects are identified by their name. + oldDescriptor.name // We need to preserve it for LocalDeclarationsLowering. + else + generateCopyName(oldDescriptor.name) + + val visibility = oldDescriptor.visibility + + return object : ClassDescriptorImpl( + /* containingDeclaration = */ newContainingDeclaration, + /* name = */ newName, + /* modality = */ oldDescriptor.modality, + /* kind = */ oldDescriptor.kind, + /* supertypes = */ listOf(newSuperClass.defaultType) + newInterfaces.map { it.defaultType }, + /* source = */ oldDescriptor.source, + /* isExternal = */ oldDescriptor.isExternal, + LockBasedStorageManager.NO_LOCKS + ) { + override fun getVisibility() = visibility + } + } + } + + //-------------------------------------------------------------------------// + + inner class DescriptorCollectorInitPhase : IrElementVisitorVoidWithContext() { + + private val initializedProperties = mutableSetOf() + + override fun visitElement(element: IrElement) { + element.acceptChildren(this, null) + } + + //---------------------------------------------------------------------// + + override fun visitPropertyNew(declaration: IrProperty) { + initPropertyOrField(declaration.descriptor) + super.visitPropertyNew(declaration) + } + + //---------------------------------------------------------------------// + + override fun visitFieldNew(declaration: IrField) { + val oldDescriptor = declaration.descriptor + if (!initializedProperties.contains(oldDescriptor)) { + initPropertyOrField(oldDescriptor) // A field without a property or a field of a delegated property. + } + super.visitFieldNew(declaration) + } + + //---------------------------------------------------------------------// + + override fun visitFunctionNew(declaration: IrFunction) { + val oldDescriptor = declaration.descriptor + if (oldDescriptor !is PropertyAccessorDescriptor) { // Property accessors are copied along with their property. + val newDescriptor = initFunctionDescriptor(oldDescriptor) + oldDescriptor.extensionReceiverParameter?.let { + descriptorSubstituteMap[it] = newDescriptor.extensionReceiverParameter!! + } + } + super.visitFunctionNew(declaration) + } + + //---------------------------------------------------------------------// + + override fun visitVariable(declaration: IrVariable) { + declaration.descriptor.let { descriptorSubstituteMap[it] = copyVariableDescriptor(it) } + + super.visitVariable(declaration) + } + + //---------------------------------------------------------------------// + + override fun visitCatch(aCatch: IrCatch) { + aCatch.parameter.let { descriptorSubstituteMap[it] = copyVariableDescriptor(it) } + + super.visitCatch(aCatch) + } + + //--- Copy descriptors ------------------------------------------------// + + private fun generateCopyName(name: Name): Name { + val declarationName = name.toString() // Name of declaration + val indexStr = (nameIndex++).toString() // Unique for inline target index + return Name.identifier(declarationName /*+ "_" + indexStr*/) + } + + //---------------------------------------------------------------------// + + private fun copyVariableDescriptor(oldDescriptor: VariableDescriptor): VariableDescriptor { + val oldContainingDeclaration = oldDescriptor.containingDeclaration + val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) + return IrTemporaryVariableDescriptorImpl( + containingDeclaration = newContainingDeclaration, + name = generateCopyName(oldDescriptor.name), + outType = substituteTypeAndTryGetCopied(oldDescriptor.type)!!, + isMutable = oldDescriptor.isVar + ) + } + + //---------------------------------------------------------------------// + + private fun initFunctionDescriptor(oldDescriptor: CallableDescriptor): CallableDescriptor = + when (oldDescriptor) { + is ConstructorDescriptor -> initConstructorDescriptor(oldDescriptor) + is SimpleFunctionDescriptor -> initSimpleFunctionDescriptor(oldDescriptor) + else -> TODO("Unsupported FunctionDescriptor subtype: $oldDescriptor") + } + + //---------------------------------------------------------------------// + + private fun initSimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor): FunctionDescriptor = + (descriptorSubstituteMap[oldDescriptor] as SimpleFunctionDescriptorImpl).apply { + val oldDispatchReceiverParameter = oldDescriptor.dispatchReceiverParameter + val newDispatchReceiverParameter = oldDispatchReceiverParameter?.let { descriptorSubstituteMap.getOrDefault(it, it) as ReceiverParameterDescriptor } + val newTypeParameters = oldDescriptor.typeParameters // TODO substitute types + val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, this) + val newReceiverParameterType = substituteTypeAndTryGetCopied(oldDescriptor.extensionReceiverParameter?.type) + val newReturnType = substituteTypeAndTryGetCopied(oldDescriptor.returnType) + + initialize( + /* receiverParameterType = */ newReceiverParameterType, + /* dispatchReceiverParameter = */ newDispatchReceiverParameter, + /* typeParameters = */ newTypeParameters, + /* unsubstitutedValueParameters = */ newValueParameters, + /* unsubstitutedReturnType = */ newReturnType, + /* modality = */ oldDescriptor.modality, + /* visibility = */ oldDescriptor.visibility + ) + isTailrec = oldDescriptor.isTailrec + isSuspend = oldDescriptor.isSuspend + overriddenDescriptors += oldDescriptor.overriddenDescriptors + } + + //---------------------------------------------------------------------// + + private fun initConstructorDescriptor(oldDescriptor: ConstructorDescriptor): FunctionDescriptor = + (descriptorSubstituteMap[oldDescriptor] as ClassConstructorDescriptorImpl).apply { + val newTypeParameters = oldDescriptor.typeParameters + val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, this) + val receiverParameterType = substituteTypeAndTryGetCopied(oldDescriptor.dispatchReceiverParameter?.type) + val returnType = substituteTypeAndTryGetCopied(oldDescriptor.returnType) + + initialize( + /* receiverParameterType = */ receiverParameterType, + /* dispatchReceiverParameter = */ null, // For constructor there is no explicit dispatch receiver. + /* typeParameters = */ newTypeParameters, + /* unsubstitutedValueParameters = */ newValueParameters, + /* unsubstitutedReturnType = */ returnType, + /* modality = */ oldDescriptor.modality, + /* visibility = */ oldDescriptor.visibility + ) + } + + //---------------------------------------------------------------------// + + private fun initPropertyOrField(oldDescriptor: PropertyDescriptor) { + val newDescriptor = (descriptorSubstituteMap[oldDescriptor] as PropertyDescriptorImpl).apply { + setType( + /* outType = */ substituteTypeAndTryGetCopied(oldDescriptor.type)!!, + /* typeParameters = */ oldDescriptor.typeParameters, + /* dispatchReceiverParameter = */ (containingDeclaration as ClassDescriptor).thisAsReceiverParameter, + /* receiverType = */ substituteTypeAndTryGetCopied(oldDescriptor.extensionReceiverParameter?.type)) + + initialize( + /* getter = */ oldDescriptor.getter?.let { copyPropertyGetterDescriptor(it, this) }, + /* setter = */ oldDescriptor.setter?.let { copyPropertySetterDescriptor(it, this) }) + + overriddenDescriptors += oldDescriptor.overriddenDescriptors + } + oldDescriptor.getter?.let { descriptorSubstituteMap[it] = newDescriptor.getter!! } + oldDescriptor.setter?.let { descriptorSubstituteMap[it] = newDescriptor.setter!! } + oldDescriptor.extensionReceiverParameter?.let { + descriptorSubstituteMap[it] = newDescriptor.extensionReceiverParameter!! + } + initializedProperties.add(oldDescriptor) + } + + //---------------------------------------------------------------------// + + private fun copyPropertyGetterDescriptor(oldDescriptor: PropertyGetterDescriptor, newPropertyDescriptor: PropertyDescriptor) = + PropertyGetterDescriptorImpl( + /* correspondingProperty = */ newPropertyDescriptor, + /* annotations = */ oldDescriptor.annotations, + /* modality = */ oldDescriptor.modality, + /* visibility = */ oldDescriptor.visibility, + /* isDefault = */ oldDescriptor.isDefault, + /* isExternal = */ oldDescriptor.isExternal, + /* isInline = */ oldDescriptor.isInline, + /* kind = */ oldDescriptor.kind, + /* original = */ null, + /* source = */ oldDescriptor.source).apply { + initialize(substituteTypeAndTryGetCopied(oldDescriptor.returnType)) + } + + //---------------------------------------------------------------------// + + private fun copyPropertySetterDescriptor(oldDescriptor: PropertySetterDescriptor, newPropertyDescriptor: PropertyDescriptor) = + PropertySetterDescriptorImpl( + /* correspondingProperty = */ newPropertyDescriptor, + /* annotations = */ oldDescriptor.annotations, + /* modality = */ oldDescriptor.modality, + /* visibility = */ oldDescriptor.visibility, + /* isDefault = */ oldDescriptor.isDefault, + /* isExternal = */ oldDescriptor.isExternal, + /* isInline = */ oldDescriptor.isInline, + /* kind = */ oldDescriptor.kind, + /* original = */ null, + /* source = */ oldDescriptor.source).apply { + initialize(copyValueParameters(oldDescriptor.valueParameters, this).single()) + } + + //-------------------------------------------------------------------------// + + private fun copyValueParameters(oldValueParameters: List , containingDeclaration: CallableDescriptor) = + oldValueParameters.map { oldDescriptor -> + val newDescriptor = ValueParameterDescriptorImpl( + containingDeclaration = containingDeclaration, + original = oldDescriptor.original, + index = oldDescriptor.index, + annotations = oldDescriptor.annotations, + name = oldDescriptor.name, + outType = substituteTypeAndTryGetCopied(oldDescriptor.type)!!, + declaresDefaultValue = oldDescriptor.declaresDefaultValue(), + isCrossinline = oldDescriptor.isCrossinline, + isNoinline = oldDescriptor.isNoinline, + varargElementType = substituteTypeAndTryGetCopied(oldDescriptor.varargElementType), + source = oldDescriptor.source + ) + descriptorSubstituteMap[oldDescriptor] = newDescriptor + newDescriptor + } + + private fun substituteTypeAndTryGetCopied(type: KotlinType?): KotlinType? { + val substitutedType = substituteType(type) ?: return null + val oldClassDescriptor = TypeUtils.getClassDescriptor(substitutedType) ?: return substitutedType + return descriptorSubstituteMap[oldClassDescriptor]?.let { (it as ClassDescriptor).defaultType } ?: substitutedType + } + } + +//-----------------------------------------------------------------------------// + + @Suppress("DEPRECATION") + inner class InlineCopyIr : DeepCopyIrTree() { + + override fun mapClassDeclaration (descriptor: ClassDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassDescriptor + override fun mapTypeAliasDeclaration (descriptor: TypeAliasDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as TypeAliasDescriptor + override fun mapFunctionDeclaration (descriptor: FunctionDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as FunctionDescriptor + override fun mapConstructorDeclaration (descriptor: ClassConstructorDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassConstructorDescriptor + override fun mapPropertyDeclaration (descriptor: PropertyDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as PropertyDescriptor + override fun mapLocalPropertyDeclaration (descriptor: VariableDescriptorWithAccessors) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptorWithAccessors + override fun mapEnumEntryDeclaration (descriptor: ClassDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassDescriptor + override fun mapVariableDeclaration (descriptor: VariableDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptor + override fun mapErrorDeclaration (descriptor: DeclarationDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) + + override fun mapClassReference (descriptor: ClassDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassDescriptor + override fun mapValueReference (descriptor: ValueDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ValueDescriptor + override fun mapVariableReference (descriptor: VariableDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptor + override fun mapPropertyReference (descriptor: PropertyDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as PropertyDescriptor + override fun mapCallee (descriptor: FunctionDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as FunctionDescriptor + override fun mapDelegatedConstructorCallee (descriptor: ClassConstructorDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassConstructorDescriptor + override fun mapEnumConstructorCallee (descriptor: ClassConstructorDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassConstructorDescriptor + override fun mapLocalPropertyReference (descriptor: VariableDescriptorWithAccessors) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptorWithAccessors + override fun mapClassifierReference (descriptor: ClassifierDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassifierDescriptor + override fun mapReturnTarget (descriptor: FunctionDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as FunctionDescriptor + + //---------------------------------------------------------------------// + + override fun mapSuperQualifier(qualifier: ClassDescriptor?): ClassDescriptor? { + if (qualifier == null) return null + return descriptorSubstituteMap.getOrDefault(qualifier, qualifier) as ClassDescriptor + } + + //--- Visits ----------------------------------------------------------// + + override fun visitCall(expression: IrCall): IrCall { + if (expression !is IrCallImpl) return super.visitCall(expression) + val newDescriptor = mapCallee(expression.descriptor) + return IrCallImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + type = newDescriptor.returnType!!, + descriptor = newDescriptor, + typeArgumentsCount = expression.typeArgumentsCount, + origin = expression.origin, + superQualifierDescriptor = mapSuperQualifier(expression.superQualifier) + ).apply { + transformValueArguments(expression) + substituteTypeArguments(expression) + } + } + + //---------------------------------------------------------------------// + + override fun visitFunction(declaration: IrFunction): IrFunction = + IrFunctionImpl( + startOffset = declaration.startOffset, + endOffset = declaration.endOffset, + origin = mapDeclarationOrigin(declaration.origin), + descriptor = mapFunctionDeclaration(declaration.descriptor), + body = declaration.body?.transform(this, null) + ).also { + it.setOverrides(context.symbolTable) + }.transformParameters(declaration) + + //---------------------------------------------------------------------// + + private fun T.transformDefaults(original: T): T { + for (originalValueParameter in original.descriptor.valueParameters) { + val valueParameter = descriptor.valueParameters[originalValueParameter.index] + original.getDefault(originalValueParameter)?.let { irDefaultParameterValue -> + putDefault(valueParameter, irDefaultParameterValue.transform(this@InlineCopyIr, null)) + } + } + return this + } + + //---------------------------------------------------------------------// + + fun getTypeOperatorReturnType(operator: IrTypeOperator, type: KotlinType) : KotlinType { + return when (operator) { + IrTypeOperator.CAST, + IrTypeOperator.IMPLICIT_CAST, + IrTypeOperator.IMPLICIT_NOTNULL, + IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, + IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type + IrTypeOperator.SAFE_CAST -> type.makeNullable() + IrTypeOperator.INSTANCEOF, + IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType + } + } + + //---------------------------------------------------------------------// + + override fun visitTypeOperator(expression: IrTypeOperatorCall): IrTypeOperatorCall { + val typeOperand = substituteType(expression.typeOperand)!! + val returnType = getTypeOperatorReturnType(expression.operator, typeOperand) + return IrTypeOperatorCallImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + type = returnType, + operator = expression.operator, + typeOperand = typeOperand, + argument = expression.argument.transform(this, null) + ) + } + + //---------------------------------------------------------------------// + + override fun visitReturn(expression: IrReturn): IrReturn = + IrReturnImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + type = substituteType(expression.type)!!, + returnTargetDescriptor = mapReturnTarget(expression.returnTarget), + value = expression.value.transform(this, null) + ) + + //---------------------------------------------------------------------// + + override fun visitBlock(expression: IrBlock): IrBlock { + return if (expression is IrReturnableBlock) { + IrReturnableBlockImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + type = expression.type, + descriptor = expression.descriptor, + origin = mapStatementOrigin(expression.origin), + statements = expression.statements.map { it.transform(this, null) }, + sourceFileName = expression.sourceFileName + ) + } else { + super.visitBlock(expression) + } + } + + //-------------------------------------------------------------------------// + + override fun visitClassReference(expression: IrClassReference): IrClassReference { + val newExpressionType = substituteType(expression.type)!! // Substituted expression type. + val newDescriptorType = substituteType(expression.descriptor.defaultType)!! // Substituted type of referenced class. + val classDescriptor = newDescriptorType.constructor.declarationDescriptor!! // Get ClassifierDescriptor of the referenced class. + return IrClassReferenceImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + type = newExpressionType, + descriptor = classDescriptor, + classType = expression.classType + ) + } + + //-------------------------------------------------------------------------// + + override fun visitGetClass(expression: IrGetClass): IrGetClass { + val type = substituteType(expression.type)!! + return IrGetClassImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + type = type, + argument = expression.argument.transform(this, null) + ) + } + + //-------------------------------------------------------------------------// + + override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop { + return irLoop + } + } + + //-------------------------------------------------------------------------// + + private fun substituteType(oldType: KotlinType?): KotlinType? { + if (typeSubstitutor == null) return oldType + if (oldType == null) return oldType + return typeSubstitutor!!.substitute(oldType, Variance.INVARIANT) ?: oldType + } + + //-------------------------------------------------------------------------// + + private fun IrMemberAccessExpression.substituteTypeArguments(original: IrMemberAccessExpression) { + for (index in 0 until original.typeArgumentsCount) { + val originalTypeArgument = original.getTypeArgument(index) + val newTypeArgument = substituteType(originalTypeArgument)!! + this.putTypeArgument(index, newTypeArgument) + } + } + + //-------------------------------------------------------------------------// + + fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap) { + descriptorSubstituteMap.forEach { t, u -> + globalSubstituteMap.put(t, SubstitutedDescriptor(targetDescriptor, u)) + } + } + +} + +class SubstitutedDescriptor(val inlinedFunction: FunctionDescriptor, val descriptor: DeclarationDescriptor) + +class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap) + : IrElementTransformerVoidWithContext() { + + private val variableSubstituteMap = mutableMapOf() + + fun run(element: IrElement) { + collectVariables(element) + element.transformChildrenVoid(this) + } + + private fun collectVariables(element: IrElement) { + element.acceptChildrenVoid(object: IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitVariable(declaration: IrVariable) { + declaration.acceptChildrenVoid(this) + + val oldDescriptor = declaration.descriptor + val oldClassDescriptor = oldDescriptor.type.constructor.declarationDescriptor as? ClassDescriptor + val substitutedDescriptor = oldClassDescriptor?.let { globalSubstituteMap[it] } + if (substitutedDescriptor == null || allScopes.any { it.scope.scopeOwner == substitutedDescriptor.inlinedFunction }) + return + val newDescriptor = IrTemporaryVariableDescriptorImpl( + containingDeclaration = oldDescriptor.containingDeclaration, + name = oldDescriptor.name, + outType = (substitutedDescriptor.descriptor as ClassDescriptor).defaultType, + isMutable = oldDescriptor.isVar) + variableSubstituteMap[oldDescriptor] = newDescriptor + } + }) + } + + override fun visitCall(expression: IrCall): IrExpression { + val oldExpression = super.visitCall(expression) as IrCall + + val substitutedDescriptor = globalSubstituteMap[expression.descriptor.original] + ?: return oldExpression + if (allScopes.any { it.scope.scopeOwner == substitutedDescriptor.inlinedFunction }) + return oldExpression + return when (oldExpression) { + is IrCallImpl -> copyIrCallImpl(oldExpression, substitutedDescriptor) + is IrCallWithShallowCopy -> copyIrCallWithShallowCopy(oldExpression, substitutedDescriptor) + else -> oldExpression + } + } + + //---------------------------------------------------------------------// + + override fun visitVariable(declaration: IrVariable): IrDeclaration { + declaration.transformChildrenVoid(this) + + val oldDescriptor = declaration.descriptor + val newDescriptor = variableSubstituteMap[oldDescriptor] ?: return declaration + + return IrVariableImpl( + startOffset = declaration.startOffset, + endOffset = declaration.endOffset, + origin = declaration.origin, + descriptor = newDescriptor, + initializer = declaration.initializer + ) + } + + //-------------------------------------------------------------------------// + + override fun visitGetValue(expression: IrGetValue): IrExpression { + expression.transformChildrenVoid(this) + + val oldDescriptor = expression.descriptor + val newDescriptor = variableSubstituteMap[oldDescriptor] ?: return expression + + return IrGetValueImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + origin = expression.origin, + symbol = createValueSymbol(newDescriptor) + ) + } + + //-------------------------------------------------------------------------// + + private fun copyIrCallImpl(oldExpression: IrCallImpl, substitutedDescriptor: SubstitutedDescriptor): IrCallImpl { + + val oldDescriptor = oldExpression.descriptor + val newDescriptor = substitutedDescriptor.descriptor as FunctionDescriptor + + if (newDescriptor == oldDescriptor) + return oldExpression + + return IrCallImpl( + startOffset = oldExpression.startOffset, + endOffset = oldExpression.endOffset, + type = newDescriptor.returnType!!, + symbol = createFunctionSymbol(newDescriptor), + descriptor = newDescriptor, + typeArgumentsCount = oldExpression.typeArgumentsCount, + origin = oldExpression.origin, + superQualifierSymbol = createClassSymbolOrNull(oldExpression.superQualifier) + ).apply { + copyTypeArgumentsFrom(oldExpression) + + oldExpression.descriptor.valueParameters.forEach { + val valueArgument = oldExpression.getValueArgument(it) + putValueArgument(it.index, valueArgument) + } + extensionReceiver = oldExpression.extensionReceiver + dispatchReceiver = oldExpression.dispatchReceiver + } + } + + //-------------------------------------------------------------------------// + + private fun copyIrCallWithShallowCopy(oldExpression: IrCallWithShallowCopy, substitutedDescriptor: SubstitutedDescriptor): IrCall { + + val oldDescriptor = oldExpression.descriptor + val newDescriptor = substitutedDescriptor.descriptor as FunctionDescriptor + + if (newDescriptor == oldDescriptor) + return oldExpression + + return oldExpression.shallowCopy(oldExpression.origin, createFunctionSymbol(newDescriptor), oldExpression.superQualifierSymbol) + } +} + 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 new file mode 100644 index 00000000000..6f4382f4bda --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt @@ -0,0 +1,386 @@ +/* + * 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. + */ + +@file:Suppress("FoldInitializerAndIfToElvis") + +package org.jetbrains.kotlin.ir.backend.js.lower.inline + +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.ScopeWithIr +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.reportWarning +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 +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.getDefault +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue +import org.jetbrains.kotlin.resolve.inline.InlineUtil +import org.jetbrains.kotlin.types.TypeConstructor +import org.jetbrains.kotlin.types.TypeProjection +import org.jetbrains.kotlin.types.TypeProjectionImpl +import org.jetbrains.kotlin.types.TypeSubstitutor + +//-----------------------------------------------------------------------------// + +typealias Context = JsIrBackendContext + +// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt +internal class FunctionInlining(val context: Context): IrElementTransformerVoidWithContext() { + + // TODO private val deserializer = DeserializerDriver(context) + private val globalSubstituteMap = mutableMapOf() + + //-------------------------------------------------------------------------// + + fun inline(irModule: IrModuleFragment): IrElement { + val transformedModule = irModule.accept(this, null) + DescriptorSubstitutorForExternalScope(globalSubstituteMap).run(transformedModule) // Transform calls to object that might be returned from inline function call. + return transformedModule + } + + //-------------------------------------------------------------------------// + + override fun visitCall(expression: IrCall): IrExpression { + + val irCall = super.visitCall(expression) as IrCall + val functionDescriptor = irCall.descriptor + if (!functionDescriptor.needsInlining) return irCall // This call does not need inlining. + + val functionDeclaration = getFunctionDeclaration(irCall) // Get declaration of the function to be inlined. + if (functionDeclaration == null) { // We failed to get the declaration. + val message = "Inliner failed to obtain function declaration: " + + functionDescriptor.fqNameSafe.toString() + context.reportWarning(message, currentFile, irCall) // Report warning. + return irCall + } + + functionDeclaration.transformChildrenVoid(this) // Process recursive inline. + val inliner = Inliner( + globalSubstituteMap, + functionDeclaration, + currentScope!!, + context + ) // Create inliner for this scope. + return inliner.inline(irCall ) // Return newly created IrInlineBody instead of IrCall. + } + + //-------------------------------------------------------------------------// + + private fun getFunctionDeclaration(irCall: IrCall): IrFunction? { + + val functionDescriptor = irCall.descriptor + val originalDescriptor = functionDescriptor.resolveFakeOverride().original + val functionDeclaration = + context.originalModuleIndex.functions[originalDescriptor] // ?: // If function is declared in the current module. + // TODO deserializer.deserializeInlineBody(originalDescriptor) // Function is declared in another module. + return functionDeclaration as IrFunction? + } + + //-------------------------------------------------------------------------// + + override fun visitElement(element: IrElement) = element.accept(this, null) +} + +// TODO: should we keep this at all? +private val inlineConstructor = FqName("konan.internal.InlineConstructor") +private val FunctionDescriptor.isInlineConstructor get() = annotations.hasAnnotation(inlineConstructor) + +//-----------------------------------------------------------------------------// + +private class Inliner(val globalSubstituteMap: MutableMap, + val functionDeclaration: IrFunction, // Function to substitute. + val currentScope: ScopeWithIr, + val context: Context +) { + + val copyIrElement = DeepCopyIrTreeWithDescriptors( + functionDeclaration.descriptor, + currentScope.scope.scopeOwner, + context + ) // Create DeepCopy for current scope. + val substituteMap = mutableMapOf() + + //-------------------------------------------------------------------------// + + fun inline(irCall: IrCall): IrReturnableBlockImpl { // Call to be substituted. + val inlineFunctionBody = inlineFunction(irCall, functionDeclaration) + copyIrElement.addCurrentSubstituteMap(globalSubstituteMap) + return inlineFunctionBody + } + + //-------------------------------------------------------------------------// + + private fun inlineFunction(callee: IrCall, // Call to be substituted. + caller: IrFunction): IrReturnableBlockImpl { // Function to substitute. + + val copyFunctionDeclaration = copyIrElement.copy( // Create copy of original function. + irElement = caller, // Descriptors declared inside the function will be copied. + typeSubstitutor = createTypeSubstitutor(callee) // Type parameters will be substituted with type arguments. + ) as IrFunction + + val irReturnableBlockSymbol = IrReturnableBlockSymbolImpl(copyFunctionDeclaration.descriptor.original) + + val evaluationStatements = evaluateArguments(callee, copyFunctionDeclaration) // And list of evaluation statements. + + val statements = (copyFunctionDeclaration.body as IrBlockBody).statements // IR statements from function copy. + + val startOffset = caller.startOffset + val endOffset = caller.endOffset + val descriptor = caller.descriptor.original + if (descriptor.isInlineConstructor) { + val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall + val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset) + irBuilder.run { + val constructorDescriptor = delegatingConstructorCall.descriptor.original + val constructorCall = irCall(delegatingConstructorCall.symbol, + constructorDescriptor.typeParameters.associate { it to delegatingConstructorCall.getTypeArgument(it)!! }).apply { + constructorDescriptor.valueParameters.forEach { putValueArgument(it, delegatingConstructorCall.getValueArgument(it)) } + } + val oldThis = delegatingConstructorCall.descriptor.constructedClass.thisAsReceiverParameter + val newThis = currentScope.scope.createTemporaryVariable( + irExpression = constructorCall, + nameHint = delegatingConstructorCall.descriptor.fqNameSafe.toString() + ".this" + ) + statements[0] = newThis + substituteMap[oldThis] = irGet(newThis.symbol) + statements.add(irReturn(irGet(newThis.symbol))) + } + } + + val returnType = copyFunctionDeclaration.descriptor.returnType!! // Substituted return type. + val sourceFileName = context.originalModuleIndex.declarationToFile[caller.descriptor.original] ?: "" + val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call". + startOffset = startOffset, + endOffset = endOffset, + type = returnType, + symbol = irReturnableBlockSymbol, + origin = null, + statements = statements, + sourceFileName = sourceFileName + ) + + val transformer = ParameterSubstitutor() + inlineFunctionBody.transformChildrenVoid(transformer) // Replace value parameters with arguments. + inlineFunctionBody.statements.addAll(0, evaluationStatements) // Insert evaluation statements. + return inlineFunctionBody // Replace call site with InlineFunctionBody. + } + + //---------------------------------------------------------------------// + + private inner class ParameterSubstitutor: IrElementTransformerVoid() { + + override fun visitGetValue(expression: IrGetValue): IrExpression { + val newExpression = super.visitGetValue(expression) as IrGetValue + val descriptor = newExpression.descriptor + val argument = substituteMap[descriptor] // Find expression to replace this parameter. + if (argument == null) return newExpression // If there is no such expression - do nothing. + + argument.transformChildrenVoid(this) // Default argument can contain subjects for substitution. + return copyIrElement.copy( // Make copy of argument expression. + irElement = argument, + typeSubstitutor = null + ) as IrExpression + } + + //-----------------------------------------------------------------// + + override fun visitCall(expression: IrCall): IrExpression { + + if (!isLambdaCall(expression)) return super.visitCall(expression) // If it is not lambda call - return. + + val dispatchReceiver = expression.dispatchReceiver as IrGetValue // Here we can have only GetValue as dispatch receiver. + val functionArgument = substituteMap[dispatchReceiver.descriptor] // Try to find lambda representation. // TODO original? + if (functionArgument == null) return super.visitCall(expression) // It is not call of argument lambda - nothing to substitute. + if (functionArgument !is IrBlock) return super.visitCall(expression) + + val dispatchDescriptor = dispatchReceiver.descriptor // Check if this functional parameter has "noInline" tag + if (dispatchDescriptor is ValueParameterDescriptor && + dispatchDescriptor.isNoinline) return super.visitCall(expression) + + val functionDeclaration = getLambdaFunction(functionArgument) + val newExpression = inlineFunction(expression, functionDeclaration) // Inline the lambda. Lambda parameters will be substituted with lambda arguments. + return newExpression.transform(this, null) // Substitute lambda arguments with target function arguments. + } + + //-----------------------------------------------------------------// + + override fun visitElement(element: IrElement) = element.accept(this, null) + } + + //--- Helpers -------------------------------------------------------------// + + private fun isLambdaCall(irCall: IrCall) : Boolean { + if (!irCall.descriptor.isFunctionInvoke) return false // Lambda mast be called by "invoke". + if (irCall.dispatchReceiver !is IrGetValue) return false // Dispatch receiver mast be IrGetValue. + return true // It is lambda call. + } + + //-------------------------------------------------------------------------// + + private fun getLambdaFunction(lambdaArgument: IrBlock): IrFunction { + val statements = lambdaArgument.statements + return statements[0] as IrFunction + } + + //-------------------------------------------------------------------------// + + private fun createTypeSubstitutor(irCall: IrCall): TypeSubstitutor? { + if (irCall.typeArgumentsCount == 0) return null + val descriptor = irCall.descriptor.resolveFakeOverride().original + val typeParameters = descriptor.propertyIfAccessor.typeParameters + val substitutionContext = mutableMapOf() + for (index in 0 until irCall.typeArgumentsCount) { + val typeArgument = irCall.getTypeArgument(index) ?: continue + substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument) + } + return TypeSubstitutor.create(substitutionContext) + } + + //-------------------------------------------------------------------------// + + private class ParameterToArgument(val parameterDescriptor: ParameterDescriptor, + val argumentExpression : IrExpression) { + + val isInlinableLambda : Boolean + get() { + if (!InlineUtil.isInlineParameter(parameterDescriptor)) return false + if (argumentExpression !is IrBlock) return false // Lambda must be represented with IrBlock. + if (argumentExpression.origin != IrStatementOrigin.LAMBDA && // Origin must be LAMBDA or ANONYMOUS. + argumentExpression.origin != IrStatementOrigin.ANONYMOUS_FUNCTION) return false + + val statements = argumentExpression.statements + val irFunction = statements[0] // Lambda function declaration. + val irCallableReference = statements[1] // Lambda callable reference. + if (irFunction !is IrFunction) return false // First statement of the block must be lambda declaration. + if (irCallableReference !is IrCallableReference) return false // Second statement of the block must be CallableReference. + return true // The expression represents lambda. + } + } + + //-------------------------------------------------------------------------// + + private fun buildParameterToArgument(irCall : IrCall, // Call site. + irFunction: IrFunction // Function to be called. + ): List { + + val parameterToArgument = mutableListOf() // Result list. + val functionDescriptor = irFunction.descriptor.original // Descriptor of function to be called. + + if (irCall.dispatchReceiver != null && // Only if there are non null dispatch receivers both + functionDescriptor.dispatchReceiverParameter != null) // on call site and in function declaration. + parameterToArgument += ParameterToArgument( + parameterDescriptor = functionDescriptor.dispatchReceiverParameter!!, + argumentExpression = irCall.dispatchReceiver!! + ) + + val valueArguments = + irCall.descriptor.valueParameters.map { irCall.getValueArgument(it) }.toMutableList() + + if (functionDescriptor.extensionReceiverParameter != null) { + parameterToArgument += ParameterToArgument( + parameterDescriptor = functionDescriptor.extensionReceiverParameter!!, + argumentExpression = if (irCall.extensionReceiver != null) { + irCall.extensionReceiver!! + } else { + // Special case: lambda with receiver is called as usual lambda: + valueArguments.removeAt(0)!! + } + ) + } else if (irCall.extensionReceiver != null) { + // Special case: usual lambda is called as lambda with receiver: + valueArguments.add(0, irCall.extensionReceiver!!) + } + + val parametersWithDefaultToArgument = mutableListOf() + functionDescriptor.valueParameters.forEach { parameterDescriptor -> // Iterate value parameter descriptors. + val argument = valueArguments[parameterDescriptor.index] // Get appropriate argument from call site. + when { + argument != null -> { // Argument is good enough. + parameterToArgument += ParameterToArgument( // Associate current parameter with the argument. + parameterDescriptor = parameterDescriptor, + argumentExpression = argument + ) + } + + parameterDescriptor.hasDefaultValue() -> { // There is no argument - try default value. + val defaultArgument = irFunction.getDefault(parameterDescriptor)!! + parametersWithDefaultToArgument += ParameterToArgument( + parameterDescriptor = parameterDescriptor, + argumentExpression = defaultArgument.expression + ) + } + + parameterDescriptor.varargElementType != null -> { + val emptyArray = IrVarargImpl( + startOffset = irCall.startOffset, + endOffset = irCall.endOffset, + type = parameterDescriptor.type, + varargElementType = parameterDescriptor.varargElementType!! + ) + parameterToArgument += ParameterToArgument( + parameterDescriptor = parameterDescriptor, + argumentExpression = emptyArray + ) + } + + else -> { + val message = "Incomplete expression: call to $functionDescriptor " + + "has no argument at index ${parameterDescriptor.index}" + throw Error(message) + } + } + } + return parameterToArgument + parametersWithDefaultToArgument // All arguments except default are evaluated at callsite, + // but default arguments are evaluated inside callee. + } + + //-------------------------------------------------------------------------// + + private fun evaluateArguments(irCall : IrCall, // Call site. + functionDeclaration: IrFunction // Function to be called. + ): List { + + val parameterToArgumentOld = buildParameterToArgument(irCall, functionDeclaration) // Create map parameter_descriptor -> original_argument_expression. + val evaluationStatements = mutableListOf() // List of evaluation statements. + val substitutor = ParameterSubstitutor() + parameterToArgumentOld.forEach { + val parameterDescriptor = it.parameterDescriptor + + if (it.isInlinableLambda || it.argumentExpression is IrGetValue) { // If argument is inlinable lambda. IrGetValue is skipped because of recursive inline. + substituteMap[parameterDescriptor] = it.argumentExpression // Associate parameter with lambda argument. + return@forEach + } + + val newVariable = currentScope.scope.createTemporaryVariable( // Create new variable and init it with the parameter expression. + irExpression = it.argumentExpression.transform(substitutor, data = null), // Arguments may reference the previous ones - substitute them. + nameHint = functionDeclaration.descriptor.name.toString(), + isMutable = false) + + evaluationStatements.add(newVariable) // Add initialization of the new variable in statement list. + val getVal = IrGetValueImpl( // Create new expression, representing access the new variable. + startOffset = currentScope.irElement.startOffset, + endOffset = currentScope.irElement.endOffset, + symbol = createValueSymbol(newVariable.descriptor) + ) + substituteMap[parameterDescriptor] = getVal // Parameter will be replaced with the new variable. + } + return evaluationStatements + } +} \ No newline at end of file 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 new file mode 100644 index 00000000000..570af4a1aec --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUnboundSymbolReplacer.kt @@ -0,0 +1,417 @@ +/* + * 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.lower.inline + +import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +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.lower.inline.addChildren +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator +import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.ir.visitors.* + +// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt +@Deprecated("") +internal fun IrModuleFragment.replaceUnboundSymbols(context: JsIrBackendContext) { + val collector = DeclarationSymbolCollector() + with(collector) { + with(irBuiltins) { + for (op in arrayOf(eqeqeqFun, eqeqFun, throwNpeFun, booleanNotFun, noWhenBranchMatchedExceptionFun) + + lessFunByOperandType.values + + lessOrEqualFunByOperandType.values + + greaterOrEqualFunByOperandType.values + + greaterFunByOperandType.values + + ieee754equalsFunByOperandType.values) { + register(op.symbol) + } + } + } + this.acceptVoid(collector) + + val symbolTable = context.symbolTable + + this.transformChildrenVoid( + IrUnboundSymbolReplacer( + symbolTable, + collector.descriptorToSymbol + ) + ) + + // Generate missing external stubs: + // TODO: ModuleGenerator::generateUnboundSymbolsAsDependencies(IRModuleFragment) is private function :/ + @Suppress("DEPRECATION") + ExternalDependenciesGenerator(symbolTable = context.symbolTable, irBuiltIns = context.irBuiltIns).generateUnboundSymbolsAsDependencies(this) + + // Merge duplicated module and package declarations: + this.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) {} + + override fun visitModuleFragment(declaration: IrModuleFragment) { + declaration.dependencyModules.forEach { it.acceptVoid(this) } + + val dependencyModules = declaration.dependencyModules.toSet().groupBy { it.descriptor }.map { (_, fragments) -> + fragments.reduce { firstModule, nextModule -> + firstModule.apply { + mergeFrom(nextModule) + } + } + } + + declaration.dependencyModules.clear() + declaration.dependencyModules.addAll(dependencyModules) + } + + }) +} + +private fun IrModuleFragment.mergeFrom(other: IrModuleFragment): Unit { + assert(this.files.isEmpty()) + assert(other.files.isEmpty()) + + val thisPackages = this.externalPackageFragments.groupBy { it.packageFragmentDescriptor } + other.externalPackageFragments.forEach { + val thisPackage = thisPackages[it.packageFragmentDescriptor]?.toSet()?.single() + if (thisPackage == null) { + this.externalPackageFragments.add(it) + } else { + thisPackage.addChildren(it.declarations) + } + } +} + +private class DeclarationSymbolCollector : IrElementVisitorVoid { + + val descriptorToSymbol = mutableMapOf() + + fun register(symbol: IrSymbol) { + descriptorToSymbol[symbol.descriptor] = symbol + } + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + + if (element is IrSymbolOwner && element !is IrAnonymousInitializer) { + register(element.symbol) + } + } +} + +private class IrUnboundSymbolReplacer( + val symbolTable: SymbolTable, + val descriptorToSymbol: Map +) : IrElementTransformerVoid() { + + private val localDescriptorToSymbol = mutableMapOf>() + + private inline fun withLocal(symbol: IrSymbol?, block: () -> R): R { + if (symbol == null) return block() + + val locals = localDescriptorToSymbol.getOrPut(symbol.descriptor) { mutableListOf() } + locals.add(symbol) + return try { + block() + } finally { + locals.removeAt(locals.lastIndex) + } + } + + private inline fun S.replace( + referenceSymbol: (SymbolTable, D) -> S): S? { + + if (this.isBound) { + return null + } + + localDescriptorToSymbol[this.descriptor]?.lastOrNull()?.let { + return it as S + } + + + descriptorToSymbol[this.descriptor]?.let { + return it as S + } + + return referenceSymbol(symbolTable, this.descriptor as D) + } + + private inline fun S.replaceOrSame( + referenceSymbol: (SymbolTable, D) -> S): S = this.replace(referenceSymbol) ?: this + + private inline fun S.replaceLocal(): S? { + return if (this.isBound) { + null + } else { + (localDescriptorToSymbol[this.descriptor]?.lastOrNull() ?: descriptorToSymbol[this.descriptor]) as S + } + } + + override fun visitGetValue(expression: IrGetValue): IrExpression { + val symbol = expression.symbol.replaceLocal() ?: return super.visitGetValue(expression) + + expression.transformChildrenVoid(this) + return with(expression) { + IrGetValueImpl(startOffset, endOffset, symbol, origin) + } + } + + override fun visitSetVariable(expression: IrSetVariable): IrExpression { + val symbol = expression.symbol.replaceLocal() ?: return super.visitSetVariable(expression) + + expression.transformChildrenVoid(this) + return with(expression) { + IrSetVariableImpl(startOffset, endOffset, symbol, value, origin) + } + } + + override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceClass) ?: + return super.visitGetObjectValue(expression) + + expression.transformChildrenVoid(this) + return with(expression) { + IrGetObjectValueImpl(startOffset, endOffset, type, symbol) + } + } + + override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceEnumEntry) ?: + return super.visitGetEnumValue(expression) + + expression.transformChildrenVoid(this) + return with(expression) { + IrGetEnumValueImpl(startOffset, endOffset, type, symbol) + } + } + + override fun visitClassReference(expression: IrClassReference): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceClassifier) + ?: return super.visitClassReference(expression) + + expression.transformChildrenVoid(this) + return with(expression) { + IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.descriptor.defaultType) + } + } + + override fun visitClass(declaration: IrClass): IrStatement { + declaration.superClasses.forEachIndexed { index, symbol -> + val newSymbol = symbol.replace(SymbolTable::referenceClass) + if (newSymbol != null) { + declaration.superClasses[index] = newSymbol + } + } + withLocal(declaration.thisReceiver?.symbol) { + return super.visitClass(declaration) + } + } + + override fun visitGetField(expression: IrGetField): IrExpression { + val symbol = expression.symbol.replaceOrSame(SymbolTable::referenceField) + + val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass) + + if (symbol == expression.symbol && superQualifierSymbol == expression.superQualifierSymbol) { + return super.visitGetField(expression) + } + + expression.transformChildrenVoid(this) + return with(expression) { + IrGetFieldImpl(startOffset, endOffset, symbol, receiver, origin, superQualifierSymbol) + } + } + + override fun visitSetField(expression: IrSetField): IrExpression { + val symbol = expression.symbol.replaceOrSame(SymbolTable::referenceField) + + val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass) + + if (symbol == expression.symbol && superQualifierSymbol == expression.superQualifierSymbol) { + return super.visitSetField(expression) + } + + expression.transformChildrenVoid(this) + return with(expression) { + IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, origin, superQualifierSymbol) + } + } + + override fun visitCall(expression: IrCall): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: expression.symbol + + val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass) + + if (symbol == expression.symbol && superQualifierSymbol == expression.superQualifierSymbol) { + return super.visitCall(expression) + } + + expression.transformChildrenVoid() + return with(expression) { + IrCallImpl(startOffset, endOffset, symbol, descriptor, + getTypeArgumentsMap(), + origin, superQualifierSymbol).also { + + it.copyArgumentsFrom(this) + } + } + } + + private fun IrMemberAccessExpression.getTypeArgumentsMap() = + descriptor.original.typeParameters.associate { it to getTypeArgumentOrDefault(it) } + + private fun IrMemberAccessExpressionBase.copyArgumentsFrom(original: IrMemberAccessExpression) { + dispatchReceiver = original.dispatchReceiver + extensionReceiver = original.extensionReceiver + original.descriptor.valueParameters.forEachIndexed { index, _ -> + putValueArgument(index, original.getValueArgument(index)) + } + } + + override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?: + return super.visitEnumConstructorCall(expression) + + return with(expression) { + IrEnumConstructorCallImpl(startOffset, endOffset, symbol, null).also { + it.copyArgumentsFrom(this) + } + } + } + + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?: + return super.visitDelegatingConstructorCall(expression) + + expression.transformChildrenVoid() + return with(expression) { + IrDelegatingConstructorCallImpl(startOffset, endOffset, symbol, descriptor, getTypeArgumentsMap()).also { + it.copyArgumentsFrom(this) + } + } + } + + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: + return super.visitFunctionReference(expression) + + expression.transformChildrenVoid(this) + return with(expression) { + IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, getTypeArgumentsMap()).also { + it.copyArgumentsFrom(this) + } + } + } + + override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { + 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 + + if (field == expression.field && getter == expression.getter && setter == expression.setter) { + return super.visitPropertyReference(expression) + } + + expression.transformChildrenVoid(this) + return with(expression) { + IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor, + field, + getter, + setter, + getTypeArgumentsMap(), origin).also { + + it.copyArgumentsFrom(this) + } + } + } + + 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 + + if (delegate == expression.delegate && getter == expression.getter && setter == expression.setter) { + return super.visitLocalDelegatedPropertyReference(expression) + } + + expression.transformChildrenVoid(this) + return with(expression) { + IrLocalDelegatedPropertyReferenceImpl(startOffset, endOffset, type, descriptor, + delegate, getter, setter, origin).also { + + it.copyArgumentsFrom(this) + } + } + } + + private val returnTargetStack = mutableListOf() + + override fun visitFunction(declaration: IrFunction): IrStatement { + returnTargetStack.push(declaration.symbol) + try { + if (declaration is IrSimpleFunction) { + declaration.overriddenSymbols.forEachIndexed { index, symbol -> + val newSymbol = symbol.replace(SymbolTable::referenceSimpleFunction) + if (newSymbol != null) { + declaration.overriddenSymbols[index] = newSymbol + } + } + } + + withLocal(declaration.dispatchReceiverParameter?.symbol) { + withLocal(declaration.extensionReceiverParameter?.symbol) { + return super.visitFunction(declaration) + } + } + } finally { + returnTargetStack.pop() + } + } + + override fun visitBlock(expression: IrBlock): IrExpression { + if (expression is IrReturnableBlock) { + returnTargetStack.push(expression.symbol) + try { + return super.visitBlock(expression) + } finally { + returnTargetStack.pop() + } + } else { + return super.visitBlock(expression) + } + } + + override fun visitReturn(expression: IrReturn): IrExpression { + if (expression.returnTargetSymbol.isBound) { + return super.visitReturn(expression) + } + + val returnTargetSymbol = returnTargetStack.last { it.descriptor == expression.returnTarget } + + expression.transformChildrenVoid(this) + + return with(expression) { + IrReturnImpl(startOffset, endOffset, type, returnTargetSymbol, value) + } + } + + override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression { + val classSymbol = expression.classSymbol.replace(SymbolTable::referenceClass) ?: + return super.visitInstanceInitializerCall(expression) + + expression.transformChildrenVoid(this) + + return with(expression) { + IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol) + } + } +} 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 new file mode 100644 index 00000000000..99575377221 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUtils2.kt @@ -0,0 +1,59 @@ +/* + * 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.lower.inline + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl +import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor + +// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt +fun IrSimpleFunction.setOverrides(symbolTable: SymbolTable) { + assert(this.overriddenSymbols.isEmpty()) + + this.descriptor.overriddenDescriptors.mapTo(this.overriddenSymbols) { + symbolTable.referenceSimpleFunction(it.original) + } + + this.typeParameters.forEach { it.setSupers(symbolTable) } +} + +fun IrTypeParameter.setSupers(symbolTable: SymbolTable) { + assert(this.superClassifiers.isEmpty()) + this.descriptor.upperBounds.mapNotNullTo(this.superClassifiers) { + it.constructor.declarationDescriptor?.let { + if (it is TypeParameterDescriptor) { + IrTypeParameterSymbolImpl(it) // Workaround for deserialized inline functions + } else { + symbolTable.referenceClassifier(it) + } + } + } +} + +fun IrDeclarationContainer.addChildren(declarations: List) { + declarations.forEach { this.addChild(it) } +} + +fun IrDeclarationContainer.addChild(declaration: IrDeclaration) { + this.declarations += declaration + declaration.accept(SetDeclarationsParentVisitor, this) +} + +object SetDeclarationsParentVisitor : IrElementVisitor { + override fun visitElement(element: IrElement, data: IrDeclarationParent) { + if (element !is IrDeclarationParent) { + element.acceptChildren(this, data) + } + } + + override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclarationParent) { + declaration.parent = data + super.visitDeclaration(declaration, data) + } +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/LegacyDescriptorUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/LegacyDescriptorUtils.kt new file mode 100644 index 00000000000..998437556d7 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/LegacyDescriptorUtils.kt @@ -0,0 +1,62 @@ +/* + * 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.lower.inline + +import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor +import org.jetbrains.kotlin.builtins.getFunctionalClassKind +import org.jetbrains.kotlin.builtins.isFunctionType +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.OverridingUtil +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.util.OperatorNameConventions + +// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt +/** + * Implementation of given method. + * + * TODO: this method is actually a part of resolve and probably duplicates another one + */ +internal fun T.resolveFakeOverride(): T { + if (this.kind.isReal) { + return this + } else { + val overridden = OverridingUtil.getOverriddenDeclarations(this) + val filtered = OverridingUtil.filterOutOverridden(overridden) + // TODO: is it correct to take first? + @Suppress("UNCHECKED_CAST") + return filtered.first { it.modality != Modality.ABSTRACT } as T + } +} + +internal val KotlinType.isKFunctionType: Boolean + get() { + val kind = constructor.declarationDescriptor?.getFunctionalClassKind() + return kind == FunctionClassDescriptor.Kind.KFunction + } + +internal val FunctionDescriptor.isFunctionInvoke: Boolean + get() { + val dispatchReceiver = dispatchReceiverParameter ?: return false + assert(!dispatchReceiver.type.isKFunctionType) + + return dispatchReceiver.type.isFunctionType && + this.isOperator && this.name == OperatorNameConventions.INVOKE + } + +// It is possible to declare "external inline fun", +// but it doesn't have much sense for native, +// since externals don't have IR bodies. +// Enforce inlining of constructors annotated with @InlineConstructor. +// TODO: should we keep this? +private val inlineConstructor = FqName("konan.internal.InlineConstructor") + +internal val FunctionDescriptor.needsInlining: Boolean + get() { + val inlineConstructor = annotations.hasAnnotation(inlineConstructor) + if (inlineConstructor) return true + return (this.isInline && !this.isExternal) + } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/ModuleIndex.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/ModuleIndex.kt new file mode 100644 index 00000000000..f56bdf551e2 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/ModuleIndex.kt @@ -0,0 +1,73 @@ +/* + * 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.lower.inline + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid + +// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/ModuleIndex.kt +class ModuleIndex(val module: IrModuleFragment) { + + var currentFile: IrFile? = null + /** + * Contains all classes declared in [module] + */ + val classes: Map + + val enumEntries: Map + + /** + * Contains all functions declared in [module] + */ + val functions = mutableMapOf() + val declarationToFile = mutableMapOf() + + init { + val map = mutableMapOf() + enumEntries = mutableMapOf() + + module.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitFile(declaration: IrFile) { + currentFile = declaration + super.visitFile(declaration) + } + + override fun visitClass(declaration: IrClass) { + super.visitClass(declaration) + + map[declaration.descriptor] = declaration + } + + override fun visitEnumEntry(declaration: IrEnumEntry) { + super.visitEnumEntry(declaration) + + enumEntries[declaration.descriptor] = declaration + } + + override fun visitFunction(declaration: IrFunction) { + super.visitFunction(declaration) + functions[declaration.descriptor] = declaration + } + + override fun visitDeclaration(declaration: IrDeclaration) { + super.visitDeclaration(declaration) + declarationToFile[declaration.descriptor] = currentFile!!.name + } + }) + + classes = map + } +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/NewIrUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/NewIrUtils.kt new file mode 100644 index 00000000000..5f7782cb545 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/NewIrUtils.kt @@ -0,0 +1,128 @@ +/* + * 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.lower.inline + +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression +import org.jetbrains.kotlin.ir.expressions.getTypeArgumentOrDefault +import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.resolve.constants.* +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.types.ErrorUtils +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils + +// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt +fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTable) { + val moduleDescriptor = this.descriptor + + fun KotlinType.referenceAllClassifiers() { + TypeUtils.getClassDescriptor(this)?.let { + if (!ErrorUtils.isError(it) && it.module != moduleDescriptor) { + if (it.kind == ClassKind.ENUM_ENTRY) { + symbolTable.referenceEnumEntry(it) + } else { + symbolTable.referenceClass(it) + } + } + } + + this.constructor.supertypes.forEach { + it.referenceAllClassifiers() + } + } + + val visitor = object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitValueParameter(declaration: IrValueParameter) { + super.visitValueParameter(declaration) + declaration.type.referenceAllClassifiers() + } + + override fun visitVariable(declaration: IrVariable) { + super.visitVariable(declaration) + declaration.type.referenceAllClassifiers() + } + + override fun visitExpression(expression: IrExpression) { + super.visitExpression(expression) + expression.type.referenceAllClassifiers() + } + + override fun visitDeclaration(declaration: IrDeclaration) { + super.visitDeclaration(declaration) + declaration.descriptor.annotations.getAllAnnotations().forEach { + handleClassReferences(it.annotation) + } + } + + private fun handleClassReferences(annotation: AnnotationDescriptor) { + annotation.allValueArguments.values.forEach { + it.accept(object : AnnotationArgumentVisitor { + + override fun visitKClassValue(p0: KClassValue?, p1: Nothing?) { + p0?.value?.referenceAllClassifiers() + } + + override fun visitArrayValue(p0: ArrayValue?, p1: Nothing?) { + p0?.value?.forEach { it.accept(this, null) } + } + + override fun visitAnnotationValue(p0: AnnotationValue?, p1: Nothing?) { + p0?.let { handleClassReferences(p0.value) } + } + + override fun visitBooleanValue(p0: BooleanValue?, p1: Nothing?) {} + override fun visitShortValue(p0: ShortValue?, p1: Nothing?) {} + override fun visitByteValue(p0: ByteValue?, p1: Nothing?) {} + override fun visitNullValue(p0: NullValue?, p1: Nothing?) {} + override fun visitDoubleValue(p0: DoubleValue?, p1: Nothing?) {} + override fun visitLongValue(p0: LongValue, p1: Nothing?) {} + override fun visitCharValue(p0: CharValue?, p1: Nothing?) {} + override fun visitIntValue(p0: IntValue?, p1: Nothing?) {} + override fun visitErrorValue(p0: ErrorValue?, p1: Nothing?) {} + override fun visitFloatValue(p0: FloatValue?, p1: Nothing?) {} + override fun visitEnumValue(p0: EnumValue?, p1: Nothing?) {} + override fun visitStringValue(p0: StringValue?, p1: Nothing?) {} + override fun visitUByteValue(value: UByteValue?, data: Nothing?) {} + override fun visitUShortValue(value: UShortValue?, data: Nothing?) {} + override fun visitUIntValue(value: UIntValue?, data: Nothing?) {} + override fun visitULongValue(value: ULongValue?, data: Nothing?) {} + }, null) + } + } + + override fun visitFunction(declaration: IrFunction) { + super.visitFunction(declaration) + declaration.returnType.referenceAllClassifiers() + } + + override fun visitFunctionAccess(expression: IrFunctionAccessExpression) { + super.visitFunctionAccess(expression) + expression.descriptor.original.typeParameters.forEach { + expression.getTypeArgumentOrDefault(it).referenceAllClassifiers() + } + } + } + + this.acceptVoid(visitor) + this.dependencyModules.forEach { module -> + module.externalPackageFragments.forEach { + it.acceptVoid(visitor) + } + } +} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/ReturnableBlockLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/ReturnableBlockLowering.kt new file mode 100644 index 00000000000..c3305bf1053 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/ReturnableBlockLowering.kt @@ -0,0 +1,179 @@ +/* + * 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.lower.inline + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +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.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrDoWhileLoopImpl +import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid + +/** + * Replaces returnable blocks and `return`'s with loops and `break`'s correspondingly. + * + * Converts returnable blocks into regular composite blocks when the only `return` is the last statement. + * + * ``` + * block { + * ... + * return@block e + * ... + * } + * ``` + * + * is transformed into + * + * ``` + * { + * val result + * loop@ do { + * ... + * { + * result = e + * break@loop + * } + * ... + * } while (false) + * result + * } + * ``` + * + * When the only `return` for the block is the last statement: + * + * ``` + * block { + * ... + * return@block e + * } + * ``` + * + * is transformed into + * + * { + * ... + * e + * } + * + */ +class ReturnableBlockLowering(val context: JsIrBackendContext) : FileLoweringPass { + override fun lower(irFile: IrFile) { + irFile.transform(ReturnableBlockTransformer(context), ReturnableBlockLoweringContext(irFile)) + } +} + +private class ReturnableBlockLoweringContext(val containingDeclaration: IrSymbolOwner) { + var labelCnt = 0 + val returnMap = mutableMapOf IrExpression>() +} + +private class ReturnableBlockTransformer( + val context: JsIrBackendContext +) : IrElementTransformer { + + override fun visitReturn(expression: IrReturn, data: ReturnableBlockLoweringContext): IrExpression { + expression.transformChildren(this, data) + return data.returnMap[expression.returnTargetSymbol]?.invoke(expression) ?: expression + } + + override fun visitDeclaration(declaration: IrDeclaration, data: ReturnableBlockLoweringContext): IrStatement { + if (declaration is IrSymbolOwner) { + declaration.transformChildren(this, ReturnableBlockLoweringContext(declaration)) + } + return super.visitDeclaration(declaration, data) + } + + private val constFalse = JsIrBuilder.buildBoolean(context.builtIns.booleanType, false) + + override fun visitContainerExpression(expression: IrContainerExpression, data: ReturnableBlockLoweringContext): IrExpression { + 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 + ) + } + + val loop by lazy { + IrDoWhileLoopImpl( + expression.startOffset, + expression.endOffset, + context.builtIns.unitType, + expression.origin + ).apply { + label = "l\$ret\$${data.labelCnt++}" + condition = constFalse + } + } + + var hasReturned = false + + data.returnMap[expression.symbol] = { returnExpression -> + hasReturned = true + + IrCompositeImpl( + returnExpression.startOffset, + returnExpression.endOffset, + context.builtIns.unitType + ).apply { + statements += JsIrBuilder.buildSetVariable(variable, returnExpression.value) + statements += JsIrBuilder.buildBreak(context.builtIns.unitType, loop) + } + } + + val newStatements = expression.statements.mapIndexed { i, s -> + 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) + } + } else { + s.transform(this, data) + } + } + + data.returnMap.remove(expression.symbol) + + if (!hasReturned) { + return IrCompositeImpl( + expression.startOffset, + expression.endOffset, + expression.type, + expression.origin, + newStatements + ) + } else { + loop.body = IrBlockImpl( + expression.startOffset, + expression.endOffset, + context.builtIns.unitType, + expression.origin, + newStatements + ) + + return IrCompositeImpl( + expression.startOffset, + expression.endOffset, + expression.type, + expression.origin + ).apply { + statements += JsIrBuilder.buildVar(variable) + statements += loop + statements += JsIrBuilder.buildGetValue(variable) + } + } + } +} \ No newline at end of file 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 index 15bc3d4474e..aacccde4b88 100644 --- 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 @@ -14,6 +14,7 @@ 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 @@ -67,7 +68,7 @@ object JsSymbolBuilder { ) ) - fun buildTempVar(containingSymbol: IrFunctionSymbol, type: KotlinType, name: String? = null, mutable: Boolean = false) = + fun buildTempVar(containingSymbol: IrSymbol, type: KotlinType, name: String? = null, mutable: Boolean = false) = buildTempVar(containingSymbol.descriptor, type, name, mutable) fun buildTempVar(containingDeclaration: DeclarationDescriptor, type: KotlinType, name: String? = null, mutable: Boolean = false) = 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 7b3f0ce8fdb..af03757577c 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 @@ -77,7 +77,7 @@ class SimpleNameGenerator : NameGenerator { is ConstructorDescriptor -> { nameBuilder.append(getNameForDescriptor(descriptor.constructedClass, context)) } - is LocalVariableDescriptor -> { + is VariableDescriptor -> { nameBuilder.append(descriptor.name.identifier) nameDeclarator = context.currentScope::declareFreshName } 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 index af181cd9263..9d06c789236 100644 --- 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 @@ -9,6 +9,10 @@ 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.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol @@ -50,4 +54,8 @@ fun createValueParameter(containingDeclaration: CallableDescriptor, index: Int, varargElementType = null, source = SourceElement.NO_SOURCE ) -} \ No newline at end of file +} +val CallableMemberDescriptor.propertyIfAccessor + get() = if (this is PropertyAccessorDescriptor) + this.correspondingProperty + else this \ No newline at end of file diff --git a/compiler/testData/codegen/box/functions/invoke/implicitInvokeInCompanionObjectWithFunctionalArgument.kt b/compiler/testData/codegen/box/functions/invoke/implicitInvokeInCompanionObjectWithFunctionalArgument.kt index ba692250080..f277bae8b6e 100644 --- a/compiler/testData/codegen/box/functions/invoke/implicitInvokeInCompanionObjectWithFunctionalArgument.kt +++ b/compiler/testData/codegen/box/functions/invoke/implicitInvokeInCompanionObjectWithFunctionalArgument.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR class TestClass { companion object { inline operator fun invoke(task: () -> T) = task() diff --git a/compiler/testData/codegen/box/functions/invoke/implicitInvokeWithFunctionLiteralArgument.kt b/compiler/testData/codegen/box/functions/invoke/implicitInvokeWithFunctionLiteralArgument.kt index d03c0e48d0e..de3ac9fbc73 100644 --- a/compiler/testData/codegen/box/functions/invoke/implicitInvokeWithFunctionLiteralArgument.kt +++ b/compiler/testData/codegen/box/functions/invoke/implicitInvokeWithFunctionLiteralArgument.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR class TestClass { inline operator fun invoke(task: () -> T) = task() } diff --git a/compiler/testData/codegen/boxInline/defaultValues/defaultMethod.kt b/compiler/testData/codegen/boxInline/defaultValues/defaultMethod.kt index df20c911e32..398f6768a0f 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/defaultMethod.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/defaultMethod.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/defaultParamRemapping.kt b/compiler/testData/codegen/boxInline/defaultValues/defaultParamRemapping.kt index 364ecce1330..948111cf500 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/defaultParamRemapping.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/defaultParamRemapping.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/inlineLambdaInNoInlineDefault.kt b/compiler/testData/codegen/boxInline/defaultValues/inlineLambdaInNoInlineDefault.kt index ee97220eac7..ddfd491cc90 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/inlineLambdaInNoInlineDefault.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/inlineLambdaInNoInlineDefault.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/kt18689_2.kt b/compiler/testData/codegen/boxInline/defaultValues/kt18689_2.kt index 07e6a5f8e9b..5ad6a07bf34 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/kt18689_2.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/kt18689_2.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/kt18689_4.kt b/compiler/testData/codegen/boxInline/defaultValues/kt18689_4.kt index 23c19b4b11d..231cbf0020f 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/kt18689_4.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/kt18689_4.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/kt5685.kt b/compiler/testData/codegen/boxInline/defaultValues/kt5685.kt index 287dd42f56b..4d74b2c26e1 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/kt5685.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/kt5685.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReference.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReference.kt index 978c91da9d1..70154e97dfe 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReference.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundFunctionReference.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReference.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReference.kt index 549665b5ade..83bb3f0b7c9 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReference.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReference.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnInt.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnInt.kt index 3ebf18272cb..18acbd44ecd 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnInt.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/boundPropertyReferenceOnInt.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/constuctorReference.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/constuctorReference.kt index 9bb145444dc..b953e910015 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/constuctorReference.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/constuctorReference.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionImportedFromObject.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionImportedFromObject.kt index 9cda1d7926f..98b9e147958 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionImportedFromObject.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionImportedFromObject.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReference.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReference.kt index 97ededaada2..ae652db6fc2 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReference.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReference.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReferenceFromClass.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReferenceFromClass.kt index 56f529dd6fe..b979f06a998 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReferenceFromClass.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReferenceFromClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReferenceFromObject.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReferenceFromObject.kt index 00043e3c3ad..cd1d2d67bd9 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReferenceFromObject.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/functionReferenceFromObject.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/privateFunctionReference.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/privateFunctionReference.kt index f51bccdb6a5..9daf1aa9f06 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/privateFunctionReference.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/privateFunctionReference.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/privatePropertyReference.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/privatePropertyReference.kt index 636cc3e202c..4514cfd5a70 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/privatePropertyReference.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/privatePropertyReference.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyImportedFromObject.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyImportedFromObject.kt index e93e6773fca..c09d36b5d90 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyImportedFromObject.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyImportedFromObject.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReference.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReference.kt index 6fe30d6ee07..aaa25f84e3c 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReference.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReference.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReferenceFromClass.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReferenceFromClass.kt index db1e0b0b989..ba9f84bcb56 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReferenceFromClass.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReferenceFromClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReferenceFromObject.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReferenceFromObject.kt index 585d0daafe2..e569fdf7d8b 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReferenceFromObject.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/callableReferences/propertyReferenceFromObject.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/checkLambdaClassIsPresent.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/checkLambdaClassIsPresent.kt index d6a7132367f..fea6c9e2ce6 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/checkLambdaClassIsPresent.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/checkLambdaClassIsPresent.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // NO_CHECK_LAMBDA_INLINING // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/defaultCallInDefaultLambda.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/defaultCallInDefaultLambda.kt index d0e1dae15be..42ce6e1de9d 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/defaultCallInDefaultLambda.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/defaultCallInDefaultLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // SKIP_INLINE_CHECK_IN: bar$default package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/defaultLambdaInNoInline.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/defaultLambdaInNoInline.kt index f5ac4ee7268..5ffab7914d9 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/defaultLambdaInNoInline.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/defaultLambdaInNoInline.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/genericLambda.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/genericLambda.kt index 514286b9096..9886812a50b 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/genericLambda.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/genericLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // NO_CHECK_LAMBDA_INLINING // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt index f997e3a8cef..080ee06cd0e 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInInterface.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInInterface.kt index 941cd930b03..05608dbb358 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInInterface.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInInterface.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/noInline.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/noInline.kt index ff49703cdbe..2f9c2618cc3 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/noInline.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/noInline.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/nonDefaultInlineInNoInline.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/nonDefaultInlineInNoInline.kt index db1104d05b0..abe5059b0e8 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/nonDefaultInlineInNoInline.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/nonDefaultInlineInNoInline.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/receiverClash.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/receiverClash.kt index 6e0d47f029d..f5367e6f018 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/receiverClash.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/receiverClash.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/receiverClash2.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/receiverClash2.kt index 75ee6124538..7a8f71ffc8b 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/receiverClash2.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/receiverClash2.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt index 36d62d96b20..e032606205d 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleExtension.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleExtension.kt index 43a29e636ad..29c9f3dac2d 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleExtension.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleExtension.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleGeneric.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleGeneric.kt index dc89504a061..3a91a6322ec 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleGeneric.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleGeneric.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleStaticInstance.kt b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleStaticInstance.kt index 19bd8932985..fb8a67b97ac 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleStaticInstance.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simpleStaticInstance.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt // LANGUAGE_VERSION: 1.2 // SKIP_INLINE_CHECK_IN: inlineFun$default diff --git a/compiler/testData/codegen/boxInline/defaultValues/maskElimination/32Parameters.kt b/compiler/testData/codegen/boxInline/defaultValues/maskElimination/32Parameters.kt index f86fad9ed47..5ec5e8be2a5 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/maskElimination/32Parameters.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/maskElimination/32Parameters.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/maskElimination/33Parameters.kt b/compiler/testData/codegen/boxInline/defaultValues/maskElimination/33Parameters.kt index 62c3077e19d..70b89a7c6d2 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/maskElimination/33Parameters.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/maskElimination/33Parameters.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/maskElimination/simple.kt b/compiler/testData/codegen/boxInline/defaultValues/maskElimination/simple.kt index f48cc41b29b..bca4b1fd4a8 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/maskElimination/simple.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/maskElimination/simple.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/defaultValues/simpleDefaultMethod.kt b/compiler/testData/codegen/boxInline/defaultValues/simpleDefaultMethod.kt index a6247d2f4ae..6e401f286af 100644 --- a/compiler/testData/codegen/boxInline/defaultValues/simpleDefaultMethod.kt +++ b/compiler/testData/codegen/boxInline/defaultValues/simpleDefaultMethod.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChain.kt b/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChain.kt index 541efe7cbf3..f4e50a39909 100644 --- a/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChain.kt +++ b/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChain.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChainWithCapturedInline.kt b/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChainWithCapturedInline.kt index 97254e08ff8..d68050e918d 100644 --- a/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChainWithCapturedInline.kt +++ b/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChainWithCapturedInline.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test @@ -80,4 +81,5 @@ fun box(): String { else "OK" } () + return "OK" } diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/bracket.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/bracket.kt index 344edc2e03c..8d3805a819a 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/bracket.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/bracket.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/labeled.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/labeled.kt index 77b6850445c..34b99e73279 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/labeled.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/deparenthesize/labeled.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt index 77b6850445c..34b99e73279 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt index 956fddd4247..200ee54cf38 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/kt5199.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/kt5199.kt index e88356f1325..d7e1c7edc17 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/kt5199.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/kt5199.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt index 1cab7108718..275024ae34f 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/returnFromFunctionExpr.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/returnFromFunctionExpr.kt index 5127fa3ec18..d653a70cc5a 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/returnFromFunctionExpr.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/returnFromFunctionExpr.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt inline fun foo(f: () -> Unit) { diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/simple.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/simple.kt index bb3b7317de5..efe029b8d69 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/simple.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/simple.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/simpleFunctional.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/simpleFunctional.kt index 5b7b1217c75..4790c794384 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/simpleFunctional.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/simpleFunctional.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/simpleVoid.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/simpleVoid.kt index dff1924b85c..8cebf05330e 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/simpleVoid.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/simpleVoid.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // FILE: 1.kt package test diff --git a/js/js.translator/testData/box/inline/inlineDefaultArgument.kt b/js/js.translator/testData/box/inline/inlineDefaultArgument.kt index 13b5890c775..471dc11d8e3 100644 --- a/js/js.translator/testData/box/inline/inlineDefaultArgument.kt +++ b/js/js.translator/testData/box/inline/inlineDefaultArgument.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1114 package foo diff --git a/js/js.translator/testData/box/inline/localInlineFunctionNameClash.kt b/js/js.translator/testData/box/inline/localInlineFunctionNameClash.kt index 64ff35f6942..dcf4acba28a 100644 --- a/js/js.translator/testData/box/inline/localInlineFunctionNameClash.kt +++ b/js/js.translator/testData/box/inline/localInlineFunctionNameClash.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1114 package foo diff --git a/js/js.translator/testData/box/inlineEvaluationOrder/capturedVarAsArgument.kt b/js/js.translator/testData/box/inlineEvaluationOrder/capturedVarAsArgument.kt index 65417543eb9..708f6bce504 100644 --- a/js/js.translator/testData/box/inlineEvaluationOrder/capturedVarAsArgument.kt +++ b/js/js.translator/testData/box/inlineEvaluationOrder/capturedVarAsArgument.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1110 var log = "" diff --git a/js/js.translator/testData/box/inlineMultiFile/defaultMethod.kt b/js/js.translator/testData/box/inlineMultiFile/defaultMethod.kt index b97cdb6988c..c9a1ce1e8d6 100644 --- a/js/js.translator/testData/box/inlineMultiFile/defaultMethod.kt +++ b/js/js.translator/testData/box/inlineMultiFile/defaultMethod.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1110 /* * Copy of JVM-backend test diff --git a/js/js.translator/testData/box/inlineMultiFile/lambdaInLambdaNoInline.kt b/js/js.translator/testData/box/inlineMultiFile/lambdaInLambdaNoInline.kt index a82d62c51a0..e712a359af9 100644 --- a/js/js.translator/testData/box/inlineMultiFile/lambdaInLambdaNoInline.kt +++ b/js/js.translator/testData/box/inlineMultiFile/lambdaInLambdaNoInline.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1124 /* * Copy of JVM-backend test diff --git a/js/js.translator/testData/box/inlineMultiFile/sameCaptured.kt b/js/js.translator/testData/box/inlineMultiFile/sameCaptured.kt index ce0c0a8cfdd..691fd85eea9 100644 --- a/js/js.translator/testData/box/inlineMultiFile/sameCaptured.kt +++ b/js/js.translator/testData/box/inlineMultiFile/sameCaptured.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1117 /* * Copy of JVM-backend test diff --git a/js/js.translator/testData/box/inlineMultiFile/simpleDefaultMethod.kt b/js/js.translator/testData/box/inlineMultiFile/simpleDefaultMethod.kt index e9f2c359000..6f9ee83bb03 100644 --- a/js/js.translator/testData/box/inlineMultiFile/simpleDefaultMethod.kt +++ b/js/js.translator/testData/box/inlineMultiFile/simpleDefaultMethod.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1110 /* * Copy of JVM-backend test diff --git a/js/js.translator/testData/box/labels/nestedInlineLabels.kt b/js/js.translator/testData/box/labels/nestedInlineLabels.kt index 3f790063721..88f3d6d1f5c 100644 --- a/js/js.translator/testData/box/labels/nestedInlineLabels.kt +++ b/js/js.translator/testData/box/labels/nestedInlineLabels.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1117 package foo