//===-- LVScope.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 LVScope class.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
#include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"
#include "llvm/DebugInfo/LogicalView/Core/LVRange.h"
#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
#include "llvm/DebugInfo/LogicalView/Core/LVType.h"

using namespace llvm;
using namespace llvm::logicalview;

#define DEBUG_TYPE "Scope"

namespace {
const char *const KindArray = "Array";
const char *const KindBlock = "Block";
const char *const KindCallSite = "CallSite";
const char *const KindClass = "Class";
const char *const KindCompileUnit = "CompileUnit";
const char *const KindEnumeration = "Enumeration";
const char *const KindFile = "File";
const char *const KindFunction = "Function";
const char *const KindInlinedFunction = "InlinedFunction";
const char *const KindNamespace = "Namespace";
const char *const KindStruct = "Struct";
const char *const KindTemplateAlias = "TemplateAlias";
const char *const KindTemplatePack = "TemplatePack";
const char *const KindUndefined = "Undefined";
const char *const KindUnion = "Union";
} // end anonymous namespace

//===----------------------------------------------------------------------===//
// DWARF lexical block, such as: namespace, function, compile unit, module, etc.
//===----------------------------------------------------------------------===//
LVScope::~LVScope() {
  delete Types;
  delete Symbols;
  delete Scopes;
  delete Lines;
  delete Ranges;
  delete Children;
}

// Return a string representation for the scope kind.
const char *LVScope::kind() const {
  const char *Kind = KindUndefined;
  if (getIsArray())
    Kind = KindArray;
  else if (getIsBlock())
    Kind = KindBlock;
  else if (getIsCallSite())
    Kind = KindCallSite;
  else if (getIsCompileUnit())
    Kind = KindCompileUnit;
  else if (getIsEnumeration())
    Kind = KindEnumeration;
  else if (getIsInlinedFunction())
    Kind = KindInlinedFunction;
  else if (getIsNamespace())
    Kind = KindNamespace;
  else if (getIsTemplatePack())
    Kind = KindTemplatePack;
  else if (getIsRoot())
    Kind = KindFile;
  else if (getIsTemplateAlias())
    Kind = KindTemplateAlias;
  else if (getIsClass())
    Kind = KindClass;
  else if (getIsFunction())
    Kind = KindFunction;
  else if (getIsStructure())
    Kind = KindStruct;
  else if (getIsUnion())
    Kind = KindUnion;
  return Kind;
}

LVScopeDispatch LVScope::Dispatch = {
    {LVScopeKind::IsAggregate, &LVScope::getIsAggregate},
    {LVScopeKind::IsArray, &LVScope::getIsArray},
    {LVScopeKind::IsBlock, &LVScope::getIsBlock},
    {LVScopeKind::IsCallSite, &LVScope::getIsCallSite},
    {LVScopeKind::IsCatchBlock, &LVScope::getIsCatchBlock},
    {LVScopeKind::IsClass, &LVScope::getIsClass},
    {LVScopeKind::IsCompileUnit, &LVScope::getIsCompileUnit},
    {LVScopeKind::IsEntryPoint, &LVScope::getIsEntryPoint},
    {LVScopeKind::IsEnumeration, &LVScope::getIsEnumeration},
    {LVScopeKind::IsFunction, &LVScope::getIsFunction},
    {LVScopeKind::IsFunctionType, &LVScope::getIsFunctionType},
    {LVScopeKind::IsInlinedFunction, &LVScope::getIsInlinedFunction},
    {LVScopeKind::IsLabel, &LVScope::getIsLabel},
    {LVScopeKind::IsLexicalBlock, &LVScope::getIsLexicalBlock},
    {LVScopeKind::IsNamespace, &LVScope::getIsNamespace},
    {LVScopeKind::IsRoot, &LVScope::getIsRoot},
    {LVScopeKind::IsStructure, &LVScope::getIsStructure},
    {LVScopeKind::IsTemplate, &LVScope::getIsTemplate},
    {LVScopeKind::IsTemplateAlias, &LVScope::getIsTemplateAlias},
    {LVScopeKind::IsTemplatePack, &LVScope::getIsTemplatePack},
    {LVScopeKind::IsTryBlock, &LVScope::getIsTryBlock},
    {LVScopeKind::IsUnion, &LVScope::getIsUnion}};

void LVScope::addToChildren(LVElement *Element) {
  if (!Children)
    Children = new LVElements();
  Children->push_back(Element);
}

void LVScope::addElement(LVElement *Element) {
  assert(Element && "Invalid element.");
  if (Element->getIsType())
    addElement(static_cast<LVType *>(Element));
  else if (Element->getIsScope())
    addElement(static_cast<LVScope *>(Element));
  else if (Element->getIsSymbol())
    addElement(static_cast<LVSymbol *>(Element));
  else if (Element->getIsLine())
    addElement(static_cast<LVLine *>(Element));
  else
    llvm_unreachable("Invalid Element.");
}

// Adds the line info item to the ones stored in the scope.
void LVScope::addElement(LVLine *Line) {
  assert(Line && "Invalid line.");
  assert(!Line->getParent() && "Line already inserted");
  if (!Lines)
    Lines = new LVAutoLines();

  // Add it to parent.
  Lines->push_back(Line);
  Line->setParent(this);

  // Notify the reader about the new element being added.
  getReaderCompileUnit()->addedElement(Line);

  // All logical elements added to the children, are sorted by any of the
  // following criterias: offset, name, line number, kind.
  // Do not add the line records to the children, as they represent the
  // logical view for the text section and any sorting will not preserve
  // the original sequence.

  // Indicate that this tree branch has lines.
  traverseParents(&LVScope::getHasLines, &LVScope::setHasLines);
}

// Add a location.
void LVScope::addObject(LVLocation *Location) {
  assert(Location && "Invalid location.");
  assert(!Location->getParent() && "Location already inserted");
  if (!Ranges)
    Ranges = new LVAutoLocations();

  // Add it to parent.
  Location->setParent(this);
  Location->setOffset(getOffset());

  Ranges->push_back(Location);
  setHasRanges();
}

// Adds the scope to the child scopes and sets the parent in the child.
void LVScope::addElement(LVScope *Scope) {
  assert(Scope && "Invalid scope.");
  assert(!Scope->getParent() && "Scope already inserted");
  if (!Scopes)
    Scopes = new LVAutoScopes();

  // Add it to parent.
  Scopes->push_back(Scope);
  addToChildren(Scope);
  Scope->setParent(this);

  // Notify the reader about the new element being added.
  getReaderCompileUnit()->addedElement(Scope);

  // If the element is a global reference, mark its parent as having global
  // references; that information is used, to print only those branches
  // with global references.
  if (Scope->getIsGlobalReference())
    traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);
  else
    traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);

  // Indicate that this tree branch has scopes.
  traverseParents(&LVScope::getHasScopes, &LVScope::setHasScopes);
}

// Adds a symbol to the ones stored in the scope.
void LVScope::addElement(LVSymbol *Symbol) {
  assert(Symbol && "Invalid symbol.");
  assert(!Symbol->getParent() && "Symbol already inserted");
  if (!Symbols)
    Symbols = new LVAutoSymbols();

  // Add it to parent.
  Symbols->push_back(Symbol);
  addToChildren(Symbol);
  Symbol->setParent(this);

  // Notify the reader about the new element being added.
  getReaderCompileUnit()->addedElement(Symbol);

  // If the element is a global reference, mark its parent as having global
  // references; that information is used, to print only those branches
  // with global references.
  if (Symbol->getIsGlobalReference())
    traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);
  else
    traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);

  // Indicate that this tree branch has symbols.
  traverseParents(&LVScope::getHasSymbols, &LVScope::setHasSymbols);
}

// Adds a type to the ones stored in the scope.
void LVScope::addElement(LVType *Type) {
  assert(Type && "Invalid type.");
  assert(!Type->getParent() && "Type already inserted");
  if (!Types)
    Types = new LVAutoTypes();

  // Add it to parent.
  Types->push_back(Type);
  addToChildren(Type);
  Type->setParent(this);

  // Notify the reader about the new element being added.
  getReaderCompileUnit()->addedElement(Type);

  // If the element is a global reference, mark its parent as having global
  // references; that information is used, to print only those branches
  // with global references.
  if (Type->getIsGlobalReference())
    traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);
  else
    traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);

  // Indicate that this tree branch has types.
  traverseParents(&LVScope::getHasTypes, &LVScope::setHasTypes);
}

// Add a pair of ranges.
void LVScope::addObject(LVAddress LowerAddress, LVAddress UpperAddress) {
  // Pack the ranges into a Location object.
  LVLocation *Location = new LVLocation();
  Location->setLowerAddress(LowerAddress);
  Location->setUpperAddress(UpperAddress);
  Location->setIsAddressRange();

  addObject(Location);
}

