Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:41

0001 //===--- DWARFExpression.h - DWARF Expression handling ----------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H
0010 #define LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H
0011 
0012 #include "llvm/ADT/StringRef.h"
0013 #include "llvm/ADT/iterator.h"
0014 #include "llvm/BinaryFormat/Dwarf.h"
0015 #include "llvm/Support/DataExtractor.h"
0016 
0017 namespace llvm {
0018 class DWARFUnit;
0019 struct DIDumpOptions;
0020 class MCRegisterInfo;
0021 class raw_ostream;
0022 
0023 class DWARFExpression {
0024 public:
0025   class iterator;
0026 
0027   /// This class represents an Operation in the Expression.
0028   ///
0029   /// An Operation can be in Error state (check with isError()). This
0030   /// means that it couldn't be decoded successfully and if it is the
0031   /// case, all others fields contain undefined values.
0032   class Operation {
0033   public:
0034     /// Size and signedness of expression operations' operands.
0035     enum Encoding : uint8_t {
0036       Size1 = 0,
0037       Size2 = 1,
0038       Size4 = 2,
0039       Size8 = 3,
0040       SizeLEB = 4,
0041       SizeAddr = 5,
0042       SizeRefAddr = 6,
0043       SizeBlock = 7, ///< Preceding operand contains block size
0044       BaseTypeRef = 8,
0045       /// The operand is a ULEB128 encoded SubOpcode. This is only valid
0046       /// for the first operand of an operation.
0047       SizeSubOpLEB = 9,
0048       WasmLocationArg = 30,
0049       SignBit = 0x80,
0050       SignedSize1 = SignBit | Size1,
0051       SignedSize2 = SignBit | Size2,
0052       SignedSize4 = SignBit | Size4,
0053       SignedSize8 = SignBit | Size8,
0054       SignedSizeLEB = SignBit | SizeLEB,
0055     };
0056 
0057     enum DwarfVersion : uint8_t {
0058       DwarfNA, ///< Serves as a marker for unused entries
0059       Dwarf2 = 2,
0060       Dwarf3,
0061       Dwarf4,
0062       Dwarf5
0063     };
0064 
0065     /// Description of the encoding of one expression Op.
0066     struct Description {
0067       DwarfVersion Version; ///< Dwarf version where the Op was introduced.
0068       SmallVector<Encoding> Op; ///< Encoding for Op operands.
0069 
0070       template <typename... Ts>
0071       Description(DwarfVersion Version, Ts... Op)
0072           : Version(Version), Op{Op...} {}
0073       Description() : Description(DwarfNA) {}
0074       ~Description() = default;
0075     };
0076 
0077   private:
0078     friend class DWARFExpression::iterator;
0079     uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
0080     Description Desc;
0081     bool Error = false;
0082     uint64_t EndOffset;
0083     SmallVector<uint64_t> Operands;
0084     SmallVector<uint64_t> OperandEndOffsets;
0085 
0086   public:
0087     const Description &getDescription() const { return Desc; }
0088     uint8_t getCode() const { return Opcode; }
0089     std::optional<unsigned> getSubCode() const;
0090     uint64_t getNumOperands() const { return Operands.size(); }
0091     ArrayRef<uint64_t> getRawOperands() const { return Operands; };
0092     uint64_t getRawOperand(unsigned Idx) const { return Operands[Idx]; }
0093     ArrayRef<uint64_t> getOperandEndOffsets() const {
0094       return OperandEndOffsets;
0095     }
0096     uint64_t getOperandEndOffset(unsigned Idx) const {
0097       return OperandEndOffsets[Idx];
0098     }
0099     uint64_t getEndOffset() const { return EndOffset; }
0100     bool isError() const { return Error; }
0101     bool print(raw_ostream &OS, DIDumpOptions DumpOpts,
0102                const DWARFExpression *Expr, DWARFUnit *U) const;
0103 
0104     /// Verify \p Op. Does not affect the return of \a isError().
0105     static bool verify(const Operation &Op, DWARFUnit *U);
0106 
0107   private:
0108     bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset,
0109                  std::optional<dwarf::DwarfFormat> Format);
0110   };
0111 
0112   /// An iterator to go through the expression operations.
0113   class iterator
0114       : public iterator_facade_base<iterator, std::forward_iterator_tag,
0115                                     const Operation> {
0116     friend class DWARFExpression;
0117     const DWARFExpression *Expr;
0118     uint64_t Offset;
0119     Operation Op;
0120     iterator(const DWARFExpression *Expr, uint64_t Offset)
0121         : Expr(Expr), Offset(Offset) {
0122       Op.Error =
0123           Offset >= Expr->Data.getData().size() ||
0124           !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
0125     }
0126 
0127   public:
0128     iterator &operator++() {
0129       Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset;
0130       Op.Error =
0131           Offset >= Expr->Data.getData().size() ||
0132           !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
0133       return *this;
0134     }
0135 
0136     const Operation &operator*() const { return Op; }
0137 
0138     iterator skipBytes(uint64_t Add) const {
0139       return iterator(Expr, Op.EndOffset + Add);
0140     }
0141 
0142     // Comparison operators are provided out of line.
0143     friend bool operator==(const iterator &, const iterator &);
0144   };
0145 
0146   DWARFExpression(DataExtractor Data, uint8_t AddressSize,
0147                   std::optional<dwarf::DwarfFormat> Format = std::nullopt)
0148       : Data(Data), AddressSize(AddressSize), Format(Format) {
0149     assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2);
0150   }
0151 
0152   iterator begin() const { return iterator(this, 0); }
0153   iterator end() const { return iterator(this, Data.getData().size()); }
0154 
0155   void print(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFUnit *U,
0156              bool IsEH = false) const;
0157 
0158   /// Print the expression in a format intended to be compact and useful to a
0159   /// user, but not perfectly unambiguous, or capable of representing every
0160   /// valid DWARF expression. Returns true if the expression was sucessfully
0161   /// printed.
0162   bool printCompact(raw_ostream &OS,
0163                     std::function<StringRef(uint64_t RegNum, bool IsEH)>
0164                         GetNameForDWARFReg = nullptr);
0165 
0166   bool verify(DWARFUnit *U);
0167 
0168   bool operator==(const DWARFExpression &RHS) const;
0169 
0170   StringRef getData() const { return Data.getData(); }
0171 
0172   static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
0173                                     DIDumpOptions DumpOpts, uint8_t Opcode,
0174                                     const ArrayRef<uint64_t> Operands);
0175 
0176 private:
0177   DataExtractor Data;
0178   uint8_t AddressSize;
0179   std::optional<dwarf::DwarfFormat> Format;
0180 };
0181 
0182 inline bool operator==(const DWARFExpression::iterator &LHS,
0183                        const DWARFExpression::iterator &RHS) {
0184   return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
0185 }
0186 }
0187 #endif