From c7f182adbf87fc61c8536e29eec95031f96817b8 Mon Sep 17 00:00:00 2001 From: Pavel Kunyavskiy Date: Thu, 16 Sep 2021 16:04:47 +0300 Subject: [PATCH] [K/N] Introduce intrinsic constant constructors --- .../kotlin/backend/konan/KonanFqNames.kt | 1 + .../konan/descriptors/DescriptorUtils.kt | 3 ++ .../jetbrains/kotlin/backend/konan/ir/Ir.kt | 9 ++--- .../backend/konan/llvm/IntrinsicGenerator.kt | 37 ++++++++++++++++++- .../kotlin/native/internal/Annotations.kt | 4 ++ .../kotlin/native/internal/KClassImpl.kt | 5 +++ 6 files changed, 53 insertions(+), 6 deletions(-) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt index baf2dcd08d6..bf2e50511c0 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt @@ -29,6 +29,7 @@ object KonanFqNames { val leakDetectorCandidate = FqName("kotlin.native.internal.LeakDetectorCandidate") val canBePrecreated = FqName("kotlin.native.internal.CanBePrecreated") val typedIntrinsic = FqName("kotlin.native.internal.TypedIntrinsic") + val constantConstructorIntrinsic = FqName("kotlin.native.internal.ConstantConstructorIntrinsic") val objCMethod = FqName("kotlinx.cinterop.ObjCMethod") val hasFinalizer = FqName("kotlin.native.internal.HasFinalizer") val hasFreezeHook = FqName("kotlin.native.internal.HasFreezeHook") diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index f277cd787c8..6e5ce225749 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -43,6 +43,9 @@ internal val IrClass.implementedInterfaces: List internal val IrFunction.isTypedIntrinsic: Boolean get() = annotations.hasAnnotation(KonanFqNames.typedIntrinsic) +internal val IrConstructor.isConstantConstructorIntrinsic: Boolean + get() = annotations.hasAnnotation(KonanFqNames.constantConstructorIntrinsic) + internal val arrayTypes = setOf( "kotlin.Array", "kotlin.ByteArray", diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index da3a7cc5011..1d53348b77a 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -29,10 +29,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.typeWith -import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable -import org.jetbrains.kotlin.ir.util.SymbolTable -import org.jetbrains.kotlin.ir.util.constructors -import org.jetbrains.kotlin.ir.util.referenceFunction +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -447,11 +444,13 @@ internal class KonanSymbols( val getClassTypeInfo = internalFunction("getClassTypeInfo") val getObjectTypeInfo = internalFunction("getObjectTypeInfo") val kClassImpl = internalClass("KClassImpl") - val kClassImplConstructor by lazy { kClassImpl.constructors.single() } + val kClassImplConstructor by lazy { kClassImpl.constructors.single { it.descriptor.isPrimary } } + val kClassImplIntrinsicConstructor by lazy { kClassImpl.constructors.single { it.descriptor.valueParameters.isEmpty() } } val kClassUnsupportedImpl = internalClass("KClassUnsupportedImpl") val kClassUnsupportedImplConstructor by lazy { kClassUnsupportedImpl.constructors.single() } val kTypeParameterImpl = internalClass("KTypeParameterImpl") val kTypeImpl = internalClass("KTypeImpl") + val kTypeImplIntrinsicConstructor by lazy { kTypeImpl.constructors.single { it.descriptor.valueParameters.isEmpty() } } val kTypeImplForTypeParametersWithRecursiveBounds = internalClass("KTypeImplForTypeParametersWithRecursiveBounds") val kTypeProjection = symbolTable.referenceClass(context.reflectionTypes.kTypeProjection) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt index 5d5b81e444a..03d34812b25 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt @@ -2,9 +2,11 @@ package org.jetbrains.kotlin.backend.konan.llvm import kotlinx.cinterop.cValuesOf import llvm.* +import org.jetbrains.kotlin.backend.konan.KonanFqNames import org.jetbrains.kotlin.backend.konan.MemoryModel import org.jetbrains.kotlin.backend.konan.RuntimeNames import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationStringValue +import org.jetbrains.kotlin.backend.konan.descriptors.isConstantConstructorIntrinsic import org.jetbrains.kotlin.backend.konan.descriptors.isTypedIntrinsic import org.jetbrains.kotlin.backend.konan.llvm.objc.genObjCSelector import org.jetbrains.kotlin.backend.konan.reportCompilationError @@ -12,6 +14,7 @@ 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.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.findAnnotation @@ -93,6 +96,11 @@ internal enum class IntrinsicType { WORKER_EXECUTE } +internal enum class ConstantConstructorIntrinsicType { + KCLASS_IMPL, + KTYPE_IMPL, +} + // Explicit and single interface between Intrinsic Generator and IrToBitcode. internal interface IntrinsicGeneratorEnvironment { @@ -125,6 +133,16 @@ private fun getIntrinsicType(callSite: IrFunctionAccessExpression): IntrinsicTyp return IntrinsicType.valueOf(value) } +internal fun tryGetConstantConstructorIntrinsicType(constructor: IrConstructorSymbol): ConstantConstructorIntrinsicType? = + if (constructor.owner.isConstantConstructorIntrinsic) getConstantConstructorIntrinsicType(constructor) else null + +private fun getConstantConstructorIntrinsicType(constructor: IrConstructorSymbol): ConstantConstructorIntrinsicType { + val annotation = constructor.owner.annotations.findAnnotation(KonanFqNames.constantConstructorIntrinsic)!! + val value = annotation.getAnnotationStringValue()!! + return ConstantConstructorIntrinsicType.valueOf(value) +} + + internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnvironment) { private val codegen = environment.codegen @@ -260,11 +278,28 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv reportSpecialIntrinsic(intrinsicType) } + fun evaluateConstantConstructorFields(constant: IrConstantObject, args: List) : List { + return when (val intrinsicType = getConstantConstructorIntrinsicType(constant.constructor)) { + ConstantConstructorIntrinsicType.KCLASS_IMPL -> { + require(args.isEmpty()) + val typeArgument = constant.typeArguments[0] + val typeArgumentClass = typeArgument.getClass()!! + val typeInfo = codegen.typeInfoValue(typeArgumentClass) + listOf(constPointer(typeInfo).bitcast(int8TypePtr)) + } + ConstantConstructorIntrinsicType.KTYPE_IMPL -> + reportNonLoweredIntrinsic(intrinsicType) + } + } + private fun reportSpecialIntrinsic(intrinsicType: IntrinsicType): Nothing = context.reportCompilationError("$intrinsicType should be handled by `tryEvaluateSpecialCall`") private fun reportNonLoweredIntrinsic(intrinsicType: IntrinsicType): Nothing = - context.reportCompilationError("Intrinsic of type $intrinsicType should be handled by previos lowering phase") + context.reportCompilationError("Intrinsic of type $intrinsicType should be handled by previous lowering phase") + + private fun reportNonLoweredIntrinsic(intrinsicType: ConstantConstructorIntrinsicType): Nothing = + context.reportCompilationError("Constant constructor intrinsic of type $intrinsicType should be handled by previous lowering phase") private fun FunctionGenerationContext.emitGetContinuation(): LLVMValueRef = environment.continuation diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Annotations.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Annotations.kt index 4e236b8993b..c887af6fd2d 100644 --- a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Annotations.kt +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Annotations.kt @@ -100,6 +100,10 @@ internal annotation class PointsTo(vararg val onWhom: Int) @Retention(AnnotationRetention.BINARY) internal annotation class TypedIntrinsic(val kind: String) +@Target(AnnotationTarget.CONSTRUCTOR) +@Retention(AnnotationRetention.BINARY) +internal annotation class ConstantConstructorIntrinsic(val kind: String) + /** * Indicates that `@SymbolName external` function is implemented in library-stored bitcode * and doesn't have native dependencies. diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KClassImpl.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KClassImpl.kt index 4486f41e69e..e15f3833538 100644 --- a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KClassImpl.kt +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KClassImpl.kt @@ -9,6 +9,11 @@ import kotlin.reflect.KClass @ExportForCompiler internal class KClassImpl(private val typeInfo: NativePtr) : KClass { + + @ExportForCompiler + @ConstantConstructorIntrinsic("KCLASS_IMPL") + constructor() : this(TODO("This is intrinsic constructor and it shouldn't be used directly")) + // TODO: consider replacing '$' by another delimeter that can't be used in class name specified with backticks (``) override val simpleName: String? get() = getRelativeName(typeInfo, true)?.substringAfterLast('.')?.substringAfterLast('$')