JDevlieghere created this revision.
JDevlieghere added reviewers: Michael137, bulbazord, jasonmolenda.
Herald added a project: All.
JDevlieghere requested review of this revision.

Support recursive record types in CTF. We are now more lazy when creating LLDB 
types. When encountering a record type (struct or union) we create a forward 
declaration and only complete it when requested.


https://reviews.llvm.org/D156498

Files:
  lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
  lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
  lldb/test/API/macosx/ctf/TestCTF.py
  lldb/test/API/macosx/ctf/test.c

Index: lldb/test/API/macosx/ctf/test.c
===================================================================
--- lldb/test/API/macosx/ctf/test.c
+++ lldb/test/API/macosx/ctf/test.c
@@ -36,9 +36,14 @@
   int b;
 };
 
+struct RecursiveStruct {
+  struct RecursiveStruct *n;
+};
+
 MyStructT foo;
 struct ForwardDecl *forward;
 struct LargeStruct bar;
+struct RecursiveStruct ke;
 
 void populate(MyInt i) {
   foo.n.i = i;
@@ -52,6 +57,7 @@
   foo.f = NULL;
   forward = NULL;
   bar.b = i;
+  ke.n = NULL;
 }
 
 int main(int argc, char** argv) {
Index: lldb/test/API/macosx/ctf/TestCTF.py
===================================================================
--- lldb/test/API/macosx/ctf/TestCTF.py
+++ lldb/test/API/macosx/ctf/TestCTF.py
@@ -91,4 +91,5 @@
                 "int b ",
             ],
         )
->>>>>>> Stashed changes
+
+        self.expect("type lookup RecursiveStruct", substrs=["RecursiveStruct *n;"])
Index: lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
===================================================================
--- lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
+++ lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
@@ -93,7 +93,7 @@
     return std::nullopt;
   }
 
-  bool CompleteType(CompilerType &compiler_type) override { return false; }
+  bool CompleteType(CompilerType &compiler_type) override;
 
   uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr,
                                 lldb::SymbolContextItem resolve_scope,
@@ -247,6 +247,11 @@
 
   std::vector<std::unique_ptr<CTFType>> m_ctf_types;
 
+  /// To complete types, we need a way to map (imcomplete) compiler types back
+  /// to parsed CTF types.
+  llvm::DenseMap<lldb::opaque_compiler_type_t, const CTFType *>
+      m_compiler_types;
+
   llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types;
 
   std::vector<lldb::FunctionSP> m_functions;
Index: lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
+++ lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
@@ -502,26 +502,55 @@
 llvm::Expected<lldb::TypeSP>
 SymbolFileCTF::CreateRecord(const CTFRecord &ctf_record) {
   const clang::TagTypeKind tag_kind = TranslateRecordKind(ctf_record.kind);
-
   CompilerType record_type =
       m_ast->CreateRecordType(nullptr, OptionalClangModuleID(), eAccessPublic,
                               ctf_record.name.data(), tag_kind, eLanguageTypeC);
+  m_compiler_types[record_type.GetOpaqueQualType()] = &ctf_record;
+  Declaration decl;
+  return MakeType(ctf_record.uid, ConstString(ctf_record.name), ctf_record.size,
+                  nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,
+                  decl, record_type, lldb_private::Type::ResolveState::Forward);
+}
+
+bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) {
+  // Check if we have a CTF type for the given incomplete compiler type.
+  auto it = m_compiler_types.find(compiler_type.GetOpaqueQualType());
+  if (it == m_compiler_types.end())
+    return false;
+
+  const CTFType *ctf_type = it->second;
+  assert(ctf_type && "m_compiler_types should only contain valid CTF types");
+
+  // We only support resolving record types.
+  assert(ctf_type->kind == CTFType::Kind::eStruct ||
+         ctf_type->kind == CTFType::Kind::eUnion);
 
-  m_ast->StartTagDeclarationDefinition(record_type);
-  for (const CTFRecord::Field &field : ctf_record.fields) {
-    if (Type *field_type = ResolveTypeUID(field.type)) {
-      const uint32_t field_size = field_type->GetByteSize(nullptr).value_or(0);
-      TypeSystemClang::AddFieldToRecordType(record_type, field.name,
-                                            field_type->GetFullCompilerType(),
-                                            eAccessPublic, field_size);
+  // Cast to the appropriate CTF type.
+  const CTFRecord *ctf_record = static_cast<const CTFRecord *>(ctf_type);
+
+  // If any of the fields are incomplete, we cannot complete the type.
+  for (const CTFRecord::Field &field : ctf_record->fields) {
+    if (!ResolveTypeUID(field.type)) {
+      LLDB_LOG(GetLog(LLDBLog::Symbols),
+               "Cannot complete type {0} because field {1} is incomplete",
+               ctf_type->uid, field.type);
+      return false;
     }
   }
-  m_ast->CompleteTagDeclarationDefinition(record_type);
 
-  Declaration decl;
-  return MakeType(ctf_record.uid, ConstString(ctf_record.name), ctf_record.size,
-                  nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,
-                  decl, record_type, lldb_private::Type::ResolveState::Full);
+  // Complete the record type.
+  m_ast->StartTagDeclarationDefinition(compiler_type);
+  for (const CTFRecord::Field &field : ctf_record->fields) {
+    Type *field_type = ResolveTypeUID(field.type);
+    assert(field_type && "field must be complete");
+    const uint32_t field_size = field_type->GetByteSize(nullptr).value_or(0);
+    TypeSystemClang::AddFieldToRecordType(compiler_type, field.name,
+                                          field_type->GetFullCompilerType(),
+                                          eAccessPublic, field_size);
+  }
+  m_ast->CompleteTagDeclarationDefinition(compiler_type);
+
+  return true;
 }
 
 llvm::Expected<lldb::TypeSP>
@@ -958,7 +987,6 @@
   if (!ctf_type)
     return nullptr;
 
-  m_types[type_uid] = TypeSP();
   Log *log = GetLog(LLDBLog::Symbols);
 
   llvm::Expected<TypeSP> type_or_error = CreateType(ctf_type);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to