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
|
interface PrimitiveType : Type
|
||||||
|
|
||||||
object VoidType : Type
|
|
||||||
|
|
||||||
object CharType : PrimitiveType
|
object CharType : PrimitiveType
|
||||||
|
|
||||||
object Int8Type : PrimitiveType
|
data class IntegerType(val size: Int, val isSigned: Boolean, val spelling: String) : PrimitiveType
|
||||||
object UInt8Type : PrimitiveType
|
|
||||||
|
|
||||||
object Int16Type : PrimitiveType
|
// TODO: floating type is not actually defined entirely by its size.
|
||||||
object UInt16Type : PrimitiveType
|
data class FloatingType(val size: Int, val spelling: String) : PrimitiveType
|
||||||
|
|
||||||
object Int32Type : PrimitiveType
|
object VoidType : Type
|
||||||
object UInt32Type : PrimitiveType
|
|
||||||
|
|
||||||
object IntPtrType : PrimitiveType
|
|
||||||
object UIntPtrType : PrimitiveType
|
|
||||||
|
|
||||||
object Int64Type : PrimitiveType
|
|
||||||
object UInt64Type : PrimitiveType
|
|
||||||
|
|
||||||
object Float32Type : PrimitiveType
|
|
||||||
object Float64Type : PrimitiveType
|
|
||||||
|
|
||||||
data class RecordType(val decl: StructDecl) : 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>) =
|
internal fun getCursorSpelling(cursor: CValue<CXCursor>) =
|
||||||
clang_getCursorSpelling(cursor).convertAndDispose()
|
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) {
|
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, CXTypeKind.CXType_Short,
|
||||||
CXTypeKind.CXType_SChar -> Int8Type
|
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_Float, CXTypeKind.CXType_Double -> FloatingType(
|
||||||
CXTypeKind.CXType_Short -> Int16Type
|
size = type.getSize().toInt(),
|
||||||
|
spelling = clang_getTypeSpelling(type).convertAndDispose()
|
||||||
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
|
|
||||||
|
|
||||||
else -> UnsupportedType
|
else -> UnsupportedType
|
||||||
}
|
}
|
||||||
|
|||||||
+43
-40
@@ -171,21 +171,10 @@ class StubGenerator(
|
|||||||
*/
|
*/
|
||||||
fun Type.getStringRepresentation(): String {
|
fun Type.getStringRepresentation(): String {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
|
|
||||||
is VoidType -> "void"
|
is VoidType -> "void"
|
||||||
is CharType -> "char"
|
is CharType -> "char"
|
||||||
is Int8Type -> "signed char"
|
is IntegerType -> this.spelling
|
||||||
is UInt8Type -> "unsigned char"
|
is FloatingType -> this.spelling
|
||||||
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 PointerType -> {
|
is PointerType -> {
|
||||||
val pointeeType = this.pointeeType
|
val pointeeType = this.pointeeType
|
||||||
@@ -214,14 +203,22 @@ class StubGenerator(
|
|||||||
|
|
||||||
val PrimitiveType.kotlinType: String
|
val PrimitiveType.kotlinType: String
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
|
is CharType -> "Byte"
|
||||||
|
|
||||||
is CharType, is Int8Type, is UInt8Type -> "Byte"
|
// TODO: C primitive types should probably be generated as type aliases for Kotlin types.
|
||||||
is Int16Type, is UInt16Type -> "Short"
|
is IntegerType -> when (this.size) {
|
||||||
is Int32Type, is UInt32Type -> "Int"
|
1 -> "Byte"
|
||||||
is IntPtrType, is UIntPtrType, // TODO: 64-bit specific
|
2 -> "Short"
|
||||||
is Int64Type, is UInt64Type -> "Long"
|
4 -> "Int"
|
||||||
is Float32Type -> "Float"
|
8 -> "Long"
|
||||||
is Float64Type -> "Double"
|
else -> TODO(this.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
is FloatingType -> when (this.size) {
|
||||||
|
4 -> "Float"
|
||||||
|
8 -> "Double"
|
||||||
|
else -> TODO(this.toString())
|
||||||
|
}
|
||||||
|
|
||||||
else -> throw NotImplementedError()
|
else -> throw NotImplementedError()
|
||||||
}
|
}
|
||||||
@@ -327,13 +324,19 @@ class StubGenerator(
|
|||||||
|
|
||||||
private fun mirror(type: PrimitiveType): TypeMirror.ByValue {
|
private fun mirror(type: PrimitiveType): TypeMirror.ByValue {
|
||||||
val varTypeName = when (type) {
|
val varTypeName = when (type) {
|
||||||
is CharType, is Int8Type, is UInt8Type -> "CInt8Var"
|
is CharType -> "CInt8Var"
|
||||||
is Int16Type, is UInt16Type -> "CInt16Var"
|
is IntegerType -> when (type.size) {
|
||||||
is Int32Type, is UInt32Type -> "CInt32Var"
|
1 -> "CInt8Var"
|
||||||
is IntPtrType, is UIntPtrType, // TODO: 64-bit specific
|
2 -> "CInt16Var"
|
||||||
is Int64Type, is UInt64Type -> "CInt64Var"
|
4 -> "CInt32Var"
|
||||||
is Float32Type -> "CFloat32Var"
|
8 -> "CInt64Var"
|
||||||
is Float64Type -> "CFloat64Var"
|
else -> TODO(type.toString())
|
||||||
|
}
|
||||||
|
is FloatingType -> when (type.size) {
|
||||||
|
4 -> "CFloat32Var"
|
||||||
|
8 -> "CFloat64Var"
|
||||||
|
else -> TODO(type.toString())
|
||||||
|
}
|
||||||
else -> TODO(type.toString())
|
else -> TODO(type.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -845,17 +848,15 @@ class StubGenerator(
|
|||||||
private fun getFfiType(type: Type): String {
|
private fun getFfiType(type: Type): String {
|
||||||
return when(type) {
|
return when(type) {
|
||||||
is VoidType -> "Void"
|
is VoidType -> "Void"
|
||||||
is CharType, is Int8Type -> "SInt8"
|
is CharType -> "SInt8" // TODO: libffi has separate representation for char type.
|
||||||
// TODO: libffi has separate representation for char type.
|
is IntegerType -> when (type.size) {
|
||||||
is UInt8Type -> "UInt8"
|
1 -> if (type.isSigned) "SInt8" else "UInt8"
|
||||||
is Int16Type -> "SInt16"
|
2 -> if (type.isSigned) "SInt16" else "UInt16"
|
||||||
is UInt16Type -> "UInt16"
|
4 -> if (type.isSigned) "SInt32" else "UInt32"
|
||||||
is Int32Type -> "SInt32"
|
8 -> if (type.isSigned) "SInt64" else "UInt64"
|
||||||
is UInt32Type -> "UInt32"
|
else -> TODO(type.toString())
|
||||||
is IntPtrType, is UIntPtrType, // TODO
|
}
|
||||||
is PointerType -> "Pointer"
|
is PointerType -> "Pointer"
|
||||||
is Int64Type -> "SInt64"
|
|
||||||
is UInt64Type -> "UInt64"
|
|
||||||
is ConstArrayType -> getFfiStructType(
|
is ConstArrayType -> getFfiStructType(
|
||||||
Array(type.length.toInt(), { type.elemType }).toList()
|
Array(type.length.toInt(), { type.elemType }).toList()
|
||||||
)
|
)
|
||||||
@@ -992,13 +993,15 @@ class StubGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun floatingLiteral(type: Type, value: Double): String? {
|
private fun floatingLiteral(type: Type, value: Double): String? {
|
||||||
return when (type.unwrapTypedefs()) {
|
val unwrappedType = type.unwrapTypedefs()
|
||||||
Float32Type -> {
|
if (unwrappedType !is FloatingType) return null
|
||||||
|
return when (unwrappedType.size) {
|
||||||
|
4 -> {
|
||||||
val floatValue = value.toFloat()
|
val floatValue = value.toFloat()
|
||||||
val bits = java.lang.Float.floatToRawIntBits(floatValue)
|
val bits = java.lang.Float.floatToRawIntBits(floatValue)
|
||||||
"bitsToFloat($bits) /* == $floatValue */"
|
"bitsToFloat($bits) /* == $floatValue */"
|
||||||
}
|
}
|
||||||
Float64Type -> {
|
8 -> {
|
||||||
val bits = java.lang.Double.doubleToRawLongBits(value)
|
val bits = java.lang.Double.doubleToRawLongBits(value)
|
||||||
"bitsToDouble($bits) /* == $value */"
|
"bitsToDouble($bits) /* == $value */"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user