bool LVScope::removeElement(LVElement *Element) {
  auto Predicate = [Element](LVElement *Item) -> bool {
    return Item == Element;
  };
  auto RemoveElement = [Element, Predicate](auto &Container) -> bool {
    auto Iter = std::remove_if(Container->begin(), Container->end(), Predicate);
    if (Iter != Container->end()) {
      Container->erase(Iter, Container->end());
      Element->resetParent();
      return true;
    }
    return false;
  };

  // As 'children' contains only (scopes, symbols and types), check if the
  // element we are deleting is a line.
  if (Element->getIsLine())
    return RemoveElement(Lines);

  if (RemoveElement(Children)) {
    if (Element->getIsSymbol())
      return RemoveElement(Symbols);
    if (Element->getIsType())
      return RemoveElement(Types);
    if (Element->getIsScope())
      return RemoveElement(Scopes);
    llvm_unreachable("Invalid element.");
  }

  return false;
}

void LVScope::addMissingElements(LVScope *Reference) {
  setAddedMissing();
  if (!Reference)
    return;

  // Get abstract symbols for the given scope reference.
  const LVSymbols *ReferenceSymbols = Reference->getSymbols();
  if (!ReferenceSymbols)
    return;

  LVSymbols References;
  References.append(ReferenceSymbols->begin(), ReferenceSymbols->end());

  auto RemoveSymbol = [&](LVSymbols &Symbols, LVSymbol *Symbol) {
    LVSymbols::iterator Iter = std::remove_if(
        Symbols.begin(), Symbols.end(),
        [Symbol](LVSymbol *Item) -> bool { return Item == Symbol; });
    if (Iter != Symbols.end())
      Symbols.erase(Iter, Symbols.end());
  };

  // Erase abstract symbols already in this scope from the collection of
  // symbols in the referenced scope.
  if (getSymbols())
    for (const LVSymbol *Symbol : *getSymbols())
      if (Symbol->getHasReferenceAbstract())
        RemoveSymbol(References, Symbol->getReference());

  // If we have elements left in 'References', those are the elements that
  // need to be inserted in the current scope.
  if (References.size()) {
    LLVM_DEBUG({
      dbgs() << "Insert Missing Inlined Elements\n"
             << "Offset = " << hexSquareString(getOffset()) << " "
             << "Abstract = " << hexSquareString(Reference->getOffset())
             << "\n";
    });
    for (LVSymbol *Reference : References) {
      LLVM_DEBUG({
        dbgs() << "Missing Offset = " << hexSquareString(Reference->getOffset())
               << "\n";
      });
      // We can't clone the abstract origin reference, as it contain extra
      // information that is incorrect for the element to be inserted.
      // As the symbol being added does not exist in the debug section,
      // use its parent scope offset, to indicate its DIE location.
      LVSymbol *Symbol = new LVSymbol();
      addElement(Symbol);
      Symbol->setOffset(getOffset());
      Symbol->setIsOptimized();
      Symbol->setReference(Reference);

      // The symbol can be a constant, parameter or variable.
      if (Reference->getIsConstant())
        Symbol->setIsConstant();
      else if (Reference->getIsParameter())
        Symbol->setIsParameter();
      else if (Reference->getIsVariable())
        Symbol->setIsVariable();
      else
        llvm_unreachable("Invalid symbol kind.");
    }
  }
}

void LVScope::updateLevel(LVScope *Parent, bool Moved) {
  // Update the level for the element itself and all its children, using the
  // given scope parent as reference.
  setLevel(Parent->getLevel() + 1);

  // Update the children.
  if (Children)
    for (LVElement *Element : *Children)
      Element->updateLevel(this, Moved);

  // Update any lines.
  if (Lines)
    for (LVLine *Line : *Lines)
      Line->updateLevel(this, Moved);
}

void LVScope::resolve() {
  if (getIsResolved())
    return;

  // Resolve the element itself.
  LVElement::resolve();

  // Resolve the children.
  if (Children)
    for (LVElement *Element : *Children) {
      if (getIsGlobalReference())
        // If the scope is a global reference, mark all its children as well.
        Element->setIsGlobalReference();
      Element->resolve();
    }
}

void LVScope::resolveName() {
  if (getIsResolvedName())
    return;
  setIsResolvedName();

  // If the scope is a template, resolve the template parameters and get
  // the name for the template with the encoded arguments.
  if (getIsTemplate())
    resolveTemplate();
  else {
    if (LVElement *BaseType = getType()) {
      BaseType->resolveName();
      resolveFullname(BaseType);
    }
  }

  // In the case of unnamed scopes, try to generate a name for it, using
  // the parents name and the line information. In the case of compiler
  // generated functions, use its linkage name if is available.
  if (!isNamed()) {
    if (getIsArtificial())
      setName(getLinkageName());
    else
      generateName();
  }

  LVElement::resolveName();

  // Resolve any given pattern.
  patterns().resolvePatternMatch(this);
}

void LVScope::resolveReferences() {
  // The scopes can have the following references to other elements:
  //   A type:
  //     DW_AT_type             ->  Type or Scope
  //     DW_AT_import           ->  Type
  //   A Reference:
  //     DW_AT_specification    ->  Scope
  //     DW_AT_abstract_origin  ->  Scope
  //     DW_AT_extension        ->  Scope

  // Resolve any referenced scope.
  LVScope *Reference = getReference();
  if (Reference) {
    Reference->resolve();
    // Recursively resolve the scope names.
    resolveReferencesChain();
  }

  // Set the file/line information using the Debug Information entry.
  setFile(Reference);

  // Resolve any referenced type or scope.
  if (LVElement *Element = getType())
    Element->resolve();
}

void LVScope::resolveElements() {
  // The current element represents the Root. Traverse each Compile Unit.
  if (!Scopes)
    return;

  for (LVScope *Scope : *Scopes) {
    LVScopeCompileUnit *CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);
    getReader().setCompileUnit(CompileUnit);
    CompileUnit->resolve();
    // Propagate any matching information into the scopes tree.
    CompileUnit->propagatePatternMatch();
  }
}

StringRef LVScope::resolveReferencesChain() {
  // If the scope has a DW_AT_specification or DW_AT_abstract_origin,
  // follow the chain to resolve the name from those references.
  if (getHasReference() && !isNamed())
    setName(getReference()->resolveReferencesChain());

  return getName();
}

// Get template parameter types.
bool LVScope::getTemplateParameterTypes(LVTypes &Params) {
  // Traverse the scope types and populate the given container with those
  // types that are template parameters; that container will be used by
  // 'encodeTemplateArguments' to resolve them.
  if (const LVTypes *Types = getTypes())
    for (LVType *Type : *Types)
      if (Type->getIsTemplateParam()) {
        Type->resolve();
        Params.push_back(Type);
      }

  return !Params.empty();
}

// Resolve the template parameters/arguments relationship.
void LVScope::resolveTemplate() {
  if (getIsTemplateResolved())
    return;
  setIsTemplateResolved();

  // Check if we need to encode the template arguments.
  if (options().getAttributeEncoded()) {
    LVTypes Params;
    if (getTemplateParameterTypes(Params)) {
      std::string EncodedArgs;
      // Encode the arguments as part of the template name and update the
      // template name, to reflect the encoded parameters.
      encodeTemplateArguments(EncodedArgs, &Params);
      setEncodedArgs(EncodedArgs);
    }
  }
}

// Get the qualified name for the template.
void LVScope::getQualifiedName(std::string &QualifiedName) const {
  if (getIsRoot() || getIsCompileUnit())
    return;

  if (LVScope *Parent = getParentScope())
    Parent->getQualifiedName(QualifiedName);
  if (!QualifiedName.empty())
    QualifiedName.append("::");
  QualifiedName.append(std::string(getName()));
}

// Encode the template arguments as part of the template name.
void LVScope::encodeTemplateArguments(std::string &Name) const {
  // Qualify only when we are expanding parameters that are template
  // instances; the debugger will assume the current scope symbol as
  // the qualifying tag for the symbol being generated, which gives:
  //   namespace std {
  //     ...
  //     set<float,std::less<float>,std::allocator<float>>
  //     ...
  //   }
  // The 'set' symbol is assumed to have the qualified tag 'std'.

  // We are resolving a template parameter which is another template. If
  // it is already resolved, just get the qualified name and return.
  std::string BaseName;
  getQualifiedName(BaseName);
  if (getIsTemplateResolved())
    Name.append(BaseName);
}

void LVScope::encodeTemplateArguments(std::string &Name,
                                      const LVTypes *Types) const {
  // The encoded string will start with the scope name.
  Name.append("<");

  // The list of types are the template parameters.
  if (Types) {
    bool AddComma = false;
    for (const LVType *Type : *Types) {
      if (AddComma)
        Name.append(", ");
      Type->encodeTemplateArgument(Name);
      AddComma = true;
    }
  }

  Name.append(">");
}

