diff --git a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst index 60fa024db5e99..fa4a3924879ac 100644 --- a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst +++ b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst @@ -528,6 +528,7 @@ The following options allow printing of scopes that match the given . =TemplatePack: A template pack. =TryBlock: An exception try block. =Union: A union. + =Module: A module. SYMBOLS ^^^^^^^ diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h index 17fa04040ad77..b4e09d901eb9b 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h @@ -45,6 +45,7 @@ enum class LVSubclassID : unsigned char { LV_SCOPE_NAMESPACE, LV_SCOPE_ROOT, LV_SCOPE_TEMPLATE_PACK, + LV_SCOPE_MODULE, LV_SCOPE_LAST, LV_SYMBOL_FIRST, LV_SYMBOL, diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h index 9ce26398e48df..b0d8ff4952d79 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h @@ -107,6 +107,7 @@ class LVReader { LV_OBJECT_ALLOCATOR(ScopeNamespace) LV_OBJECT_ALLOCATOR(ScopeRoot) LV_OBJECT_ALLOCATOR(ScopeTemplatePack) + LV_OBJECT_ALLOCATOR(ScopeModule) // Symbols allocator. LV_OBJECT_ALLOCATOR(Symbol) @@ -213,6 +214,7 @@ class LVReader { LV_CREATE_OBJECT(ScopeNamespace) LV_CREATE_OBJECT(ScopeRoot) LV_CREATE_OBJECT(ScopeTemplatePack) + LV_CREATE_OBJECT(ScopeModule) // Symbols creation. LV_CREATE_OBJECT(Symbol) diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h index 1b3c377cd7dbb..76ee19848ef0a 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h @@ -57,6 +57,7 @@ enum class LVScopeKind { IsTemplatePack, IsTryBlock, IsUnion, + IsModule, LastEntry }; using LVScopeKindSet = std::set; @@ -181,6 +182,7 @@ class LVScope : public LVElement { KIND(LVScopeKind, IsTemplatePack); KIND_1(LVScopeKind, IsTryBlock, IsBlock); KIND_1(LVScopeKind, IsUnion, IsAggregate); + KIND_2(LVScopeKind, IsModule, CanHaveRanges, CanHaveLines); PROPERTY(Property, HasDiscriminator); PROPERTY(Property, CanHaveRanges); @@ -826,6 +828,23 @@ class LVScopeTemplatePack final : public LVScope { void printExtra(raw_ostream &OS, bool Full = true) const override; }; +// Class to represent a DWARF Module. +class LVScopeModule final : public LVScope { +public: + LVScopeModule() : LVScope() { + setIsModule(); + setIsLexicalBlock(); + } + LVScopeModule(const LVScopeModule &) = delete; + LVScopeModule &operator=(const LVScopeModule &) = delete; + ~LVScopeModule() = default; + + // Returns true if current scope is logically equal to the given 'Scope'. + bool equals(const LVScope *Scope) const override; + + void printExtra(raw_ostream &OS, bool Full = true) const override; +}; + } // end namespace logicalview } // end namespace llvm diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp index 8bbaf93db0caa..7ffeed8f18f8a 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp @@ -40,6 +40,7 @@ const char *const KindTemplateAlias = "TemplateAlias"; const char *const KindTemplatePack = "TemplatePack"; const char *const KindUndefined = "Undefined"; const char *const KindUnion = "Union"; +const char *const KindModule = "Module"; } // end anonymous namespace //===----------------------------------------------------------------------===// @@ -50,6 +51,8 @@ const char *LVScope::kind() const { const char *Kind = KindUndefined; if (getIsArray()) Kind = KindArray; + else if (getIsModule()) + Kind = KindModule; else if (getIsBlock()) Kind = KindBlock; else if (getIsCallSite()) @@ -101,7 +104,8 @@ LVScopeDispatch LVScope::Dispatch = { {LVScopeKind::IsTemplateAlias, &LVScope::getIsTemplateAlias}, {LVScopeKind::IsTemplatePack, &LVScope::getIsTemplatePack}, {LVScopeKind::IsTryBlock, &LVScope::getIsTryBlock}, - {LVScopeKind::IsUnion, &LVScope::getIsUnion}}; + {LVScopeKind::IsUnion, &LVScope::getIsUnion}, + {LVScopeKind::IsModule, &LVScope::getIsModule}}; void LVScope::addToChildren(LVElement *Element) { if (!Children) @@ -2107,3 +2111,15 @@ bool LVScopeTemplatePack::equals(const LVScope *Scope) const { void LVScopeTemplatePack::printExtra(raw_ostream &OS, bool Full) const { OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n"; } + +//===----------------------------------------------------------------------===// +// DWARF module (DW_TAG_module). +//===----------------------------------------------------------------------===// +bool LVScopeModule::equals(const LVScope *Scope) const { + // For lexical blocks, LVScope::equals() compares the parent scope. + return LVScope::equals(Scope) && (Scope->getName() == getName()); +} + +void LVScopeModule::printExtra(raw_ostream &OS, bool Full) const { + OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n"; +} diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp index 42da957233667..d2b9b1930f46d 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp @@ -233,6 +233,9 @@ LVElement *LVDWARFReader::createElement(dwarf::Tag Tag) { case dwarf::DW_TAG_GNU_template_parameter_pack: CurrentScope = createScopeTemplatePack(); return CurrentScope; + case dwarf::DW_TAG_module: + CurrentScope = createScopeModule(); + return CurrentScope; default: // Collect TAGs not implemented. if (options().getInternalTag() && Tag) diff --git a/llvm/tools/llvm-debuginfo-analyzer/Options.cpp b/llvm/tools/llvm-debuginfo-analyzer/Options.cpp index e5566b3390fd2..1ede9fa48c525 100644 --- a/llvm/tools/llvm-debuginfo-analyzer/Options.cpp +++ b/llvm/tools/llvm-debuginfo-analyzer/Options.cpp @@ -364,7 +364,8 @@ cl::list cmdline::SelectScopes( clEnumValN(LVScopeKind::IsTemplatePack, "TemplatePack", "Template pack."), clEnumValN(LVScopeKind::IsTryBlock, "TryBlock", "Exception try block."), - clEnumValN(LVScopeKind::IsUnion, "Union", "Union."))); + clEnumValN(LVScopeKind::IsUnion, "Union", "Union."), + clEnumValN(LVScopeKind::IsModule, "Module", "Module."))); // --select-symbols=[,,...] cl::list cmdline::SelectSymbols( diff --git a/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp index c062c15481da9..4b6a1f093e0da 100644 --- a/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp +++ b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp @@ -30,6 +30,7 @@ extern const char *TestMainArgv0; namespace { const char *DwarfClang = "test-dwarf-clang.o"; +const char *DwarfClangModule = "test-dwarf-clang-module.o"; const char *DwarfGcc = "test-dwarf-gcc.o"; // Helper function to get the first compile unit. @@ -124,6 +125,22 @@ void checkElementProperties(LVReader *Reader) { ASSERT_EQ(Lines->size(), 0x12u); } +// Check the basic properties on parsed DW_TAG_module. +void checkScopeModule(LVReader *Reader) { + LVScopeRoot *Root = Reader->getScopesRoot(); + LVScopeCompileUnit *CompileUnit = getFirstCompileUnit(Root); + + EXPECT_EQ(Root->getFileFormatName(), "Mach-O 64-bit x86-64"); + EXPECT_EQ(Root->getName(), DwarfClangModule); + + ASSERT_NE(CompileUnit->getChildren(), nullptr); + LVElement *FirstChild = *(CompileUnit->getChildren()->begin()); + EXPECT_EQ(FirstChild->getIsScope(), 1); + LVScopeModule *Module = static_cast(FirstChild); + EXPECT_EQ(Module->getIsModule(), 1); + EXPECT_EQ(Module->getName(), "DebugModule"); +} + // Check the logical elements selection. void checkElementSelection(LVReader *Reader) { LVScopeRoot *Root = Reader->getScopesRoot(); @@ -264,6 +281,9 @@ void elementProperties(SmallString<128> &InputsDir) { std::unique_ptr Reader = createReader(ReaderHandler, InputsDir, DwarfClang); checkElementProperties(Reader.get()); + + Reader = createReader(ReaderHandler, InputsDir, DwarfClangModule); + checkScopeModule(Reader.get()); } // Logical elements selection. diff --git a/llvm/unittests/DebugInfo/LogicalView/Inputs/test-dwarf-clang-module.o b/llvm/unittests/DebugInfo/LogicalView/Inputs/test-dwarf-clang-module.o new file mode 100644 index 0000000000000..0cded9bfb37d1 Binary files /dev/null and b/llvm/unittests/DebugInfo/LogicalView/Inputs/test-dwarf-clang-module.o differ