-/// \brief A complex location expression in postfix notation.
-///
-/// This is (almost) a DWARF expression that modifies the location of a
-/// variable or (or the location of a single piece of a variable).
-///
-/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const
-/// and have DW_OP_plus consume the topmost elements on the stack.
-class DIExpression : public DIDescriptor {
-public:
- explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {}
- DIExpression(const MDExpression *N) : DIDescriptor(N) {}
-
- MDExpression *get() const {
- return cast_or_null<MDExpression>(DIDescriptor::get());
- }
- operator MDExpression *() const { return get(); }
- MDExpression *operator->() const { return get(); }
- MDExpression &operator*() const {
- assert(get() && "Expected valid pointer");
- return *get();
- }
-
- // Don't call this. Call isValid() directly.
- bool Verify() const = delete;
-
- /// \brief Return the number of elements in the complex expression.
- unsigned getNumElements() const { return get()->getNumElements(); }
-
- /// \brief return the Idx'th complex address element.
- uint64_t getElement(unsigned I) const { return get()->getElement(I); }
-
- /// \brief Return whether this is a piece of an aggregate variable.
- bool isBitPiece() const;
- /// \brief Return the offset of this piece in bits.
- uint64_t getBitPieceOffset() const;
- /// \brief Return the size of this piece in bits.
- uint64_t getBitPieceSize() const;
-
- class iterator;
- /// \brief A lightweight wrapper around an element of a DIExpression.
- class Operand {
- friend class iterator;
- MDExpression::element_iterator I;
- Operand() {}
- Operand(MDExpression::element_iterator I) : I(I) {}
- public:
- /// \brief Operands such as DW_OP_piece have explicit (non-stack) arguments.
- /// Argument 0 is the operand itself.
- uint64_t getArg(unsigned N) const {
- MDExpression::element_iterator In = I;
- std::advance(In, N);
- return *In;
- }
- operator uint64_t () const { return *I; }
- /// \brief Returns underlying MDExpression::element_iterator.
- const MDExpression::element_iterator &getBase() const { return I; }
- /// \brief Returns the next operand.
- iterator getNext() const;
- };
-
- /// \brief An iterator for DIExpression elements.
- class iterator : public std::iterator<std::input_iterator_tag, StringRef,
- unsigned, const Operand*, Operand> {
- friend class Operand;
- MDExpression::element_iterator I;
- Operand Tmp;
-
- public:
- iterator(MDExpression::element_iterator I) : I(I) {}
- const Operand &operator*() { return Tmp = Operand(I); }
- const Operand *operator->() { return &(Tmp = Operand(I)); }
- iterator &operator++() {
- increment();
- return *this;
- }
- iterator operator++(int) {
- iterator X(*this);
- increment();
- return X;
- }
- bool operator==(const iterator &X) const { return I == X.I; }
- bool operator!=(const iterator &X) const { return !(*this == X); }
-
- private:
- void increment() {
- switch (**this) {
- case dwarf::DW_OP_bit_piece: std::advance(I, 3); break;
- case dwarf::DW_OP_plus: std::advance(I, 2); break;
- case dwarf::DW_OP_deref: std::advance(I, 1); break;
- default:
- llvm_unreachable("unsupported operand");
- }
- }
- };
-
- iterator begin() const { return get()->elements_begin(); }
- iterator end() const { return get()->elements_end(); }
-};