Author: Raphael Isemann Date: 2021-10-19T12:05:14+02:00 New Revision: 9a57d1e52680ac05c29d6d0d2cfbaf3b05a5cbce
URL: https://github.com/llvm/llvm-project/commit/9a57d1e52680ac05c29d6d0d2cfbaf3b05a5cbce DIFF: https://github.com/llvm/llvm-project/commit/9a57d1e52680ac05c29d6d0d2cfbaf3b05a5cbce.diff LOG: [lldb] Allow dumping the state of all scratch TypeSystems This adds the `target dump typesystem'`command which dumps the TypeSystem of the target itself (aka the 'scratch TypeSystem'). This is similar to `target modules dump ast` which dumps the AST of lldb::Modules associated with a selected target. Unlike `target modules dump ast`, the new command is not a subcommand of `target modules dump` as it's not touching the modules of a target at all. Also unlike `target modules dump ast` I tried to keep the implementation language-neutral, so this patch moves our Clang `Dump` to the `TypeSystem` interface so it will also dump the state of any future/downstream scratch TypeSystems (e.g., Swift). That's also why the command just refers to a 'typesystem' instead of an 'ast' (which is only how Clang is necessarily modelling the internal TypeSystem state). The main motivation for this patch is that I need to write some tests that check for duplicates in the ScratchTypeSystemClang of a target. There is currently no way to check for this at the moment (beside measuring memory consumption of course). It's probably also useful for debugging LLDB itself. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D111936 Added: lldb/test/API/commands/target/dump/Makefile lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py lldb/test/API/commands/target/dump/main.cpp Modified: lldb/include/lldb/Symbol/TypeSystem.h lldb/source/Commands/CommandObjectTarget.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h Removed: ################################################################################ diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index a37c1040b16e7..e695f65807671 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -392,6 +392,12 @@ class TypeSystem : public PluginInterface { lldb::opaque_compiler_type_t type, Stream *s, lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) = 0; + /// Dump a textual representation of the internal TypeSystem state to the + /// given stream. + /// + /// This should not modify the state of the TypeSystem if possible. + virtual void Dump(llvm::raw_ostream &output) = 0; + // TODO: These methods appear unused. Should they be removed? virtual bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) = 0; diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 3112216f8a352..e0a88a710fb97 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -4990,6 +4990,55 @@ class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword { ~CommandObjectMultiwordTargetStopHooks() override = default; }; +#pragma mark CommandObjectTargetDumpTypesystem + +/// Dumps the TypeSystem of the selected Target. +class CommandObjectTargetDumpTypesystem : public CommandObjectParsed { +public: + CommandObjectTargetDumpTypesystem(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "target dump typesystem", + "Dump the state of the target's internal type system.\n" + "Intended to be used for debugging LLDB itself.", + nullptr, eCommandRequiresTarget) {} + + ~CommandObjectTargetDumpTypesystem() override = default; + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (!command.empty()) { + result.AppendError("target dump typesystem doesn't take arguments."); + return result.Succeeded(); + } + + // Go over every scratch TypeSystem and dump to the command output. + for (TypeSystem *ts : GetSelectedTarget().GetScratchTypeSystems()) + ts->Dump(result.GetOutputStream().AsRawOstream()); + + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } +}; + +#pragma mark CommandObjectTargetDump + +/// Multi-word command for 'target dump'. +class CommandObjectTargetDump : public CommandObjectMultiword { +public: + // Constructors and Destructors + CommandObjectTargetDump(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "target dump", + "Commands for dumping information about the target.", + "target dump [typesystem]") { + LoadSubCommand( + "typesystem", + CommandObjectSP(new CommandObjectTargetDumpTypesystem(interpreter))); + } + + ~CommandObjectTargetDump() override = default; +}; + #pragma mark CommandObjectMultiwordTarget // CommandObjectMultiwordTarget @@ -5003,6 +5052,8 @@ CommandObjectMultiwordTarget::CommandObjectMultiwordTarget( CommandObjectSP(new CommandObjectTargetCreate(interpreter))); LoadSubCommand("delete", CommandObjectSP(new CommandObjectTargetDelete(interpreter))); + LoadSubCommand("dump", + CommandObjectSP(new CommandObjectTargetDump(interpreter))); LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetList(interpreter))); LoadSubCommand("select", diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 81c730539604e..c396e591ddc45 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3846,7 +3846,7 @@ void SymbolFileDWARF::DumpClangAST(Stream &s) { llvm::dyn_cast_or_null<TypeSystemClang>(&ts_or_err.get()); if (!clang) return; - clang->Dump(s); + clang->Dump(s.AsRawOstream()); } SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 43cf262016c2f..8856c7e72e08a 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -1358,4 +1358,6 @@ PdbAstBuilder::FromCompilerDeclContext(CompilerDeclContext context) { return static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext()); } -void PdbAstBuilder::Dump(Stream &stream) { m_clang.Dump(stream); } +void PdbAstBuilder::Dump(Stream &stream) { + m_clang.Dump(stream.AsRawOstream()); +} diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index 9c98ce76ba40e..f6e34285138ce 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1461,7 +1461,7 @@ void SymbolFilePDB::DumpClangAST(Stream &s) { llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); if (!clang_type_system) return; - clang_type_system->Dump(s); + clang_type_system->Dump(s.AsRawOstream()); } void SymbolFilePDB::FindTypesByRegex( diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 6db0f5a5d2af5..00daaad41a6e1 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -8358,9 +8358,8 @@ TypeSystemClang::dump(lldb::opaque_compiler_type_t type) const { } #endif -void TypeSystemClang::Dump(Stream &s) { - Decl *tu = Decl::castFromDeclContext(GetTranslationUnitDecl()); - tu->dump(s.AsRawOstream()); +void TypeSystemClang::Dump(llvm::raw_ostream &output) { + GetTranslationUnitDecl()->dump(output); } void TypeSystemClang::DumpFromSymbolFile(Stream &s, @@ -9746,6 +9745,41 @@ ScratchTypeSystemClang::GetForTarget(Target &target, return &scratch_ast.GetIsolatedAST(*ast_kind); } +/// Returns a human-readable name that uniquely identifiers the sub-AST kind. +static llvm::StringRef +GetNameForIsolatedASTKind(ScratchTypeSystemClang::IsolatedASTKind kind) { + switch (kind) { + case ScratchTypeSystemClang::IsolatedASTKind::CppModules: + return "C++ modules"; + } + llvm_unreachable("Unimplemented IsolatedASTKind?"); +} + +void ScratchTypeSystemClang::Dump(llvm::raw_ostream &output) { + // First dump the main scratch AST. + output << "State of scratch Clang type system:\n"; + TypeSystemClang::Dump(output); + + // Now sort the isolated sub-ASTs. + typedef std::pair<IsolatedASTKey, TypeSystem *> KeyAndTS; + std::vector<KeyAndTS> sorted_typesystems; + for (const auto &a : m_isolated_asts) + sorted_typesystems.emplace_back(a.first, a.second.get()); + llvm::stable_sort(sorted_typesystems, + [](const KeyAndTS &lhs, const KeyAndTS &rhs) { + return lhs.first < rhs.first; + }); + + // Dump each sub-AST too. + for (const auto &a : sorted_typesystems) { + IsolatedASTKind kind = + static_cast<ScratchTypeSystemClang::IsolatedASTKind>(a.first); + output << "State of scratch Clang type subsystem " + << GetNameForIsolatedASTKind(kind) << ":\n"; + a.second->Dump(output); + } +} + UserExpression *ScratchTypeSystemClang::GetUserExpression( llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language, Expression::ResultType desired_type, diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 1c57440fda29c..93300439806d4 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -938,7 +938,8 @@ class TypeSystemClang : public TypeSystem { LLVM_DUMP_METHOD void dump(lldb::opaque_compiler_type_t type) const override; #endif - void Dump(Stream &s); + /// \see lldb_private::TypeSystem::Dump + void Dump(llvm::raw_ostream &output) override; /// Dump clang AST types from the symbol file. /// @@ -1162,6 +1163,9 @@ class ScratchTypeSystemClang : public TypeSystemClang { return GetForTarget(target, InferIsolatedASTKindFromLangOpts(lang_opts)); } + /// \see lldb_private::TypeSystem::Dump + void Dump(llvm::raw_ostream &output) override; + UserExpression * GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language, diff --git a/lldb/test/API/commands/target/dump/Makefile b/lldb/test/API/commands/target/dump/Makefile new file mode 100644 index 0000000000000..99998b20bcb05 --- /dev/null +++ b/lldb/test/API/commands/target/dump/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py b/lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py new file mode 100644 index 0000000000000..c9a20b8aa1e41 --- /dev/null +++ b/lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py @@ -0,0 +1,33 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil + +class TestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_dumping(self): + """ Tests dumping an empty and non-empty scratch AST. """ + self.build() + self.createTestTarget() + + # Make sure DummyStruct is not in the scratch AST by default. + self.expect("target dump typesystem", matching=False, substrs=["struct DummyStruct"]) + + # Move DummyStruct into the scratch AST via the expression evaluator. + # FIXME: Once there is an SB API for using variable paths on globals + # then this should be done this way. + self.expect_expr("s", result_type="DummyStruct") + + # Dump the scratch AST and make sure DummyStruct is in there. + self.expect("target dump typesystem", substrs=["struct DummyStruct"]) + + @no_debug_info_test + def test_invalid_arg(self): + """ Test an invalid invocation on 'target dump typesystem'. """ + self.build() + self.createTestTarget() + self.expect("target dump typesystem arg", error=True, + substrs=["error: target dump typesystem doesn't take arguments."]) diff --git a/lldb/test/API/commands/target/dump/main.cpp b/lldb/test/API/commands/target/dump/main.cpp new file mode 100644 index 0000000000000..4db770ece5335 --- /dev/null +++ b/lldb/test/API/commands/target/dump/main.cpp @@ -0,0 +1,7 @@ +struct DummyStruct { + int i; +}; + +DummyStruct s; + +int main() { return s.i; } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits