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
|
||||
}.owner
|
||||
|
||||
// TODO: consider adding box caches for unsigned types.
|
||||
enum class BoxCache {
|
||||
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.konan.descriptors.isUnit
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
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.konan.target.*
|
||||
import org.jetbrains.kotlin.name.isChildOf
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
@@ -760,14 +758,18 @@ internal class CAdapterGenerator(
|
||||
typedef _Bool ${prefix}_KBoolean;
|
||||
#endif
|
||||
""".trimIndent())
|
||||
output("typedef char ${prefix}_KByte;")
|
||||
output("typedef unsigned short ${prefix}_KChar;")
|
||||
output("typedef short ${prefix}_KShort;")
|
||||
output("typedef int ${prefix}_KInt;")
|
||||
output("typedef long long ${prefix}_KLong;")
|
||||
output("typedef float ${prefix}_KFloat;")
|
||||
output("typedef double ${prefix}_KDouble;")
|
||||
output("typedef void* ${prefix}_KNativePtr;")
|
||||
output("typedef unsigned short ${prefix}_KChar;")
|
||||
output("typedef signed char ${prefix}_KByte;")
|
||||
output("typedef short ${prefix}_KShort;")
|
||||
output("typedef int ${prefix}_KInt;")
|
||||
output("typedef long long ${prefix}_KLong;")
|
||||
output("typedef unsigned char ${prefix}_KUByte;")
|
||||
output("typedef unsigned short ${prefix}_KUShort;")
|
||||
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("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 =
|
||||
isMappedToString(descriptor.defaultType.computeBinaryType())
|
||||
|
||||
@@ -926,8 +937,10 @@ internal class CAdapterGenerator(
|
||||
}
|
||||
|
||||
private fun translateNonVoidTypeFull(type: KotlinType): Pair<String, String> = type.unwrapToPrimitiveOrReference(
|
||||
eachInlinedClass = { _, _ ->
|
||||
// unsigned types to be handled.
|
||||
eachInlinedClass = { inlinedClass, _ ->
|
||||
unsignedTypeMapping[inlinedClass.classId]?.let {
|
||||
return it to it
|
||||
}
|
||||
},
|
||||
ifPrimitive = { primitiveType, _ ->
|
||||
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.lower.TestProcessor
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
|
||||
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 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 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.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -95,8 +96,11 @@ internal class ObjCExportCodeGenerator(
|
||||
): LLVMValueRef = when (valueType) {
|
||||
ObjCValueType.BOOL -> zext(value, int8Type) // TODO: zext behaviour may be strange on bit types.
|
||||
|
||||
ObjCValueType.CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.SHORT,
|
||||
ObjCValueType.INT, ObjCValueType.LONG_LONG, ObjCValueType.FLOAT, ObjCValueType.DOUBLE -> value
|
||||
ObjCValueType.UNICHAR,
|
||||
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(
|
||||
@@ -105,8 +109,11 @@ internal class ObjCExportCodeGenerator(
|
||||
): LLVMValueRef = when (valueType) {
|
||||
ObjCValueType.BOOL -> icmpNe(value, Int8(0).llvm)
|
||||
|
||||
ObjCValueType.CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.SHORT,
|
||||
ObjCValueType.INT, ObjCValueType.LONG_LONG, ObjCValueType.FLOAT, ObjCValueType.DOUBLE -> value
|
||||
ObjCValueType.UNICHAR,
|
||||
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) =
|
||||
@@ -340,22 +347,30 @@ private fun ObjCExportCodeGenerator.setObjCExportTypeInfo(
|
||||
private val ObjCExportCodeGenerator.kotlinToObjCFunctionType: LLVMTypeRef
|
||||
get() = functionType(int8TypePtr, false, codegen.kObjHeaderPtr)
|
||||
|
||||
private fun ObjCExportCodeGenerator.emitBoxConverter(objCValueType: ObjCValueType) {
|
||||
val symbols = context.ir.symbols
|
||||
private fun ObjCExportCodeGenerator.emitBoxConverters() {
|
||||
val irBuiltIns = context.irBuiltIns
|
||||
val symbols = context.ir.symbols
|
||||
|
||||
val boxClass = when (objCValueType) {
|
||||
ObjCValueType.BOOL -> irBuiltIns.booleanClass
|
||||
ObjCValueType.UNSIGNED_SHORT -> irBuiltIns.charClass
|
||||
ObjCValueType.CHAR -> irBuiltIns.byteClass
|
||||
ObjCValueType.SHORT -> irBuiltIns.shortClass
|
||||
ObjCValueType.INT -> irBuiltIns.intClass
|
||||
ObjCValueType.LONG_LONG -> irBuiltIns.longClass
|
||||
ObjCValueType.FLOAT -> irBuiltIns.floatClass
|
||||
ObjCValueType.DOUBLE -> irBuiltIns.doubleClass
|
||||
}.owner
|
||||
emitBoxConverter(irBuiltIns.booleanClass, ObjCValueType.BOOL, "numberWithBool:")
|
||||
emitBoxConverter(irBuiltIns.byteClass, ObjCValueType.CHAR, "numberWithChar:")
|
||||
emitBoxConverter(irBuiltIns.shortClass, ObjCValueType.SHORT, "numberWithShort:")
|
||||
emitBoxConverter(irBuiltIns.intClass, ObjCValueType.INT, "numberWithInt:")
|
||||
emitBoxConverter(irBuiltIns.longClass, ObjCValueType.LONG_LONG, "numberWithLongLong:")
|
||||
emitBoxConverter(symbols.uByte, ObjCValueType.UNSIGNED_CHAR, "numberWithUnsignedChar")
|
||||
emitBoxConverter(symbols.uShort, ObjCValueType.UNSIGNED_SHORT, "numberWithUnsignedShort:")
|
||||
emitBoxConverter(symbols.uInt, ObjCValueType.UNSIGNED_INT, "numberWithUnsignedInt:")
|
||||
emitBoxConverter(symbols.uLong, ObjCValueType.UNSIGNED_LONG_LONG, "numberWithUnsignedLongLong:")
|
||||
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 unboxFunction = context.getUnboxFunction(boxClass).llvmFunction
|
||||
@@ -368,7 +383,7 @@ private fun ObjCExportCodeGenerator.emitBoxConverter(objCValueType: ObjCValueTyp
|
||||
val value = kotlinToObjC(kotlinValue, objCValueType)
|
||||
|
||||
val nsNumber = genGetSystemClass("NSNumber")
|
||||
ret(genSendMessage(int8TypePtr, nsNumber, objCValueType.nsNumberFactorySelector, value))
|
||||
ret(genSendMessage(int8TypePtr, nsNumber, nsNumberFactorySelector, value))
|
||||
}
|
||||
|
||||
LLVMSetLinkage(converter, LLVMLinkage.LLVMPrivateLinkage)
|
||||
@@ -446,9 +461,7 @@ private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() {
|
||||
constPointer(context.llvm.Kotlin_Interop_CreateKotlinMutableDictonaryFromKMap)
|
||||
)
|
||||
|
||||
ObjCValueType.values().forEach {
|
||||
emitBoxConverter(it)
|
||||
}
|
||||
emitBoxConverters()
|
||||
|
||||
emitFunctionConverters()
|
||||
|
||||
@@ -1091,11 +1104,15 @@ private fun objCFunctionType(context: Context, methodBridge: MethodBridge): LLVM
|
||||
|
||||
private val ObjCValueType.llvmType: LLVMTypeRef get() = when (this) {
|
||||
ObjCValueType.BOOL -> int8Type
|
||||
ObjCValueType.UNICHAR -> int16Type
|
||||
ObjCValueType.CHAR -> int8Type
|
||||
ObjCValueType.UNSIGNED_SHORT -> int16Type
|
||||
ObjCValueType.SHORT -> int16Type
|
||||
ObjCValueType.INT -> int32Type
|
||||
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.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.descriptors.*
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -66,13 +67,18 @@ abstract class ObjCExportHeaderGenerator(
|
||||
result += CustomTypeMapper.Collection(generator, map, "NSDictionary")
|
||||
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,
|
||||
// so it is possible that it expects boxed number of other type and unboxes it incorrectly.
|
||||
// TODO: NSNumber seem to have different equality semantics.
|
||||
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")
|
||||
|
||||
(0..mapper.maxFunctionTypeParameterCount).forEach {
|
||||
@@ -737,11 +743,15 @@ abstract class ObjCExportHeaderGenerator(
|
||||
is ValueTypeBridge -> {
|
||||
val cName = when (typeBridge.objCValueType) {
|
||||
ObjCValueType.BOOL -> "BOOL"
|
||||
ObjCValueType.UNICHAR -> "unichar"
|
||||
ObjCValueType.CHAR -> "int8_t"
|
||||
ObjCValueType.UNSIGNED_SHORT -> "unichar"
|
||||
ObjCValueType.SHORT -> "int16_t"
|
||||
ObjCValueType.INT -> "int32_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.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.isInterface
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
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(
|
||||
eachInlinedClass = { _, _ ->
|
||||
// unsigned types to be handled.
|
||||
eachInlinedClass = { inlinedClass, _ ->
|
||||
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, _ ->
|
||||
val objCValueType = when (primitiveType) {
|
||||
KonanPrimitiveType.BOOLEAN -> ObjCValueType.BOOL
|
||||
KonanPrimitiveType.CHAR -> ObjCValueType.UNSIGNED_SHORT
|
||||
KonanPrimitiveType.CHAR -> ObjCValueType.UNICHAR
|
||||
KonanPrimitiveType.BYTE -> ObjCValueType.CHAR
|
||||
KonanPrimitiveType.SHORT -> ObjCValueType.SHORT
|
||||
KonanPrimitiveType.INT -> ObjCValueType.INT
|
||||
@@ -219,4 +225,4 @@ internal fun ObjCExportMapper.bridgePropertyType(descriptor: PropertyDescriptor)
|
||||
assert(isBaseProperty(descriptor))
|
||||
|
||||
return bridgeType(descriptor.type)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-16
@@ -111,27 +111,17 @@ object ObjCVoidType : ObjCType() {
|
||||
override fun render(attrsAndName: String) = "void".withAttrsAndName(attrsAndName)
|
||||
}
|
||||
|
||||
internal enum class ObjCValueType(
|
||||
val encoding: String
|
||||
) {
|
||||
|
||||
internal enum class ObjCValueType(val encoding: String) {
|
||||
BOOL("c"),
|
||||
UNICHAR("S"),
|
||||
CHAR("c"),
|
||||
SHORT("s"),
|
||||
UNSIGNED_SHORT("S"),
|
||||
INT("i"),
|
||||
LONG_LONG("q"),
|
||||
UNSIGNED_CHAR("C"),
|
||||
UNSIGNED_SHORT("S"),
|
||||
UNSIGNED_INT("I"),
|
||||
UNSIGNED_LONG_LONG("Q"),
|
||||
FLOAT("f"),
|
||||
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" {
|
||||
|
||||
OBJ_GETTER(Kotlin_boxBoolean, KBoolean value);
|
||||
OBJ_GETTER(Kotlin_boxChar, KChar value);
|
||||
OBJ_GETTER(Kotlin_boxByte, KByte value);
|
||||
OBJ_GETTER(Kotlin_boxShort, KShort value);
|
||||
OBJ_GETTER(Kotlin_boxInt, KInt 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_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.
|
||||
|
||||
switch (type[0]) {
|
||||
case 'S': RETURN_RESULT_OF(Kotlin_boxChar, self.unsignedShortValue);
|
||||
case 'c': RETURN_RESULT_OF(Kotlin_boxByte, self.charValue);
|
||||
case 's': RETURN_RESULT_OF(Kotlin_boxShort, self.shortValue);
|
||||
case 'i': RETURN_RESULT_OF(Kotlin_boxInt, self.intValue);
|
||||
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 'd': RETURN_RESULT_OF(Kotlin_boxDouble, self.doubleValue);
|
||||
|
||||
|
||||
@@ -42,6 +42,10 @@ typedef uint16_t KChar;
|
||||
typedef int16_t KShort;
|
||||
typedef int32_t KInt;
|
||||
typedef int64_t KLong;
|
||||
typedef uint8_t KUByte;
|
||||
typedef uint16_t KUShort;
|
||||
typedef uint32_t KUInt;
|
||||
typedef uint64_t KULong;
|
||||
typedef float KFloat;
|
||||
typedef double KDouble;
|
||||
typedef void* KNativePtr;
|
||||
|
||||
@@ -237,6 +237,29 @@ external private fun copyImpl(array: IntArray, fromIndex: Int,
|
||||
external private fun copyImpl(array: LongArray, fromIndex: 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")
|
||||
external private fun copyImpl(array: FloatArray, fromIndex: 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)
|
||||
}
|
||||
|
||||
@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) {
|
||||
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].
|
||||
*/
|
||||
@@ -972,6 +1060,54 @@ public actual fun LongArray.contentHashCode(): Int {
|
||||
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].
|
||||
*/
|
||||
|
||||
@@ -61,6 +61,22 @@ fun boxInt(value: Int): Int? = value
|
||||
@ExportForCppRuntime("Kotlin_boxLong")
|
||||
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")
|
||||
fun boxFloat(value: Float): Float? = value
|
||||
|
||||
|
||||
Reference in New Issue
Block a user