From c1d63fa6dd2ee0530fac993da8753ee17f26818d Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Thu, 11 Aug 2022 11:10:51 +0300 Subject: [PATCH] [K/N][IR] Moved caches ABI lowerings to a separate file --- .../kotlin/backend/konan/ToplevelPhases.kt | 229 +---------------- .../backend/konan/lower/CachesAbiLowering.kt | 240 ++++++++++++++++++ 2 files changed, 244 insertions(+), 225 deletions(-) create mode 100644 kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CachesAbiLowering.kt diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index 830b0d9f003..29f8aa16c05 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -3,35 +3,26 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.backend.common.checkDeclarationParents import org.jetbrains.kotlin.backend.common.IrValidator import org.jetbrains.kotlin.backend.common.IrValidatorConfig -import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.phaser.* import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.backend.konan.lower.* import org.jetbrains.kotlin.backend.konan.lower.CacheInfoBuilder -import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_ENUM import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier import org.jetbrains.kotlin.backend.konan.lower.SamSuperTypesChecker import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport import org.jetbrains.kotlin.backend.konan.serialization.* import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.languageVersionSettings -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.builders.declarations.buildFun -import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl -import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name internal fun moduleValidationCallback(state: ActionState, module: IrModuleFragment, context: Context) { if (!context.config.needVerifyIr) return @@ -383,226 +374,14 @@ internal val exportInternalAbiPhase = makeKonanModuleOpPhase( name = "exportInternalAbi", description = "Add accessors to private entities", prerequisite = emptySet(), - op = { context, module -> - val visitor = object : IrElementVisitorVoid { - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitClass(declaration: IrClass) { - declaration.acceptChildrenVoid(this) - - if (declaration.isLocal) return - - if (declaration.isCompanion) { - val function = context.irFactory.buildFun { - name = InternalAbi.getCompanionObjectAccessorName(declaration) - origin = InternalAbi.INTERNAL_ABI_ORIGIN - returnType = declaration.defaultType - } - context.createIrBuilder(function.symbol).apply { - function.body = irBlockBody { - +irReturn(irGetObjectValue(declaration.defaultType, declaration.symbol)) - } - } - context.internalAbi.declare(function, declaration.module) - } - - if (declaration.isInner) { - val function = context.irFactory.buildFun { - name = InternalAbi.getInnerClassOuterThisAccessorName(declaration) - origin = InternalAbi.INTERNAL_ABI_ORIGIN - returnType = declaration.parentAsClass.defaultType - } - function.addValueParameter { - name = Name.identifier("innerClass") - origin = InternalAbi.INTERNAL_ABI_ORIGIN - type = declaration.defaultType - } - - context.createIrBuilder(function.symbol).apply { - function.body = irBlockBody { - +irReturn(irGetField( - irGet(function.valueParameters[0]), - context.innerClassesSupport.getOuterThisField(declaration)) - ) - } - } - context.internalAbi.declare(function, declaration.module) - } - - if (declaration.isEnumClass) { - val function = context.irFactory.buildFun { - name = InternalAbi.getEnumValuesAccessorName(declaration) - returnType = context.ir.symbols.array.typeWith(declaration.defaultType) - origin = InternalAbi.INTERNAL_ABI_ORIGIN - } - - context.createIrBuilder(function.symbol).run { - function.body = irBlockBody { - +irReturn(with(context.enumsSupport) { irGetValuesField(declaration) }) - } - } - context.internalAbi.declare(function, declaration.module) - } - } - - override fun visitProperty(declaration: IrProperty) { - declaration.acceptChildrenVoid(this) - - if (!declaration.isLateinit || declaration.isFakeOverride - || DescriptorVisibilities.isPrivate(declaration.visibility) || declaration.isLocal) - return - - val backingField = declaration.backingField ?: error("Lateinit property ${declaration.render()} should have a backing field") - val function = context.irFactory.buildFun { - name = InternalAbi.getLateinitPropertyFieldAccessorName(declaration) - origin = InternalAbi.INTERNAL_ABI_ORIGIN - returnType = backingField.type - } - val ownerClass = declaration.parentClassOrNull - if (ownerClass != null) - function.addValueParameter { - name = Name.identifier("owner") - origin = InternalAbi.INTERNAL_ABI_ORIGIN - type = ownerClass.defaultType - } - - context.createIrBuilder(function.symbol).apply { - function.body = irBlockBody { - +irReturn(irGetField(ownerClass?.let { irGet(function.valueParameters[0]) }, backingField)) - } - } - context.internalAbi.declare(function, declaration.module) - } - } - module.acceptChildrenVoid(visitor) - } + op = { context, module -> module.acceptChildrenVoid(ExportCachesAbiVisitor(context)) } ) internal val useInternalAbiPhase = makeKonanModuleOpPhase( name = "useInternalAbi", description = "Use internal ABI functions to access private entities", prerequisite = emptySet(), - op = { context, module -> - val companionObjectAccessors = mutableMapOf() - val outerThisAccessors = mutableMapOf() - val lateinitPropertyAccessors = mutableMapOf() - val enumValuesAccessors = mutableMapOf() - - val transformer = object : IrElementTransformerVoid() { - override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression { - expression.transformChildrenVoid(this) - - val irClass = expression.symbol.owner - if (!irClass.isCompanion || context.llvmModuleSpecification.containsDeclaration(irClass)) { - return expression - } - val parent = irClass.parentAsClass - if (parent.isObjCClass()) { - // Access to Obj-C metaclass is done via intrinsic. - return expression - } - val accessor = companionObjectAccessors.getOrPut(irClass) { - context.irFactory.buildFun { - name = InternalAbi.getCompanionObjectAccessorName(irClass) - returnType = irClass.defaultType - origin = InternalAbi.INTERNAL_ABI_ORIGIN - isExternal = true - }.also { - context.internalAbi.reference(it, irClass.module) - } - } - return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size) - } - - override fun visitGetField(expression: IrGetField): IrExpression { - expression.transformChildrenVoid(this) - - val field = expression.symbol.owner - val irClass = field.parentClassOrNull - val property = field.correspondingPropertySymbol?.owner - - return when { - context.llvmModuleSpecification.containsDeclaration(field) -> expression - - irClass?.isInner == true && context.innerClassesSupport.getOuterThisField(irClass) == field -> { - val accessor = outerThisAccessors.getOrPut(irClass) { - context.irFactory.buildFun { - name = InternalAbi.getInnerClassOuterThisAccessorName(irClass) - returnType = irClass.parentAsClass.defaultType - origin = InternalAbi.INTERNAL_ABI_ORIGIN - isExternal = true - }.also { function -> - context.internalAbi.reference(function, irClass.module) - - function.addValueParameter { - name = Name.identifier("innerClass") - origin = InternalAbi.INTERNAL_ABI_ORIGIN - type = irClass.defaultType - } - } - } - return IrCallImpl( - expression.startOffset, expression.endOffset, - expression.type, accessor.symbol, - accessor.typeParameters.size, accessor.valueParameters.size - ).apply { - putValueArgument(0, expression.receiver) - } - } - - property?.isLateinit == true -> { - val accessor = lateinitPropertyAccessors.getOrPut(property) { - context.irFactory.buildFun { - name = InternalAbi.getLateinitPropertyFieldAccessorName(property) - returnType = field.type - origin = InternalAbi.INTERNAL_ABI_ORIGIN - isExternal = true - }.also { function -> - context.internalAbi.reference(function, property.module) - - if (irClass != null) - function.addValueParameter { - name = Name.identifier("owner") - origin = InternalAbi.INTERNAL_ABI_ORIGIN - type = irClass.defaultType - } - } - } - return IrCallImpl( - expression.startOffset, expression.endOffset, - expression.type, accessor.symbol, - accessor.typeParameters.size, accessor.valueParameters.size - ).apply { - if (irClass != null) - putValueArgument(0, expression.receiver) - } - } - - field.origin == DECLARATION_ORIGIN_ENUM -> { - val enumClass = irClass?.parentClassOrNull - require(enumClass != null) { "Unexpected usage of enum VALUES field" } - require(enumClass.isEnumClass) { "Expected a enum class: ${enumClass.render()}" } - val accessor = enumValuesAccessors.getOrPut(enumClass) { - context.irFactory.buildFun { - name = InternalAbi.getEnumValuesAccessorName(enumClass) - returnType = context.ir.symbols.array.typeWith(enumClass.defaultType) - origin = InternalAbi.INTERNAL_ABI_ORIGIN - isExternal = true - }.also { - context.internalAbi.reference(it, enumClass.module) - } - } - return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size) - } - - else -> expression - } - } - } - module.transformChildrenVoid(transformer) - } + op = { context, module -> module.transformChildrenVoid(ImportCachesAbiTransformer(context)) } ) internal val bitcodePhase = NamedCompilerPhase( diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CachesAbiLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CachesAbiLowering.kt new file mode 100644 index 00000000000..ed7da65c300 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CachesAbiLowering.kt @@ -0,0 +1,240 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.InternalAbi +import org.jetbrains.kotlin.backend.konan.isObjCClass +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.builders.declarations.buildFun +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrGetField +import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue +import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.* +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.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name + +internal class ExportCachesAbiVisitor(val context: Context) : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitClass(declaration: IrClass) { + declaration.acceptChildrenVoid(this) + + if (declaration.isLocal) return + + if (declaration.isCompanion) { + val function = context.irFactory.buildFun { + name = InternalAbi.getCompanionObjectAccessorName(declaration) + origin = InternalAbi.INTERNAL_ABI_ORIGIN + returnType = declaration.defaultType + } + context.createIrBuilder(function.symbol).apply { + function.body = irBlockBody { + +irReturn(irGetObjectValue(declaration.defaultType, declaration.symbol)) + } + } + context.internalAbi.declare(function, declaration.module) + } + + if (declaration.isInner) { + val function = context.irFactory.buildFun { + name = InternalAbi.getInnerClassOuterThisAccessorName(declaration) + origin = InternalAbi.INTERNAL_ABI_ORIGIN + returnType = declaration.parentAsClass.defaultType + } + function.addValueParameter { + name = Name.identifier("innerClass") + origin = InternalAbi.INTERNAL_ABI_ORIGIN + type = declaration.defaultType + } + + context.createIrBuilder(function.symbol).apply { + function.body = irBlockBody { + +irReturn(irGetField( + irGet(function.valueParameters[0]), + this@ExportCachesAbiVisitor.context.innerClassesSupport.getOuterThisField(declaration)) + ) + } + } + context.internalAbi.declare(function, declaration.module) + } + + if (declaration.isEnumClass) { + val function = context.irFactory.buildFun { + name = InternalAbi.getEnumValuesAccessorName(declaration) + returnType = context.ir.symbols.array.typeWith(declaration.defaultType) + origin = InternalAbi.INTERNAL_ABI_ORIGIN + } + + context.createIrBuilder(function.symbol).run { + function.body = irBlockBody { + +irReturn(with(this@ExportCachesAbiVisitor.context.enumsSupport) { irGetValuesField(declaration) }) + } + } + context.internalAbi.declare(function, declaration.module) + } + } + + override fun visitProperty(declaration: IrProperty) { + declaration.acceptChildrenVoid(this) + + if (!declaration.isLateinit || declaration.isFakeOverride + || DescriptorVisibilities.isPrivate(declaration.visibility) || declaration.isLocal) + return + + val backingField = declaration.backingField ?: error("Lateinit property ${declaration.render()} should have a backing field") + val function = context.irFactory.buildFun { + name = InternalAbi.getLateinitPropertyFieldAccessorName(declaration) + origin = InternalAbi.INTERNAL_ABI_ORIGIN + returnType = backingField.type + } + val ownerClass = declaration.parentClassOrNull + if (ownerClass != null) + function.addValueParameter { + name = Name.identifier("owner") + origin = InternalAbi.INTERNAL_ABI_ORIGIN + type = ownerClass.defaultType + } + + context.createIrBuilder(function.symbol).apply { + function.body = irBlockBody { + +irReturn(irGetField(ownerClass?.let { irGet(function.valueParameters[0]) }, backingField)) + } + } + context.internalAbi.declare(function, declaration.module) + } +} + +internal class ImportCachesAbiTransformer(val context: Context) : IrElementTransformerVoid() { + private val companionObjectAccessors = mutableMapOf() + private val outerThisAccessors = mutableMapOf() + private val lateinitPropertyAccessors = mutableMapOf() + private val enumValuesAccessors = mutableMapOf() + + override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression { + expression.transformChildrenVoid(this) + + val irClass = expression.symbol.owner + if (!irClass.isCompanion || context.llvmModuleSpecification.containsDeclaration(irClass)) { + return expression + } + val parent = irClass.parentAsClass + if (parent.isObjCClass()) { + // Access to Obj-C metaclass is done via intrinsic. + return expression + } + val accessor = companionObjectAccessors.getOrPut(irClass) { + context.irFactory.buildFun { + name = InternalAbi.getCompanionObjectAccessorName(irClass) + returnType = irClass.defaultType + origin = InternalAbi.INTERNAL_ABI_ORIGIN + isExternal = true + }.also { + context.internalAbi.reference(it, irClass.module) + } + } + return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size) + } + + override fun visitGetField(expression: IrGetField): IrExpression { + expression.transformChildrenVoid(this) + + val field = expression.symbol.owner + val irClass = field.parentClassOrNull + val property = field.correspondingPropertySymbol?.owner + + return when { + context.llvmModuleSpecification.containsDeclaration(field) -> expression + + irClass?.isInner == true && context.innerClassesSupport.getOuterThisField(irClass) == field -> { + val accessor = outerThisAccessors.getOrPut(irClass) { + context.irFactory.buildFun { + name = InternalAbi.getInnerClassOuterThisAccessorName(irClass) + returnType = irClass.parentAsClass.defaultType + origin = InternalAbi.INTERNAL_ABI_ORIGIN + isExternal = true + }.also { function -> + context.internalAbi.reference(function, irClass.module) + + function.addValueParameter { + name = Name.identifier("innerClass") + origin = InternalAbi.INTERNAL_ABI_ORIGIN + type = irClass.defaultType + } + } + } + return IrCallImpl( + expression.startOffset, expression.endOffset, + expression.type, accessor.symbol, + accessor.typeParameters.size, accessor.valueParameters.size + ).apply { + putValueArgument(0, expression.receiver) + } + } + + property?.isLateinit == true -> { + val accessor = lateinitPropertyAccessors.getOrPut(property) { + context.irFactory.buildFun { + name = InternalAbi.getLateinitPropertyFieldAccessorName(property) + returnType = field.type + origin = InternalAbi.INTERNAL_ABI_ORIGIN + isExternal = true + }.also { function -> + context.internalAbi.reference(function, property.module) + + if (irClass != null) + function.addValueParameter { + name = Name.identifier("owner") + origin = InternalAbi.INTERNAL_ABI_ORIGIN + type = irClass.defaultType + } + } + } + return IrCallImpl( + expression.startOffset, expression.endOffset, + expression.type, accessor.symbol, + accessor.typeParameters.size, accessor.valueParameters.size + ).apply { + if (irClass != null) + putValueArgument(0, expression.receiver) + } + } + + field.origin == DECLARATION_ORIGIN_ENUM -> { + val enumClass = irClass?.parentClassOrNull + require(enumClass != null) { "Unexpected usage of enum VALUES field" } + require(enumClass.isEnumClass) { "Expected a enum class: ${enumClass.render()}" } + val accessor = enumValuesAccessors.getOrPut(enumClass) { + context.irFactory.buildFun { + name = InternalAbi.getEnumValuesAccessorName(enumClass) + returnType = context.ir.symbols.array.typeWith(enumClass.defaultType) + origin = InternalAbi.INTERNAL_ABI_ORIGIN + isExternal = true + }.also { + context.internalAbi.reference(it, enumClass.module) + } + } + return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size) + } + + else -> expression + } + } +} \ No newline at end of file