committed by
SvyatoslavScherbina
parent
c81ceed7c6
commit
ce27695290
+36
-33
@@ -27,10 +27,10 @@ private class StructDeclImpl(spelling: String) : StructDecl(spelling) {
|
||||
|
||||
private class StructDefImpl(
|
||||
size: Long, align: Int, decl: StructDecl,
|
||||
hasNaturalLayout: Boolean, hasUnalignedFields: Boolean
|
||||
hasNaturalLayout: Boolean
|
||||
) : StructDef(
|
||||
size, align, decl,
|
||||
hasNaturalLayout = hasNaturalLayout, hasUnalignedFields = hasUnalignedFields
|
||||
hasNaturalLayout = hasNaturalLayout
|
||||
) {
|
||||
|
||||
override val fields = mutableListOf<Field>()
|
||||
@@ -140,20 +140,39 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
||||
|
||||
val structDef = StructDefImpl(
|
||||
size, align, structDecl,
|
||||
hasNaturalLayout = structHasNaturalLayout(cursor),
|
||||
hasUnalignedFields = structHasUnalignedFields(cursor)
|
||||
hasNaturalLayout = structHasNaturalLayout(cursor)
|
||||
)
|
||||
|
||||
structDecl.def = structDef
|
||||
|
||||
visitChildren(cursor) { childCursor: CValue<CXCursor>, _: CValue<CXCursor> ->
|
||||
if (clang_getCursorKind(childCursor) == CXCursorKind.CXCursor_FieldDecl) {
|
||||
val name = clang_getCursorSpelling(childCursor).convertAndDispose()
|
||||
val fieldType = convertCursorType(childCursor)
|
||||
val offset = clang_Cursor_getOffsetOfField(childCursor)
|
||||
structDef.fields.add(Field(name, fieldType, offset))
|
||||
addDeclaredFields(structDef, type, type)
|
||||
}
|
||||
|
||||
private fun addDeclaredFields(structDef: StructDefImpl, structType: CValue<CXType>, containerType: CValue<CXType>) {
|
||||
getFields(containerType).forEach { fieldCursor ->
|
||||
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>) =
|
||||
convertType(clang_getCursorType(cursor), clang_getDeclTypeAttributes(cursor))
|
||||
|
||||
@@ -507,7 +505,12 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
||||
|
||||
when (kind) {
|
||||
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 -> {
|
||||
|
||||
+5
-3
@@ -50,7 +50,10 @@ abstract class NativeIndex {
|
||||
/**
|
||||
* 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.
|
||||
@@ -68,8 +71,7 @@ abstract class StructDecl(val spelling: String) {
|
||||
*/
|
||||
abstract class StructDef(val size: Long, val align: Int,
|
||||
val decl: StructDecl,
|
||||
val hasNaturalLayout: Boolean,
|
||||
val hasUnalignedFields: Boolean) {
|
||||
val hasNaturalLayout: Boolean) {
|
||||
|
||||
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) {
|
||||
val visitorPtr = StableObjPtr.create(visitor)
|
||||
val clientData = visitorPtr.value
|
||||
clang_visitChildren(parent, staticCFunction { cursor, parent, clientData ->
|
||||
@Suppress("NAME_SHADOWING", "UNCHECKED_CAST")
|
||||
val visitor = StableObjPtr.fromValue(clientData!!).get() as CursorVisitor
|
||||
visitor(cursor, parent)
|
||||
}, clientData)
|
||||
try {
|
||||
val clientData = visitorPtr.value
|
||||
clang_visitChildren(parent, staticCFunction { cursor, parent, clientData ->
|
||||
@Suppress("NAME_SHADOWING", "UNCHECKED_CAST")
|
||||
val visitor = StableObjPtr.fromValue(clientData!!).get() as CursorVisitor
|
||||
visitor(cursor, parent)
|
||||
}, clientData)
|
||||
} finally {
|
||||
visitorPtr.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun visitChildren(translationUnit: CXTranslationUnit, visitor: CursorVisitor) =
|
||||
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 {
|
||||
var hasChildren = false
|
||||
|
||||
|
||||
+5
-2
@@ -213,8 +213,11 @@ private fun Type.isLargeOrUnaligned(): Boolean {
|
||||
private fun Type.hasUnalignedMembers(): Boolean = when (this) {
|
||||
is Typedef -> this.def.aliased.hasUnalignedMembers()
|
||||
is RecordType -> this.decl.def!!.let { def ->
|
||||
def.hasUnalignedFields || // Check members of fields too:
|
||||
def.fields.any { it.type.hasUnalignedMembers() }
|
||||
def.fields.any {
|
||||
!it.isAligned ||
|
||||
// Check members of fields too:
|
||||
it.type.hasUnalignedMembers()
|
||||
}
|
||||
}
|
||||
is ArrayType -> this.elemType.hasUnalignedMembers()
|
||||
else -> false
|
||||
|
||||
+2
-2
@@ -267,9 +267,9 @@ class StubGenerator(
|
||||
out("companion object : Type(${def.size}, ${def.align})") // FIXME: align
|
||||
out("")
|
||||
for (field in def.fields) {
|
||||
if (field.name.isEmpty()) continue
|
||||
|
||||
try {
|
||||
assert(field.name.isNotEmpty())
|
||||
|
||||
if (field.offset < 0) throw NotImplementedError();
|
||||
assert(field.offset % 8 == 0L)
|
||||
val offset = field.offset / 8
|
||||
|
||||
Reference in New Issue
Block a user