Rework primitive types handling in interop stub generation
Use libclang API to get correct size and spelling. This should improve support for e.g. 32-bit platforms.
This commit is contained in:
committed by
SvyatoslavScherbina
parent
d6ba399e1e
commit
8ec4cb48f9
+4
-17
@@ -93,27 +93,14 @@ interface Type
|
||||
|
||||
interface PrimitiveType : Type
|
||||
|
||||
object VoidType : Type
|
||||
|
||||
object CharType : PrimitiveType
|
||||
|
||||
object Int8Type : PrimitiveType
|
||||
object UInt8Type : PrimitiveType
|
||||
data class IntegerType(val size: Int, val isSigned: Boolean, val spelling: String) : PrimitiveType
|
||||
|
||||
object Int16Type : PrimitiveType
|
||||
object UInt16Type : PrimitiveType
|
||||
// TODO: floating type is not actually defined entirely by its size.
|
||||
data class FloatingType(val size: Int, val spelling: String) : PrimitiveType
|
||||
|
||||
object Int32Type : PrimitiveType
|
||||
object UInt32Type : PrimitiveType
|
||||
|
||||
object IntPtrType : PrimitiveType
|
||||
object UIntPtrType : PrimitiveType
|
||||
|
||||
object Int64Type : PrimitiveType
|
||||
object UInt64Type : PrimitiveType
|
||||
|
||||
object Float32Type : PrimitiveType
|
||||
object Float64Type : PrimitiveType
|
||||
object VoidType : Type
|
||||
|
||||
data class RecordType(val decl: StructDecl) : Type
|
||||
|
||||
|
||||
+28
-18
@@ -19,28 +19,38 @@ internal fun CValue<CXString>.convertAndDispose(): String {
|
||||
internal fun getCursorSpelling(cursor: CValue<CXCursor>) =
|
||||
clang_getCursorSpelling(cursor).convertAndDispose()
|
||||
|
||||
internal fun CValue<CXType>.getSize(): Long {
|
||||
val size = clang_Type_getSizeOf(this)
|
||||
if (size < 0) {
|
||||
throw Error(size.toString())
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
internal fun convertUnqualifiedPrimitiveType(type: CValue<CXType>): Type = when (type.kind) {
|
||||
// TODO: is e.g. CXType_Int guaranteed to be int32_t?
|
||||
CXTypeKind.CXType_Char_U, CXTypeKind.CXType_Char_S -> {
|
||||
assert(type.getSize() == 1L)
|
||||
CharType
|
||||
}
|
||||
|
||||
CXTypeKind.CXType_Char_U, CXTypeKind.CXType_Char_S -> CharType
|
||||
CXTypeKind.CXType_UChar, CXTypeKind.CXType_UShort,
|
||||
CXTypeKind.CXType_UInt, CXTypeKind.CXType_ULong, CXTypeKind.CXType_ULongLong -> IntegerType(
|
||||
size = type.getSize().toInt(),
|
||||
isSigned = false,
|
||||
spelling = clang_getTypeSpelling(type).convertAndDispose()
|
||||
)
|
||||
|
||||
CXTypeKind.CXType_UChar -> UInt8Type
|
||||
CXTypeKind.CXType_SChar -> Int8Type
|
||||
CXTypeKind.CXType_SChar, CXTypeKind.CXType_Short,
|
||||
CXTypeKind.CXType_Int, CXTypeKind.CXType_Long, CXTypeKind.CXType_LongLong -> IntegerType(
|
||||
size = type.getSize().toInt(),
|
||||
isSigned = true,
|
||||
spelling = clang_getTypeSpelling(type).convertAndDispose()
|
||||
)
|
||||
|
||||
CXTypeKind.CXType_UShort -> UInt16Type
|
||||
CXTypeKind.CXType_Short -> Int16Type
|
||||
|
||||
CXTypeKind.CXType_UInt -> UInt32Type
|
||||
CXTypeKind.CXType_Int -> Int32Type
|
||||
|
||||
CXTypeKind.CXType_ULong -> UIntPtrType
|
||||
CXTypeKind.CXType_Long -> IntPtrType
|
||||
|
||||
CXTypeKind.CXType_ULongLong -> UInt64Type
|
||||
CXTypeKind.CXType_LongLong -> Int64Type
|
||||
|
||||
CXTypeKind.CXType_Float -> Float32Type
|
||||
CXTypeKind.CXType_Double -> Float64Type
|
||||
CXTypeKind.CXType_Float, CXTypeKind.CXType_Double -> FloatingType(
|
||||
size = type.getSize().toInt(),
|
||||
spelling = clang_getTypeSpelling(type).convertAndDispose()
|
||||
)
|
||||
|
||||
else -> UnsupportedType
|
||||
}
|
||||
|
||||
+43
-40
@@ -171,21 +171,10 @@ class StubGenerator(
|
||||
*/
|
||||
fun Type.getStringRepresentation(): String {
|
||||
return when (this) {
|
||||
|
||||
is VoidType -> "void"
|
||||
is CharType -> "char"
|
||||
is Int8Type -> "signed char"
|
||||
is UInt8Type -> "unsigned char"
|
||||
is Int16Type -> "short"
|
||||
is UInt16Type -> "unsigned short"
|
||||
is Int32Type -> "int"
|
||||
is UInt32Type -> "unsigned int"
|
||||
is IntPtrType -> "intptr_t"
|
||||
is UIntPtrType -> "uintptr_t"
|
||||
is Int64Type -> "int64_t"
|
||||
is UInt64Type -> "uint64_t"
|
||||
is Float32Type -> "float"
|
||||
is Float64Type -> "double"
|
||||
is IntegerType -> this.spelling
|
||||
is FloatingType -> this.spelling
|
||||
|
||||
is PointerType -> {
|
||||
val pointeeType = this.pointeeType
|
||||
@@ -214,14 +203,22 @@ class StubGenerator(
|
||||
|
||||
val PrimitiveType.kotlinType: String
|
||||
get() = when (this) {
|
||||
is CharType -> "Byte"
|
||||
|
||||
is CharType, is Int8Type, is UInt8Type -> "Byte"
|
||||
is Int16Type, is UInt16Type -> "Short"
|
||||
is Int32Type, is UInt32Type -> "Int"
|
||||
is IntPtrType, is UIntPtrType, // TODO: 64-bit specific
|
||||
is Int64Type, is UInt64Type -> "Long"
|
||||
is Float32Type -> "Float"
|
||||
is Float64Type -> "Double"
|
||||
// TODO: C primitive types should probably be generated as type aliases for Kotlin types.
|
||||
is IntegerType -> when (this.size) {
|
||||
1 -> "Byte"
|
||||
2 -> "Short"
|
||||
4 -> "Int"
|
||||
8 -> "Long"
|
||||
else -> TODO(this.toString())
|
||||
}
|
||||
|
||||
is FloatingType -> when (this.size) {
|
||||
4 -> "Float"
|
||||
8 -> "Double"
|
||||
else -> TODO(this.toString())
|
||||
}
|
||||
|
||||
else -> throw NotImplementedError()
|
||||
}
|
||||
@@ -327,13 +324,19 @@ class StubGenerator(
|
||||
|
||||
private fun mirror(type: PrimitiveType): TypeMirror.ByValue {
|
||||
val varTypeName = when (type) {
|
||||
is CharType, is Int8Type, is UInt8Type -> "CInt8Var"
|
||||
is Int16Type, is UInt16Type -> "CInt16Var"
|
||||
is Int32Type, is UInt32Type -> "CInt32Var"
|
||||
is IntPtrType, is UIntPtrType, // TODO: 64-bit specific
|
||||
is Int64Type, is UInt64Type -> "CInt64Var"
|
||||
is Float32Type -> "CFloat32Var"
|
||||
is Float64Type -> "CFloat64Var"
|
||||
is CharType -> "CInt8Var"
|
||||
is IntegerType -> when (type.size) {
|
||||
1 -> "CInt8Var"
|
||||
2 -> "CInt16Var"
|
||||
4 -> "CInt32Var"
|
||||
8 -> "CInt64Var"
|
||||
else -> TODO(type.toString())
|
||||
}
|
||||
is FloatingType -> when (type.size) {
|
||||
4 -> "CFloat32Var"
|
||||
8 -> "CFloat64Var"
|
||||
else -> TODO(type.toString())
|
||||
}
|
||||
else -> TODO(type.toString())
|
||||
}
|
||||
|
||||
@@ -845,17 +848,15 @@ class StubGenerator(
|
||||
private fun getFfiType(type: Type): String {
|
||||
return when(type) {
|
||||
is VoidType -> "Void"
|
||||
is CharType, is Int8Type -> "SInt8"
|
||||
// TODO: libffi has separate representation for char type.
|
||||
is UInt8Type -> "UInt8"
|
||||
is Int16Type -> "SInt16"
|
||||
is UInt16Type -> "UInt16"
|
||||
is Int32Type -> "SInt32"
|
||||
is UInt32Type -> "UInt32"
|
||||
is IntPtrType, is UIntPtrType, // TODO
|
||||
is CharType -> "SInt8" // TODO: libffi has separate representation for char type.
|
||||
is IntegerType -> when (type.size) {
|
||||
1 -> if (type.isSigned) "SInt8" else "UInt8"
|
||||
2 -> if (type.isSigned) "SInt16" else "UInt16"
|
||||
4 -> if (type.isSigned) "SInt32" else "UInt32"
|
||||
8 -> if (type.isSigned) "SInt64" else "UInt64"
|
||||
else -> TODO(type.toString())
|
||||
}
|
||||
is PointerType -> "Pointer"
|
||||
is Int64Type -> "SInt64"
|
||||
is UInt64Type -> "UInt64"
|
||||
is ConstArrayType -> getFfiStructType(
|
||||
Array(type.length.toInt(), { type.elemType }).toList()
|
||||
)
|
||||
@@ -992,13 +993,15 @@ class StubGenerator(
|
||||
}
|
||||
|
||||
private fun floatingLiteral(type: Type, value: Double): String? {
|
||||
return when (type.unwrapTypedefs()) {
|
||||
Float32Type -> {
|
||||
val unwrappedType = type.unwrapTypedefs()
|
||||
if (unwrappedType !is FloatingType) return null
|
||||
return when (unwrappedType.size) {
|
||||
4 -> {
|
||||
val floatValue = value.toFloat()
|
||||
val bits = java.lang.Float.floatToRawIntBits(floatValue)
|
||||
"bitsToFloat($bits) /* == $floatValue */"
|
||||
}
|
||||
Float64Type -> {
|
||||
8 -> {
|
||||
val bits = java.lang.Double.doubleToRawLongBits(value)
|
||||
"bitsToDouble($bits) /* == $value */"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user