Move more intrinsics under TypedIntrinsic annotation (#2474)

This commit is contained in:
Sergey Bogolepov
2018-12-19 18:40:30 +03:00
committed by GitHub
parent 992a0a7337
commit baaf6edba7
16 changed files with 432 additions and 418 deletions
@@ -18,37 +18,40 @@ package kotlinx.cinterop
import kotlin.native.*
import kotlin.native.internal.Intrinsic
import kotlin.native.internal.TypedIntrinsic
import kotlin.native.internal.IntrinsicType
@PublishedApi
internal inline val pointerSize: Int
get() = getPointerSize()
@PublishedApi
@Intrinsic internal external fun getPointerSize(): Int
@TypedIntrinsic(IntrinsicType.GET_POINTER_SIZE)
internal external fun getPointerSize(): Int
// TODO: do not use singleton because it leads to init-check on any access.
@PublishedApi
internal object nativeMemUtils {
@Intrinsic external fun getByte(mem: NativePointed): Byte
@Intrinsic external fun putByte(mem: NativePointed, value: Byte)
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getByte(mem: NativePointed): Byte
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putByte(mem: NativePointed, value: Byte)
@Intrinsic external fun getShort(mem: NativePointed): Short
@Intrinsic external fun putShort(mem: NativePointed, value: Short)
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getShort(mem: NativePointed): Short
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putShort(mem: NativePointed, value: Short)
@Intrinsic external fun getInt(mem: NativePointed): Int
@Intrinsic external fun putInt(mem: NativePointed, value: Int)
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getInt(mem: NativePointed): Int
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putInt(mem: NativePointed, value: Int)
@Intrinsic external fun getLong(mem: NativePointed): Long
@Intrinsic external fun putLong(mem: NativePointed, value: Long)
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getLong(mem: NativePointed): Long
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putLong(mem: NativePointed, value: Long)
@Intrinsic external fun getFloat(mem: NativePointed): Float
@Intrinsic external fun putFloat(mem: NativePointed, value: Float)
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getFloat(mem: NativePointed): Float
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putFloat(mem: NativePointed, value: Float)
@Intrinsic external fun getDouble(mem: NativePointed): Double
@Intrinsic external fun putDouble(mem: NativePointed, value: Double)
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getDouble(mem: NativePointed): Double
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putDouble(mem: NativePointed, value: Double)
@Intrinsic external fun getNativePtr(mem: NativePointed): NativePtr
@Intrinsic external fun putNativePtr(mem: NativePointed, value: NativePtr)
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getNativePtr(mem: NativePointed): NativePtr
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putNativePtr(mem: NativePointed, value: NativePtr)
// TODO: optimize
fun getByteArray(source: NativePointed, dest: ByteArray, length: Int) {
@@ -151,5 +154,7 @@ private external fun malloc(size: Long, align: Int): NativePtr
@SymbolName("Kotlin_interop_free")
private external fun cfree(ptr: NativePtr)
@Intrinsic external fun readBits(ptr: NativePtr, offset: Long, size: Int, signed: Boolean): Long
@Intrinsic external fun writeBits(ptr: NativePtr, offset: Long, size: Int, value: Long)
@TypedIntrinsic(IntrinsicType.READ_BITS)
external fun readBits(ptr: NativePtr, offset: Long, size: Int, signed: Boolean): Long
@TypedIntrinsic(IntrinsicType.WRITE_BITS)
external fun writeBits(ptr: NativePtr, offset: Long, size: Int, value: Long)
@@ -20,6 +20,8 @@ import kotlin.native.internal.getNativeNullPtr
import kotlin.native.internal.reinterpret
import kotlin.native.internal.Intrinsic
import kotlin.native.internal.VolatileLambda
import kotlin.native.internal.TypedIntrinsic
import kotlin.native.internal.IntrinsicType
typealias NativePtr = kotlin.native.internal.NativePtr
internal typealias NonNullNativePtr = kotlin.native.internal.NonNullNativePtr
@@ -37,16 +39,20 @@ fun <T : CVariable> typeOf(): CVariable.Type = throw Error("typeOf() is called w
*
* @param T must not be abstract
*/
@Intrinsic external fun <T : NativePointed> interpretNullablePointed(ptr: NativePtr): T?
@TypedIntrinsic(IntrinsicType.IDENTITY)
external fun <T : NativePointed> interpretNullablePointed(ptr: NativePtr): T?
/**
* Performs type cast of the [CPointer] from the given raw pointer.
*/
@Intrinsic external fun <T : CPointed> interpretCPointer(rawValue: NativePtr): CPointer<T>?
@TypedIntrinsic(IntrinsicType.IDENTITY)
external fun <T : CPointed> interpretCPointer(rawValue: NativePtr): CPointer<T>?
@Intrinsic external fun NativePointed.getRawPointer(): NativePtr
@TypedIntrinsic(IntrinsicType.IDENTITY)
external fun NativePointed.getRawPointer(): NativePtr
@Intrinsic external fun CPointer<*>.getRawValue(): NativePtr
@TypedIntrinsic(IntrinsicType.IDENTITY)
external fun CPointer<*>.getRawValue(): NativePtr
internal fun CPointer<*>.cPointerToString() = "CPointer(raw=$rawValue)"
@@ -19,6 +19,8 @@
package kotlinx.cinterop
import kotlin.native.*
import kotlin.native.internal.ExportTypeInfo
import kotlin.native.internal.TypedIntrinsic
import kotlin.native.internal.IntrinsicType
interface ObjCObject
interface ObjCClass : ObjCObject
@@ -91,7 +93,8 @@ var <T : Any?> ObjCNotImplementedVar<T>.value: T
typealias ObjCStringVarOf<T> = ObjCNotImplementedVar<T>
typealias ObjCBlockVar<T> = ObjCNotImplementedVar<T>
@kotlin.native.internal.Intrinsic external fun getReceiverOrSuper(receiver: NativePtr, superClass: NativePtr): COpaquePointer?
@TypedIntrinsic(IntrinsicType.OBJC_GET_RECEIVER_OR_SUPER)
external fun getReceiverOrSuper(receiver: NativePtr, superClass: NativePtr): COpaquePointer?
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
@@ -146,12 +149,14 @@ private fun allocObjCObject(clazz: NativePtr): NativePtr {
return rawResult
}
@kotlin.native.internal.Intrinsic
@TypedIntrinsic(IntrinsicType.OBJC_GET_OBJC_CLASS)
@kotlin.native.internal.ExportForCompiler
private external fun <T : ObjCObject> getObjCClass(): NativePtr
@kotlin.native.internal.Intrinsic external fun getMessenger(superClass: NativePtr): COpaquePointer?
@kotlin.native.internal.Intrinsic external fun getMessengerStret(superClass: NativePtr): COpaquePointer?
@TypedIntrinsic(IntrinsicType.OBJC_GET_MESSENGER)
external fun getMessenger(superClass: NativePtr): COpaquePointer?
@TypedIntrinsic(IntrinsicType.OBJC_GET_MESSENGER_STRET)
external fun getMessengerStret(superClass: NativePtr): COpaquePointer?
internal class ObjCWeakReferenceImpl : kotlin.native.ref.WeakReferenceImpl() {
@@ -277,8 +277,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
private val packageScope by lazy { builtIns.builtInsModule.getPackage(KonanFqNames.internalPackageName).memberScope }
val nativePtr by lazy { packageScope.getContributedClassifier(NATIVE_PTR_NAME) as ClassDescriptor }
val nativePtrPlusLong by lazy { nativePtr.unsubstitutedMemberScope.getContributedFunctions("plus").single() }
val nativePtrToLong by lazy { nativePtr.unsubstitutedMemberScope.getContributedFunctions("toLong").single() }
val getNativeNullPtr by lazy { packageScope.getContributedFunctions("getNativeNullPtr").single() }
val immutableBlobOf by lazy {
builtIns.builtInsModule.getPackage(KonanFqNames.packageName).memberScope.getContributedFunctions("immutableBlobOf").single()
@@ -31,8 +31,6 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives:
val packageScope = builtIns.builtInsModule.getPackage(InteropFqNames.packageName).memberScope
val getPointerSize = packageScope.getContributedFunctions("getPointerSize").single()
val nativePointed = packageScope.getContributedClass(InteropFqNames.nativePointedName)
val cPointer = this.packageScope.getContributedClass(InteropFqNames.cPointerName)
@@ -54,26 +52,8 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives:
TypeUtils.getClassDescriptor(extensionReceiverParameter.type) == nativePointed
}
val interpretNullablePointed = packageScope.getContributedFunctions("interpretNullablePointed").single()
val interpretCPointer = packageScope.getContributedFunctions("interpretCPointer").single()
val typeOf = packageScope.getContributedFunctions("typeOf").single()
val nativeMemUtils = packageScope.getContributedClass("nativeMemUtils")
private val primitives = arrayOf(
arrayOf(builtIns.byte, builtIns.short, builtIns.int, builtIns.long, builtIns.float, builtIns.double),
konanPrimitives).flatten()
val readPrimitive = primitives.map {
nativeMemUtils.unsubstitutedMemberScope.getContributedFunctions("get" + it.name).single()
}.toSet()
val writePrimitive = primitives.map {
nativeMemUtils.unsubstitutedMemberScope.getContributedFunctions("put" + it.name).single()
}.toSet()
val bitsToFloat = packageScope.getContributedFunctions("bitsToFloat").single()
val bitsToDouble = packageScope.getContributedFunctions("bitsToDouble").single()
@@ -93,9 +73,6 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives:
val convert = packageScope.getContributedFunctions("convert").toSet()
val readBits = packageScope.getContributedFunctions("readBits").single()
val writeBits = packageScope.getContributedFunctions("writeBits").single()
val cFunctionPointerInvokes = packageScope.getContributedFunctions(OperatorNameConventions.INVOKE.asString())
.filter {
val extensionReceiverParameter = it.extensionReceiverParameter
@@ -135,11 +112,6 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives:
val objCObjectRawPtr = packageScope.getContributedFunctions("objcPtr").single()
val getObjCReceiverOrSuper = packageScope.getContributedFunctions("getReceiverOrSuper").single()
val getObjCMessenger = packageScope.getContributedFunctions("getMessenger").single()
val getObjCMessengerStret = packageScope.getContributedFunctions("getMessengerStret").single()
val interpretObjCPointerOrNull = packageScope.getContributedFunctions("interpretObjCPointerOrNull").single()
val interpretObjCPointer = packageScope.getContributedFunctions("interpretObjCPointer").single()
@@ -1,9 +1,14 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.cValuesOf
import llvm.*
import org.jetbrains.kotlin.backend.konan.descriptors.TypedIntrinsic
import org.jetbrains.kotlin.backend.konan.reportCompilationError
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrVararg
import org.jetbrains.kotlin.ir.expressions.getTypeArgument
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.name.Name
private enum class IntrinsicType {
@@ -36,11 +41,35 @@ private enum class IntrinsicType {
SIGNED_COMPARE_TO,
UNSIGNED_COMPARE_TO,
NOT,
TO_BITS,
FROM_BITS
REINTERPRET,
ARE_EQUAL_BY_VALUE,
IEEE_754_EQUALS,
// OBJC
OBJC_GET_MESSENGER,
OBJC_GET_MESSENGER_STRET,
OBJC_GET_OBJC_CLASS,
OBJC_GET_RECEIVER_OR_SUPER,
// Other
GET_CLASS_TYPE_INFO,
READ_BITS,
WRITE_BITS,
CREATE_UNINITIALIZED_INSTANCE,
LIST_OF_INTERNAL,
IDENTITY,
GET_CONTINUATION,
// Interop
READ_PRIMITIVE,
WRITE_PRIMITIVE,
GET_POINTER_SIZE,
NATIVE_PTR_TO_LONG,
NATIVE_PTR_PLUS_LONG,
GET_NATIVE_NULL_PTR
}
internal class IntrinsicGenerator(val codegen: CodeGenerator) {
internal class IntrinsicGenerator(private val codegen: CodeGenerator,
private val lifetimeCalculator: (IrElement) -> Lifetime,
private val continuationProvider: () -> LLVMValueRef,
private val exceptionHandlerProvider: () -> ExceptionHandler) {
private val context = codegen.context
@@ -54,48 +83,297 @@ internal class IntrinsicGenerator(val codegen: CodeGenerator) {
return IntrinsicType.valueOf(value)
}
fun evaluateCall(callSite: IrCall, args: List<LLVMValueRef>, generationContext: FunctionGenerationContext, exceptionHandler: ExceptionHandler): LLVMValueRef =
generationContext.evaluateCall(callSite, args, exceptionHandler)
fun evaluateCall(callSite: IrCall, args: List<LLVMValueRef>, generationContext: FunctionGenerationContext): LLVMValueRef =
generationContext.evaluateCall(callSite, args)
// Assuming that we checked for `TypedIntrinsic` annotation presence.
private fun FunctionGenerationContext.evaluateCall(callSite: IrCall, args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
val result = when (getIntrinsicType(callSite)) {
IntrinsicType.PLUS -> emitPlus(args)
IntrinsicType.MINUS -> emitMinus(args)
IntrinsicType.TIMES -> emitTimes(args)
IntrinsicType.SIGNED_DIV -> emitSignedDiv(args, exceptionHandler)
IntrinsicType.SIGNED_REM -> emitSignedRem(args, exceptionHandler)
IntrinsicType.UNSIGNED_DIV -> emitUnsignedDiv(args, exceptionHandler)
IntrinsicType.UNSIGNED_REM -> emitUnsignedRem(args, exceptionHandler)
IntrinsicType.INC -> emitInc(args)
IntrinsicType.DEC -> emitDec(args)
IntrinsicType.UNARY_PLUS -> emitUnaryPlus(args)
IntrinsicType.UNARY_MINUS -> emitUnaryMinus(args)
IntrinsicType.SHL -> emitShl(args)
IntrinsicType.SHR -> emitShr(args)
IntrinsicType.USHR -> emitUshr(args)
IntrinsicType.AND -> emitAnd(args)
IntrinsicType.OR -> emitOr(args)
IntrinsicType.XOR -> emitXor(args)
IntrinsicType.INV -> emitInv(args)
IntrinsicType.SIGNED_COMPARE_TO -> emitSignedCompareTo(args)
IntrinsicType.UNSIGNED_COMPARE_TO -> emitUnsignedCompareTo(args)
IntrinsicType.NOT -> emitNot(args)
IntrinsicType.FROM_BITS -> emitReinterpret(callSite, args)
IntrinsicType.TO_BITS -> emitReinterpret(callSite, args)
IntrinsicType.SIGN_EXTEND -> emitSignExtend(callSite, args)
IntrinsicType.ZERO_EXTEND -> emitZeroExtend(callSite, args)
IntrinsicType.INT_TRUNCATE -> emitIntTruncate(callSite, args)
IntrinsicType.SIGNED_TO_FLOAT -> emitSignedToFloat(callSite, args)
IntrinsicType.UNSIGNED_TO_FLOAT -> emitUnsignedToFloat(callSite, args)
IntrinsicType.FLOAT_TO_SIGNED -> emitFloatToSigned(callSite, args)
IntrinsicType.FLOAT_EXTEND -> emitFloatExtend(callSite, args)
IntrinsicType.FLOAT_TRUNCATE -> emitFloatTruncate(callSite, args)
private fun FunctionGenerationContext.evaluateCall(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef =
when (getIntrinsicType(callSite)) {
IntrinsicType.PLUS -> emitPlus(args)
IntrinsicType.MINUS -> emitMinus(args)
IntrinsicType.TIMES -> emitTimes(args)
IntrinsicType.SIGNED_DIV -> emitSignedDiv(args)
IntrinsicType.SIGNED_REM -> emitSignedRem(args)
IntrinsicType.UNSIGNED_DIV -> emitUnsignedDiv(args)
IntrinsicType.UNSIGNED_REM -> emitUnsignedRem(args)
IntrinsicType.INC -> emitInc(args)
IntrinsicType.DEC -> emitDec(args)
IntrinsicType.UNARY_PLUS -> emitUnaryPlus(args)
IntrinsicType.UNARY_MINUS -> emitUnaryMinus(args)
IntrinsicType.SHL -> emitShl(args)
IntrinsicType.SHR -> emitShr(args)
IntrinsicType.USHR -> emitUshr(args)
IntrinsicType.AND -> emitAnd(args)
IntrinsicType.OR -> emitOr(args)
IntrinsicType.XOR -> emitXor(args)
IntrinsicType.INV -> emitInv(args)
IntrinsicType.SIGNED_COMPARE_TO -> emitSignedCompareTo(args)
IntrinsicType.UNSIGNED_COMPARE_TO -> emitUnsignedCompareTo(args)
IntrinsicType.NOT -> emitNot(args)
IntrinsicType.REINTERPRET -> emitReinterpret(callSite, args)
IntrinsicType.SIGN_EXTEND -> emitSignExtend(callSite, args)
IntrinsicType.ZERO_EXTEND -> emitZeroExtend(callSite, args)
IntrinsicType.INT_TRUNCATE -> emitIntTruncate(callSite, args)
IntrinsicType.SIGNED_TO_FLOAT -> emitSignedToFloat(callSite, args)
IntrinsicType.UNSIGNED_TO_FLOAT -> emitUnsignedToFloat(callSite, args)
IntrinsicType.FLOAT_TO_SIGNED -> emitFloatToSigned(callSite, args)
IntrinsicType.FLOAT_EXTEND -> emitFloatExtend(callSite, args)
IntrinsicType.FLOAT_TRUNCATE -> emitFloatTruncate(callSite, args)
IntrinsicType.ARE_EQUAL_BY_VALUE -> emitAreEqualByValue(args)
IntrinsicType.IEEE_754_EQUALS -> emitIeee754Equals(args)
IntrinsicType.OBJC_GET_MESSENGER -> emitObjCGetMessenger(args, isStret = false)
IntrinsicType.OBJC_GET_MESSENGER_STRET -> emitObjCGetMessenger(args, isStret = true)
IntrinsicType.OBJC_GET_OBJC_CLASS -> emitGetObjCClass(callSite)
IntrinsicType.OBJC_GET_RECEIVER_OR_SUPER -> emitGetReceiverOrSuper(args)
IntrinsicType.GET_CLASS_TYPE_INFO -> emitGetClassTypeInfo(callSite)
IntrinsicType.READ_BITS -> emitReadBits(args)
IntrinsicType.WRITE_BITS -> emitWriteBits(args)
IntrinsicType.READ_PRIMITIVE -> emitReadPrimitive(callSite, args)
IntrinsicType.WRITE_PRIMITIVE -> emitWritePrimitive(callSite, args)
IntrinsicType.GET_POINTER_SIZE -> emitGetPointerSize()
IntrinsicType.CREATE_UNINITIALIZED_INSTANCE -> emitCreateUninitializedInstance(callSite)
IntrinsicType.NATIVE_PTR_TO_LONG -> emitNativePtrToLong(callSite, args)
IntrinsicType.NATIVE_PTR_PLUS_LONG -> emitNativePtrPlusLong(args)
IntrinsicType.GET_NATIVE_NULL_PTR -> emitGetNativeNullPtr()
IntrinsicType.LIST_OF_INTERNAL -> emitListOfInternal(callSite, args)
IntrinsicType.IDENTITY -> emitIdentity(args)
IntrinsicType.GET_CONTINUATION -> emitGetContinuation()
}
private fun FunctionGenerationContext.emitGetContinuation(): LLVMValueRef =
continuationProvider()
private fun FunctionGenerationContext.emitIdentity(args: List<LLVMValueRef>): LLVMValueRef =
args.single()
private fun FunctionGenerationContext.emitListOfInternal(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
val varargExpression = callSite.getValueArgument(0) as IrVararg
val vararg = args.single()
val length = varargExpression.elements.size
// TODO: store length in `vararg` itself when more abstract types will be used for values.
val array = constPointer(vararg)
// Note: dirty hack here: `vararg` has type `Array<out E>`, but `createConstArrayList` expects `Array<E>`;
// however `vararg` is immutable, and in current implementation it has type `Array<E>`,
// so let's ignore this mismatch currently for simplicity.
return context.llvm.staticData.createConstArrayList(array, length).llvm
}
private fun FunctionGenerationContext.emitGetNativeNullPtr(): LLVMValueRef =
kNullInt8Ptr
private fun FunctionGenerationContext.emitNativePtrPlusLong(args: List<LLVMValueRef>): LLVMValueRef =
gep(args[0], args[1])
private fun FunctionGenerationContext.emitNativePtrToLong(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
val intPtrValue = ptrToInt(args.single(), codegen.intPtrType)
val resultType = callSite.llvmReturnType
return if (resultType == intPtrValue.type) {
intPtrValue
} else {
LLVMBuildSExt(builder, intPtrValue, resultType, "")!!
}
assert(result.type == callSite.llvmReturnType) {
"Substitution of ${callSite.symbol.owner.functionName} has wrong result type"
}
private fun FunctionGenerationContext.emitCreateUninitializedInstance(callSite: IrCall): LLVMValueRef {
val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0]
val enumClass = callSite.getTypeArgument(typeParameterT)!!
val enumIrClass = enumClass.getClass()!!
return allocInstance(enumIrClass, lifetimeCalculator(callSite))
}
private fun FunctionGenerationContext.emitGetPointerSize(): LLVMValueRef =
Int32(LLVMPointerSize(codegen.llvmTargetData)).llvm
private fun FunctionGenerationContext.emitReadPrimitive(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
val pointerType = pointerType(callSite.llvmReturnType)
val rawPointer = args.last()
val pointer = bitcast(pointerType, rawPointer)
return load(pointer)
}
private fun FunctionGenerationContext.emitWritePrimitive(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
val function = callSite.symbol.owner
val pointerType = pointerType(codegen.getLLVMType(function.valueParameters.last().type))
val rawPointer = args[1]
val pointer = bitcast(pointerType, rawPointer)
store(args[2], pointer)
return codegen.theUnitInstanceRef.llvm
}
private fun FunctionGenerationContext.emitReadBits(args: List<LLVMValueRef>): LLVMValueRef {
val ptr = args[0]
assert(ptr.type == int8TypePtr)
val offset = extractConstUnsignedInt(args[1])
val size = extractConstUnsignedInt(args[2]).toInt()
val signed = extractConstUnsignedInt(args[3]) != 0L
val prefixBitsNum = (offset % 8).toInt()
val suffixBitsNum = (8 - ((size + offset) % 8).toInt()) % 8
// Note: LLVM allows to read without padding tail up to byte boundary, but the result seems to be incorrect.
val bitsWithPaddingNum = prefixBitsNum + size + suffixBitsNum
val bitsWithPaddingType = LLVMIntType(bitsWithPaddingNum)!!
val bitsWithPaddingPtr = bitcast(org.jetbrains.kotlin.backend.konan.llvm.pointerType(bitsWithPaddingType), gep(ptr, org.jetbrains.kotlin.backend.konan.llvm.Int64(offset / 8).llvm))
val bitsWithPadding = load(bitsWithPaddingPtr).setUnaligned()
val bits = shr(
shl(bitsWithPadding, suffixBitsNum),
prefixBitsNum + suffixBitsNum, signed
)
return when {
bitsWithPaddingNum == 64 -> bits
bitsWithPaddingNum > 64 -> trunc(bits, org.jetbrains.kotlin.backend.konan.llvm.int64Type)
else -> ext(bits, org.jetbrains.kotlin.backend.konan.llvm.int64Type, signed)
}
return result
}
private fun FunctionGenerationContext.emitWriteBits(args: List<LLVMValueRef>): LLVMValueRef {
val ptr = args[0]
assert(ptr.type == int8TypePtr)
val offset = extractConstUnsignedInt(args[1])
val size = extractConstUnsignedInt(args[2]).toInt()
val value = args[3]
assert(value.type == int64Type)
val bitsType = LLVMIntType(size)!!
val prefixBitsNum = (offset % 8).toInt()
val suffixBitsNum = (8 - ((size + offset) % 8).toInt()) % 8
val bitsWithPaddingNum = prefixBitsNum + size + suffixBitsNum
val bitsWithPaddingType = LLVMIntType(bitsWithPaddingNum)!!
// 0011111000:
val discardBitsMask = LLVMConstShl(
LLVMConstZExt(
LLVMConstAllOnes(bitsType), // 11111
bitsWithPaddingType
), // 1111100000
LLVMConstInt(bitsWithPaddingType, prefixBitsNum.toLong(), 0)
)
val preservedBitsMask = LLVMConstNot(discardBitsMask)!!
val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(ptr, Int64(offset / 8).llvm))
val bits = trunc(value, bitsType)
val bitsToStore = if (prefixBitsNum == 0 && suffixBitsNum == 0) {
bits
} else {
val previousValue = load(bitsWithPaddingPtr).setUnaligned()
val preservedBits = and(previousValue, preservedBitsMask)
val bitsWithPadding = shl(zext(bits, bitsWithPaddingType), prefixBitsNum)
or(bitsWithPadding, preservedBits)
}
llvm.LLVMBuildStore(builder, bitsToStore, bitsWithPaddingPtr)!!.setUnaligned()
return codegen.theUnitInstanceRef.llvm
}
private fun extractConstUnsignedInt(value: LLVMValueRef): Long {
assert(LLVMIsConstant(value) != 0)
return LLVMConstIntGetZExtValue(value)
}
private fun FunctionGenerationContext.emitGetClassTypeInfo(callSite: IrCall): LLVMValueRef {
val typeArgument = callSite.getTypeArgument(0)!!
val typeArgumentClass = typeArgument.getClass()
return if (typeArgumentClass == null) {
// Should not happen anymore, but it is safer to handle this case.
unreachable()
kNullInt8Ptr
} else {
val typeInfo = codegen.typeInfoValue(typeArgumentClass)
LLVMConstBitCast(typeInfo, kInt8Ptr)!!
}
}
private fun FunctionGenerationContext.emitGetReceiverOrSuper(args: List<LLVMValueRef>): LLVMValueRef {
assert(args.size == 2)
val receiver = args[0]
val superClass = args[1]
val superClassIsNull = icmpEq(superClass, kNullInt8Ptr)
return ifThenElse(superClassIsNull, receiver) {
val structType = structType(kInt8Ptr, kInt8Ptr)
val ptr = alloca(structType)
store(receiver, LLVMBuildGEP(builder, ptr, cValuesOf(kImmZero, kImmZero), 2, "")!!)
store(superClass, LLVMBuildGEP(builder, ptr, cValuesOf(kImmZero, kImmOne), 2, "")!!)
bitcast(int8TypePtr, ptr)
}
}
// TODO: Find better place for these guys.
private val kImmZero = LLVMConstInt(LLVMInt32Type(), 0, 1)!!
private val kImmOne = LLVMConstInt(LLVMInt32Type(), 1, 1)!!
private fun FunctionGenerationContext.emitGetObjCClass(callSite: IrCall): LLVMValueRef {
val descriptor = callSite.descriptor.original
val typeArgument = callSite.getTypeArgument(descriptor.typeParameters.single())
return getObjCClass(typeArgument!!.getClass()!!, exceptionHandlerProvider())
}
private fun FunctionGenerationContext.emitObjCGetMessenger(args: List<LLVMValueRef>, isStret: Boolean): LLVMValueRef {
val messengerNameSuffix = if (isStret) "_stret" else ""
val functionType = functionType(int8TypePtr, true, int8TypePtr, int8TypePtr)
val libobjc = context.standardLlvmSymbolsOrigin
val normalMessenger = context.llvm.externalFunction(
"objc_msgSend$messengerNameSuffix",
functionType,
origin = libobjc
)
val superMessenger = context.llvm.externalFunction(
"objc_msgSendSuper$messengerNameSuffix",
functionType,
origin = libobjc
)
val superClass = args.single()
val messenger = LLVMBuildSelect(builder,
If = icmpEq(superClass, kNullInt8Ptr),
Then = normalMessenger,
Else = superMessenger,
Name = ""
)!!
return bitcast(int8TypePtr, messenger)
}
private fun FunctionGenerationContext.emitAreEqualByValue(args: List<LLVMValueRef>): LLVMValueRef {
val (first, second) = args
assert (first.type == second.type) { "Types are different: '${llvmtype2string(first.type)}' and '${llvmtype2string(second.type)}'" }
return when (val typeKind = LLVMGetTypeKind(first.type)) {
llvm.LLVMTypeKind.LLVMFloatTypeKind, llvm.LLVMTypeKind.LLVMDoubleTypeKind -> {
val numBits = llvm.LLVMSizeOfTypeInBits(codegen.llvmTargetData, first.type).toInt()
val integerType = llvm.LLVMIntType(numBits)!!
icmpEq(bitcast(integerType, first), bitcast(integerType, second))
}
llvm.LLVMTypeKind.LLVMIntegerTypeKind, llvm.LLVMTypeKind.LLVMPointerTypeKind -> icmpEq(first, second)
else -> error(typeKind)
}
}
private fun FunctionGenerationContext.emitIeee754Equals(args: List<LLVMValueRef>): LLVMValueRef {
val (first, second) = args
assert (first.type == second.type)
{ "Types are different: '${llvmtype2string(first.type)}' and '${llvmtype2string(second.type)}'" }
val type = LLVMGetTypeKind(first.type)
assert (type == LLVMTypeKind.LLVMFloatTypeKind || type == LLVMTypeKind.LLVMDoubleTypeKind)
{ "Should be of floating point kind, not: '${llvmtype2string(first.type)}'"}
return fcmpEq(first, second)
}
private fun FunctionGenerationContext.emitReinterpret(callSite: IrCall, args: List<LLVMValueRef>) =
@@ -196,18 +474,18 @@ internal class IntrinsicGenerator(val codegen: CodeGenerator) {
}!!
}
private fun FunctionGenerationContext.emitThrowIfZero(divider: LLVMValueRef, exceptionHandler: ExceptionHandler) {
private fun FunctionGenerationContext.emitThrowIfZero(divider: LLVMValueRef) {
ifThen(icmpEq(divider, Zero(divider.type).llvm)) {
val throwArithExc = codegen.llvmFunction(context.ir.symbols.throwArithmeticException.owner)
call(throwArithExc, emptyList(), Lifetime.GLOBAL, exceptionHandler)
call(throwArithExc, emptyList(), Lifetime.GLOBAL, exceptionHandlerProvider())
unreachable()
}
}
private fun FunctionGenerationContext.emitSignedDiv(args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
private fun FunctionGenerationContext.emitSignedDiv(args: List<LLVMValueRef>): LLVMValueRef {
val (first, second) = args
if (!second.type.isFloatingPoint()) {
emitThrowIfZero(second, exceptionHandler)
emitThrowIfZero(second)
}
return if (first.type.isFloatingPoint()) {
LLVMBuildFDiv(builder, first, second, "")
@@ -216,10 +494,10 @@ internal class IntrinsicGenerator(val codegen: CodeGenerator) {
}!!
}
private fun FunctionGenerationContext.emitSignedRem(args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
private fun FunctionGenerationContext.emitSignedRem(args: List<LLVMValueRef>): LLVMValueRef {
val (first, second) = args
if (!second.type.isFloatingPoint()) {
emitThrowIfZero(second, exceptionHandler)
emitThrowIfZero(second)
}
return if (first.type.isFloatingPoint()) {
LLVMBuildFRem(builder, first, second, "")
@@ -228,15 +506,15 @@ internal class IntrinsicGenerator(val codegen: CodeGenerator) {
}!!
}
private fun FunctionGenerationContext.emitUnsignedDiv(args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
private fun FunctionGenerationContext.emitUnsignedDiv(args: List<LLVMValueRef>): LLVMValueRef {
val (first, second) = args
emitThrowIfZero(second, exceptionHandler)
emitThrowIfZero(second)
return LLVMBuildUDiv(builder, first, second, "")!!
}
private fun FunctionGenerationContext.emitUnsignedRem(args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
private fun FunctionGenerationContext.emitUnsignedRem(args: List<LLVMValueRef>): LLVMValueRef {
val (first, second) = args
emitThrowIfZero(second, exceptionHandler)
emitThrowIfZero(second)
return LLVMBuildURem(builder, first, second, "")!!
}
@@ -291,13 +291,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
val codegen = CodeGenerator(context)
val intrinsicGenerator = IntrinsicGenerator(codegen)
//-------------------------------------------------------------------------//
// TODO: consider eliminating mutable state
private var currentCodeContext: CodeContext = TopLevelCodeContext
private val intrinsicGenerator = IntrinsicGenerator(codegen,
::resultLifetime, ::getContinuation, { currentCodeContext.exceptionHandler })
/**
* Fake [CodeContext] that doesn't support any operation.
@@ -1799,8 +1798,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
return codegen.theUnitInstanceRef.llvm
}
//-------------------------------------------------------------------------//
// TODO: should be unified with other intrinsics
private fun evaluateSpecialIntrinsicCall(expression: IrFunctionAccessExpression): LLVMValueRef? {
val function = expression.symbol.owner
@@ -2097,8 +2095,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
args + getContinuation()
else args
return when {
function.isTypedIntrinsic -> intrinsicGenerator.evaluateCall(callee, args, functionGenerationContext, currentCodeContext.exceptionHandler)
function.isIntrinsic -> evaluateIntrinsicCall(callee, argsWithContinuationIfNeeded)
function.isTypedIntrinsic -> intrinsicGenerator.evaluateCall(callee, args, functionGenerationContext)
function.isIntrinsic -> context.reportCompilationError("Unexpected @Intrinsic function: ${function.name.asString()}")
function.origin == IrDeclarationOrigin.IR_BUILTINS_STUB -> evaluateOperatorCall(callee, argsWithContinuationIfNeeded)
function is ConstructorDescriptor -> evaluateConstructorCall(callee, argsWithContinuationIfNeeded)
else -> evaluateSimpleFunctionCall(function, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifierSymbol?.owner)
@@ -2198,233 +2196,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
}
}
//-------------------------------------------------------------------------//
// TODO: Move to [IntrinsicsGenerator]
private fun evaluateIntrinsicCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
val descriptor = callee.descriptor.original
val function = callee.symbol.owner
val name = descriptor.fqNameUnsafe.asString()
when (name) {
"kotlin.native.internal.areEqualByValue" -> {
val arg0 = args[0]
val arg1 = args[1]
assert (arg0.type == arg1.type,
{ "Types are different: '${llvmtype2string(arg0.type)}' and '${llvmtype2string(arg1.type)}'" })
val typeKind = LLVMGetTypeKind(arg0.type)
with (functionGenerationContext) {
return when (typeKind) {
LLVMTypeKind.LLVMFloatTypeKind, LLVMTypeKind.LLVMDoubleTypeKind -> {
val numBits = LLVMSizeOfTypeInBits(codegen.llvmTargetData, arg0.type).toInt()
val integerType = LLVMIntType(numBits)!!
icmpEq(bitcast(integerType, arg0), bitcast(integerType, arg1))
}
LLVMTypeKind.LLVMIntegerTypeKind, LLVMTypeKind.LLVMPointerTypeKind -> icmpEq(arg0, arg1)
else -> error(typeKind)
}
}
}
"kotlin.native.internal.ieee754Equals" -> {
val arg0 = args[0]
val arg1 = args[1]
assert (arg0.type == arg1.type,
{ "Types are different: '${llvmtype2string(arg0.type)}' and '${llvmtype2string(arg1.type)}'" })
val type = LLVMGetTypeKind(arg0.type)
assert (type == LLVMTypeKind.LLVMFloatTypeKind || type == LLVMTypeKind.LLVMDoubleTypeKind,
{ "Should be of floating point kind, not: '${llvmtype2string(arg0.type)}'"})
return functionGenerationContext.fcmpEq(arg0, arg1)
}
"kotlin.native.internal.getContinuation" -> return getContinuation()
}
val interop = context.interopBuiltIns
return when (descriptor) {
interop.interpretNullablePointed, interop.interpretCPointer,
interop.nativePointedGetRawPointer, interop.cPointerGetRawValue, // TODO: implement through `reinterpret`
context.ir.symbols.reinterpret.descriptor -> args.single()
in interop.readPrimitive -> {
val pointerType = pointerType(codegen.getLLVMType(function.returnType))
val rawPointer = args.last()
val pointer = functionGenerationContext.bitcast(pointerType, rawPointer)
functionGenerationContext.load(pointer)
}
in interop.writePrimitive -> {
val pointerType = pointerType(codegen.getLLVMType(function.valueParameters.last().type))
val rawPointer = args[1]
val pointer = functionGenerationContext.bitcast(pointerType, rawPointer)
functionGenerationContext.store(args[2], pointer)
codegen.theUnitInstanceRef.llvm
}
context.nativePtrPlusLong -> functionGenerationContext.gep(args[0], args[1])
context.getNativeNullPtr -> kNullInt8Ptr
interop.getPointerSize -> Int32(LLVMPointerSize(codegen.llvmTargetData)).llvm
context.nativePtrToLong -> {
val intPtrValue = functionGenerationContext.ptrToInt(args.single(), codegen.intPtrType)
val resultType = functionGenerationContext.getLLVMType(function.returnType)
if (resultType == intPtrValue.type) {
intPtrValue
} else {
LLVMBuildSExt(functionGenerationContext.builder, intPtrValue, resultType, "")!!
}
}
interop.getObjCReceiverOrSuper -> {
genGetObjCReceiverOrSuper(args)
}
interop.getObjCClass -> {
val typeArgument = callee.getTypeArgument(descriptor.typeParameters.single())
val irClass = typeArgument!!.getClass()!!
genGetObjCClass(irClass)
}
interop.getObjCMessenger -> {
genGetObjCMessenger(args, isStret = false)
}
interop.getObjCMessengerStret -> {
genGetObjCMessenger(args, isStret = true)
}
interop.readBits -> genReadBits(args)
interop.writeBits -> genWriteBits(args)
context.ir.symbols.getClassTypeInfo.descriptor -> {
val typeArgument = callee.getTypeArgument(0)!!
val typeArgumentClass = typeArgument.getClass()
if (typeArgumentClass == null) {
// Should not happen anymore, but it is safer to handle this case.
functionGenerationContext.unreachable()
kNullInt8Ptr
} else {
val typeInfo = codegen.typeInfoValue(typeArgumentClass)
LLVMConstBitCast(typeInfo, kInt8Ptr)!!
}
}
context.ir.symbols.createUninitializedInstance.descriptor -> {
val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0]
val enumClass = callee.getTypeArgument(typeParameterT)!!
val enumIrClass = enumClass.getClass()!!
functionGenerationContext.allocInstance(enumIrClass, resultLifetime(callee))
}
context.ir.symbols.listOfInternal.descriptor -> {
val varargExpression = callee.getValueArgument(0) as IrVararg
val vararg = args.single()
val length = varargExpression.elements.size
// TODO: store length in `vararg` itself when more abstract types will be used for values.
val array = constPointer(vararg)
// Note: dirty hack here: `vararg` has type `Array<out E>`, but `createConstArrayList` expects `Array<E>`;
// however `vararg` is immutable, and in current implementation it has type `Array<E>`,
// so let's ignore this mismatch currently for simplicity.
return context.llvm.staticData.createConstArrayList(array, length).llvm
}
else -> TODO(callee.descriptor.original.toString())
}
}
private fun genReadBits(args: List<LLVMValueRef>): LLVMValueRef {
val ptr = args[0]
assert(ptr.type == int8TypePtr)
val offset = extractConstUnsignedInt(args[1])
val size = extractConstUnsignedInt(args[2]).toInt()
val signed = extractConstUnsignedInt(args[3]) != 0L
val prefixBitsNum = (offset % 8).toInt()
val suffixBitsNum = (8 - ((size + offset) % 8).toInt()) % 8
// Note: LLVM allows to read without padding tail up to byte boundary, but the result seems to be incorrect.
val bitsWithPaddingNum = prefixBitsNum + size + suffixBitsNum
val bitsWithPaddingType = LLVMIntType(bitsWithPaddingNum)!!
with (functionGenerationContext) {
val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(ptr, Int64(offset / 8).llvm))
val bitsWithPadding = load(bitsWithPaddingPtr).setUnaligned()
val bits = shr(
shl(bitsWithPadding, suffixBitsNum),
prefixBitsNum + suffixBitsNum, signed
)
return if (bitsWithPaddingNum == 64) {
bits
} else if (bitsWithPaddingNum > 64) {
trunc(bits, int64Type)
} else {
ext(bits, int64Type, signed)
}
}
}
private fun genWriteBits(args: List<LLVMValueRef>): LLVMValueRef {
val ptr = args[0]
assert(ptr.type == int8TypePtr)
val offset = extractConstUnsignedInt(args[1])
val size = extractConstUnsignedInt(args[2]).toInt()
val value = args[3]
assert(value.type == int64Type)
val bitsType = LLVMIntType(size)!!
val prefixBitsNum = (offset % 8).toInt()
val suffixBitsNum = (8 - ((size + offset) % 8).toInt()) % 8
val bitsWithPaddingNum = prefixBitsNum + size + suffixBitsNum
val bitsWithPaddingType = LLVMIntType(bitsWithPaddingNum)!!
// 0011111000:
val discardBitsMask = LLVMConstShl(
LLVMConstZExt(
LLVMConstAllOnes(bitsType), // 11111
bitsWithPaddingType
), // 1111100000
LLVMConstInt(bitsWithPaddingType, prefixBitsNum.toLong(), 0)
)
val preservedBitsMask = LLVMConstNot(discardBitsMask)!!
with (functionGenerationContext) {
val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(ptr, Int64(offset / 8).llvm))
val bits = trunc(value, bitsType)
val bitsToStore = if (prefixBitsNum == 0 && suffixBitsNum == 0) {
bits
} else {
val previousValue = load(bitsWithPaddingPtr).setUnaligned()
val preservedBits = and(previousValue, preservedBitsMask)
val bitsWithPadding = shl(zext(bits, bitsWithPaddingType), prefixBitsNum)
or(bitsWithPadding, preservedBits)
}
LLVMBuildStore(builder, bitsToStore, bitsWithPaddingPtr)!!.setUnaligned()
}
return codegen.theUnitInstanceRef.llvm
}
private fun extractConstUnsignedInt(value: LLVMValueRef): Long {
assert(LLVMIsConstant(value) != 0)
return LLVMConstIntGetZExtValue(value)
}
private fun genGetObjCClass(classDescriptor: ClassDescriptor): LLVMValueRef {
return functionGenerationContext.getObjCClass(classDescriptor, currentCodeContext.exceptionHandler)
}
@@ -2446,64 +2217,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
return call(protocolGetter, emptyList())
}
private fun genGetObjCMessenger(args: List<LLVMValueRef>, isStret: Boolean): LLVMValueRef {
val gen = functionGenerationContext
val messengerNameSuffix = if (isStret) "_stret" else ""
val functionType = functionType(int8TypePtr, true, int8TypePtr, int8TypePtr)
val libobjc = context.standardLlvmSymbolsOrigin
val normalMessenger = context.llvm.externalFunction(
"objc_msgSend$messengerNameSuffix",
functionType,
origin = libobjc
)
val superMessenger = context.llvm.externalFunction(
"objc_msgSendSuper$messengerNameSuffix",
functionType,
origin = libobjc
)
val superClass = args.single()
val messenger = LLVMBuildSelect(gen.builder,
If = gen.icmpEq(superClass, kNullInt8Ptr),
Then = normalMessenger,
Else = superMessenger,
Name = ""
)!!
return gen.bitcast(int8TypePtr, messenger)
}
private fun genGetObjCReceiverOrSuper(args: List<LLVMValueRef>): LLVMValueRef {
val gen = functionGenerationContext
assert(args.size == 2)
val receiver = args[0]
val superClass = args[1]
val superClassIsNull = gen.icmpEq(superClass, kNullInt8Ptr)
return gen.ifThenElse(superClassIsNull, receiver) {
val structType = structType(kInt8Ptr, kInt8Ptr)
val ptr = gen.alloca(structType)
gen.store(receiver,
LLVMBuildGEP(gen.builder, ptr, cValuesOf(kImmZero, kImmZero), 2, "")!!)
gen.store(superClass,
LLVMBuildGEP(gen.builder, ptr, cValuesOf(kImmZero, kImmOne), 2, "")!!)
gen.bitcast(int8TypePtr, ptr)
}
}
//-------------------------------------------------------------------------//
private val kImmZero = LLVMConstInt(LLVMInt32Type(), 0, 1)!!
private val kImmOne = LLVMConstInt(LLVMInt32Type(), 1, 1)!!
private val kTrue = LLVMConstInt(LLVMInt1Type(), 1, 1)!!
private val kFalse = LLVMConstInt(LLVMInt1Type(), 0, 1)!!
// TODO: Intrinsify?
private fun evaluateOperatorCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
context.log{"evaluateOperatorCall : origin:${ir2string(callee)}"}
val descriptor = callee.symbol.owner
+2 -2
View File
@@ -71,7 +71,7 @@ public actual inline fun Double.toRawBits(): Long = bits()
public actual inline fun Double.Companion.fromBits(bits: Long): Double = kotlin.fromBits(bits)
@PublishedApi
@TypedIntrinsic(IntrinsicType.FROM_BITS)
@TypedIntrinsic(IntrinsicType.REINTERPRET)
external internal fun fromBits(bits: Long): Double
/**
@@ -99,5 +99,5 @@ public actual inline fun Float.toRawBits(): Int = bits()
public actual inline fun Float.Companion.fromBits(bits: Int): Float = kotlin.fromBits(bits)
@PublishedApi
@TypedIntrinsic(IntrinsicType.FROM_BITS)
@TypedIntrinsic(IntrinsicType.REINTERPRET)
external internal fun fromBits(bits: Int): Float
+2 -2
View File
@@ -1174,7 +1174,7 @@ public final class Float private constructor(private val value: kotlin.native.in
return bits()
}
@TypedIntrinsic(IntrinsicType.TO_BITS)
@TypedIntrinsic(IntrinsicType.REINTERPRET)
@PublishedApi
external internal fun bits(): Int
}
@@ -1396,7 +1396,7 @@ public final class Double private constructor(private val value: kotlin.native.i
public override fun hashCode(): Int = bits().hashCode()
@TypedIntrinsic(IntrinsicType.TO_BITS)
@TypedIntrinsic(IntrinsicType.REINTERPRET)
@PublishedApi
external internal fun bits(): Long
}
@@ -13,7 +13,7 @@ import kotlin.coroutines.intrinsics.*
internal inline suspend fun <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T =
returnIfSuspended<T>(block(getContinuation<T>()))
@Intrinsic
@TypedIntrinsic(IntrinsicType.GET_CONTINUATION)
@PublishedApi
internal external fun <T> getContinuation(): Continuation<T>
@@ -2,6 +2,7 @@ package kotlin.native.internal
class IntrinsicType {
companion object {
// Arithmetic
const val PLUS = "PLUS"
const val MINUS = "MINUS"
const val TIMES = "TIMES"
@@ -31,7 +32,30 @@ class IntrinsicType {
const val SIGNED_COMPARE_TO = "SIGNED_COMPARE_TO"
const val UNSIGNED_COMPARE_TO = "UNSIGNED_COMPARE_TO"
const val NOT = "NOT"
const val TO_BITS = "TO_BITS"
const val FROM_BITS = "FROM_BITS"
const val REINTERPRET = "REINTERPRET"
const val ARE_EQUAL_BY_VALUE = "ARE_EQUAL_BY_VALUE"
const val IEEE_754_EQUALS = "IEEE_754_EQUALS"
// ObjC related stuff
const val OBJC_GET_MESSENGER = "OBJC_GET_MESSENGER"
const val OBJC_GET_MESSENGER_STRET = "OBJC_GET_MESSENGER_STRET"
const val OBJC_GET_OBJC_CLASS = "OBJC_GET_OBJC_CLASS"
const val OBJC_GET_RECEIVER_OR_SUPER = "OBJC_GET_RECEIVER_OR_SUPER"
// Other
const val GET_CLASS_TYPE_INFO = "GET_CLASS_TYPE_INFO"
const val READ_BITS = "READ_BITS"
const val WRITE_BITS = "WRITE_BITS"
const val CREATE_UNINITIALIZED_INSTANCE = "CREATE_UNINITIALIZED_INSTANCE"
const val LIST_OF_INTERNAL = "LIST_OF_INTERNAL"
const val IDENTITY = "IDENTITY"
const val GET_CONTINUATION = "GET_CONTINUATION"
// Interop
const val READ_PRIMITIVE = "READ_PRIMITIVE"
const val WRITE_PRIMITIVE = "WRITE_PRIMITIVE"
const val GET_POINTER_SIZE = "GET_POINTER_SIZE"
const val NATIVE_PTR_TO_LONG = "NATIVE_PTR_TO_LONG"
const val NATIVE_PTR_PLUS_LONG = "NATIVE_PTR_PLUS_LONG"
const val GET_NATIVE_NULL_PTR = "GET_NATIVE_NULL_PTR"
}
}
@@ -9,20 +9,23 @@ import kotlinx.cinterop.CPointer
import kotlinx.cinterop.NativePointed
import kotlinx.cinterop.NativePtr
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Boolean, second: Boolean): Boolean
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Byte, second: Byte): Boolean
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Short, second: Short): Boolean
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Int, second: Int): Boolean
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Long, second: Long): Boolean
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: NativePtr, second: NativePtr): Boolean
import kotlin.native.internal.TypedIntrinsic
import kotlin.native.internal.IntrinsicType
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Boolean, second: Boolean): Boolean
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Byte, second: Byte): Boolean
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Short, second: Short): Boolean
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Int, second: Int): Boolean
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Long, second: Long): Boolean
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: NativePtr, second: NativePtr): Boolean
// Bitwise equality:
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Float, second: Float): Boolean
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Double, second: Double): Boolean
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Float, second: Float): Boolean
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Double, second: Double): Boolean
// IEEE754 equality:
@Intrinsic @PublishedApi external internal fun ieee754Equals(first: Float, second: Float): Boolean
@Intrinsic @PublishedApi external internal fun ieee754Equals(first: Double, second: Double): Boolean
@TypedIntrinsic(IntrinsicType.IEEE_754_EQUALS) @PublishedApi external internal fun ieee754Equals(first: Float, second: Float): Boolean
@TypedIntrinsic(IntrinsicType.IEEE_754_EQUALS) @PublishedApi external internal fun ieee754Equals(first: Double, second: Double): Boolean
// Reinterprets this value from T to R having the same binary representation (e.g. to unwrap inline class).
@Intrinsic @PublishedApi external internal fun <T, R> T.reinterpret(): R
@TypedIntrinsic(IntrinsicType.IDENTITY) @PublishedApi external internal fun <T, R> T.reinterpret(): R
@@ -62,7 +62,7 @@ internal class KClassUnsupportedImpl(private val message: String) : KClass<Any>
internal external fun getObjectTypeInfo(obj: Any): NativePtr
@ExportForCompiler
@Intrinsic
@TypedIntrinsic(IntrinsicType.GET_CLASS_TYPE_INFO)
internal external inline fun <reified T : Any> getClassTypeInfo(): NativePtr
@SymbolName("Kotlin_TypeInfo_getPackageName")
@@ -7,16 +7,19 @@
package kotlin.native.internal
@Intrinsic external fun getNativeNullPtr(): NativePtr
@TypedIntrinsic(IntrinsicType.GET_NATIVE_NULL_PTR)
external fun getNativeNullPtr(): NativePtr
class NativePtr @PublishedApi internal constructor(private val value: NonNullNativePtr?) {
companion object {
val NULL = getNativeNullPtr()
}
@Intrinsic external operator fun plus(offset: Long): NativePtr
@TypedIntrinsic(IntrinsicType.NATIVE_PTR_PLUS_LONG)
external operator fun plus(offset: Long): NativePtr
@Intrinsic external fun toLong(): Long
@TypedIntrinsic(IntrinsicType.NATIVE_PTR_TO_LONG)
external fun toLong(): Long
override fun equals(other: Any?) = (other is NativePtr) && kotlin.native.internal.areEqualByValue(this, other)
@@ -117,7 +117,7 @@ fun <T: Enum<T>> valuesForEnum(values: Array<T>): Array<T> {
return result as Array<T>
}
@Intrinsic
@TypedIntrinsic(IntrinsicType.CREATE_UNINITIALIZED_INSTANCE)
internal external fun <T> createUninitializedInstance(): T
@Intrinsic
@@ -150,7 +150,7 @@ fun KonanObjectToUtf8Array(value: Any?): ByteArray {
return string.toUtf8()
}
@Intrinsic
@TypedIntrinsic(IntrinsicType.LIST_OF_INTERNAL)
@PublishedApi
internal fun <T> listOfInternal(vararg elements: T): List<T> {
val result = ArrayList<T>(elements.size)
@@ -203,7 +203,7 @@ internal fun SearchPathResolverWithTarget.libraryMatch(candidate: KonanLibraryIm
val candidateAbiVersion = candidate.versions.abiVersion
val candidateLibraryVersion = candidate.versions.libraryVersion
if (resolverTarget != null && !candidate.targetList.contains(resolverTarget.visibleName)) {
if (!candidate.targetList.contains(resolverTarget.visibleName)) {
logger("skipping $candidatePath. The target doesn't match. Expected '$resolverTarget', found ${candidate.targetList}")
return false
}