[K/N][IR] Never consider a enum a final class

Unfortunately, neither descriptors nor Lazy IR have enough information
to correctly deduce a enum's modality as psi2ir does, so to avoid the RTTI generator
generating different vtables in different setups (whether a klib is cached or not),
conservatively consider all enums non-final.
This commit is contained in:
Igor Chevdar
2022-01-31 19:13:09 +05:00
parent 97a28df43d
commit 554e94a322
9 changed files with 29 additions and 9 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.backend.common.ir.isFinalClass
import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions
import org.jetbrains.kotlin.backend.konan.descriptors.isInteropLibrary
@@ -62,9 +63,6 @@ val IrFunction.isOverridable get() = this is IrSimpleFunction && this.isOverrida
val IrFunction.isOverridableOrOverrides
get() = this is IrSimpleFunction && (this.isOverridable || this.overriddenSymbols.isNotEmpty())
val IrClass.isFinalClass: Boolean
get() = modality == Modality.FINAL
fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing()
inline fun <reified T> IrDeclaration.getAnnotationArgumentValue(fqName: FqName, argumentName: String): T? {
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
import llvm.LLVMLinkage
import llvm.LLVMSetLinkage
import llvm.LLVMValueRef
import org.jetbrains.kotlin.backend.common.ir.isFinalClass
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationStringValue
import org.jetbrains.kotlin.backend.konan.ir.*
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.konan.cgen.*
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.backend.konan.ir.isFinalClass
import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType
import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType
import org.jetbrains.kotlin.backend.konan.serialization.resolveFakeOverrideMaybeAbstract
@@ -5,9 +5,9 @@
package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.ir.isFinalClass
import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationTransformer
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.ir.isFinalClass
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.optimizations
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.common.ir.allParameters
import org.jetbrains.kotlin.backend.common.ir.isFinalClass
import org.jetbrains.kotlin.backend.konan.descriptors.*
import org.jetbrains.kotlin.backend.konan.descriptors.OverriddenFunctionInfo
import org.jetbrains.kotlin.backend.konan.descriptors.implementedInterfaces
@@ -486,14 +487,12 @@ internal object DataFlowIR {
}, data = null)
}
private fun IrClass.isFinal() = modality == Modality.FINAL
fun mapClassReferenceType(irClass: IrClass): Type {
// Do not try to devirtualize ObjC classes.
if (irClass.module.name == Name.special("<forward declarations>") || irClass.isObjCClass())
return Type.Virtual
val isFinal = irClass.isFinal()
val isFinal = irClass.isFinalClass
val isAbstract = irClass.isAbstract()
val name = irClass.fqNameForIrSerialization.asString()
classMap[irClass]?.let { return it }
@@ -638,7 +637,7 @@ internal object DataFlowIR {
}
val bridgeTargetSymbol = if (isSpecialBridge || bridgeTarget == null) null else mapFunction(bridgeTarget)
val placeToFunctionsTable = !isAbstract && it !is IrConstructor && irClass != null
&& (it.isOverridableOrOverrides || bridgeTarget != null || function.isSpecial || !irClass.isFinal())
&& (it.isOverridableOrOverrides || bridgeTarget != null || function.isSpecial || !irClass.isFinalClass)
val symbolTableIndex = if (placeToFunctionsTable) module.numberOfFunctions++ else -1
val frozen = it is IrConstructor && irClass!!.isFrozen(context)
val functionSymbol = if (it.isExported())
@@ -1362,6 +1362,12 @@ linkTest("enum_linkTest") {
lib = "codegen/enum/linkTest_lib.kt"
}
linkTest("enum_openMethodNoOverrides") {
useGoldenData = true
source = "codegen/enum/openMethodNoOverrides_main.kt"
lib = "codegen/enum/openMethodNoOverrides_lib.kt"
}
task enum_varargParam(type: KonanLocalTest) {
useGoldenData = true
source = "codegen/enum/varargParam.kt"
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
enum class Foo {
Z;
open fun bar() = 42
}
@@ -0,0 +1,6 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
fun main() = println(Foo.Z.bar())