[K/N] Introduce intrinsic constant constructors

This commit is contained in:
Pavel Kunyavskiy
2021-09-16 16:04:47 +03:00
committed by Space
parent 74b9eeb584
commit c7f182adbf
6 changed files with 53 additions and 6 deletions
@@ -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")
@@ -43,6 +43,9 @@ internal val IrClass.implementedInterfaces: List<IrClass>
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",
@@ -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)
@@ -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<ConstValue>) : List<ConstValue> {
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
@@ -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.
@@ -9,6 +9,11 @@ import kotlin.reflect.KClass
@ExportForCompiler
internal class KClassImpl<T : Any>(private val typeInfo: NativePtr) : KClass<T> {
@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('$')