[llvm] c28a977 - Recommit [llvm-debuginfo-analyzer] (02/09) - Driver and documentation

Carlos Alberto Enciso via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 18 00:42:55 PDT 2022


Author: Carlos Alberto Enciso
Date: 2022-10-18T08:39:26+01:00
New Revision: c28a977b87defd2f37fd0808d7ba6173133744ce

URL: https://github.com/llvm/llvm-project/commit/c28a977b87defd2f37fd0808d7ba6173133744ce
DIFF: https://github.com/llvm/llvm-project/commit/c28a977b87defd2f37fd0808d7ba6173133744ce.diff

LOG: Recommit [llvm-debuginfo-analyzer] (02/09) - Driver and documentation

Originally committed in fe7a3cedf77125a6309150d85cecbc20b1a31775

Reverted in 26dd64ba9cfabe5474bb207f3b7099965f81fed7

Buildbot failures:
https://lab.llvm.org/buildbot#builders/139/builds/29663
- unittest trigger an invalid assertion.

https://lab.llvm.org/buildbot#builders/196/builds/19665
- 'has virtual functions but non-virtual destructor' warning as error.

Recommitted with fix:
- Removed the assertion.
- Added virtual destructor.

Added: 
    llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVOptions.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVSort.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h
    llvm/lib/DebugInfo/LogicalView/CMakeLists.txt
    llvm/lib/DebugInfo/LogicalView/Core/LVOptions.cpp
    llvm/lib/DebugInfo/LogicalView/LLVMBuild.txt
    llvm/test/tools/llvm-debuginfo-analyzer/cmdline.test
    llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt
    llvm/tools/llvm-debuginfo-analyzer/LLVMBuild.txt
    llvm/tools/llvm-debuginfo-analyzer/Options.cpp
    llvm/tools/llvm-debuginfo-analyzer/Options.h
    llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp
    llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt
    llvm/unittests/DebugInfo/LogicalView/CommandLineOptionsTest.cpp
    llvm/unittests/DebugInfo/LogicalView/StringPoolTest.cpp

Modified: 
    llvm/docs/CommandGuide/index.rst
    llvm/lib/DebugInfo/CMakeLists.txt
    llvm/test/CMakeLists.txt
    llvm/test/lit.cfg.py
    llvm/unittests/DebugInfo/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/docs/CommandGuide/index.rst b/llvm/docs/CommandGuide/index.rst
index fc87f15c9d588..3b8375cb7e868 100644
--- a/llvm/docs/CommandGuide/index.rst
+++ b/llvm/docs/CommandGuide/index.rst
@@ -21,6 +21,7 @@ Basic Commands
    llvm-config
    llvm-cov
    llvm-cxxmap
+   llvm-debuginfo-analyzer
    llvm-
diff 
    llvm-dis
    llvm-dwarfdump

