diff --git a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst index 60fa024db5e99..0ab249087ea9e 100644 --- a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst +++ b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst @@ -489,8 +489,8 @@ The given criteria describes the debug line state machine registers. =Discriminator: Line that has a discriminator. =EndSequence: Marks the end in the sequence of lines. =EpilogueBegin: Marks the start of a function epilogue. - =LineDebug: Lines that correspond to debug lines. =LineAssembler: Lines that correspond to disassembly text. + =LineDebug: Lines that correspond to debug lines. =NeverStepInto: marks a never step into. =NewStatement: Marks a new statement. =PrologueEnd: Marks the end of a function prologue. @@ -519,6 +519,7 @@ The following options allow printing of scopes that match the given . =InlinedFunction: An inlined function. =Label: A label. =LexicalBlock: A lexical block. + =Module: A module. =Namespace: A namespace. =Root: The element representing the main scope. =Structure: A structure. diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h index 17fa04040ad77..0e564bf2b0802 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h @@ -42,6 +42,7 @@ enum class LVSubclassID : unsigned char { LV_SCOPE_FUNCTION, LV_SCOPE_FUNCTION_INLINED, LV_SCOPE_FUNCTION_TYPE, + LV_SCOPE_MODULE, LV_SCOPE_NAMESPACE, LV_SCOPE_ROOT, LV_SCOPE_TEMPLATE_PACK, diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h index 9ce26398e48df..870b53f6774a8 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h @@ -104,6 +104,7 @@ class LVReader { LV_OBJECT_ALLOCATOR(ScopeFunction) LV_OBJECT_ALLOCATOR(ScopeFunctionInlined) LV_OBJECT_ALLOCATOR(ScopeFunctionType) + LV_OBJECT_ALLOCATOR(ScopeModule) LV_OBJECT_ALLOCATOR(ScopeNamespace) LV_OBJECT_ALLOCATOR(ScopeRoot) LV_OBJECT_ALLOCATOR(ScopeTemplatePack) @@ -210,6 +211,7 @@ class LVReader { LV_CREATE_OBJECT(ScopeFunction) LV_CREATE_OBJECT(ScopeFunctionInlined) LV_CREATE_OBJECT(ScopeFunctionType) + LV_CREATE_OBJECT(ScopeModule) LV_CREATE_OBJECT(ScopeNamespace) LV_CREATE_OBJECT(ScopeRoot) LV_CREATE_OBJECT(ScopeTemplatePack) diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h index 1b3c377cd7dbb..cbeb3944b9ec8 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h @@ -48,6 +48,7 @@ enum class LVScopeKind { IsLabel, IsLexicalBlock, IsMember, + IsModule, IsNamespace, IsRoot, IsStructure, @@ -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); @@ -748,6 +750,23 @@ class LVScopeFunctionType final : public LVScopeFunction { void resolveExtra() 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; +}; + // Class to represent a DWARF Namespace. class LVScopeNamespace final : public LVScope { LVScope *Reference = nullptr; // Reference to DW_AT_extension attribute. diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp index 594b6816f14c5..dc9a4ecee3e8b 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp @@ -34,6 +34,7 @@ const char *const KindEnumeration = "Enumeration"; const char *const KindFile = "File"; const char *const KindFunction = "Function"; const char *const KindInlinedFunction = "InlinedFunction"; +const char *const KindModule = "Module"; const char *const KindNamespace = "Namespace"; const char *const KindStruct = "Struct"; const char *const KindTemplateAlias = "TemplateAlias"; @@ -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()) @@ -94,6 +97,7 @@ LVScopeDispatch LVScope::Dispatch = { {LVScopeKind::IsInlinedFunction, &LVScope::getIsInlinedFunction}, {LVScopeKind::IsLabel, &LVScope::getIsLabel}, {LVScopeKind::IsLexicalBlock, &LVScope::getIsLexicalBlock}, + {LVScopeKind::IsModule, &LVScope::getIsModule}, {LVScopeKind::IsNamespace, &LVScope::getIsNamespace}, {LVScopeKind::IsRoot, &LVScope::getIsRoot}, {LVScopeKind::IsStructure, &LVScope::getIsStructure}, @@ -1962,6 +1966,18 @@ void LVScopeFunctionType::resolveExtra() { setName(Name); } +//===----------------------------------------------------------------------===// +// 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"; +} + //===----------------------------------------------------------------------===// // DWARF namespace (DW_TAG_namespace). //===----------------------------------------------------------------------===// diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp index 37bc60d4045c7..763e070e5d98f 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..99ed67ce5346f 100644 --- a/llvm/tools/llvm-debuginfo-analyzer/Options.cpp +++ b/llvm/tools/llvm-debuginfo-analyzer/Options.cpp @@ -354,6 +354,7 @@ cl::list cmdline::SelectScopes( clEnumValN(LVScopeKind::IsLabel, "Label", "Label."), clEnumValN(LVScopeKind::IsLexicalBlock, "LexicalBlock", "Lexical block."), + clEnumValN(LVScopeKind::IsModule, "Module", "Module."), clEnumValN(LVScopeKind::IsNamespace, "Namespace", "Namespace."), clEnumValN(LVScopeKind::IsRoot, "Root", "Root."), clEnumValN(LVScopeKind::IsStructure, "Structure", "Structure."), diff --git a/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp index 03bf394631c99..0d3a5d8959679 100644 --- a/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp +++ b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp @@ -33,6 +33,7 @@ const char *DwarfClang = "test-dwarf-clang.o"; // Two compile units: one declares `extern int foo_printf(const char *, ...);` // and another one that defines the function. const char *DwarfClangUnspecParams = "test-dwarf-clang-unspec-params.elf"; +const char *DwarfClangModule = "test-dwarf-clang-module.o"; const char *DwarfGcc = "test-dwarf-gcc.o"; // Helper function to get the first compile unit. @@ -157,6 +158,22 @@ void checkUnspecifiedParameters(LVReader *Reader) { true); } +// 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(); @@ -301,6 +318,9 @@ void elementProperties(SmallString<128> &InputsDir) { Reader = createReader(ReaderHandler, InputsDir, DwarfClangUnspecParams); checkUnspecifiedParameters(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