Move more intrinsics under TypedIntrinsic annotation (#2474)
This commit is contained in:
@@ -18,37 +18,40 @@ package kotlinx.cinterop
|
|||||||
|
|
||||||
import kotlin.native.*
|
import kotlin.native.*
|
||||||
import kotlin.native.internal.Intrinsic
|
import kotlin.native.internal.Intrinsic
|
||||||
|
import kotlin.native.internal.TypedIntrinsic
|
||||||
|
import kotlin.native.internal.IntrinsicType
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal inline val pointerSize: Int
|
internal inline val pointerSize: Int
|
||||||
get() = getPointerSize()
|
get() = getPointerSize()
|
||||||
|
|
||||||
@PublishedApi
|
@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.
|
// TODO: do not use singleton because it leads to init-check on any access.
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal object nativeMemUtils {
|
internal object nativeMemUtils {
|
||||||
@Intrinsic external fun getByte(mem: NativePointed): Byte
|
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getByte(mem: NativePointed): Byte
|
||||||
@Intrinsic external fun putByte(mem: NativePointed, value: Byte)
|
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putByte(mem: NativePointed, value: Byte)
|
||||||
|
|
||||||
@Intrinsic external fun getShort(mem: NativePointed): Short
|
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getShort(mem: NativePointed): Short
|
||||||
@Intrinsic external fun putShort(mem: NativePointed, value: Short)
|
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putShort(mem: NativePointed, value: Short)
|
||||||
|
|
||||||
@Intrinsic external fun getInt(mem: NativePointed): Int
|
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getInt(mem: NativePointed): Int
|
||||||
@Intrinsic external fun putInt(mem: NativePointed, value: Int)
|
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putInt(mem: NativePointed, value: Int)
|
||||||
|
|
||||||
@Intrinsic external fun getLong(mem: NativePointed): Long
|
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getLong(mem: NativePointed): Long
|
||||||
@Intrinsic external fun putLong(mem: NativePointed, value: Long)
|
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putLong(mem: NativePointed, value: Long)
|
||||||
|
|
||||||
@Intrinsic external fun getFloat(mem: NativePointed): Float
|
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getFloat(mem: NativePointed): Float
|
||||||
@Intrinsic external fun putFloat(mem: NativePointed, value: Float)
|
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putFloat(mem: NativePointed, value: Float)
|
||||||
|
|
||||||
@Intrinsic external fun getDouble(mem: NativePointed): Double
|
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getDouble(mem: NativePointed): Double
|
||||||
@Intrinsic external fun putDouble(mem: NativePointed, value: Double)
|
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putDouble(mem: NativePointed, value: Double)
|
||||||
|
|
||||||
@Intrinsic external fun getNativePtr(mem: NativePointed): NativePtr
|
@TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getNativePtr(mem: NativePointed): NativePtr
|
||||||
@Intrinsic external fun putNativePtr(mem: NativePointed, value: NativePtr)
|
@TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putNativePtr(mem: NativePointed, value: NativePtr)
|
||||||
|
|
||||||
// TODO: optimize
|
// TODO: optimize
|
||||||
fun getByteArray(source: NativePointed, dest: ByteArray, length: Int) {
|
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")
|
@SymbolName("Kotlin_interop_free")
|
||||||
private external fun cfree(ptr: NativePtr)
|
private external fun cfree(ptr: NativePtr)
|
||||||
|
|
||||||
@Intrinsic external fun readBits(ptr: NativePtr, offset: Long, size: Int, signed: Boolean): Long
|
@TypedIntrinsic(IntrinsicType.READ_BITS)
|
||||||
@Intrinsic external fun writeBits(ptr: NativePtr, offset: Long, size: Int, value: Long)
|
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.reinterpret
|
||||||
import kotlin.native.internal.Intrinsic
|
import kotlin.native.internal.Intrinsic
|
||||||
import kotlin.native.internal.VolatileLambda
|
import kotlin.native.internal.VolatileLambda
|
||||||
|
import kotlin.native.internal.TypedIntrinsic
|
||||||
|
import kotlin.native.internal.IntrinsicType
|
||||||
|
|
||||||
typealias NativePtr = kotlin.native.internal.NativePtr
|
typealias NativePtr = kotlin.native.internal.NativePtr
|
||||||
internal typealias NonNullNativePtr = kotlin.native.internal.NonNullNativePtr
|
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
|
* @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.
|
* 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)"
|
internal fun CPointer<*>.cPointerToString() = "CPointer(raw=$rawValue)"
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
package kotlinx.cinterop
|
package kotlinx.cinterop
|
||||||
import kotlin.native.*
|
import kotlin.native.*
|
||||||
import kotlin.native.internal.ExportTypeInfo
|
import kotlin.native.internal.ExportTypeInfo
|
||||||
|
import kotlin.native.internal.TypedIntrinsic
|
||||||
|
import kotlin.native.internal.IntrinsicType
|
||||||
|
|
||||||
interface ObjCObject
|
interface ObjCObject
|
||||||
interface ObjCClass : ObjCObject
|
interface ObjCClass : ObjCObject
|
||||||
@@ -91,7 +93,8 @@ var <T : Any?> ObjCNotImplementedVar<T>.value: T
|
|||||||
typealias ObjCStringVarOf<T> = ObjCNotImplementedVar<T>
|
typealias ObjCStringVarOf<T> = ObjCNotImplementedVar<T>
|
||||||
typealias ObjCBlockVar<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)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
@@ -146,12 +149,14 @@ private fun allocObjCObject(clazz: NativePtr): NativePtr {
|
|||||||
return rawResult
|
return rawResult
|
||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.native.internal.Intrinsic
|
@TypedIntrinsic(IntrinsicType.OBJC_GET_OBJC_CLASS)
|
||||||
@kotlin.native.internal.ExportForCompiler
|
@kotlin.native.internal.ExportForCompiler
|
||||||
private external fun <T : ObjCObject> getObjCClass(): NativePtr
|
private external fun <T : ObjCObject> getObjCClass(): NativePtr
|
||||||
|
|
||||||
@kotlin.native.internal.Intrinsic external fun getMessenger(superClass: NativePtr): COpaquePointer?
|
@TypedIntrinsic(IntrinsicType.OBJC_GET_MESSENGER)
|
||||||
@kotlin.native.internal.Intrinsic external fun getMessengerStret(superClass: NativePtr): COpaquePointer?
|
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() {
|
internal class ObjCWeakReferenceImpl : kotlin.native.ref.WeakReferenceImpl() {
|
||||||
|
|||||||
-2
@@ -277,8 +277,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
|||||||
private val packageScope by lazy { builtIns.builtInsModule.getPackage(KonanFqNames.internalPackageName).memberScope }
|
private val packageScope by lazy { builtIns.builtInsModule.getPackage(KonanFqNames.internalPackageName).memberScope }
|
||||||
|
|
||||||
val nativePtr by lazy { packageScope.getContributedClassifier(NATIVE_PTR_NAME) as ClassDescriptor }
|
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 getNativeNullPtr by lazy { packageScope.getContributedFunctions("getNativeNullPtr").single() }
|
||||||
val immutableBlobOf by lazy {
|
val immutableBlobOf by lazy {
|
||||||
builtIns.builtInsModule.getPackage(KonanFqNames.packageName).memberScope.getContributedFunctions("immutableBlobOf").single()
|
builtIns.builtInsModule.getPackage(KonanFqNames.packageName).memberScope.getContributedFunctions("immutableBlobOf").single()
|
||||||
|
|||||||
-28
@@ -31,8 +31,6 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives:
|
|||||||
|
|
||||||
val packageScope = builtIns.builtInsModule.getPackage(InteropFqNames.packageName).memberScope
|
val packageScope = builtIns.builtInsModule.getPackage(InteropFqNames.packageName).memberScope
|
||||||
|
|
||||||
val getPointerSize = packageScope.getContributedFunctions("getPointerSize").single()
|
|
||||||
|
|
||||||
val nativePointed = packageScope.getContributedClass(InteropFqNames.nativePointedName)
|
val nativePointed = packageScope.getContributedClass(InteropFqNames.nativePointedName)
|
||||||
|
|
||||||
val cPointer = this.packageScope.getContributedClass(InteropFqNames.cPointerName)
|
val cPointer = this.packageScope.getContributedClass(InteropFqNames.cPointerName)
|
||||||
@@ -54,26 +52,8 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives:
|
|||||||
TypeUtils.getClassDescriptor(extensionReceiverParameter.type) == nativePointed
|
TypeUtils.getClassDescriptor(extensionReceiverParameter.type) == nativePointed
|
||||||
}
|
}
|
||||||
|
|
||||||
val interpretNullablePointed = packageScope.getContributedFunctions("interpretNullablePointed").single()
|
|
||||||
|
|
||||||
val interpretCPointer = packageScope.getContributedFunctions("interpretCPointer").single()
|
|
||||||
|
|
||||||
val typeOf = packageScope.getContributedFunctions("typeOf").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 bitsToFloat = packageScope.getContributedFunctions("bitsToFloat").single()
|
||||||
|
|
||||||
val bitsToDouble = packageScope.getContributedFunctions("bitsToDouble").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 convert = packageScope.getContributedFunctions("convert").toSet()
|
||||||
|
|
||||||
val readBits = packageScope.getContributedFunctions("readBits").single()
|
|
||||||
val writeBits = packageScope.getContributedFunctions("writeBits").single()
|
|
||||||
|
|
||||||
val cFunctionPointerInvokes = packageScope.getContributedFunctions(OperatorNameConventions.INVOKE.asString())
|
val cFunctionPointerInvokes = packageScope.getContributedFunctions(OperatorNameConventions.INVOKE.asString())
|
||||||
.filter {
|
.filter {
|
||||||
val extensionReceiverParameter = it.extensionReceiverParameter
|
val extensionReceiverParameter = it.extensionReceiverParameter
|
||||||
@@ -135,11 +112,6 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives:
|
|||||||
|
|
||||||
val objCObjectRawPtr = packageScope.getContributedFunctions("objcPtr").single()
|
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 interpretObjCPointerOrNull = packageScope.getContributedFunctions("interpretObjCPointerOrNull").single()
|
||||||
val interpretObjCPointer = packageScope.getContributedFunctions("interpretObjCPointer").single()
|
val interpretObjCPointer = packageScope.getContributedFunctions("interpretObjCPointer").single()
|
||||||
|
|
||||||
|
|||||||
+329
-51
@@ -1,9 +1,14 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.llvm
|
package org.jetbrains.kotlin.backend.konan.llvm
|
||||||
|
|
||||||
|
import kotlinx.cinterop.cValuesOf
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.TypedIntrinsic
|
import org.jetbrains.kotlin.backend.konan.descriptors.TypedIntrinsic
|
||||||
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
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.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
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
private enum class IntrinsicType {
|
private enum class IntrinsicType {
|
||||||
@@ -36,11 +41,35 @@ private enum class IntrinsicType {
|
|||||||
SIGNED_COMPARE_TO,
|
SIGNED_COMPARE_TO,
|
||||||
UNSIGNED_COMPARE_TO,
|
UNSIGNED_COMPARE_TO,
|
||||||
NOT,
|
NOT,
|
||||||
TO_BITS,
|
REINTERPRET,
|
||||||
FROM_BITS
|
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
|
private val context = codegen.context
|
||||||
|
|
||||||
@@ -54,48 +83,297 @@ internal class IntrinsicGenerator(val codegen: CodeGenerator) {
|
|||||||
return IntrinsicType.valueOf(value)
|
return IntrinsicType.valueOf(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun evaluateCall(callSite: IrCall, args: List<LLVMValueRef>, generationContext: FunctionGenerationContext, exceptionHandler: ExceptionHandler): LLVMValueRef =
|
fun evaluateCall(callSite: IrCall, args: List<LLVMValueRef>, generationContext: FunctionGenerationContext): LLVMValueRef =
|
||||||
generationContext.evaluateCall(callSite, args, exceptionHandler)
|
generationContext.evaluateCall(callSite, args)
|
||||||
|
|
||||||
// Assuming that we checked for `TypedIntrinsic` annotation presence.
|
// Assuming that we checked for `TypedIntrinsic` annotation presence.
|
||||||
private fun FunctionGenerationContext.evaluateCall(callSite: IrCall, args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
private fun FunctionGenerationContext.evaluateCall(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef =
|
||||||
val result = when (getIntrinsicType(callSite)) {
|
when (getIntrinsicType(callSite)) {
|
||||||
IntrinsicType.PLUS -> emitPlus(args)
|
IntrinsicType.PLUS -> emitPlus(args)
|
||||||
IntrinsicType.MINUS -> emitMinus(args)
|
IntrinsicType.MINUS -> emitMinus(args)
|
||||||
IntrinsicType.TIMES -> emitTimes(args)
|
IntrinsicType.TIMES -> emitTimes(args)
|
||||||
IntrinsicType.SIGNED_DIV -> emitSignedDiv(args, exceptionHandler)
|
IntrinsicType.SIGNED_DIV -> emitSignedDiv(args)
|
||||||
IntrinsicType.SIGNED_REM -> emitSignedRem(args, exceptionHandler)
|
IntrinsicType.SIGNED_REM -> emitSignedRem(args)
|
||||||
IntrinsicType.UNSIGNED_DIV -> emitUnsignedDiv(args, exceptionHandler)
|
IntrinsicType.UNSIGNED_DIV -> emitUnsignedDiv(args)
|
||||||
IntrinsicType.UNSIGNED_REM -> emitUnsignedRem(args, exceptionHandler)
|
IntrinsicType.UNSIGNED_REM -> emitUnsignedRem(args)
|
||||||
IntrinsicType.INC -> emitInc(args)
|
IntrinsicType.INC -> emitInc(args)
|
||||||
IntrinsicType.DEC -> emitDec(args)
|
IntrinsicType.DEC -> emitDec(args)
|
||||||
IntrinsicType.UNARY_PLUS -> emitUnaryPlus(args)
|
IntrinsicType.UNARY_PLUS -> emitUnaryPlus(args)
|
||||||
IntrinsicType.UNARY_MINUS -> emitUnaryMinus(args)
|
IntrinsicType.UNARY_MINUS -> emitUnaryMinus(args)
|
||||||
IntrinsicType.SHL -> emitShl(args)
|
IntrinsicType.SHL -> emitShl(args)
|
||||||
IntrinsicType.SHR -> emitShr(args)
|
IntrinsicType.SHR -> emitShr(args)
|
||||||
IntrinsicType.USHR -> emitUshr(args)
|
IntrinsicType.USHR -> emitUshr(args)
|
||||||
IntrinsicType.AND -> emitAnd(args)
|
IntrinsicType.AND -> emitAnd(args)
|
||||||
IntrinsicType.OR -> emitOr(args)
|
IntrinsicType.OR -> emitOr(args)
|
||||||
IntrinsicType.XOR -> emitXor(args)
|
IntrinsicType.XOR -> emitXor(args)
|
||||||
IntrinsicType.INV -> emitInv(args)
|
IntrinsicType.INV -> emitInv(args)
|
||||||
IntrinsicType.SIGNED_COMPARE_TO -> emitSignedCompareTo(args)
|
IntrinsicType.SIGNED_COMPARE_TO -> emitSignedCompareTo(args)
|
||||||
IntrinsicType.UNSIGNED_COMPARE_TO -> emitUnsignedCompareTo(args)
|
IntrinsicType.UNSIGNED_COMPARE_TO -> emitUnsignedCompareTo(args)
|
||||||
IntrinsicType.NOT -> emitNot(args)
|
IntrinsicType.NOT -> emitNot(args)
|
||||||
IntrinsicType.FROM_BITS -> emitReinterpret(callSite, args)
|
IntrinsicType.REINTERPRET -> emitReinterpret(callSite, args)
|
||||||
IntrinsicType.TO_BITS -> emitReinterpret(callSite, args)
|
IntrinsicType.SIGN_EXTEND -> emitSignExtend(callSite, args)
|
||||||
IntrinsicType.SIGN_EXTEND -> emitSignExtend(callSite, args)
|
IntrinsicType.ZERO_EXTEND -> emitZeroExtend(callSite, args)
|
||||||
IntrinsicType.ZERO_EXTEND -> emitZeroExtend(callSite, args)
|
IntrinsicType.INT_TRUNCATE -> emitIntTruncate(callSite, args)
|
||||||
IntrinsicType.INT_TRUNCATE -> emitIntTruncate(callSite, args)
|
IntrinsicType.SIGNED_TO_FLOAT -> emitSignedToFloat(callSite, args)
|
||||||
IntrinsicType.SIGNED_TO_FLOAT -> emitSignedToFloat(callSite, args)
|
IntrinsicType.UNSIGNED_TO_FLOAT -> emitUnsignedToFloat(callSite, args)
|
||||||
IntrinsicType.UNSIGNED_TO_FLOAT -> emitUnsignedToFloat(callSite, args)
|
IntrinsicType.FLOAT_TO_SIGNED -> emitFloatToSigned(callSite, args)
|
||||||
IntrinsicType.FLOAT_TO_SIGNED -> emitFloatToSigned(callSite, args)
|
IntrinsicType.FLOAT_EXTEND -> emitFloatExtend(callSite, args)
|
||||||
IntrinsicType.FLOAT_EXTEND -> emitFloatExtend(callSite, args)
|
IntrinsicType.FLOAT_TRUNCATE -> emitFloatTruncate(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>) =
|
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)) {
|
ifThen(icmpEq(divider, Zero(divider.type).llvm)) {
|
||||||
val throwArithExc = codegen.llvmFunction(context.ir.symbols.throwArithmeticException.owner)
|
val throwArithExc = codegen.llvmFunction(context.ir.symbols.throwArithmeticException.owner)
|
||||||
call(throwArithExc, emptyList(), Lifetime.GLOBAL, exceptionHandler)
|
call(throwArithExc, emptyList(), Lifetime.GLOBAL, exceptionHandlerProvider())
|
||||||
unreachable()
|
unreachable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FunctionGenerationContext.emitSignedDiv(args: List<LLVMValueRef>, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
private fun FunctionGenerationContext.emitSignedDiv(args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
val (first, second) = args
|
val (first, second) = args
|
||||||
if (!second.type.isFloatingPoint()) {
|
if (!second.type.isFloatingPoint()) {
|
||||||
emitThrowIfZero(second, exceptionHandler)
|
emitThrowIfZero(second)
|
||||||
}
|
}
|
||||||
return if (first.type.isFloatingPoint()) {
|
return if (first.type.isFloatingPoint()) {
|
||||||
LLVMBuildFDiv(builder, first, second, "")
|
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
|
val (first, second) = args
|
||||||
if (!second.type.isFloatingPoint()) {
|
if (!second.type.isFloatingPoint()) {
|
||||||
emitThrowIfZero(second, exceptionHandler)
|
emitThrowIfZero(second)
|
||||||
}
|
}
|
||||||
return if (first.type.isFloatingPoint()) {
|
return if (first.type.isFloatingPoint()) {
|
||||||
LLVMBuildFRem(builder, first, second, "")
|
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
|
val (first, second) = args
|
||||||
emitThrowIfZero(second, exceptionHandler)
|
emitThrowIfZero(second)
|
||||||
return LLVMBuildUDiv(builder, first, 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
|
val (first, second) = args
|
||||||
emitThrowIfZero(second, exceptionHandler)
|
emitThrowIfZero(second)
|
||||||
return LLVMBuildURem(builder, first, second, "")!!
|
return LLVMBuildURem(builder, first, second, "")!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-287
@@ -291,13 +291,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
val codegen = CodeGenerator(context)
|
val codegen = CodeGenerator(context)
|
||||||
|
|
||||||
val intrinsicGenerator = IntrinsicGenerator(codegen)
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
// TODO: consider eliminating mutable state
|
// TODO: consider eliminating mutable state
|
||||||
private var currentCodeContext: CodeContext = TopLevelCodeContext
|
private var currentCodeContext: CodeContext = TopLevelCodeContext
|
||||||
|
|
||||||
|
private val intrinsicGenerator = IntrinsicGenerator(codegen,
|
||||||
|
::resultLifetime, ::getContinuation, { currentCodeContext.exceptionHandler })
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fake [CodeContext] that doesn't support any operation.
|
* 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
|
return codegen.theUnitInstanceRef.llvm
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
// TODO: should be unified with other intrinsics
|
||||||
|
|
||||||
private fun evaluateSpecialIntrinsicCall(expression: IrFunctionAccessExpression): LLVMValueRef? {
|
private fun evaluateSpecialIntrinsicCall(expression: IrFunctionAccessExpression): LLVMValueRef? {
|
||||||
val function = expression.symbol.owner
|
val function = expression.symbol.owner
|
||||||
|
|
||||||
@@ -2097,8 +2095,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
args + getContinuation()
|
args + getContinuation()
|
||||||
else args
|
else args
|
||||||
return when {
|
return when {
|
||||||
function.isTypedIntrinsic -> intrinsicGenerator.evaluateCall(callee, args, functionGenerationContext, currentCodeContext.exceptionHandler)
|
function.isTypedIntrinsic -> intrinsicGenerator.evaluateCall(callee, args, functionGenerationContext)
|
||||||
function.isIntrinsic -> evaluateIntrinsicCall(callee, argsWithContinuationIfNeeded)
|
function.isIntrinsic -> context.reportCompilationError("Unexpected @Intrinsic function: ${function.name.asString()}")
|
||||||
function.origin == IrDeclarationOrigin.IR_BUILTINS_STUB -> evaluateOperatorCall(callee, argsWithContinuationIfNeeded)
|
function.origin == IrDeclarationOrigin.IR_BUILTINS_STUB -> evaluateOperatorCall(callee, argsWithContinuationIfNeeded)
|
||||||
function is ConstructorDescriptor -> evaluateConstructorCall(callee, argsWithContinuationIfNeeded)
|
function is ConstructorDescriptor -> evaluateConstructorCall(callee, argsWithContinuationIfNeeded)
|
||||||
else -> evaluateSimpleFunctionCall(function, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifierSymbol?.owner)
|
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 {
|
private fun genGetObjCClass(classDescriptor: ClassDescriptor): LLVMValueRef {
|
||||||
return functionGenerationContext.getObjCClass(classDescriptor, currentCodeContext.exceptionHandler)
|
return functionGenerationContext.getObjCClass(classDescriptor, currentCodeContext.exceptionHandler)
|
||||||
}
|
}
|
||||||
@@ -2446,64 +2217,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
return call(protocolGetter, emptyList())
|
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 kImmZero = LLVMConstInt(LLVMInt32Type(), 0, 1)!!
|
||||||
private val kImmOne = LLVMConstInt(LLVMInt32Type(), 1, 1)!!
|
private val kImmOne = LLVMConstInt(LLVMInt32Type(), 1, 1)!!
|
||||||
private val kTrue = LLVMConstInt(LLVMInt1Type(), 1, 1)!!
|
private val kTrue = LLVMConstInt(LLVMInt1Type(), 1, 1)!!
|
||||||
private val kFalse = LLVMConstInt(LLVMInt1Type(), 0, 1)!!
|
private val kFalse = LLVMConstInt(LLVMInt1Type(), 0, 1)!!
|
||||||
|
|
||||||
|
// TODO: Intrinsify?
|
||||||
private fun evaluateOperatorCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
private fun evaluateOperatorCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
context.log{"evaluateOperatorCall : origin:${ir2string(callee)}"}
|
context.log{"evaluateOperatorCall : origin:${ir2string(callee)}"}
|
||||||
val descriptor = callee.symbol.owner
|
val descriptor = callee.symbol.owner
|
||||||
|
|||||||
@@ -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)
|
public actual inline fun Double.Companion.fromBits(bits: Long): Double = kotlin.fromBits(bits)
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
@TypedIntrinsic(IntrinsicType.FROM_BITS)
|
@TypedIntrinsic(IntrinsicType.REINTERPRET)
|
||||||
external internal fun fromBits(bits: Long): Double
|
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)
|
public actual inline fun Float.Companion.fromBits(bits: Int): Float = kotlin.fromBits(bits)
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
@TypedIntrinsic(IntrinsicType.FROM_BITS)
|
@TypedIntrinsic(IntrinsicType.REINTERPRET)
|
||||||
external internal fun fromBits(bits: Int): Float
|
external internal fun fromBits(bits: Int): Float
|
||||||
|
|||||||
@@ -1174,7 +1174,7 @@ public final class Float private constructor(private val value: kotlin.native.in
|
|||||||
return bits()
|
return bits()
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypedIntrinsic(IntrinsicType.TO_BITS)
|
@TypedIntrinsic(IntrinsicType.REINTERPRET)
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
external internal fun bits(): Int
|
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()
|
public override fun hashCode(): Int = bits().hashCode()
|
||||||
|
|
||||||
@TypedIntrinsic(IntrinsicType.TO_BITS)
|
@TypedIntrinsic(IntrinsicType.REINTERPRET)
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
external internal fun bits(): Long
|
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 =
|
internal inline suspend fun <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T =
|
||||||
returnIfSuspended<T>(block(getContinuation<T>()))
|
returnIfSuspended<T>(block(getContinuation<T>()))
|
||||||
|
|
||||||
@Intrinsic
|
@TypedIntrinsic(IntrinsicType.GET_CONTINUATION)
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal external fun <T> getContinuation(): Continuation<T>
|
internal external fun <T> getContinuation(): Continuation<T>
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package kotlin.native.internal
|
|||||||
|
|
||||||
class IntrinsicType {
|
class IntrinsicType {
|
||||||
companion object {
|
companion object {
|
||||||
|
// Arithmetic
|
||||||
const val PLUS = "PLUS"
|
const val PLUS = "PLUS"
|
||||||
const val MINUS = "MINUS"
|
const val MINUS = "MINUS"
|
||||||
const val TIMES = "TIMES"
|
const val TIMES = "TIMES"
|
||||||
@@ -31,7 +32,30 @@ class IntrinsicType {
|
|||||||
const val SIGNED_COMPARE_TO = "SIGNED_COMPARE_TO"
|
const val SIGNED_COMPARE_TO = "SIGNED_COMPARE_TO"
|
||||||
const val UNSIGNED_COMPARE_TO = "UNSIGNED_COMPARE_TO"
|
const val UNSIGNED_COMPARE_TO = "UNSIGNED_COMPARE_TO"
|
||||||
const val NOT = "NOT"
|
const val NOT = "NOT"
|
||||||
const val TO_BITS = "TO_BITS"
|
const val REINTERPRET = "REINTERPRET"
|
||||||
const val FROM_BITS = "FROM_BITS"
|
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.NativePointed
|
||||||
import kotlinx.cinterop.NativePtr
|
import kotlinx.cinterop.NativePtr
|
||||||
|
|
||||||
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Boolean, second: Boolean): Boolean
|
import kotlin.native.internal.TypedIntrinsic
|
||||||
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Byte, second: Byte): Boolean
|
import kotlin.native.internal.IntrinsicType
|
||||||
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Short, second: Short): Boolean
|
|
||||||
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Int, second: Int): Boolean
|
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Boolean, second: Boolean): Boolean
|
||||||
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Long, second: Long): Boolean
|
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Byte, second: Byte): Boolean
|
||||||
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: NativePtr, second: NativePtr): 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:
|
// Bitwise equality:
|
||||||
@Intrinsic @PublishedApi external internal fun areEqualByValue(first: Float, second: Float): Boolean
|
@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @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: Double, second: Double): Boolean
|
||||||
|
|
||||||
// IEEE754 equality:
|
// IEEE754 equality:
|
||||||
@Intrinsic @PublishedApi external internal fun ieee754Equals(first: Float, second: Float): Boolean
|
@TypedIntrinsic(IntrinsicType.IEEE_754_EQUALS) @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: Double, second: Double): Boolean
|
||||||
|
|
||||||
// Reinterprets this value from T to R having the same binary representation (e.g. to unwrap inline class).
|
// 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
|
internal external fun getObjectTypeInfo(obj: Any): NativePtr
|
||||||
|
|
||||||
@ExportForCompiler
|
@ExportForCompiler
|
||||||
@Intrinsic
|
@TypedIntrinsic(IntrinsicType.GET_CLASS_TYPE_INFO)
|
||||||
internal external inline fun <reified T : Any> getClassTypeInfo(): NativePtr
|
internal external inline fun <reified T : Any> getClassTypeInfo(): NativePtr
|
||||||
|
|
||||||
@SymbolName("Kotlin_TypeInfo_getPackageName")
|
@SymbolName("Kotlin_TypeInfo_getPackageName")
|
||||||
|
|||||||
@@ -7,16 +7,19 @@
|
|||||||
|
|
||||||
package kotlin.native.internal
|
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?) {
|
class NativePtr @PublishedApi internal constructor(private val value: NonNullNativePtr?) {
|
||||||
companion object {
|
companion object {
|
||||||
val NULL = getNativeNullPtr()
|
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)
|
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>
|
return result as Array<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Intrinsic
|
@TypedIntrinsic(IntrinsicType.CREATE_UNINITIALIZED_INSTANCE)
|
||||||
internal external fun <T> createUninitializedInstance(): T
|
internal external fun <T> createUninitializedInstance(): T
|
||||||
|
|
||||||
@Intrinsic
|
@Intrinsic
|
||||||
@@ -150,7 +150,7 @@ fun KonanObjectToUtf8Array(value: Any?): ByteArray {
|
|||||||
return string.toUtf8()
|
return string.toUtf8()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Intrinsic
|
@TypedIntrinsic(IntrinsicType.LIST_OF_INTERNAL)
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal fun <T> listOfInternal(vararg elements: T): List<T> {
|
internal fun <T> listOfInternal(vararg elements: T): List<T> {
|
||||||
val result = ArrayList<T>(elements.size)
|
val result = ArrayList<T>(elements.size)
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ internal fun SearchPathResolverWithTarget.libraryMatch(candidate: KonanLibraryIm
|
|||||||
val candidateAbiVersion = candidate.versions.abiVersion
|
val candidateAbiVersion = candidate.versions.abiVersion
|
||||||
val candidateLibraryVersion = candidate.versions.libraryVersion
|
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}")
|
logger("skipping $candidatePath. The target doesn't match. Expected '$resolverTarget', found ${candidate.targetList}")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user