diff  --git a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst
new file mode 100644
index 0000000000000..a78066a5eea37
--- /dev/null
+++ b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst
@@ -0,0 +1,1962 @@
+llvm-debuginfo-analyzer - Print a logical representation of low-level debug information.
+========================================================================================
+
+.. program:: llvm-debuginfo-analyzer
+
+.. contents::
+   :local:
+
+SYNOPSIS
+--------
+:program:`llvm-debuginfo-analyzer` [*options*] [*filename ...*]
+
+DESCRIPTION
+-----------
+:program:`llvm-debuginfo-analyzer` parses debug and text sections in
+binary object files and prints their contents in a logical view, which
+is a human readable representation that closely matches the structure
+of the original user source code. Supported object file formats include
+ELF, Mach-O, PDB and COFF.
+
+The **logical view** abstracts the complexity associated with the
+
diff erent low-level representations of the debugging information that
+is embedded in the object file. :program:`llvm-debuginfo-analyzer`
+produces a canonical view of the debug information regardless of how it
+is formatted. The same logical view will be seen regardless of object
+file format, assuming the debug information correctly represents the
+same original source code.
+
+The logical view includes the following **logical elements**: *type*,
+*scope*, *symbol* and *line*, which are the basic software elements used
+in the C/C++ programming language. Each logical element has a set of
+**attributes**, such as *types*, *classes*, *functions*, *variables*,
+*parameters*, etc. The :option:`--attribute` can be used to specify which
+attributes to include when printing a logical element. A logical element
+may have a **kind** that describes specific types of elements. For
+instance, a *scope* could have a kind value of *function*, *class*,
+*namespace*.
+
+:program:`llvm-debuginfo-analyzer` defaults to print a pre-defined
+layout of logical elements and attributes. The command line options can
+be used to control the printed elements (:option:`--print`), using a
+specific layout (:option:`--report`), matching a given pattern
+(:option:`--select`, :option:`--select-offsets`). Also, the output can
+be limited to specified logical elements using (:option:`--select-lines`,
+:option:`--select-scopes`, :option:`--select-symbols`,
+:option:`--select-types`).
+
+:program:`llvm-debuginfo-analyzer` can also compare a set of logical
+views (:option:`--compare`), to find 
diff erences and identify possible
+debug information syntax issues (:option:`--warning`) in any object file.
+
+OPTIONS
+-------
+:program:`llvm-debuginfo-analyzer` options are separated into several
+categories, each tailored to a 
diff erent purpose:
+
+  * :ref:`general_` - Standard LLVM options to display help, version, etc.
+  * :ref:`attributes_` - Describe how to include 
diff erent details when
+    printing an element.
+  * :ref:`print_` - Specify which elements will be included when printing
+    the view.
+  * :ref:`output_` - Describe the supported formats when printing the view.
+  * :ref:`report_` - Describe the format layouts for view printing.
+  * :ref:`select_` - Allows to use specific criteria or conditions to
+    select which elements to print.
+  * :ref:`compare_` - Compare logical views and print missing and/or
+    added elements.
+  * :ref:`warning_` - Print the warnings detected during the creation
+    of the view.
+  * :ref:`internal_` - Internal analysis of the logical view.
+
+.. _general_:
+
+GENERAL
+~~~~~~~
+This section describes the standard help options, used to display the
+usage, version, response files, etc.
+
+.. option:: -h, --help
+
+ Show help and usage for this command. (--help-hidden for more).
+
+.. option:: --help-list
+
+ Show help and usage for this command without grouping the options
+ into categories (--help-list-hidden for more).
+
+.. option:: --help-hidden
+
+ Display all available options.
+
+.. option:: --print-all-options
+
+ Print all option values after command line parsing.
+
+.. option:: --print-options
+
+ Print non-default options after command line parsing
+
+.. option:: --version
+
+ Display the version of the tool.
+
+.. option:: @<FILE>
+
+ Read command-line options from `<FILE>`.
+
+If no input file is specified, :program:`llvm-debuginfo-analyzer`
+defaults to read `a.out` and return an error when no input file is found.
+
+If `-` is used as the input file, :program:`llvm-debuginfo-analyzer`
+reads the input from its standard input stream.
+
+.. _attributes_:
+
+ATTRIBUTES
+~~~~~~~~~~
+The following options enable attributes given for the printed elements.
+The attributes are divided in categories based on the type of data being
+added, such as: internal offsets in the binary file, location descriptors,
+register names, user source filenames, additional element transformations,
+toolchain name, binary file format, etc.
+
+.. option:: --attribute=<value[,value,...]>
+
+ With **value** being one of the options in the following lists.
+
+ .. code-block:: text
+
+   =all: Include all the below attributes.
+   =extended: Add low-level attributes.
+   =standard: Add standard high-level attributes.
+
+ The following attributes describe the most common information for a
+ logical element. They help to identify the lexical scope level; the
+ element visibility across modules (global, local); the toolchain name
+ that produced the binary file.
+
+ .. code-block:: text
+
+   =global: Element referenced across Compile Units.
+   =format: Object file format name.
+   =level: Lexical scope level (File=0, Compile Unit=1).
+   =local: Element referenced only in the Compile Unit.
+   =producer: Toolchain identification name.
+
+ The following attributes describe files and directory names from the
+ user source code, where the elements are declared or defined; functions
+ with public visibility across modules. These options allow to map the
+ elements to their user code location, for cross references purposes.
+
+ .. code-block:: text
+
+   =directories: Directories referenced in the debug information.
+   =filename: Filename where the element is defined.
+   =files: Files referenced in the debug information.
+   =pathname: Pathname where the object is defined.
+   =publics: Function names that are public.
+
+ The following attributes describe additional logical element source
+ transformations, in order to display built-in types (int, bool, etc.);
+ parameters and arguments used during template instantiation; parent
+ name hierarchy; array dimensions information; compiler generated
+ elements and the underlying types associated with the types aliases.
+
+ .. code-block:: text
+
+   =argument: Template parameters replaced by its arguments.
+   =base: Base types (int, bool, etc.).
+   =generated: Compiler generated elements.
+   =encoded: Template arguments encoded in the template name.
+   =qualified: The element type include parents in its name.
+   =reference: Element declaration and definition references.
+   =subrange: Subrange encoding information for arrays.
+   =typename: Template parameters.
+   =underlying: Underlying type for type definitions.
+
+ The following attributes describe the debug location information for
+ a symbol or scope. It includes the symbol percentage coverage and any
+ gaps within the location layout; ranges determining the code sections
+ attached to a function. When descriptors are used, the target processor
+ registers are displayed.
+
+ .. code-block:: text
+
+   =coverage: Symbol location coverage.
+   =gaps: Missing debug location (gaps).
+   =location: Symbol debug location.
+   =range: Debug location ranges.
+   =register: Processor register names.
+
+ The following attributes are associated with low level details, such
+ as: offsets in the binary file; discriminators added to the lines of
+ inlined functions in order to distinguish specific instances; debug
+ lines state machine registers; elements discarded by the compiler
+ (inlining) or by the linker optimizations (dead-stripping); system
+ compile units generated by the MS toolchain in PDBs.
+
+ .. code-block:: text
+
+   =discarded: Discarded elements by the linker.
+   =discriminator: Discriminators for inlined function instances.
+   =inserted: Generated inlined abstract references.
+   =linkage: Object file linkage name.
+   =offset: Debug information offset.
+   =qualifier: Line qualifiers (Newstatement, BasicBlock, etc).
+   =zero: Zero line numbers.
+
+ The following attribute described specific information for the **PE/COFF**
+ file format. It includes MS runtime types.
+
+ .. code-block:: text
+
+   =system: Display PDB's MS system elements.
+
+ The above attributes are grouped into *standard* and *extended*
+ categories that can be enabled.
+
+ The *standard* group, contains those attributes that add sufficient
+ information to describe a logical element and that can cover the
+ normal situations while dealing with debug information.
+
+ .. code-block:: text
+
+   =base
+   =coverage
+   =directories
+   =discriminator
+   =filename
+   =files
+   =format
+   =level
+   =producer
+   =publics
+   =range
+   =reference
+   =zero
+
+ The *extended* group, contains those attributes that require a more
+ extended knowledge about debug information. They are intended when a
+ lower level of detail is required.
+
+ .. code-block:: text
+
+   =argument
+   =discarded
+   =encoded
+   =gaps
+   =generated
+   =global
+   =inserted
+   =linkage
+   =local
+   =location
+   =offset
+   =operation
+   =pathname
+   =qualified
+   =qualifier
+   =register
+   =subrange
+   =system
+   =typename
+
+.. _print_:
+
+PRINT
+~~~~~
+The following options describe the elements to print. The layout used
+is determined by the :option:`--report`. In the tree layout, all the
+elements have their enclosing lexical scopes printed, even when not
+explicitly specified.
+
+.. option:: --print=<value[,value,...]>
+
+ With **value** being one of the options in the following lists.
+
+ .. code-block:: text
+
+   =all: Include all the below attributes.
+
+ The following options print the requested elements; in the case of any
+ given select conditions (:option:`--select`), only those elements that
+ match them, will be printed. The **elements** value is a convenient
+ way to specify instructions, lines, scopes, symbols and types all at
+ once.
+
+ .. code-block:: text
+
+   =elements: Instructions, lines, scopes, symbols and types.
+   =instructions: Assembler instructions for code sections.
+   =lines: Source lines referenced in the debug information.
+   =scopes: Lexical blocks (function, class, namespace, etc).
+   =symbols: Symbols (variable, member, parameter, etc).
+   =types: Types (pointer, reference, type alias, etc).
+
+ The following options print information, collected during the creation
+ of the elements, such as: scope contributions to the debug information;
+ summary of elements created, printed or matched (:option:`--select`);
+ warnings produced during the view creation.
+
+ .. code-block:: text
+
+   =sizes: Debug Information scopes contributions.
+   =summary: Summary of elements allocated, selected or printed.
+   =warnings: Warnings detected.
+
+ Note: The **--print=sizes** option is ELF specific.
+
+.. _output_:
+
+OUTPUT
+~~~~~~
+The following options describe how to control the output generated when
+printing the logical elements.
+
+.. option:: --output-file=<path>
+
+ Redirect the output to a file specified by <path>, where - is the
+ standard output stream.
+
+:program:`llvm-debuginfo-analyzer` has the concept of **split view**.
+When redirecting the output from a complex binary format, it is
+**divided** into individual files, each one containing the logical view
+output for a single compilation unit.
+
+.. option:: --output-folder=<name>
+
+ The folder to write a file per compilation unit when **--output=split**
+ is specified.
+
+.. option:: --output-level=<level>
+
+ Only print elements up to the given **lexical level** value. The input
+ file is at lexical level zero and a compilation unit is at lexical level
+ one.
+
+.. option:: --output=<value[,value,...]>
+
+ With **value** being one of the options in the following lists.
+
+ .. code-block:: text
+
+   =all: Include all the below outputs.
+
+ .. code-block:: text
+
+   =json: Use JSON as the output format (Not implemented).
+   =split: Split the output by Compile Units.
+   =text: Use a free form text output.
+
+.. option:: --output-sort=<key>
+
+ Primary key when ordering the elements in the output (default: line).
+ Sorting by logical element kind, requires be familiarity with the
+ element kind selection options (:option:`--select-lines`,
+ :option:`--select-scopes`, :option:`--select-symbols`,
+ :option:`--select-types`), as those options describe the 
diff erent
+ logical element kinds.
+
+ .. code-block:: text
+
+   =kind: Sort by element kind.
+   =line: Sort by element line number.
+   =name: Sort by element name.
+   =offset: Sort by element offset.
+
+.. _report_:
+
+REPORT
+~~~~~~
+Depending on the task being executed (print, compare, select), several
+layouts are supported to display the elements in a more suitable way,
+to make the output easier to understand.
+
+.. option:: --report=<value[,value,...]>
+
+ With **value** being one of the options in the following list.
+
+ .. code-block:: text
+
+   =all: Include all the below reports.
+
+ .. code-block:: text
+
+   =children: Elements and children are displayed in a tree format.
+   =list: Elements are displayed in a tabular format.
+   =parents: Elements and parents are displayed in a tree format.
+   =view: Elements, parents and children are displayed in a tree format.
+
+The **list** layout presents the logical elements in a tabular form
+without any parent-child relationship. This may be the preferred way to
+display elements that match specific conditions when comparing logical
+views, making it easier to find 
diff erences.
+
+The **children**, **parents** and **view** layout displays the elements
+in a tree format, with the scopes representing their nodes, and types,
+symbols, lines and other scopes representing the children. The layout
+shows the lexical scoping relationship between elements, with the binary
+file being the tree root (level 0) and each compilation unit being a
+child (level 1).
+
+The **children** layout includes the elements that match any given
+criteria (:option:`--select`) or (:option:`--compare`) and its children.
+
+The **parents** layout includes the elements that match any given
+criteria (:option:`--select`) or (:option:`--compare`) and its parents.
+
+The combined **view** layout includes the elements that match any given
+criteria (:option:`--select`) or (:option:`--compare`), its parents
+and children.
+
+**Notes**:
+
+1. When a selection criteria (:option:`--select`) is specified with no
+   report option, the **list** layout is selected.
+2. The comparison mode always uses the **view** layout.
+
+.. _select_:
+
+SELECTION
+~~~~~~~~~
+When printing an element, 
diff erent data can be included and it varies
+(:option:`--attribute`) from data directly associated with the binary
+file (offset) to high level details such as coverage, lexical scope
+level, location. As the printed output can reach a considerable size,
+several selection options, enable printing of specific elements.
+
+The pattern matching can ignore the case (:option:`--select-nocase`)
+and be extended to use regular expressions (:option:`--select-regex`).
+
+ELEMENTS
+^^^^^^^^
+The following options allow printing of elements that match the given
+<pattern>, offset <value> or an element <condition>.
+
+.. option:: --select=<pattern>
+
+ Print all elements whose name or line number matches the given <pattern>.
+
+.. option:: --select-offsets=<value[,value,...]>
+
+ Print all elements whose offset matches the given values. See
+ :option:`--attribute` option.
+
+.. option:: --select-elements=<condition[,condition,...]>
+
+ Print all elements that satisfy the given <condition>. With **condition**
+ being one of the options in the following list.
+
+ .. code-block:: text
+
+   =discarded: Discarded elements by the linker.
+   =global: Element referenced across Compile Units.
+   =optimized: Optimized inlined abstract references.
+
+.. option:: --select-nocase
+
+ Pattern matching is case-insensitive when using :option:`--select`.
+
+.. option:: --select-regex
+
+ Treat any <pattern> strings as regular expressions when selecting with
+ :option:`--select` option. If :option:`--select-nocase` is specified,
+ the regular expression becomes case-insensitive.
+
+If the <pattern> criteria is too general, a more selective option can
+be specified to target a particular category of elements:
+lines (:option:`--select-lines`), scopes (:option:`--select-scopes`),
+symbols (:option:`--select-symbols`) and types (:option:`--select-types`).
+These options require knowledge of the debug information format (DWARF,
+CodeView, COFF), as the given **kind** describes a very specific type
+of element.
+
+LINES
+^^^^^
+The following options allow printing of lines that match the given <kind>.
+The given criteria describes the debug line state machine registers.
+
+.. option:: --select-lines=<kind[,kind,...]>
+
+ With **kind** being one of the options in the following list.
+
+ .. code-block:: text
+
+   =AlwaysStepInto: marks an always step into.
+   =BasicBlock: Marks a new basic block.
+   =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.
+   =NeverStepInto: marks a never step into.
+   =NewStatement: Marks a new statement.
+   =PrologueEnd: Marks the end of a function prologue.
+
+SCOPES
+^^^^^^
+The following options allow printing of scopes that match the given <kind>.
+
+.. option:: --select-scopes=<kind[,kind,...]>
+
+ With **kind** being one of the options in the following list.
+
+ .. code-block:: text
+
+    =Aggregate: A class, structure or union.
+    =Array: An array.
+    =Block: A generic block (lexical block or exception block).
+    =CallSite: A call site.
+    =CatchBlock: An exception block.
+    =Class: A class.
+    =CompileUnit: A compile unit.
+    =EntryPoint: A subroutine entry point.
+    =Enumeration: An enumeration.
+    =Function: A function.
+    =FunctionType: A function pointer.
+    =InlinedFunction: An inlined function.
+    =Label: A label.
+    =LexicalBlock: A lexical block.
+    =Namespace: A namespace.
+    =Root: The element representing the main scope.
+    =Structure: A structure.
+    =Subprogram: A subprogram.
+    =Template: A template definition.
+    =TemplateAlias: A template alias.
+    =TemplatePack: A template pack.
+    =TryBlock: An exception try block.
+    =Union: A union.
+
+SYMBOLS
+^^^^^^^
+The following options allow printing of symbols that match the given <kind>.
+
+.. option:: --select-symbols=<kind[,kind,...]>
+
+ With **kind** being one of the options in the following list.
+
+ .. code-block:: text
+
+    =CallSiteParameter: A call site parameter.
+    =Constant: A constant symbol.
+    =Inheritance: A base class.
+    =Member: A member class.
+    =Parameter: A parameter to function.
+    =Unspecified: Unspecified parameters to function.
+    =Variable: A variable.
+
+TYPES
+^^^^^
+The following options allow printing of types that match the given <kind>.
+
+.. option:: --select-types=<kind[,kind,...]>
+
+ With **kind** being one of the options in the following list.
+
+ .. code-block:: text
+
+    =Base: Base type (integer, boolean, etc).
+    =Const: Constant specifier.
+    =Enumerator: Enumerator.
+    =Import: Import declaration.
+    =ImportDeclaration: Import declaration.
+    =ImportModule: Import module.
+    =Pointer: Pointer type.
+    =PointerMember: Pointer to member function.
+    =Reference: Reference type.
+    =Restrict: Restrict specifier.
+    =RvalueReference: R-value reference.
+    =Subrange: Array subrange.
+    =TemplateParam: Template parameter.
+    =TemplateTemplateParam: Template template parameter.
+    =TemplateTypeParam: Template type parameter.
+    =TemplateValueParam: Template value parameter.
+    =Typedef: Type definition.
+    =Unspecified: Unspecified type.
+    =Volatile: Volatile specifier.
+
+.. _compare_:
+
+COMPARE
+~~~~~~~
+When dealing with debug information, there are situations when the
+printing of the elements is not the correct approach. That is the case,
+when we are interested in the effects caused by 
diff erent versions of
+the same toolchain, or the impact of specific compiler optimizations.
+
+For those cases, we are looking to see which elements have been added
+or removed. Due to the complicated debug information format, it is very
+
diff icult to use a regular 
diff  tool to find those elements; even
+impossible when dealing with 
diff erent debug formats.
+
+:program:`llvm-debuginfo-analyzer` supports a logical element comparison,
+allowing to find semantic 
diff erences between logical views, produced by
+
diff erent toolchain versions or even debug information formats.
+
+When comparing logical views created from 
diff erent debug formats, its
+accuracy depends on how close the debug information represents the
+user code. For instance, a logical view created from a binary file with
+DWARF debug information may include more detailed data than a logical
+view created from a binary file with CodeView/COFF debug information.
+
+The following options describe the elements to compare.
+
+.. option:: --compare=<value[,value,...]>
+
+ With **value** being one of the options in the following list.
+
+ .. code-block:: text
+
+    =all: Include all the below elements.
+
+ .. code-block:: text
+
+    =lines: Include lines.
+    =scopes: Include scopes.
+    =symbols: Include symbols.
+    =types: Include types.
+
+:program:`llvm-debuginfo-analyzer` takes the first binary file on the
+command line as the **reference** and the second one as the **target**.
+To get a more descriptive report, the comparison is done twice. The
+reference and target views are swapped, in order to produce those
+**missing** elements from the target view and those **added** elements
+to the reference view.
+
+See :option:`--report` options on how to describe the comparison
+reports.
+
+.. _warning_:
+
+WARNING
+~~~~~~~
+When reading the input object files, :program:`llvm-debuginfo-analyzer`
+can detect issues in the raw debug information. These may not be
+considered fatal to the purpose of printing a logical view but they can
+give an indication about the quality and potentially expose issues with
+the generated debug information.
+
+The following options describe the warnings to be recorded for later
+printing, if they are requested by :option:`--print`.
+
+.. option:: --warning=<value[,value,...]>
+
+ With **value** being one of the options in the following list.
+
+ .. code-block:: text
+
+    =all: Include all the below warnings.
+
+ The following options collect additional information during the creation
+ of the logical view, to include invalid coverage values and locations
+ for symbols; invalid code ranges; lines that are zero.
+
+ .. code-block:: text
+
+    =coverages: Invalid symbol coverages values.
+    =lines: Debug lines that are zero.
+    =locations: Invalid symbol locations.
+    =ranges: Invalid code ranges.
+
+.. _internal_:
+
+INTERNAL
+~~~~~~~~
+ For a better understanding of the logical view, access to more detailed
+ internal information could be needed. Such data would help to identify
+ debug information processed or incorrect logical element management.
+ Typically these kind of options are available only in *debug* builds.
+
+ :program:`llvm-debuginfo-analyzer` supports these advanced options in
+ both *release* and *debug* builds, with the exception of the unique ID
+ that is generated only in *debug* builds.
+
+.. option:: --internal=<value[,value,...]>
+
+ With **value** being one of the options in the following list.
+
+ .. code-block:: text
+
+    =all: Include all the below options.
+
+ The following options allow to check the integrity of the logical view;
+ collect the debug tags that are processed or not implemented; ignore the
+ logical element line number, to facilitate the logical view comparison
+ when using external comparison tools; print the command line options
+ used to invoke :program:`llvm-debuginfo-analyzer`.
+
+ .. code-block:: text
+
+    =id: Print unique element ID.
+    =cmdline: Print command line.
+    =integrity: Check elements integrity.
+    =none: Ignore element line number.
+    =tag: Debug information tags.
+
+ **Note:** For ELF format, the collected tags represent the debug tags
+ that are not processed. For PE/COFF format, they represent the tags
+ that are processed.
+
+EXAMPLES
+--------
+This section includes some real binary files to show how to use
+:program:`llvm-debuginfo-analyzer` to print a logical view and to
+diagnose possible debug information issues.
+
+TEST CASE 1 - GENERAL OPTIONS
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The below example is used to show 
diff erent output generated by
+:program:`llvm-debuginfo-analyzer`. We compiled the example for an X86
+ELF target with Clang (-O0 -g):
+
+.. code-block:: c++
+
+  1  using INTPTR = const int *;
+  2  int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
+  3    if (ParamBool) {
+  4      typedef int INTEGER;
+  5      const INTEGER CONSTANT = 7;
+  6      return CONSTANT;
+  7    }
+  8    return ParamUnsigned;
+  9  }
+
+PRINTING MODE
+^^^^^^^^^^^^^
+In this mode :program:`llvm-debuginfo-analyzer` prints the *logical view*
+or portions of it, based on criteria patterns (including regular
+expressions) to select the kind of *logical elements* to be included in
+the output.
+
+BASIC DETAILS
+"""""""""""""
+The following command prints basic details for all the logical elements
+sorted by the debug information internal offset; it includes its lexical
+level and debug info format.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level,format
+                          --output-sort=offset
+                          --print=scopes,symbols,types,lines,instructions
+                          test-dwarf-clang.o
+
+or
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level,format
+                          --output-sort=offset
+                          --print=elements
+                          test-dwarf-clang.o
+
+Each row represents an element that is present within the debug
+information. The first column represents the scope level, followed by
+the associated line number (if any), and finally the description of
+the element.
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'test-dwarf-clang.o' -> elf64-x86-64
+
+  [001]             {CompileUnit} 'test.cpp'
+  [002]     2         {Function} extern not_inlined 'foo' -> 'int'
+  [003]     2           {Parameter} 'ParamPtr' -> 'INTPTR'
+  [003]     2           {Parameter} 'ParamUnsigned' -> 'unsigned int'
+  [003]     2           {Parameter} 'ParamBool' -> 'bool'
+  [003]                 {Block}
+  [004]     5             {Variable} 'CONSTANT' -> 'const INTEGER'
+  [004]     5             {Line}
+  [004]                   {Code} 'movl	$0x7, -0x1c(%rbp)'
+  [004]     6             {Line}
+  [004]                   {Code} 'movl	$0x7, -0x4(%rbp)'
+  [004]                   {Code} 'jmp	0x6'
+  [004]     8             {Line}
+  [004]                   {Code} 'movl	-0x14(%rbp), %eax'
+  [003]     4           {TypeAlias} 'INTEGER' -> 'int'
+  [003]     2           {Line}
+  [003]                 {Code} 'pushq	%rbp'
+  [003]                 {Code} 'movq	%rsp, %rbp'
+  [003]                 {Code} 'movb	%dl, %al'
+  [003]                 {Code} 'movq	%rdi, -0x10(%rbp)'
+  [003]                 {Code} 'movl	%esi, -0x14(%rbp)'
+  [003]                 {Code} 'andb	$0x1, %al'
+  [003]                 {Code} 'movb	%al, -0x15(%rbp)'
+  [003]     3           {Line}
+  [003]                 {Code} 'testb	$0x1, -0x15(%rbp)'
+  [003]                 {Code} 'je	0x13'
+  [003]     8           {Line}
+  [003]                 {Code} 'movl	%eax, -0x4(%rbp)'
+  [003]     9           {Line}
+  [003]                 {Code} 'movl	-0x4(%rbp), %eax'
+  [003]                 {Code} 'popq	%rbp'
+  [003]                 {Code} 'retq'
+  [003]     9           {Line}
+  [002]     1         {TypeAlias} 'INTPTR' -> '* const int'
+
+On closer inspection, we can see what could be a potential debug issue:
+
+.. code-block:: none
+
+  [003]                 {Block}
+  [003]     4           {TypeAlias} 'INTEGER' -> 'int'
+
+The **'INTEGER'** definition is at level **[003]**, the same lexical
+scope as the anonymous **{Block}** ('true' branch for the 'if' statement)
+whereas in the original source code the typedef statement is clearly
+inside that block, so the **'INTEGER'** definition should also be at
+level **[004]** inside the block.
+
+SELECT LOGICAL ELEMENTS
+"""""""""""""""""""""""
+The following prints all *instructions*, *symbols* and *types* that
+contain **'inte'** or **'movl'** in their names or types, using a tab
+layout and given the number of matches.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level
+                          --select-nocase --select-regex
+                          --select=INTe --select=movl
+                          --report=list
+                          --print=symbols,types,instructions,summary
+                          test-dwarf-clang.o
+
+  Logical View:
+  [000]           {File} 'test-dwarf-clang.o'
+
+  [001]           {CompileUnit} 'test.cpp'
+  [003]           {Code} 'movl	$0x7, -0x1c(%rbp)'
+  [003]           {Code} 'movl	$0x7, -0x4(%rbp)'
+  [003]           {Code} 'movl	%eax, -0x4(%rbp)'
+  [003]           {Code} 'movl	%esi, -0x14(%rbp)'
+  [003]           {Code} 'movl	-0x14(%rbp), %eax'
+  [003]           {Code} 'movl	-0x4(%rbp), %eax'
+  [003]     4     {TypeAlias} 'INTEGER' -> 'int'
+  [004]     5     {Variable} 'CONSTANT' -> 'const INTEGER'
+
+  -----------------------------
+  Element      Total      Found
+  -----------------------------
+  Scopes           3          0
+  Symbols          4          1
+  Types            2          1
+  Lines           17          6
+  -----------------------------
+  Total           26          8
+
+COMPARISON MODE
+^^^^^^^^^^^^^^^
+In this mode :program:`llvm-debuginfo-analyzer` compares logical views
+to produce a report with the logical elements that are missing or added.
+This a very powerful aid in finding semantic 
diff erences in the debug
+information produced by 
diff erent toolchain versions or even completely
+
diff erent toolchains altogether (For example a compiler producing DWARF
+can be directly compared against a completely 
diff erent compiler that
+produces CodeView).
+
+Given the previous example we found the above debug information issue
+(related to the previous invalid scope location for the **'typedef int
+INTEGER'**) by comparing against another compiler.
+
+Using GCC to generate test-dwarf-gcc.o, we can apply a selection pattern
+with the printing mode to obtain the following logical view output.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level
+                          --select-regex --select-nocase --select=INTe
+                          --report=list
+                          --print=symbols,types
+                          test-dwarf-clang.o test-dwarf-gcc.o
+
+  Logical View:
+  [000]           {File} 'test-dwarf-clang.o'
+
+  [001]           {CompileUnit} 'test.cpp'
+  [003]     4     {TypeAlias} 'INTEGER' -> 'int'
+  [004]     5     {Variable} 'CONSTANT' -> 'const INTEGER'
+
+  Logical View:
+  [000]           {File} 'test-dwarf-gcc.o'
+
+  [001]           {CompileUnit} 'test.cpp'
+  [004]     4     {TypeAlias} 'INTEGER' -> 'int'
+  [004]     5     {Variable} 'CONSTANT' -> 'const INTEGER'
+
+The output shows that both objects contain the same elements. But the
+**'typedef INTEGER'** is located at 
diff erent scope level. The GCC
+generated object, shows **'4'**, which is the correct value.
+
+Note that there is no requirement that GCC must produce identical or
+similar DWARF to Clang to allow the comparison. We're only comparing
+the semantics. The same case when comparing CodeView debug information
+generated by MSVC and Clang.
+
+There are 2 comparison methods: logical view and logical elements.
+
+LOGICAL VIEW
+""""""""""""
+It compares the logical view as a whole unit; for a match, each compared
+logical element must have the same parents and children.
+
+Using the :program:`llvm-debuginfo-analyzer` comparison functionality,
+that issue can be seen in a more global context, that can include the
+logical view.
+
+The output shows in view form the **missing (-), added (+)** elements,
+giving more context by swapping the reference and target object files.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level
+                          --compare=types
+                          --report=view
+                          --print=symbols,types
+                          test-dwarf-clang.o test-dwarf-gcc.o
+
+  Reference: 'test-dwarf-clang.o'
+  Target:    'test-dwarf-gcc.o'
+
+  Logical View:
+   [000]           {File} 'test-dwarf-clang.o'
+
+   [001]             {CompileUnit} 'test.cpp'
+   [002]     1         {TypeAlias} 'INTPTR' -> '* const int'
+   [002]     2         {Function} extern not_inlined 'foo' -> 'int'
+   [003]                 {Block}
+   [004]     5             {Variable} 'CONSTANT' -> 'const INTEGER'
+  +[004]     4             {TypeAlias} 'INTEGER' -> 'int'
+   [003]     2           {Parameter} 'ParamBool' -> 'bool'
+   [003]     2           {Parameter} 'ParamPtr' -> 'INTPTR'
+   [003]     2           {Parameter} 'ParamUnsigned' -> 'unsigned int'
+  -[003]     4           {TypeAlias} 'INTEGER' -> 'int'
+
+The output shows the merging view path (reference and target) with the
+missing and added elements.
+
+LOGICAL ELEMENTS
+""""""""""""""""
+It compares individual logical elements without considering if their
+parents are the same. For both comparison methods, the equal criteria
+includes the name, source code location, type, lexical scope level.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level
+                          --compare=types
+                          --report=list
+                          --print=symbols,types,summary
+                          test-dwarf-clang.o test-dwarf-gcc.o
+
+  Reference: 'test-dwarf-clang.o'
+  Target:    'test-dwarf-gcc.o'
+
+  (1) Missing Types:
+  -[003]     4     {TypeAlias} 'INTEGER' -> 'int'
+
+  (1) Added Types:
+  +[004]     4     {TypeAlias} 'INTEGER' -> 'int'
+
+  ----------------------------------------
+  Element   Expected    Missing      Added
+  ----------------------------------------
+  Scopes           4          0          0
+  Symbols          0          0          0
+  Types            2          1          1
+  Lines            0          0          0
+  ----------------------------------------
+  Total            6          1          1
+
+Changing the *Reference* and *Target* order:
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level
+                          --compare=types
+                          --report=list
+                          --print=symbols,types,summary
+                          test-dwarf-gcc.o test-dwarf-clang.o
+
+  Reference: 'test-dwarf-gcc.o'
+  Target:    'test-dwarf-clang.o'
+
+  (1) Missing Types:
+  -[004]     4     {TypeAlias} 'INTEGER' -> 'int'
+
+  (1) Added Types:
+  +[003]     4     {TypeAlias} 'INTEGER' -> 'int'
+
+  ----------------------------------------
+  Element   Expected    Missing      Added
+  ----------------------------------------
+  Scopes           4          0          0
+  Symbols          0          0          0
+  Types            2          1          1
+  Lines            0          0          0
+  ----------------------------------------
+  Total            6          1          1
+
+As the *Reference* and *Target* are switched, the *Added Types* from
+the first case now are listed as *Missing Types*.
+
+TEST CASE 2 - ASSEMBLER INSTRUCTIONS
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The below example is used to show 
diff erent output generated by
+:program:`llvm-debuginfo-analyzer`. We compiled the example for an X86
+Codeview and ELF targets with recent versions of Clang, GCC and MSVC
+(-O0 -g) for Windows and Linux.
+
+.. code-block:: c++
+
+   1  extern int printf(const char * format, ... );
+   2
+   3  int main()
+   4  {
+   5    printf("Hello, World\n");
+   6    return 0;
+   7  }
+
+These are the logical views that :program:`llvm-debuginfo-analyzer`
+generates for 3 
diff erent compilers (MSVC, Clang and GCC), emitting
+
diff erent debug information formats (CodeView, DWARF) on Windows and
+Linux.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level,format,producer
+                          --print=lines,instructions
+                          hello-world-codeview-clang.o
+                          hello-world-codeview-msvc.o
+                          hello-world-dwarf-clang.o
+                          hello-world-dwarf-gcc.o
+
+CodeView - Clang (Windows)
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'hello-world-codeview-clang.o' -> COFF-x86-64
+
+  [001]             {CompileUnit} 'hello-world.cpp'
+  [002]               {Producer} 'clang version 14.0.0'
+  [002]               {Function} extern not_inlined 'main' -> 'int'
+  [003]     4           {Line}
+  [003]                 {Code} 'subq	$0x28, %rsp'
+  [003]                 {Code} 'movl	$0x0, 0x24(%rsp)'
+  [003]     5           {Line}
+  [003]                 {Code} 'leaq	(%rip), %rcx'
+  [003]                 {Code} 'callq	0x0'
+  [003]     6           {Line}
+  [003]                 {Code} 'xorl	%eax, %eax'
+  [003]                 {Code} 'addq	$0x28, %rsp'
+  [003]                 {Code} 'retq'
+
+CodeView - MSVC (Windows)
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'hello-world-codeview-msvc.o' -> COFF-i386
+
+  [001]             {CompileUnit} 'hello-world.cpp'
+  [002]               {Producer} 'Microsoft (R) Optimizing Compiler'
+  [002]               {Function} extern not_inlined 'main' -> 'int'
+  [003]     4           {Line}
+  [003]                 {Code} 'pushl	%ebp'
+  [003]                 {Code} 'movl	%esp, %ebp'
+  [003]     5           {Line}
+  [003]                 {Code} 'pushl	$0x0'
+  [003]                 {Code} 'calll	0x0'
+  [003]                 {Code} 'addl	$0x4, %esp'
+  [003]     6           {Line}
+  [003]                 {Code} 'xorl	%eax, %eax'
+  [003]     7           {Line}
+  [003]                 {Code} 'popl	%ebp'
+  [003]                 {Code} 'retl'
+
+DWARF - Clang (Linux)
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'hello-world-dwarf-clang.o' -> elf64-x86-64
+
+  [001]             {CompileUnit} 'hello-world.cpp'
+  [002]               {Producer} 'clang version 14.0.0'
+  [002]     3         {Function} extern not_inlined 'main' -> 'int'
+  [003]     4           {Line}
+  [003]                 {Code} 'pushq	%rbp'
+  [003]                 {Code} 'movq	%rsp, %rbp'
+  [003]                 {Code} 'subq	$0x10, %rsp'
+  [003]                 {Code} 'movl	$0x0, -0x4(%rbp)'
+  [003]     5           {Line}
+  [003]                 {Code} 'movabsq	$0x0, %rdi'
+  [003]                 {Code} 'movb	$0x0, %al'
+  [003]                 {Code} 'callq	0x0'
+  [003]     6           {Line}
+  [003]                 {Code} 'xorl	%eax, %eax'
+  [003]                 {Code} 'addq	$0x10, %rsp'
+  [003]                 {Code} 'popq	%rbp'
+  [003]                 {Code} 'retq'
+  [003]     6           {Line}
+
+DWARF - GCC (Linux)
+^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'hello-world-dwarf-gcc.o' -> elf64-x86-64
+
+  [001]             {CompileUnit} 'hello-world.cpp'
+  [002]               {Producer} 'GNU C++14 9.3.0'
+  [002]     3         {Function} extern not_inlined 'main' -> 'int'
+  [003]     4           {Line}
+  [003]                 {Code} 'endbr64'
+  [003]                 {Code} 'pushq	%rbp'
+  [003]                 {Code} 'movq	%rsp, %rbp'
+  [003]     5           {Line}
+  [003]                 {Code} 'leaq	(%rip), %rdi'
+  [003]                 {Code} 'movl	$0x0, %eax'
+  [003]                 {Code} 'callq	0x0'
+  [003]     6           {Line}
+  [003]                 {Code} 'movl	$0x0, %eax'
+  [003]     7           {Line}
+  [003]                 {Code} 'popq	%rbp'
+  [003]                 {Code} 'retq'
+  [003]     7           {Line}
+
+The logical views shows the intermixed lines and assembler instructions,
+allowing to compare the code generated by the 
diff erent toolchains.
+
+TEST CASE 3 - INCORRECT LEXICAL SCOPE FOR TYPEDEF
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The below example is used to show 
diff erent output generated by
+:program:`llvm-debuginfo-analyzer`. We compiled the example for an X86
+Codeview and ELF targets with recent versions of Clang, GCC and MSVC
+(-O0 -g).
+
+.. code-block:: c++
+
+   1  int bar(float Input) { return (int)Input; }
+   2
+   3  unsigned foo(char Param) {
+   4    typedef int INT;                // ** Definition for INT **
+   5    INT Value = Param;
+   6    {
+   7      typedef float FLOAT;          // ** Definition for FLOAT **
+   8      {
+   9        FLOAT Added = Value + Param;
+  10        Value = bar(Added);
+  11      }
+  12    }
+  13    return Value + Param;
+  14  }
+
+The above test is used to illustrate a scope issue found in the Clang
+compiler:
+`PR44884 (Bugs LLVM) <https://bugs.llvm.org/show_bug.cgi?id=44884>`_ /
+`PR44229 (GitHub LLVM) <https://github.com/llvm/llvm-project/issues/44229>`_
+
+The lines 4 and 7 contains 2 typedefs, defined at 
diff erent lexical
+scopes.
+
+.. code-block:: c++
+
+  4    typedef int INT;
+  7      typedef float FLOAT;
+
+These are the logical views that :program:`llvm-debuginfo-analyzer`
+generates for 3 
diff erent compilers (MSVC, Clang and GCC), emitting
+
diff erent debug information formats (CodeView, DWARF) on 
diff erent
+platforms.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level,format,producer
+                          --print=symbols,types,lines
+                          --output-sort=kind
+                          pr-44884-codeview-clang.o
+                          pr-44884-codeview-msvc.o
+                          pr-44884-dwarf-clang.o
+                          pr-44884-dwarf-gcc.o
+
+CodeView - Clang (Windows)
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-44884-codeview-clang.o' -> COFF-x86-64
+
+  [001]             {CompileUnit} 'pr-44884.cpp'
+  [002]               {Producer} 'clang version 14.0.0'
+  [002]               {Function} extern not_inlined 'bar' -> 'int'
+  [003]                 {Parameter} 'Input' -> 'float'
+  [003]     1           {Line}
+  [002]               {Function} extern not_inlined 'foo' -> 'unsigned'
+  [003]                 {Block}
+  [004]                   {Variable} 'Added' -> 'float'
+  [004]     9             {Line}
+  [004]    10             {Line}
+  [003]                 {Parameter} 'Param' -> 'char'
+  [003]                 {TypeAlias} 'FLOAT' -> 'float'
+  [003]                 {TypeAlias} 'INT' -> 'int'
+  [003]                 {Variable} 'Value' -> 'int'
+  [003]     3           {Line}
+  [003]     5           {Line}
+  [003]    13           {Line}
+
+CodeView - MSVC (Windows)
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-44884-codeview-msvc.o' -> COFF-i386
+
+  [001]             {CompileUnit} 'pr-44884.cpp'
+  [002]               {Producer} 'Microsoft (R) Optimizing Compiler'
+  [002]               {Function} extern not_inlined 'bar' -> 'int'
+  [003]                 {Variable} 'Input' -> 'float'
+  [003]     1           {Line}
+  [002]               {Function} extern not_inlined 'foo' -> 'unsigned'
+  [003]                 {Block}
+  [004]                   {Block}
+  [005]                     {Variable} 'Added' -> 'float'
+  [004]                   {TypeAlias} 'FLOAT' -> 'float'
+  [004]     9             {Line}
+  [004]    10             {Line}
+  [003]                 {TypeAlias} 'INT' -> 'int'
+  [003]                 {Variable} 'Param' -> 'char'
+  [003]                 {Variable} 'Value' -> 'int'
+  [003]     3           {Line}
+  [003]     5           {Line}
+  [003]    13           {Line}
+  [003]    14           {Line}
+
+DWARF - Clang (Linux)
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-44884-dwarf-clang.o' -> elf64-x86-64
+
+  [001]             {CompileUnit} 'pr-44884.cpp'
+  [002]               {Producer} 'clang version 14.0.0'
+  [002]     1         {Function} extern not_inlined 'bar' -> 'int'
+  [003]     1           {Parameter} 'Input' -> 'float'
+  [003]     1           {Line}
+  [003]     1           {Line}
+  [003]     1           {Line}
+  [002]     3         {Function} extern not_inlined 'foo' -> 'unsigned int'
+  [003]                 {Block}
+  [004]     9             {Variable} 'Added' -> 'FLOAT'
+  [004]     9             {Line}
+  [004]     9             {Line}
+  [004]     9             {Line}
+  [004]     9             {Line}
+  [004]     9             {Line}
+  [004]    10             {Line}
+  [004]    10             {Line}
+  [004]    10             {Line}
+  [004]    13             {Line}
+  [003]     3           {Parameter} 'Param' -> 'char'
+  [003]     7           {TypeAlias} 'FLOAT' -> 'float'
+  [003]     4           {TypeAlias} 'INT' -> 'int'
+  [003]     5           {Variable} 'Value' -> 'INT'
+  [003]     3           {Line}
+  [003]     5           {Line}
+  [003]     5           {Line}
+  [003]    13           {Line}
+  [003]    13           {Line}
+  [003]    13           {Line}
+  [003]    13           {Line}
+
+DWARF - GCC (Linux)
+^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-44884-dwarf-gcc.o' -> elf32-littlearm
+
+  [001]             {CompileUnit} 'pr-44884.cpp'
+  [002]               {Producer} 'GNU C++14 10.2.1 20201103'
+  [002]     1         {Function} extern not_inlined 'bar' -> 'int'
+  [003]     1           {Parameter} 'Input' -> 'float'
+  [003]     1           {Line}
+  [003]     1           {Line}
+  [003]     1           {Line}
+  [002]     3         {Function} extern not_inlined 'foo' -> 'unsigned int'
+  [003]                 {Block}
+  [004]                   {Block}
+  [005]     9               {Variable} 'Added' -> 'FLOAT'
+  [005]     9               {Line}
+  [005]     9               {Line}
+  [005]     9               {Line}
+  [005]    10               {Line}
+  [005]    13               {Line}
+  [004]     7             {TypeAlias} 'FLOAT' -> 'float'
+  [003]     3           {Parameter} 'Param' -> 'char'
+  [003]     4           {TypeAlias} 'INT' -> 'int'
+  [003]     5           {Variable} 'Value' -> 'INT'
+  [003]     3           {Line}
+  [003]     5           {Line}
+  [003]    13           {Line}
+  [003]    14           {Line}
+  [003]    14           {Line}
+
+From the previous logical views, we can see that the Clang compiler
+emits **both typedefs at the same lexical scope (3)**, which is wrong.
+GCC and MSVC emit correct lexical scope for both typedefs.
+
+Using the :program:`llvm-debuginfo-analyzer` selection facilities, we
+can produce a simple tabular output showing just the logical types that
+are **Typedef**.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level,format
+                          --output-sort=name
+                          --select-types=Typedef
+                          --report=list
+                          --print=types
+                          pr-44884-*.o
+
+  Logical View:
+  [000]           {File} 'pr-44884-codeview-clang.o' -> COFF-x86-64
+
+  [001]           {CompileUnit} 'pr_44884.cpp'
+  [003]           {TypeAlias} 'FLOAT' -> 'float'
+  [003]           {TypeAlias} 'INT' -> 'int'
+
+  Logical View:
+  [000]           {File} 'pr-44884-codeview-msvc.o' -> COFF-i386
+
+  [001]           {CompileUnit} 'pr_44884.cpp'
+  [004]           {TypeAlias} 'FLOAT' -> 'float'
+  [003]           {TypeAlias} 'INT' -> 'int'
+
+  Logical View:
+  [000]           {File} 'pr-44884-dwarf-clang.o' -> elf64-x86-64
+
+  [001]           {CompileUnit} 'pr_44884.cpp'
+  [003]     7     {TypeAlias} 'FLOAT' -> 'float'
+  [003]     4     {TypeAlias} 'INT' -> 'int'
+
+  Logical View:
+  [000]           {File} 'pr-44884-dwarf-gcc.o' -> elf32-littlearm
+
+  [001]           {CompileUnit} 'pr_44884.cpp'
+  [004]     7     {TypeAlias} 'FLOAT' -> 'float'
+  [003]     4     {TypeAlias} 'INT' -> 'int'
+
+It also shows, that the CodeView debug information does not generate
+source code line numbers for the those logical types. The logical view
+is sorted by the types name.
+
+TEST CASE 4 - MISSING NESTED ENUMERATIONS
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The below example is used to show 
diff erent output generated by
+:program:`llvm-debuginfo-analyzer`. We compiled the example for an X86
+Codeview and ELF targets with recent versions of Clang, GCC and MSVC
+(-O0 -g).
+
+.. code-block:: c++
+
+   1  struct Struct {
+   2    union Union {
+   3      enum NestedEnum { RED, BLUE };
+   4    };
+   5    Union U;
+   6  };
+   7
+   8  Struct S;
+   9  int test() {
+  10    return S.U.BLUE;
+  11  }
+
+The above test is used to illustrate a scope issue found in the Clang
+compiler:
+`PR46466 (Bugs LLVM) <https://bugs.llvm.org/show_bug.cgi?id=46466>`_ /
+`PR45811 (GitHub LLVM) <https://github.com/llvm/llvm-project/issues/45811>`_
+
+These are the logical views that :program:`llvm-debuginfo-analyzer`
+generates for 3 
diff erent compilers (MSVC, Clang and GCC), emitting
+
diff erent debug information formats (CodeView, DWARF) on 
diff erent
+platforms.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level,format,producer
+                          --output-sort=name
+                          --print=symbols,types
+                          pr-46466-codeview-clang.o
+                          pr-46466-codeview-msvc.o
+                          pr-46466-dwarf-clang.o
+                          pr-46466-dwarf-gcc.o
+
+CodeView - Clang (Windows)
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64
+
+  [001]             {CompileUnit} 'pr-46466.cpp'
+  [002]               {Producer} 'clang version 14.0.0'
+  [002]               {Variable} extern 'S' -> 'Struct'
+  [002]     1         {Struct} 'Struct'
+  [003]                 {Member} public 'U' -> 'Union'
+  [003]     2           {Union} 'Union'
+  [004]     3             {Enumeration} 'NestedEnum' -> 'int'
+  [005]                     {Enumerator} 'BLUE' = '0x1'
+  [005]                     {Enumerator} 'RED' = '0x0'
+
+CodeView - MSVC (Windows)
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-46466-codeview-msvc.o' -> COFF-i386
+
+  [001]             {CompileUnit} 'pr-46466.cpp'
+  [002]               {Producer} 'Microsoft (R) Optimizing Compiler'
+  [002]               {Variable} extern 'S' -> 'Struct'
+  [002]     1         {Struct} 'Struct'
+  [003]                 {Member} public 'U' -> 'Union'
+  [003]     2           {Union} 'Union'
+  [004]     3             {Enumeration} 'NestedEnum' -> 'int'
+  [005]                     {Enumerator} 'BLUE' = '0x1'
+  [005]                     {Enumerator} 'RED' = '0x0'
+
+DWARF - Clang (Linux)
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64
+
+  [001]             {CompileUnit} 'pr-46466.cpp'
+  [002]               {Producer} 'clang version 14.0.0'
+  [002]     8         {Variable} extern 'S' -> 'Struct'
+  [002]     1         {Struct} 'Struct'
+  [003]     5           {Member} public 'U' -> 'Union'
+
+DWARF - GCC (Linux)
+^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
+
+  [001]             {CompileUnit} 'pr-46466.cpp'
+  [002]               {Producer} 'GNU C++14 9.3.0'
+  [002]     8         {Variable} extern 'S' -> 'Struct'
+  [002]     1         {Struct} 'Struct'
+  [003]     5           {Member} public 'U' -> 'Union'
+  [003]     2           {Union} 'Union'
+  [004]     3             {Enumeration} 'NestedEnum' -> 'unsigned int'
+  [005]                     {Enumerator} 'BLUE' = '0x1'
+  [005]                     {Enumerator} 'RED' = '0x0'
+
+From the previous logical views, we can see that the DWARF debug
+information generated by the Clang compiler does not include any
+references to the enumerators **RED** and **BLUE**. The DWARF
+generated by GCC, CodeView generated by Clang and MSVC, they do
+include such references.
+
+Using the :program:`llvm-debuginfo-analyzer` selection facilities, we
+can produce a logical view showing just the logical types that are
+**Enumerator** and its parents. The logical view is sorted by the types
+name.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=format,level
+                          --output-sort=name
+                          --select-types=Enumerator
+                          --report=parents
+                          --print=types
+                          pr-46466-*.o
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64
+
+  [001]             {CompileUnit} 'pr-46466.cpp'
+  [002]     1         {Struct} 'Struct'
+  [003]     2           {Union} 'Union'
+  [004]     3             {Enumeration} 'NestedEnum' -> 'int'
+  [005]                     {Enumerator} 'BLUE' = '0x1'
+  [005]                     {Enumerator} 'RED' = '0x0'
+
+  Logical View:
+  [000]           {File} 'pr-46466-codeview-msvc.o' -> COFF-i386
+
+  [001]             {CompileUnit} 'pr-46466.cpp'
+  [002]     1         {Struct} 'Struct'
+  [003]     2           {Union} 'Union'
+  [004]     3             {Enumeration} 'NestedEnum' -> 'int'
+  [005]                     {Enumerator} 'BLUE' = '0x1'
+  [005]                     {Enumerator} 'RED' = '0x0'
+
+  Logical View:
+  [000]           {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64
+
+  [001]             {CompileUnit} 'pr-46466.cpp'
+
+  Logical View:
+  [000]           {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
+
+  [001]             {CompileUnit} 'pr-46466.cpp'
+  [002]     1         {Struct} 'Struct'
+  [003]     2           {Union} 'Union'
+  [004]     3             {Enumeration} 'NestedEnum' -> 'unsigned int'
+  [005]                     {Enumerator} 'BLUE' = '0x1'
+  [005]                     {Enumerator} 'RED' = '0x0'
+
+Using the :program:`llvm-debuginfo-analyzer` selection facilities, we
+can produce a simple tabular output including a summary for the logical
+types that are **Enumerator**. The logical view is sorted by the types
+name.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=format,level
+                          --output-sort=name
+                          --select-types=Enumerator
+                          --print=types,summary
+                          pr-46466-*.o
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64
+
+  [001]           {CompileUnit} 'pr-46466.cpp'
+  [005]           {Enumerator} 'BLUE' = '0x1'
+  [005]           {Enumerator} 'RED' = '0x0'
+
+  -----------------------------
+  Element      Total      Found
+  -----------------------------
+  Scopes           5          0
+  Symbols          2          0
+  Types            6          2
+  Lines            0          0
+  -----------------------------
+  Total           13          2
+
+  Logical View:
+  [000]           {File} 'pr-46466-codeview-msvc.o' -> COFF-i386
+
+  [001]           {CompileUnit} 'pr-46466.cpp'
+  [005]           {Enumerator} 'BLUE' = '0x1'
+  [005]           {Enumerator} 'RED' = '0x0'
+
+  -----------------------------
+  Element      Total      Found
+  -----------------------------
+  Scopes           5          0
+  Symbols          2          0
+  Types            7          2
+  Lines            0          0
+  -----------------------------
+  Total           14          2
+
+  Logical View:
+  [000]           {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64
+
+  [001]           {CompileUnit} 'pr-46466.cpp'
+
+  -----------------------------
+  Element      Total      Found
+  -----------------------------
+  Scopes           4          0
+  Symbols          0          0
+  Types            0          0
+  Lines            0          0
+  -----------------------------
+  Total            4          0
+
+  Logical View:
+  [000]           {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
+
+  [001]           {CompileUnit} 'pr-46466.cpp'
+  [005]           {Enumerator} 'BLUE' = '0x1'
+  [005]           {Enumerator} 'RED' = '0x0'
+
+  -----------------------------
+  Element      Total      Found
+  -----------------------------
+  Scopes           5          0
+  Symbols          0          0
+  Types            2          2
+  Lines            0          0
+  -----------------------------
+  Total            7          2
+
+From the values printed under the **Found** column, we can see that no
+**Types** were found in the DWARF debug information generated by Clang.
+
+TEST CASE 5 - INCORRECT LEXICAL SCOPE FOR VARIABLE
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The below example is used to show 
diff erent output generated by
+:program:`llvm-debuginfo-analyzer`. We compiled the example for an X86
+Codeview and ELF targets with recent versions of Clang, GCC and MSVC
+(-O0 -g).
+
+.. code-block:: c++
+
+  // definitions.h
+  #ifdef _MSC_VER
+    #define forceinline __forceinline
+  #elif defined(__clang__)
+    #if __has_attribute(__always_inline__)
+      #define forceinline inline __attribute__((__always_inline__))
+    #else
+      #define forceinline inline
+    #endif
+  #elif defined(__GNUC__)
+    #define forceinline inline __attribute__((__always_inline__))
+  #else
+    #define forceinline inline
+    #error
+  #endif
+
+As the test is dependent on inline compiler options, the above header
+file defines *forceinline*.
+
+.. code-block:: c++
+
+   #include "definitions.h"
+
+.. code-block:: c++
+
+   1  #include "definitions.h"
+   2  forceinline int InlineFunction(int Param) {
+   3    int Var_1 = Param;
+   4    {
+   5      int Var_2 = Param + Var_1;
+   6      Var_1 = Var_2;
+   7    }
+   8    return Var_1;
+   9  }
+  10
+  11  int test(int Param_1, int Param_2) {
+  12    int A = Param_1;
+  13    A += InlineFunction(Param_2);
+  14    return A;
+  15  }
+
+The above test is used to illustrate a variable issue found in the Clang
+compiler:
+`PR43860 (Bugs LLVM) <https://bugs.llvm.org/show_bug.cgi?id=43860>`_ /
+`PR43205 (GitHub) <https://github.com/llvm/llvm-project/issues/43205>`_
+
+These are the logical views that :program:`llvm-debuginfo-analyzer`
+generates for 3 
diff erent compilers (MSVC, Clang and GCC), emitting
+
diff erent debug information formats (CodeView, DWARF) on 
diff erent
+platforms.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level,format,producer
+                          --output-sort=name
+                          --print=symbols
+                          pr-43860-codeview-clang.o
+                          pr-43860-codeview-msvc.o
+                          pr-43860-dwarf-clang.o
+                          pr-43860-dwarf-gcc.o
+
+CODEVIEW - Clang (Windows)
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-43860-codeview-clang.o' -> COFF-x86-64
+
+  [001]             {CompileUnit} 'pr-43860.cpp'
+  [002]               {Producer} 'clang version 14.0.0'
+  [002]     2         {Function} inlined 'InlineFunction' -> 'int'
+  [003]                 {Parameter} '' -> 'int'
+  [002]               {Function} extern not_inlined 'test' -> 'int'
+  [003]                 {Variable} 'A' -> 'int'
+  [003]                 {InlinedFunction} inlined 'InlineFunction' -> 'int'
+  [004]                   {Parameter} 'Param' -> 'int'
+  [004]                   {Variable} 'Var_1' -> 'int'
+  [004]                   {Variable} 'Var_2' -> 'int'
+  [003]                 {Parameter} 'Param_1' -> 'int'
+  [003]                 {Parameter} 'Param_2' -> 'int'
+
+CODEVIEW - MSVC (Windows)
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-43860-codeview-msvc.o' -> COFF-i386
+
+  [001]             {CompileUnit} 'pr-43860.cpp'
+  [002]               {Producer} 'Microsoft (R) Optimizing Compiler'
+  [002]               {Function} extern not_inlined 'InlineFunction' -> 'int'
+  [003]                 {Block}
+  [004]                   {Variable} 'Var_2' -> 'int'
+  [003]                 {Variable} 'Param' -> 'int'
+  [003]                 {Variable} 'Var_1' -> 'int'
+  [002]               {Function} extern not_inlined 'test' -> 'int'
+  [003]                 {Variable} 'A' -> 'int'
+  [003]                 {Variable} 'Param_1' -> 'int'
+  [003]                 {Variable} 'Param_2' -> 'int'
+
+DWARF - Clang (Linux)
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-43860-dwarf-clang.o' -> elf64-x86-64
+
+  [001]             {CompileUnit} 'pr-43860.cpp'
+  [002]               {Producer} 'clang version 14.0.0'
+  [002]     2         {Function} extern inlined 'InlineFunction' -> 'int'
+  [003]                 {Block}
+  [004]     5             {Variable} 'Var_2' -> 'int'
+  [003]     2           {Parameter} 'Param' -> 'int'
+  [003]     3           {Variable} 'Var_1' -> 'int'
+  [002]    11         {Function} extern not_inlined 'test' -> 'int'
+  [003]    12           {Variable} 'A' -> 'int'
+  [003]    14           {InlinedFunction} inlined 'InlineFunction' -> 'int'
+  [004]                   {Block}
+  [005]                     {Variable} 'Var_2' -> 'int'
+  [004]                   {Parameter} 'Param' -> 'int'
+  [004]                   {Variable} 'Var_1' -> 'int'
+  [003]    11           {Parameter} 'Param_1' -> 'int'
+  [003]    11           {Parameter} 'Param_2' -> 'int'
+
+DWARF - GCC (Linux)
+^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64
+
+  [001]             {CompileUnit} 'pr-43860.cpp'
+  [002]               {Producer} 'GNU C++14 9.3.0'
+  [002]     2         {Function} extern declared_inlined 'InlineFunction' -> 'int'
+  [003]                 {Block}
+  [004]     5             {Variable} 'Var_2' -> 'int'
+  [003]     2           {Parameter} 'Param' -> 'int'
+  [003]     3           {Variable} 'Var_1' -> 'int'
+  [002]    11         {Function} extern not_inlined 'test' -> 'int'
+  [003]    12           {Variable} 'A' -> 'int'
+  [003]    13           {InlinedFunction} declared_inlined 'InlineFunction' -> 'int'
+  [004]                   {Block}
+  [005]                     {Variable} 'Var_2' -> 'int'
+  [004]                   {Parameter} 'Param' -> 'int'
+  [004]                   {Variable} 'Var_1' -> 'int'
+  [003]    11           {Parameter} 'Param_1' -> 'int'
+  [003]    11           {Parameter} 'Param_2' -> 'int'
+
+From the previous logical views, we can see that the CodeView debug
+information generated by the Clang compiler shows the variables **Var_1**
+and **Var_2** are at the same lexical scope (**4**) in the function
+**InlineFuction**. The DWARF generated by GCC/Clang and CodeView
+generated by MSVC, show those variables at the correct lexical scope:
+**3** and **4** respectively.
+
+Using the :program:`llvm-debuginfo-analyzer` selection facilities, we
+can produce a simple tabular output showing just the logical elements
+that have in their name the *var* pattern. The logical view is sorted
+by the variables name.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=level,format
+                          --output-sort=name
+                          --select-regex --select-nocase --select=Var
+                          --report=list
+                          --print=symbols
+                          pr-43860-*.o
+
+.. code-block:: none
+
+  Logical View:
+  [000]           {File} 'pr-43860-codeview-clang.o' -> COFF-x86-64
+
+  [001]           {CompileUnit} 'pr-43860.cpp'
+  [004]           {Variable} 'Var_1' -> 'int'
+  [004]           {Variable} 'Var_2' -> 'int'
+
+  Logical View:
+  [000]           {File} 'pr-43860-codeview-msvc.o' -> COFF-i386
+
+  [001]           {CompileUnit} 'pr-43860.cpp'
+  [003]           {Variable} 'Var_1' -> 'int'
+  [004]           {Variable} 'Var_2' -> 'int'
+
+  Logical View:
+  [000]           {File} 'pr-43860-dwarf-clang.o' -> elf64-x86-64
+
+  [001]           {CompileUnit} 'pr-43860.cpp'
+  [004]           {Variable} 'Var_1' -> 'int'
+  [003]     3     {Variable} 'Var_1' -> 'int'
+  [005]           {Variable} 'Var_2' -> 'int'
+  [004]     5     {Variable} 'Var_2' -> 'int'
+
+  Logical View:
+  [000]           {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64
+
+  [001]           {CompileUnit} 'pr-43860.cpp'
+  [004]           {Variable} 'Var_1' -> 'int'
+  [003]     3     {Variable} 'Var_1' -> 'int'
+  [005]           {Variable} 'Var_2' -> 'int'
+  [004]     5     {Variable} 'Var_2' -> 'int'
+
+It also shows, that the CodeView debug information does not generate
+source code line numbers for the those logical symbols. The logical
+view is sorted by the types name.
+
+TEST CASE 6 - FULL LOGICAL VIEW
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+For advanced users, :program:`llvm-debuginfo-analyzer` can display low
+level information that includes offsets within the debug information
+section, debug location operands, linkage names, etc.
+
+.. code-block:: none
+
+  llvm-debuginfo-analyzer --attribute=all
+                          --print=all
+                          test-dwarf-clang.o
+
+  Logical View:
+  [0x0000000000][000]            {File} 'test-dwarf-clang.o' -> elf64-x86-64
+
+  [0x000000000b][001]              {CompileUnit} 'test.cpp'
+  [0x000000000b][002]                {Producer} 'clang version 12.0.0'
+                                     {Directory} ''
+                                     {File} 'test.cpp'
+                                     {Public} 'foo' [0x0000000000:0x000000003a]
+  [0x000000000b][002]                {Range} Lines 2:9 [0x0000000000:0x000000003a]
+  [0x00000000bc][002]                {BaseType} 'bool'
+  [0x0000000099][002]                {BaseType} 'int'
+  [0x00000000b5][002]                {BaseType} 'unsigned int'
+
+  [0x00000000a0][002]   {Source} '/test.cpp'
+  [0x00000000a0][002]      1         {TypeAlias} 'INTPTR' -> [0x00000000ab]'* const int'
+  [0x000000002a][002]      2         {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
+  [0x000000002a][003]                  {Range} Lines 2:9 [0x0000000000:0x000000003a]
+  [0x000000002a][003]                  {Linkage}  0x2 '_Z3fooPKijb'
+  [0x0000000071][003]                  {Block}
+  [0x0000000071][004]                    {Range} Lines 5:8 [0x000000001c:0x000000002f]
+  [0x000000007e][004]      5             {Variable} 'CONSTANT' -> [0x00000000c3]'const INTEGER'
+  [0x000000007e][005]                      {Coverage} 100.00%
+  [0x000000007f][005]                      {Location}
+  [0x000000007f][006]                        {Entry} Stack Offset: -28 (0xffffffffffffffe4) [DW_OP_fbreg]
+  [0x000000001c][004]      5             {Line} {NewStatement} '/test.cpp'
+  [0x000000001c][004]                    {Code} 'movl	$0x7, -0x1c(%rbp)'
+  [0x0000000023][004]      6             {Line} {NewStatement} '/test.cpp'
+  [0x0000000023][004]                    {Code} 'movl	$0x7, -0x4(%rbp)'
+  [0x000000002a][004]                    {Code} 'jmp	0x6'
+  [0x000000002f][004]      8             {Line} {NewStatement} '/test.cpp'
+  [0x000000002f][004]                    {Code} 'movl	-0x14(%rbp), %eax'
+  [0x0000000063][003]      2           {Parameter} 'ParamBool' -> [0x00000000bc]'bool'
+  [0x0000000063][004]                    {Coverage} 100.00%
+  [0x0000000064][004]                    {Location}
+  [0x0000000064][005]                      {Entry} Stack Offset: -21 (0xffffffffffffffeb) [DW_OP_fbreg]
+  [0x0000000047][003]      2           {Parameter} 'ParamPtr' -> [0x00000000a0]'INTPTR'
+  [0x0000000047][004]                    {Coverage} 100.00%
+  [0x0000000048][004]                    {Location}
+  [0x0000000048][005]                      {Entry} Stack Offset: -16 (0xfffffffffffffff0) [DW_OP_fbreg]
+  [0x0000000055][003]      2           {Parameter} 'ParamUnsigned' -> [0x00000000b5]'unsigned int'
+  [0x0000000055][004]                    {Coverage} 100.00%
+  [0x0000000056][004]                    {Location}
+  [0x0000000056][005]                      {Entry} Stack Offset: -20 (0xffffffffffffffec) [DW_OP_fbreg]
+  [0x000000008d][003]      4           {TypeAlias} 'INTEGER' -> [0x0000000099]'int'
+  [0x0000000000][003]      2           {Line} {NewStatement} '/test.cpp'
+  [0x0000000000][003]                  {Code} 'pushq	%rbp'
+  [0x0000000001][003]                  {Code} 'movq	%rsp, %rbp'
+  [0x0000000004][003]                  {Code} 'movb	%dl, %al'
+  [0x0000000006][003]                  {Code} 'movq	%rdi, -0x10(%rbp)'
+  [0x000000000a][003]                  {Code} 'movl	%esi, -0x14(%rbp)'
+  [0x000000000d][003]                  {Code} 'andb	$0x1, %al'
+  [0x000000000f][003]                  {Code} 'movb	%al, -0x15(%rbp)'
+  [0x0000000012][003]      3           {Line} {NewStatement} {PrologueEnd} '/test.cpp'
+  [0x0000000012][003]                  {Code} 'testb	$0x1, -0x15(%rbp)'
+  [0x0000000016][003]                  {Code} 'je	0x13'
+  [0x0000000032][003]      8           {Line} '/test.cpp'
+  [0x0000000032][003]                  {Code} 'movl	%eax, -0x4(%rbp)'
+  [0x0000000035][003]      9           {Line} {NewStatement} '/test.cpp'
+  [0x0000000035][003]                  {Code} 'movl	-0x4(%rbp), %eax'
+  [0x0000000038][003]                  {Code} 'popq	%rbp'
+  [0x0000000039][003]                  {Code} 'retq'
+  [0x000000003a][003]      9           {Line} {NewStatement} {EndSequence} '/test.cpp'
+
+  -----------------------------
+  Element      Total    Printed
+  -----------------------------
+  Scopes           3          3
+  Symbols          4          4
+  Types            5          5
+  Lines           25         25
+  -----------------------------
+  Total           37         37
+
+  Scope Sizes:
+         189 (100.00%) : [0x000000000b][001]              {CompileUnit} 'test.cpp'
+         110 ( 58.20%) : [0x000000002a][002]      2         {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
+          27 ( 14.29%) : [0x0000000071][003]                  {Block}
+
+  Totals by lexical level:
+  [001]:        189 (100.00%)
+  [002]:        110 ( 58.20%)
+  [003]:         27 ( 14.29%)
+
+The **Scope Sizes** table shows the contribution in bytes to the debug
+information by each scope, which can be used to determine unexpected
+size changes in the DWARF sections between 
diff erent versions of the
+same toolchain.
+
+.. code-block:: none
+
+  [0x000000002a][002]      2         {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
+  [0x000000002a][003]                  {Range} Lines 2:9 [0x0000000000:0x000000003a]
+  [0x000000002a][003]                  {Linkage}  0x2 '_Z3fooPKijb'
+  [0x0000000071][003]                  {Block}
+  [0x0000000071][004]                    {Range} Lines 5:8 [0x000000001c:0x000000002f]
+  [0x000000007e][004]      5             {Variable} 'CONSTANT' -> [0x00000000c3]'const INTEGER'
+  [0x000000007e][005]                      {Coverage} 100.00%
+  [0x000000007f][005]                      {Location}
+  [0x000000007f][006]                        {Entry} Stack Offset: -28 (0xffffffffffffffe4) [DW_OP_fbreg]
+
+The **{Range}** attribute describe the line ranges for a logical scope.
+For this case, the function **foo** is within the lines **2** and **9**.
+
+The **{Coverage}** and **{Location}** attributes describe the debug
+location and coverage for logical symbols. For optimized code, the
+coverage value decreases and it affects the program debuggability.
+
+EXIT STATUS
+-----------
+:program:`llvm-debuginfo-analyzer` returns 0 if the input files were
+parsed and printed successfully. Otherwise, it returns 1.
+
+SEE ALSO
+--------
+:manpage:`llvm-dwarfdump`

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
new file mode 100644
index 0000000000000..a622c499b48aa
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
@@ -0,0 +1,55 @@
+//===-- LVElement.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVElement class, which is used to describe a debug
+// information element.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVELEMENT_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVELEMENT_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVObject.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVStringPool.h"
+#include <set>
+
+namespace llvm {
+namespace logicalview {
+
+enum class LVElementKind { Discarded, Global, Optimized, LastEntry };
+using LVElementKindSet = std::set<LVElementKind>;
+
+class LVElement : public LVObject {
+  // Indexes in the String Pool.
+  size_t NameIndex = 0;
+  size_t FilenameIndex = 0;
+
+public:
+  LVElement() = default;
+  virtual ~LVElement() = default;
+
+  bool isNamed() const override { return NameIndex != 0; }
+
+  StringRef getName() const override {
+    return getStringPool().getString(NameIndex);
+  }
+
+  // Get pathname associated with the Element.
+  StringRef getPathname() const {
+    return getStringPool().getString(getFilenameIndex());
+  }
+
+  // Element type name.
+  StringRef getTypeName() const;
+  size_t getFilenameIndex() const { return FilenameIndex; }
+};
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVELEMENT_H

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h
new file mode 100644
index 0000000000000..552e9bb792cbc
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h
@@ -0,0 +1,40 @@
+//===-- LVLine.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVLine class, which is used to describe a debug
+// information line.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLINE_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLINE_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
+
+namespace llvm {
+namespace logicalview {
+
+enum class LVLineKind {
+  IsBasicBlock,
+  IsDiscriminator,
+  IsEndSequence,
+  IsEpilogueBegin,
+  IsLineDebug,
+  IsLineAssembler,
+  IsNewStatement, // Shared with CodeView 'IsStatement' flag.
+  IsPrologueEnd,
+  IsAlwaysStepInto, // CodeView
+  IsNeverStepInto,  // CodeView
+  LastEntry
+};
+using LVLineKindSet = std::set<LVLineKind>;
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLINE_H

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
new file mode 100644
index 0000000000000..462d929bad339
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
@@ -0,0 +1,60 @@
+//===-- LVObject.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVObject class, which is used to describe a debug
+// information object.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVSupport.h"
+#include <string>
+
+namespace llvm {
+namespace logicalview {
+
+using LVHalf = uint16_t;
+using LVOffset = uint64_t;
+
+class LVObject {
+  LVOffset Offset = 0;
+
+protected:
+  // Get a string representation for the given number and discriminator.
+  std::string lineAsString(uint32_t LineNumber, LVHalf Discriminator,
+                           bool ShowZero) const;
+
+  // Get a string representation for the given number.
+  std::string referenceAsString(uint32_t LineNumber, bool Spaces) const;
+
+  // Print the Filename or Pathname.
+  // Empty implementation for those objects that do not have any user
+  // source file references, such as debug locations.
+  virtual void printFileIndex(raw_ostream &OS, bool Full = true) const {}
+
+public:
+  LVObject() = default;
+  virtual ~LVObject() = default;
+
+  // True if the scope has been named.
+  virtual bool isNamed() const { return false; }
+
+  // DIE offset.
+  LVOffset getOffset() const { return Offset; }
+
+  virtual StringRef getName() const { return StringRef(); }
+
+  std::string lineNumberAsStringStripped(bool ShowZero = false) const;
+};
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVOptions.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVOptions.h
new file mode 100644
index 0000000000000..88b027166d054
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVOptions.h
@@ -0,0 +1,451 @@
+//===-- LVOptions.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVOptions class, which is used to record the command
+// line options.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOPTIONS_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOPTIONS_H
+
+#include "llvm/ADT/StringSet.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
+#include <set>
+#include <string>
+
+namespace llvm {
+namespace logicalview {
+
+// Generate get and set 'bool' functions.
+#define BOOL_FUNCTION(FAMILY, FIELD)                                           \
+  bool get##FAMILY##FIELD() const { return FAMILY.FIELD; }                     \
+  void set##FAMILY##FIELD() { FAMILY.FIELD = true; }                           \
+  void reset##FAMILY##FIELD() { FAMILY.FIELD = false; }
+
+// Generate get and set 'unsigned' functions.
+#define UNSIGNED_FUNCTION(FAMILY, FIELD)                                       \
+  unsigned get##FAMILY##FIELD() const { return FAMILY.FIELD; }                 \
+  void set##FAMILY##FIELD(unsigned Value) { FAMILY.FIELD = Value; }            \
+  void reset##FAMILY##FIELD() { FAMILY.FIELD = -1U; }
+
+// Generate get and set 'std::string' functions.
+#define STD_STRING_FUNCTION(FAMILY, FIELD)                                     \
+  std::string get##FAMILY##FIELD() const { return FAMILY.FIELD; }              \
+  void set##FAMILY##FIELD(std::string FIELD) { FAMILY.FIELD = FIELD; }         \
+  void reset##FAMILY##FIELD() { FAMILY.FIELD = ""; }
+
+// Generate get and set 'std::set' functions.
+#define STDSET_FUNCTION_4(FAMILY, FIELD, TYPE, SET)                            \
+  bool get##FAMILY##FIELD() const {                                            \
+    return FAMILY.SET.find(TYPE::FIELD) != FAMILY.SET.end();                   \
+  }                                                                            \
+  void set##FAMILY##FIELD() { FAMILY.SET.insert(TYPE::FIELD); }                \
+  void reset##FAMILY##FIELD() {                                                \
+    std::set<TYPE>::iterator Iter = FAMILY.SET.find(TYPE::FIELD);              \
+    if (Iter != FAMILY.SET.end())                                              \
+      FAMILY.SET.erase(Iter);                                                  \
+  }
+
+#define STDSET_FUNCTION_5(FAMILY, FIELD, ENTRY, TYPE, SET)                     \
+  bool get##FAMILY##FIELD##ENTRY() const {                                     \
+    return FAMILY.SET.find(TYPE::ENTRY) != FAMILY.SET.end();                   \
+  }                                                                            \
+  void set##FAMILY##FIELD##ENTRY() { FAMILY.SET.insert(TYPE::ENTRY); }
+
+// Generate get and set functions for '--attribute'
+#define ATTRIBUTE_OPTION(FIELD)                                                \
+  STDSET_FUNCTION_4(Attribute, FIELD, LVAttributeKind, Kinds)
+
+// Generate get and set functions for '--output'
+#define OUTPUT_OPTION(FIELD)                                                   \
+  STDSET_FUNCTION_4(Output, FIELD, LVOutputKind, Kinds)
+
+// Generate get and set functions for '--print'
+#define PRINT_OPTION(FIELD) STDSET_FUNCTION_4(Print, FIELD, LVPrintKind, Kinds)
+
+// Generate get and set functions for '--warning'
+#define WARNING_OPTION(FIELD)                                                  \
+  STDSET_FUNCTION_4(Warning, FIELD, LVWarningKind, Kinds)
+
+// Generate get and set functions for '--compare'
+#define COMPARE_OPTION(FIELD)                                                  \
+  STDSET_FUNCTION_4(Compare, FIELD, LVCompareKind, Elements)
+
+// Generate get and set functions for '--report'
+#define REPORT_OPTION(FIELD)                                                   \
+  STDSET_FUNCTION_4(Report, FIELD, LVReportKind, Kinds)
+
+// Generate get and set functions for '--internal'
+#define INTERNAL_OPTION(FIELD)                                                 \
+  STDSET_FUNCTION_4(Internal, FIELD, LVInternalKind, Kinds)
+
+using LVOffsetSet = std::set<uint64_t>;
+
+enum class LVAttributeKind {
+  All,           // --attribute=all
+  Argument,      // --attribute=argument
+  Base,          // --attribute=base
+  Coverage,      // --attribute=coverage
+  Directories,   // --attribute=directories
+  Discarded,     // --attribute=discarded
+  Discriminator, // --attribute=discriminator
+  Encoded,       // --attribute=encoded
+  Extended,      // --attribute=extended
+  Filename,      // --attribute=filename
+  Files,         // --attribute=files
+  Format,        // --attribute=format
+  Gaps,          // --attribute=gaps
+  Generated,     // --attribute=generated
+  Global,        // --attribute=global
+  Inserted,      // --attribute=inserted
+  Level,         // --attribute=level
+  Linkage,       // --attribute=linkage
+  Local,         // --attribute=local
+  Location,      // --attribute=location
+  Offset,        // --attribute=offset
+  Pathname,      // --attribute=pathname
+  Producer,      // --attribute=producer
+  Publics,       // --attribute=publics
+  Qualified,     // --attribute=qualified
+  Qualifier,     // --attribute=qualifier
+  Range,         // --attribute=range
+  Reference,     // --attribute=reference
+  Register,      // --attribute=register
+  Standard,      // --attribute=standard
+  Subrange,      // --attribute=subrange
+  System,        // --attribute=system
+  Typename,      // --attribute=typename
+  Underlying,    // --attribute=underlying
+  Zero           // --attribute=zero
+};
+using LVAttributeKindSet = std::set<LVAttributeKind>;
+
+enum class LVCompareKind {
+  All,     // --compare=all
+  Lines,   // --compare=lines
+  Scopes,  // --compare=scopes
+  Symbols, // --compare=symbols
+  Types    // --compare=types
+};
+using LVCompareKindSet = std::set<LVCompareKind>;
+
+enum class LVOutputKind {
+  All,   // --output=all
+  Split, // --output=split
+  Json,  // --output=json
+  Text   // --output=text
+};
+using LVOutputKindSet = std::set<LVOutputKind>;
+
+enum class LVPrintKind {
+  All,          // --print=all
+  Elements,     // --print=elements
+  Instructions, // --print=instructions
+  Lines,        // --print=lines
+  Scopes,       // --print=scopes
+  Sizes,        // --print=sizes
+  Symbols,      // --print=symbols
+  Summary,      // --print=summary
+  Types,        // --print=types
+  Warnings      // --print=warnings
+};
+using LVPrintKindSet = std::set<LVPrintKind>;
+
+enum class LVReportKind {
+  All,      // --report=all
+  Children, // --report=children
+  List,     // --report=list
+  Parents,  // --report=parents
+  View      // --report=view
+};
+using LVReportKindSet = std::set<LVReportKind>;
+
+enum class LVWarningKind {
+  All,       // --warning=all
+  Coverages, // --warning=coverages
+  Lines,     // --warning=lines
+  Locations, // --warning=locations
+  Ranges     // --warning=ranges
+};
+using LVWarningKindSet = std::set<LVWarningKind>;
+
+enum class LVInternalKind {
+  All,       // --internal=all
+  Cmdline,   // --internal=cmdline
+  ID,        // --internal=id
+  Integrity, // --internal=integrity
+  None,      // --internal=none
+  Tag        // --internal=tag
+};
+using LVInternalKindSet = std::set<LVInternalKind>;
+
+// The 'Kinds' members are a one-to-one mapping to the associated command
+// options that supports comma separated values. There are other 'bool'
+// members that in very few cases point to a command option (see associated
+// comment). Other cases for 'bool' refers to internal values derivated from
+// the command options.
+class LVOptions {
+  class LVAttribute {
+  public:
+    LVAttributeKindSet Kinds; // --attribute=<Kind>
+    bool Added = false;       // Added elements found during comparison.
+    bool AnyLocation = false; // Any kind of location information.
+    bool AnySource = false;   // Any kind of source information.
+    bool Missing = false;     // Missing elements found during comparison.
+  };
+
+  class LVCompare {
+  public:
+    LVCompareKindSet Elements; // --compare=<kind>
+    bool Context = false;      // --compare-context
+    bool Execute = false;      // Compare requested.
+    bool Print = false;        // Enable any printing.
+  };
+
+  class LVPrint {
+  public:
+    LVPrintKindSet Kinds;      // --print=<Kind>
+    bool AnyElement = false;   // Request to print any element.
+    bool AnyLine = false;      // Print 'lines' or 'instructions'.
+    bool Execute = false;      // Print requested.
+    bool Formatting = true;    // Disable formatting during printing.
+    bool Offset = false;       // Print offsets while formatting is disabled.
+    bool SizesSummary = false; // Print 'sizes' or 'summary'.
+  };
+
+  class LVReport {
+  public:
+    LVReportKindSet Kinds; // --report=<kind>
+    bool AnyView = false;  // View, Parents or Children.
+    bool Execute = false;  // Report requested.
+  };
+
+  class LVSelect {
+  public:
+    bool IgnoreCase = false;     // --select-ignore-case
+    bool UseRegex = false;       // --select-use-regex
+    bool Execute = false;        // Select requested.
+    bool GenericKind = false;    // We have collected generic kinds.
+    bool GenericPattern = false; // We have collected generic patterns.
+    bool OffsetPattern = false;  // We have collected offset patterns.
+    StringSet<> Generic;         // --select=<Pattern>
+    LVOffsetSet Offsets;         // --select-offset=<Offset>
+    LVElementKindSet Elements;   // --select-elements=<Kind>
+    LVLineKindSet Lines;         // --select-lines=<Kind>
+    LVScopeKindSet Scopes;       // --select-scopes=<Kind>
+    LVSymbolKindSet Symbols;     // --select-symbols=<Kind>
+    LVTypeKindSelection Types;   // --select-types=<Kind>
+  };
+
+  class LVOutput {
+  public:
+    LVOutputKindSet Kinds;                  // --output=<kind>
+    LVSortMode SortMode = LVSortMode::None; // --output-sort=<SortMode>
+    std::string Folder;                     // --output-folder=<Folder>
+    unsigned Level = -1U;                   // --output-level=<level>
+  };
+
+  class LVWarning {
+  public:
+    LVWarningKindSet Kinds; // --warning=<Kind>
+  };
+
+  class LVInternal {
+  public:
+    LVInternalKindSet Kinds; // --internal=<Kind>
+  };
+
+  class LVGeneral {
+  public:
+    bool CollectRanges = false; // Collect ranges information.
+  };
+
+  // Filters the output of the filename associated with the element being
+  // printed in order to see clearly which logical elements belongs to
+  // a particular filename. It is value is reset after the element
+  // that represents the Compile Unit is printed.
+  size_t LastFilenameIndex = 0;
+
+  // Controls the amount of additional spaces to insert when printing
+  // object attributes, in order to get a consistent printing layout.
+  size_t IndentationSize = 0;
+
+  // Calculate the indentation size, so we can use that value when printing
+  // additional attributes to objects, such as location.
+  void calculateIndentationSize();
+
+public:
+  void resetFilenameIndex() { LastFilenameIndex = 0; }
+  bool changeFilenameIndex(size_t Index) {
+    bool IndexChanged = (Index != LastFilenameIndex);
+    if (IndexChanged)
+      LastFilenameIndex = Index;
+    return IndexChanged;
+  }
+
+  // Access to command line options, pattern and printing information.
+  static LVOptions *getOptions();
+  static void setOptions(LVOptions *Options);
+
+  LVOptions() = default;
+  LVOptions(const LVOptions &) = default;
+  LVOptions &operator=(const LVOptions &) = default;
+  ~LVOptions() = default;
+
+  // Some command line options support shortcuts. For example:
+  // The command line option '--print=elements' is a shortcut for:
+  // '--print=instructions,lines,scopes,symbols,types'.
+  // In the case of logical view comparison, some options related to
+  // attributes must be set or reset for a proper comparison.
+  // Resolve any dependencies between command line options.
+  void resolveDependencies();
+  size_t indentationSize() const { return IndentationSize; }
+
+  LVAttribute Attribute;
+  LVCompare Compare;
+  LVOutput Output;
+  LVPrint Print;
+  LVReport Report;
+  LVSelect Select;
+  LVWarning Warning;
+  LVInternal Internal;
+  LVGeneral General;
+
+  // --attribute.
+  ATTRIBUTE_OPTION(All);
+  ATTRIBUTE_OPTION(Argument);
+  ATTRIBUTE_OPTION(Base);
+  ATTRIBUTE_OPTION(Coverage);
+  ATTRIBUTE_OPTION(Directories);
+  ATTRIBUTE_OPTION(Discarded);
+  ATTRIBUTE_OPTION(Discriminator);
+  ATTRIBUTE_OPTION(Encoded);
+  ATTRIBUTE_OPTION(Extended);
+  ATTRIBUTE_OPTION(Filename);
+  ATTRIBUTE_OPTION(Files);
+  ATTRIBUTE_OPTION(Format);
+  ATTRIBUTE_OPTION(Gaps);
+  ATTRIBUTE_OPTION(Generated);
+  ATTRIBUTE_OPTION(Global);
+  ATTRIBUTE_OPTION(Inserted);
+  ATTRIBUTE_OPTION(Level);
+  ATTRIBUTE_OPTION(Linkage);
+  ATTRIBUTE_OPTION(Location);
+  ATTRIBUTE_OPTION(Local);
+  ATTRIBUTE_OPTION(Offset);
+  ATTRIBUTE_OPTION(Pathname);
+  ATTRIBUTE_OPTION(Producer);
+  ATTRIBUTE_OPTION(Publics);
+  ATTRIBUTE_OPTION(Qualified);
+  ATTRIBUTE_OPTION(Qualifier);
+  ATTRIBUTE_OPTION(Range);
+  ATTRIBUTE_OPTION(Reference);
+  ATTRIBUTE_OPTION(Register);
+  ATTRIBUTE_OPTION(Standard);
+  ATTRIBUTE_OPTION(Subrange);
+  ATTRIBUTE_OPTION(System);
+  ATTRIBUTE_OPTION(Typename);
+  ATTRIBUTE_OPTION(Underlying);
+  ATTRIBUTE_OPTION(Zero);
+  BOOL_FUNCTION(Attribute, Added);
+  BOOL_FUNCTION(Attribute, AnyLocation);
+  BOOL_FUNCTION(Attribute, AnySource);
+  BOOL_FUNCTION(Attribute, Missing);
+
+  // --compare.
+  COMPARE_OPTION(All);
+  COMPARE_OPTION(Lines);
+  COMPARE_OPTION(Scopes);
+  COMPARE_OPTION(Symbols);
+  COMPARE_OPTION(Types);
+  BOOL_FUNCTION(Compare, Context);
+  BOOL_FUNCTION(Compare, Execute);
+  BOOL_FUNCTION(Compare, Print);
+
+  // --output.
+  OUTPUT_OPTION(All);
+  OUTPUT_OPTION(Split);
+  OUTPUT_OPTION(Text);
+  OUTPUT_OPTION(Json);
+  STD_STRING_FUNCTION(Output, Folder);
+  UNSIGNED_FUNCTION(Output, Level);
+  LVSortMode getSortMode() const { return Output.SortMode; }
+  void setSortMode(LVSortMode SortMode) { Output.SortMode = SortMode; }
+
+  // --print.
+  PRINT_OPTION(All);
+  PRINT_OPTION(Elements);
+  PRINT_OPTION(Instructions);
+  PRINT_OPTION(Lines);
+  PRINT_OPTION(Scopes);
+  PRINT_OPTION(Sizes);
+  PRINT_OPTION(Symbols);
+  PRINT_OPTION(Summary);
+  PRINT_OPTION(Types);
+  PRINT_OPTION(Warnings);
+  BOOL_FUNCTION(Print, AnyElement);
+  BOOL_FUNCTION(Print, AnyLine);
+  BOOL_FUNCTION(Print, Execute);
+  BOOL_FUNCTION(Print, Formatting);
+  BOOL_FUNCTION(Print, Offset);
+  BOOL_FUNCTION(Print, SizesSummary);
+
+  // --report.
+  REPORT_OPTION(All);
+  REPORT_OPTION(Children);
+  REPORT_OPTION(List);
+  REPORT_OPTION(Parents);
+  REPORT_OPTION(View);
+  BOOL_FUNCTION(Report, AnyView);
+  BOOL_FUNCTION(Report, Execute);
+
+  // --select.
+  BOOL_FUNCTION(Select, IgnoreCase);
+  BOOL_FUNCTION(Select, UseRegex);
+  BOOL_FUNCTION(Select, Execute);
+  BOOL_FUNCTION(Select, GenericKind);
+  BOOL_FUNCTION(Select, GenericPattern);
+  BOOL_FUNCTION(Select, OffsetPattern);
+
+  // --warning.
+  WARNING_OPTION(All);
+  WARNING_OPTION(Coverages);
+  WARNING_OPTION(Lines);
+  WARNING_OPTION(Locations);
+  WARNING_OPTION(Ranges);
+
+  // --internal.
+  INTERNAL_OPTION(All);
+  INTERNAL_OPTION(Cmdline);
+  INTERNAL_OPTION(ID);
+  INTERNAL_OPTION(Integrity);
+  INTERNAL_OPTION(None);
+  INTERNAL_OPTION(Tag);
+
+  // General shortcuts to some combinations.
+  BOOL_FUNCTION(General, CollectRanges);
+
+  void print(raw_ostream &OS) const;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+  void dump() const { print(dbgs()); }
+#endif
+};
+
+inline LVOptions &options() { return (*LVOptions::getOptions()); }
+inline void setOptions(LVOptions *Options) { LVOptions::setOptions(Options); }
+
+} // namespace logicalview
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOPTIONS_H

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
new file mode 100644
index 0000000000000..0ce2d7e2538e0
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
@@ -0,0 +1,56 @@
+//===-- LVScope.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVScope class, which is used to describe a debug
+// information scope.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVSort.h"
+#include <set>
+
+namespace llvm {
+namespace logicalview {
+
+enum class LVScopeKind {
+  IsAggregate,
+  IsArray,
+  IsBlock,
+  IsCallSite,
+  IsCatchBlock,
+  IsClass,
+  IsCompileUnit,
+  IsEntryPoint,
+  IsEnumeration,
+  IsFunction,
+  IsFunctionType,
+  IsInlinedFunction,
+  IsLabel,
+  IsLexicalBlock,
+  IsMember,
+  IsNamespace,
+  IsRoot,
+  IsStructure,
+  IsSubprogram,
+  IsTemplate,
+  IsTemplateAlias,
+  IsTemplatePack,
+  IsTryBlock,
+  IsUnion,
+  LastEntry
+};
+using LVScopeKindSet = std::set<LVScopeKind>;
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSort.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSort.h
new file mode 100644
index 0000000000000..d5ed3f965810e
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSort.h
@@ -0,0 +1,31 @@
+//===-- LVSort.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the sort algorithms.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSORT_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSORT_H
+
+namespace llvm {
+namespace logicalview {
+
+// Object Sorting Mode.
+enum class LVSortMode {
+  None = 0, // No given sort.
+  Kind,     // Sort by kind.
+  Line,     // Sort by line.
+  Name,     // Sort by name.
+  Offset    // Sort by offset.
+};
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSORT_H

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h
new file mode 100644
index 0000000000000..3733c6c51f19d
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h
@@ -0,0 +1,98 @@
+//===-- LVStringPool.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVStringPool class, which is used to implement a
+// basic string pool table.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSTRINGPOOL_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSTRINGPOOL_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <iomanip>
+#include <vector>
+
+namespace llvm {
+namespace logicalview {
+
+class LVStringPool {
+  static constexpr size_t BadIndex = std::numeric_limits<size_t>::max();
+  using TableType = StringMap<size_t, BumpPtrAllocator>;
+  using ValueType = TableType::value_type;
+  BumpPtrAllocator Allocator;
+  TableType StringTable;
+  std::vector<ValueType *> Entries;
+
+public:
+  LVStringPool() { getIndex(""); }
+  LVStringPool(LVStringPool const &other) = delete;
+  LVStringPool(LVStringPool &&other) = delete;
+  ~LVStringPool() = default;
+
+  bool isValidIndex(size_t Index) const { return Index != BadIndex; }
+
+  // Return number of strings in the pool. The empty string is allocated
+  // at the slot zero. We substract 1 to indicate the number of non empty
+  // strings.
+  size_t getSize() const { return Entries.size() - 1; }
+
+  // Return the index for the specified key, otherwise 'BadIndex'.
+  size_t findIndex(StringRef Key) const {
+    TableType::const_iterator Iter = StringTable.find(Key);
+    if (Iter != StringTable.end())
+      return Iter->second;
+    return BadIndex;
+  }
+
+  // Return an index for the specified key.
+  size_t getIndex(StringRef Key) {
+    size_t Index = findIndex(Key);
+    if (isValidIndex(Index))
+      return Index;
+    size_t Value = Entries.size();
+    ValueType *Entry = ValueType::Create(Key, Allocator, std::move(Value));
+    StringTable.insert(Entry);
+    Entries.push_back(Entry);
+    return Value;
+  }
+
+  // Given the index, return its corresponding string.
+  StringRef getString(size_t Index) const {
+    return (Index >= Entries.size()) ? StringRef() : Entries[Index]->getKey();
+  }
+
+  static LVStringPool &getInstance() {
+    static LVStringPool Instance;
+    return Instance;
+  }
+
+  void print(raw_ostream &OS) const {
+    if (!Entries.empty()) {
+      OS << "\nString Pool:\n";
+      for (const ValueType *Entry : Entries)
+        OS << "Index: " << Entry->getValue() << ", "
+           << "Key: '" << Entry->getKey() << "'\n";
+    }
+  }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+  void dump() const { print(dbgs()); }
+#endif
+};
+
+inline LVStringPool &getStringPool() { return LVStringPool::getInstance(); }
+
+} // namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSTRINGPOOL_H

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
new file mode 100644
index 0000000000000..0df64842d9037
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
@@ -0,0 +1,51 @@
+//===-- LVSupport.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines support functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H
+
+#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cctype>
+#include <sstream>
+
+namespace llvm {
+namespace logicalview {
+
+const int HEX_WIDTH = 12;
+inline FormattedNumber hexValue(uint64_t N, unsigned Width = HEX_WIDTH,
+                                bool Upper = false) {
+  return format_hex(N, Width, Upper);
+}
+
+// Output the hexadecimal representation of 'Value' using '[0x%08x]' format.
+inline std::string hexString(uint64_t Value, size_t Width = HEX_WIDTH) {
+  std::string String;
+  raw_string_ostream Stream(String);
+  Stream << hexValue(Value, Width, false);
+  return Stream.str();
+}
+
+// Get a hexadecimal string representation for the given value.
+inline std::string hexSquareString(uint64_t Value) {
+  return (Twine("[") + Twine(hexString(Value)) + Twine("]")).str();
+}
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h
new file mode 100644
index 0000000000000..52b46f8a117b8
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h
@@ -0,0 +1,37 @@
+//===-- LVSymbol.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVSymbol class, which is used to describe a debug
+// information symbol.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSYMBOL_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSYMBOL_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
+
+namespace llvm {
+namespace logicalview {
+
+enum class LVSymbolKind {
+  IsCallSiteParameter,
+  IsConstant,
+  IsInheritance,
+  IsMember,
+  IsParameter,
+  IsUnspecified,
+  IsVariable,
+  LastEntry
+};
+using LVSymbolKindSet = std::set<LVSymbolKind>;
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSYMBOL_H

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h
new file mode 100644
index 0000000000000..a288a16bd7320
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h
@@ -0,0 +1,51 @@
+//===-- LVType.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LVType class, which is used to describe a debug
+// information type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVTYPE_H
+#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVTYPE_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
+
+namespace llvm {
+namespace logicalview {
+
+enum class LVTypeKind {
+  IsBase,
+  IsConst,
+  IsEnumerator,
+  IsImport,
+  IsImportDeclaration,
+  IsImportModule,
+  IsPointer,
+  IsPointerMember,
+  IsReference,
+  IsRestrict,
+  IsRvalueReference,
+  IsSubrange,
+  IsTemplateParam,
+  IsTemplateTemplateParam,
+  IsTemplateTypeParam,
+  IsTemplateValueParam,
+  IsTypedef,
+  IsUnaligned,
+  IsUnspecified,
+  IsVolatile,
+  IsModifier, // CodeView - LF_MODIFIER
+  LastEntry
+};
+using LVTypeKindSelection = std::set<LVTypeKind>;
+
+} // end namespace logicalview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVTYPE_H

diff  --git a/llvm/lib/DebugInfo/CMakeLists.txt b/llvm/lib/DebugInfo/CMakeLists.txt
index 6355ba08d03c7..d004981fb087a 100644
--- a/llvm/lib/DebugInfo/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_subdirectory(DWARF)
 add_subdirectory(GSYM)
+add_subdirectory(LogicalView)
 add_subdirectory(MSF)
 add_subdirectory(CodeView)
 add_subdirectory(PDB)

diff  --git a/llvm/lib/DebugInfo/LogicalView/CMakeLists.txt b/llvm/lib/DebugInfo/LogicalView/CMakeLists.txt
new file mode 100644
index 0000000000000..dbdfa031cbcc9
--- /dev/null
+++ b/llvm/lib/DebugInfo/LogicalView/CMakeLists.txt
@@ -0,0 +1,31 @@
+set(LLVM_LINK_COMPONENTS
+  BinaryFormat
+  DebugInfoDWARF
+  DebugInfoCodeView
+  DebugInfoPDB
+  Demangle
+  MC
+  Object
+  Support
+  )
+
+macro(add_lv_impl_folder group)
+  list(APPEND LV_IMPL_SOURCES ${ARGN})
+  source_group(${group} FILES ${ARGN})
+endmacro()
+
+add_lv_impl_folder(Core
+  Core/LVOptions.cpp
+  )
+
+list(APPEND LIBLV_ADDITIONAL_HEADER_DIRS
+  "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/LogicalView"
+  "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/LogicalView/Core"
+  )
+
+add_llvm_library(LLVMDebugInfoLogicalView
+  ${LV_IMPL_SOURCES}
+
+  ADDITIONAL_HEADER_DIRS
+  ${LIBLV_ADDITIONAL_HEADER_DIRS}
+  )

diff  --git a/llvm/lib/DebugInfo/LogicalView/Core/LVOptions.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVOptions.cpp
new file mode 100644
index 0000000000000..1afc24403837b
--- /dev/null
+++ b/llvm/lib/DebugInfo/LogicalView/Core/LVOptions.cpp
@@ -0,0 +1,396 @@
+//===-- LVOptions.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This implements the LVOptions class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+
+using namespace llvm;
+using namespace llvm::logicalview;
+
+#define DEBUG_TYPE "Options"
+
+//===----------------------------------------------------------------------===//
+// Options extracted from the command line.
+//===----------------------------------------------------------------------===//
+static LVOptions Options;
+LVOptions *LVOptions::getOptions() { return &Options; }
+void LVOptions::setOptions(LVOptions *CmdOptions) { Options = *CmdOptions; }
+
+void LVOptions::resolveDependencies() {
+  // Attributes that are classified as standard options.
+  auto StandardAttributes = [&]() {
+    // Set the 'standard' attribute to indicate its associated attributes.
+    setAttributeStandard();
+
+    setAttributeBase();
+    setAttributeCoverage();
+    setAttributeDirectories();
+    setAttributeDiscriminator();
+    setAttributeFilename();
+    setAttributeFiles();
+    setAttributeFormat();
+    setAttributeLevel();
+    setAttributeProducer();
+    setAttributePublics();
+    setAttributeRange();
+    setAttributeReference();
+    setAttributeZero();
+  };
+
+  // Attributes that are classified as extended options.
+  auto ExtendedAttributes = [&]() {
+    // Set the 'extended' attribute to indicate its associated attributes.
+    setAttributeExtended();
+
+    setAttributeArgument();
+    setAttributeDiscarded();
+    setAttributeEncoded();
+    setAttributeGaps();
+    setAttributeGenerated();
+    setAttributeGlobal();
+    setAttributeInserted();
+    setAttributeLinkage();
+    setAttributeLocal();
+    setAttributeLocation();
+    setAttributeOffset();
+    setAttributePathname();
+    setAttributeQualified();
+    setAttributeQualifier();
+    setAttributeRegister();
+    setAttributeSubrange();
+    setAttributeSystem();
+    setAttributeTypename();
+  };
+
+  // '--Attribute=standard' settings.
+  if (getAttributeStandard())
+    StandardAttributes();
+
+  // '--Attribute=extended' settings.
+  if (getAttributeExtended())
+    ExtendedAttributes();
+
+  // '--Attribute=all' settings.
+  if (getAttributeAll()) {
+    StandardAttributes();
+    ExtendedAttributes();
+  }
+
+  // '--attribute=pathname' supersedes '--attribute=filename'.
+  if (getAttributePathname())
+    resetAttributeFilename();
+
+  // Assume '--output=text' as default
+  if (!getOutputText() && !getOutputJson())
+    setOutputText();
+
+  // '--output=all' settings.
+  if (getOutputAll()) {
+    setOutputJson();
+    setOutputSplit();
+    setOutputText();
+  }
+
+  // A view split folder was specified.
+  if (getOutputFolder().length())
+    setOutputSplit();
+
+  // Always use the full pathname with splitted output.
+  if (getOutputSplit())
+    setAttributePathname();
+
+  // '--print=elements' settings.
+  if (getPrintElements()) {
+    setPrintInstructions();
+    setPrintLines();
+    setPrintScopes();
+    setPrintSymbols();
+    setPrintTypes();
+  }
+
+  // '--print=all' settings.
+  if (getPrintAll()) {
+    setPrintInstructions();
+    setPrintLines();
+    setPrintScopes();
+    setPrintSizes();
+    setPrintSymbols();
+    setPrintSummary();
+    setPrintTypes();
+    setPrintWarnings();
+  }
+
+  // '--warning=all' settings.
+  if (getWarningAll()) {
+    setWarningCoverages();
+    setWarningLines();
+    setWarningLocations();
+    setWarningRanges();
+  }
+
+  // '--internal=all' settings.
+  if (getInternalAll()) {
+    setInternalCmdline();
+    setInternalID();
+    setInternalIntegrity();
+    setInternalNone();
+    setInternalTag();
+  }
+
+  // '--compare=all' settings.
+  if (getCompareAll()) {
+    setCompareLines();
+    setCompareScopes();
+    setCompareSymbols();
+    setCompareTypes();
+  }
+
+  // Compare the scopes if a request for compare symbols, types, lines.
+  if (getCompareLines() || getCompareSymbols() || getCompareTypes())
+    setCompareScopes();
+
+  // Generic request for comparison.
+  if (getCompareScopes())
+    setCompareExecute();
+
+  // Print any logical line (debug or instruction).
+  if (getPrintInstructions() || getPrintLines())
+    setPrintAnyLine();
+
+  // Print any logical element (line, scope, symbol or type).
+  if (getPrintAnyLine() || getPrintScopes() || getPrintSymbols() ||
+      getPrintTypes())
+    setPrintAnyElement();
+
+  // Print 'sizes' or 'summary'.
+  if (getPrintSizes() && getPrintSummary())
+    setPrintSizesSummary();
+
+  // Generic request for printing.
+  if (getPrintAll() || getPrintAnyElement() || getPrintSizesSummary() ||
+      getPrintWarnings())
+    setPrintExecute();
+
+  // '--reports=all' settings.
+  if (getReportAll()) {
+    setReportChildren();
+    setReportList();
+    setReportParents();
+    setReportView();
+  }
+
+  // '--report=view' is a shortcut for '--report=parents,children'.
+  if (getReportView()) {
+    setReportChildren();
+    setReportParents();
+  }
+
+  // The report will include: Parents or Children.
+  if (getReportParents() || getReportChildren() || getReportView())
+    setReportAnyView();
+
+  // The report will include: List or Parents or Children.
+  if (getReportList() || getReportAnyView())
+    setReportExecute();
+
+  // If a view or element comparison has been requested, the following options
+  // must be set, in order to get a correct compare:
+  // 1) Sort the CUs, to get a fast compare.
+  // 2) Encode template instantiations, so the names include template
+  //    parameter information.
+  // 3) Include qualified types.
+  // 4) Include any inserted abstract references.
+  // 5) For added/missing elements add the '+' or '-' tags.
+  if (getCompareExecute()) {
+    resetPrintExecute();
+    setComparePrint();
+    setSortMode(LVSortMode::Line);
+    setAttributeAdded();
+    setAttributeArgument();
+    setAttributeEncoded();
+    setAttributeInserted();
+    setAttributeMissing();
+    setAttributeQualified();
+  }
+
+  // Enable formatting for printing (indentation, print children).
+  setPrintFormatting();
+
+  // These attributes are dependent on the capture of location information.
+  if (getAttributeCoverage() || getAttributeGaps() || getAttributeRegister())
+    setAttributeLocation();
+
+  // Location information is only relevant when printing symbols.
+  if (!getPrintSymbols()) {
+    resetAttributeCoverage();
+    resetAttributeGaps();
+    resetAttributeLocation();
+    resetAttributeRegister();
+  }
+
+  // Quick check for printing any element source information.
+  if (getAttributeFilename() || getAttributePathname())
+    setAttributeAnySource();
+
+  // Quick check for printing any location information.
+  if (getAttributeLocation() || getAttributeRange())
+    setAttributeAnyLocation();
+
+  if (getAttributeRange() || getPrintAnyLine())
+    setGeneralCollectRanges();
+
+  calculateIndentationSize();
+
+  // Print collected command line options.
+  LLVM_DEBUG({ dump(); });
+}
+
+void LVOptions::calculateIndentationSize() {
+#ifndef NDEBUG
+  if (getInternalID()) {
+    std::string String = hexSquareString(0);
+    IndentationSize += String.length();
+  }
+#endif
+  if (getCompareExecute() && (getAttributeAdded() || getAttributeMissing()))
+    ++IndentationSize;
+  if (getAttributeOffset()) {
+    std::string String = hexSquareString(0);
+    IndentationSize += String.length();
+  }
+  if (getAttributeLevel()) {
+    std::stringstream Stream;
+    Stream.str(std::string());
+    Stream << "[" << std::setfill('0') << std::setw(3) << 0 << "]";
+    IndentationSize += Stream.tellp();
+  }
+  if (getAttributeGlobal())
+    ++IndentationSize;
+}
+
+// Print the current values for all the options, after the dependencies
+// has been resolved.
+void LVOptions::print(raw_ostream &OS) const {
+  // --attribute
+  OS << "** Attributes **\n"
+     << "All:           " << getAttributeAll() << ", "
+     << "Argument:      " << getAttributeArgument() << ", "
+     << "Base:          " << getAttributeBase() << ", "
+     << "Coverage:      " << getAttributeCoverage() << "\n"
+     << "Directories:   " << getAttributeDirectories() << ", "
+     << "Discarded:     " << getAttributeDiscarded() << ", "
+     << "Discriminator: " << getAttributeDiscriminator() << ", "
+     << "Encoded:       " << getAttributeEncoded() << "\n"
+     << "Extended:      " << getAttributeExtended() << ", "
+     << "Filename:      " << getAttributeFilename() << ", "
+     << "Files:         " << getAttributeFiles() << ", "
+     << "Format:        " << getAttributeFormat() << "\n"
+     << "Gaps:          " << getAttributeGaps() << ", "
+     << "Generated:     " << getAttributeGenerated() << ", "
+     << "Global:        " << getAttributeGlobal() << ", "
+     << "Inserted:      " << getAttributeInserted() << "\n"
+     << "Level:         " << getAttributeLevel() << ", "
+     << "Linkage:       " << getAttributeLinkage() << ", "
+     << "Local:         " << getAttributeLocal() << ", "
+     << "Location:      " << getAttributeLocation() << "\n"
+     << "Offset:        " << getAttributeOffset() << ", "
+     << "Pathname:      " << getAttributePathname() << ", "
+     << "Producer:      " << getAttributeProducer() << ", "
+     << "Publics:       " << getAttributePublics() << "\n"
+     << "Qualified:     " << getAttributeQualified() << ", "
+     << "Qualifier:     " << getAttributeQualifier() << ", "
+     << "Range:         " << getAttributeRange() << ", "
+     << "Reference:     " << getAttributeReference() << "\n"
+     << "Register:      " << getAttributeRegister() << ", "
+     << "Standard:      " << getAttributeStandard() << ", "
+     << "Subrange:      " << getAttributeSubrange() << ", "
+     << "System:        " << getAttributeSystem() << "\n"
+     << "Typename:      " << getAttributeTypename() << ", "
+     << "Underlying:    " << getAttributeUnderlying() << ", "
+     << "Zero:          " << getAttributeZero() << "\n";
+  OS << "Added:         " << getAttributeAdded() << ", "
+     << "AnyLocation:   " << getAttributeAnyLocation() << ", "
+     << "AnySource:     " << getAttributeAnySource() << ", "
+     << "Missing:       " << getAttributeMissing() << "\n"
+     << "\n";
+
+  // --compare
+  OS << "** Compare **\n"
+     << "All:     " << getCompareAll() << ", "
+     << "Lines:   " << getCompareLines() << ", "
+     << "Scopes:  " << getCompareScopes() << ", "
+     << "Symbols: " << getCompareSymbols() << ", "
+     << "Types:   " << getCompareTypes() << "\n";
+  OS << "Context: " << getCompareContext() << ", "
+     << "Execute: " << getCompareExecute() << ", "
+     << "Print:   " << getComparePrint() << "\n"
+     << "\n";
+
+  // --print
+  OS << "** Print **\n"
+     << "All:          " << getPrintAll() << ", "
+     << "Elements:     " << getPrintElements() << ", "
+     << "Instructions: " << getPrintInstructions() << ", "
+     << "Lines:        " << getPrintLines() << "\n"
+     << "Scopes:       " << getPrintScopes() << ", "
+     << "Sizes:        " << getPrintSizes() << ", "
+     << "Summary:      " << getPrintSummary() << ", "
+     << "Symbols:      " << getPrintSymbols() << "\n"
+     << "Types:        " << getPrintTypes() << ", "
+     << "Warnings:     " << getPrintWarnings() << "\n";
+  OS << "AnyElemeny:   " << getPrintAnyElement() << ", "
+     << "AnyLine:      " << getPrintAnyLine() << ", "
+     << "Execute:      " << getPrintExecute() << ", "
+     << "Formatting:   " << getPrintFormatting() << "\n"
+     << "Offset:       " << getPrintOffset() << ", "
+     << "SizesSummary: " << getPrintSizesSummary() << "\n"
+     << "\n";
+
+  // --report
+  OS << "** Report **\n"
+     << "All:      " << getReportAll() << ", "
+     << "Children: " << getReportChildren() << ", "
+     << "List:     " << getReportList() << ", "
+     << "Parents:  " << getReportParents() << ", "
+     << "View:     " << getReportView() << "\n";
+  OS << "AnyView:  " << getReportAnyView() << ", "
+     << "Execute:  " << getReportExecute() << "\n"
+     << "\n";
+
+  // --select
+  OS << "** Select **\n"
+     << "IgnoreCase:     " << getSelectIgnoreCase() << ", "
+     << "UseRegex:       " << getSelectUseRegex() << ", "
+     << "Execute:        " << getSelectExecute() << ", "
+     << "GenericKind:    " << getSelectGenericKind() << "\n"
+     << "GenericPattern: " << getSelectGenericPattern() << ", "
+     << "OffsetPattern:  " << getSelectOffsetPattern() << "\n"
+     << "\n";
+
+  // --warning
+  OS << "** Warning **\n"
+     << "All:       " << getWarningAll() << ", "
+     << "Coverage:  " << getWarningCoverages() << ", "
+     << "Lines:     " << getWarningLines() << ", "
+     << "Locations: " << getWarningLocations() << ", "
+     << "Ranges:    " << getWarningRanges() << "\n"
+     << "\n";
+
+  // --internal
+  OS << "** Internal **\n"
+     << "All:       " << Options.getInternalAll() << ", "
+     << "Cmdline:   " << Options.getInternalCmdline() << ", "
+     << "ID:        " << Options.getInternalID() << ", "
+     << "Integrity: " << Options.getInternalIntegrity() << ", "
+     << "None:      " << Options.getInternalNone() << "\n"
+     << "Tag:       " << Options.getInternalTag() << "\n"
+     << "\n";
+}

diff  --git a/llvm/lib/DebugInfo/LogicalView/LLVMBuild.txt b/llvm/lib/DebugInfo/LogicalView/LLVMBuild.txt
new file mode 100644
index 0000000000000..11037f03daef0
--- /dev/null
+++ b/llvm/lib/DebugInfo/LogicalView/LLVMBuild.txt
@@ -0,0 +1,21 @@
+;===- ./lib/DebugInfo/LogicalView/LLVMBuild.txt ----------------*- Conf -*--===;
+;
+; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+; See https://llvm.org/LICENSE.txt for license information.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = DebugInfoLogicalView
+parent = DebugInfo
+required_libraries = Object Support DebugInfoDWARF DebugInfoCodeView DebugInfoPDB

diff  --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt
index a38fb0a2408d4..01e2a6ebf6c72 100644
--- a/llvm/test/CMakeLists.txt
+++ b/llvm/test/CMakeLists.txt
@@ -77,6 +77,7 @@ set(LLVM_TEST_DEPENDS
           llvm-cxxdump
           llvm-cxxfilt
           llvm-cxxmap
+          llvm-debuginfo-analyzer
           llvm-debuginfod-find
           llvm-
diff 
           llvm-dis

diff  --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index c554b9d902fa9..476424fd75df9 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -159,6 +159,7 @@ def get_asan_rtlib():
     'dsymutil', 'lli', 'lli-child-target', 'llvm-ar', 'llvm-as',
     'llvm-addr2line', 'llvm-bcanalyzer', 'llvm-bitcode-strip', 'llvm-config',
     'llvm-cov', 'llvm-cxxdump', 'llvm-cvtres', 'llvm-debuginfod-find', 'llvm-debuginfod',
+    'llvm-debuginfo-analyzer',
     'llvm-
diff ', 'llvm-dis', 'llvm-dwarfdump', 'llvm-dwarfutil', 'llvm-dlltool',
     'llvm-exegesis', 'llvm-extract', 'llvm-isel-fuzzer', 'llvm-ifs',
     'llvm-install-name-tool', 'llvm-jitlink', 'llvm-opt-fuzzer', 'llvm-lib',

diff  --git a/llvm/test/tools/llvm-debuginfo-analyzer/cmdline.test b/llvm/test/tools/llvm-debuginfo-analyzer/cmdline.test
new file mode 100644
index 0000000000000..c9c2dbe9fa3ea
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/cmdline.test
@@ -0,0 +1,221 @@
+RUN: llvm-debuginfo-analyzer --version 2>&1 | FileCheck --check-prefix=VERSION %s
+VERSION: {{ version }}
+
+RUN: llvm-debuginfo-analyzer -h > %t 2>&1
+RUN: FileCheck -input-file=%t %s --check-prefix=HELP --implicit-check-not=out-file
+RUN: llvm-debuginfo-analyzer --help > %t 2>&1
+RUN: FileCheck -input-file=%t %s --check-prefix=HELP --implicit-check-not=out-file
+HELP: OVERVIEW: Printing a logical representation of low-level debug information.
+HELP: USAGE: llvm-debuginfo-analyzer{{[^ ]*}} [options] <input object files or .dSYM bundles>
+HELP: OPTIONS:
+HELP: Generic Options:
+HELP:   --help          - Display available options (--help-hidden for more)
+HELP:   --help-list     - Display list of available options (--help-list-hidden for more)
+HELP:   --version       - Display the version of this program
+HELP: Print Options:
+HELP: These control which elements are printed.
+HELP:   --print=<value> - Element to print.
+HELP:     =all          -   All elements.
+HELP:     =elements     -   Instructions, lines, scopes, symbols and types.
+HELP:     =instructions -   Assembler instructions.
+HELP:     =lines        -   Lines referenced in the debug information.
+HELP:     =scopes       -   A lexical block (Function, Class, etc.).
+HELP:     =sizes        -   Scope contributions to the debug information.
+HELP:     =summary      -   Summary of elements missing/added/matched/printed.
+HELP:     =symbols      -   Symbols (Variable, Members, etc.).
+HELP:     =types        -   Types (Pointer, Reference, etc.).
+HELP:     =warnings     -   Warnings detected.
+HELP: Pass @FILE as argument to read options from FILE.
+
+RUN: llvm-debuginfo-analyzer --help-hidden > %t 2>&1
+RUN: FileCheck -input-file=%t %s --check-prefix=HELP-ALL --implicit-check-not=out-file
+HELP-ALL: OVERVIEW: Printing a logical representation of low-level debug information.
+HELP-ALL: USAGE: llvm-debuginfo-analyzer{{[^ ]*}} [options] <input object files or .dSYM bundles>
+HELP-ALL: OPTIONS:
+HELP-ALL: Attribute Options:
+HELP-ALL: These control extra attributes that are added when the element is printed.
+HELP-ALL:   --attribute=<value>        - Element attributes.
+HELP-ALL:     =all                     -   Include all attributes.
+HELP-ALL:     =argument                -   Template parameters replaced by its arguments.
+HELP-ALL:     =base                    -   Base types (int, bool, etc.).
+HELP-ALL:     =coverage                -   Symbol location coverage.
+HELP-ALL:     =directories             -   Directories referenced in the debug information.
+HELP-ALL:     =discarded               -   Discarded elements by the linker.
+HELP-ALL:     =discriminator           -   Discriminators for inlined function instances.
+HELP-ALL:     =encoded                 -   Template arguments encoded in the template name.
+HELP-ALL:     =extended                -   Advanced attributes alias.
+HELP-ALL:     =filename                -   Filename where the element is defined.
+HELP-ALL:     =files                   -   Files referenced in the debug information.
+HELP-ALL:     =format                  -   Object file format name.
+HELP-ALL:     =gaps                    -   Missing debug location (gaps).
+HELP-ALL:     =generated               -   Compiler generated elements.
+HELP-ALL:     =global                  -   Element referenced across Compile Units.
+HELP-ALL:     =inserted                -   Generated inlined abstract references.
+HELP-ALL:     =level                   -   Lexical scope level (File=0, Compile Unit=1).
+HELP-ALL:     =linkage                 -   Linkage name.
+HELP-ALL:     =local                   -   Element referenced only in the Compile Unit.
+HELP-ALL:     =location                -   Element debug location.
+HELP-ALL:     =offset                  -   Debug information offset.
+HELP-ALL:     =pathname                -   Pathname where the element is defined.
+HELP-ALL:     =producer                -   Toolchain identification name.
+HELP-ALL:     =publics                 -   Function names that are public.
+HELP-ALL:     =qualified               -   The element type include parents in its name.
+HELP-ALL:     =qualifier               -   Line qualifiers (Newstatement, BasicBlock, etc.).
+HELP-ALL:     =range                   -   Debug location ranges.
+HELP-ALL:     =reference               -   Element declaration and definition references.
+HELP-ALL:     =register                -   Processor register names.
+HELP-ALL:     =standard                -   Basic attributes alias.
+HELP-ALL:     =subrange                -   Subrange encoding information for arrays.
+HELP-ALL:     =system                  -   Display PDB's MS system elements.
+HELP-ALL:     =typename                -   Include Parameters in templates.
+HELP-ALL:     =underlying              -   Underlying type for type definitions.
+HELP-ALL:     =zero                    -   Zero line numbers.
+HELP-ALL: Color Options:
+HELP-ALL:   This option category has no options.
+HELP-ALL: Compare Options:
+HELP-ALL: These control the view comparison.
+HELP-ALL:   --compare=<value>          - Elements to compare.
+HELP-ALL:     =all                     -   Compare all elements.
+HELP-ALL:     =lines                   -   Lines.
+HELP-ALL:     =scopes                  -   Scopes.
+HELP-ALL:     =symbols                 -   Symbols.
+HELP-ALL:     =types                   -   Types.
+HELP-ALL:   --compare-context          - Add the view as compare context.
+HELP-ALL: General options:
+HELP-ALL:   This option category has no options.
+HELP-ALL: Generic Options:
+HELP-ALL:   -h                         - Alias for --help
+HELP-ALL:   --help                     - Display available options (--help-hidden for more)
+HELP-ALL:   --help-hidden              - Display all available options
+HELP-ALL:   --help-list                - Display list of available options (--help-list-hidden for more)
+HELP-ALL:   --help-list-hidden         - Display list of all available options
+HELP-ALL:   --print-all-options        - Print all option values after command line parsing
+HELP-ALL:   --print-options            - Print non-default options after command line parsing
+HELP-ALL:   --version                  - Display the version of this program
+HELP-ALL: Internal Options:
+HELP-ALL: Internal traces and extra debugging code.
+HELP-ALL:   --internal=<value>         - Traces to enable.
+HELP-ALL:     =all                     -   Enable all traces.
+HELP-ALL:     =cmdline                 -   Print command line.
+HELP-ALL:     =id                      -   Print unique element ID
+HELP-ALL:     =integrity               -   Check elements integrity.
+HELP-ALL:     =none                    -   Ignore element line number.
+HELP-ALL:     =tag                     -   Debug information tags.
+HELP-ALL: Output Options:
+HELP-ALL: These control the output generated.
+HELP-ALL:   --output=<value>           - Outputs for view.
+HELP-ALL:     =all                     -   All outputs.
+HELP-ALL:     =split                   -   Split the output by Compile Units.
+HELP-ALL:     =text                    -   Use a free form text output.
+HELP-ALL:     =json                    -   Use JSON as the output format.
+HELP-ALL:   --output-file=<filename>   - Redirect output to the specified file.
+HELP-ALL:   --output-folder=<pathname> - Folder name for view splitting.
+HELP-ALL:   --output-level=<N>         - Only print to a depth of N elements.
+HELP-ALL:   --output-sort=<value>      - Primary key when ordering logical view (default: line).
+HELP-ALL:     =kind                    -   Sort by element kind.
+HELP-ALL:     =line                    -   Sort by element line number.
+HELP-ALL:     =name                    -   Sort by element name.
+HELP-ALL:     =offset                  -   Sort by element offset.
+HELP-ALL: Print Options:
+HELP-ALL: These control which elements are printed.
+HELP-ALL:   --print=<value>            - Element to print.
+HELP-ALL:     =all                     -   All elements.
+HELP-ALL:     =elements                -   Instructions, lines, scopes, symbols and types.
+HELP-ALL:     =instructions            -   Assembler instructions.
+HELP-ALL:     =lines                   -   Lines referenced in the debug information.
+HELP-ALL:     =scopes                  -   A lexical block (Function, Class, etc.).
+HELP-ALL:     =sizes                   -   Scope contributions to the debug information.
+HELP-ALL:     =summary                 -   Summary of elements missing/added/matched/printed.
+HELP-ALL:     =symbols                 -   Symbols (Variable, Members, etc.).
+HELP-ALL:     =types                   -   Types (Pointer, Reference, etc.).
+HELP-ALL:     =warnings                -   Warnings detected.
+HELP-ALL: Report Options:
+HELP-ALL: These control how the elements are printed.
+HELP-ALL:   --report=<value>           - Reports layout used for print, compare and select.
+HELP-ALL:     =all                     -   Generate all reports.
+HELP-ALL:     =children                -   Selected elements are displayed in a tree view (Include children)
+HELP-ALL:     =list                    -   Selected elements are displayed in a tabular format.
+HELP-ALL:     =parents                 -   Selected elements are displayed in a tree view. (Include parents)
+HELP-ALL:     =view                    -   Selected elements are displayed in a tree view (Include parents and children.
+HELP-ALL: Select Options:
+HELP-ALL: These control which elements are selected.
+HELP-ALL:   --select=<pattern>         - Search elements matching the given pattern.
+HELP-ALL:   --select-elements=<value>  - Conditions to use when printing elements.
+HELP-ALL:     =Discarded               -   Discarded elements by the linker.
+HELP-ALL:     =Global                  -   Element referenced across Compile Units.
+HELP-ALL:     =Optimized               -   Generated inlined abstract references.
+HELP-ALL:   --select-lines=<value>     - Line kind to use when printing lines.
+HELP-ALL:     =AlwaysStepInto          -   Always Step Into.
+HELP-ALL:     =BasicBlock              -   Basic block.
+HELP-ALL:     =Discriminator           -   Discriminator.
+HELP-ALL:     =EndSequence             -   End sequence.
+HELP-ALL:     =EpilogueBegin.          -   Epilogue begin.
+HELP-ALL:     =LineDebug               -   Debug line.
+HELP-ALL:     =LineAssembler           -   Assembler line.
+HELP-ALL:     =NeverStepInto           -   Never Step Into.
+HELP-ALL:     =NewStatement            -   New statement.
+HELP-ALL:     =PrologueEnd             -   Prologue end.
+HELP-ALL:   --select-nocase            - Ignore case distinctions when searching.
+HELP-ALL:   --select-offsets=<offset>  - Offset element to print.
+HELP-ALL:   --select-regex             - Treat any <pattern> strings as regular expressions when selecting instead of just as an exact string match.
+HELP-ALL:   --select-scopes=<value>    - Scope kind to use when printing scopes.
+HELP-ALL:     =Aggregate               -   Class, Structure or Union.
+HELP-ALL:     =Array                   -   Array.
+HELP-ALL:     =Block                   -   Lexical block.
+HELP-ALL:     =CallSite                -   Call site block.
+HELP-ALL:     =CatchBlock              -   Exception catch block.
+HELP-ALL:     =Class                   -   Class.
+HELP-ALL:     =CompileUnit             -   Compile unit.
+HELP-ALL:     =EntryPoint              -   Function entry point.
+HELP-ALL:     =Enumeration             -   Enumeration.
+HELP-ALL:     =Function                -   Function.
+HELP-ALL:     =FunctionType            -   Function type.
+HELP-ALL:     =InlinedFunction         -   Inlined function.
+HELP-ALL:     =Label                   -   Label.
+HELP-ALL:     =LexicalBlock            -   Lexical block.
+HELP-ALL:     =Namespace               -   Namespace.
+HELP-ALL:     =Root                    -   Root.
+HELP-ALL:     =Structure               -   Structure.
+HELP-ALL:     =Subprogram              -   Subprogram.
+HELP-ALL:     =Template                -   Template.
+HELP-ALL:     =TemplateAlias           -   Template alias.
+HELP-ALL:     =TemplatePack            -   Template pack.
+HELP-ALL:     =TryBlock                -   Exception try block.
+HELP-ALL:     =Union                   -   Union.
+HELP-ALL:   --select-symbols=<value>   - Symbol kind to use when printing symbols.
+HELP-ALL:     =CallSiteParameter       -   Call site parameter.
+HELP-ALL:     =Constant                -   Constant.
+HELP-ALL:     =Inheritance             -   Inheritance.
+HELP-ALL:     =Member                  -   Member.
+HELP-ALL:     =Parameter               -   Parameter.
+HELP-ALL:     =Unspecified             -   Unspecified parameter.
+HELP-ALL:     =Variable                -   Variable.
+HELP-ALL:   --select-types=<value>     - Type kind to use when printing types.
+HELP-ALL:     =Base                    -   Base Type (int, bool, etc.).
+HELP-ALL:     =Const                   -   Constant specifier.
+HELP-ALL:     =Enumerator              -   Enumerator.
+HELP-ALL:     =Import                  -   Import.
+HELP-ALL:     =ImportDeclaration       -   Import declaration.
+HELP-ALL:     =ImportModule            -   Import module.
+HELP-ALL:     =Pointer                 -   Pointer.
+HELP-ALL:     =PointerMember           -   Pointer to member.
+HELP-ALL:     =Reference               -   Reference type.
+HELP-ALL:     =Restrict                -   Restrict specifier.
+HELP-ALL:     =RvalueReference         -   Rvalue reference.
+HELP-ALL:     =Subrange                -   Array subrange.
+HELP-ALL:     =TemplateParam           -   Template Parameter.
+HELP-ALL:     =TemplateTemplateParam   -   Template template parameter.
+HELP-ALL:     =TemplateTypeParam       -   Template type parameter.
+HELP-ALL:     =TemplateValueParam      -   Template value parameter.
+HELP-ALL:     =Typedef                 -   Type definition.
+HELP-ALL:     =Unspecified             -   Unspecified type.
+HELP-ALL:     =Volatile                -   Volatile specifier.
+HELP-ALL: Warning Options:
+HELP-ALL: These control the generated warnings.
+HELP-ALL:   --warning=<value>          - Warnings to generate.
+HELP-ALL:     =all                     -   All warnings.
+HELP-ALL:     =coverages               -   Invalid symbol coverages values.
+HELP-ALL:     =lines                   -   Debug lines that are zero.
+HELP-ALL:     =locations               -   Invalid symbol locations.
+HELP-ALL:     =ranges                  -   Invalid code ranges.
+HELP-ALL: Pass @FILE as argument to read options from FILE.

diff  --git a/llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt b/llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt
new file mode 100644
index 0000000000000..b36f5d7aa2f37
--- /dev/null
+++ b/llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(LLVM_LINK_COMPONENTS
+  AllTargetsDescs
+  AllTargetsInfos
+  AllTargetsDisassemblers
+  BinaryFormat
+  DebugInfoLogicalView
+  DebugInfoCodeView
+  DebugInfoDWARF
+  DebugInfoPDB
+  MC
+  MCDisassembler
+  Object
+  Support
+  )
+
+add_llvm_tool(llvm-debuginfo-analyzer
+  llvm-debuginfo-analyzer.cpp
+  Options.cpp
+  )

diff  --git a/llvm/tools/llvm-debuginfo-analyzer/LLVMBuild.txt b/llvm/tools/llvm-debuginfo-analyzer/LLVMBuild.txt
new file mode 100644
index 0000000000000..2fcd27062688f
--- /dev/null
+++ b/llvm/tools/llvm-debuginfo-analyzer/LLVMBuild.txt
@@ -0,0 +1,21 @@
+;===- ./tools/llvm-debuginfo-analyzer/LLVMBuild.txt ------------*- Conf -*--===;
+;
+; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+; See https://llvm.org/LICENSE.txt for license information.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Tool
+name = llvm-debuginfo-analyzer
+parent = Tools
+required_libraries = DebugInfoLogicalView DebugInfoDWARF DebugInfoCodeView DebugInfoPDB Object

diff  --git a/llvm/tools/llvm-debuginfo-analyzer/Options.cpp b/llvm/tools/llvm-debuginfo-analyzer/Options.cpp
new file mode 100644
index 0000000000000..e5566b3390fd2
--- /dev/null
+++ b/llvm/tools/llvm-debuginfo-analyzer/Options.cpp
@@ -0,0 +1,501 @@
+//===-- options.cpp - Command line options for llvm-debuginfo-analyzer----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This handles the command line options for llvm-debuginfo-analyzer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Options.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVSort.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+using namespace llvm::logicalview;
+using namespace llvm::logicalview::cmdline;
+
+/// @}
+/// Command line options.
+/// @{
+
+OffsetParser::OffsetParser(cl::Option &O) : parser<unsigned long long>(O) {}
+OffsetParser::~OffsetParser() = default;
+
+bool OffsetParser::parse(cl::Option &O, StringRef ArgName, StringRef Arg,
+                         unsigned long long &Val) {
+  char *End;
+  std::string Argument(Arg);
+  Val = strtoull(Argument.c_str(), &End, 0);
+  if (*End)
+    // Print an error message if unrecognized character.
+    return O.error("'" + Arg + "' unrecognized character.");
+  return false;
+}
+
+LVOptions cmdline::ReaderOptions;
+
+//===----------------------------------------------------------------------===//
+// Specific options
+//===----------------------------------------------------------------------===//
+cl::list<std::string>
+    cmdline::InputFilenames(cl::desc("<input object files or .dSYM bundles>"),
+                            cl::Positional, cl::ZeroOrMore);
+
+//===----------------------------------------------------------------------===//
+// '--attribute' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::AttributeCategory("Attribute Options",
+                               "These control extra attributes that are "
+                               "added when the element is printed.");
+
+// --attribute=<value>[,<value>,...]
+cl::list<LVAttributeKind> cmdline::AttributeOptions(
+    "attribute", cl::cat(AttributeCategory), cl::desc("Element attributes."),
+    cl::Hidden, cl::CommaSeparated,
+    values(clEnumValN(LVAttributeKind::All, "all", "Include all attributes."),
+           clEnumValN(LVAttributeKind::Argument, "argument",
+                      "Template parameters replaced by its arguments."),
+           clEnumValN(LVAttributeKind::Base, "base",
+                      "Base types (int, bool, etc.)."),
+           clEnumValN(LVAttributeKind::Coverage, "coverage",
+                      "Symbol location coverage."),
+           clEnumValN(LVAttributeKind::Directories, "directories",
+                      "Directories referenced in the debug information."),
+           clEnumValN(LVAttributeKind::Discarded, "discarded",
+                      "Discarded elements by the linker."),
+           clEnumValN(LVAttributeKind::Discriminator, "discriminator",
+                      "Discriminators for inlined function instances."),
+           clEnumValN(LVAttributeKind::Encoded, "encoded",
+                      "Template arguments encoded in the template name."),
+           clEnumValN(LVAttributeKind::Extended, "extended",
+                      "Advanced attributes alias."),
+           clEnumValN(LVAttributeKind::Filename, "filename",
+                      "Filename where the element is defined."),
+           clEnumValN(LVAttributeKind::Files, "files",
+                      "Files referenced in the debug information."),
+           clEnumValN(LVAttributeKind::Format, "format",
+                      "Object file format name."),
+           clEnumValN(LVAttributeKind::Gaps, "gaps",
+                      "Missing debug location (gaps)."),
+           clEnumValN(LVAttributeKind::Generated, "generated",
+                      "Compiler generated elements."),
+           clEnumValN(LVAttributeKind::Global, "global",
+                      "Element referenced across Compile Units."),
+           clEnumValN(LVAttributeKind::Inserted, "inserted",
+                      "Generated inlined abstract references."),
+           clEnumValN(LVAttributeKind::Level, "level",
+                      "Lexical scope level (File=0, Compile Unit=1)."),
+           clEnumValN(LVAttributeKind::Linkage, "linkage", "Linkage name."),
+           clEnumValN(LVAttributeKind::Local, "local",
+                      "Element referenced only in the Compile Unit."),
+           clEnumValN(LVAttributeKind::Location, "location",
+                      "Element debug location."),
+           clEnumValN(LVAttributeKind::Offset, "offset",
+                      "Debug information offset."),
+           clEnumValN(LVAttributeKind::Pathname, "pathname",
+                      "Pathname where the element is defined."),
+           clEnumValN(LVAttributeKind::Producer, "producer",
+                      "Toolchain identification name."),
+           clEnumValN(LVAttributeKind::Publics, "publics",
+                      "Function names that are public."),
+           clEnumValN(LVAttributeKind::Qualified, "qualified",
+                      "The element type include parents in its name."),
+           clEnumValN(LVAttributeKind::Qualifier, "qualifier",
+                      "Line qualifiers (Newstatement, BasicBlock, etc.)."),
+           clEnumValN(LVAttributeKind::Range, "range",
+                      "Debug location ranges."),
+           clEnumValN(LVAttributeKind::Reference, "reference",
+                      "Element declaration and definition references."),
+           clEnumValN(LVAttributeKind::Register, "register",
+                      "Processor register names."),
+           clEnumValN(LVAttributeKind::Standard, "standard",
+                      "Basic attributes alias."),
+           clEnumValN(LVAttributeKind::Subrange, "subrange",
+                      "Subrange encoding information for arrays."),
+           clEnumValN(LVAttributeKind::System, "system",
+                      "Display PDB's MS system elements."),
+           clEnumValN(LVAttributeKind::Typename, "typename",
+                      "Include Parameters in templates."),
+           clEnumValN(LVAttributeKind::Underlying, "underlying",
+                      "Underlying type for type definitions."),
+           clEnumValN(LVAttributeKind::Zero, "zero", "Zero line numbers.")));
+
+//===----------------------------------------------------------------------===//
+// '--compare' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::CompareCategory("Compare Options",
+                             "These control the view comparison.");
+
+// --compare-context
+static cl::opt<bool, true>
+    CompareContext("compare-context", cl::cat(CompareCategory),
+                   cl::desc("Add the view as compare context."), cl::Hidden,
+                   cl::ZeroOrMore, cl::location(ReaderOptions.Compare.Context),
+                   cl::init(false));
+
+// --compare=<value>[,<value>,...]
+cl::list<LVCompareKind> cmdline::CompareElements(
+    "compare", cl::cat(CompareCategory), cl::desc("Elements to compare."),
+    cl::Hidden, cl::CommaSeparated,
+    values(clEnumValN(LVCompareKind::All, "all", "Compare all elements."),
+           clEnumValN(LVCompareKind::Lines, "lines", "Lines."),
+           clEnumValN(LVCompareKind::Scopes, "scopes", "Scopes."),
+           clEnumValN(LVCompareKind::Symbols, "symbols", "Symbols."),
+           clEnumValN(LVCompareKind::Types, "types", "Types.")));
+
+//===----------------------------------------------------------------------===//
+// '--output' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::OutputCategory("Output Options",
+                            "These control the output generated.");
+
+// --output-file=<filename>
+cl::opt<std::string>
+    cmdline::OutputFilename("output-file", cl::cat(OutputCategory),
+                            cl::desc("Redirect output to the specified file."),
+                            cl::Hidden, cl::value_desc("filename"),
+                            cl::init("-"));
+
+// --output-folder=<path>
+static cl::opt<std::string, true>
+    OutputFolder("output-folder", cl::cat(OutputCategory),
+                 cl::desc("Folder name for view splitting."),
+                 cl::value_desc("pathname"), cl::Hidden, cl::ZeroOrMore,
+                 cl::location(ReaderOptions.Output.Folder));
+
+// --output-level=<level>
+static cl::opt<unsigned, true>
+    OutputLevel("output-level", cl::cat(OutputCategory),
+                cl::desc("Only print to a depth of N elements."),
+                cl::value_desc("N"), cl::Hidden, cl::ZeroOrMore,
+                cl::location(ReaderOptions.Output.Level), cl::init(-1U));
+
+// --ouput=<value>[,<value>,...]
+cl::list<LVOutputKind> cmdline::OutputOptions(
+    "output", cl::cat(OutputCategory), cl::desc("Outputs for view."),
+    cl::Hidden, cl::CommaSeparated,
+    values(clEnumValN(LVOutputKind::All, "all", "All outputs."),
+           clEnumValN(LVOutputKind::Split, "split",
+                      "Split the output by Compile Units."),
+           clEnumValN(LVOutputKind::Text, "text",
+                      "Use a free form text output."),
+           clEnumValN(LVOutputKind::Json, "json",
+                      "Use JSON as the output format.")));
+
+// --output-sort
+static cl::opt<LVSortMode, true> OutputSort(
+    "output-sort", cl::cat(OutputCategory),
+    cl::desc("Primary key when ordering logical view (default: line)."),
+    cl::Hidden, cl::ZeroOrMore,
+    values(clEnumValN(LVSortMode::Kind, "kind", "Sort by element kind."),
+           clEnumValN(LVSortMode::Line, "line", "Sort by element line number."),
+           clEnumValN(LVSortMode::Name, "name", "Sort by element name."),
+           clEnumValN(LVSortMode::Offset, "offset", "Sort by element offset.")),
+    cl::location(ReaderOptions.Output.SortMode), cl::init(LVSortMode::Line));
+
+//===----------------------------------------------------------------------===//
+// '--print' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::PrintCategory("Print Options",
+                           "These control which elements are printed.");
+
+// --print=<value>[,<value>,...]
+cl::list<LVPrintKind> cmdline::PrintOptions(
+    "print", cl::cat(PrintCategory), cl::desc("Element to print."),
+    cl::CommaSeparated,
+    values(clEnumValN(LVPrintKind::All, "all", "All elements."),
+           clEnumValN(LVPrintKind::Elements, "elements",
+                      "Instructions, lines, scopes, symbols and types."),
+           clEnumValN(LVPrintKind::Instructions, "instructions",
+                      "Assembler instructions."),
+           clEnumValN(LVPrintKind::Lines, "lines",
+                      "Lines referenced in the debug information."),
+           clEnumValN(LVPrintKind::Scopes, "scopes",
+                      "A lexical block (Function, Class, etc.)."),
+           clEnumValN(LVPrintKind::Sizes, "sizes",
+                      "Scope contributions to the debug information."),
+           clEnumValN(LVPrintKind::Summary, "summary",
+                      "Summary of elements missing/added/matched/printed."),
+           clEnumValN(LVPrintKind::Symbols, "symbols",
+                      "Symbols (Variable, Members, etc.)."),
+           clEnumValN(LVPrintKind::Types, "types",
+                      "Types (Pointer, Reference, etc.)."),
+           clEnumValN(LVPrintKind::Warnings, "warnings",
+                      "Warnings detected.")));
+
+//===----------------------------------------------------------------------===//
+// '--report' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::ReportCategory("Report Options",
+                            "These control how the elements are printed.");
+
+// --report=<value>[,<value>,...]
+cl::list<LVReportKind> cmdline::ReportOptions(
+    "report", cl::cat(ReportCategory),
+    cl::desc("Reports layout used for print, compare and select."), cl::Hidden,
+    cl::CommaSeparated,
+    values(clEnumValN(LVReportKind::All, "all", "Generate all reports."),
+           clEnumValN(LVReportKind::Children, "children",
+                      "Selected elements are displayed in a tree view "
+                      "(Include children)"),
+           clEnumValN(LVReportKind::List, "list",
+                      "Selected elements are displayed in a tabular format."),
+           clEnumValN(LVReportKind::Parents, "parents",
+                      "Selected elements are displayed in a tree view. "
+                      "(Include parents)"),
+           clEnumValN(LVReportKind::View, "view",
+                      "Selected elements are displayed in a tree view "
+                      "(Include parents and children.")));
+
+//===----------------------------------------------------------------------===//
+// '--select' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::SelectCategory("Select Options",
+                            "These control which elements are selected.");
+
+// --select-nocase
+static cl::opt<bool, true>
+    SelectIgnoreCase("select-nocase", cl::cat(SelectCategory),
+                     cl::desc("Ignore case distinctions when searching."),
+                     cl::Hidden, cl::ZeroOrMore,
+                     cl::location(ReaderOptions.Select.IgnoreCase),
+                     cl::init(false));
+
+// --select-regex
+static cl::opt<bool, true> SelectUseRegex(
+    "select-regex", cl::cat(SelectCategory),
+    cl::desc("Treat any <pattern> strings as regular expressions when "
+             "selecting instead of just as an exact string match."),
+    cl::Hidden, cl::ZeroOrMore, cl::location(ReaderOptions.Select.UseRegex),
+    cl::init(false));
+
+// --select=<pattern>
+cl::list<std::string> cmdline::SelectPatterns(
+    "select", cl::cat(SelectCategory),
+    cl::desc("Search elements matching the given pattern."), cl::Hidden,
+    cl::value_desc("pattern"), cl::CommaSeparated);
+
+// --select-offsets=<value>[,<value>,...]
+OffsetOptionList cmdline::SelectOffsets("select-offsets",
+                                        cl::cat(SelectCategory),
+                                        cl::desc("Offset element to print."),
+                                        cl::Hidden, cl::value_desc("offset"),
+                                        cl::CommaSeparated, cl::ZeroOrMore);
+
+// --select-elements=<value>[,<value>,...]
+cl::list<LVElementKind> cmdline::SelectElements(
+    "select-elements", cl::cat(SelectCategory),
+    cl::desc("Conditions to use when printing elements."), cl::Hidden,
+    cl::CommaSeparated,
+    values(clEnumValN(LVElementKind::Discarded, "Discarded",
+                      "Discarded elements by the linker."),
+           clEnumValN(LVElementKind::Global, "Global",
+                      "Element referenced across Compile Units."),
+           clEnumValN(LVElementKind::Optimized, "Optimized",
+                      "Generated inlined abstract references.")));
+
+// --select-lines=<value>[,<value>,...]
+cl::list<LVLineKind> cmdline::SelectLines(
+    "select-lines", cl::cat(SelectCategory),
+    cl::desc("Line kind to use when printing lines."), cl::Hidden,
+    cl::CommaSeparated,
+    values(
+        clEnumValN(LVLineKind::IsAlwaysStepInto, "AlwaysStepInto",
+                   "Always Step Into."),
+        clEnumValN(LVLineKind::IsBasicBlock, "BasicBlock", "Basic block."),
+        clEnumValN(LVLineKind::IsDiscriminator, "Discriminator",
+                   "Discriminator."),
+        clEnumValN(LVLineKind::IsEndSequence, "EndSequence", "End sequence."),
+        clEnumValN(LVLineKind::IsEpilogueBegin, "EpilogueBegin.",
+                   "Epilogue begin."),
+        clEnumValN(LVLineKind::IsLineDebug, "LineDebug", "Debug line."),
+        clEnumValN(LVLineKind::IsLineAssembler, "LineAssembler",
+                   "Assembler line."),
+        clEnumValN(LVLineKind::IsNeverStepInto, "NeverStepInto",
+                   "Never Step Into."),
+        clEnumValN(LVLineKind::IsNewStatement, "NewStatement",
+                   "New statement."),
+        clEnumValN(LVLineKind::IsPrologueEnd, "PrologueEnd", "Prologue end.")));
+
+// --select-scopes=<value>[,<value>,...]
+cl::list<LVScopeKind> cmdline::SelectScopes(
+    "select-scopes", cl::cat(SelectCategory),
+    cl::desc("Scope kind to use when printing scopes."), cl::Hidden,
+    cl::CommaSeparated,
+    values(
+        clEnumValN(LVScopeKind::IsAggregate, "Aggregate",
+                   "Class, Structure or Union."),
+        clEnumValN(LVScopeKind::IsArray, "Array", "Array."),
+        clEnumValN(LVScopeKind::IsBlock, "Block", "Lexical block."),
+        clEnumValN(LVScopeKind::IsCallSite, "CallSite", "Call site block."),
+        clEnumValN(LVScopeKind::IsCatchBlock, "CatchBlock",
+                   "Exception catch block."),
+        clEnumValN(LVScopeKind::IsClass, "Class", "Class."),
+        clEnumValN(LVScopeKind::IsCompileUnit, "CompileUnit", "Compile unit."),
+        clEnumValN(LVScopeKind::IsEntryPoint, "EntryPoint",
+                   "Function entry point."),
+        clEnumValN(LVScopeKind::IsEnumeration, "Enumeration", "Enumeration."),
+        clEnumValN(LVScopeKind::IsFunction, "Function", "Function."),
+        clEnumValN(LVScopeKind::IsFunctionType, "FunctionType",
+                   "Function type."),
+        clEnumValN(LVScopeKind::IsInlinedFunction, "InlinedFunction",
+                   "Inlined function."),
+        clEnumValN(LVScopeKind::IsLabel, "Label", "Label."),
+        clEnumValN(LVScopeKind::IsLexicalBlock, "LexicalBlock",
+                   "Lexical block."),
+        clEnumValN(LVScopeKind::IsNamespace, "Namespace", "Namespace."),
+        clEnumValN(LVScopeKind::IsRoot, "Root", "Root."),
+        clEnumValN(LVScopeKind::IsStructure, "Structure", "Structure."),
+        clEnumValN(LVScopeKind::IsSubprogram, "Subprogram", "Subprogram."),
+        clEnumValN(LVScopeKind::IsTemplate, "Template", "Template."),
+        clEnumValN(LVScopeKind::IsTemplateAlias, "TemplateAlias",
+                   "Template alias."),
+        clEnumValN(LVScopeKind::IsTemplatePack, "TemplatePack",
+                   "Template pack."),
+        clEnumValN(LVScopeKind::IsTryBlock, "TryBlock", "Exception try block."),
+        clEnumValN(LVScopeKind::IsUnion, "Union", "Union.")));
+
+// --select-symbols=<value>[,<value>,...]
+cl::list<LVSymbolKind> cmdline::SelectSymbols(
+    "select-symbols", cl::cat(SelectCategory),
+    cl::desc("Symbol kind to use when printing symbols."), cl::Hidden,
+    cl::CommaSeparated,
+    values(clEnumValN(LVSymbolKind::IsCallSiteParameter, "CallSiteParameter",
+                      "Call site parameter."),
+           clEnumValN(LVSymbolKind::IsConstant, "Constant", "Constant."),
+           clEnumValN(LVSymbolKind::IsInheritance, "Inheritance",
+                      "Inheritance."),
+           clEnumValN(LVSymbolKind::IsMember, "Member", "Member."),
+           clEnumValN(LVSymbolKind::IsParameter, "Parameter", "Parameter."),
+           clEnumValN(LVSymbolKind::IsUnspecified, "Unspecified",
+                      "Unspecified parameter."),
+           clEnumValN(LVSymbolKind::IsVariable, "Variable", "Variable.")));
+
+// --select-types=<value>[,<value>,...]
+cl::list<LVTypeKind> cmdline::SelectTypes(
+    "select-types", cl::cat(SelectCategory),
+    cl::desc("Type kind to use when printing types."), cl::Hidden,
+    cl::CommaSeparated,
+    values(
+        clEnumValN(LVTypeKind::IsBase, "Base", "Base Type (int, bool, etc.)."),
+        clEnumValN(LVTypeKind::IsConst, "Const", "Constant specifier."),
+        clEnumValN(LVTypeKind::IsEnumerator, "Enumerator", "Enumerator."),
+        clEnumValN(LVTypeKind::IsImport, "Import", "Import."),
+        clEnumValN(LVTypeKind::IsImportDeclaration, "ImportDeclaration",
+                   "Import declaration."),
+        clEnumValN(LVTypeKind::IsImportModule, "ImportModule",
+                   "Import module."),
+        clEnumValN(LVTypeKind::IsPointer, "Pointer", "Pointer."),
+        clEnumValN(LVTypeKind::IsPointerMember, "PointerMember",
+                   "Pointer to member."),
+        clEnumValN(LVTypeKind::IsReference, "Reference", "Reference type."),
+        clEnumValN(LVTypeKind::IsRestrict, "Restrict", "Restrict specifier."),
+        clEnumValN(LVTypeKind::IsRvalueReference, "RvalueReference",
+                   "Rvalue reference."),
+        clEnumValN(LVTypeKind::IsSubrange, "Subrange", "Array subrange."),
+        clEnumValN(LVTypeKind::IsTemplateParam, "TemplateParam",
+                   "Template Parameter."),
+        clEnumValN(LVTypeKind::IsTemplateTemplateParam, "TemplateTemplateParam",
+                   "Template template parameter."),
+        clEnumValN(LVTypeKind::IsTemplateTypeParam, "TemplateTypeParam",
+                   "Template type parameter."),
+        clEnumValN(LVTypeKind::IsTemplateValueParam, "TemplateValueParam",
+                   "Template value parameter."),
+        clEnumValN(LVTypeKind::IsTypedef, "Typedef", "Type definition."),
+        clEnumValN(LVTypeKind::IsUnspecified, "Unspecified",
+                   "Unspecified type."),
+        clEnumValN(LVTypeKind::IsVolatile, "Volatile", "Volatile specifier.")));
+
+//===----------------------------------------------------------------------===//
+// '--warning' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::WarningCategory("Warning Options",
+                             "These control the generated warnings.");
+
+// --warning=<value>[,<value>,...]
+cl::list<LVWarningKind> cmdline::WarningOptions(
+    "warning", cl::cat(WarningCategory), cl::desc("Warnings to generate."),
+    cl::Hidden, cl::CommaSeparated,
+    values(
+        clEnumValN(LVWarningKind::All, "all", "All warnings."),
+        clEnumValN(LVWarningKind::Coverages, "coverages",
+                   "Invalid symbol coverages values."),
+        clEnumValN(LVWarningKind::Lines, "lines", "Debug lines that are zero."),
+        clEnumValN(LVWarningKind::Locations, "locations",
+                   "Invalid symbol locations."),
+        clEnumValN(LVWarningKind::Ranges, "ranges", "Invalid code ranges.")));
+
+//===----------------------------------------------------------------------===//
+// '--internal' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::InternalCategory("Internal Options",
+                              "Internal traces and extra debugging code.");
+
+// --internal=<value>[,<value>,...]
+cl::list<LVInternalKind> cmdline::InternalOptions(
+    "internal", cl::cat(InternalCategory), cl::desc("Traces to enable."),
+    cl::Hidden, cl::CommaSeparated,
+    values(
+        clEnumValN(LVInternalKind::All, "all", "Enable all traces."),
+        clEnumValN(LVInternalKind::Cmdline, "cmdline", "Print command line."),
+        clEnumValN(LVInternalKind::ID, "id", "Print unique element ID"),
+        clEnumValN(LVInternalKind::Integrity, "integrity",
+                   "Check elements integrity."),
+        clEnumValN(LVInternalKind::None, "none", "Ignore element line number."),
+        clEnumValN(LVInternalKind::Tag, "tag", "Debug information tags.")));
+
+/// @}
+
+// Copy local options into a globally accessible data structure.
+void llvm::logicalview::cmdline::propagateOptions() {
+  // Traverse list of options and update the given set (Using case and Regex).
+  auto UpdatePattern = [&](auto &List, auto &Set, bool IgnoreCase,
+                           bool UseRegex) {
+    if (!List.empty())
+      for (std::string &Pattern : List)
+        Set.insert((IgnoreCase && !UseRegex) ? StringRef(Pattern).lower()
+                                             : Pattern);
+  };
+
+  // Handle --select.
+  UpdatePattern(SelectPatterns, ReaderOptions.Select.Generic,
+                ReaderOptions.Select.IgnoreCase, ReaderOptions.Select.UseRegex);
+
+  // Traverse list of options and update the given set.
+  auto UpdateSet = [&](auto &List, auto &Set) {
+    std::copy(List.begin(), List.end(), std::inserter(Set, Set.begin()));
+  };
+
+  // Handle options sets.
+  UpdateSet(AttributeOptions, ReaderOptions.Attribute.Kinds);
+  UpdateSet(PrintOptions, ReaderOptions.Print.Kinds);
+  UpdateSet(OutputOptions, ReaderOptions.Output.Kinds);
+  UpdateSet(ReportOptions, ReaderOptions.Report.Kinds);
+  UpdateSet(WarningOptions, ReaderOptions.Warning.Kinds);
+  UpdateSet(InternalOptions, ReaderOptions.Internal.Kinds);
+
+  UpdateSet(SelectElements, ReaderOptions.Select.Elements);
+  UpdateSet(SelectLines, ReaderOptions.Select.Lines);
+  UpdateSet(SelectScopes, ReaderOptions.Select.Scopes);
+  UpdateSet(SelectSymbols, ReaderOptions.Select.Symbols);
+  UpdateSet(SelectTypes, ReaderOptions.Select.Types);
+  UpdateSet(SelectOffsets, ReaderOptions.Select.Offsets);
+  UpdateSet(CompareElements, ReaderOptions.Compare.Elements);
+
+  // Resolve any options dependencies (ie. --print=all should set other
+  // print options, etc.).
+  ReaderOptions.resolveDependencies();
+}

diff  --git a/llvm/tools/llvm-debuginfo-analyzer/Options.h b/llvm/tools/llvm-debuginfo-analyzer/Options.h
new file mode 100644
index 0000000000000..7f30141f9c7b8
--- /dev/null
+++ b/llvm/tools/llvm-debuginfo-analyzer/Options.h
@@ -0,0 +1,81 @@
+//===-- Options.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines command line options used by llvm-debuginfo-analyzer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef OPTIONS_H
+#define OPTIONS_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
+#include "llvm/Support/CommandLine.h"
+
+namespace llvm {
+namespace logicalview {
+namespace cmdline {
+
+class OffsetParser final : public llvm::cl::parser<unsigned long long> {
+public:
+  OffsetParser(llvm::cl::Option &O);
+  ~OffsetParser() override;
+
+  // Parse an argument representing an offset. Return true on error.
+  // If the prefix is 0, the base is octal, if the prefix is 0x or 0X, the
+  // base is hexadecimal, otherwise the base is decimal.
+  bool parse(llvm::cl::Option &O, StringRef ArgName, StringRef ArgValue,
+             unsigned long long &Val);
+};
+
+typedef llvm::cl::list<unsigned long long, bool, OffsetParser> OffsetOptionList;
+
+extern llvm::cl::OptionCategory AttributeCategory;
+extern llvm::cl::OptionCategory CompareCategory;
+extern llvm::cl::OptionCategory OutputCategory;
+extern llvm::cl::OptionCategory PrintCategory;
+extern llvm::cl::OptionCategory ReportCategory;
+extern llvm::cl::OptionCategory SelectCategory;
+extern llvm::cl::OptionCategory WarningCategory;
+extern llvm::cl::OptionCategory InternalCategory;
+
+extern llvm::cl::list<std::string> InputFilenames;
+extern llvm::cl::opt<std::string> OutputFilename;
+
+extern llvm::cl::list<std::string> SelectPatterns;
+
+extern llvm::cl::list<LVElementKind> SelectElements;
+extern llvm::cl::list<LVLineKind> SelectLines;
+extern llvm::cl::list<LVScopeKind> SelectScopes;
+extern llvm::cl::list<LVSymbolKind> SelectSymbols;
+extern llvm::cl::list<LVTypeKind> SelectTypes;
+extern OffsetOptionList SelectOffsets;
+
+extern llvm::cl::list<LVAttributeKind> AttributeOptions;
+extern llvm::cl::list<LVOutputKind> OutputOptions;
+extern llvm::cl::list<LVPrintKind> PrintOptions;
+extern llvm::cl::list<LVWarningKind> WarningOptions;
+extern llvm::cl::list<LVInternalKind> InternalOptions;
+
+extern llvm::cl::list<LVCompareKind> CompareElements;
+extern llvm::cl::list<LVReportKind> ReportOptions;
+
+extern LVOptions ReaderOptions;
+
+// Perform any additional post parse command line actions. Propagate the
+// values captured by the command line parser, into the generic reader.
+void propagateOptions();
+
+} // namespace cmdline
+} // namespace logicalview
+} // namespace llvm
+
+#endif // OPTIONS_H

diff  --git a/llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp b/llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp
new file mode 100644
index 0000000000000..a651b97f3d7de
--- /dev/null
+++ b/llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp
@@ -0,0 +1,127 @@
+//===-- llvm-debuginfo-analyzer.cpp - LLVM Debug info analysis utility ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This program is a utility that displays the logical view for the debug
+// information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Options.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Support/COM.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
+
+using namespace llvm;
+using namespace logicalview;
+using namespace cmdline;
+
+/// Create formatted StringError object.
+static StringRef ToolName = "llvm-debuginfo-analyzer";
+template <typename... Ts>
+static void error(std::error_code EC, char const *Fmt, const Ts &...Vals) {
+  if (!EC)
+    return;
+  std::string Buffer;
+  raw_string_ostream Stream(Buffer);
+  Stream << format(Fmt, Vals...);
+  WithColor::error(errs(), ToolName) << Stream.str() << "\n";
+  exit(1);
+}
+
+/// If the input path is a .dSYM bundle (as created by the dsymutil tool),
+/// replace it with individual entries for each of the object files inside the
+/// bundle otherwise return the input path.
+static std::vector<std::string> expandBundle(const std::string &InputPath) {
+  std::vector<std::string> BundlePaths;
+  SmallString<256> BundlePath(InputPath);
+  // Normalize input path. This is necessary to accept `bundle.dSYM/`.
+  sys::path::remove_dots(BundlePath);
+  // Manually open up the bundle to avoid introducing additional dependencies.
+  if (sys::fs::is_directory(BundlePath) &&
+      sys::path::extension(BundlePath) == ".dSYM") {
+    std::error_code EC;
+    sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
+    for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd;
+         Dir != DirEnd && !EC; Dir.increment(EC)) {
+      const std::string &Path = Dir->path();
+      sys::fs::file_status Status;
+      EC = sys::fs::status(Path, Status);
+      error(EC, "%s", Path.c_str());
+      switch (Status.type()) {
+      case sys::fs::file_type::regular_file:
+      case sys::fs::file_type::symlink_file:
+      case sys::fs::file_type::type_unknown:
+        BundlePaths.push_back(Path);
+        break;
+      default: /*ignore*/;
+      }
+    }
+  }
+  if (BundlePaths.empty())
+    BundlePaths.push_back(InputPath);
+  return BundlePaths;
+}
+
+int main(int argc, char **argv) {
+  InitLLVM X(argc, argv);
+
+  // Initialize targets and assembly printers/parsers.
+  llvm::InitializeAllTargetInfos();
+  llvm::InitializeAllTargetMCs();
+  InitializeAllDisassemblers();
+
+  llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
+
+  cl::extrahelp HelpResponse(
+      "\nPass @FILE as argument to read options from FILE.\n");
+
+  cl::HideUnrelatedOptions(
+      {&AttributeCategory, &CompareCategory, &InternalCategory, &OutputCategory,
+       &PrintCategory, &ReportCategory, &SelectCategory, &WarningCategory});
+  cl::ParseCommandLineOptions(argc, argv,
+                              "Printing a logical representation of low-level "
+                              "debug information.\n");
+  cl::PrintOptionValues();
+
+  std::error_code EC;
+  ToolOutputFile OutputFile(OutputFilename, EC, sys::fs::OF_None);
+  error(EC, "Unable to open output file %s", OutputFilename.c_str());
+  // Don't remove output file if we exit with an error.
+  OutputFile.keep();
+
+  // Defaults to a.out if no filenames specified.
+  if (InputFilenames.empty())
+    InputFilenames.push_back("a.out");
+
+  // Expand any .dSYM bundles to the individual object files contained therein.
+  std::vector<std::string> Objects;
+  for (const std::string &Filename : InputFilenames) {
+    std::vector<std::string> Objs = expandBundle(Filename);
+    Objects.insert(Objects.end(), Objs.begin(), Objs.end());
+  }
+
+  propagateOptions();
+  ScopedPrinter W(OutputFile.os());
+
+  // Print the command line.
+  if (options().getInternalCmdline()) {
+    raw_ostream &Stream = W.getOStream();
+    Stream << "\nCommand line:\n";
+    for (int Index = 0; Index < argc; ++Index)
+      Stream << "  " << argv[Index] << "\n";
+    Stream << "\n";
+  }
+
+  return EXIT_SUCCESS;
+}

diff  --git a/llvm/unittests/DebugInfo/CMakeLists.txt b/llvm/unittests/DebugInfo/CMakeLists.txt
index 4be8d76473c2e..8e28a90b45beb 100644
--- a/llvm/unittests/DebugInfo/CMakeLists.txt
+++ b/llvm/unittests/DebugInfo/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(CodeView)
 add_subdirectory(DWARF)
 add_subdirectory(GSYM)
+add_subdirectory(LogicalView)
 add_subdirectory(MSF)
 add_subdirectory(PDB)
 add_subdirectory(Symbolizer)

diff  --git a/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt b/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt
new file mode 100644
index 0000000000000..f376c4a397750
--- /dev/null
+++ b/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt
@@ -0,0 +1,10 @@
+set(LLVM_LINK_COMPONENTS
+  DebugInfoLogicalView
+  )
+
+add_llvm_unittest(DebugInfoLogicalViewTests
+  CommandLineOptionsTest.cpp
+  StringPoolTest.cpp
+  )
+
+target_link_libraries(DebugInfoLogicalViewTests PRIVATE LLVMTestingSupport)

diff  --git a/llvm/unittests/DebugInfo/LogicalView/CommandLineOptionsTest.cpp b/llvm/unittests/DebugInfo/LogicalView/CommandLineOptionsTest.cpp
new file mode 100644
index 0000000000000..1d4b48d215cdf
--- /dev/null
+++ b/llvm/unittests/DebugInfo/LogicalView/CommandLineOptionsTest.cpp
@@ -0,0 +1,276 @@
+//===- llvm/unittest/DebugInfo/LogicalView/CommandLineOptionsTest.cpp -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::logicalview;
+
+namespace {
+
+// '--attribute' options.
+TEST(CommandLineOptionsTest, attributeOptions) {
+  auto CheckStandardAttributes = [&](LVOptions &Options, bool Value) {
+    EXPECT_EQ(Options.getAttributeBase(), 1);
+    EXPECT_EQ(Options.getAttributeCoverage(), Value);
+    EXPECT_EQ(Options.getAttributeDirectories(), 1);
+    EXPECT_EQ(Options.getAttributeDiscriminator(), 1);
+    EXPECT_EQ(Options.getAttributeFilename(), 0);
+    EXPECT_EQ(Options.getAttributeFiles(), 1);
+    EXPECT_EQ(Options.getAttributeFormat(), 1);
+    EXPECT_EQ(Options.getAttributeLevel(), 1);
+    EXPECT_EQ(Options.getAttributeProducer(), 1);
+    EXPECT_EQ(Options.getAttributePublics(), 1);
+    EXPECT_EQ(Options.getAttributeRange(), 1);
+    EXPECT_EQ(Options.getAttributeReference(), 1);
+    EXPECT_EQ(Options.getAttributeZero(), 1);
+  };
+
+  auto CheckExtendedAttributes = [&](LVOptions &Options, bool Value) {
+    EXPECT_EQ(Options.getAttributeArgument(), 1);
+    EXPECT_EQ(Options.getAttributeDiscarded(), 1);
+    EXPECT_EQ(Options.getAttributeEncoded(), 1);
+    EXPECT_EQ(Options.getAttributeGaps(), Value);
+    EXPECT_EQ(Options.getAttributeGenerated(), 1);
+    EXPECT_EQ(Options.getAttributeGlobal(), 1);
+    EXPECT_EQ(Options.getAttributeInserted(), 1);
+    EXPECT_EQ(Options.getAttributeLinkage(), 1);
+    EXPECT_EQ(Options.getAttributeLocal(), 1);
+    EXPECT_EQ(Options.getAttributeLocation(), Value);
+    EXPECT_EQ(Options.getAttributeOffset(), 1);
+    EXPECT_EQ(Options.getAttributePathname(), 1);
+    EXPECT_EQ(Options.getAttributeQualified(), 1);
+    EXPECT_EQ(Options.getAttributeQualifier(), 1);
+    EXPECT_EQ(Options.getAttributeRegister(), Value);
+    EXPECT_EQ(Options.getAttributeSubrange(), 1);
+    EXPECT_EQ(Options.getAttributeSystem(), 1);
+    EXPECT_EQ(Options.getAttributeTypename(), 1);
+  };
+
+  // Location information is only relevant when printing symbols.
+  // It means the following attributes are dependent on --print=symbols:
+  // Coverage, gaps, location and register attributes.
+  // '--attribute=pathname' supersedes '--attribute=filename'.
+
+  // Set standard and extended attributes.
+  LVOptions OptionsOne;
+  OptionsOne.setAttributeStandard();
+  OptionsOne.setAttributeExtended();
+  OptionsOne.resolveDependencies();
+  CheckStandardAttributes(OptionsOne, false);
+  CheckExtendedAttributes(OptionsOne, false);
+
+  // Set standard and extended attributes; enable location attributes.
+  LVOptions OptionsTwo;
+  OptionsTwo.setAttributeStandard();
+  OptionsTwo.setAttributeExtended();
+  OptionsTwo.setPrintSymbols();
+  OptionsTwo.resolveDependencies();
+  CheckStandardAttributes(OptionsTwo, true);
+  CheckExtendedAttributes(OptionsTwo, true);
+
+  // Set all attributes.
+  LVOptions OptionsThree;
+  OptionsThree.setAttributeAll();
+  OptionsThree.resolveDependencies();
+  EXPECT_EQ(OptionsThree.getAttributeExtended(), 1);
+  EXPECT_EQ(OptionsThree.getAttributeStandard(), 1);
+
+  // Set filename attribute.
+  LVOptions OptionsFour;
+  OptionsFour.setAttributeFilename();
+  OptionsFour.resolveDependencies();
+  EXPECT_EQ(OptionsFour.getAttributeFilename(), 1);
+  EXPECT_EQ(OptionsFour.getAttributePathname(), 0);
+
+  // Set pathname attribute.
+  OptionsFour.setAttributePathname();
+  OptionsFour.resolveDependencies();
+  EXPECT_EQ(OptionsFour.getAttributeFilename(), 0);
+  EXPECT_EQ(OptionsFour.getAttributePathname(), 1);
+
+  // The location attribute depends on: coverage, gaps or register.
+  LVOptions OptionsFive;
+  OptionsFive.setPrintSymbols();
+  OptionsFive.resetAttributeLocation();
+  OptionsFive.resolveDependencies();
+  EXPECT_EQ(OptionsFive.getAttributeLocation(), 0);
+
+  OptionsFive.resetAttributeLocation();
+  OptionsFive.setAttributeCoverage();
+  OptionsFive.resolveDependencies();
+  EXPECT_EQ(OptionsFive.getAttributeLocation(), 1);
+
+  OptionsFive.resetAttributeLocation();
+  OptionsFive.setAttributeGaps();
+  OptionsFive.resolveDependencies();
+  EXPECT_EQ(OptionsFive.getAttributeLocation(), 1);
+
+  OptionsFive.resetAttributeLocation();
+  OptionsFive.setAttributeRegister();
+  OptionsFive.resolveDependencies();
+  EXPECT_EQ(OptionsFive.getAttributeLocation(), 1);
+}
+
+// '--compare' options.
+TEST(CommandLineOptionsTest, compareOptions) {
+  LVOptions OptionsOne;
+  OptionsOne.setCompareAll();
+  OptionsOne.resolveDependencies();
+  EXPECT_EQ(OptionsOne.getCompareLines(), 1);
+  EXPECT_EQ(OptionsOne.getCompareScopes(), 1);
+  EXPECT_EQ(OptionsOne.getCompareSymbols(), 1);
+  EXPECT_EQ(OptionsOne.getCompareTypes(), 1);
+
+  // The compare scopes attribute depends on: symbols, types or lines.
+  LVOptions OptionsTwo;
+  OptionsTwo.resetCompareScopes();
+  OptionsTwo.resolveDependencies();
+  EXPECT_EQ(OptionsTwo.getCompareScopes(), 0);
+
+  OptionsTwo.resetCompareScopes();
+  OptionsTwo.setCompareLines();
+  OptionsTwo.resolveDependencies();
+  EXPECT_EQ(OptionsTwo.getCompareScopes(), 1);
+
+  OptionsTwo.resetCompareScopes();
+  OptionsTwo.setCompareSymbols();
+  OptionsTwo.resolveDependencies();
+  EXPECT_EQ(OptionsTwo.getCompareScopes(), 1);
+
+  OptionsTwo.resetCompareScopes();
+  OptionsTwo.setCompareTypes();
+  OptionsTwo.resolveDependencies();
+  EXPECT_EQ(OptionsTwo.getCompareScopes(), 1);
+
+  // The compare option, set/reset other attributes.
+  LVOptions OptionsThree;
+  OptionsThree.setCompareAll();
+  OptionsThree.resolveDependencies();
+  EXPECT_EQ(OptionsThree.getAttributeArgument(), 1);
+  EXPECT_EQ(OptionsThree.getAttributeEncoded(), 1);
+  EXPECT_EQ(OptionsThree.getAttributeInserted(), 1);
+  EXPECT_EQ(OptionsThree.getAttributeMissing(), 1);
+  EXPECT_EQ(OptionsThree.getAttributeQualified(), 1);
+}
+
+// '--internal' options.
+TEST(CommandLineOptionsTest, internalOptions) {
+  LVOptions OptionsOne;
+  OptionsOne.setInternalAll();
+  OptionsOne.resolveDependencies();
+  EXPECT_EQ(OptionsOne.getInternalCmdline(), 1);
+  EXPECT_EQ(OptionsOne.getInternalID(), 1);
+  EXPECT_EQ(OptionsOne.getInternalIntegrity(), 1);
+  EXPECT_EQ(OptionsOne.getInternalNone(), 1);
+  EXPECT_EQ(OptionsOne.getInternalTag(), 1);
+}
+
+// '--output' options.
+TEST(CommandLineOptionsTest, outputOptions) {
+  LVOptions OptionsOne;
+  OptionsOne.setOutputAll();
+  OptionsOne.resolveDependencies();
+  EXPECT_EQ(OptionsOne.getOutputJson(), 1);
+  EXPECT_EQ(OptionsOne.getOutputSplit(), 1);
+  EXPECT_EQ(OptionsOne.getOutputText(), 1);
+
+  // The pathname attribute is set with split output.
+  LVOptions OptionsTwo;
+  OptionsTwo.resetAttributePathname();
+  OptionsTwo.setOutputSplit();
+  OptionsTwo.resolveDependencies();
+  EXPECT_EQ(OptionsTwo.getAttributePathname(), 1);
+
+  // Setting an output folder, it sets split option.
+  LVOptions OptionsThree;
+  OptionsThree.resolveDependencies();
+  EXPECT_EQ(OptionsThree.getOutputSplit(), 0);
+
+  OptionsThree.setOutputFolder("folder-name");
+  OptionsThree.resolveDependencies();
+  EXPECT_EQ(OptionsThree.getOutputSplit(), 1);
+  EXPECT_STREQ(OptionsThree.getOutputFolder().c_str(), "folder-name");
+
+  // Assume '--output=text' as default.
+  LVOptions OptionsFour;
+  OptionsFour.resolveDependencies();
+  EXPECT_EQ(OptionsFour.getOutputText(), 1);
+}
+
+// '--print' options.
+TEST(CommandLineOptionsTest, printOptions) {
+  LVOptions OptionsOne;
+  OptionsOne.setPrintAll();
+  OptionsOne.resolveDependencies();
+  EXPECT_EQ(OptionsOne.getPrintInstructions(), 1);
+  EXPECT_EQ(OptionsOne.getPrintLines(), 1);
+  EXPECT_EQ(OptionsOne.getPrintScopes(), 1);
+  EXPECT_EQ(OptionsOne.getPrintSizes(), 1);
+  EXPECT_EQ(OptionsOne.getPrintSymbols(), 1);
+  EXPECT_EQ(OptionsOne.getPrintSummary(), 1);
+  EXPECT_EQ(OptionsOne.getPrintTypes(), 1);
+  EXPECT_EQ(OptionsOne.getPrintWarnings(), 1);
+
+  // '--print=elements' is a shortcut for:
+  // '--print=instructions,lines,scopes,symbols,types'.
+  LVOptions OptionsTwo;
+  OptionsTwo.setPrintElements();
+  OptionsTwo.resolveDependencies();
+  EXPECT_EQ(OptionsTwo.getPrintInstructions(), 1);
+  EXPECT_EQ(OptionsTwo.getPrintLines(), 1);
+  EXPECT_EQ(OptionsTwo.getPrintScopes(), 1);
+  EXPECT_EQ(OptionsTwo.getPrintSizes(), 0);
+  EXPECT_EQ(OptionsTwo.getPrintSymbols(), 1);
+  EXPECT_EQ(OptionsTwo.getPrintSummary(), 0);
+  EXPECT_EQ(OptionsTwo.getPrintTypes(), 1);
+  EXPECT_EQ(OptionsTwo.getPrintWarnings(), 0);
+}
+
+// '--report' options.
+TEST(CommandLineOptionsTest, reportOptions) {
+  LVOptions OptionsOne;
+  OptionsOne.setReportAll();
+  OptionsOne.resolveDependencies();
+  EXPECT_EQ(OptionsOne.getReportChildren(), 1);
+  EXPECT_EQ(OptionsOne.getReportList(), 1);
+  EXPECT_EQ(OptionsOne.getReportParents(), 1);
+  EXPECT_EQ(OptionsOne.getReportView(), 1);
+
+  // '--report=view' is a shortcut for '--report=parents,children'.
+  LVOptions OptionsTwo;
+  OptionsTwo.setReportView();
+  OptionsTwo.resolveDependencies();
+  EXPECT_EQ(OptionsTwo.getReportChildren(), 1);
+  EXPECT_EQ(OptionsTwo.getReportParents(), 1);
+}
+
+// '--select' options.
+TEST(CommandLineOptionsTest, selectOptions) {
+  LVOptions OptionsOne;
+  OptionsOne.setSelectIgnoreCase();
+  OptionsOne.setSelectUseRegex();
+  OptionsOne.resolveDependencies();
+  EXPECT_EQ(OptionsOne.getSelectIgnoreCase(), 1);
+  EXPECT_EQ(OptionsOne.getSelectUseRegex(), 1);
+}
+
+// '--warning' options.
+TEST(CommandLineOptionsTest, warningOptions) {
+  LVOptions OptionsOne;
+  OptionsOne.setWarningAll();
+  OptionsOne.resolveDependencies();
+  EXPECT_EQ(OptionsOne.getWarningCoverages(), 1);
+  EXPECT_EQ(OptionsOne.getWarningLines(), 1);
+  EXPECT_EQ(OptionsOne.getWarningLocations(), 1);
+  EXPECT_EQ(OptionsOne.getWarningRanges(), 1);
+}
+
+} // namespace

diff  --git a/llvm/unittests/DebugInfo/LogicalView/StringPoolTest.cpp b/llvm/unittests/DebugInfo/LogicalView/StringPoolTest.cpp
new file mode 100644
index 0000000000000..27ff449c98e64
--- /dev/null
+++ b/llvm/unittests/DebugInfo/LogicalView/StringPoolTest.cpp
@@ -0,0 +1,60 @@
+//===- llvm/unittest/DebugInfo/LogicalView/StringPoolTest.cpp -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/LogicalView/Core/LVStringPool.h"
+#include <vector>
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::logicalview;
+
+namespace {
+
+TEST(StringPoolTest, AddStrings) {
+  LVStringPool PoolInstance;
+  EXPECT_EQ(0u, PoolInstance.getSize());
+
+  // Get indexes for the initial strings.
+  EXPECT_EQ(1u, PoolInstance.getIndex("one"));
+  EXPECT_EQ(2u, PoolInstance.getIndex("two"));
+  EXPECT_EQ(3u, PoolInstance.getIndex("three"));
+  EXPECT_EQ(4u, PoolInstance.getIndex("four"));
+  EXPECT_EQ(5u, PoolInstance.getIndex("five"));
+  EXPECT_EQ(5u, PoolInstance.getSize());
+
+  // Verify the string returned by the given index.
+  EXPECT_EQ("one", PoolInstance.getString(1));
+  EXPECT_EQ("two", PoolInstance.getString(2));
+  EXPECT_EQ("three", PoolInstance.getString(3));
+  EXPECT_EQ("four", PoolInstance.getString(4));
+  EXPECT_EQ("five", PoolInstance.getString(5));
+  EXPECT_EQ(5u, PoolInstance.getSize());
+
+  // Get indexes for the same initial strings.
+  EXPECT_EQ(5u, PoolInstance.getIndex("five"));
+  EXPECT_EQ(4u, PoolInstance.getIndex("four"));
+  EXPECT_EQ(3u, PoolInstance.getIndex("three"));
+  EXPECT_EQ(2u, PoolInstance.getIndex("two"));
+  EXPECT_EQ(1u, PoolInstance.getIndex("one"));
+  EXPECT_EQ(5u, PoolInstance.getSize());
+
+  // Empty string gets the index zero.
+  EXPECT_EQ(0u, PoolInstance.getIndex(""));
+  EXPECT_EQ(5u, PoolInstance.getSize());
+
+  // Empty string for invalid index.
+  EXPECT_EQ("", PoolInstance.getString(620));
+
+  // Lookup for strings
+  EXPECT_EQ(5u, PoolInstance.findIndex("five"));
+  EXPECT_TRUE(PoolInstance.isValidIndex(PoolInstance.findIndex("five")));
+  EXPECT_FALSE(PoolInstance.isValidIndex(PoolInstance.findIndex("FIVE")));
+}
+
+} // namespace


        


More information about the llvm-commits mailing list