text: //===- DWARFDebugLoc.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
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
  #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
  
  #include "llvm/ADT/Optional.h"
  #include "llvm/ADT/SmallVector.h"
  #include "llvm/DebugInfo/DIContext.h"
  #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
  #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
  #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
  #include <cstdint>
  
  namespace llvm {
  class DWARFUnit;
  class MCRegisterInfo;
  class raw_ostream;
  
  /// A single location within a location list. Entries are stored in the DWARF5
  /// form even if they originally come from a DWARF<=4 location list.
  struct DWARFLocationEntry {
    /// The entry kind (DW_LLE_***).
    uint8_t Kind;
  
    /// The first value of the location entry (if applicable).
    uint64_t Value0;
  
    /// The second value of the location entry (if applicable).
    uint64_t Value1;
  
    /// The location expression itself (if applicable).
    SmallVector<uint8_t, 4> Loc;
  };
  
  /// An abstract base class for various kinds of location tables (.debug_loc,
  /// .debug_loclists, and their dwo variants).
  class DWARFLocationTable {
  public:
    DWARFLocationTable(DWARFDataExtractor Data) : Data(std::move(Data)) {}
    virtual ~DWARFLocationTable() = default;
  
    /// Call the user-provided callback for each entry (including the end-of-list
    /// entry) in the location list starting at \p Offset. The callback can return
    /// false to terminate the iteration early. Returns an error if it was unable
    /// to parse the entire location list correctly. Upon successful termination
    /// \p Offset will be updated point past the end of the list.
    virtual Error visitLocationList(
        uint64_t *Offset,
        function_ref<bool(const DWARFLocationEntry &)> Callback) const = 0;
  
    /// Dump the location list at the given \p Offset. The function returns true
    /// iff it has successfully reched the end of the list. This means that one
    /// can attempt to parse another list after the current one (\p Offset will be
    /// updated to point past the end of the current list).
    bool dumpLocationList(uint64_t *Offset, raw_ostream &OS,
                          Optional<object::SectionedAddress> BaseAddr,
                          const MCRegisterInfo *MRI, DWARFUnit *U,
                          DIDumpOptions DumpOpts, unsigned Indent) const;
  
    Error visitAbsoluteLocationList(
        uint64_t Offset, Optional<object::SectionedAddress> BaseAddr,
        std::function<Optional<object::SectionedAddress>(uint32_t)> LookupAddr,
        function_ref<bool(Expected<DWARFLocationExpression>)> Callback) const;
  
  protected:
    DWARFDataExtractor Data;
  
    virtual void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
                              unsigned Indent) const = 0;
  };
  
  class DWARFDebugLoc final : public DWARFLocationTable {
  public:
    /// A list of locations that contain one variable.
    struct LocationList {
      /// The beginning offset where this location list is stored in the debug_loc
      /// section.
      uint64_t Offset;
      /// All the locations in which the variable is stored.
      SmallVector<DWARFLocationEntry, 2> Entries;
    };
  
  private:
    using LocationLists = SmallVector<LocationList, 4>;
  
    /// A list of all the variables in the debug_loc section, each one describing
    /// the locations in which the variable is stored.
    LocationLists Locations;
  
  public:
    DWARFDebugLoc(DWARFDataExtractor Data)
        : DWARFLocationTable(std::move(Data)) {}
  
    /// Print the location lists found within the debug_loc section.
    void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, DIDumpOptions DumpOpts,
              Optional<uint64_t> Offset) const;
  
    Error visitLocationList(
        uint64_t *Offset,
        function_ref<bool(const DWARFLocationEntry &)> Callback) const override;
  
  protected:
    void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
                      unsigned Indent) const override;
  };
  
  class DWARFDebugLoclists final : public DWARFLocationTable {
  public:
    DWARFDebugLoclists(DWARFDataExtractor Data, uint16_t Version)
        : DWARFLocationTable(std::move(Data)), Version(Version) {}
  
    Error visitLocationList(
        uint64_t *Offset,
        function_ref<bool(const DWARFLocationEntry &)> Callback) const override;
  
    /// Dump all location lists within the given range.
    void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS,
                   const MCRegisterInfo *MRI, DIDumpOptions DumpOpts);
  
  protected:
    void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
                      unsigned Indent) const override;
  
  private:
    uint16_t Version;
  };
  
  } // end namespace llvm
  
  #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
  