bool LVScope::resolvePrinting() const {
  // The warnings collected during the scope creation as per compile unit.
  // If there is a request for printing warnings, always print its associate
  // Compile Unit.
  if (options().getPrintWarnings() && (getIsRoot() || getIsCompileUnit()))
    return true;

  // In selection mode, always print the root scope regardless of the
  // number of matched elements. If no matches, the root by itself will
  // indicate no matches.
  if (options().getSelectExecute()) {
    return getIsRoot() || getIsCompileUnit() || getHasPattern();
  }

  bool Globals = options().getAttributeGlobal();
  bool Locals = options().getAttributeLocal();
  if ((Globals && Locals) || (!Globals && !Locals)) {
    // Print both Global and Local.
  } else {
    // Check for Global or Local Objects.
    if ((Globals && !(getHasGlobals() || getIsGlobalReference())) ||
        (Locals && !(getHasLocals() || !getIsGlobalReference())))
      return false;
  }

  // For the case of functions, skip it if is compiler generated.
  if (getIsFunction() && getIsArtificial() &&
      !options().getAttributeGenerated())
    return false;

  return true;
}

Error LVScope::doPrint(bool Split, bool Match, bool Print, raw_ostream &OS,
                       bool Full) const {
  // During a view output splitting, use the output stream created by the
  // split context, then switch to the reader output stream.
  raw_ostream *StreamSplit = &OS;

  // If 'Split', we use the scope name (CU name) as the ouput file; the
  // delimiters in the pathname, must be replaced by a normal character.
  if (getIsCompileUnit()) {
    getReader().setCompileUnit(const_cast<LVScope *>(this));
    if (Split) {
      std::string ScopeName(getName());
      if (std::error_code EC =
              getReaderSplitContext().open(ScopeName, ".txt", OS))
        return createStringError(EC, "Unable to create split output file %s",
                                 ScopeName.c_str());
      StreamSplit = static_cast<raw_ostream *>(&getReaderSplitContext().os());
    }
  }

  // Ignore discarded or stripped scopes (functions).
  bool DoPrint = (options().getAttributeDiscarded()) ? true : !getIsDiscarded();

  // If we are in compare mode, the only conditions are related to the
  // element being missing. In the case of elements comparison, we print the
  // augmented view, that includes added elements.
  // In print mode, we check other conditions, such as local, global, etc.
  if (DoPrint) {
    DoPrint =
        getIsInCompare() ? options().getReportExecute() : resolvePrinting();
  }

  // At this point we have checked for very specific options, to decide if the
  // element will be printed. Include the caller's test for element general
  // print.
  DoPrint = DoPrint && (Print || options().getOutputSplit());

  if (DoPrint) {
    // Print the element itself.
    print(*StreamSplit, Full);

    // Check if we have reached the requested lexical level specified in the
    // command line options. Input file is level zero and the CU is level 1.
    if ((getIsRoot() || options().getPrintAnyElement()) &&
        options().getPrintFormatting() &&
        getLevel() < options().getOutputLevel()) {
      // Print the children.
      if (Children)
        for (const LVElement *Element : *Children) {
          if (Match && !Element->getHasPattern())
            continue;
          if (Error Err =
                  Element->doPrint(Split, Match, Print, *StreamSplit, Full))
            return Err;
        }

      // Print the line records.
      if (Lines)
        for (const LVLine *Line : *Lines) {
          if (Match && !Line->getHasPattern())
            continue;
          if (Error Err =
                  Line->doPrint(Split, Match, Print, *StreamSplit, Full))
            return Err;
        }

      // Print the warnings.
      if (options().getPrintWarnings())
        printWarnings(*StreamSplit, Full);
    }
  }

  // Done printing the compile unit. Print any requested summary and
  // restore the original output context.
  if (getIsCompileUnit()) {
    if (options().getPrintSummary())
      printSummary(*StreamSplit);
    if (options().getPrintSizes())
      printSizes(*StreamSplit);
    if (Split) {
      getReaderSplitContext().close();
      StreamSplit = &getReader().outputStream();
    }
  }

  if (getIsRoot() && options().getPrintWarnings()) {
    getReader().printRecords(*StreamSplit);
  }

  return Error::success();
}

void LVScope::sort() {
  // Preserve the lines order as they are associated with user code.
  LVSortFunction SortFunction = getSortFunction();
  if (SortFunction) {
    std::function<void(LVScope * Parent, LVSortFunction SortFunction)> Sort =
        [&](LVScope *Parent, LVSortFunction SortFunction) {
          auto Traverse = [&](auto *Set, LVSortFunction SortFunction) {
            if (Set)
              std::stable_sort(Set->begin(), Set->end(), SortFunction);
          };
          Traverse(Parent->Types, SortFunction);
          Traverse(Parent->Symbols, SortFunction);
          Traverse(Parent->Scopes, SortFunction);
          Traverse(Parent->Ranges, compareRange);
          Traverse(Parent->Children, SortFunction);

          if (Parent->Scopes)
            for (LVScope *Scope : *Parent->Scopes)
              Sort(Scope, SortFunction);
        };

    // Start traversing the scopes root and transform the element name.
    Sort(this, SortFunction);
  }
}

void LVScope::traverseParents(LVScopeGetFunction GetFunction,
                              LVScopeSetFunction SetFunction) {
  // Traverse the parent tree.
  LVScope *Parent = this;
  while (Parent) {
    // Terminates if the 'SetFunction' has been already executed.
    if ((Parent->*GetFunction)())
      break;
    (Parent->*SetFunction)();
    Parent = Parent->getParentScope();
  }
}

void LVScope::traverseParentsAndChildren(LVObjectGetFunction GetFunction,
                                         LVObjectSetFunction SetFunction) {
  if (options().getReportParents()) {
    // First traverse the parent tree.
    LVScope *Parent = this;
    while (Parent) {
      // Terminates if the 'SetFunction' has been already executed.
      if ((Parent->*GetFunction)())
        break;
      (Parent->*SetFunction)();
      Parent = Parent->getParentScope();
    }
  }

  std::function<void(LVScope * Scope)> TraverseChildren = [&](LVScope *Scope) {
    auto Traverse = [&](const auto *Set) {
      if (Set)
        for (const auto &Entry : *Set)
          (Entry->*SetFunction)();
    };

    (Scope->*SetFunction)();

    Traverse(Scope->getTypes());
    Traverse(Scope->getSymbols());
    Traverse(Scope->getLines());

    if (const LVScopes *Scopes = Scope->getScopes())
      for (LVScope *Scope : *Scopes)
        TraverseChildren(Scope);
  };

  if (options().getReportChildren())
    TraverseChildren(this);
}

// Traverse the symbol location ranges and for each range:
// - Apply the 'ValidLocation' validation criteria.
// - Add any failed range to the 'LocationList'.
// - Calculate location coverage.
void LVScope::getLocations(LVLocations &LocationList,
                           LVValidLocation ValidLocation, bool RecordInvalid) {
  // Traverse scopes and symbols.
  if (Symbols)
    for (LVSymbol *Symbol : *Symbols)
      Symbol->getLocations(LocationList, ValidLocation, RecordInvalid);
  if (Scopes)
    for (LVScope *Scope : *Scopes)
      Scope->getLocations(LocationList, ValidLocation, RecordInvalid);
}

// Traverse the scope ranges and for each range:
// - Apply the 'ValidLocation' validation criteria.
// - Add any failed range to the 'LocationList'.
// - Calculate location coverage.
void LVScope::getRanges(LVLocations &LocationList,
                        LVValidLocation ValidLocation, bool RecordInvalid) {
  // Ignore discarded or stripped scopes (functions).
  if (getIsDiscarded())
    return;

  // Process the ranges for current scope.
  if (Ranges) {
    for (LVLocation *Location : *Ranges) {
      // Add the invalid location object.
      if (!(Location->*ValidLocation)() && RecordInvalid)
        LocationList.push_back(Location);
    }

    // Calculate coverage factor.
    calculateCoverage();
  }

  // Traverse the scopes.
  if (Scopes)
    for (LVScope *Scope : *Scopes)
      Scope->getRanges(LocationList, ValidLocation, RecordInvalid);
}

// Get all the ranges associated with scopes.
void LVScope::getRanges(LVRange &RangeList) {
  // Ignore discarded or stripped scopes (functions).
  if (getIsDiscarded())
    return;

  if (Ranges)
    RangeList.addEntry(this);
  if (Scopes)
    for (LVScope *Scope : *Scopes)
      Scope->getRanges(RangeList);
}

LVScope *LVScope::outermostParent(LVAddress Address) {
  LVScope *Parent = this;
  while (Parent) {
    const LVLocations *ParentRanges = Parent->getRanges();
    if (ParentRanges)
      for (const LVLocation *Location : *ParentRanges)
        if (Location->getLowerAddress() <= Address)
          return Parent;
    Parent = Parent->getParentScope();
  }
  return Parent;
}

