From 8296c65aebedef1f95d068c93ad535c162777f85 Mon Sep 17 00:00:00 2001 From: Vasily Levchenko Date: Wed, 9 Aug 2017 19:10:30 +0300 Subject: [PATCH] Migrate native to moved common lowers (cherry picked from commit 6665d48017540afd8b8cb2fa0f104cab93e73473) --- .../backend/common/CheckIrElementVisitor.kt | 253 ------ .../backend/common/CommonBackendContext.kt | 107 --- .../common/DeepCopyIrTreeWithDeclarations.kt | 54 -- .../common/DeepCopyIrTreeWithDescriptoros.kt | 621 --------------- .../DumpIrTreeWithDescriptorsVisitor.kt | 366 --------- .../jetbrains/kotlin/backend/common/IrCopy.kt | 66 -- .../IrElementTransformerVoidWithContext.kt | 166 ---- .../kotlin/backend/common/IrValidator.kt | 72 -- .../common/TailRecursionCallsCollector.kt | 160 ---- .../jetbrains/kotlin/backend/common/Utils.kt | 48 -- .../common/descriptors/DescriptorUtils.kt | 94 --- .../jetbrains/kotlin/backend/common/ir/Ir.kt | 208 ----- .../kotlin/backend/common/ir/IrUtils.kt | 140 ---- .../common/lower/AbstractClosureAnnotator.kt | 189 ----- .../lower/DefaultArgumentStubGenerator.kt | 460 ----------- .../backend/common/lower/IrBuildUtils.kt | 216 ------ .../backend/common/lower/LateinitLowering.kt | 72 -- .../common/lower/LocalDeclarationsLowering.kt | 729 ------------------ .../kotlin/backend/common/lower/LowerUtils.kt | 239 ------ .../lower/StringConcatenationLowering.kt | 123 --- .../backend/common/lower/TailrecLowering.kt | 163 ---- .../backend/common/lower/VarargLowering.kt | 262 ------- .../kotlin/backend/konan/EscapeAnalysis.kt | 1 - .../kotlin/backend/konan/ir/KonanIr.kt | 64 +- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 1 + .../konan/lower/FinallyBlocksLowering.kt | 5 +- .../backend/konan/lower/FunctionInlining.kt | 2 +- .../kotlin/ir/builders/IrBuilders.kt | 58 -- .../kotlin/ir/util/IrUnboundSymbolReplacer.kt | 1 - .../org/jetbrains/kotlin/ir/util/IrUtils.kt | 241 ------ .../org/jetbrains/kotlin/ir/util/IrUtils2.kt | 25 + 31 files changed, 30 insertions(+), 5176 deletions(-) delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DumpIrTreeWithDescriptorsVisitor.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrCopy.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/TailRecursionCallsCollector.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/Utils.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorUtils.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/IrBuildUtils.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/VarargLowering.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt deleted file mode 100644 index a7029a86c45..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common - -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.makeNullable - -typealias ReportError = (element: IrElement, message: String) -> Unit - -class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: ReportError, val ensureAllNodesAreDifferent: Boolean) : IrElementVisitorVoid { - - val set = mutableSetOf() - - override fun visitElement(element: IrElement) { - if (ensureAllNodesAreDifferent) { - if (set.contains(element)) - reportError(element, "Duplicate IR node") - set.add(element) - } - // Nothing to do. - } - - private fun IrExpression.ensureTypeIs(expectedType: KotlinType) { - if (expectedType != type) { - reportError(this, "unexpected expression.type: expected $expectedType, got ${type}") - } - } - - private fun IrSymbol.ensureBound(expression: IrExpression) { - if (!this.isBound) { - reportError(expression, "Unbound symbol ${this}") - } - } - - override fun visitConst(expression: IrConst) { - super.visitConst(expression) - - val naturalType = when (expression.kind) { - IrConstKind.Null -> builtIns.nullableNothingType - IrConstKind.Boolean -> builtIns.booleanType - IrConstKind.Char -> builtIns.charType - IrConstKind.Byte -> builtIns.byteType - IrConstKind.Short -> builtIns.shortType - IrConstKind.Int -> builtIns.intType - IrConstKind.Long -> builtIns.longType - IrConstKind.String -> builtIns.stringType - IrConstKind.Float -> builtIns.floatType - IrConstKind.Double -> builtIns.doubleType - } - - expression.ensureTypeIs(naturalType) - } - - override fun visitStringConcatenation(expression: IrStringConcatenation) { - super.visitStringConcatenation(expression) - - expression.ensureTypeIs(builtIns.stringType) - } - - override fun visitGetObjectValue(expression: IrGetObjectValue) { - super.visitGetObjectValue(expression) - - expression.ensureTypeIs(expression.descriptor.defaultType) - } - - // TODO: visitGetEnumValue - - override fun visitGetValue(expression: IrGetValue) { - super.visitGetValue(expression) - - expression.ensureTypeIs(expression.descriptor.type) - } - - override fun visitSetVariable(expression: IrSetVariable) { - super.visitSetVariable(expression) - - expression.ensureTypeIs(builtIns.unitType) - } - - override fun visitGetField(expression: IrGetField) { - super.visitGetField(expression) - - expression.ensureTypeIs(expression.descriptor.type) - } - - override fun visitSetField(expression: IrSetField) { - super.visitSetField(expression) - - expression.ensureTypeIs(builtIns.unitType) - } - - override fun visitCall(expression: IrCall) { - super.visitCall(expression) - - val returnType = expression.descriptor.returnType - if (returnType == null) { - reportError(expression, "${expression.descriptor} return type is null") - } else { - expression.ensureTypeIs(returnType) - } - - expression.superQualifierSymbol?.ensureBound(expression) - } - - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) { - super.visitDelegatingConstructorCall(expression) - - expression.ensureTypeIs(builtIns.unitType) - } - - override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) { - super.visitEnumConstructorCall(expression) - - expression.ensureTypeIs(builtIns.unitType) - } - - override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) { - super.visitInstanceInitializerCall(expression) - - expression.ensureTypeIs(builtIns.unitType) - expression.classSymbol.ensureBound(expression) - } - - override fun visitTypeOperator(expression: IrTypeOperatorCall) { - super.visitTypeOperator(expression) - - val operator = expression.operator - val typeOperand = expression.typeOperand - - val naturalType = when (operator) { - IrTypeOperator.CAST, - IrTypeOperator.IMPLICIT_CAST, - IrTypeOperator.IMPLICIT_NOTNULL, - IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, - IrTypeOperator.IMPLICIT_INTEGER_COERCION -> typeOperand - - IrTypeOperator.SAFE_CAST -> typeOperand.makeNullable() - - IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF -> builtIns.booleanType - } - - if (operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT && typeOperand != builtIns.unitType) { - reportError(expression, "typeOperand is $typeOperand") - } - - // TODO: check IMPLICIT_NOTNULL's argument type. - - expression.ensureTypeIs(naturalType) - } - - override fun visitLoop(loop: IrLoop) { - super.visitLoop(loop) - - loop.ensureTypeIs(builtIns.unitType) - } - - override fun visitBreakContinue(jump: IrBreakContinue) { - super.visitBreakContinue(jump) - - jump.ensureTypeIs(builtIns.nothingType) - } - - override fun visitReturn(expression: IrReturn) { - super.visitReturn(expression) - - expression.ensureTypeIs(builtIns.nothingType) - expression.returnTargetSymbol.ensureBound(expression) - } - - override fun visitThrow(expression: IrThrow) { - super.visitThrow(expression) - - expression.ensureTypeIs(builtIns.nothingType) - } - - override fun visitClass(declaration: IrClass) { - super.visitClass(declaration) - - if (declaration.descriptor.kind != ClassKind.ANNOTATION_CLASS) { - // Check that all functions and properties from memberScope are present in IR - // (including FAKE_OVERRIDE ones). - - val allDescriptors = declaration.descriptor.unsubstitutedMemberScope - .getContributedDescriptors().filterIsInstance() - - val presentDescriptors = declaration.declarations.map { it.descriptor } - - val missingDescriptors = allDescriptors - presentDescriptors - - if (missingDescriptors.isNotEmpty()) { - reportError(declaration, "Missing declarations for descriptors:\n" + - missingDescriptors.joinToString("\n")) - } - } - } - - override fun visitDeclarationReference(expression: IrDeclarationReference) { - super.visitDeclarationReference(expression) - - expression.symbol.ensureBound(expression) - } - - override fun visitFunctionAccess(expression: IrFunctionAccessExpression) { - super.visitFunctionAccess(expression) - - expression.symbol.ensureBound(expression) - } - - override fun visitFunctionReference(expression: IrFunctionReference) { - super.visitFunctionReference(expression) - - expression.symbol.ensureBound(expression) - } - - override fun visitPropertyReference(expression: IrPropertyReference) { - super.visitPropertyReference(expression) - - expression.field?.ensureBound(expression) - expression.getter?.ensureBound(expression) - expression.setter?.ensureBound(expression) - } - - override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference) { - super.visitLocalDelegatedPropertyReference(expression) - - expression.delegate.ensureBound(expression) - expression.getter.ensureBound(expression) - expression.setter?.ensureBound(expression) - } - -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt deleted file mode 100644 index 6a65cce7003..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt +++ /dev/null @@ -1,107 +0,0 @@ -package org.jetbrains.kotlin.backend.common - -import org.jetbrains.kotlin.backend.common.ir.Ir -import org.jetbrains.kotlin.builtins.KOTLIN_REFLECT_FQ_NAME -import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.KotlinTypeFactory -import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.types.typeUtil.asTypeProjection -import org.jetbrains.kotlin.utils.addIfNotNull -import java.util.* -import kotlin.reflect.KProperty - - -interface CommonBackendContext : BackendContext { - - val ir: Ir - - //TODO move to builtins - fun getInternalClass(name: String): ClassDescriptor - - //TODO move to builtins - fun getInternalFunctions(name: String): List - - val reflectionTypes: ReflectionTypes - - fun log(message: () -> String) - - val messageCollector: MessageCollector -} - -class ReflectionTypes(module: ModuleDescriptor, internalPackage: FqName) { - - private val kotlinReflectScope: MemberScope by lazy(LazyThreadSafetyMode.PUBLICATION) { - module.getPackage(KOTLIN_REFLECT_FQ_NAME).memberScope - } - - private val internalScope: MemberScope by lazy(LazyThreadSafetyMode.PUBLICATION) { - module.getPackage(internalPackage).memberScope - } - - private fun find(memberScope: MemberScope, className: String): ClassDescriptor { - val name = Name.identifier(className) - return memberScope.getContributedClassifier(name, NoLookupLocation.FROM_REFLECTION) as ClassDescriptor - } - - private class ClassLookup(val memberScope: MemberScope) { - operator fun getValue(types: ReflectionTypes, property: KProperty<*>): ClassDescriptor { - return types.find(memberScope, property.name.capitalize()) - } - } - - private fun getFunctionTypeArgumentProjections( - receiverType: KotlinType?, - parameterTypes: List, - returnType: KotlinType - ): List { - val arguments = ArrayList(parameterTypes.size + (if (receiverType != null) 1 else 0) + 1) - - arguments.addIfNotNull(receiverType?.asTypeProjection()) - - parameterTypes.mapTo(arguments, KotlinType::asTypeProjection) - - arguments.add(returnType.asTypeProjection()) - - return arguments - } - - fun getKFunction(n: Int): ClassDescriptor = find(kotlinReflectScope, "KFunction$n") - - val kClass: ClassDescriptor by ClassLookup(kotlinReflectScope) - val kProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope) - val kProperty1: ClassDescriptor by ClassLookup(kotlinReflectScope) - val kProperty2: ClassDescriptor by ClassLookup(kotlinReflectScope) - val kMutableProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope) - val kMutableProperty1: ClassDescriptor by ClassLookup(kotlinReflectScope) - val kMutableProperty2: ClassDescriptor by ClassLookup(kotlinReflectScope) - val kFunctionImpl: ClassDescriptor by ClassLookup(internalScope) - val kProperty0Impl: ClassDescriptor by ClassLookup(internalScope) - val kProperty1Impl: ClassDescriptor by ClassLookup(internalScope) - val kProperty2Impl: ClassDescriptor by ClassLookup(internalScope) - val kMutableProperty0Impl: ClassDescriptor by ClassLookup(internalScope) - val kMutableProperty1Impl: ClassDescriptor by ClassLookup(internalScope) - val kMutableProperty2Impl: ClassDescriptor by ClassLookup(internalScope) - val kLocalDelegatedPropertyImpl: ClassDescriptor by ClassLookup(internalScope) - val kLocalDelegatedMutablePropertyImpl: ClassDescriptor by ClassLookup(internalScope) - - fun getKFunctionType( - annotations: Annotations, - receiverType: KotlinType?, - parameterTypes: List, - returnType: KotlinType - ): KotlinType { - val arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType) - val classDescriptor = getKFunction(arguments.size - 1 /* return type */) - return KotlinTypeFactory.simpleNotNullType(annotations, classDescriptor, arguments) - } -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt deleted file mode 100644 index c7f69b754e4..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common - -import org.jetbrains.kotlin.descriptors.VariableDescriptor -import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.expressions.IrLoop -import org.jetbrains.kotlin.ir.util.DeepCopySymbolsRemapper -import org.jetbrains.kotlin.ir.util.DescriptorsRemapper -import org.jetbrains.kotlin.ir.visitors.acceptVoid - -fun IrElement.deepCopyWithVariablesImpl(): IrElement { - val descriptorsRemapper = object : DescriptorsRemapper { - override fun remapDeclaredVariable(descriptor: VariableDescriptor) = LocalVariableDescriptor( - /* containingDeclaration = */ descriptor.containingDeclaration, - /* annotations = */ descriptor.annotations, - /* name = */ descriptor.name, - /* type = */ descriptor.type, - /* mutable = */ descriptor.isVar, - /* isDelegated = */ false, - /* source = */ descriptor.source - ) - } - - val symbolsRemapper = DeepCopySymbolsRemapper(descriptorsRemapper) - acceptVoid(symbolsRemapper) - - return this.transform( - object : DeepCopyIrTreeWithReturnableBlockSymbols(symbolsRemapper) { - override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop { - return irLoop - } - }, - null - ) -} - -inline fun T.deepCopyWithVariables(): T = - this.deepCopyWithVariablesImpl() as T \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt deleted file mode 100644 index fa79e474cc6..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDescriptoros.kt +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common - -import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope -import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.impl.* -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.util.DeepCopyIrTree -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeSubstitutor -import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.types.typeUtil.makeNullable - -internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor, - val context: Context) { - - private val descriptorSubstituteMap: MutableMap = mutableMapOf() - private var typeSubstitutor: TypeSubstitutor? = null - private var nameIndex = 0 - - //-------------------------------------------------------------------------// - - fun copy(irElement: IrElement, typeSubstitutor: TypeSubstitutor?): IrElement { - this.typeSubstitutor = typeSubstitutor - irElement.acceptChildrenVoid(DescriptorCollector()) - return irElement.accept(InlineCopyIr(), null) - } - - //-------------------------------------------------------------------------// - - inner class DescriptorCollector: IrElementVisitorVoid { - - override fun visitElement(element: IrElement) { - element.acceptChildren(this, null) - } - - //---------------------------------------------------------------------// - - override fun visitClass(declaration: IrClass) { - - val oldDescriptor = declaration.descriptor - val newDescriptor = copyClassDescriptor(oldDescriptor) - descriptorSubstituteMap[oldDescriptor] = newDescriptor - descriptorSubstituteMap[oldDescriptor.thisAsReceiverParameter] = newDescriptor.thisAsReceiverParameter - - super.visitClass(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 visitProperty(declaration: IrProperty) { - - copyPropertyOrField(declaration.descriptor) - super.visitProperty(declaration) - } - - //---------------------------------------------------------------------// - - override fun visitField(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.visitField(declaration) - } - - //---------------------------------------------------------------------// - - override fun visitFunction(declaration: IrFunction) { - - val oldDescriptor = declaration.descriptor - if (oldDescriptor !is PropertyAccessorDescriptor) { // Property accessors are copied along with their property. - val newDescriptor = copyFunctionDescriptor(oldDescriptor) - descriptorSubstituteMap[oldDescriptor] = newDescriptor - oldDescriptor.extensionReceiverParameter?.let{ - descriptorSubstituteMap[it] = newDescriptor.extensionReceiverParameter!! - } - } - super.visitFunction(declaration) - } - - //---------------------------------------------------------------------// - - override fun visitVariable(declaration: IrVariable) { - - val oldDescriptor = declaration.descriptor - val oldContainingDeclaration = oldDescriptor.containingDeclaration - val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) - val newDescriptor = IrTemporaryVariableDescriptorImpl( - containingDeclaration = newContainingDeclaration, - name = generateCopyName(oldDescriptor.name), - outType = substituteType(oldDescriptor.type)!!, - isMutable = oldDescriptor.isVar) - descriptorSubstituteMap[oldDescriptor] = newDescriptor - - super.visitVariable(declaration) - } - - //---------------------------------------------------------------------// - - override fun visitCatch(aCatch: IrCatch) { - val oldDescriptor = aCatch.parameter - val oldContainingDeclaration = oldDescriptor.containingDeclaration - val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) - val newDescriptor = IrTemporaryVariableDescriptorImpl( - containingDeclaration = newContainingDeclaration, - name = generateCopyName(oldDescriptor.name), - outType = substituteType(oldDescriptor.type)!!, - isMutable = oldDescriptor.isVar) - descriptorSubstituteMap[oldDescriptor] = newDescriptor - - 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 copyFunctionDescriptor(oldDescriptor: CallableDescriptor): CallableDescriptor { - - return when (oldDescriptor) { - is ConstructorDescriptor -> copyConstructorDescriptor(oldDescriptor) - is SimpleFunctionDescriptor -> copySimpleFunctionDescriptor(oldDescriptor) - else -> TODO("Unsupported FunctionDescriptor subtype: $oldDescriptor") - } - } - - //---------------------------------------------------------------------// - - private fun copySimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor) : FunctionDescriptor { - - val oldContainingDeclaration = oldDescriptor.containingDeclaration - val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) - return SimpleFunctionDescriptorImpl.create( - /* containingDeclaration = */ newContainingDeclaration, - /* annotations = */ oldDescriptor.annotations, - /* name = */ generateCopyName(oldDescriptor.name), - /* kind = */ oldDescriptor.kind, - /* source = */ oldDescriptor.source - ).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 = substituteType(oldDescriptor.extensionReceiverParameter?.type) - val newReturnType = substituteType(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 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 - ).apply { - - val newTypeParameters = oldDescriptor.typeParameters - val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, this) - val receiverParameterType = substituteType(oldDescriptor.dispatchReceiverParameter?.type) - val returnType = substituteType(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 copyPropertyOrField(oldDescriptor: PropertyDescriptor) { - - val newDescriptor = copyPropertyDescriptor(oldDescriptor) - descriptorSubstituteMap[oldDescriptor] = newDescriptor - oldDescriptor.getter?.let { - descriptorSubstituteMap[it] = newDescriptor.getter!! - } - oldDescriptor.setter?.let { - descriptorSubstituteMap[it] = newDescriptor.setter!! - } - oldDescriptor.extensionReceiverParameter?.let{ - descriptorSubstituteMap[it] = newDescriptor.extensionReceiverParameter!! - } - - } - - //---------------------------------------------------------------------// - - private fun copyPropertyDescriptor(oldDescriptor: PropertyDescriptor): PropertyDescriptor { - - val oldContainingDeclaration = oldDescriptor.containingDeclaration - val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) as ClassDescriptor - return 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, - /* isHeader = */ oldDescriptor.isHeader, - /* isImpl = */ oldDescriptor.isImpl, - /* isExternal = */ oldDescriptor.isExternal, - /* isDelegated = */ oldDescriptor.isDelegated - ).apply { - - setType( - /* outType = */ oldDescriptor.type, - /* typeParameters = */ oldDescriptor.typeParameters, - /* dispatchReceiverParameter = */ newContainingDeclaration.thisAsReceiverParameter, - /* receiverType = */ oldDescriptor.extensionReceiverParameter?.type) - - initialize( - /* getter = */ oldDescriptor.getter?.let { copyPropertyGetterDescriptor(it, this) }, - /* setter = */ oldDescriptor.setter?.let { copyPropertySetterDescriptor(it, this) }) - - overriddenDescriptors += oldDescriptor.overriddenDescriptors - } - } - - //---------------------------------------------------------------------// - - private fun copyPropertyGetterDescriptor(oldDescriptor: PropertyGetterDescriptor, newPropertyDescriptor: PropertyDescriptor) - : PropertyGetterDescriptorImpl { - - return 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(oldDescriptor.returnType) - } - } - - //---------------------------------------------------------------------// - - private fun copyPropertySetterDescriptor(oldDescriptor: PropertySetterDescriptor, newPropertyDescriptor: PropertyDescriptor) - : PropertySetterDescriptorImpl { - - return 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 copyClassDescriptor(oldDescriptor: ClassDescriptor): ClassDescriptorImpl { - - val oldSuperClass = oldDescriptor.getSuperClassOrAny() - val newSuperClass = descriptorSubstituteMap.getOrDefault(oldSuperClass, oldSuperClass) 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) - return ClassDescriptorImpl( - /* containingDeclaration = */ newContainingDeclaration, - /* name = */ newName, - /* modality = */ oldDescriptor.modality, - /* kind = */ oldDescriptor.kind, - /* supertypes = */ listOf(newSuperClass.defaultType), - /* source = */ oldDescriptor.source, - /* isExternal = */ oldDescriptor.isExternal - ) - } - } - -//-----------------------------------------------------------------------------// - - 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!!, - calleeDescriptor = newDescriptor, - typeArguments = substituteTypeArguments(expression.transformTypeArguments(newDescriptor)), - origin = expression.origin, - superQualifierDescriptor = mapSuperQualifier(expression.superQualifier) - ).transformValueArguments(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) - ).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 getNonTransformedLoop(irLoop: IrLoop): IrLoop { - return irLoop - } - } - - //-------------------------------------------------------------------------// - - private fun copyValueParameters(oldValueParameters: List , containingDeclaration: CallableDescriptor): List { - - return oldValueParameters.map { oldDescriptor -> - val newDescriptor = ValueParameterDescriptorImpl( - containingDeclaration = containingDeclaration, - original = oldDescriptor.original, - index = oldDescriptor.index, - annotations = oldDescriptor.annotations, - name = oldDescriptor.name, - outType = substituteType(oldDescriptor.type)!!, - declaresDefaultValue = oldDescriptor.declaresDefaultValue(), - isCrossinline = oldDescriptor.isCrossinline, - isNoinline = oldDescriptor.isNoinline, - varargElementType = substituteType(oldDescriptor.varargElementType), - source = oldDescriptor.source - ) - descriptorSubstituteMap[oldDescriptor] = newDescriptor - newDescriptor - } - } - - //-------------------------------------------------------------------------// - - 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 substituteTypeArguments(oldTypeArguments: Map ?): Map ? { - - if (oldTypeArguments == null) return null - if (typeSubstitutor == null) return oldTypeArguments - - val newTypeArguments = oldTypeArguments.entries.associate { - val typeParameterDescriptor = it.key - val oldTypeArgument = it.value - val newTypeArgument = substituteType(oldTypeArgument)!! - typeParameterDescriptor to newTypeArgument - } - return newTypeArguments - } - - //-------------------------------------------------------------------------// - - fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap) { - descriptorSubstituteMap.forEach { t, u -> - globalSubstituteMap.put(t, SubstitutedDescriptor(targetDescriptor, u)) - } - } - -} - -internal class SubstitutedDescriptor(val inlinedFunction: FunctionDescriptor, val descriptor: DeclarationDescriptor) - -internal class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap) - : IrElementTransformerVoidWithContext() { - - 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 - } - } - - //-------------------------------------------------------------------------// - - private fun copyIrCallImpl(oldExpression: IrCallImpl, substitutedDescriptor: SubstitutedDescriptor): IrCallImpl { - - val oldDescriptor = oldExpression.descriptor - val newDescriptor = substitutedDescriptor.descriptor as FunctionDescriptor - - if (newDescriptor == oldDescriptor) - return oldExpression - - val newExpression = IrCallImpl( - startOffset = oldExpression.startOffset, - endOffset = oldExpression.endOffset, - type = oldExpression.type, - calleeDescriptor = newDescriptor, - typeArguments = oldExpression.typeArguments, - origin = oldExpression.origin, - superQualifierDescriptor = oldExpression.superQualifier - ).apply { - oldExpression.descriptor.valueParameters.forEach { - val valueArgument = oldExpression.getValueArgument(it) - putValueArgument(it.index, valueArgument) - } - extensionReceiver = oldExpression.extensionReceiver - dispatchReceiver = oldExpression.dispatchReceiver - } - - return newExpression - } - - //-------------------------------------------------------------------------// - - 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, newDescriptor, oldExpression.superQualifier) - } -} - diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DumpIrTreeWithDescriptorsVisitor.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DumpIrTreeWithDescriptorsVisitor.kt deleted file mode 100644 index f77db618789..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DumpIrTreeWithDescriptorsVisitor.kt +++ /dev/null @@ -1,366 +0,0 @@ -package org.jetbrains.kotlin.backend.common - -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -import org.jetbrains.kotlin.renderer.* -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.utils.Printer - -class RenderIrElementWithDescriptorsVisitor : IrElementVisitor { - override fun visitElement(element: IrElement, data: Nothing?): String = - "? ${element.javaClass.simpleName}" - - override fun visitDeclaration(declaration: IrDeclaration, data: Nothing?): String = - "? ${declaration.javaClass.simpleName} ${declaration.descriptor.ref()}" - - override fun visitModuleFragment(declaration: IrModuleFragment, data: Nothing?): String = - "MODULE_FRAGMENT ${declaration.descriptor}" - - override fun visitFile(declaration: IrFile, data: Nothing?): String = - "FILE ${declaration.name}" - - override fun visitFunction(declaration: IrFunction, data: Nothing?): String = - "FUN ${declaration.descriptor}" - - override fun visitConstructor(declaration: IrConstructor, data: Nothing?): String = - "CONSTRUCTOR ${declaration.descriptor}" - - override fun visitProperty(declaration: IrProperty, data: Nothing?): String = - "PROPERTY ${declaration.descriptor}" - - override fun visitField(declaration: IrField, data: Nothing?): String = - "FIELD ${declaration.descriptor}" - - override fun visitClass(declaration: IrClass, data: Nothing?): String = - "CLASS ${declaration.descriptor}" - - override fun visitTypeAlias(declaration: IrTypeAlias, data: Nothing?): String = - "TYPEALIAS ${declaration.descriptor} type=${declaration.descriptor.underlyingType.render()}" - - override fun visitVariable(declaration: IrVariable, data: Nothing?): String = - "VAR ${declaration.descriptor}" - - override fun visitEnumEntry(declaration: IrEnumEntry, data: Nothing?): String = - "ENUM_ENTRY ${declaration.descriptor}" - - override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer, data: Nothing?): String = - "ANONYMOUS_INITIALIZER ${declaration.descriptor}" - - override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty, data: Nothing?): String = - "LOCAL_DELEGATED_PROPERTY ${declaration.descriptor}" - - override fun visitExpressionBody(body: IrExpressionBody, data: Nothing?): String = - "EXPRESSION_BODY" - - override fun visitBlockBody(body: IrBlockBody, data: Nothing?): String = - "BLOCK_BODY" - - override fun visitSyntheticBody(body: IrSyntheticBody, data: Nothing?): String = - "SYNTHETIC_BODY kind=${body.kind}" - - override fun visitExpression(expression: IrExpression, data: Nothing?): String = - "? ${expression.javaClass.simpleName} type=${expression.type.render()}" - - override fun visitConst(expression: IrConst, data: Nothing?): String = - "CONST ${expression.kind} type=${expression.type.render()} value='${expression.value}'" - - override fun visitVararg(expression: IrVararg, data: Nothing?): String = - "VARARG type=${expression.type} varargElementType=${expression.varargElementType}" - - override fun visitSpreadElement(spread: IrSpreadElement, data: Nothing?): String = - "SPREAD_ELEMENT" - - override fun visitBlock(expression: IrBlock, data: Nothing?): String = - "BLOCK type=${expression.type.render()} origin=${expression.origin}" - - override fun visitComposite(expression: IrComposite, data: Nothing?): String = - "COMPOSITE type=${expression.type.render()} origin=${expression.origin}" - - override fun visitReturn(expression: IrReturn, data: Nothing?): String = - "RETURN type=${expression.type.render()} from='${expression.returnTarget}'" - - override fun visitCall(expression: IrCall, data: Nothing?): String = - "CALL '${expression.descriptor}' ${expression.renderSuperQualifier()}" + - "type=${expression.type.render()} origin=${expression.origin}" - - private fun IrCall.renderSuperQualifier(): String = - superQualifier?.let { "superQualifier=${it.name} " } ?: "" - - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: Nothing?): String = - "DELEGATING_CONSTRUCTOR_CALL '${expression.descriptor}'" - - override fun visitEnumConstructorCall(expression: IrEnumConstructorCall, data: Nothing?): String = - "ENUM_CONSTRUCTOR_CALL '${expression.descriptor}'" - - override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, data: Nothing?): String = - "INSTANCE_INITIALIZER_CALL classDescriptor='${expression.classDescriptor}'" - - override fun visitGetValue(expression: IrGetValue, data: Nothing?): String = - "GET_VAR '${expression.descriptor}' type=${expression.type.render()} origin=${expression.origin}" - - override fun visitSetVariable(expression: IrSetVariable, data: Nothing?): String = - "SET_VAR '${expression.descriptor}' type=${expression.type.render()} origin=${expression.origin}" - - override fun visitGetField(expression: IrGetField, data: Nothing?): String = - "GET_FIELD '${expression.descriptor}' type=${expression.type.render()} origin=${expression.origin}" - - override fun visitSetField(expression: IrSetField, data: Nothing?): String = - "SET_FIELD '${expression.descriptor}' type=${expression.type.render()} origin=${expression.origin}" - - override fun visitGetObjectValue(expression: IrGetObjectValue, data: Nothing?): String = - "GET_OBJECT '${expression.descriptor}' type=${expression.type.render()}" - - override fun visitGetEnumValue(expression: IrGetEnumValue, data: Nothing?): String = - "GET_ENUM '${expression.descriptor}' type=${expression.type.render()}" - - override fun visitStringConcatenation(expression: IrStringConcatenation, data: Nothing?): String = - "STRING_CONCATENATION type=${expression.type.render()}" - - override fun visitTypeOperator(expression: IrTypeOperatorCall, data: Nothing?): String = - "TYPE_OP origin=${expression.operator} typeOperand=${expression.typeOperand.render()}" - - override fun visitWhen(expression: IrWhen, data: Nothing?): String = - "WHEN type=${expression.type.render()} origin=${expression.origin}" - - override fun visitBranch(branch: IrBranch, data: Nothing?): String = - "BRANCH" - - override fun visitWhileLoop(loop: IrWhileLoop, data: Nothing?): String = - "WHILE label=${loop.label} origin=${loop.origin}" - - override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: Nothing?): String = - "DO_WHILE label=${loop.label} origin=${loop.origin}" - - override fun visitBreak(jump: IrBreak, data: Nothing?): String = - "BREAK label=${jump.label} loop.label=${jump.loop.label}" - - override fun visitContinue(jump: IrContinue, data: Nothing?): String = - "CONTINUE label=${jump.label} loop.label=${jump.loop.label}" - - override fun visitThrow(expression: IrThrow, data: Nothing?): String = - "THROW type=${expression.type.render()}" - - override fun visitCallableReference(expression: IrCallableReference, data: Nothing?): String = - "CALLABLE_REFERENCE '${expression.descriptor}' type=${expression.type.render()} origin=${expression.origin}" - - override fun visitClassReference(expression: IrClassReference, data: Nothing?): String = - "CLASS_REFERENCE '${expression.descriptor}' type=${expression.type.render()}" - - override fun visitGetClass(expression: IrGetClass, data: Nothing?): String = - "GET_CLASS type=${expression.type.render()}" - - override fun visitTry(aTry: IrTry, data: Nothing?): String = - "TRY type=${aTry.type.render()}" - - override fun visitCatch(aCatch: IrCatch, data: Nothing?): String = - "CATCH parameter=${aCatch.parameter.ref()}" - - override fun visitErrorDeclaration(declaration: IrErrorDeclaration, data: Nothing?): String = - "ERROR_DECL ${declaration.descriptor.javaClass.simpleName} ${declaration.descriptor.ref()}" - - override fun visitErrorExpression(expression: IrErrorExpression, data: Nothing?): String = - "ERROR_EXPR '${expression.description}' type=${expression.type.render()}" - - override fun visitErrorCallExpression(expression: IrErrorCallExpression, data: Nothing?): String = - "ERROR_CALL '${expression.description}' type=${expression.type.render()}" - - companion object { - val DECLARATION_RENDERER = DescriptorRenderer.withOptions { - withDefinedIn = false - overrideRenderingPolicy = OverrideRenderingPolicy.RENDER_OPEN_OVERRIDE - includePropertyConstant = true - classifierNamePolicy = ClassifierNamePolicy.FULLY_QUALIFIED - verbose = false - modifiers = DescriptorRendererModifier.ALL - } - - val REFERENCE_RENDERER = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES - - internal fun IrDeclaration.name(): String = - descriptor.let { it.name.toString() } - - internal fun IrDeclaration.renderDeclared(): String = - DECLARATION_RENDERER.render(this.descriptor) - - internal fun DeclarationDescriptor.ref(): String = - if (this is ReceiverParameterDescriptor) - "" - else - REFERENCE_RENDERER.render(this) - - internal fun KotlinType.render(): String = - DECLARATION_RENDERER.renderType(this) - - internal fun IrDeclaration.renderOrigin(): String = - if (origin != IrDeclarationOrigin.DEFINED) origin.toString() + " " else "" - } -} - -class DumpIrTreeWithDescriptorsVisitor(out: Appendable): IrElementVisitor { - val printer = Printer(out, " ") - val elementRenderer = RenderIrElementWithDescriptorsVisitor() - - companion object { - val ANNOTATIONS_RENDERER = DescriptorRenderer.withOptions { - verbose = true - annotationArgumentsRenderingPolicy = AnnotationArgumentsRenderingPolicy.UNLESS_EMPTY - } - } - - override fun visitElement(element: IrElement, data: String) { - element.dumpLabeledSubTree(data) - } - - override fun visitFile(declaration: IrFile, data: String) { - declaration.dumpLabeledElementWith(data) { - if (declaration.fileAnnotations.isNotEmpty()) { - printer.println("fileAnnotations:") - indented { - declaration.fileAnnotations.forEach { - printer.println(ANNOTATIONS_RENDERER.renderAnnotation(it)) - } - } - } - declaration.declarations.forEach { it.accept(this, "") } - } - } - - override fun visitBlock(expression: IrBlock, data: String) { - if (expression is IrReturnableBlock) { - printer.println("RETURNABLE BLOCK " + expression.descriptor) - indented { super.visitBlock(expression, data) } - return - } - super.visitBlock(expression, data) - } - - override fun visitFunction(declaration: IrFunction, data: String) { - visitFunctionWithParameters(declaration, data) - } - - override fun visitConstructor(declaration: IrConstructor, data: String) { - visitFunctionWithParameters(declaration, data) - } - - override fun visitErrorCallExpression(expression: IrErrorCallExpression, data: String) { - expression.dumpLabeledElementWith(data) { - expression.explicitReceiver?.accept(this, "receiver") - expression.arguments.forEach { it.accept(this, "") } - } - } - - private fun visitFunctionWithParameters(declaration: IrFunction, data: String) { - declaration.dumpLabeledElementWith(data) { - declaration.descriptor.valueParameters.forEach { valueParameter -> - declaration.getDefault(valueParameter)?.accept(this, valueParameter.name.asString()) - } - declaration.body?.accept(this, "") - } - } - - override fun visitEnumEntry(declaration: IrEnumEntry, data: String) { - declaration.dumpLabeledElementWith(data) { - declaration.initializerExpression?.accept(this, "init") - declaration.correspondingClass?.accept(this, "class") - } - } - - override fun visitMemberAccess(expression: IrMemberAccessExpression, data: String) { - expression.dumpLabeledElementWith(data) { - dumpTypeArguments(expression) - - expression.dispatchReceiver?.accept(this, "\$this") - expression.extensionReceiver?.accept(this, "\$receiver") - for (valueParameter in expression.descriptor.valueParameters) { - expression.getValueArgument(valueParameter.index)?.accept(this, valueParameter.name.asString()) - } - } - } - - private fun dumpTypeArguments(expression: IrMemberAccessExpression) { - for (typeParameter in expression.descriptor.original.typeParameters) { - val typeArgument = expression.getTypeArgument(typeParameter) ?: continue - val renderedParameter = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.render(typeParameter) - val renderedType = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.renderType(typeArgument) - printer.println("$renderedParameter: $renderedType") - } - } - - override fun visitGetField(expression: IrGetField, data: String) { - expression.dumpLabeledElementWith(data) { - expression.receiver?.accept(this, "receiver") - } - } - - override fun visitSetField(expression: IrSetField, data: String) { - expression.dumpLabeledElementWith(data) { - expression.receiver?.accept(this, "receiver") - expression.value.accept(this, "value") - } - } - - override fun visitWhen(expression: IrWhen, data: String) { - expression.dumpLabeledElementWith(data) { - expression.branches.forEach { - it.accept(this, "") - } - } - } - - override fun visitBranch(branch: IrBranch, data: String) { - branch.dumpLabeledElementWith(data) { - branch.condition.accept(this, "if") - branch.result.accept(this, "then") - } - } - - override fun visitWhileLoop(loop: IrWhileLoop, data: String) { - loop.dumpLabeledElementWith(data) { - loop.condition.accept(this, "condition") - loop.body?.accept(this, "body") - } - } - - override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: String) { - loop.dumpLabeledElementWith(data) { - loop.body?.accept(this, "body") - loop.condition.accept(this, "condition") - } - } - - override fun visitTry(aTry: IrTry, data: String) { - aTry.dumpLabeledElementWith(data) { - aTry.tryResult.accept(this, "try") - for (aCatch in aTry.catches) { - aCatch.accept(this, "") - } - aTry.finallyExpression?.accept(this, "finally") - } - } - - private inline fun IrElement.dumpLabeledElementWith(label: String, body: () -> Unit) { - printer.println(accept(elementRenderer, null).withLabel(label)) - indented(body) - } - - private fun IrElement.dumpLabeledSubTree(label: String) { - printer.println(accept(elementRenderer, null).withLabel(label)) - indented { - acceptChildren(this@DumpIrTreeWithDescriptorsVisitor, "") - } - } - - private inline fun indented(body: () -> Unit) { - printer.pushIndent() - body() - printer.popIndent() - } - - private fun String.withLabel(label: String) = - if (label.isEmpty()) this else "$label: $this" -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrCopy.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrCopy.kt deleted file mode 100644 index 2f5671c7148..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrCopy.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common - -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockSymbol -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.expressions.IrBlock -import org.jetbrains.kotlin.ir.expressions.IrReturn -import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl -import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols -import org.jetbrains.kotlin.ir.util.SymbolRemapper - -open class DeepCopyIrTreeWithReturnableBlockSymbols( - private val symbolRemapper: SymbolRemapper -) : DeepCopyIrTreeWithSymbols(symbolRemapper) { - - private inline fun T.transform() = - transform(this@DeepCopyIrTreeWithReturnableBlockSymbols, null) as T - - private val transformedReturnableBlocks = mutableMapOf() - - override fun visitBlock(expression: IrBlock): IrBlock = if (expression is IrReturnableBlock) { - IrReturnableBlockImpl( - expression.startOffset, expression.endOffset, - expression.type, - expression.descriptor, - expression.origin, - expression.sourceFileName - ).also { - transformedReturnableBlocks.put(expression, it) - it.statements.addAll(expression.statements.map { it.transform() }) - } - } else { - super.visitBlock(expression) - } - - override fun visitReturn(expression: IrReturn): IrReturn { - val returnTargetSymbol = expression.returnTargetSymbol - return if (returnTargetSymbol is IrReturnableBlockSymbol) { - IrReturnImpl( - expression.startOffset, expression.endOffset, - expression.type, - transformedReturnableBlocks.getOrElse(returnTargetSymbol.owner) { returnTargetSymbol.owner }.symbol, - expression.value.transform() - ) - } else { - super.visitReturn(expression) - } - } -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt deleted file mode 100644 index 05e8c645ec0..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common - -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.builders.Scope -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.descriptors.* - -internal class ScopeWithIr(val scope: Scope, val irElement: IrElement) - -abstract internal class IrElementTransformerVoidWithContext : IrElementTransformerVoid() { - - private val scopeStack = mutableListOf() - - override final fun visitFile(declaration: IrFile): IrFile { - scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) - val result = visitFileNew(declaration) - scopeStack.pop() - return result - } - - override final fun visitClass(declaration: IrClass): IrStatement { - scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) - val result = visitClassNew(declaration) - scopeStack.pop() - return result - } - - override final fun visitProperty(declaration: IrProperty): IrStatement { - scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) - val result = visitPropertyNew(declaration) - scopeStack.pop() - return result - } - - override final fun visitField(declaration: IrField): IrStatement { - scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) - val result = visitFieldNew(declaration) - scopeStack.pop() - return result - } - - override final fun visitFunction(declaration: IrFunction): IrStatement { - scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) - val result = visitFunctionNew(declaration) - scopeStack.pop() - return result - } - - protected val currentFile get() = scopeStack.lastOrNull { it.irElement is IrFile }!!.irElement as IrFile - protected val currentClass get() = scopeStack.lastOrNull { it.scope.scopeOwner is ClassDescriptor } - protected val currentFunction get() = scopeStack.lastOrNull { it.scope.scopeOwner is FunctionDescriptor } - protected val currentProperty get() = scopeStack.lastOrNull { it.scope.scopeOwner is PropertyDescriptor } - protected val currentScope get() = scopeStack.peek() - protected val parentScope get() = if (scopeStack.size < 2) null else scopeStack[scopeStack.size - 2] - protected val allScopes get() = scopeStack - - fun printScopeStack() { - scopeStack.forEach { println(it.scope.scopeOwner) } - } - - open fun visitFileNew(declaration: IrFile): IrFile { - return super.visitFile(declaration) - } - - open fun visitClassNew(declaration: IrClass): IrStatement { - return super.visitClass(declaration) - } - - open fun visitFunctionNew(declaration: IrFunction): IrStatement { - return super.visitFunction(declaration) - } - - open fun visitPropertyNew(declaration: IrProperty): IrStatement { - return super.visitProperty(declaration) - } - - open fun visitFieldNew(declaration: IrField): IrStatement { - return super.visitField(declaration) - } -} - -abstract internal class IrElementVisitorVoidWithContext : IrElementVisitorVoid { - - private val scopeStack = mutableListOf() - - override final fun visitFile(declaration: IrFile) { - scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) - visitFileNew(declaration) - scopeStack.pop() - } - - override final fun visitClass(declaration: IrClass) { - scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) - visitClassNew(declaration) - scopeStack.pop() - } - - override final fun visitProperty(declaration: IrProperty) { - scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) - visitPropertyNew(declaration) - scopeStack.pop() - } - - override final fun visitField(declaration: IrField) { - val isDelegated = declaration.descriptor.isDelegated - if (isDelegated) scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) - visitFieldNew(declaration) - if (isDelegated) scopeStack.pop() - } - - override final fun visitFunction(declaration: IrFunction) { - scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) - visitFunctionNew(declaration) - scopeStack.pop() - } - - protected val currentFile get() = scopeStack.lastOrNull { it.scope.scopeOwner is PackageFragmentDescriptor } - protected val currentClass get() = scopeStack.lastOrNull { it.scope.scopeOwner is ClassDescriptor } - protected val currentFunction get() = scopeStack.lastOrNull { it.scope.scopeOwner is FunctionDescriptor } - protected val currentProperty get() = scopeStack.lastOrNull { it.scope.scopeOwner is PropertyDescriptor } - protected val currentScope get() = scopeStack.peek() - protected val parentScope get() = if (scopeStack.size < 2) null else scopeStack[scopeStack.size - 2] - - fun printScopeStack() { - scopeStack.forEach { println(it.scope.scopeOwner) } - } - - open fun visitFileNew(declaration: IrFile) { - super.visitFile(declaration) - } - - open fun visitClassNew(declaration: IrClass) { - super.visitClass(declaration) - } - - open fun visitFunctionNew(declaration: IrFunction) { - super.visitFunction(declaration) - } - - open fun visitPropertyNew(declaration: IrProperty) { - super.visitProperty(declaration) - } - - open fun visitFieldNew(declaration: IrField) { - super.visitField(declaration) - } -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt deleted file mode 100644 index 6457f235a87..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common - -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.util.render -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid -import org.jetbrains.kotlin.ir.visitors.acceptVoid - -fun validateIrFile(context: CommonBackendContext, irFile: IrFile) { - val visitor = IrValidator(context, false) - irFile.acceptVoid(visitor) -} - -fun validateIrModule(context: CommonBackendContext, irModule: IrModuleFragment) { - val visitor = IrValidator(context, true) // TODO: consider taking the boolean from settings. - irModule.acceptVoid(visitor) - - // TODO: also check that all referenced symbol targets are reachable. -} - -private fun CommonBackendContext.reportIrValidationError(message: String, irFile: IrFile, irElement: IrElement) { - try { - this.reportWarning("[IR VALIDATION] $message", irFile, irElement) - } catch (e: Throwable) { - println("an error trying to print a warning message: $e") - e.printStackTrace() - } - // TODO: throw an exception after fixing bugs leading to invalid IR. -} - -private class IrValidator(val context: CommonBackendContext, performHeavyValidations: Boolean) : IrElementVisitorVoid { - - val builtIns = context.builtIns - lateinit var currentFile: IrFile - - override fun visitFile(declaration: IrFile) { - currentFile = declaration - super.visitFile(declaration) - } - - private fun error(element: IrElement, message: String) { - // TODO: render all element's parents. - context.reportIrValidationError( - "$message\n" + - element.render(), - currentFile, element) - } - - private val elementChecker = CheckIrElementVisitor(builtIns, this::error, performHeavyValidations) - - override fun visitElement(element: IrElement) { - element.acceptVoid(elementChecker) - element.acceptChildrenVoid(this) - } -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/TailRecursionCallsCollector.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/TailRecursionCallsCollector.kt deleted file mode 100644 index 66e1e4e3e6f..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/TailRecursionCallsCollector.kt +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common - -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.util.usesDefaultArguments -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.types.typeUtil.isUnit - -/** - * Collects calls to be treated as tail recursion. - * The checks are partially based on the frontend implementation - * in `ControlFlowInformationProvider.markAndCheckRecursiveTailCalls()`. - * - * This analysis is not very precise and can miss some calls. - * It is also not guaranteed that each returned call is detected as tail recursion by the frontend. - * However any returned call can be correctly optimized as tail recursion. - */ -fun collectTailRecursionCalls(irFunction: IrFunction): Set { - if (!irFunction.descriptor.isTailrec) { - return emptySet() - } - - val result = mutableSetOf() - - val visitor = object : IrElementVisitor { - - override fun visitElement(element: IrElement, data: ElementKind) { - val childKind = ElementKind.NOT_SURE // Not sure by default. - element.acceptChildren(this, childKind) - } - - override fun visitFunction(declaration: IrFunction, data: ElementKind) { - // Ignore local functions. - } - - override fun visitClass(declaration: IrClass, data: ElementKind) { - // Ignore local classes. - } - - override fun visitTry(aTry: IrTry, data: ElementKind) { - // We do not support tail calls in try-catch-finally, for simplicity of the mental model - // very few cases there would be real tail-calls, and it's often not so easy for the user to see why - } - - override fun visitReturn(expression: IrReturn, data: ElementKind) { - val valueKind = if (expression.returnTarget == irFunction.descriptor) { - ElementKind.TAIL_STATEMENT - } else { - ElementKind.NOT_SURE - } - expression.value.accept(this, valueKind) - } - - override fun visitContainerExpression(expression: IrContainerExpression, data: ElementKind) { - expression.statements.forEachIndexed { index, irStatement -> - val statementKind = if (index == expression.statements.lastIndex) { - // The last statement defines the result of the container expression, so it has the same kind. - data - } else { - ElementKind.NOT_SURE - } - irStatement.accept(this, statementKind) - } - } - - override fun visitWhen(expression: IrWhen, data: ElementKind) { - expression.branches.forEach { - it.condition.accept(this, ElementKind.NOT_SURE) - it.result.accept(this, data) - } - } - - override fun visitCall(expression: IrCall, data: ElementKind) { - expression.acceptChildren(this, ElementKind.NOT_SURE) - - // Is it a tail call? - if (data != ElementKind.TAIL_STATEMENT) { - return - } - - // Is it a recursive call? - if (expression.descriptor.original != irFunction.descriptor) { - return - } - // TODO: check type arguments - - if (DescriptorUtils.isOverride(irFunction.descriptor) && expression.usesDefaultArguments()) { - // Overridden functions using default arguments at tail call are not included: KT-4285 - return - } - - expression.dispatchReceiver?.let { - if (it !is IrGetValue || it.descriptor != irFunction.descriptor.dispatchReceiverParameter) { - // A tail call is not allowed to change dispatch receiver - // class C { - // fun foo(other: C) { - // other.foo(this) // not a tail call - // } - // } - return - } - } - - result.add(expression) - - } - - } - - val body = irFunction.body - if (body !is IrBlockBody) { - return emptySet() // TODO: should an assert be here instead? - } - - body.statements.forEachIndexed { index, irStatement -> - val kind = if (index == body.statements.lastIndex && irFunction.descriptor.returnType?.isUnit() == true) { - ElementKind.TAIL_STATEMENT - } else { - ElementKind.NOT_SURE - } - irStatement.accept(visitor, kind) - } - - return result -} - -/** - * The kind of IR element used to detect tail calls. - */ -private enum class ElementKind { - /** - * This element is the last statement to be executed before the return from the function. - * If the return type is not `Unit`, the result of this statement defines the result of the entire function. - */ - TAIL_STATEMENT, - - /** - * Not sure if the element meets the requirements to be [TAIL_STATEMENT]. - */ - NOT_SURE -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/Utils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/Utils.kt deleted file mode 100644 index eaa9236628b..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/Utils.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common - -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.util.getCompilerMessageLocation - -fun CommonBackendContext.reportWarning(message: String, irFile: IrFile, irElement: IrElement) { - val location = irElement.getCompilerMessageLocation(irFile) - messageCollector.report(CompilerMessageSeverity.WARNING, message, location) -} - -fun MutableList.push(element: E) = this.add(element) - -fun MutableList.pop() = this.removeAt(size - 1) - -fun MutableList.peek(): E? = if (size == 0) null else this[size - 1] - -fun Collection.atMostOne(): T? { - return when (this.size) { - 0 -> null - 1 -> this.iterator().next() - else -> throw IllegalArgumentException("Collection has more than one element.") - } -} - -inline fun Iterable.atMostOne(predicate: (T) -> Boolean): T? = this.filter(predicate).atMostOne() - -fun T.onlyIf(condition: T.()->Boolean, then: (T)->Unit): T { - if (this.condition()) then(this) - return this -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorUtils.kt deleted file mode 100644 index 10aa9b8695a..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorUtils.kt +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common.descriptors - -import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor -import org.jetbrains.kotlin.builtins.getFunctionalClassKind -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeProjectionImpl -import org.jetbrains.kotlin.types.TypeSubstitutor -import org.jetbrains.kotlin.types.replace - -internal val CallableDescriptor.isSuspend: Boolean - get() = this is FunctionDescriptor && isSuspend - -/** - * @return naturally-ordered list of all parameters available inside the function body. - */ -internal val CallableDescriptor.allParameters: List - get() = if (this is ConstructorDescriptor) { - listOf(this.constructedClass.thisAsReceiverParameter) + explicitParameters - } else { - explicitParameters - } - -/** - * @return naturally-ordered list of the parameters that can have values specified at call site. - */ -internal val CallableDescriptor.explicitParameters: List - get() { - val result = ArrayList(valueParameters.size + 2) - - this.dispatchReceiverParameter?.let { - result.add(it) - } - - this.extensionReceiverParameter?.let { - result.add(it) - } - - result.addAll(valueParameters) - - return result - } - -fun KotlinType.replace(types: List) = this.replace(types.map(::TypeProjectionImpl)) - -fun FunctionDescriptor.substitute(vararg types: KotlinType): FunctionDescriptor { - val typeSubstitutor = TypeSubstitutor.create( - typeParameters - .withIndex() - .associateBy({ it.value.typeConstructor }, { TypeProjectionImpl(types[it.index]) }) - ) - return substitute(typeSubstitutor)!! -} - -fun FunctionDescriptor.substitute(typeArguments: Map): FunctionDescriptor { - val typeSubstitutor = TypeSubstitutor.create( - typeParameters.associateBy({ it.typeConstructor }, { TypeProjectionImpl(typeArguments[it]!!) }) - ) - return substitute(typeSubstitutor)!! -} - -fun ClassDescriptor.getFunction(name: String, types: List): FunctionDescriptor { - val typeSubstitutor = TypeSubstitutor.create( - declaredTypeParameters - .withIndex() - .associateBy({ it.value.typeConstructor }, { TypeProjectionImpl(types[it.index]) }) - ) - return unsubstitutedMemberScope - .getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).single().substitute(typeSubstitutor)!! -} - -val KotlinType.isFunctionOrKFunctionType: Boolean - get() { - val kind = constructor.declarationDescriptor?.getFunctionalClassKind() - return kind == FunctionClassDescriptor.Kind.Function || kind == FunctionClassDescriptor.Kind.KFunction - } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt deleted file mode 100644 index 2038360405c..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt +++ /dev/null @@ -1,208 +0,0 @@ -package org.jetbrains.kotlin.backend.common.ir - -import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.builtins.PrimitiveType -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.util.SymbolTable -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.util.OperatorNameConventions - -// This is what Context collects about IR. -abstract class Ir(val context: T, val irModule: IrModuleFragment) { - - abstract val symbols: Symbols - - val defaultParameterDeclarationsCache = mutableMapOf() - - open fun shouldGenerateHandlerParameterForDefaultBodyFun() = false -} - -abstract class Symbols(val context: T, private val symbolTable: SymbolTable) { - - private val builtIns - get() = context.builtIns - - protected fun builtInsPackage(vararg packageNameSegments: String) = - context.builtIns.builtInsModule.getPackage(FqName.fromSegments(listOf(*packageNameSegments))).memberScope - - val refClass = symbolTable.referenceClass(context.getInternalClass("Ref")) - - abstract val areEqual: IrFunctionSymbol - abstract val ThrowNullPointerException: IrFunctionSymbol - abstract val ThrowNoWhenBranchMatchedException: IrFunctionSymbol - abstract val ThrowTypeCastException: IrFunctionSymbol - abstract val ThrowUninitializedPropertyAccessException: IrFunctionSymbol - - abstract val stringBuilder: IrClassSymbol - - val iterator = symbolTable.referenceClass( - builtInsPackage("kotlin", "collections").getContributedClassifier( - Name.identifier("Iterator"), NoLookupLocation.FROM_BACKEND - ) as ClassDescriptor) - - val asserts = builtInsPackage("kotlin") - .getContributedFunctions(Name.identifier("assert"), NoLookupLocation.FROM_BACKEND) - .map { symbolTable.referenceFunction(it) } - - private fun progression(name: String) = symbolTable.referenceClass( - builtInsPackage("kotlin", "ranges").getContributedClassifier( - Name.identifier(name), NoLookupLocation.FROM_BACKEND - ) as ClassDescriptor - ) - - val charProgression = progression("CharProgression") - val intProgression = progression("IntProgression") - val longProgression = progression("LongProgression") - val progressionClasses = listOf(charProgression, intProgression, longProgression) - val progressionClassesTypes = progressionClasses.map { it.descriptor.defaultType }.toSet() - - val defaultConstructorMarker = symbolTable.referenceClass(context.getInternalClass("DefaultConstructorMarker")) - - val any = symbolTable.referenceClass(builtIns.any) - val unit = symbolTable.referenceClass(builtIns.unit) - - val char = symbolTable.referenceClass(builtIns.char) - - val byte = symbolTable.referenceClass(builtIns.byte) - val short = symbolTable.referenceClass(builtIns.short) - val int = symbolTable.referenceClass(builtIns.int) - val long = symbolTable.referenceClass(builtIns.long) - - val integerClasses = listOf(byte, short, int, long) - val integerClassesTypes = integerClasses.map { it.descriptor.defaultType } - - val arrayOf = symbolTable.referenceSimpleFunction( - builtInsPackage("kotlin").getContributedFunctions( - Name.identifier("arrayOf"), NoLookupLocation.FROM_BACKEND - ).single() - ) - - val array = symbolTable.referenceClass(builtIns.array) - - private fun primitiveArrayClass(type: PrimitiveType) = - symbolTable.referenceClass(builtIns.getPrimitiveArrayClassDescriptor(type)) - - val byteArray = primitiveArrayClass(PrimitiveType.BYTE) - val charArray = primitiveArrayClass(PrimitiveType.CHAR) - val shortArray = primitiveArrayClass(PrimitiveType.SHORT) - val intArray = primitiveArrayClass(PrimitiveType.INT) - val longArray = primitiveArrayClass(PrimitiveType.LONG) - val floatArray = primitiveArrayClass(PrimitiveType.FLOAT) - val doubleArray = primitiveArrayClass(PrimitiveType.DOUBLE) - val booleanArray = primitiveArrayClass(PrimitiveType.BOOLEAN) - - val arrays = PrimitiveType.values().map { primitiveArrayClass(it) } + array - - protected fun arrayExtensionFun(type: KotlinType, name: String): IrSimpleFunctionSymbol { - val descriptor = builtInsPackage("kotlin") - .getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND) - .singleOrNull { it.valueParameters.isEmpty() - && (it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.defaultType == type } - ?: throw Error(type.toString()) - return symbolTable.referenceSimpleFunction(descriptor) - } - - - protected val arrayTypes = arrayOf( - builtIns.getPrimitiveArrayKotlinType(PrimitiveType.BYTE), - builtIns.getPrimitiveArrayKotlinType(PrimitiveType.CHAR), - builtIns.getPrimitiveArrayKotlinType(PrimitiveType.SHORT), - builtIns.getPrimitiveArrayKotlinType(PrimitiveType.INT), - builtIns.getPrimitiveArrayKotlinType(PrimitiveType.LONG), - builtIns.getPrimitiveArrayKotlinType(PrimitiveType.FLOAT), - builtIns.getPrimitiveArrayKotlinType(PrimitiveType.DOUBLE), - builtIns.getPrimitiveArrayKotlinType(PrimitiveType.BOOLEAN), - builtIns.array.defaultType - ) - - val copyRangeTo = arrays.map { symbol -> - val packageViewDescriptor = builtIns.builtInsModule.getPackage(KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME) - val functionDescriptor = packageViewDescriptor.memberScope - .getContributedFunctions(Name.identifier("copyRangeTo"), NoLookupLocation.FROM_BACKEND) - .first { - it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == symbol.descriptor - } - symbol.descriptor to symbolTable.referenceSimpleFunction(functionDescriptor) - }.toMap() - - val intAnd = symbolTable.referenceFunction( - builtIns.intType.memberScope - .getContributedFunctions(OperatorNameConventions.AND, NoLookupLocation.FROM_BACKEND) - .single() - ) - - val intPlusInt = symbolTable.referenceFunction( - builtIns.intType.memberScope - .getContributedFunctions(OperatorNameConventions.PLUS, NoLookupLocation.FROM_BACKEND) - .single { - it.valueParameters.single().type == builtIns.intType - } - ) - - - - abstract val valuesForEnum: IrFunctionSymbol - abstract val valueOfForEnum: IrFunctionSymbol - abstract val getContinuation: IrFunctionSymbol - - val coroutineImpl = symbolTable.referenceClass(context.getInternalClass("CoroutineImpl")) - - val coroutineSuspendedGetter = symbolTable.referenceSimpleFunction( - builtInsPackage("kotlin", "coroutines", "experimental", "intrinsics") - .getContributedVariables(Name.identifier("COROUTINE_SUSPENDED"), NoLookupLocation.FROM_BACKEND) - .single().getter!! - ) - - val kFunctionImpl = symbolTable.referenceClass(context.reflectionTypes.kFunctionImpl) - - val kProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty0Impl) - val kProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl) - val kProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty2Impl) - val kMutableProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty0Impl) - val kMutableProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty1Impl) - val kMutableProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty2Impl) - - fun getFunction(name: Name, receiverType: KotlinType, vararg argTypes: KotlinType) = - symbolTable.referenceFunction(receiverType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) - .single { - var i = 0 - it.valueParameters.size == argTypes.size && it.valueParameters.all { type -> type == argTypes[i++] } - } - ) - - private val binaryOperatorCache = mutableMapOf, IrFunctionSymbol>() - fun getBinaryOperator(name: Name, lhsType: KotlinType, rhsType: KotlinType): IrFunctionSymbol { - val key = Triple(name, lhsType, rhsType) - var result = binaryOperatorCache[key] - if (result == null) { - result = symbolTable.referenceFunction(lhsType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) - .single { it.valueParameters.size == 1 && it.valueParameters[0].type == rhsType } - ) - binaryOperatorCache[key] = result - } - return result - } - - private val unaryOperatorCache = mutableMapOf, IrFunctionSymbol>() - fun getUnaryOperator(name: Name, receiverType: KotlinType): IrFunctionSymbol { - val key = name to receiverType - var result = unaryOperatorCache[key] - if (result == null) { - result = symbolTable.referenceFunction(receiverType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) - .single { it.valueParameters.isEmpty() } - ) - unaryOperatorCache[key] = result - } - return result - } -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt deleted file mode 100644 index eec80a7732a..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common.ir - -import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor -import org.jetbrains.kotlin.ir.util.createParameterDeclarations -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeProjectionImpl -import org.jetbrains.kotlin.types.TypeSubstitutor -import java.io.StringWriter - - -fun ir2string(ir: IrElement?): String = ir2stringWhole(ir).takeWhile { it != '\n' } - -fun ir2stringWhole(ir: IrElement?, withDescriptors: Boolean = false): String { - val strWriter = StringWriter() - - if (withDescriptors) - ir?.accept(DumpIrTreeWithDescriptorsVisitor(strWriter), "") - else - ir?.accept(DumpIrTreeVisitor(strWriter), "") - return strWriter.toString() -} - -internal fun DeclarationDescriptor.createFakeOverrideDescriptor(owner: ClassDescriptor): DeclarationDescriptor? { - // We need to copy descriptors for vtable building, thus take only functions and properties. - return when (this) { - is CallableMemberDescriptor -> - copy( - /* newOwner = */ owner, - /* modality = */ modality, - /* visibility = */ visibility, - /* kind = */ CallableMemberDescriptor.Kind.FAKE_OVERRIDE, - /* copyOverrides = */ true).apply { - overriddenDescriptors += this@createFakeOverrideDescriptor - } - else -> null - } -} - -internal fun FunctionDescriptor.createOverriddenDescriptor(owner: ClassDescriptor, final: Boolean = true): FunctionDescriptor { - return this.newCopyBuilder() - .setOwner(owner) - .setCopyOverrides(true) - .setModality(if (final) Modality.FINAL else Modality.OPEN) - .setDispatchReceiverParameter(owner.thisAsReceiverParameter) - .build()!!.apply { - overriddenDescriptors += this@createOverriddenDescriptor - } -} - -internal fun ClassDescriptor.createSimpleDelegatingConstructorDescriptor(superConstructorDescriptor: ClassConstructorDescriptor, isPrimary: Boolean = false) - : ClassConstructorDescriptor { - val constructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized( - /* containingDeclaration = */ this, - /* annotations = */ Annotations.EMPTY, - /* isPrimary = */ isPrimary, - /* source = */ SourceElement.NO_SOURCE) - val valueParameters = superConstructorDescriptor.valueParameters.map { - it.copy(constructorDescriptor, it.name, it.index) - } - constructorDescriptor.initialize(valueParameters, superConstructorDescriptor.visibility) - constructorDescriptor.returnType = superConstructorDescriptor.returnType - return constructorDescriptor -} - -internal fun IrClass.addSimpleDelegatingConstructor(superConstructorSymbol: IrConstructorSymbol, - constructorDescriptor: ClassConstructorDescriptor, - origin: IrDeclarationOrigin) - : IrConstructor { - - return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor).also { constructor -> - constructor.createParameterDeclarations() - - constructor.body = IrBlockBodyImpl(startOffset, endOffset, - listOf( - IrDelegatingConstructorCallImpl( - startOffset, endOffset, - superConstructorSymbol, superConstructorSymbol.descriptor - ).apply { - constructor.valueParameters.forEachIndexed { idx, parameter -> - putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.symbol)) - } - }, - IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol) - ) - ) - - this.declarations.add(constructor) - } -} - -internal fun CommonBackendContext.createArrayOfExpression(arrayElementType: KotlinType, - arrayElements: List, - startOffset: Int, endOffset: Int): IrExpression { - - val genericArrayOfFunSymbol = ir.symbols.arrayOf - val genericArrayOfFun = genericArrayOfFunSymbol.descriptor - val typeParameter0 = genericArrayOfFun.typeParameters[0] - val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType))) - val substitutedArrayOfFun = genericArrayOfFun.substitute(typeSubstitutor)!! - - val typeArguments = mapOf(typeParameter0 to arrayElementType) - - val valueParameter0 = substitutedArrayOfFun.valueParameters[0] - val arg0VarargType = valueParameter0.type - val arg0VarargElementType = valueParameter0.varargElementType!! - val arg0 = IrVarargImpl(startOffset, endOffset, arg0VarargType, arg0VarargElementType, arrayElements) - - return IrCallImpl(startOffset, endOffset, genericArrayOfFunSymbol, substitutedArrayOfFun, typeArguments).apply { - putValueArgument(0, arg0) - } -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt deleted file mode 100644 index 88b0bc74d5f..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common.lower - -import org.jetbrains.kotlin.backend.common.* -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.IrCatch -import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression -import org.jetbrains.kotlin.ir.expressions.IrValueAccessExpression -import org.jetbrains.kotlin.ir.symbols.IrValueSymbol -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.DescriptorUtils - -// TODO: synchronize with JVM BE -// TODO: rename the file. -class Closure(val capturedValues: List = emptyList()) - -class ClosureAnnotator { - private val closureBuilders = mutableMapOf() - - constructor(declaration: IrDeclaration) { - // Collect all closures for classes and functions. Collect call graph - declaration.acceptChildrenVoid(ClosureCollectorVisitor()) - } - - fun getFunctionClosure(descriptor: FunctionDescriptor) = getClosure(descriptor) - fun getClassClosure(descriptor: ClassDescriptor) = getClosure(descriptor) - - private fun getClosure(descriptor: DeclarationDescriptor) : Closure { - closureBuilders.values.forEach { it.processed = false } - return closureBuilders - .getOrElse(descriptor) { throw AssertionError("No closure builder for passed descriptor.") } - .buildClosure() - } - - private class ClosureBuilder(val owner: DeclarationDescriptor) { - val capturedValues = mutableSetOf() - private val declaredValues = mutableSetOf() - private val includes = mutableSetOf() - - var processed = false - - /* - * Node's closure = variables captured by the node + - * closure of all included nodes - - * variables declared in the node. - */ - fun buildClosure(): Closure { - val result = mutableSetOf().apply { addAll(capturedValues) } - includes.forEach { - if (!it.processed) { - it.processed = true - it.buildClosure().capturedValues.filterTo(result) { isExternal(it.descriptor) } - } - } - // TODO: We can save the closure and reuse it. - return Closure(result.toList()) - } - - - fun include(includingBuilder: ClosureBuilder) { - includes.add(includingBuilder) - } - - fun declareVariable(valueDescriptor: ValueDescriptor?) { - if (valueDescriptor != null) - declaredValues.add(valueDescriptor) - } - - fun seeVariable(value: IrValueSymbol) { - if (isExternal(value.descriptor)) - capturedValues.add(value) - } - - fun isExternal(valueDescriptor: ValueDescriptor): Boolean { - return !declaredValues.contains(valueDescriptor) - } - - } - - private inner class ClosureCollectorVisitor : IrElementVisitorVoid { - - val closuresStack = mutableListOf() - - fun includeInParent(builder: ClosureBuilder) { - // We don't include functions or classes in a parent function when they are declared. - // Instead we will include them when are is used (use = call for a function or constructor call for a class). - val parentBuilder = closuresStack.peek() - if (parentBuilder != null && parentBuilder.owner !is FunctionDescriptor) { - parentBuilder.include(builder) - } - } - - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitClass(declaration: IrClass) { - val classDescriptor = declaration.descriptor - val closureBuilder = ClosureBuilder(classDescriptor) - closureBuilders[declaration.descriptor] = closureBuilder - - closureBuilder.declareVariable(classDescriptor.thisAsReceiverParameter) - if (classDescriptor.isInner) { - closureBuilder.declareVariable((classDescriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter) - includeInParent(closureBuilder) - } - - closuresStack.push(closureBuilder) - declaration.acceptChildrenVoid(this) - closuresStack.pop() - } - - override fun visitFunction(declaration: IrFunction) { - val functionDescriptor = declaration.descriptor - val closureBuilder = ClosureBuilder(functionDescriptor) - closureBuilders[functionDescriptor] = closureBuilder - - functionDescriptor.valueParameters.forEach { closureBuilder.declareVariable(it) } - closureBuilder.declareVariable(functionDescriptor.dispatchReceiverParameter) - closureBuilder.declareVariable(functionDescriptor.extensionReceiverParameter) - if (functionDescriptor is ConstructorDescriptor) { - closureBuilder.declareVariable(functionDescriptor.constructedClass.thisAsReceiverParameter) - // Include closure of the class in the constructor closure. - val classBuilder = closuresStack.peek() - classBuilder?.let { - assert(classBuilder.owner == functionDescriptor.constructedClass) - closureBuilder.include(classBuilder) - } - } - - closuresStack.push(closureBuilder) - declaration.acceptChildrenVoid(this) - closuresStack.pop() - - includeInParent(closureBuilder) - } - - override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty) { - // Getter and setter of local delegated properties are special generated functions and don't have closure. - declaration.delegate.initializer?.acceptVoid(this) - } - - override fun visitVariableAccess(expression: IrValueAccessExpression) { - closuresStack.peek()?.seeVariable(expression.symbol) - super.visitVariableAccess(expression) - } - - override fun visitVariable(declaration: IrVariable) { - closuresStack.peek()?.declareVariable(declaration.descriptor) - super.visitVariable(declaration) - } - - override fun visitCatch(aCatch: IrCatch) { - closuresStack.peek()?.declareVariable(aCatch.parameter) - super.visitCatch(aCatch) - } - - // Process delegating constructor calls, enum constructor calls, calls and callable references. - override fun visitMemberAccess(expression: IrMemberAccessExpression) { - expression.acceptChildrenVoid(this) - val descriptor = expression.descriptor - if (DescriptorUtils.isLocal(descriptor)) { - val builder = closureBuilders[descriptor] - builder?.let { - closuresStack.peek()?.include(builder) - } - } - } - } -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt deleted file mode 100644 index a6afa2bcbe3..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common.lower - -import org.jetbrains.kotlin.backend.common.BodyLoweringPass -import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass -import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName -import org.jetbrains.kotlin.backend.common.ir.ir2string -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl -import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl -import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns -import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.builtIns - -open class DefaultArgumentStubGenerator constructor(val context: CommonBackendContext): DeclarationContainerLoweringPass { - override fun lower(irDeclarationContainer: IrDeclarationContainer) { - irDeclarationContainer.declarations.transformFlat { memberDeclaration -> - if (memberDeclaration is IrFunction) - lower(memberDeclaration) - else - null - } - - } - - private val symbols = context.ir.symbols - - private fun lower(irFunction: IrFunction): List { - val functionDescriptor = irFunction.descriptor - - if (!functionDescriptor.needsDefaultArgumentsLowering) - return listOf(irFunction) - - val bodies = functionDescriptor.valueParameters - .mapNotNull{irFunction.getDefault(it)} - - - log("detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions") - functionDescriptor.overriddenDescriptors.forEach { context.log{"DEFAULT-REPLACER: $it"} } - if (bodies.isNotEmpty()) { - val newIrFunction = functionDescriptor.generateDefaultsFunction(context) - val descriptor = newIrFunction.descriptor - log("$functionDescriptor -> $descriptor") - val builder = context.createIrBuilder(newIrFunction.symbol) - val body = builder.irBlockBody(irFunction) { - val params = mutableListOf() - val variables = mutableMapOf() - if (descriptor.extensionReceiverParameter != null) { - variables[functionDescriptor.extensionReceiverParameter!!] = - newIrFunction.extensionReceiverParameter!!.symbol - } - - for (valueParameter in functionDescriptor.valueParameters) { - val parameterSymbol = newIrFunction.valueParameters[valueParameter.index].symbol - val temporaryVariableSymbol = - IrVariableSymbolImpl(scope.createTemporaryVariableDescriptor(parameterSymbol.descriptor)) - params.add(temporaryVariableSymbol) - variables.put(valueParameter, temporaryVariableSymbol) - if (valueParameter.hasDefaultValue()) { - val kIntAnd = symbols.intAnd - val condition = irNotEquals(irCall(kIntAnd).apply { - dispatchReceiver = irGet(maskParameterSymbol(newIrFunction, valueParameter.index / 32)) - putValueArgument(0, irInt(1 shl (valueParameter.index % 32))) - }, irInt(0)) - val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter) - - /* Use previously calculated values in next expression. */ - expressionBody.transformChildrenVoid(object:IrElementTransformerVoid() { - override fun visitGetValue(expression: IrGetValue): IrExpression { - log("GetValue: ${expression.descriptor}") - val valueSymbol = variables[expression.descriptor] ?: return expression - return irGet(valueSymbol) - } - }) - val variableInitialization = irIfThenElse( - type = temporaryVariableSymbol.descriptor.type, - condition = condition, - thenPart = expressionBody.expression, - elsePart = irGet(parameterSymbol)) - + scope.createTemporaryVariable( - symbol = temporaryVariableSymbol, - initializer = variableInitialization) - /* Mapping calculated values with its origin variables. */ - } else { - + scope.createTemporaryVariable( - symbol = temporaryVariableSymbol, - initializer = irGet(parameterSymbol)) - } - } - if (irFunction is IrConstructor) { - + IrDelegatingConstructorCallImpl( - startOffset = irFunction.startOffset, - endOffset = irFunction.endOffset, - symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor - ).apply { - params.forEachIndexed { i, variable -> - putValueArgument(i, irGet(variable)) - } - if (functionDescriptor.dispatchReceiverParameter != null) { - dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol) - } - } - } else { - +irReturn(irCall(irFunction.symbol).apply { - if (functionDescriptor.dispatchReceiverParameter != null) { - dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol) - } - if (functionDescriptor.extensionReceiverParameter != null) { - extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!]!!) - } - params.forEachIndexed { i, variable -> - putValueArgument(i, irGet(variable)) - } - }) - } - } - // Remove default argument initializers. - irFunction.valueParameters.forEach { - it.defaultValue = null - } - return if (functionDescriptor is ClassConstructorDescriptor) - listOf(irFunction, IrConstructorImpl( - startOffset = irFunction.startOffset, - endOffset = irFunction.endOffset, - descriptor = descriptor as ClassConstructorDescriptor, - origin = DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, - body = body).apply { createParameterDeclarations() }) - else - listOf(irFunction, IrFunctionImpl( - startOffset = irFunction.startOffset, - endOffset = irFunction.endOffset, - descriptor = descriptor, - origin = DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, - body = body).apply { createParameterDeclarations() }) - } - return listOf(irFunction) - } - - - private fun log(msg:String) = context.log{"DEFAULT-REPLACER: $msg"} -} - -private fun Scope.createTemporaryVariableDescriptor(parameterDescriptor: ParameterDescriptor?): VariableDescriptor = - IrTemporaryVariableDescriptorImpl( - containingDeclaration = this.scopeOwner, - name = parameterDescriptor!!.name.asString().synthesizedName, - outType = parameterDescriptor.type, - isMutable = false) - -private fun Scope.createTemporaryVariable(symbol: IrVariableSymbol, initializer: IrExpression) = - IrVariableImpl( - startOffset = initializer.startOffset, - endOffset = initializer.endOffset, - origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, - symbol = symbol).apply { - - this.initializer = initializer - } - -private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor):IrExpressionBody { - return irFunction.getDefault(valueParameter) as? IrExpressionBody ?: TODO("FIXME!!!") -} - -private fun maskParameterDescriptor(function: IrFunction, number: Int) = - maskParameterSymbol(function, number).descriptor as ValueParameterDescriptor -private fun maskParameterSymbol(function: IrFunction, number: Int) = - function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }.symbol - -private fun markerParameterDescriptor(descriptor: FunctionDescriptor) = descriptor.valueParameters.single { it.name == kConstructorMarkerName } - -private fun nullConst(expression: IrElement, type: KotlinType): IrExpression? { - when { - KotlinBuiltIns.isFloat(type) -> return IrConstImpl.float (expression.startOffset, expression.endOffset, type, 0.0F) - KotlinBuiltIns.isDouble(type) -> return IrConstImpl.double (expression.startOffset, expression.endOffset, type, 0.0) - KotlinBuiltIns.isBoolean(type) -> return IrConstImpl.boolean (expression.startOffset, expression.endOffset, type, false) - KotlinBuiltIns.isByte(type) -> return IrConstImpl.byte (expression.startOffset, expression.endOffset, type, 0) - KotlinBuiltIns.isChar(type) -> return IrConstImpl.char (expression.startOffset, expression.endOffset, type, 0.toChar()) - KotlinBuiltIns.isShort(type) -> return IrConstImpl.short (expression.startOffset, expression.endOffset, type, 0) - KotlinBuiltIns.isInt(type) -> return IrConstImpl.int (expression.startOffset, expression.endOffset, type, 0) - KotlinBuiltIns.isLong(type) -> return IrConstImpl.long (expression.startOffset, expression.endOffset, type, 0) - else -> return IrConstImpl.constNull (expression.startOffset, expression.endOffset, type.builtIns.nullableNothingType) - } -} - -class DefaultParameterInjector constructor(val context: CommonBackendContext): BodyLoweringPass { - override fun lower(irBody: IrBody) { - - irBody.transformChildrenVoid(object : IrElementTransformerVoid() { - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { - super.visitDelegatingConstructorCall(expression) - val descriptor = expression.descriptor - if (!descriptor.needsDefaultArgumentsLowering) - return expression - val argumentsCount = argumentCount(expression) - if (argumentsCount == descriptor.valueParameters.size) - return expression - val (symbolForCall, params) = parametersForCall(expression) - return IrDelegatingConstructorCallImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - symbol = symbolForCall as IrConstructorSymbol, - descriptor = symbolForCall.descriptor) - .apply { - params.forEach { - log("call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}") - putValueArgument(it.first.index, it.second) - } - dispatchReceiver = expression.dispatchReceiver - } - - } - - override fun visitCall(expression: IrCall): IrExpression { - super.visitCall(expression) - val functionDescriptor = expression.descriptor - - if (!functionDescriptor.needsDefaultArgumentsLowering) - return expression - - val argumentsCount = argumentCount(expression) - if (argumentsCount == functionDescriptor.valueParameters.size) - return expression - val (symbol, params) = parametersForCall(expression) - val descriptor = symbol.descriptor - descriptor.typeParameters.forEach { log("$descriptor [${it.index}]: $it") } - descriptor.original.typeParameters.forEach { log("${descriptor.original}[${it.index}] : $it") } - return IrCallImpl( - startOffset = expression.startOffset, - endOffset = expression.endOffset, - symbol = symbol, - descriptor = descriptor, - typeArguments = expression.descriptor.typeParameters.map{it to (expression.getTypeArgument(it) ?: it.defaultType) }.toMap()) - .apply { - params.forEach { - log("call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}") - putValueArgument(it.first.index, it.second) - } - expression.extensionReceiver?.apply{ - extensionReceiver = expression.extensionReceiver - } - expression.dispatchReceiver?.apply { - dispatchReceiver = expression.dispatchReceiver - } - log("call::extension@: ${ir2string(expression.extensionReceiver)}") - log("call::dispatch@: ${ir2string(expression.dispatchReceiver)}") - } - } - - private fun parametersForCall(expression: IrMemberAccessExpression): Pair>> { - val descriptor = expression.descriptor as FunctionDescriptor - val keyDescriptor = if (DescriptorUtils.isOverride(descriptor)) - DescriptorUtils.getAllOverriddenDescriptors(descriptor).first() - else - descriptor.original - val realFunction = keyDescriptor.generateDefaultsFunction(context) - val realDescriptor = realFunction.descriptor - - log("$descriptor -> $realDescriptor") - val maskValues = Array(descriptor.valueParameters.size / 32 + 1, {0}) - val params = mutableListOf>() - params.addAll(descriptor.valueParameters.mapIndexed { i, _ -> - val valueArgument = expression.getValueArgument(i) - if (valueArgument == null) { - val maskIndex = i / 32 - maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (i % 32)) - } - val valueParameterDescriptor = realDescriptor.valueParameters[i] - val pair = valueParameterDescriptor to (valueArgument ?: nullConst(expression, valueParameterDescriptor.type)) - return@mapIndexed pair - }) - maskValues.forEachIndexed { i, maskValue -> - params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int( - startOffset = irBody.startOffset, - endOffset = irBody.endOffset, - type = descriptor.builtIns.intType, - value = maskValue) - } - if (expression.descriptor is ClassConstructorDescriptor) { - val defaultArgumentMarker = context.ir.symbols.defaultConstructorMarker - params += markerParameterDescriptor(realDescriptor) to IrGetObjectValueImpl( - startOffset = irBody.startOffset, - endOffset = irBody.endOffset, - type = defaultArgumentMarker.owner.defaultType, - symbol = defaultArgumentMarker) - } - params.forEach { - log("descriptor::${realDescriptor.name.asString()}#${it.first.index}: ${it.first.name.asString()}") - } - return Pair(realFunction.symbol, params) - } - - private fun argumentCount(expression: IrMemberAccessExpression) = - expression.descriptor.valueParameters.count { expression.getValueArgument(it) != null } - }) - } - - private fun log(msg: String) = context.log{"DEFAULT-INJECTOR: $msg"} -} - -private val CallableMemberDescriptor.needsDefaultArgumentsLowering - get() = valueParameters.any { it.hasDefaultValue() } && !(this is FunctionDescriptor && isInline) - -private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendContext): IrFunction { - return context.ir.defaultParameterDeclarationsCache.getOrPut(this) { - val descriptor = when (this) { - is ClassConstructorDescriptor -> - ClassConstructorDescriptorImpl.create( - /* containingDeclaration = */ containingDeclaration, - /* annotations = */ annotations, - /* isPrimary = */ false, - /* source = */ source) - is FunctionDescriptor -> { - val name = Name.identifier("$name\$default") - - SimpleFunctionDescriptorImpl.create( - /* containingDeclaration = */ containingDeclaration, - /* annotations = */ annotations, - /* name = */ name, - /* kind = */ CallableMemberDescriptor.Kind.SYNTHESIZED, - /* source = */ source) - } - else -> TODO("FIXME: $this") - } - - val syntheticParameters = MutableList(valueParameters.size / 32 + 1) { i -> - valueParameter(descriptor, valueParameters.size + i, parameterMaskName(i), descriptor.builtIns.intType) - } - if (this is ClassConstructorDescriptor) { - syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1, - kConstructorMarkerName, - context.ir.symbols.defaultConstructorMarker.owner.defaultType) - } - else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { - syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1, - "handler".synthesizedName, - context.ir.symbols.any.owner.defaultType) - } - - descriptor.initialize( - /* receiverParameterType = */ extensionReceiverParameter?.type, - /* dispatchReceiverParameter = */ dispatchReceiverParameter, - /* typeParameters = */ typeParameters.map { - TypeParameterDescriptorImpl.createForFurtherModification( - /* containingDeclaration = */ descriptor, - /* annotations = */ it.annotations, - /* reified = */ it.isReified, - /* variance = */ it.variance, - /* name = */ it.name, - /* index = */ it.index, - /* source = */ it.source, - /* reportCycleError = */ null, - /* supertypeLoopsChecker = */ SupertypeLoopChecker.EMPTY - ).apply { - it.upperBounds.forEach { addUpperBound(it) } - setInitialized() - } - }, - /* unsubstitutedValueParameters = */ valueParameters.map { - ValueParameterDescriptorImpl( - containingDeclaration = descriptor, - original = null, /* ValueParameterDescriptorImpl::copy do not save original. */ - index = it.index, - annotations = it.annotations, - name = it.name, - outType = it.type, - declaresDefaultValue = false, - isCrossinline = it.isCrossinline, - isNoinline = it.isNoinline, - varargElementType = it.varargElementType, - source = it.source) - } + syntheticParameters, - /* unsubstitutedReturnType = */ returnType, - /* modality = */ Modality.FINAL, - /* visibility = */ this.visibility) - descriptor.isSuspend = this.isSuspend - context.log{"adds to cache[$this] = $descriptor"} - - val startOffset = this.startOffsetOrUndefined - val endOffset = this.endOffsetOrUndefined - - val result: IrFunction = when (descriptor) { - is ClassConstructorDescriptor -> IrConstructorImpl( - startOffset, endOffset, - DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, - descriptor - ) - - else -> IrFunctionImpl( - startOffset, endOffset, - DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, - descriptor - ) - } - - result.createParameterDeclarations() - - result - } -} - -object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER : - IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT") - -private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: KotlinType):ValueParameterDescriptor { - return ValueParameterDescriptorImpl( - containingDeclaration = descriptor, - original = null, - index = index, - annotations = Annotations.EMPTY, - name = name, - outType = type, - declaresDefaultValue = false, - isCrossinline = false, - isNoinline = false, - varargElementType = null, - source = SourceElement.NO_SOURCE - ) -} - -internal val kConstructorMarkerName = "marker".synthesizedName - -private fun parameterMaskName(number: Int) = "mask$number".synthesizedName diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/IrBuildUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/IrBuildUtils.kt deleted file mode 100644 index 841b6d11649..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/IrBuildUtils.kt +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common.lower - -import org.jetbrains.kotlin.backend.common.BackendContext -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl -import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl -import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol -import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl -import org.jetbrains.kotlin.ir.util.createParameterDeclarations -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.KotlinType - -abstract class SymbolWithIrBuilder { - - protected abstract fun buildSymbol(): S - - protected open fun doInitialize() { } - - protected abstract fun buildIr(): D - - val symbol by lazy { buildSymbol() } - - private val builtIr by lazy { buildIr() } - private var initialized: Boolean = false - - fun initialize() { - doInitialize() - initialized = true - } - - val ir: D - get() { - if (!initialized) - throw Error("Access to IR before initialization") - return builtIr - } -} - -fun BackendContext.createPropertyGetterBuilder(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, - fieldSymbol: IrFieldSymbol, type: KotlinType) - = object: SymbolWithIrBuilder() { - - override fun buildSymbol() = IrSimpleFunctionSymbolImpl( - PropertyGetterDescriptorImpl( - /* correspondingProperty = */ fieldSymbol.descriptor, - /* annotations = */ Annotations.EMPTY, - /* modality = */ Modality.FINAL, - /* visibility = */ Visibilities.PRIVATE, - /* isDefault = */ false, - /* isExternal = */ false, - /* isInline = */ false, - /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, - /* original = */ null, - /* source = */ SourceElement.NO_SOURCE - ) - ) - - override fun doInitialize() { - val descriptor = symbol.descriptor as PropertyGetterDescriptorImpl - descriptor.apply { - initialize(type) - } - } - - override fun buildIr() = IrFunctionImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - symbol = symbol).apply { - - createParameterDeclarations() - - body = createIrBuilder(this.symbol, startOffset, endOffset).irBlockBody { - +irReturn(irGetField(irGet(this@apply.dispatchReceiverParameter!!.symbol), fieldSymbol)) - } - } -} - -private fun BackendContext.createPropertySetterBuilder(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, - fieldSymbol: IrFieldSymbol, type: KotlinType) - = object: SymbolWithIrBuilder() { - - override fun buildSymbol() = IrSimpleFunctionSymbolImpl( - PropertySetterDescriptorImpl( - /* correspondingProperty = */ fieldSymbol.descriptor, - /* annotations = */ Annotations.EMPTY, - /* modality = */ Modality.FINAL, - /* visibility = */ Visibilities.PRIVATE, - /* isDefault = */ false, - /* isExternal = */ false, - /* isInline = */ false, - /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, - /* original = */ null, - /* source = */ SourceElement.NO_SOURCE - ) - ) - - lateinit var valueParameterDescriptor: ValueParameterDescriptor - - override fun doInitialize() { - val descriptor = symbol.descriptor as PropertySetterDescriptorImpl - descriptor.apply { - valueParameterDescriptor = ValueParameterDescriptorImpl( - containingDeclaration = this, - original = null, - index = 0, - annotations = Annotations.EMPTY, - name = Name.identifier("value"), - outType = type, - declaresDefaultValue = false, - isCrossinline = false, - isNoinline = false, - varargElementType = null, - source = SourceElement.NO_SOURCE - ) - - initialize(valueParameterDescriptor) - } - } - - override fun buildIr() = IrFunctionImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - symbol = symbol).apply { - - createParameterDeclarations() - - body = createIrBuilder(this.symbol, startOffset, endOffset).irBlockBody { - +irSetField(irGet(this@apply.dispatchReceiverParameter!!.symbol), fieldSymbol, irGet(this@apply.valueParameters.single().symbol)) - } - } -} - -fun BackendContext.createPropertyWithBackingFieldBuilder(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, - owner: ClassDescriptor, name: Name, type: KotlinType, isMutable: Boolean) - = object: SymbolWithIrBuilder() { - - private lateinit var getterBuilder: SymbolWithIrBuilder - private var setterBuilder: SymbolWithIrBuilder? = null - - override fun buildSymbol() = IrFieldSymbolImpl( - PropertyDescriptorImpl.create( - /* containingDeclaration = */ owner, - /* annotations = */ Annotations.EMPTY, - /* modality = */ Modality.FINAL, - /* visibility = */ Visibilities.PRIVATE, - /* isVar = */ isMutable, - /* name = */ name, - /* kind = */ CallableMemberDescriptor.Kind.DECLARATION, - /* source = */ SourceElement.NO_SOURCE, - /* lateInit = */ false, - /* isConst = */ false, - /* isHeader = */ false, - /* isImpl = */ false, - /* isExternal = */ false, - /* isDelegated = */ false - ) - ) - - override fun doInitialize() { - val descriptor = symbol.descriptor as PropertyDescriptorImpl - getterBuilder = createPropertyGetterBuilder(startOffset, endOffset, origin, symbol, type).apply { initialize() } - if (isMutable) - setterBuilder = createPropertySetterBuilder(startOffset, endOffset, origin, symbol, type).apply { initialize() } - descriptor.initialize( - /* getter = */ getterBuilder.symbol.descriptor as PropertyGetterDescriptorImpl, - /* setter = */ setterBuilder?.symbol?.descriptor as? PropertySetterDescriptorImpl) - val receiverType: KotlinType? = null - descriptor.setType(type, emptyList(), owner.thisAsReceiverParameter, receiverType) - } - - override fun buildIr(): IrProperty { - val backingField = IrFieldImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - symbol = symbol) - return IrPropertyImpl( - startOffset = startOffset, - endOffset = endOffset, - origin = origin, - isDelegated = false, - descriptor = symbol.descriptor, - backingField = backingField, - getter = getterBuilder.ir, - setter = setterBuilder?.ir) - } -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt deleted file mode 100644 index 739755a10a1..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common.lower - -import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.FileLoweringPass -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.IrProperty -import org.jetbrains.kotlin.ir.expressions.IrBlock -import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl -import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.types.KotlinType - -class LateinitLowering(val context: CommonBackendContext): FileLoweringPass { - override fun lower(irFile: IrFile) { - irFile.transformChildrenVoid(object: IrElementTransformerVoid() { - override fun visitProperty(declaration: IrProperty): IrStatement { - if (declaration.descriptor.isLateInit && declaration.descriptor.kind.isReal) - transformGetter(declaration.backingField!!.symbol, declaration.getter!!) - return declaration - } - - private fun transformGetter(backingFieldSymbol: IrFieldSymbol, getter: IrFunction) { - val type = backingFieldSymbol.descriptor.type - assert (!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" }) - val startOffset = getter.startOffset - val endOffset = getter.endOffset - val irBuilder = context.createIrBuilder(getter.symbol, startOffset, endOffset) - irBuilder.run { - val block = irBlock(type) - val resultVar = scope.createTemporaryVariable( - irGetField(irGet(getter.dispatchReceiverParameter!!.symbol), backingFieldSymbol)) - block.statements.add(resultVar) - val throwIfNull = irIfThenElse(context.builtIns.nothingType, - irNotEquals(irGet(resultVar.symbol), irNull()), - irReturn(irGet(resultVar.symbol)), - irCall(throwErrorFunction)) - block.statements.add(throwIfNull) - getter.body = IrExpressionBodyImpl(startOffset, endOffset, block) - } - } - }) - } - - private val throwErrorFunction = context.ir.symbols.ThrowUninitializedPropertyAccessException - - private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock - = IrBlockImpl(startOffset, endOffset, type) - -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt deleted file mode 100644 index 31b89b06cac..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ /dev/null @@ -1,729 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common.lower - -import org.jetbrains.kotlin.backend.common.BackendContext -import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass -import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.* -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.* -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.util.createParameterDeclarations -import org.jetbrains.kotlin.ir.util.transformFlat -import org.jetbrains.kotlin.ir.visitors.* -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.parents -import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf -import org.jetbrains.kotlin.types.KotlinType -import java.util.* - -class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContainerLoweringPass { - - private object DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE : - IrDeclarationOriginImpl("FIELD_FOR_CAPTURED_VALUE") {} - - private object STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE : - IrStatementOriginImpl("INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE") {} - - override fun lower(irDeclarationContainer: IrDeclarationContainer) { - if (irDeclarationContainer is IrDeclaration && - irDeclarationContainer.descriptor.parents.any { it is CallableDescriptor }) { - - // Lowering of non-local declarations handles all local declarations inside. - // This declaration is local and shouldn't be considered. - return - } - - // Continuous numbering across all declarations in the container. - lambdasCount = 0 - - irDeclarationContainer.declarations.transformFlat { memberDeclaration -> - // TODO: may be do the opposite - specify the list of IR elements which need not to be transformed - when (memberDeclaration) { - is IrFunction -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() - is IrProperty -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() - is IrField -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() - is IrAnonymousInitializer -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() - else -> null - } - } - } - - private var lambdasCount = 0 - - private abstract class LocalContext { - /** - * @return the expression to get the value for given descriptor, or `null` if [IrGetValue] should be used. - */ - abstract fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? - } - - private abstract class LocalContextWithClosureAsParameters : LocalContext() { - - abstract val declaration: IrFunction - open val descriptor: FunctionDescriptor - get() = declaration.descriptor - - abstract val transformedDescriptor: FunctionDescriptor - abstract val transformedDeclaration: IrFunction - - val capturedValueToParameter: MutableMap = HashMap() - - override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { - val newSymbol = capturedValueToParameter[descriptor] ?: return null - - return IrGetValueImpl(startOffset, endOffset, newSymbol) - } - } - - private class LocalFunctionContext(override val declaration: IrFunction) : LocalContextWithClosureAsParameters() { - lateinit var closure: Closure - - override lateinit var transformedDescriptor: FunctionDescriptor - override lateinit var transformedDeclaration: IrSimpleFunction - - var index: Int = -1 - - override fun toString(): String = - "LocalFunctionContext for $descriptor" - } - - private class LocalClassConstructorContext(override val declaration: IrConstructor) : LocalContextWithClosureAsParameters() { - override val descriptor: ClassConstructorDescriptor - get() = declaration.descriptor - - override lateinit var transformedDescriptor: ClassConstructorDescriptor - override lateinit var transformedDeclaration: IrConstructor - - override fun toString(): String = - "LocalClassConstructorContext for $descriptor" - } - - private class LocalClassContext(val declaration: IrClass) : LocalContext() { - val descriptor: ClassDescriptor - get() = declaration.descriptor - - lateinit var closure: Closure - - val capturedValueToField: MutableMap = HashMap() - - override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { - val field = capturedValueToField[descriptor] ?: return null - - return IrGetFieldImpl(startOffset, endOffset, field.symbol, - receiver = IrGetValueImpl(startOffset, endOffset, declaration.thisReceiver!!.symbol) - ) - } - - override fun toString(): String = - "LocalClassContext for ${descriptor}" - } - - private inner class LocalDeclarationsTransformer(val memberDeclaration: IrDeclaration) { - val localFunctions: MutableMap = LinkedHashMap() - val localClasses: MutableMap = LinkedHashMap() - val localClassConstructors: MutableMap = LinkedHashMap() - - val transformedDeclarations = mutableMapOf() - - val FunctionDescriptor.transformed: IrFunctionSymbol? - get() = transformedDeclarations[this] as IrFunctionSymbol? - - val oldParameterToNew: MutableMap = HashMap() - val newParameterToOld: MutableMap = HashMap() - val newParameterToCaptured: MutableMap = HashMap() - - fun lowerLocalDeclarations(): List? { - collectLocalDeclarations() - if (localFunctions.isEmpty() && localClasses.isEmpty()) return null - - collectClosures() - - transformDescriptors() - - rewriteDeclarations() - - val result = collectRewrittenDeclarations() - return result - } - - private fun collectRewrittenDeclarations(): ArrayList = - ArrayList(localFunctions.size + localClasses.size + 1).apply { - add(memberDeclaration) - - localFunctions.values.mapTo(this) { - val original = it.declaration - it.transformedDeclaration.apply { - this.body = original.body - - original.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> - val body = original.getDefault(argument)!! - oldParameterToNew[argument]!!.owner.defaultValue = body - } - } - } - - localClasses.values.mapTo(this) { - it.declaration - } - } - - private inner class FunctionBodiesRewriter(val localContext: LocalContext?) : IrElementTransformerVoid() { - - override fun visitClass(declaration: IrClass): IrStatement { - if (declaration.descriptor in localClasses) { - // Replace local class definition with an empty composite. - return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType) - } else { - return super.visitClass(declaration) - } - } - - override fun visitFunction(declaration: IrFunction): IrStatement { - if (declaration.descriptor in localFunctions) { - // Replace local function definition with an empty composite. - return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType) - } else { - return super.visitFunction(declaration) - } - } - - override fun visitConstructor(declaration: IrConstructor): IrStatement { - // Body is transformed separately. See loop over constructors in rewriteDeclarations(). - - val constructorContext = localClassConstructors[declaration.descriptor] - if (constructorContext != null) { - return constructorContext.transformedDeclaration.apply { - this.body = declaration.body!! - - declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> - val body = declaration.getDefault(argument)!! - oldParameterToNew[argument]!!.owner.defaultValue = body - } - } - } else { - return super.visitConstructor(declaration) - } - } - - override fun visitGetValue(expression: IrGetValue): IrExpression { - val descriptor = expression.descriptor - - localContext?.irGet(expression.startOffset, expression.endOffset, descriptor)?.let { - return it - } - - oldParameterToNew[descriptor]?.let { - return IrGetValueImpl(expression.startOffset, expression.endOffset, it) - } - - return expression - } - - override fun visitCall(expression: IrCall): IrExpression { - expression.transformChildrenVoid(this) - - val oldCallee = expression.descriptor.original - val newCallee = oldCallee.transformed ?: return expression - - val newCall = createNewCall(expression, newCallee).fillArguments(expression) - - return newCall - } - - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { - expression.transformChildrenVoid(this) - - val oldCallee = expression.descriptor.original - val newCallee = transformedDeclarations[oldCallee] as IrConstructorSymbol? ?: return expression - - val newExpression = IrDelegatingConstructorCallImpl( - expression.startOffset, expression.endOffset, - newCallee, - newCallee.descriptor, - remapTypeArguments(expression, newCallee.descriptor) - ).fillArguments(expression) - - return newExpression - } - - private fun T.fillArguments(oldExpression: IrMemberAccessExpression): T { - - mapValueParameters { newValueParameterDescriptor -> - val oldParameter = newParameterToOld[newValueParameterDescriptor] - - if (oldParameter != null) { - oldExpression.getValueArgument(oldParameter as ValueParameterDescriptor) - } else { - // The callee expects captured value as argument. - val capturedValueSymbol = - newParameterToCaptured[newValueParameterDescriptor] ?: - throw AssertionError("Non-mapped parameter $newValueParameterDescriptor") - - val capturedValueDescriptor = capturedValueSymbol.descriptor - localContext?.irGet( - oldExpression.startOffset, oldExpression.endOffset, - capturedValueDescriptor - ) ?: - // Captured value is directly available for the caller. - IrGetValueImpl(oldExpression.startOffset, oldExpression.endOffset, - oldParameterToNew[capturedValueDescriptor] ?: capturedValueSymbol) - } - - } - - dispatchReceiver = oldExpression.dispatchReceiver - extensionReceiver = oldExpression.extensionReceiver - - return this - } - - override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { - expression.transformChildrenVoid(this) - - val oldCallee = expression.descriptor.original - val newCallee = oldCallee.transformed ?: return expression - - val newCallableReference = IrFunctionReferenceImpl( - expression.startOffset, expression.endOffset, - expression.type, // TODO functional type for transformed descriptor - newCallee, - newCallee.descriptor, - remapTypeArguments(expression, newCallee.descriptor), - expression.origin - ).fillArguments(expression) - - return newCallableReference - } - - override fun visitReturn(expression: IrReturn): IrExpression { - expression.transformChildrenVoid(this) - - val oldReturnTarget = expression.returnTarget - val newReturnTarget = oldReturnTarget.transformed ?: return expression - - return IrReturnImpl(expression.startOffset, expression.endOffset, newReturnTarget, expression.value) - } - - override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression { - if (expression.descriptor in transformedDeclarations) { - TODO() - } - return super.visitDeclarationReference(expression) - } - - override fun visitDeclaration(declaration: IrDeclaration): IrStatement { - if (declaration.descriptor in transformedDeclarations) { - TODO() - } - return super.visitDeclaration(declaration) - } - } - - private fun rewriteFunctionBody(irDeclaration: IrDeclaration, localContext: LocalContext?) { - irDeclaration.transformChildrenVoid(FunctionBodiesRewriter(localContext)) - } - - private fun rewriteClassMembers(irClass: IrClass, localClassContext: LocalClassContext) { - irClass.transformChildrenVoid(FunctionBodiesRewriter(localClassContext)) - - val classDescriptor = irClass.descriptor - val constructorsCallingSuper = classDescriptor.constructors - .map { localClassConstructors[it]!! } - .filter { it.declaration.callsSuper() } - assert(constructorsCallingSuper.any(), { "Expected at least one constructor calling super; class: $classDescriptor" }) - - localClassContext.capturedValueToField.forEach { capturedValue, field -> - val startOffset = irClass.startOffset - val endOffset = irClass.endOffset - irClass.declarations.add(field) - - for (constructorContext in constructorsCallingSuper) { - val blockBody = constructorContext.declaration.body as? IrBlockBody - ?: throw AssertionError("Unexpected constructor body: ${constructorContext.declaration.body}") - val capturedValueExpression = constructorContext.irGet(startOffset, endOffset, capturedValue)!! - blockBody.statements.add(0, - IrSetFieldImpl(startOffset, endOffset, field.symbol, - IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol), - capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE)) - } - } - } - - private fun rewriteDeclarations() { - localFunctions.values.forEach { - rewriteFunctionBody(it.declaration, it) - } - - localClassConstructors.values.forEach { - rewriteFunctionBody(it.declaration, it) - } - - localClasses.values.forEach { - rewriteClassMembers(it.declaration, it) - } - - rewriteFunctionBody(memberDeclaration, null) - } - - private fun createNewCall(oldCall: IrCall, newCallee: IrFunctionSymbol) = - if (oldCall is IrCallWithShallowCopy) - oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifierSymbol) - else - IrCallImpl( - oldCall.startOffset, oldCall.endOffset, - newCallee, - newCallee.descriptor, - remapTypeArguments(oldCall, newCallee.descriptor), - oldCall.origin, oldCall.superQualifierSymbol - ) - - private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: CallableDescriptor): Map? { - val oldCallee = oldExpression.descriptor.original - - return if (oldCallee.typeParameters.isEmpty()) - null - else oldCallee.typeParameters.associateBy( - { newCallee.typeParameters[it.index] }, - { oldExpression.getTypeArgumentOrDefault(it) } - ) - } - - private fun transformDescriptors() { - localFunctions.values.forEach { - createLiftedDescriptor(it) - } - - localClasses.values.forEach { - createFieldsForCapturedValues(it) - } - - localClassConstructors.values.forEach { - createTransformedConstructorDescriptor(it) - } - } - - private fun suggestLocalName(descriptor: DeclarationDescriptor): String { - localFunctions[descriptor]?.let { - if (it.index >= 0) - return "lambda-${it.index}" - } - - return descriptor.name.asString() - } - - private fun generateNameForLiftedDeclaration(descriptor: DeclarationDescriptor, - newOwner: DeclarationDescriptor): Name = - Name.identifier( - descriptor.parentsWithSelf - .takeWhile { it != newOwner } - .toList().reversed() - .map { suggestLocalName(it) } - .joinToString(separator = "$") - ) - - private fun createLiftedDescriptor(localFunctionContext: LocalFunctionContext) { - val oldDescriptor = localFunctionContext.descriptor - - val memberOwner = memberDeclaration.descriptor.containingDeclaration!! - val newDescriptor = SimpleFunctionDescriptorImpl.create( - memberOwner, - oldDescriptor.annotations, - generateNameForLiftedDeclaration(oldDescriptor, memberOwner), - CallableMemberDescriptor.Kind.SYNTHESIZED, - oldDescriptor.source - ).apply { - isTailrec = oldDescriptor.isTailrec - isSuspend = oldDescriptor.isSuspend - // TODO: copy other properties or consider using `FunctionDescriptor.CopyBuilder`. - } - - localFunctionContext.transformedDescriptor = newDescriptor - - if (oldDescriptor.dispatchReceiverParameter != null) { - throw AssertionError("local functions must not have dispatch receiver") - } - - val newDispatchReceiverParameter = null - - // Do not substitute type parameters for now. - val newTypeParameters = oldDescriptor.typeParameters - - // TODO: consider using fields to access the closure of enclosing class. - val capturedValues = localFunctionContext.closure.capturedValues - - val newValueParameters = createTransformedValueParameters(localFunctionContext, capturedValues) - - newDescriptor.initialize( - oldDescriptor.extensionReceiverParameter?.type, - newDispatchReceiverParameter, - newTypeParameters, - newValueParameters, - oldDescriptor.returnType, - Modality.FINAL, - Visibilities.PRIVATE - ) - - oldDescriptor.extensionReceiverParameter?.let { - newParameterToOld.putAbsentOrSame(newDescriptor.extensionReceiverParameter!!, it) - } - - localFunctionContext.transformedDeclaration = with(localFunctionContext.declaration) { - IrFunctionImpl(startOffset, endOffset, origin, newDescriptor) - }.apply { - createParameterDeclarations() - recordTransformedValueParameters(localFunctionContext) - transformedDeclarations[oldDescriptor] = this.symbol - } - } - - private fun createTransformedValueParameters(localContext: LocalContextWithClosureAsParameters, - capturedValues: List) - : List { - - val oldDescriptor = localContext.descriptor - val newDescriptor = localContext.transformedDescriptor - - val closureParametersCount = capturedValues.size - val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size - - val newValueParameters = ArrayList(newValueParametersCount).apply { - capturedValues.mapIndexedTo(this) { i, capturedValue -> - createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply { - newParameterToCaptured[this] = capturedValue - } - } - - oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor -> - createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply { - newParameterToOld.putAbsentOrSame(this, oldValueParameterDescriptor) - } - } - } - return newValueParameters - } - - private fun IrFunction.recordTransformedValueParameters(localContext: LocalContextWithClosureAsParameters) { - - valueParameters.forEach { - val capturedValue = newParameterToCaptured[it.descriptor] - if (capturedValue != null) { - localContext.capturedValueToParameter[capturedValue.descriptor] = it.symbol - } - } - - (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).forEach { - val oldParameter = newParameterToOld[it.descriptor] - if (oldParameter != null) { - oldParameterToNew.putAbsentOrSame(oldParameter, it.symbol) - } - } - - } - - private fun createTransformedConstructorDescriptor(constructorContext: LocalClassConstructorContext) { - val oldDescriptor = constructorContext.descriptor - val localClassContext = localClasses[oldDescriptor.containingDeclaration]!! - val newDescriptor = ClassConstructorDescriptorImpl.create( - localClassContext.descriptor, - Annotations.EMPTY, oldDescriptor.isPrimary, oldDescriptor.source) - - constructorContext.transformedDescriptor = newDescriptor - - // Do not substitute type parameters for now. - val newTypeParameters = oldDescriptor.typeParameters - - val capturedValues = localClasses[oldDescriptor.containingDeclaration]!!.closure.capturedValues - - val newValueParameters = createTransformedValueParameters(constructorContext, capturedValues) - - newDescriptor.initialize( - newValueParameters, - Visibilities.PRIVATE, - newTypeParameters - ) - newDescriptor.returnType = oldDescriptor.returnType - - oldDescriptor.dispatchReceiverParameter?.let { - newParameterToOld.putAbsentOrSame(newDescriptor.dispatchReceiverParameter!!, it) - } - - oldDescriptor.extensionReceiverParameter?.let { - throw AssertionError("constructors can't have extension receiver") - } - - constructorContext.transformedDeclaration = with(constructorContext.declaration) { - IrConstructorImpl(startOffset, endOffset, origin, newDescriptor) - }.apply { - createParameterDeclarations() - recordTransformedValueParameters(constructorContext) - transformedDeclarations[oldDescriptor] = this.symbol - } - } - - private fun createFieldsForCapturedValues(localClassContext: LocalClassContext) { - val classDescriptor = localClassContext.descriptor - - localClassContext.closure.capturedValues.forEach { capturedValue -> - val fieldDescriptor = PropertyDescriptorImpl.create( - classDescriptor, - Annotations.EMPTY, - Modality.FINAL, - Visibilities.PRIVATE, - /* isVar = */ false, - suggestNameForCapturedValue(capturedValue.descriptor), - CallableMemberDescriptor.Kind.SYNTHESIZED, - SourceElement.NO_SOURCE, - /* lateInit = */ false, - /* isConst = */ false, - /* isHeader = */ false, - /* isImpl = */ false, - /* isExternal = */ false, - /* isDelegated = */ false) - - fieldDescriptor.initialize(/* getter = */ null, /* setter = */ null) - - val extensionReceiverParameter: ReceiverParameterDescriptor? = null - - fieldDescriptor.setType( - capturedValue.descriptor.type, - emptyList(), - classDescriptor.thisAsReceiverParameter, - extensionReceiverParameter) - - localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl( - localClassContext.declaration.startOffset, localClassContext.declaration.endOffset, - DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE, - fieldDescriptor - ) - } - } - - private fun MutableMap.putAbsentOrSame(key: K, value: V) { - val current = this.getOrPut(key, { value }) - - if (current != value) { - error("$current != $value") - } - } - - private fun suggestNameForCapturedValue(valueDescriptor: ValueDescriptor): Name = - if (valueDescriptor.name.isSpecial) { - val oldNameStr = valueDescriptor.name.asString() - oldNameStr.substring(1, oldNameStr.length - 1).synthesizedName - } else - valueDescriptor.name - - private fun createUnsubstitutedCapturedValueParameter( - newParameterOwner: CallableMemberDescriptor, - valueDescriptor: ValueDescriptor, - index: Int - ): ValueParameterDescriptor = - ValueParameterDescriptorImpl( - newParameterOwner, null, index, - valueDescriptor.annotations, - suggestNameForCapturedValue(valueDescriptor), - valueDescriptor.type, - false, false, false, null, valueDescriptor.source - ) - - private fun createUnsubstitutedParameter( - newParameterOwner: CallableMemberDescriptor, - valueParameterDescriptor: ValueParameterDescriptor, - newIndex: Int - ): ValueParameterDescriptor = - valueParameterDescriptor.copy(newParameterOwner, valueParameterDescriptor.name, newIndex) - - - private fun collectClosures() { - val annotator = ClosureAnnotator(memberDeclaration) - localFunctions.forEach { descriptor, context -> - context.closure = annotator.getFunctionClosure(descriptor) - } - - localClasses.forEach { descriptor, context -> - context.closure = annotator.getClassClosure(descriptor) - } - } - - private fun collectLocalDeclarations() { - memberDeclaration.acceptChildrenVoid(object : IrElementVisitorVoid { - - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - private fun DeclarationDescriptor.declaredInFunction() = when (this.containingDeclaration) { - is CallableDescriptor -> true - is ClassDescriptor -> false - is PackageFragmentDescriptor -> false - else -> TODO(this.toString() + "\n" + this.containingDeclaration.toString()) - } - - override fun visitFunction(declaration: IrFunction) { - declaration.acceptChildrenVoid(this) - - val descriptor = declaration.descriptor - - if (descriptor.declaredInFunction()) { - val localFunctionContext = LocalFunctionContext(declaration) - - localFunctions[descriptor] = localFunctionContext - - if (descriptor.name.isSpecial) { - localFunctionContext.index = lambdasCount++ - } - } - - } - - override fun visitConstructor(declaration: IrConstructor) { - declaration.acceptChildrenVoid(this) - - val descriptor = declaration.descriptor - assert(!descriptor.declaredInFunction()) - - if (descriptor.constructedClass.isInner) return - - localClassConstructors[descriptor] = LocalClassConstructorContext(declaration) - } - - override fun visitClass(declaration: IrClass) { - declaration.acceptChildrenVoid(this) - - val descriptor = declaration.descriptor - - if (descriptor.isInner) return - - // Local nested classes can only be inner. - assert(descriptor.declaredInFunction()) - - val localClassContext = LocalClassContext(declaration) - localClasses[descriptor] = localClassContext - } - }) - } - } - -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt deleted file mode 100644 index de849c39836..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common.lower - -import org.jetbrains.kotlin.backend.common.BackendContext -import org.jetbrains.kotlin.backend.common.atMostOne -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl -import org.jetbrains.kotlin.incremental.components.LookupLocation -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin -import org.jetbrains.kotlin.ir.expressions.IrTypeOperator -import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol -import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy -import org.jetbrains.kotlin.resolve.OverridingUtil -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny -import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter -import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.utils.Printer - -class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContext(backendContext.irBuiltIns) - -class DeclarationIrBuilder( - backendContext: BackendContext, - symbol: IrSymbol, - startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET -) : IrBuilderWithScope( - IrLoweringContext(backendContext), - Scope(symbol), - startOffset, - endOffset -) - -fun BackendContext.createIrBuilder(symbol: IrSymbol, - startOffset: Int = UNDEFINED_OFFSET, - endOffset: Int = UNDEFINED_OFFSET) = - DeclarationIrBuilder(this, symbol, startOffset, endOffset) - - -fun T.at(element: IrElement) = this.at(element.startOffset, element.endOffset) - -/** - * Builds [IrBlock] to be used instead of given expression. - */ -inline fun IrGeneratorWithScope.irBlock(expression: IrExpression, origin: IrStatementOrigin? = null, - resultType: KotlinType? = expression.type, - body: IrBlockBuilder.() -> Unit) = - this.irBlock(expression.startOffset, expression.endOffset, origin, resultType, body) - -inline fun IrGeneratorWithScope.irBlockBody(irElement: IrElement, body: IrBlockBodyBuilder.() -> Unit) = - this.irBlockBody(irElement.startOffset, irElement.endOffset, body) - -fun IrBuilderWithScope.irIfThen(condition: IrExpression, thenPart: IrExpression) = - IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, thenPart, null) - -fun IrBuilderWithScope.irNot(arg: IrExpression) = - primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL, arg) - -fun IrBuilderWithScope.irThrow(arg: IrExpression) = - IrThrowImpl(startOffset, endOffset, context.builtIns.nothingType, arg) - -fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) = - IrCatchImpl( - startOffset, endOffset, - catchParameter - ) - -fun IrBuilderWithScope.irCast(arg: IrExpression, type: KotlinType, typeOperand: KotlinType) = - IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.CAST, typeOperand, arg) - -fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) = - IrTypeOperatorCallImpl(startOffset, endOffset, context.builtIns.unitType, - IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.builtIns.unitType, arg) - -fun IrBuilderWithScope.irGetField(receiver: IrExpression, symbol: IrFieldSymbol) = - IrGetFieldImpl(startOffset, endOffset, symbol, receiver) - -fun IrBuilderWithScope.irSetField(receiver: IrExpression, symbol: IrFieldSymbol, value: IrExpression) = - IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value) - -open class IrBuildingTransformer(private val context: BackendContext) : IrElementTransformerVoid() { - private var currentBuilder: IrBuilderWithScope? = null - - protected val builder: IrBuilderWithScope - get() = currentBuilder!! - - private inline fun withBuilder(symbol: IrSymbol, block: () -> T): T { - val oldBuilder = currentBuilder - currentBuilder = context.createIrBuilder(symbol) - return try { - block() - } finally { - currentBuilder = oldBuilder - } - } - - override fun visitFunction(declaration: IrFunction): IrStatement { - withBuilder(declaration.symbol) { - return super.visitFunction(declaration) - } - } - - override fun visitField(declaration: IrField): IrStatement { - withBuilder(declaration.symbol) { - // Transforms initializer: - return super.visitField(declaration) - } - } - - override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement { - withBuilder(declaration.symbol) { - return super.visitAnonymousInitializer(declaration) - } - } -} - -fun computeOverrides(current: ClassDescriptor, functionsFromCurrent: List): List { - - val result = mutableListOf() - - val allSuperDescriptors = current.typeConstructor.supertypes - .flatMap { it.memberScope.getContributedDescriptors() } - .filterIsInstance() - - for ((name, group) in allSuperDescriptors.groupBy { it.name }) { - OverridingUtil.generateOverridesInFunctionGroup( - name, - /* membersFromSupertypes = */ group, - /* membersFromCurrent = */ functionsFromCurrent.filter { it.name == name }, - current, - object : NonReportingOverrideStrategy() { - override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) { - result.add(fakeOverride) - } - - override fun conflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) { - error("Conflict in scope of $current: $fromSuper vs $fromCurrent") - } - } - ) - } - - return result -} - -class SimpleMemberScope(val members: List) : MemberScopeImpl() { - - override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = - members.filterIsInstance() - .atMostOne { it.name == name } - - override fun getContributedVariables(name: Name, location: LookupLocation): Collection = - members.filterIsInstance() - .filter { it.name == name } - - override fun getContributedFunctions(name: Name, location: LookupLocation): Collection = - members.filterIsInstance() - .filter { it.name == name } - - override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean): Collection = - members.filter { kindFilter.accepts(it) && nameFilter(it.name) } - - override fun printScopeStructure(p: Printer) = TODO("not implemented") - -} - -fun IrConstructor.callsSuper(): Boolean { - val constructedClass = descriptor.constructedClass - val superClass = constructedClass.getSuperClassOrAny() - var callsSuper = false - var numberOfCalls = 0 - acceptChildrenVoid(object : IrElementVisitorVoid { - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitClass(declaration: IrClass) { - // Skip nested - } - - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) { - assert(++numberOfCalls == 1, { "More than one delegating constructor call: $descriptor" }) - if (expression.descriptor.constructedClass == superClass) - callsSuper = true - else if (expression.descriptor.constructedClass != constructedClass) - throw AssertionError("Expected either call to another constructor of the class being constructed or" + - " call to super class constructor. But was: ${expression.descriptor.constructedClass}") - } - }) - assert(numberOfCalls == 1, { "Expected exactly one delegating constructor call but none encountered: $descriptor" }) - return callsSuper -} - -fun ParameterDescriptor.copyAsValueParameter(newOwner: CallableDescriptor, index: Int) - = when (this) { - is ValueParameterDescriptor -> this.copy(newOwner, name, index) - is ReceiverParameterDescriptor -> ValueParameterDescriptorImpl( - containingDeclaration = newOwner, - original = null, - index = index, - annotations = annotations, - name = name, - outType = type, - declaresDefaultValue = false, - isCrossinline = false, - isNoinline = false, - varargElementType = null, - source = source - ) - else -> throw Error("Unexpected parameter descriptor: $this") -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt deleted file mode 100644 index 83b708cddd9..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common.lower - -import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.FileLoweringPass -import org.jetbrains.kotlin.backend.common.atMostOne -import org.jetbrains.kotlin.builtins.PrimitiveType -import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.util.constructors -import org.jetbrains.kotlin.ir.util.functions -import org.jetbrains.kotlin.ir.util.type -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.KotlinType - - -/** - * This lowering pass replaces [IrStringConcatenation]s with StringBuilder appends. - */ -internal class StringConcatenationLowering(val context: CommonBackendContext) : FileLoweringPass { - override fun lower(irFile: IrFile) { - irFile.transformChildrenVoid(StringConcatenationTransformer(this)) - } -} - -private class StringConcatenationTransformer(val lower: StringConcatenationLowering) : IrElementTransformerVoid() { - - private val buildersStack = mutableListOf() - private val context = lower.context - private val builtIns = context.builtIns - - private val typesWithSpecialAppendFunction = - PrimitiveType.values().map { builtIns.getPrimitiveKotlinType(it) } + builtIns.stringType - - private val nameToString = Name.identifier("toString") - private val nameAppend = Name.identifier("append") - - private val stringBuilder = context.ir.symbols.stringBuilder - - //TODO: calculate and pass string length to the constructor. - private val constructor = stringBuilder.constructors.single { - it.owner.valueParameters.size == 0 - } - - private val toStringFunction = stringBuilder.functions.single { - it.owner.valueParameters.size == 0 && it.descriptor.name == nameToString - } - private val defaultAppendFunction = stringBuilder.functions.single { - it.descriptor.name == nameAppend && - it.owner.valueParameters.size == 1 && - it.owner.valueParameters.single().type == builtIns.nullableAnyType - } - - - private val appendFunctions: Map = - typesWithSpecialAppendFunction.map { type -> - type to stringBuilder.functions.toList().atMostOne { - it.descriptor.name == nameAppend && - it.owner.valueParameters.size == 1 && - it.owner.valueParameters.single().type == type - } - }.toMap() - - private fun typeToAppendFunction(type : KotlinType) : IrFunctionSymbol { - return appendFunctions[type]?:defaultAppendFunction - } - - override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression { - assert(!buildersStack.isEmpty()) - - expression.transformChildrenVoid(this) - val blockBuilder = buildersStack.last() - return blockBuilder.irBlock(expression) { - val stringBuilderImpl = irTemporary(irCall(constructor)).symbol - expression.arguments.forEach { arg -> - val appendFunction = typeToAppendFunction(arg.type) - +irCall(appendFunction).apply { - dispatchReceiver = irGet(stringBuilderImpl) - putValueArgument(0, arg) - } - } - +irCall(toStringFunction).apply { - dispatchReceiver = irGet(stringBuilderImpl) - } - } - } - - override fun visitDeclaration(declaration: IrDeclaration): IrStatement { - if (declaration !is IrSymbolDeclaration<*>) { - return super.visitDeclaration(declaration) - } - - with(declaration) { - buildersStack.add( - context.createIrBuilder(declaration.symbol, startOffset, endOffset) - ) - transformChildrenVoid(this@StringConcatenationTransformer) - buildersStack.removeAt(buildersStack.lastIndex) - return this@with - } - } -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt deleted file mode 100644 index 2f0e3fa6702..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common.lower - -import org.jetbrains.kotlin.backend.common.* -import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl -import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol -import org.jetbrains.kotlin.ir.symbols.IrValueSymbol -import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol -import org.jetbrains.kotlin.ir.util.explicitParameters -import org.jetbrains.kotlin.ir.util.getArgumentsWithSymbols -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid - -/** - * This pass lowers tail recursion calls in `tailrec` functions. - * - * Note: it currently can't handle local functions and classes declared in default arguments. - * See [deepCopyWithVariables]. - */ -class TailrecLowering(val context: BackendContext) : FunctionLoweringPass { - override fun lower(irFunction: IrFunction) { - lowerTailRecursionCalls(context, irFunction) - } -} - -private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunction) { - val tailRecursionCalls = collectTailRecursionCalls(irFunction) - if (tailRecursionCalls.isEmpty()) { - return - } - - val oldBody = irFunction.body as IrBlockBody - val builder = context.createIrBuilder(irFunction.symbol).at(oldBody) - - val parameters = irFunction.explicitParameters - - irFunction.body = builder.irBlockBody { - // Define variables containing current values of parameters: - val parameterToVariable = parameters.associate { - it to irTemporaryVar(irGet(it), nameHint = it.suggestVariableName()).symbol - } - // (these variables are to be updated on any tail call). - - +irWhile().apply { - val loop = this - condition = irTrue() - - body = irBlock(startOffset, endOffset, resultType = context.builtIns.unitType) { - // Read variables containing current values of parameters: - val parameterToNew = parameters.associate { - val variable = parameterToVariable[it]!! - it to irTemporary(irGet(variable), nameHint = it.suggestVariableName()).symbol - } - - val transformer = BodyTransformer(builder, irFunction, loop, - parameterToNew, parameterToVariable, tailRecursionCalls) - - oldBody.statements.forEach { - +it.transform(transformer, null) - } - - +irBreak(loop) - } - } - } -} - -private class BodyTransformer( - val builder: IrBuilderWithScope, - val irFunction: IrFunction, - val loop: IrLoop, - val parameterToNew: Map, - val parameterToVariable: Map, - val tailRecursionCalls: Set -) : IrElementTransformerVoid() { - - val parameters = irFunction.explicitParameters - - override fun visitGetValue(expression: IrGetValue): IrExpression { - expression.transformChildrenVoid(this) - val value = parameterToNew[expression.symbol] ?: return expression - return builder.at(expression).irGet(value) - } - - override fun visitCall(expression: IrCall): IrExpression { - expression.transformChildrenVoid(this) - if (expression !in tailRecursionCalls) { - return expression - } - - return builder.at(expression).genTailCall(expression) - } - - private fun IrBuilderWithScope.genTailCall(expression: IrCall) = this.irBlock(expression) { - // Get all specified arguments: - val parameterToArgument = expression.getArgumentsWithSymbols().map { (parameter, argument) -> - parameter to argument - } - - // For each specified argument set the corresponding variable to it in the correct order: - parameterToArgument.forEach { (parameter, argument) -> - at(argument) - // Note that argument can use values of parameters, so it is important that - // references to parameters are mapped using `parameterToNew`, not `parameterToVariable`. - +irSetVar(parameterToVariable[parameter]!!, argument) - } - - val specifiedParameters = parameterToArgument.map { (parameter, _) -> parameter }.toSet() - - // For each unspecified argument set the corresponding variable to default: - parameters.filter { it !in specifiedParameters }.forEach { parameter -> - - val originalDefaultValue = parameter.owner.defaultValue?.expression ?: - throw Error("no argument specified for $parameter") - - // Copy default value, mapping parameters to variables containing freshly computed arguments: - val defaultValue = originalDefaultValue - .deepCopyWithVariables() - .transform(object : IrElementTransformerVoid() { - - override fun visitGetValue(expression: IrGetValue): IrExpression { - expression.transformChildrenVoid(this) - - val variableSymbol = parameterToVariable[expression.symbol] ?: return expression - return IrGetValueImpl( - expression.startOffset, expression.endOffset, - variableSymbol, expression.origin - ) - } - }, data = null) - - +irSetVar(parameterToVariable[parameter]!!, defaultValue) - } - - // Jump to the entry: - +irContinue(loop) - } -} - -private fun IrValueParameterSymbol.suggestVariableName(): String = if (descriptor.name.isSpecial) { - val oldNameStr = descriptor.name.asString() - "$" + oldNameStr.substring(1, oldNameStr.length - 1) -} else { - descriptor.name.identifier -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/VarargLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/VarargLowering.kt deleted file mode 100644 index f08e2956dba..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/VarargLowering.kt +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.common.lower - -import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass -import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedString -import org.jetbrains.kotlin.backend.common.ir.ir2string -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.builtins.PrimitiveType -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol -import org.jetbrains.kotlin.ir.util.constructors -import org.jetbrains.kotlin.ir.util.defaultType -import org.jetbrains.kotlin.ir.util.functions -import org.jetbrains.kotlin.ir.util.getPropertyGetter -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.util.OperatorNameConventions - - -class VarargInjectionLowering internal constructor(val context: CommonBackendContext): DeclarationContainerLoweringPass { - override fun lower(irDeclarationContainer: IrDeclarationContainer) { - irDeclarationContainer.declarations.forEach{ - when (it) { - is IrField -> lower(it.symbol, it.initializer) - is IrFunction -> lower(it.symbol, it.body) - is IrProperty -> { - it.backingField?.let { field -> - lower(field.symbol, field) - } - it.getter?.let { getter -> - lower(getter.symbol, getter) - } - it.setter?.let { setter -> - lower(setter.symbol, setter) - } - } - } - } - } - - private fun lower(owner: IrSymbol, element: IrElement?) { - element?.transformChildrenVoid(object: IrElementTransformerVoid() { - val transformer = this - - private fun replaceEmptyParameterWithEmptyArray(expression: IrMemberAccessExpression) { - log("call of: ${expression.descriptor}") - context.createIrBuilder(owner, expression.startOffset, expression.endOffset).apply { - expression.descriptor.valueParameters.forEach { - log("varargElementType: ${it.varargElementType} expr: ${ir2string(expression.getValueArgument(it))}") - } - expression.descriptor.valueParameters.filter { it.varargElementType != null && expression.getValueArgument(it) == null }.forEach { - expression.putValueArgument(it.index, - IrVarargImpl(startOffset = startOffset, - endOffset = endOffset, - type = it.type, - varargElementType = it.varargElementType!!) - ) - } - } - expression.transformChildrenVoid(this) - } - - override fun visitCall(expression: IrCall): IrExpression { - replaceEmptyParameterWithEmptyArray(expression) - return expression - } - - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { - replaceEmptyParameterWithEmptyArray(expression) - return expression - } - - override fun visitVararg(expression: IrVararg): IrExpression { - expression.transformChildrenVoid(transformer) - val hasSpreadElement = hasSpreadElement(expression) - if (!hasSpreadElement && expression.elements.all { it is IrConst<*> && KotlinBuiltIns.isString(it.type) }) { - log("skipped vararg expression because it's string array literal") - return expression - } - val irBuilder = context.createIrBuilder(owner, expression.startOffset, expression.endOffset) - irBuilder.run { - val type = expression.varargElementType - log("$expression: array type:$type, is array of primitives ${!KotlinBuiltIns.isArray(expression.type)}") - val arrayHandle = arrayType(expression.type) - val arrayConstructor = arrayHandle.arraySymbol.constructors.find { it.owner.valueParameters.size == 1 }!! - val block = irBlock(arrayHandle.arraySymbol.owner.defaultType) - val arrayConstructorCall = if (arrayConstructor.owner.typeParameters.isEmpty()) { - irCall(arrayConstructor) - } else { - irCall(arrayConstructor, listOf(type)) - } - - - val vars = expression.elements.map { - val initVar = scope.createTemporaryVariable( - (it as? IrSpreadElement)?.expression ?: it as IrExpression, - "elem".synthesizedString, true) - block.statements.add(initVar) - it to initVar - }.toMap() - arrayConstructorCall.putValueArgument(0, calculateArraySize(arrayHandle, hasSpreadElement, scope, expression, vars)) - val arrayTmpVariable = scope.createTemporaryVariable(arrayConstructorCall, "array".synthesizedString, true) - val indexTmpVariable = scope.createTemporaryVariable(kIntZero, "index".synthesizedString, true) - block.statements.add(arrayTmpVariable) - if (hasSpreadElement) { - block.statements.add(indexTmpVariable) - } - expression.elements.forEachIndexed { i, element -> - irBuilder.startOffset = element.startOffset - irBuilder.endOffset = element.endOffset - irBuilder.apply { - log("element:$i> ${ir2string(element)}") - val dst = vars[element]!! - if (element !is IrSpreadElement) { - val setArrayElementCall = irCall(arrayHandle.setMethodSymbol) - setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.symbol) - setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.symbol) else irConstInt(i)) - setArrayElementCall.putValueArgument(1, irGet(dst.symbol)) - block.statements.add(setArrayElementCall) - if (hasSpreadElement) { - block.statements.add(incrementVariable(indexTmpVariable.symbol, kIntOne)) - } - } else { - val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst.symbol)), "length".synthesizedString) - block.statements.add(arraySizeVariable) - val copyCall = irCall(arrayHandle.copyRangeToSymbol).apply { - extensionReceiver = irGet(dst.symbol) - putValueArgument(0, irGet(arrayTmpVariable.symbol)) /* destination */ - putValueArgument(1, kIntZero) /* fromIndex */ - putValueArgument(2, irGet(arraySizeVariable.symbol)) /* toIndex */ - putValueArgument(3, irGet(indexTmpVariable.symbol)) /* destinationIndex */ - } - block.statements.add(copyCall) - block.statements.add(incrementVariable(indexTmpVariable.symbol, - irGet(arraySizeVariable.symbol))) - log("element:$i:spread element> ${ir2string(element.expression)}") - } - } - } - block.statements.add(irGet(arrayTmpVariable.symbol)) - return block - } - } - }) - } - - private val symbols = context.ir.symbols - private val intPlusInt = symbols.intPlusInt - - private fun arrayType(type: KotlinType): ArrayHandle = when { - KotlinBuiltIns.isPrimitiveArray(type) -> { - val primitiveType = KotlinBuiltIns.getPrimitiveArrayType(type.constructor.declarationDescriptor!!) - when (primitiveType) { - PrimitiveType.BYTE -> kByteArrayHandler - PrimitiveType.SHORT -> kShortArrayHandler - PrimitiveType.CHAR -> kCharArrayHandler - PrimitiveType.INT -> kIntArrayHandler - PrimitiveType.LONG -> kLongArrayHandler - PrimitiveType.FLOAT -> kFloatArrayHandler - PrimitiveType.DOUBLE -> kDoubleArrayHandler - PrimitiveType.BOOLEAN -> kBooleanArrayHandler - else -> TODO("unsupported type: $primitiveType") - } - } - else -> kArrayHandler - } - - private fun IrBuilderWithScope.intPlus() = irCall(intPlusInt) - private fun IrBuilderWithScope.increment(expression: IrExpression, value: IrExpression): IrExpression { - return intPlus().apply { - dispatchReceiver = expression - putValueArgument(0, value) - } - } - - private fun IrBuilderWithScope.incrementVariable(symbol: IrVariableSymbol, value: IrExpression): IrExpression { - return irSetVar(symbol, intPlus().apply { - dispatchReceiver = irGet(symbol) - putValueArgument(0, value) - }) - } - private fun calculateArraySize(arrayHandle: ArrayHandle, hasSpreadElement: Boolean, scope:Scope, expression: IrVararg, vars: Map): IrExpression? { - context.createIrBuilder(scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset).run { - if (!hasSpreadElement) - return irConstInt(expression.elements.size) - val notSpreadElementCount = expression.elements.filter { it !is IrSpreadElement}.size - val initialValue = irConstInt(notSpreadElementCount) as IrExpression - return vars.filter{it.key is IrSpreadElement}.toList().fold( initial = initialValue) { result, it -> - val arraySize = irArraySize(arrayHandle, irGet(it.second.symbol)) - increment(result, arraySize) - } - } - } - - private fun IrBuilderWithScope.irArraySize(arrayHandle: ArrayHandle, expression: IrExpression): IrExpression { - val arraySize = irCall(arrayHandle.sizeGetterSymbol).apply { - dispatchReceiver = expression - } - return arraySize - } - - - private fun hasSpreadElement(expression: IrVararg?) = expression?.elements?.any { it is IrSpreadElement }?:false - - private fun log(msg:String) { - context.log{"VARARG-INJECTOR: $msg"} - } - - data class ArrayHandle(val arraySymbol: IrClassSymbol, - val setMethodSymbol: IrFunctionSymbol, - val sizeGetterSymbol: IrFunctionSymbol, - val copyRangeToSymbol: IrFunctionSymbol) - - val kByteArrayHandler = handle(symbols.byteArray) - val kCharArrayHandler = handle(symbols.charArray) - val kShortArrayHandler = handle(symbols.shortArray) - val kIntArrayHandler = handle(symbols.intArray) - val kLongArrayHandler = handle(symbols.longArray) - val kFloatArrayHandler = handle(symbols.floatArray) - val kDoubleArrayHandler = handle(symbols.doubleArray) - val kBooleanArrayHandler = handle(symbols.booleanArray) - val kArrayHandler = handle(symbols.array) - - private fun handle(symbol: IrClassSymbol) = ArrayHandle( - arraySymbol = symbol, - setMethodSymbol = symbol.functions.single { it.descriptor.name == OperatorNameConventions.SET }, - sizeGetterSymbol = symbol.getPropertyGetter("size")!!, - copyRangeToSymbol = symbols.copyRangeTo[symbol.descriptor]!! - ) - -} - -private fun IrBuilderWithScope.irConstInt(value: Int): IrConst = IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, value) -private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock = IrBlockImpl(startOffset, endOffset, type) -private val IrBuilderWithScope.kIntZero get() = irConstInt(0) -private val IrBuilderWithScope.kIntOne get() = irConstInt(1) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EscapeAnalysis.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EscapeAnalysis.kt index 076a5cc3689..b6e01821e04 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EscapeAnalysis.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EscapeAnalysis.kt @@ -24,7 +24,6 @@ import org.jetbrains.kotlin.backend.common.peek import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.konan.descriptors.target -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock import org.jetbrains.kotlin.backend.konan.ir.IrSuspendableExpression import org.jetbrains.kotlin.backend.konan.ir.IrSuspensionPoint import org.jetbrains.kotlin.backend.konan.llvm.* diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt index a80cd44336f..d766f4edde6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt @@ -16,83 +16,21 @@ package org.jetbrains.kotlin.backend.konan.ir -import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor -import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.SourceManager import org.jetbrains.kotlin.ir.SourceRangeInfo import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner import org.jetbrains.kotlin.ir.declarations.IrVariable -import org.jetbrains.kotlin.ir.expressions.IrBlock import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin -import org.jetbrains.kotlin.ir.expressions.impl.IrContainerExpressionBase import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase -import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol import org.jetbrains.kotlin.ir.symbols.IrFileSymbol -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrBindableSymbolBase import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -import org.jetbrains.kotlin.konan.file.* +import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.types.KotlinType -//-----------------------------------------------------------------------------// - -interface IrReturnableBlockSymbol : IrFunctionSymbol, IrBindableSymbol - -interface IrReturnableBlock: IrBlock, IrSymbolOwner { - override val symbol: IrReturnableBlockSymbol - val descriptor: FunctionDescriptor - val sourceFileName: String -} - -class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor) : - IrBindableSymbolBase(descriptor), - IrReturnableBlockSymbol - -class IrReturnableBlockImpl(startOffset: Int, endOffset: Int, type: KotlinType, - override val symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin? = null, override val sourceFileName: String = "no source file") - : IrContainerExpressionBase(startOffset, endOffset, type, origin), IrReturnableBlock { - override val descriptor = symbol.descriptor - - constructor(startOffset: Int, endOffset: Int, type: KotlinType, - symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin?, statements: List, sourceFileName: String = "no source file") : - this(startOffset, endOffset, type, symbol, origin, sourceFileName) { - this.statements.addAll(statements) - } - - constructor(startOffset: Int, endOffset: Int, type: KotlinType, - descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null, sourceFileName: String = "no source file") : - this(startOffset, endOffset, type, IrReturnableBlockSymbolImpl(descriptor), origin, sourceFileName) - - constructor(startOffset: Int, endOffset: Int, type: KotlinType, - descriptor: FunctionDescriptor, origin: IrStatementOrigin?, statements: List, sourceFileName: String = "no source file") : - this(startOffset, endOffset, type, descriptor, origin, sourceFileName) { - this.statements.addAll(statements) - } - - init { - symbol.bind(this) - } - - override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitBlock(this, data) - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - statements.forEach { it.accept(visitor, data) } - } - - override fun transformChildren(transformer: IrElementTransformer, data: D) { - statements.forEachIndexed { i, irStatement -> - statements[i] = irStatement.transform(transformer, data) - } - } -} - //-----------------------------------------------------------------------------// /** * TODO diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index d3c8a3a18f9..e726bfa227e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptorBase import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl import org.jetbrains.kotlin.ir.util.getArguments import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt index fb6f6fde5cd..60073b84876 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt @@ -4,9 +4,6 @@ import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockSymbol -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockSymbolImpl import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl @@ -21,6 +18,8 @@ import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt index f80acea08f5..8eadbc0af9a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt @@ -24,7 +24,6 @@ import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ValueDescriptor @@ -37,6 +36,7 @@ import org.jetbrains.kotlin.ir.declarations.getDefault import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrMemberAccessExpressionBase +import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt deleted file mode 100644 index 0b4636086f7..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.ir.builders - -import org.jetbrains.kotlin.backend.common.descriptors.substitute -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrLoop -import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin -import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.util.defaultType -import org.jetbrains.kotlin.types.KotlinType - -fun IrBuilderWithScope.irWhile(origin: IrStatementOrigin? = null) = - IrWhileLoopImpl(startOffset, endOffset, context.builtIns.unitType, origin) - -fun IrBuilderWithScope.irBreak(loop: IrLoop) = - IrBreakImpl(startOffset, endOffset, context.builtIns.nothingType, loop) - -fun IrBuilderWithScope.irContinue(loop: IrLoop) = - IrContinueImpl(startOffset, endOffset, context.builtIns.nothingType, loop) - -fun IrBuilderWithScope.irTrue() = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType, true) - -fun IrBuilderWithScope.irFalse() = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType, false) - -fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol): IrCallImpl { - return IrCallImpl(this.startOffset, this.endOffset, symbol) -} - -fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: Map) = - IrCallImpl(this.startOffset, this.endOffset, symbol, symbol.descriptor.substitute(typeArguments), typeArguments) - -fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: List) = - irCall(symbol, symbol.descriptor.typeParameters.zip(typeArguments).toMap()) - -fun IrBuilderWithScope.irGetObject(classSymbol: IrClassSymbol) = - IrGetObjectValueImpl(startOffset, endOffset, classSymbol.owner.defaultType, classSymbol) - -fun IrBuilderWithScope.irGetField(receiver: IrExpression?, symbol: IrFieldSymbol) = - IrGetFieldImpl(startOffset, endOffset, symbol, receiver) \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt index 02f0846f3ff..e1610de7a15 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt @@ -3,7 +3,6 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.IrElement diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt deleted file mode 100644 index 8bce6fa5d73..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.ir.util - -import org.jetbrains.kotlin.backend.common.atMostOne -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.psiUtil.endOffset -import org.jetbrains.kotlin.psi.psiUtil.startOffset -import org.jetbrains.kotlin.resolve.source.PsiSourceElement -import org.jetbrains.kotlin.types.KotlinType - -/** - * Binds the arguments explicitly represented in the IR to the parameters of the accessed function. - * The arguments are to be evaluated in the same order as they appear in the resulting list. - */ -internal fun IrMemberAccessExpression.getArguments(): List> { - val res = mutableListOf>() - val descriptor = descriptor - - // TODO: ensure the order below corresponds to the one defined in Kotlin specs. - - dispatchReceiver?.let { - res += (descriptor.dispatchReceiverParameter!! to it) - } - - extensionReceiver?.let { - res += (descriptor.extensionReceiverParameter!! to it) - } - - descriptor.valueParameters.forEach { - val arg = getValueArgument(it.index) - if (arg != null) { - res += (it to arg) - } - } - - return res -} - -/** - * Binds the arguments explicitly represented in the IR to the parameters of the accessed function. - * The arguments are to be evaluated in the same order as they appear in the resulting list. - */ -internal fun IrFunctionAccessExpression.getArgumentsWithSymbols(): List> { - val res = mutableListOf>() - val irFunction = symbol.owner as IrFunction - - dispatchReceiver?.let { - res += (irFunction.dispatchReceiverParameter!!.symbol to it) - } - - extensionReceiver?.let { - res += (irFunction.extensionReceiverParameter!!.symbol to it) - } - - irFunction.valueParameters.forEach { - val arg = getValueArgument(it.descriptor as ValueParameterDescriptor) - if (arg != null) { - res += (it.symbol to arg) - } - } - - return res -} - -/** - * Sets arguments that are specified by given mapping of parameters. - */ -internal fun IrMemberAccessExpression.addArguments(args: Map) { - descriptor.dispatchReceiverParameter?.let { - val arg = args[it] - if (arg != null) { - this.dispatchReceiver = arg - } - } - - descriptor.extensionReceiverParameter?.let { - val arg = args[it] - if (arg != null) { - this.extensionReceiver = arg - } - } - - descriptor.valueParameters.forEach { - val arg = args[it] - if (arg != null) { - this.putValueArgument(it.index, arg) - } - } -} - -internal fun IrMemberAccessExpression.addArguments(args: List>) = - this.addArguments(args.toMap()) - -internal fun IrExpression.isNullConst() = this is IrConst<*> && this.kind == IrConstKind.Null - -fun IrCall.usesDefaultArguments(): Boolean = - this.descriptor.valueParameters.any { this.getValueArgument(it) == null } - -fun IrElement.getCompilerMessageLocation(containingFile: IrFile): CompilerMessageLocation? { - val sourceRangeInfo = containingFile.fileEntry.getSourceRangeInfo(this.startOffset, this.endOffset) - return CompilerMessageLocation.create( - path = sourceRangeInfo.filePath, - line = sourceRangeInfo.startLineNumber, - column = sourceRangeInfo.startColumnNumber, - lineContent = null // TODO: retrieve the line content. - ) -} - -fun IrFunction.createParameterDeclarations() { - fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl( - innerStartOffset(this), innerEndOffset(this), - IrDeclarationOrigin.DEFINED, - this - ) - - dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.irValueParameter() - extensionReceiverParameter = descriptor.extensionReceiverParameter?.irValueParameter() - - assert(valueParameters.isEmpty()) - descriptor.valueParameters.mapTo(valueParameters) { it.irValueParameter() } - - assert(typeParameters.isEmpty()) - descriptor.typeParameters.mapTo(typeParameters) { - IrTypeParameterImpl( - innerStartOffset(it), innerEndOffset(it), - IrDeclarationOrigin.DEFINED, - it - ) - } -} - -fun IrClass.createParameterDeclarations() { - descriptor.thisAsReceiverParameter.let { - thisReceiver = IrValueParameterImpl( - innerStartOffset(it), innerEndOffset(it), - IrDeclarationOrigin.INSTANCE_RECEIVER, - it - ) - } - - assert(typeParameters.isEmpty()) - descriptor.declaredTypeParameters.mapTo(typeParameters) { - IrTypeParameterImpl( - innerStartOffset(it), innerEndOffset(it), - IrDeclarationOrigin.DEFINED, - it - ) - } -} - -fun IrClass.addFakeOverrides() { - - val startOffset = this.startOffset - val endOffset = this.endOffset - - fun FunctionDescriptor.createFunction(): IrFunction = IrFunctionImpl( - startOffset, endOffset, - IrDeclarationOrigin.FAKE_OVERRIDE, this - ).apply { - createParameterDeclarations() - } - - descriptor.unsubstitutedMemberScope.getContributedDescriptors() - .filterIsInstance() - .filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE } - .mapTo(this.declarations) { - when (it) { - is FunctionDescriptor -> it.createFunction() - is PropertyDescriptor -> - IrPropertyImpl(startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, it).apply { - // TODO: add field if getter is missing? - getter = it.getter?.createFunction() - setter = it.setter?.createFunction() - } - else -> TODO(it.toString()) - } - } -} - -private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int = - descriptor.startOffset ?: this.startOffset - -private fun IrElement.innerEndOffset(descriptor: DeclarationDescriptorWithSource): Int = - descriptor.endOffset ?: this.endOffset - -val DeclarationDescriptorWithSource.startOffset: Int? get() = (this.source as? PsiSourceElement)?.psi?.startOffset -val DeclarationDescriptorWithSource.endOffset: Int? get() = (this.source as? PsiSourceElement)?.psi?.endOffset - -val DeclarationDescriptorWithSource.startOffsetOrUndefined: Int get() = startOffset ?: UNDEFINED_OFFSET -val DeclarationDescriptorWithSource.endOffsetOrUndefined: Int get() = endOffset ?: UNDEFINED_OFFSET - -val IrClassSymbol.functions: Sequence - get() = this.owner.declarations.asSequence().filterIsInstance().map { it.symbol } - -val IrClassSymbol.constructors: Sequence - get() = this.owner.declarations.asSequence().filterIsInstance().map { it.symbol } - -private fun IrClassSymbol.getPropertyDeclaration(name: String) = - this.owner.declarations.filterIsInstance() - .atMostOne { it.descriptor.name == Name.identifier(name) } - -fun IrClassSymbol.getPropertyGetter(name: String): IrFunctionSymbol? = - this.getPropertyDeclaration(name)?.getter?.symbol - -fun IrClassSymbol.getPropertySetter(name: String): IrFunctionSymbol? = - this.getPropertyDeclaration(name)?.setter?.symbol - -val IrFunction.explicitParameters: List - get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).map { it.symbol } - -val IrValueParameter.type: KotlinType - get() = this.descriptor.type - -val IrClass.defaultType: KotlinType - get() = this.descriptor.defaultType diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt new file mode 100644 index 00000000000..a8d6c34f3a6 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.ir.util + +import org.jetbrains.kotlin.ir.expressions.IrConst +import org.jetbrains.kotlin.ir.expressions.IrConstKind +import org.jetbrains.kotlin.ir.expressions.IrExpression + +//TODO: delete file on next kotlin dependency update +internal fun IrExpression.isNullConst() = this is IrConst<*> && this.kind == IrConstKind.Null +