Support unsigned types (#1854)
(cherry picked from commit 7b46f93033146462619376d8d008343c2ee75e00)
This commit is contained in:
committed by
Vasily Levchenko
parent
c78d070455
commit
49a32e92c1
+1
@@ -259,6 +259,7 @@ internal fun IrBuiltIns.getKotlinClass(cache: BoxCache): IrClass = when (cache)
|
|||||||
BoxCache.LONG -> longClass
|
BoxCache.LONG -> longClass
|
||||||
}.owner
|
}.owner
|
||||||
|
|
||||||
|
// TODO: consider adding box caches for unsigned types.
|
||||||
enum class BoxCache {
|
enum class BoxCache {
|
||||||
BOOLEAN, BYTE, SHORT, CHAR, INT, LONG
|
BOOLEAN, BYTE, SHORT, CHAR, INT, LONG
|
||||||
}
|
}
|
||||||
+27
-14
@@ -25,18 +25,16 @@ import org.jetbrains.kotlin.backend.common.pop
|
|||||||
import org.jetbrains.kotlin.backend.common.push
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isUnit
|
import org.jetbrains.kotlin.backend.konan.descriptors.isUnit
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
|
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.annotations.*
|
import org.jetbrains.kotlin.resolve.annotations.*
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi
|
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.konan.target.*
|
import org.jetbrains.kotlin.konan.target.*
|
||||||
import org.jetbrains.kotlin.name.isChildOf
|
import org.jetbrains.kotlin.name.isChildOf
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
|
||||||
@@ -760,14 +758,18 @@ internal class CAdapterGenerator(
|
|||||||
typedef _Bool ${prefix}_KBoolean;
|
typedef _Bool ${prefix}_KBoolean;
|
||||||
#endif
|
#endif
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
output("typedef char ${prefix}_KByte;")
|
output("typedef unsigned short ${prefix}_KChar;")
|
||||||
output("typedef unsigned short ${prefix}_KChar;")
|
output("typedef signed char ${prefix}_KByte;")
|
||||||
output("typedef short ${prefix}_KShort;")
|
output("typedef short ${prefix}_KShort;")
|
||||||
output("typedef int ${prefix}_KInt;")
|
output("typedef int ${prefix}_KInt;")
|
||||||
output("typedef long long ${prefix}_KLong;")
|
output("typedef long long ${prefix}_KLong;")
|
||||||
output("typedef float ${prefix}_KFloat;")
|
output("typedef unsigned char ${prefix}_KUByte;")
|
||||||
output("typedef double ${prefix}_KDouble;")
|
output("typedef unsigned short ${prefix}_KUShort;")
|
||||||
output("typedef void* ${prefix}_KNativePtr;")
|
output("typedef unsigned int ${prefix}_KUInt;")
|
||||||
|
output("typedef unsigned long long ${prefix}_KULong;")
|
||||||
|
output("typedef float ${prefix}_KFloat;")
|
||||||
|
output("typedef double ${prefix}_KDouble;")
|
||||||
|
output("typedef void* ${prefix}_KNativePtr;")
|
||||||
output("struct ${prefix}_KType;")
|
output("struct ${prefix}_KType;")
|
||||||
output("typedef struct ${prefix}_KType ${prefix}_KType;")
|
output("typedef struct ${prefix}_KType ${prefix}_KType;")
|
||||||
|
|
||||||
@@ -894,6 +896,15 @@ internal class CAdapterGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val unsignedTypeMapping = UnsignedType.values().associate {
|
||||||
|
it.classId to when (it) {
|
||||||
|
UnsignedType.UBYTE -> "${prefix}_KUByte"
|
||||||
|
UnsignedType.USHORT -> "${prefix}_KUShort"
|
||||||
|
UnsignedType.UINT -> "${prefix}_KUInt"
|
||||||
|
UnsignedType.ULONG -> "${prefix}_KULong"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal fun isMappedToString(descriptor: ClassDescriptor): Boolean =
|
internal fun isMappedToString(descriptor: ClassDescriptor): Boolean =
|
||||||
isMappedToString(descriptor.defaultType.computeBinaryType())
|
isMappedToString(descriptor.defaultType.computeBinaryType())
|
||||||
|
|
||||||
@@ -926,8 +937,10 @@ internal class CAdapterGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translateNonVoidTypeFull(type: KotlinType): Pair<String, String> = type.unwrapToPrimitiveOrReference(
|
private fun translateNonVoidTypeFull(type: KotlinType): Pair<String, String> = type.unwrapToPrimitiveOrReference(
|
||||||
eachInlinedClass = { _, _ ->
|
eachInlinedClass = { inlinedClass, _ ->
|
||||||
// unsigned types to be handled.
|
unsignedTypeMapping[inlinedClass.classId]?.let {
|
||||||
|
return it to it
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ifPrimitive = { primitiveType, _ ->
|
ifPrimitive = { primitiveType, _ ->
|
||||||
primitiveTypeMapping[primitiveType]!!.let { it to it }
|
primitiveTypeMapping[primitiveType]!!.let { it to it }
|
||||||
|
|||||||
+9
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.kotlinNativeInternal
|
|||||||
import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint
|
import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.TestProcessor
|
import org.jetbrains.kotlin.backend.konan.lower.TestProcessor
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||||
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
|
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
|
||||||
import org.jetbrains.kotlin.config.coroutinesPackageFqName
|
import org.jetbrains.kotlin.config.coroutinesPackageFqName
|
||||||
@@ -134,6 +135,14 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
|
|||||||
val nativePtr = symbolTable.referenceClass(context.nativePtr)
|
val nativePtr = symbolTable.referenceClass(context.nativePtr)
|
||||||
val nativePtrType = nativePtr.typeWith(arguments = emptyList())
|
val nativePtrType = nativePtr.typeWith(arguments = emptyList())
|
||||||
|
|
||||||
|
private fun unsignedClass(unsignedType: UnsignedType): IrClassSymbol =
|
||||||
|
symbolTable.referenceClass(builtIns.builtInsModule.findClassAcrossModuleDependencies(unsignedType.classId)!!)
|
||||||
|
|
||||||
|
val uByte = unsignedClass(UnsignedType.UBYTE)
|
||||||
|
val uShort = unsignedClass(UnsignedType.USHORT)
|
||||||
|
val uInt = unsignedClass(UnsignedType.UINT)
|
||||||
|
val uLong = unsignedClass(UnsignedType.ULONG)
|
||||||
|
|
||||||
val arrayList = symbolTable.referenceClass(getArrayListClassDescriptor(context))
|
val arrayList = symbolTable.referenceClass(getArrayListClassDescriptor(context))
|
||||||
|
|
||||||
val interopNativePointedGetRawPointer =
|
val interopNativePointedGetRawPointer =
|
||||||
|
|||||||
+39
-22
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -95,8 +96,11 @@ internal class ObjCExportCodeGenerator(
|
|||||||
): LLVMValueRef = when (valueType) {
|
): LLVMValueRef = when (valueType) {
|
||||||
ObjCValueType.BOOL -> zext(value, int8Type) // TODO: zext behaviour may be strange on bit types.
|
ObjCValueType.BOOL -> zext(value, int8Type) // TODO: zext behaviour may be strange on bit types.
|
||||||
|
|
||||||
ObjCValueType.CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.SHORT,
|
ObjCValueType.UNICHAR,
|
||||||
ObjCValueType.INT, ObjCValueType.LONG_LONG, ObjCValueType.FLOAT, ObjCValueType.DOUBLE -> value
|
ObjCValueType.CHAR, ObjCValueType.SHORT, ObjCValueType.INT, ObjCValueType.LONG_LONG,
|
||||||
|
ObjCValueType.UNSIGNED_CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.UNSIGNED_INT,
|
||||||
|
ObjCValueType.UNSIGNED_LONG_LONG,
|
||||||
|
ObjCValueType.FLOAT, ObjCValueType.DOUBLE -> value
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FunctionGenerationContext.objCToKotlin(
|
private fun FunctionGenerationContext.objCToKotlin(
|
||||||
@@ -105,8 +109,11 @@ internal class ObjCExportCodeGenerator(
|
|||||||
): LLVMValueRef = when (valueType) {
|
): LLVMValueRef = when (valueType) {
|
||||||
ObjCValueType.BOOL -> icmpNe(value, Int8(0).llvm)
|
ObjCValueType.BOOL -> icmpNe(value, Int8(0).llvm)
|
||||||
|
|
||||||
ObjCValueType.CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.SHORT,
|
ObjCValueType.UNICHAR,
|
||||||
ObjCValueType.INT, ObjCValueType.LONG_LONG, ObjCValueType.FLOAT, ObjCValueType.DOUBLE -> value
|
ObjCValueType.CHAR, ObjCValueType.SHORT, ObjCValueType.INT, ObjCValueType.LONG_LONG,
|
||||||
|
ObjCValueType.UNSIGNED_CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.UNSIGNED_INT,
|
||||||
|
ObjCValueType.UNSIGNED_LONG_LONG,
|
||||||
|
ObjCValueType.FLOAT, ObjCValueType.DOUBLE -> value
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FunctionGenerationContext.kotlinReferenceToObjC(value: LLVMValueRef) =
|
fun FunctionGenerationContext.kotlinReferenceToObjC(value: LLVMValueRef) =
|
||||||
@@ -340,22 +347,30 @@ private fun ObjCExportCodeGenerator.setObjCExportTypeInfo(
|
|||||||
private val ObjCExportCodeGenerator.kotlinToObjCFunctionType: LLVMTypeRef
|
private val ObjCExportCodeGenerator.kotlinToObjCFunctionType: LLVMTypeRef
|
||||||
get() = functionType(int8TypePtr, false, codegen.kObjHeaderPtr)
|
get() = functionType(int8TypePtr, false, codegen.kObjHeaderPtr)
|
||||||
|
|
||||||
private fun ObjCExportCodeGenerator.emitBoxConverter(objCValueType: ObjCValueType) {
|
private fun ObjCExportCodeGenerator.emitBoxConverters() {
|
||||||
val symbols = context.ir.symbols
|
|
||||||
val irBuiltIns = context.irBuiltIns
|
val irBuiltIns = context.irBuiltIns
|
||||||
|
val symbols = context.ir.symbols
|
||||||
|
|
||||||
val boxClass = when (objCValueType) {
|
emitBoxConverter(irBuiltIns.booleanClass, ObjCValueType.BOOL, "numberWithBool:")
|
||||||
ObjCValueType.BOOL -> irBuiltIns.booleanClass
|
emitBoxConverter(irBuiltIns.byteClass, ObjCValueType.CHAR, "numberWithChar:")
|
||||||
ObjCValueType.UNSIGNED_SHORT -> irBuiltIns.charClass
|
emitBoxConverter(irBuiltIns.shortClass, ObjCValueType.SHORT, "numberWithShort:")
|
||||||
ObjCValueType.CHAR -> irBuiltIns.byteClass
|
emitBoxConverter(irBuiltIns.intClass, ObjCValueType.INT, "numberWithInt:")
|
||||||
ObjCValueType.SHORT -> irBuiltIns.shortClass
|
emitBoxConverter(irBuiltIns.longClass, ObjCValueType.LONG_LONG, "numberWithLongLong:")
|
||||||
ObjCValueType.INT -> irBuiltIns.intClass
|
emitBoxConverter(symbols.uByte, ObjCValueType.UNSIGNED_CHAR, "numberWithUnsignedChar")
|
||||||
ObjCValueType.LONG_LONG -> irBuiltIns.longClass
|
emitBoxConverter(symbols.uShort, ObjCValueType.UNSIGNED_SHORT, "numberWithUnsignedShort:")
|
||||||
ObjCValueType.FLOAT -> irBuiltIns.floatClass
|
emitBoxConverter(symbols.uInt, ObjCValueType.UNSIGNED_INT, "numberWithUnsignedInt:")
|
||||||
ObjCValueType.DOUBLE -> irBuiltIns.doubleClass
|
emitBoxConverter(symbols.uLong, ObjCValueType.UNSIGNED_LONG_LONG, "numberWithUnsignedLongLong:")
|
||||||
}.owner
|
emitBoxConverter(irBuiltIns.floatClass, ObjCValueType.FLOAT, "numberWithFloat:")
|
||||||
|
emitBoxConverter(irBuiltIns.doubleClass, ObjCValueType.DOUBLE, "numberWithDouble:")
|
||||||
|
}
|
||||||
|
|
||||||
val name = "${boxClass.name}To${objCValueType.nsNumberName}"
|
private fun ObjCExportCodeGenerator.emitBoxConverter(
|
||||||
|
boxClassSymbol: IrClassSymbol,
|
||||||
|
objCValueType: ObjCValueType,
|
||||||
|
nsNumberFactorySelector: String
|
||||||
|
) {
|
||||||
|
val boxClass = boxClassSymbol.owner
|
||||||
|
val name = "${boxClass.name}ToNSNumber"
|
||||||
|
|
||||||
val converter = generateFunction(codegen, kotlinToObjCFunctionType, name) {
|
val converter = generateFunction(codegen, kotlinToObjCFunctionType, name) {
|
||||||
val unboxFunction = context.getUnboxFunction(boxClass).llvmFunction
|
val unboxFunction = context.getUnboxFunction(boxClass).llvmFunction
|
||||||
@@ -368,7 +383,7 @@ private fun ObjCExportCodeGenerator.emitBoxConverter(objCValueType: ObjCValueTyp
|
|||||||
val value = kotlinToObjC(kotlinValue, objCValueType)
|
val value = kotlinToObjC(kotlinValue, objCValueType)
|
||||||
|
|
||||||
val nsNumber = genGetSystemClass("NSNumber")
|
val nsNumber = genGetSystemClass("NSNumber")
|
||||||
ret(genSendMessage(int8TypePtr, nsNumber, objCValueType.nsNumberFactorySelector, value))
|
ret(genSendMessage(int8TypePtr, nsNumber, nsNumberFactorySelector, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMSetLinkage(converter, LLVMLinkage.LLVMPrivateLinkage)
|
LLVMSetLinkage(converter, LLVMLinkage.LLVMPrivateLinkage)
|
||||||
@@ -446,9 +461,7 @@ private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() {
|
|||||||
constPointer(context.llvm.Kotlin_Interop_CreateKotlinMutableDictonaryFromKMap)
|
constPointer(context.llvm.Kotlin_Interop_CreateKotlinMutableDictonaryFromKMap)
|
||||||
)
|
)
|
||||||
|
|
||||||
ObjCValueType.values().forEach {
|
emitBoxConverters()
|
||||||
emitBoxConverter(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
emitFunctionConverters()
|
emitFunctionConverters()
|
||||||
|
|
||||||
@@ -1091,11 +1104,15 @@ private fun objCFunctionType(context: Context, methodBridge: MethodBridge): LLVM
|
|||||||
|
|
||||||
private val ObjCValueType.llvmType: LLVMTypeRef get() = when (this) {
|
private val ObjCValueType.llvmType: LLVMTypeRef get() = when (this) {
|
||||||
ObjCValueType.BOOL -> int8Type
|
ObjCValueType.BOOL -> int8Type
|
||||||
|
ObjCValueType.UNICHAR -> int16Type
|
||||||
ObjCValueType.CHAR -> int8Type
|
ObjCValueType.CHAR -> int8Type
|
||||||
ObjCValueType.UNSIGNED_SHORT -> int16Type
|
|
||||||
ObjCValueType.SHORT -> int16Type
|
ObjCValueType.SHORT -> int16Type
|
||||||
ObjCValueType.INT -> int32Type
|
ObjCValueType.INT -> int32Type
|
||||||
ObjCValueType.LONG_LONG -> int64Type
|
ObjCValueType.LONG_LONG -> int64Type
|
||||||
|
ObjCValueType.UNSIGNED_CHAR -> int8Type
|
||||||
|
ObjCValueType.UNSIGNED_SHORT -> int16Type
|
||||||
|
ObjCValueType.UNSIGNED_INT -> int32Type
|
||||||
|
ObjCValueType.UNSIGNED_LONG_LONG -> int64Type
|
||||||
ObjCValueType.FLOAT -> LLVMFloatType()!!
|
ObjCValueType.FLOAT -> LLVMFloatType()!!
|
||||||
ObjCValueType.DOUBLE -> LLVMDoubleType()!!
|
ObjCValueType.DOUBLE -> LLVMDoubleType()!!
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-2
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.konan.objcexport
|
|||||||
import org.jetbrains.kotlin.backend.konan.*
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -66,13 +67,18 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
result += CustomTypeMapper.Collection(generator, map, "NSDictionary")
|
result += CustomTypeMapper.Collection(generator, map, "NSDictionary")
|
||||||
result += CustomTypeMapper.Collection(generator, mutableMap, namer.mutableMapName)
|
result += CustomTypeMapper.Collection(generator, mutableMap, namer.mutableMapName)
|
||||||
|
|
||||||
for (descriptor in listOf(boolean, char, byte, short, int, long, float, double)) {
|
for (descriptor in listOf(boolean, byte, short, int, long, float, double)) {
|
||||||
// TODO: Kotlin code doesn't have any checkcasts on unboxing,
|
// TODO: Kotlin code doesn't have any checkcasts on unboxing,
|
||||||
// so it is possible that it expects boxed number of other type and unboxes it incorrectly.
|
// so it is possible that it expects boxed number of other type and unboxes it incorrectly.
|
||||||
// TODO: NSNumber seem to have different equality semantics.
|
// TODO: NSNumber seem to have different equality semantics.
|
||||||
result += CustomTypeMapper.Simple(descriptor, "NSNumber")
|
result += CustomTypeMapper.Simple(descriptor, "NSNumber")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (unsignedType in UnsignedType.values()) {
|
||||||
|
val descriptor = moduleDescriptor.findClassAcrossModuleDependencies(unsignedType.classId)!!
|
||||||
|
result += CustomTypeMapper.Simple(descriptor, "NSNumber")
|
||||||
|
}
|
||||||
|
|
||||||
result += CustomTypeMapper.Simple(string, "NSString")
|
result += CustomTypeMapper.Simple(string, "NSString")
|
||||||
|
|
||||||
(0..mapper.maxFunctionTypeParameterCount).forEach {
|
(0..mapper.maxFunctionTypeParameterCount).forEach {
|
||||||
@@ -737,11 +743,15 @@ abstract class ObjCExportHeaderGenerator(
|
|||||||
is ValueTypeBridge -> {
|
is ValueTypeBridge -> {
|
||||||
val cName = when (typeBridge.objCValueType) {
|
val cName = when (typeBridge.objCValueType) {
|
||||||
ObjCValueType.BOOL -> "BOOL"
|
ObjCValueType.BOOL -> "BOOL"
|
||||||
|
ObjCValueType.UNICHAR -> "unichar"
|
||||||
ObjCValueType.CHAR -> "int8_t"
|
ObjCValueType.CHAR -> "int8_t"
|
||||||
ObjCValueType.UNSIGNED_SHORT -> "unichar"
|
|
||||||
ObjCValueType.SHORT -> "int16_t"
|
ObjCValueType.SHORT -> "int16_t"
|
||||||
ObjCValueType.INT -> "int32_t"
|
ObjCValueType.INT -> "int32_t"
|
||||||
ObjCValueType.LONG_LONG -> "int64_t"
|
ObjCValueType.LONG_LONG -> "int64_t"
|
||||||
|
ObjCValueType.UNSIGNED_CHAR -> "uint8_t"
|
||||||
|
ObjCValueType.UNSIGNED_SHORT -> "uint16_t"
|
||||||
|
ObjCValueType.UNSIGNED_INT -> "uint32_t"
|
||||||
|
ObjCValueType.UNSIGNED_LONG_LONG -> "uint64_t"
|
||||||
ObjCValueType.FLOAT -> "float"
|
ObjCValueType.FLOAT -> "float"
|
||||||
ObjCValueType.DOUBLE -> "double"
|
ObjCValueType.DOUBLE -> "double"
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-4
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors
|
|||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isArray
|
import org.jetbrains.kotlin.backend.konan.descriptors.isArray
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -111,13 +112,18 @@ internal fun ObjCExportMapper.doesThrow(method: FunctionDescriptor): Boolean = m
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun ObjCExportMapper.bridgeType(kotlinType: KotlinType): TypeBridge = kotlinType.unwrapToPrimitiveOrReference(
|
private fun ObjCExportMapper.bridgeType(kotlinType: KotlinType): TypeBridge = kotlinType.unwrapToPrimitiveOrReference(
|
||||||
eachInlinedClass = { _, _ ->
|
eachInlinedClass = { inlinedClass, _ ->
|
||||||
// unsigned types to be handled.
|
when (inlinedClass.classId) {
|
||||||
|
UnsignedType.UBYTE.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_CHAR)
|
||||||
|
UnsignedType.USHORT.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_SHORT)
|
||||||
|
UnsignedType.UINT.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_INT)
|
||||||
|
UnsignedType.ULONG.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_LONG_LONG)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ifPrimitive = { primitiveType, _ ->
|
ifPrimitive = { primitiveType, _ ->
|
||||||
val objCValueType = when (primitiveType) {
|
val objCValueType = when (primitiveType) {
|
||||||
KonanPrimitiveType.BOOLEAN -> ObjCValueType.BOOL
|
KonanPrimitiveType.BOOLEAN -> ObjCValueType.BOOL
|
||||||
KonanPrimitiveType.CHAR -> ObjCValueType.UNSIGNED_SHORT
|
KonanPrimitiveType.CHAR -> ObjCValueType.UNICHAR
|
||||||
KonanPrimitiveType.BYTE -> ObjCValueType.CHAR
|
KonanPrimitiveType.BYTE -> ObjCValueType.CHAR
|
||||||
KonanPrimitiveType.SHORT -> ObjCValueType.SHORT
|
KonanPrimitiveType.SHORT -> ObjCValueType.SHORT
|
||||||
KonanPrimitiveType.INT -> ObjCValueType.INT
|
KonanPrimitiveType.INT -> ObjCValueType.INT
|
||||||
@@ -219,4 +225,4 @@ internal fun ObjCExportMapper.bridgePropertyType(descriptor: PropertyDescriptor)
|
|||||||
assert(isBaseProperty(descriptor))
|
assert(isBaseProperty(descriptor))
|
||||||
|
|
||||||
return bridgeType(descriptor.type)
|
return bridgeType(descriptor.type)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-16
@@ -111,27 +111,17 @@ object ObjCVoidType : ObjCType() {
|
|||||||
override fun render(attrsAndName: String) = "void".withAttrsAndName(attrsAndName)
|
override fun render(attrsAndName: String) = "void".withAttrsAndName(attrsAndName)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum class ObjCValueType(
|
internal enum class ObjCValueType(val encoding: String) {
|
||||||
val encoding: String
|
|
||||||
) {
|
|
||||||
|
|
||||||
BOOL("c"),
|
BOOL("c"),
|
||||||
|
UNICHAR("S"),
|
||||||
CHAR("c"),
|
CHAR("c"),
|
||||||
SHORT("s"),
|
SHORT("s"),
|
||||||
UNSIGNED_SHORT("S"),
|
|
||||||
INT("i"),
|
INT("i"),
|
||||||
LONG_LONG("q"),
|
LONG_LONG("q"),
|
||||||
|
UNSIGNED_CHAR("C"),
|
||||||
|
UNSIGNED_SHORT("S"),
|
||||||
|
UNSIGNED_INT("I"),
|
||||||
|
UNSIGNED_LONG_LONG("Q"),
|
||||||
FLOAT("f"),
|
FLOAT("f"),
|
||||||
DOUBLE("d")
|
DOUBLE("d")
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
// UNSIGNED_SHORT -> unsignedShort
|
|
||||||
val nsNumberName = this.name.split('_').mapIndexed { index, s ->
|
|
||||||
val lower = s.toLowerCase()
|
|
||||||
if (index > 0) lower.capitalize() else lower
|
|
||||||
}.joinToString("")
|
|
||||||
|
|
||||||
val nsNumberValueSelector get() = "${nsNumberName}Value"
|
|
||||||
val nsNumberFactorySelector get() = "numberWith${nsNumberName.capitalize()}:"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -433,11 +433,14 @@ static void initializeObjCExport() {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
OBJ_GETTER(Kotlin_boxBoolean, KBoolean value);
|
OBJ_GETTER(Kotlin_boxBoolean, KBoolean value);
|
||||||
OBJ_GETTER(Kotlin_boxChar, KChar value);
|
|
||||||
OBJ_GETTER(Kotlin_boxByte, KByte value);
|
OBJ_GETTER(Kotlin_boxByte, KByte value);
|
||||||
OBJ_GETTER(Kotlin_boxShort, KShort value);
|
OBJ_GETTER(Kotlin_boxShort, KShort value);
|
||||||
OBJ_GETTER(Kotlin_boxInt, KInt value);
|
OBJ_GETTER(Kotlin_boxInt, KInt value);
|
||||||
OBJ_GETTER(Kotlin_boxLong, KLong value);
|
OBJ_GETTER(Kotlin_boxLong, KLong value);
|
||||||
|
OBJ_GETTER(Kotlin_boxUByte, KUByte value);
|
||||||
|
OBJ_GETTER(Kotlin_boxUShort, KUShort value);
|
||||||
|
OBJ_GETTER(Kotlin_boxUInt, KUInt value);
|
||||||
|
OBJ_GETTER(Kotlin_boxULong, KULong value);
|
||||||
OBJ_GETTER(Kotlin_boxFloat, KFloat value);
|
OBJ_GETTER(Kotlin_boxFloat, KFloat value);
|
||||||
OBJ_GETTER(Kotlin_boxDouble, KDouble value);
|
OBJ_GETTER(Kotlin_boxDouble, KDouble value);
|
||||||
|
|
||||||
@@ -457,11 +460,14 @@ static OBJ_GETTER(boxedBooleanToKotlinImp, NSNumber* self, SEL cmd) {
|
|||||||
// TODO: the code below makes some assumption on char, short, int and long sizes.
|
// TODO: the code below makes some assumption on char, short, int and long sizes.
|
||||||
|
|
||||||
switch (type[0]) {
|
switch (type[0]) {
|
||||||
case 'S': RETURN_RESULT_OF(Kotlin_boxChar, self.unsignedShortValue);
|
|
||||||
case 'c': RETURN_RESULT_OF(Kotlin_boxByte, self.charValue);
|
case 'c': RETURN_RESULT_OF(Kotlin_boxByte, self.charValue);
|
||||||
case 's': RETURN_RESULT_OF(Kotlin_boxShort, self.shortValue);
|
case 's': RETURN_RESULT_OF(Kotlin_boxShort, self.shortValue);
|
||||||
case 'i': RETURN_RESULT_OF(Kotlin_boxInt, self.intValue);
|
case 'i': RETURN_RESULT_OF(Kotlin_boxInt, self.intValue);
|
||||||
case 'q': RETURN_RESULT_OF(Kotlin_boxLong, self.longLongValue);
|
case 'q': RETURN_RESULT_OF(Kotlin_boxLong, self.longLongValue);
|
||||||
|
case 'C': RETURN_RESULT_OF(Kotlin_boxUByte, self.unsignedCharValue);
|
||||||
|
case 'S': RETURN_RESULT_OF(Kotlin_boxUShort, self.unsignedShortValue);
|
||||||
|
case 'I': RETURN_RESULT_OF(Kotlin_boxUInt, self.unsignedIntValue);
|
||||||
|
case 'Q': RETURN_RESULT_OF(Kotlin_boxULong, self.unsignedLongLongValue);
|
||||||
case 'f': RETURN_RESULT_OF(Kotlin_boxFloat, self.floatValue);
|
case 'f': RETURN_RESULT_OF(Kotlin_boxFloat, self.floatValue);
|
||||||
case 'd': RETURN_RESULT_OF(Kotlin_boxDouble, self.doubleValue);
|
case 'd': RETURN_RESULT_OF(Kotlin_boxDouble, self.doubleValue);
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ typedef uint16_t KChar;
|
|||||||
typedef int16_t KShort;
|
typedef int16_t KShort;
|
||||||
typedef int32_t KInt;
|
typedef int32_t KInt;
|
||||||
typedef int64_t KLong;
|
typedef int64_t KLong;
|
||||||
|
typedef uint8_t KUByte;
|
||||||
|
typedef uint16_t KUShort;
|
||||||
|
typedef uint32_t KUInt;
|
||||||
|
typedef uint64_t KULong;
|
||||||
typedef float KFloat;
|
typedef float KFloat;
|
||||||
typedef double KDouble;
|
typedef double KDouble;
|
||||||
typedef void* KNativePtr;
|
typedef void* KNativePtr;
|
||||||
|
|||||||
@@ -237,6 +237,29 @@ external private fun copyImpl(array: IntArray, fromIndex: Int,
|
|||||||
external private fun copyImpl(array: LongArray, fromIndex: Int,
|
external private fun copyImpl(array: LongArray, fromIndex: Int,
|
||||||
destination: LongArray, toIndex: Int, count: Int)
|
destination: LongArray, toIndex: Int, count: Int)
|
||||||
|
|
||||||
|
// Note: [copyImpl] for an unsigned array is bitwise identical to signed type, so
|
||||||
|
// signed array implementations from runtime are directly reused for unsigned ones.
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@SymbolName("Kotlin_ByteArray_copyImpl")
|
||||||
|
external private fun copyImpl(array: UByteArray, fromIndex: Int,
|
||||||
|
destination: UByteArray, toIndex: Int, count: Int)
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@SymbolName("Kotlin_ShortArray_copyImpl")
|
||||||
|
external private fun copyImpl(array: UShortArray, fromIndex: Int,
|
||||||
|
destination: UShortArray, toIndex: Int, count: Int)
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@SymbolName("Kotlin_IntArray_copyImpl")
|
||||||
|
external private fun copyImpl(array: UIntArray, fromIndex: Int,
|
||||||
|
destination: UIntArray, toIndex: Int, count: Int)
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@SymbolName("Kotlin_LongArray_copyImpl")
|
||||||
|
external private fun copyImpl(array: ULongArray, fromIndex: Int,
|
||||||
|
destination: ULongArray, toIndex: Int, count: Int)
|
||||||
|
|
||||||
@SymbolName("Kotlin_FloatArray_copyImpl")
|
@SymbolName("Kotlin_FloatArray_copyImpl")
|
||||||
external private fun copyImpl(array: FloatArray, fromIndex: Int,
|
external private fun copyImpl(array: FloatArray, fromIndex: Int,
|
||||||
destination: FloatArray, toIndex: Int, count: Int)
|
destination: FloatArray, toIndex: Int, count: Int)
|
||||||
@@ -279,6 +302,30 @@ fun LongArray.copyRangeTo(destination: LongArray, fromIndex: Int, toIndex: Int,
|
|||||||
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
|
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
fun UByteArray.copyRangeTo(destination: UByteArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
|
||||||
|
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
fun UShortArray.copyRangeTo(destination: UShortArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
|
||||||
|
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
fun UIntArray.copyRangeTo(destination: UIntArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
|
||||||
|
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
fun ULongArray.copyRangeTo(destination: ULongArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
|
||||||
|
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
|
||||||
|
}
|
||||||
|
|
||||||
fun FloatArray.copyRangeTo(destination: FloatArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
|
fun FloatArray.copyRangeTo(destination: FloatArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
|
||||||
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
|
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -514,6 +514,94 @@ public actual fun LongArray.contentToString(): String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of the contents of the specified array as if it is [List].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public fun UByteArray.contentToString(): String {
|
||||||
|
if (size == 0)
|
||||||
|
return "[]"
|
||||||
|
val iMax = size - 1
|
||||||
|
|
||||||
|
val b = StringBuilder()
|
||||||
|
b.append('[')
|
||||||
|
var i = 0
|
||||||
|
while (true) {
|
||||||
|
b.append(this[i])
|
||||||
|
if (i == iMax)
|
||||||
|
return b.append(']').toString()
|
||||||
|
b.append(", ")
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of the contents of the specified array as if it is [List].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public fun UShortArray.contentToString(): String {
|
||||||
|
if (size == 0)
|
||||||
|
return "[]"
|
||||||
|
val iMax = size - 1
|
||||||
|
|
||||||
|
val b = StringBuilder()
|
||||||
|
b.append('[')
|
||||||
|
var i = 0
|
||||||
|
while (true) {
|
||||||
|
b.append(this[i])
|
||||||
|
if (i == iMax)
|
||||||
|
return b.append(']').toString()
|
||||||
|
b.append(", ")
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of the contents of the specified array as if it is [List].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public fun UIntArray.contentToString(): String {
|
||||||
|
if (size == 0)
|
||||||
|
return "[]"
|
||||||
|
val iMax = size - 1
|
||||||
|
|
||||||
|
val b = StringBuilder()
|
||||||
|
b.append('[')
|
||||||
|
var i = 0
|
||||||
|
while (true) {
|
||||||
|
b.append(this[i])
|
||||||
|
if (i == iMax)
|
||||||
|
return b.append(']').toString()
|
||||||
|
b.append(", ")
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of the contents of the specified array as if it is [List].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public fun ULongArray.contentToString(): String {
|
||||||
|
if (size == 0)
|
||||||
|
return "[]"
|
||||||
|
val iMax = size - 1
|
||||||
|
|
||||||
|
val b = StringBuilder()
|
||||||
|
b.append('[')
|
||||||
|
var i = 0
|
||||||
|
while (true) {
|
||||||
|
b.append(this[i])
|
||||||
|
if (i == iMax)
|
||||||
|
return b.append(']').toString()
|
||||||
|
b.append(", ")
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string representation of the contents of the specified array as if it is [List].
|
* Returns a string representation of the contents of the specified array as if it is [List].
|
||||||
*/
|
*/
|
||||||
@@ -972,6 +1060,54 @@ public actual fun LongArray.contentHashCode(): Int {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a hash code based on the contents of this array as if it is [List].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public fun UByteArray.contentHashCode(): Int {
|
||||||
|
var result = 1
|
||||||
|
for (element in this)
|
||||||
|
result = 31 * result + element.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a hash code based on the contents of this array as if it is [List].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public fun UShortArray.contentHashCode(): Int {
|
||||||
|
var result = 1
|
||||||
|
for (element in this)
|
||||||
|
result = 31 * result + element.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a hash code based on the contents of this array as if it is [List].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public fun UIntArray.contentHashCode(): Int {
|
||||||
|
var result = 1
|
||||||
|
for (element in this)
|
||||||
|
result = 31 * result + element.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a hash code based on the contents of this array as if it is [List].
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
public fun ULongArray.contentHashCode(): Int {
|
||||||
|
var result = 1
|
||||||
|
for (element in this)
|
||||||
|
result = 31 * result + element.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a hash code based on the contents of this array as if it is [List].
|
* Returns a hash code based on the contents of this array as if it is [List].
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -61,6 +61,22 @@ fun boxInt(value: Int): Int? = value
|
|||||||
@ExportForCppRuntime("Kotlin_boxLong")
|
@ExportForCppRuntime("Kotlin_boxLong")
|
||||||
fun boxLong(value: Long): Long? = value
|
fun boxLong(value: Long): Long? = value
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@ExportForCppRuntime("Kotlin_boxUByte")
|
||||||
|
fun boxUByte(value: UByte): UByte? = value
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@ExportForCppRuntime("Kotlin_boxUShort")
|
||||||
|
fun boxUShort(value: UShort): UShort? = value
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@ExportForCppRuntime("Kotlin_boxUInt")
|
||||||
|
fun boxUInt(value: UInt): UInt? = value
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@ExportForCppRuntime("Kotlin_boxULong")
|
||||||
|
fun boxULong(value: ULong): ULong? = value
|
||||||
|
|
||||||
@ExportForCppRuntime("Kotlin_boxFloat")
|
@ExportForCppRuntime("Kotlin_boxFloat")
|
||||||
fun boxFloat(value: Float): Float? = value
|
fun boxFloat(value: Float): Float? = value
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user