LVScope *LVScope::findIn(const LVScopes *Targets) const {
  if (!Targets)
    return nullptr;

  // In the case of overloaded functions, sometimes the DWARF used to
  // describe them, does not give suficient information. Try to find a
  // perfect match or mark them as possible conflicts.
  LVScopes Candidates;
  for (LVScope *Target : *Targets)
    if (LVScope::equals(Target))
      Candidates.push_back(Target);

  LLVM_DEBUG({
    if (!Candidates.empty()) {
      dbgs() << "\n[LVScope::findIn]\n"
             << "Reference: "
             << "Offset = " << hexSquareString(getOffset()) << ", "
             << "Level = " << getLevel() << ", "
             << "Kind = " << formattedKind(kind()) << ", "
             << "Name = " << formattedName(getName()) << "\n";
      for (const LVScope *Candidate : Candidates)
        dbgs() << "Candidate: "
               << "Offset = " << hexSquareString(Candidate->getOffset()) << ", "
               << "Level = " << Candidate->getLevel() << ", "
               << "Kind = " << formattedKind(Candidate->kind()) << ", "
               << "Name = " << formattedName(Candidate->getName()) << "\n";
    }
  });

  if (!Candidates.empty())
    return (Candidates.size() == 1)
               ? (equals(Candidates[0]) ? Candidates[0] : nullptr)
               : findEqualScope(&Candidates);

  return nullptr;
}

bool LVScope::equalNumberOfChildren(const LVScope *Scope) const {
  // Same number of children. Take into account which elements are requested
  // to be included in the comparison.
  return !(
      (options().getCompareScopes() && scopeCount() != Scope->scopeCount()) ||
      (options().getCompareSymbols() &&
       symbolCount() != Scope->symbolCount()) ||
      (options().getCompareTypes() && typeCount() != Scope->typeCount()) ||
      (options().getCompareLines() && lineCount() != Scope->lineCount()));
}

void LVScope::markMissingParents(const LVScope *Target, bool TraverseChildren) {
  auto SetCompareState = [&](auto *Container) {
    if (Container)
      for (auto *Entry : *Container)
        Entry->setIsInCompare();
  };
  SetCompareState(Types);
  SetCompareState(Symbols);
  SetCompareState(Lines);
  SetCompareState(Scopes);

  // At this point, we are ready to start comparing the current scope, once
  // the compare bits have been set.
  if (options().getCompareTypes() && getTypes() && Target->getTypes())
    LVType::markMissingParents(getTypes(), Target->getTypes());
  if (options().getCompareSymbols() && getSymbols() && Target->getSymbols())
    LVSymbol::markMissingParents(getSymbols(), Target->getSymbols());
  if (options().getCompareLines() && getLines() && Target->getLines())
    LVLine::markMissingParents(getLines(), Target->getLines());
  if (getScopes() && Target->getScopes())
    LVScope::markMissingParents(getScopes(), Target->getScopes(),
                                TraverseChildren);
}

void LVScope::markMissingParents(const LVScopes *References,
                                 const LVScopes *Targets,
                                 bool TraverseChildren) {
  if (!(References && Targets))
    return;

  LLVM_DEBUG({
    dbgs() << "\n[LVScope::markMissingParents]\n";
    for (const LVScope *Reference : *References)
      dbgs() << "References: "
             << "Offset = " << hexSquareString(Reference->getOffset()) << ", "
             << "Level = " << Reference->getLevel() << ", "
             << "Kind = " << formattedKind(Reference->kind()) << ", "
             << "Name = " << formattedName(Reference->getName()) << "\n";
    for (const LVScope *Target : *Targets)
      dbgs() << "Targets   : "
             << "Offset = " << hexSquareString(Target->getOffset()) << ", "
             << "Level = " << Target->getLevel() << ", "
             << "Kind = " << formattedKind(Target->kind()) << ", "
             << "Name = " << formattedName(Target->getName()) << "\n";
  });

  for (LVScope *Reference : *References) {
    // Don't process 'Block' scopes, as we can't identify them.
    if (Reference->getIsBlock() || Reference->getIsGeneratedName())
      continue;

    LLVM_DEBUG({
      dbgs() << "\nSearch Reference: "
             << "Offset = " << hexSquareString(Reference->getOffset()) << " "
             << "Name = " << formattedName(Reference->getName()) << "\n";
    });
    LVScope *Target = Reference->findIn(Targets);
    if (Target) {
      LLVM_DEBUG({
        dbgs() << "\nFound Target: "
               << "Offset = " << hexSquareString(Target->getOffset()) << " "
               << "Name = " << formattedName(Target->getName()) << "\n";
      });
      if (TraverseChildren)
        Reference->markMissingParents(Target, TraverseChildren);
    } else {
      LLVM_DEBUG({
        dbgs() << "Missing Reference: "
               << "Offset = " << hexSquareString(Reference->getOffset()) << " "
               << "Name = " << formattedName(Reference->getName()) << "\n";
      });
      Reference->markBranchAsMissing();
    }
  }
}

bool LVScope::equals(const LVScope *Scope) const {
  if (!LVElement::equals(Scope))
    return false;
  // For lexical scopes, check if their parents are the same.
  if (getIsLexicalBlock() && Scope->getIsLexicalBlock())
    return getParentScope()->equals(Scope->getParentScope());
  return true;
}

LVScope *LVScope::findEqualScope(const LVScopes *Scopes) const {
  assert(Scopes && "Scopes must not be nullptr");
  for (LVScope *Scope : *Scopes)
    if (equals(Scope))
      return Scope;
  return nullptr;
}

bool LVScope::equals(const LVScopes *References, const LVScopes *Targets) {
  if (!References && !Targets)
    return true;
  if (References && Targets && References->size() == Targets->size()) {
    for (const LVScope *Reference : *References)
      if (!Reference->findIn(Targets))
        return false;
    return true;
  }
  return false;
}

void LVScope::report(LVComparePass Pass) {
  getComparator().printItem(this, Pass);
  getComparator().push(this);
  if (Children)
    for (LVElement *Element : *Children)
      Element->report(Pass);

  if (Lines)
    for (LVLine *Line : *Lines)
      Line->report(Pass);
  getComparator().pop();
}

void LVScope::printActiveRanges(raw_ostream &OS, bool Full) const {
  if (options().getPrintFormatting() && options().getAttributeRange() &&
      Ranges) {
    for (const LVLocation *Location : *Ranges)
      Location->print(OS, Full);
  }
}

void LVScope::printEncodedArgs(raw_ostream &OS, bool Full) const {
  if (options().getPrintFormatting() && options().getAttributeEncoded())
    printAttributes(OS, Full, "{Encoded} ", const_cast<LVScope *>(this),
                    getEncodedArgs(), /*UseQuotes=*/false, /*PrintRef=*/false);
}

void LVScope::print(raw_ostream &OS, bool Full) const {
  if (getIncludeInPrint() && getReader().doPrintScope(this)) {
    // For a summary (printed elements), do not count the scope root.
    // For a summary (selected elements) do not count a compile unit.
    if (!(getIsRoot() || (getIsCompileUnit() && options().getSelectExecute())))
      getReaderCompileUnit()->incrementPrintedScopes();
    LVElement::print(OS, Full);
    printExtra(OS, Full);
  }
}

void LVScope::printExtra(raw_ostream &OS, bool Full) const {
  OS << formattedKind(kind());
  // Do not print any type or name for a lexical block.
  if (!getIsBlock()) {
    OS << " " << formattedName(getName());
    if (!getIsAggregate())
      OS << " -> " << typeOffsetAsString()
         << formattedNames(getTypeQualifiedName(), typeAsString());
  }
  OS << "\n";

  // Print any active ranges.
  if (Full && getIsBlock())
    printActiveRanges(OS, Full);
}

//===----------------------------------------------------------------------===//
// DWARF Union/Structure/Class.
//===----------------------------------------------------------------------===//
bool LVScopeAggregate::equals(const LVScope *Scope) const {
  if (!LVScope::equals(Scope))
    return false;

  if (!equalNumberOfChildren(Scope))
    return false;

  // Check if the parameters match in the case of templates.
  if (!LVType::parametersMatch(getTypes(), Scope->getTypes()))
    return false;

  if (!isNamed() && !Scope->isNamed())
    // In the case of unnamed union/structure/class compare the file name.
    if (getFilenameIndex() != Scope->getFilenameIndex())
      return false;

  return true;
}

LVScope *LVScopeAggregate::findEqualScope(const LVScopes *Scopes) const {
  assert(Scopes && "Scopes must not be nullptr");
  for (LVScope *Scope : *Scopes)
    if (equals(Scope))
      return Scope;
  return nullptr;
}

void LVScopeAggregate::printExtra(raw_ostream &OS, bool Full) const {
  LVScope::printExtra(OS, Full);
  if (Full) {
    if (getIsTemplateResolved())
      printEncodedArgs(OS, Full);
    LVScope *Reference = getReference();
    if (Reference)
      Reference->printReference(OS, Full, const_cast<LVScopeAggregate *>(this));
  }
}

//===----------------------------------------------------------------------===//
// DWARF Template alias.
//===----------------------------------------------------------------------===//
bool LVScopeAlias::equals(const LVScope *Scope) const {
  if (!LVScope::equals(Scope))
    return false;
  return equalNumberOfChildren(Scope);
}

void LVScopeAlias::printExtra(raw_ostream &OS, bool Full) const {
  OS << formattedKind(kind()) << " " << formattedName(getName()) << " -> "
     << typeOffsetAsString()
     << formattedNames(getTypeQualifiedName(), typeAsString()) << "\n";
}

