committed by
SvyatoslavScherbina
parent
c81ceed7c6
commit
ce27695290
+36
-33
@@ -27,10 +27,10 @@ private class StructDeclImpl(spelling: String) : StructDecl(spelling) {
|
|||||||
|
|
||||||
private class StructDefImpl(
|
private class StructDefImpl(
|
||||||
size: Long, align: Int, decl: StructDecl,
|
size: Long, align: Int, decl: StructDecl,
|
||||||
hasNaturalLayout: Boolean, hasUnalignedFields: Boolean
|
hasNaturalLayout: Boolean
|
||||||
) : StructDef(
|
) : StructDef(
|
||||||
size, align, decl,
|
size, align, decl,
|
||||||
hasNaturalLayout = hasNaturalLayout, hasUnalignedFields = hasUnalignedFields
|
hasNaturalLayout = hasNaturalLayout
|
||||||
) {
|
) {
|
||||||
|
|
||||||
override val fields = mutableListOf<Field>()
|
override val fields = mutableListOf<Field>()
|
||||||
@@ -140,20 +140,39 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
|||||||
|
|
||||||
val structDef = StructDefImpl(
|
val structDef = StructDefImpl(
|
||||||
size, align, structDecl,
|
size, align, structDecl,
|
||||||
hasNaturalLayout = structHasNaturalLayout(cursor),
|
hasNaturalLayout = structHasNaturalLayout(cursor)
|
||||||
hasUnalignedFields = structHasUnalignedFields(cursor)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
structDecl.def = structDef
|
structDecl.def = structDef
|
||||||
|
|
||||||
visitChildren(cursor) { childCursor: CValue<CXCursor>, _: CValue<CXCursor> ->
|
addDeclaredFields(structDef, type, type)
|
||||||
if (clang_getCursorKind(childCursor) == CXCursorKind.CXCursor_FieldDecl) {
|
}
|
||||||
val name = clang_getCursorSpelling(childCursor).convertAndDispose()
|
|
||||||
val fieldType = convertCursorType(childCursor)
|
private fun addDeclaredFields(structDef: StructDefImpl, structType: CValue<CXType>, containerType: CValue<CXType>) {
|
||||||
val offset = clang_Cursor_getOffsetOfField(childCursor)
|
getFields(containerType).forEach { fieldCursor ->
|
||||||
structDef.fields.add(Field(name, fieldType, offset))
|
val name = getCursorSpelling(fieldCursor)
|
||||||
|
if (name.isNotEmpty()) {
|
||||||
|
val fieldType = convertCursorType(fieldCursor)
|
||||||
|
val offset = clang_Type_getOffsetOf(structType, name)
|
||||||
|
if (clang_Cursor_isBitField(fieldCursor) == 0) {
|
||||||
|
val typeAlign = clang_Type_getAlignOf(clang_getCursorType(fieldCursor))
|
||||||
|
structDef.fields.add(Field(name, fieldType, offset, typeAlign))
|
||||||
|
} else {
|
||||||
|
// Ignore bit fields for now.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Unnamed field.
|
||||||
|
val fieldType = clang_getCursorType(fieldCursor)
|
||||||
|
when (fieldType.kind) {
|
||||||
|
CXTypeKind.CXType_Record -> {
|
||||||
|
// Unnamed struct fields also contribute their fields:
|
||||||
|
addDeclaredFields(structDef, structType, fieldType)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// Nothing.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CXChildVisitResult.CXChildVisit_Continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,27 +360,6 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes [StructDef.hasUnalignedFields] property.
|
|
||||||
*/
|
|
||||||
fun structHasUnalignedFields(structDefCursor: CValue<CXCursor>): Boolean {
|
|
||||||
var hasUnalignedFields = false
|
|
||||||
visitChildren(structDefCursor) { child, _ ->
|
|
||||||
if (clang_getCursorKind(child) == CXCursorKind.CXCursor_FieldDecl &&
|
|
||||||
clang_Cursor_isBitField(child) == 0 &&
|
|
||||||
clang_Cursor_getOffsetOfField(child) %
|
|
||||||
(clang_Type_getAlignOf(clang_getCursorType(child)) * 8) != 0L) {
|
|
||||||
|
|
||||||
hasUnalignedFields = true
|
|
||||||
CXChildVisitResult.CXChildVisit_Break
|
|
||||||
} else {
|
|
||||||
CXChildVisitResult.CXChildVisit_Continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hasUnalignedFields
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun convertCursorType(cursor: CValue<CXCursor>) =
|
private fun convertCursorType(cursor: CValue<CXCursor>) =
|
||||||
convertType(clang_getCursorType(cursor), clang_getDeclTypeAttributes(cursor))
|
convertType(clang_getCursorType(cursor), clang_getDeclTypeAttributes(cursor))
|
||||||
|
|
||||||
@@ -507,7 +505,12 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
|||||||
|
|
||||||
when (kind) {
|
when (kind) {
|
||||||
CXIdxEntity_Struct, CXIdxEntity_Union -> {
|
CXIdxEntity_Struct, CXIdxEntity_Union -> {
|
||||||
getStructDeclAt(cursor)
|
if (entityName == null) {
|
||||||
|
// Skip anonymous struct.
|
||||||
|
// (It gets included anyway if used as a named field type).
|
||||||
|
} else {
|
||||||
|
getStructDeclAt(cursor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CXIdxEntity_Typedef -> {
|
CXIdxEntity_Typedef -> {
|
||||||
|
|||||||
+5
-3
@@ -50,7 +50,10 @@ abstract class NativeIndex {
|
|||||||
/**
|
/**
|
||||||
* C struct field.
|
* C struct field.
|
||||||
*/
|
*/
|
||||||
class Field(val name: String, val type: Type, val offset: Long)
|
class Field(val name: String, val type: Type, val offset: Long, val typeAlign: Long)
|
||||||
|
|
||||||
|
val Field.isAligned: Boolean
|
||||||
|
get() = offset % (typeAlign * 8) == 0L
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C struct declaration.
|
* C struct declaration.
|
||||||
@@ -68,8 +71,7 @@ abstract class StructDecl(val spelling: String) {
|
|||||||
*/
|
*/
|
||||||
abstract class StructDef(val size: Long, val align: Int,
|
abstract class StructDef(val size: Long, val align: Int,
|
||||||
val decl: StructDecl,
|
val decl: StructDecl,
|
||||||
val hasNaturalLayout: Boolean,
|
val hasNaturalLayout: Boolean) {
|
||||||
val hasUnalignedFields: Boolean) {
|
|
||||||
|
|
||||||
abstract val fields: List<Field>
|
abstract val fields: List<Field>
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-6
@@ -137,17 +137,41 @@ internal typealias CursorVisitor = (cursor: CValue<CXCursor>, parent: CValue<CXC
|
|||||||
|
|
||||||
internal fun visitChildren(parent: CValue<CXCursor>, visitor: CursorVisitor) {
|
internal fun visitChildren(parent: CValue<CXCursor>, visitor: CursorVisitor) {
|
||||||
val visitorPtr = StableObjPtr.create(visitor)
|
val visitorPtr = StableObjPtr.create(visitor)
|
||||||
val clientData = visitorPtr.value
|
try {
|
||||||
clang_visitChildren(parent, staticCFunction { cursor, parent, clientData ->
|
val clientData = visitorPtr.value
|
||||||
@Suppress("NAME_SHADOWING", "UNCHECKED_CAST")
|
clang_visitChildren(parent, staticCFunction { cursor, parent, clientData ->
|
||||||
val visitor = StableObjPtr.fromValue(clientData!!).get() as CursorVisitor
|
@Suppress("NAME_SHADOWING", "UNCHECKED_CAST")
|
||||||
visitor(cursor, parent)
|
val visitor = StableObjPtr.fromValue(clientData!!).get() as CursorVisitor
|
||||||
}, clientData)
|
visitor(cursor, parent)
|
||||||
|
}, clientData)
|
||||||
|
} finally {
|
||||||
|
visitorPtr.dispose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun visitChildren(translationUnit: CXTranslationUnit, visitor: CursorVisitor) =
|
internal fun visitChildren(translationUnit: CXTranslationUnit, visitor: CursorVisitor) =
|
||||||
visitChildren(clang_getTranslationUnitCursor(translationUnit), visitor)
|
visitChildren(clang_getTranslationUnitCursor(translationUnit), visitor)
|
||||||
|
|
||||||
|
internal fun getFields(type: CValue<CXType>): List<CValue<CXCursor>> {
|
||||||
|
val result = mutableListOf<CValue<CXCursor>>()
|
||||||
|
val resultPtr = StableObjPtr.create(result)
|
||||||
|
try {
|
||||||
|
val clientData = resultPtr.value
|
||||||
|
|
||||||
|
@Suppress("NAME_SHADOWING", "UNCHECKED_CAST")
|
||||||
|
clang_Type_visitFields(type, staticCFunction { cursor, clientData ->
|
||||||
|
val result = StableObjPtr.fromValue(clientData!!).get() as MutableList<CValue<CXCursor>>
|
||||||
|
result.add(cursor)
|
||||||
|
CXVisitorResult.CXVisit_Continue
|
||||||
|
}, clientData)
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
resultPtr.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
internal fun CValue<CXCursor>.isLeaf(): Boolean {
|
internal fun CValue<CXCursor>.isLeaf(): Boolean {
|
||||||
var hasChildren = false
|
var hasChildren = false
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -213,8 +213,11 @@ private fun Type.isLargeOrUnaligned(): Boolean {
|
|||||||
private fun Type.hasUnalignedMembers(): Boolean = when (this) {
|
private fun Type.hasUnalignedMembers(): Boolean = when (this) {
|
||||||
is Typedef -> this.def.aliased.hasUnalignedMembers()
|
is Typedef -> this.def.aliased.hasUnalignedMembers()
|
||||||
is RecordType -> this.decl.def!!.let { def ->
|
is RecordType -> this.decl.def!!.let { def ->
|
||||||
def.hasUnalignedFields || // Check members of fields too:
|
def.fields.any {
|
||||||
def.fields.any { it.type.hasUnalignedMembers() }
|
!it.isAligned ||
|
||||||
|
// Check members of fields too:
|
||||||
|
it.type.hasUnalignedMembers()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is ArrayType -> this.elemType.hasUnalignedMembers()
|
is ArrayType -> this.elemType.hasUnalignedMembers()
|
||||||
else -> false
|
else -> false
|
||||||
|
|||||||
+2
-2
@@ -267,9 +267,9 @@ class StubGenerator(
|
|||||||
out("companion object : Type(${def.size}, ${def.align})") // FIXME: align
|
out("companion object : Type(${def.size}, ${def.align})") // FIXME: align
|
||||||
out("")
|
out("")
|
||||||
for (field in def.fields) {
|
for (field in def.fields) {
|
||||||
if (field.name.isEmpty()) continue
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
assert(field.name.isNotEmpty())
|
||||||
|
|
||||||
if (field.offset < 0) throw NotImplementedError();
|
if (field.offset < 0) throw NotImplementedError();
|
||||||
assert(field.offset % 8 == 0L)
|
assert(field.offset % 8 == 0L)
|
||||||
val offset = field.offset / 8
|
val offset = field.offset / 8
|
||||||
|
|||||||
Reference in New Issue
Block a user