#ifndef LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H
#define LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Support/DataExtractor.h"
namespace llvm {
class DWARFUnit;
struct DIDumpOptions;
class MCRegisterInfo;
class raw_ostream;
class DWARFExpression {
public:
class iterator;
class Operation {
public:
enum Encoding : uint8_t {
Size1 = 0,
Size2 = 1,
Size4 = 2,
Size8 = 3,
SizeLEB = 4,
SizeAddr = 5,
SizeRefAddr = 6,
SizeBlock = 7, BaseTypeRef = 8,
WasmLocationArg = 30,
SignBit = 0x80,
SignedSize1 = SignBit | Size1,
SignedSize2 = SignBit | Size2,
SignedSize4 = SignBit | Size4,
SignedSize8 = SignBit | Size8,
SignedSizeLEB = SignBit | SizeLEB,
SizeNA = 0xFF };
enum DwarfVersion : uint8_t {
DwarfNA, Dwarf2 = 2,
Dwarf3,
Dwarf4,
Dwarf5
};
struct Description {
DwarfVersion Version; Encoding Op[2];
Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA,
Encoding Op2 = SizeNA)
: Version(Version) {
Op[0] = Op1;
Op[1] = Op2;
}
};
private:
friend class DWARFExpression::iterator;
uint8_t Opcode; Description Desc;
bool Error = false;
uint64_t EndOffset;
uint64_t Operands[2];
uint64_t OperandEndOffsets[2];
public:
const Description &getDescription() const { return Desc; }
uint8_t getCode() const { return Opcode; }
uint64_t getRawOperand(unsigned Idx) const { return Operands[Idx]; }
uint64_t getOperandEndOffset(unsigned Idx) const {
return OperandEndOffsets[Idx];
}
uint64_t getEndOffset() const { return EndOffset; }
bool isError() const { return Error; }
bool print(raw_ostream &OS, DIDumpOptions DumpOpts,
const DWARFExpression *Expr, const MCRegisterInfo *RegInfo,
DWARFUnit *U, bool isEH) const;
static bool verify(const Operation &Op, DWARFUnit *U);
private:
bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset,
Optional<dwarf::DwarfFormat> Format);
};
class iterator
: public iterator_facade_base<iterator, std::forward_iterator_tag,
const Operation> {
friend class DWARFExpression;
const DWARFExpression *Expr;
uint64_t Offset;
Operation Op;
iterator(const DWARFExpression *Expr, uint64_t Offset)
: Expr(Expr), Offset(Offset) {
Op.Error =
Offset >= Expr->Data.getData().size() ||
!Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
}
public:
iterator &operator++() {
Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset;
Op.Error =
Offset >= Expr->Data.getData().size() ||
!Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
return *this;
}
const Operation &operator*() const { return Op; }
iterator skipBytes(uint64_t Add) const {
return iterator(Expr, Op.EndOffset + Add);
}
friend bool operator==(const iterator &, const iterator &);
};
DWARFExpression(DataExtractor Data, uint8_t AddressSize,
Optional<dwarf::DwarfFormat> Format = None)
: Data(Data), AddressSize(AddressSize), Format(Format) {
assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2);
}
iterator begin() const { return iterator(this, 0); }
iterator end() const { return iterator(this, Data.getData().size()); }
void print(raw_ostream &OS, DIDumpOptions DumpOpts,
const MCRegisterInfo *RegInfo, DWARFUnit *U,
bool IsEH = false) const;
bool printCompact(raw_ostream &OS, const MCRegisterInfo &RegInfo);
bool verify(DWARFUnit *U);
bool operator==(const DWARFExpression &RHS) const;
StringRef getData() const { return Data.getData(); }
private:
DataExtractor Data;
uint8_t AddressSize;
Optional<dwarf::DwarfFormat> Format;
};
inline bool operator==(const DWARFExpression::iterator &LHS,
const DWARFExpression::iterator &RHS) {
return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
}
}
#endif