//===----------------------------------------------------------------------===//
// DWARF array (DW_TAG_array_type).
//===----------------------------------------------------------------------===//
void LVScopeArray::resolveExtra() {
  // If the scope is an array, resolve the subrange entries and get those
  // values encoded and assigned to the scope type.
  // Encode the array subrange entries as part of the name.
  if (getIsArrayResolved())
    return;
  setIsArrayResolved();

  // There are 2 cases to represent the bounds information for an array:
  // 1) DW_TAG_array_type
  //      DW_AT_type --> ref_type
  //      DW_TAG_subrange_type
  //        DW_AT_type --> ref_type (type of object)
  //        DW_AT_count --> value (number of elements in subrange)

  // 2) DW_TAG_array_type
  //      DW_AT_type --> ref_type
  //        DW_TAG_subrange_type
  //          DW_AT_lower_bound --> value
  //          DW_AT_upper_bound --> value

  // The idea is to represent the bounds as a string, depending on the format:
  // 1) [count]
  // 2) [lower][upper]

  // Traverse scope types, looking for those types that are subranges.
  LVTypes Subranges;
  if (const LVTypes *Types = getTypes())
    for (LVType *Type : *Types)
      if (Type->getIsSubrange()) {
        Type->resolve();
        Subranges.push_back(Type);
      }

  // Use the subrange types to generate the high level name for the array.
  // Check the type has been fully resolved.
  if (LVElement *BaseType = getType()) {
    BaseType->resolveName();
    resolveFullname(BaseType);
  }

  // In 'resolveFullname' a check is done for double spaces in the type name.
  std::stringstream ArrayInfo;
  if (ElementType)
    ArrayInfo << getTypeName().str() << " ";

  for (const LVType *Type : Subranges) {
    if (Type->getIsSubrangeCount())
      // Check if we have DW_AT_count subrange style.
      ArrayInfo << "[" << Type->getCount() << "]";
    else {
      // Get lower and upper subrange values.
      unsigned LowerBound;
      unsigned UpperBound;
      std::tie(LowerBound, UpperBound) = Type->getBounds();

      // The representation depends on the bound values. If the lower value
      // is zero, treat the pair as the elements count. Otherwise, just use
      // the pair, as they are representing arrays in languages other than
      // C/C++ and the lower limit is not zero.
      if (LowerBound)
        ArrayInfo << "[" << LowerBound << ".." << UpperBound << "]";
      else
        ArrayInfo << "[" << UpperBound + 1 << "]";
    }
  }

  // Update the scope name, to reflect the encoded subranges.
  setName(ArrayInfo.str());
}

bool LVScopeArray::equals(const LVScope *Scope) const {
  if (!LVScope::equals(Scope))
    return false;

  if (!equalNumberOfChildren(Scope))
    return false;

  // Despite the arrays are encoded, to reflect the dimensions, we have to
  // check the subranges, in order to determine if they are the same.
  if (!LVType::equals(getTypes(), Scope->getTypes()))
    return false;

  return true;
}

void LVScopeArray::printExtra(raw_ostream &OS, bool Full) const {
  OS << formattedKind(kind()) << " " << typeOffsetAsString()
     << formattedName(getName()) << "\n";
}

//===----------------------------------------------------------------------===//
// An object file (single or multiple CUs).
//===----------------------------------------------------------------------===//
void LVScopeCompileUnit::addSize(LVScope *Scope, LVOffset Lower,
                                 LVOffset Upper) {
  LLVM_DEBUG({
    dbgs() << format(
        "CU [0x%08" PRIx64 "], Scope [0x%08" PRIx64 "], Range [0x%08" PRIx64
        ":0x%08" PRIx64 "], Size = %" PRId64 "\n",
        getOffset(), Scope->getOffset(), Lower, Upper, Upper - Lower);
  });

  // There is no need to check for a previous entry, as we are traversing the
  // debug information in sequential order.
  LVOffset Size = Upper - Lower;
  Sizes[Scope] = Size;
  if (this == Scope)
    // Record contribution size for the compilation unit.
    CUContributionSize = Size;
}

// Update parents and children with pattern information.
void LVScopeCompileUnit::propagatePatternMatch() {
  // At this stage, we have finished creating the Scopes tree and we have
  // a list of elements that match the pattern specified in the command line.
  // The pattern corresponds to a scope or element; mark parents and/or
  // children as having that pattern, before any printing is done.
  if (!options().getSelectExecute())
    return;

  if (MatchedScopes.size()) {
    for (LVScope *Scope : MatchedScopes)
      Scope->traverseParentsAndChildren(&LVScope::getHasPattern,
                                        &LVScope::setHasPattern);
  } else {
    // Mark the compile unit as having a pattern to enable any requests to
    // print sizes and summary as that information is recorded at that level.
    setHasPattern();
  }
}

void LVScopeCompileUnit::processRangeLocationCoverage(
    LVValidLocation ValidLocation) {
  if (options().getAttributeRange()) {
    // Traverse the scopes to get scopes that have invalid ranges.
    LVLocations Locations;
    bool RecordInvalid = options().getWarningRanges();
    getRanges(Locations, ValidLocation, RecordInvalid);

    // Validate ranges associated with scopes.
    if (RecordInvalid)
      for (LVLocation *Location : Locations)
        addInvalidRange(Location);
  }

  if (options().getAttributeLocation()) {
    // Traverse the scopes to get locations that have invalid ranges.
    LVLocations Locations;
    bool RecordInvalid = options().getWarningLocations();
    getLocations(Locations, ValidLocation, RecordInvalid);

    // Validate ranges associated with locations.
    if (RecordInvalid)
      for (LVLocation *Location : Locations)
        addInvalidLocation(Location);
  }
}

void LVScopeCompileUnit::addMapping(LVLine *Line, LVSectionIndex SectionIndex) {
  LVAddress Address = Line->getOffset();
  SectionMappings.add(SectionIndex, Address, Line);
}

LVLine *LVScopeCompileUnit::lineLowerBound(LVAddress Address,
                                           LVScope *Scope) const {
  LVSectionIndex SectionIndex = getReader().getSectionIndex(Scope);
  LVAddressToLine *Map = SectionMappings.findMap(SectionIndex);
  if (!Map || Map->empty())
    return nullptr;
  LVAddressToLine::const_iterator Iter = Map->lower_bound(Address);
  return (Iter != Map->end()) ? Iter->second : nullptr;
}

LVLine *LVScopeCompileUnit::lineUpperBound(LVAddress Address,
                                           LVScope *Scope) const {
  LVSectionIndex SectionIndex = getReader().getSectionIndex(Scope);
  LVAddressToLine *Map = SectionMappings.findMap(SectionIndex);
  if (!Map || Map->empty())
    return nullptr;
  LVAddressToLine::const_iterator Iter = Map->upper_bound(Address);
  if (Iter != Map->begin())
    Iter = std::prev(Iter);
  return Iter->second;
}

LVLineRange LVScopeCompileUnit::lineRange(LVLocation *Location) const {
  // The parent of a location can be a symbol or a scope.
  LVElement *Element = Location->getParent();
  LVScope *Parent = Element->getIsScope() ? static_cast<LVScope *>(Element)
                                          : Element->getParentScope();
  LVLine *LowLine = lineLowerBound(Location->getLowerAddress(), Parent);
  LVLine *HighLine = lineUpperBound(Location->getUpperAddress(), Parent);
  return LVLineRange(LowLine, HighLine);
}

StringRef LVScopeCompileUnit::getFilename(size_t Index) const {
  if (Index <= 0 || Index > Filenames.size())
    return StringRef();
  return getStringPool().getString(Filenames[Index - 1]);
}

bool LVScopeCompileUnit::equals(const LVScope *Scope) const {
  if (!LVScope::equals(Scope))
    return false;

  return getNameIndex() == Scope->getNameIndex();
}

void LVScopeCompileUnit::incrementPrintedLines() {
  options().getSelectExecute() ? ++Found.Lines : ++Printed.Lines;
}
void LVScopeCompileUnit::incrementPrintedScopes() {
  options().getSelectExecute() ? ++Found.Scopes : ++Printed.Scopes;
}
void LVScopeCompileUnit::incrementPrintedSymbols() {
  options().getSelectExecute() ? ++Found.Symbols : ++Printed.Symbols;
}
void LVScopeCompileUnit::incrementPrintedTypes() {
  options().getSelectExecute() ? ++Found.Types : ++Printed.Types;
}

// Values are used by '--summary' option (allocated).
void LVScopeCompileUnit::increment(LVLine *Line) {
  if (Line->getIncludeInPrint())
    ++Allocated.Lines;
}
void LVScopeCompileUnit::increment(LVScope *Scope) {
  if (Scope->getIncludeInPrint())
    ++Allocated.Scopes;
}
void LVScopeCompileUnit::increment(LVSymbol *Symbol) {
  if (Symbol->getIncludeInPrint())
    ++Allocated.Symbols;
}
void LVScopeCompileUnit::increment(LVType *Type) {
  if (Type->getIncludeInPrint())
    ++Allocated.Types;
}

// A new element has been added to the scopes tree. Take the following steps:
// Increase the added element counters, for printing summary.
// During comparison notify the Reader of the new element.
void LVScopeCompileUnit::addedElement(LVLine *Line) {
  increment(Line);
  getReader().notifyAddedElement(Line);
}
void LVScopeCompileUnit::addedElement(LVScope *Scope) {
  increment(Scope);
  getReader().notifyAddedElement(Scope);
}
void LVScopeCompileUnit::addedElement(LVSymbol *Symbol) {
  increment(Symbol);
  getReader().notifyAddedElement(Symbol);
}
void LVScopeCompileUnit::addedElement(LVType *Type) {
  increment(Type);
  getReader().notifyAddedElement(Type);
}

// Record unsuported DWARF tags.
void LVScopeCompileUnit::addDebugTag(dwarf::Tag Target, LVOffset Offset) {
  addItem<LVTagOffsetsMap, LVOffsetList, dwarf::Tag, LVOffset>(&DebugTags,
                                                               Target, Offset);
}

// Record elements with invalid offsets.
void LVScopeCompileUnit::addInvalidOffset(LVOffset Offset, LVElement *Element) {
  if (WarningOffsets.find(Offset) == WarningOffsets.end())
    WarningOffsets.emplace(Offset, Element);
}

// Record symbols with invalid coverage values.
void LVScopeCompileUnit::addInvalidCoverage(LVSymbol *Symbol) {
  LVOffset Offset = Symbol->getOffset();
  if (InvalidCoverages.find(Offset) == InvalidCoverages.end())
    InvalidCoverages.emplace(Offset, Symbol);
}

// Record symbols with invalid locations.
void LVScopeCompileUnit::addInvalidLocation(LVLocation *Location) {
  addInvalidLocationOrRange(Location, Location->getParentSymbol(),
                            &InvalidLocations);
}

// Record scopes with invalid ranges.
void LVScopeCompileUnit::addInvalidRange(LVLocation *Location) {
  addInvalidLocationOrRange(Location, Location->getParentScope(),
                            &InvalidRanges);
}

// Record line zero.
void LVScopeCompileUnit::addLineZero(LVLine *Line) {
  LVScope *Scope = Line->getParentScope();
  LVOffset Offset = Scope->getOffset();
  addInvalidOffset(Offset, Scope);
  addItem<LVOffsetLinesMap, LVLines, LVOffset, LVLine *>(&LinesZero, Offset,
                                                         Line);
}

void LVScopeCompileUnit::printLocalNames(raw_ostream &OS, bool Full) const {
  if (!options().getPrintFormatting())
    return;

  // Calculate an indentation value, to preserve a nice layout.
  size_t Indentation = options().indentationSize() +
                       lineNumberAsString().length() +
                       indentAsString(getLevel() + 1).length() + 3;

  enum class Option { Directory, File };
  auto PrintNames = [&](Option Action) {
    StringRef Kind = Action == Option::Directory ? "Directory" : "File";
    std::set<std::string> UniqueNames;
    for (size_t Index : Filenames) {
      // In the case of missing directory name in the .debug_line table,
      // the returned string has a leading '/'.
      StringRef Name = getStringPool().getString(Index);
      size_t Pos = Name.rfind('/');
      if (Pos != std::string::npos)
        Name = (Action == Option::File) ? Name.substr(Pos + 1)
                                        : Name.substr(0, Pos);
      // Collect only unique names.
      UniqueNames.insert(std::string(Name));
    }
    for (const std::string &Name : UniqueNames)
      OS << std::string(Indentation, ' ') << formattedKind(Kind) << " "
         << formattedName(Name) << "\n";
  };

  if (options().getAttributeDirectories())
    PrintNames(Option::Directory);
  if (options().getAttributeFiles())
    PrintNames(Option::File);
  if (options().getAttributePublics()) {
    StringRef Kind = "Public";
    // The public names are indexed by 'LVScope *'. We want to print
    // them by logical element address, to show the scopes layout.
    using OffsetSorted = std::map<LVAddress, LVPublicNames::const_iterator>;
    OffsetSorted SortedNames;
    for (LVPublicNames::const_iterator Iter = PublicNames.begin();
         Iter != PublicNames.end(); ++Iter)
      SortedNames.emplace(Iter->first->getOffset(), Iter);

    LVPublicNames::const_iterator Iter;
    for (OffsetSorted::reference Entry : SortedNames) {
      Iter = Entry.second;
      OS << std::string(Indentation, ' ') << formattedKind(Kind) << " "
         << formattedName((*Iter).first->getName());
      if (options().getAttributeOffset()) {
        LVAddress Address = (*Iter).second.first;
        size_t Size = (*Iter).second.second;
        OS << " [" << hexString(Address) << ":" << hexString(Address + Size)
           << "]";
      }
      OS << "\n";
    }
  }
}

void LVScopeCompileUnit::printWarnings(raw_ostream &OS, bool Full) const {
  auto PrintHeader = [&](const char *Header) { OS << "\n" << Header << ":\n"; };
  auto PrintFooter = [&](auto &Set) {
    if (Set.empty())
      OS << "None\n";
  };
  auto PrintOffset = [&](unsigned &Count, LVOffset Offset) {
    if (Count == 5) {
      Count = 0;
      OS << "\n";
    }
    ++Count;
    OS << hexSquareString(Offset) << " ";
  };
  auto PrintElement = [&](const LVOffsetElementMap &Map, LVOffset Offset) {
    LVOffsetElementMap::const_iterator Iter = Map.find(Offset);
    LVElement *Element = Iter != Map.end() ? Iter->second : nullptr;
    OS << "[" << hexString(Offset) << "]";
    if (Element)
      OS << " " << formattedKind(Element->kind()) << " "
         << formattedName(Element->getName());
    OS << "\n";
  };
  auto PrintInvalidLocations = [&](const LVOffsetLocationsMap &Map,
                                   const char *Header) {
    PrintHeader(Header);
    for (LVOffsetLocationsMap::const_reference Entry : Map) {
      PrintElement(WarningOffsets, Entry.first);
      for (const LVLocation *Location : *Entry.second)
        OS << hexSquareString(Location->getOffset()) << " "
           << Location->getIntervalInfo() << "\n";
    }
    PrintFooter(Map);
  };

  if (options().getInternalTag() && getReader().isBinaryTypeELF()) {
    PrintHeader("Unsupported DWARF Tags");
    for (LVTagOffsetsMap::const_reference Entry : DebugTags) {
      OS << format("\n0x%02x", (unsigned)Entry.first) << ", "
         << dwarf::TagString(Entry.first) << "\n";
      unsigned Count = 0;
      for (const LVOffset &Offset : *Entry.second)
        PrintOffset(Count, Offset);
      OS << "\n";
    }
    PrintFooter(DebugTags);
  }

  if (options().getWarningCoverages()) {
    PrintHeader("Symbols Invalid Coverages");
    for (LVOffsetSymbolMap::const_reference Entry : InvalidCoverages) {
      // Symbol basic information.
      LVSymbol *Symbol = Entry.second;
      OS << hexSquareString(Entry.first) << " {Coverage} "
         << format("%.2f%%", Symbol->getCoveragePercentage()) << " "
         << formattedKind(Symbol->kind()) << " "
         << formattedName(Symbol->getName()) << "\n";
    }
    PrintFooter(InvalidCoverages);
  }

  if (options().getWarningLines()) {
    PrintHeader("Lines Zero References");
    for (LVOffsetLinesMap::const_reference Entry : LinesZero) {
      PrintElement(WarningOffsets, Entry.first);
      unsigned Count = 0;
      for (const LVLine *Line : *Entry.second)
        PrintOffset(Count, Line->getOffset());
      OS << "\n";
    }
    PrintFooter(LinesZero);
  }

  if (options().getWarningLocations())
    PrintInvalidLocations(InvalidLocations, "Invalid Location Ranges");

  if (options().getWarningRanges())
    PrintInvalidLocations(InvalidRanges, "Invalid Code Ranges");
}

void LVScopeCompileUnit::printTotals(raw_ostream &OS) const {
  OS << "\nTotals by lexical level:\n";
  for (size_t Index = 1; Index <= MaxSeenLevel; ++Index)
    OS << format("[%03d]: %10d (%6.2f%%)\n", Index, Totals[Index].first,
                 Totals[Index].second);
}

void LVScopeCompileUnit::printScopeSize(const LVScope *Scope, raw_ostream &OS) {
  LVSizesMap::const_iterator Iter = Sizes.find(Scope);
  if (Iter != Sizes.end()) {
    LVOffset Size = Iter->second;
    assert(CUContributionSize && "Invalid CU contribution size.");
    // Get a percentage rounded to two decimal digits. This avoids
    // implementation-defined rounding inside printing functions.
    float Percentage =
        rint((float(Size) / CUContributionSize) * 100.0 * 100.0) / 100.0;
    OS << format("%10" PRId64 " (%6.2f%%) : ", Size, Percentage);
    Scope->print(OS);

    // Keep record of the total sizes at each lexical level.
    LVLevel Level = Scope->getLevel();
    if (Level > MaxSeenLevel)
      MaxSeenLevel = Level;
    if (Level >= Totals.size())
      Totals.resize(2 * Level);
    Totals[Level].first += Size;
    Totals[Level].second += Percentage;
  }
}

void LVScopeCompileUnit::printSizes(raw_ostream &OS) const {
  // Recursively print the contributions for each scope.
  std::function<void(const LVScope *Scope)> PrintScope =
      [&](const LVScope *Scope) {
        // If we have selection criteria, then use only the selected scopes.
        if (options().getSelectExecute() && options().getReportAnyView()) {
          for (const LVScope *Scope : MatchedScopes)
            if (Scope->getLevel() < options().getOutputLevel())
              printScopeSize(Scope, OS);
          return;
        }
        if (Scope->getLevel() < options().getOutputLevel()) {
          if (const LVScopes *Scopes = Scope->getScopes())
            for (const LVScope *Scope : *Scopes) {
              printScopeSize(Scope, OS);
              PrintScope(Scope);
            }
        }
      };

  bool PrintScopes = options().getPrintScopes();
  if (!PrintScopes)
    options().setPrintScopes();
  getReader().setCompileUnit(const_cast<LVScopeCompileUnit *>(this));

  OS << "\nScope Sizes:\n";
  options().resetPrintFormatting();
  options().setPrintOffset();

  // Print the scopes regardless if the user has requested any scopes
  // printing. Set the option just to allow printing the contributions.
  printScopeSize(this, OS);
  PrintScope(this);

  // Print total scope sizes by level.
  printTotals(OS);

  options().resetPrintOffset();
  options().setPrintFormatting();

  if (!PrintScopes)
    options().resetPrintScopes();
}

void LVScopeCompileUnit::printSummary(raw_ostream &OS) const {
  printSummary(OS, options().getSelectExecute() ? Found : Printed, "Printed");
}

// Print summary details for the scopes tree.
void LVScopeCompileUnit::printSummary(raw_ostream &OS, const LVCounter &Counter,
                                      const char *Header) const {
  std::string Separator = std::string(29, '-');
  auto PrintSeparator = [&]() { OS << Separator << "\n"; };
  auto PrintHeadingRow = [&](const char *T, const char *U, const char *V) {
    OS << format("%-9s%9s  %9s\n", T, U, V);
  };
  auto PrintDataRow = [&](const char *T, unsigned U, unsigned V) {
    OS << format("%-9s%9d  %9d\n", T, U, V);
  };

  OS << "\n";
  PrintSeparator();
  PrintHeadingRow("Element", "Total", Header);
  PrintSeparator();
  PrintDataRow("Scopes", Allocated.Scopes, Counter.Scopes);
  PrintDataRow("Symbols", Allocated.Symbols, Counter.Symbols);
  PrintDataRow("Types", Allocated.Types, Counter.Types);
  PrintDataRow("Lines", Allocated.Lines, Counter.Lines);
  PrintSeparator();
  PrintDataRow(
      "Total",
      Allocated.Scopes + Allocated.Symbols + Allocated.Lines + Allocated.Types,
      Counter.Scopes + Counter.Symbols + Counter.Lines + Counter.Types);
}

void LVScopeCompileUnit::printMatchedElements(raw_ostream &OS,
                                              bool UseMatchedElements) {
  LVSortFunction SortFunction = getSortFunction();
  if (SortFunction)
    std::stable_sort(MatchedElements.begin(), MatchedElements.end(),
                     SortFunction);

  // Check the type of elements required to be printed. 'MatchedElements'
  // contains generic elements (lines, scopes, symbols, types). If we have a
  // request to print any generic element, then allow the normal printing.
  if (options().getPrintAnyElement()) {
    if (UseMatchedElements)
      OS << "\n";
    print(OS);

    if (UseMatchedElements) {
      // Print the details for the matched elements.
      for (const LVElement *Element : MatchedElements)
        Element->print(OS);
    } else {
      // Print the view for the matched scopes.
      for (const LVScope *Scope : MatchedScopes) {
        Scope->print(OS);
        if (const LVElements *Elements = Scope->getChildren())
          for (LVElement *Element : *Elements)
            Element->print(OS);
      }
    }

    // Print any requested summary.
    if (options().getPrintSummary()) {
      // In the case of '--report=details' the matched elements are
      // already counted; just proceed to print any requested summary.
      // Otherwise, count them and print the summary.
      if (!options().getReportList()) {
        for (LVElement *Element : MatchedElements) {
          if (!Element->getIncludeInPrint())
            continue;
          if (Element->getIsType())
            ++Found.Types;
          else if (Element->getIsSymbol())
            ++Found.Symbols;
          else if (Element->getIsScope())
            ++Found.Scopes;
          else if (Element->getIsLine())
            ++Found.Lines;
          else
            assert(Element && "Invalid element.");
        }
      }
      printSummary(OS, Found, "Printed");
    }
  }

  // Check if we have a request to print sizes for the matched elements
  // that are scopes.
  if (options().getPrintSizes()) {
    OS << "\n";
    print(OS);

    OS << "\nScope Sizes:\n";
    printScopeSize(this, OS);
    for (LVElement *Element : MatchedElements)
      if (Element->getIsScope())
        // Print sizes only for scopes.
        printScopeSize(static_cast<LVScope *>(Element), OS);

    printTotals(OS);
  }
}

void LVScopeCompileUnit::print(raw_ostream &OS, bool Full) const {
  // Reset counters for printed and found elements.
  const_cast<LVScopeCompileUnit *>(this)->Found.reset();
  const_cast<LVScopeCompileUnit *>(this)->Printed.reset();

  if (getReader().doPrintScope(this) && options().getPrintFormatting())
    OS << "\n";

  LVScope::print(OS, Full);
}

void LVScopeCompileUnit::printExtra(raw_ostream &OS, bool Full) const {
  OS << formattedKind(kind()) << " '" << getName() << "'\n";
  if (options().getPrintFormatting() && options().getAttributeProducer())
    printAttributes(OS, Full, "{Producer} ",
                    const_cast<LVScopeCompileUnit *>(this), getProducer(),
                    /*UseQuotes=*/true,
                    /*PrintRef=*/false);

  // Reset file index, to allow its children to print the correct filename.
  options().resetFilenameIndex();

  // Print any files, directories, public names and active ranges.
  if (Full) {
    printLocalNames(OS, Full);
    printActiveRanges(OS, Full);
  }
}

//===----------------------------------------------------------------------===//
// DWARF enumeration (DW_TAG_enumeration_type).
//===----------------------------------------------------------------------===//
bool LVScopeEnumeration::equals(const LVScope *Scope) const {
  if (!LVScope::equals(Scope))
    return false;
  return equalNumberOfChildren(Scope);
}

void LVScopeEnumeration::printExtra(raw_ostream &OS, bool Full) const {
  // Print the full type name.
  OS << formattedKind(kind()) << " " << (getIsEnumClass() ? "class " : "")
     << formattedName(getName());
  if (getHasType())
    OS << " -> " << typeOffsetAsString()
       << formattedNames(getTypeQualifiedName(), typeAsString());
  OS << "\n";
}

//===----------------------------------------------------------------------===//
// DWARF formal parameter pack (DW_TAG_GNU_formal_parameter_pack).
//===----------------------------------------------------------------------===//
bool LVScopeFormalPack::equals(const LVScope *Scope) const {
  if (!LVScope::equals(Scope))
    return false;
  return equalNumberOfChildren(Scope);
}

void LVScopeFormalPack::printExtra(raw_ostream &OS, bool Full) const {
  OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
}

//===----------------------------------------------------------------------===//
// DWARF function.
//===----------------------------------------------------------------------===//
void LVScopeFunction::resolveReferences() {
  // Before we resolve any references to other elements, check if we have
  // to insert missing elements, that have been stripped, which will help
  // the logical view comparison.
  if (options().getAttributeInserted() && getHasReferenceAbstract() &&
      !getAddedMissing()) {
    // Add missing elements at the function scope.
    addMissingElements(getReference());
    if (Scopes)
      for (LVScope *Scope : *Scopes)
        if (Scope->getHasReferenceAbstract() && !Scope->getAddedMissing())
          Scope->addMissingElements(Scope->getReference());
  }

  LVScope::resolveReferences();

  // The DWARF 'extern' attribute is generated at the class level.
  // 0000003f DW_TAG_class_type "CLASS"
  //   00000048 DW_TAG_subprogram "bar"
  //	            DW_AT_external DW_FORM_flag_present
  // 00000070 DW_TAG_subprogram "bar"
  //   DW_AT_specification DW_FORM_ref4 0x00000048
  // If there is a reference linking the declaration and definition, mark
  // the definition as extern, to facilitate the logical view comparison.
  if (getHasReferenceSpecification()) {
    LVScope *Reference = getReference();
    if (Reference && Reference->getIsExternal()) {
      Reference->resetIsExternal();
      setIsExternal();
    }
  }

  // Resolve the function associated type.
  if (!getType())
    if (LVScope *Reference = getReference())
      setType(Reference->getType());
}

void LVScopeFunction::setName(StringRef ObjectName) {
  LVScope::setName(ObjectName);
  // Check for system generated functions.
  getReader().isSystemEntry(this, ObjectName);
}

void LVScopeFunction::resolveExtra() {
  // Check if we need to encode the template arguments.
  if (getIsTemplate())
    resolveTemplate();
}

bool LVScopeFunction::equals(const LVScope *Scope) const {
  if (!LVScope::equals(Scope))
    return false;

  // When comparing logical elements, ignore any difference in the children.
  if (options().getCompareContext() && !equalNumberOfChildren(Scope))
    return false;

  // Check if the linkage name matches.
  if (getLinkageNameIndex() != Scope->getLinkageNameIndex())
    return false;

  // Check if the parameters match in the case of templates.
  if (!LVType::parametersMatch(getTypes(), Scope->getTypes()))
    return false;

  // Check if the arguments match.
  if (!LVSymbol::parametersMatch(getSymbols(), Scope->getSymbols()))
    return false;

  // Check if the lines match.
  if (options().getCompareLines() &&
      !LVLine::equals(getLines(), Scope->getLines()))
    return false;

  // Check if any reference is the same.
  if (!referenceMatch(Scope))
    return false;

  if (getReference() && !getReference()->equals(Scope->getReference()))
    return false;

  return true;
}

LVScope *LVScopeFunction::findEqualScope(const LVScopes *Scopes) const {
  assert(Scopes && "Scopes must not be nullptr");
  // Go through candidates and try to find a best match.
  for (LVScope *Scope : *Scopes)
    // Match arguments, children, lines, references.
    if (equals(Scope))
      return Scope;
  return nullptr;
}

void LVScopeFunction::printExtra(raw_ostream &OS, bool Full) const {
  LVScope *Reference = getReference();

  // Inline attributes based on the reference element.
  uint32_t InlineCode =
      Reference ? Reference->getInlineCode() : getInlineCode();

  // Accessibility depends on the parent (class, structure).
  uint32_t AccessCode = 0;
  if (getIsMember())
    AccessCode = getParentScope()->getIsClass() ? dwarf::DW_ACCESS_private
                                                : dwarf::DW_ACCESS_public;

  std::string Attributes =
      getIsCallSite()
          ? ""
          : formatAttributes(externalString(), accessibilityString(AccessCode),
                             inlineCodeString(InlineCode), virtualityString());

  OS << formattedKind(kind()) << " " << Attributes << formattedName(getName())
     << discriminatorAsString() << " -> " << typeOffsetAsString()
     << formattedNames(getTypeQualifiedName(), typeAsString()) << "\n";

  // Print any active ranges.
  if (Full) {
    if (getIsTemplateResolved())
      printEncodedArgs(OS, Full);
    printActiveRanges(OS, Full);
    if (getLinkageNameIndex())
      printLinkageName(OS, Full, const_cast<LVScopeFunction *>(this),
                       const_cast<LVScopeFunction *>(this));
    if (Reference)
      Reference->printReference(OS, Full, const_cast<LVScopeFunction *>(this));
  }
}

//===----------------------------------------------------------------------===//
// DWARF inlined function (DW_TAG_inlined_function).
//===----------------------------------------------------------------------===//
void LVScopeFunctionInlined::resolveExtra() {
  // Check if we need to encode the template arguments.
  if (getIsTemplate())
    resolveTemplate();
}

bool LVScopeFunctionInlined::equals(const LVScope *Scope) const {
  if (!LVScopeFunction::equals(Scope))
    return false;

  // Check if any reference is the same.
  if (getHasDiscriminator() && Scope->getHasDiscriminator())
    if (getDiscriminator() != Scope->getDiscriminator())
      return false;

  // Check the call site information.
  if (getCallFilenameIndex() != Scope->getCallFilenameIndex() ||
      getCallLineNumber() != Scope->getCallLineNumber())
    return false;

  return true;
}

LVScope *LVScopeFunctionInlined::findEqualScope(const LVScopes *Scopes) const {
  return LVScopeFunction::findEqualScope(Scopes);
}

void LVScopeFunctionInlined::printExtra(raw_ostream &OS, bool Full) const {
  LVScopeFunction::printExtra(OS, Full);
}

//===----------------------------------------------------------------------===//
// DWARF subroutine type.
//===----------------------------------------------------------------------===//
// Resolve a Subroutine Type (Callback).
void LVScopeFunctionType::resolveExtra() {
  if (getIsMemberPointerResolved())
    return;
  setIsMemberPointerResolved();

  // The encoded string has the return type and the formal parameters type.
  std::string Name(typeAsString());
  Name.append(" (*)");
  Name.append("(");

  // Traverse the scope symbols, looking for those which are parameters.
  if (const LVSymbols *Symbols = getSymbols()) {
    bool AddComma = false;
    for (LVSymbol *Symbol : *Symbols)
      if (Symbol->getIsParameter()) {
        Symbol->resolve();
        if (LVElement *Type = Symbol->getType())
          Type->resolveName();
        if (AddComma)
          Name.append(", ");
        Name.append(std::string(Symbol->getTypeName()));
        AddComma = true;
      }
  }

  Name.append(")");

  // Update the scope name, to reflect the encoded parameters.
  setName(Name);
}

//===----------------------------------------------------------------------===//
// DWARF namespace (DW_TAG_namespace).
//===----------------------------------------------------------------------===//
bool LVScopeNamespace::equals(const LVScope *Scope) const {
  if (!LVScope::equals(Scope))
    return false;

  if (!equalNumberOfChildren(Scope))
    return false;

  // Check if any reference is the same.
  if (!referenceMatch(Scope))
    return false;

  if (getReference() && !getReference()->equals(Scope->getReference()))
    return false;

  return true;
}

LVScope *LVScopeNamespace::findEqualScope(const LVScopes *Scopes) const {
  assert(Scopes && "Scopes must not be nullptr");
  // Go through candidates and try to find a best match.
  for (LVScope *Scope : *Scopes)
    if (equals(Scope))
      return Scope;
  return nullptr;
}

void LVScopeNamespace::printExtra(raw_ostream &OS, bool Full) const {
  OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";

  // Print any active ranges.
  if (Full) {
    printActiveRanges(OS, Full);

    if (LVScope *Reference = getReference())
      Reference->printReference(OS, Full, const_cast<LVScopeNamespace *>(this));
  }
}

//===----------------------------------------------------------------------===//
// An object file (single or multiple CUs).
//===----------------------------------------------------------------------===//
void LVScopeRoot::processRangeInformation() {
  if (!options().getAttributeAnyLocation())
    return;

  if (Scopes)
    for (LVScope *Scope : *Scopes) {
      LVScopeCompileUnit *CompileUnit =
          static_cast<LVScopeCompileUnit *>(Scope);
      getReader().setCompileUnit(CompileUnit);
      CompileUnit->processRangeLocationCoverage();
    }
}

bool LVScopeRoot::equals(const LVScope *Scope) const {
  return LVScope::equals(Scope);
}

void LVScopeRoot::print(raw_ostream &OS, bool Full) const {
  OS << "\nLogical View:\n";
  LVScope::print(OS, Full);
}

void LVScopeRoot::printExtra(raw_ostream &OS, bool Full) const {
  OS << formattedKind(kind()) << " " << formattedName(getName()) << "";
  if (options().getAttributeFormat())
    OS << " -> " << getFileFormatName();
  OS << "\n";
}

Error LVScopeRoot::doPrintMatches(bool Split, raw_ostream &OS,
                                  bool UseMatchedElements) const {
  // During a view output splitting, use the output stream created by the
  // split context, then switch to the reader output stream.
  static raw_ostream *StreamSplit = &OS;

  if (Scopes) {
    if (UseMatchedElements)
      options().resetPrintFormatting();
    print(OS);

    for (LVScope *Scope : *Scopes) {
      getReader().setCompileUnit(const_cast<LVScope *>(Scope));

      // If 'Split', we use the scope name (CU name) as the ouput file; the
      // delimiters in the pathname, must be replaced by a normal character.
      if (Split) {
        std::string ScopeName(Scope->getName());
        if (std::error_code EC =
                getReaderSplitContext().open(ScopeName, ".txt", OS))
          return createStringError(EC, "Unable to create split output file %s",
                                   ScopeName.c_str());
        StreamSplit = static_cast<raw_ostream *>(&getReaderSplitContext().os());
      }

      Scope->printMatchedElements(*StreamSplit, UseMatchedElements);

      // Done printing the compile unit. Restore the original output context.
      if (Split) {
        getReaderSplitContext().close();
        StreamSplit = &getReader().outputStream();
      }
    }
    if (UseMatchedElements)
      options().setPrintFormatting();
  }

  return Error::success();
}

//===----------------------------------------------------------------------===//
// DWARF template parameter pack (DW_TAG_GNU_template_parameter_pack).
//===----------------------------------------------------------------------===//
bool LVScopeTemplatePack::equals(const LVScope *Scope) const {
  if (!LVScope::equals(Scope))
    return false;
  return equalNumberOfChildren(Scope);
}

void LVScopeTemplatePack::printExtra(raw_ostream &OS, bool Full) const {
  OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
}
