[llvm] r229002 - IR: Add MDExpression::ExprOperand
Duncan P. N. Exon Smith
dexonsmith at apple.com
Thu Feb 12 17:07:46 PST 2015
Author: dexonsmith
Date: Thu Feb 12 19:07:46 2015
New Revision: 229002
URL: http://llvm.org/viewvc/llvm-project?rev=229002&view=rev
Log:
IR: Add MDExpression::ExprOperand
Port `DIExpression::Operand` over to `MDExpression::ExprOperand`. The
logic is needed directly in `MDExpression` to support printing in
assembly.
Modified:
llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
llvm/trunk/lib/IR/DebugInfoMetadata.cpp
llvm/trunk/lib/IR/Verifier.cpp
llvm/trunk/unittests/IR/MetadataTest.cpp
Modified: llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugInfoMetadata.h?rev=229002&r1=229001&r2=229002&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DebugInfoMetadata.h (original)
+++ llvm/trunk/include/llvm/IR/DebugInfoMetadata.h Thu Feb 12 19:07:46 2015
@@ -1401,6 +1401,85 @@ public:
element_iterator elements_begin() const { return getElements().begin(); }
element_iterator elements_end() const { return getElements().end(); }
+ /// \brief A lightweight wrapper around an expression operand.
+ ///
+ /// TODO: Store arguments directly and change \a MDExpression to store a
+ /// range of these.
+ class ExprOperand {
+ const uint64_t *Op;
+
+ public:
+ explicit ExprOperand(const uint64_t *Op) : Op(Op) {}
+
+ const uint64_t *get() const { return Op; }
+
+ /// \brief Get the operand code.
+ uint64_t getOp() const { return *Op; }
+
+ /// \brief Get an argument to the operand.
+ ///
+ /// Never returns the operand itself.
+ uint64_t getArg(unsigned I) const { return Op[I + 1]; }
+
+ unsigned getNumArgs() const { return getSize() - 1; }
+
+ /// \brief Return the size of the operand.
+ ///
+ /// Return the number of elements in the operand (1 + args).
+ unsigned getSize() const;
+ };
+
+ /// \brief An iterator for expression operands.
+ class expr_op_iterator
+ : public std::iterator<std::input_iterator_tag, ExprOperand> {
+ ExprOperand Op;
+
+ public:
+ explicit expr_op_iterator(element_iterator I) : Op(I) {}
+
+ element_iterator getBase() const { return Op.get(); }
+ const ExprOperand &operator*() const { return Op; }
+ const ExprOperand *operator->() const { return &Op; }
+
+ expr_op_iterator &operator++() {
+ increment();
+ return *this;
+ }
+ expr_op_iterator operator++(int) {
+ expr_op_iterator T(*this);
+ increment();
+ return T;
+ }
+
+ bool operator==(const expr_op_iterator &X) const {
+ return getBase() == X.getBase();
+ }
+ bool operator!=(const expr_op_iterator &X) const {
+ return getBase() != X.getBase();
+ }
+
+ private:
+ void increment() { Op = ExprOperand(getBase() + Op.getSize()); }
+ };
+
+ /// \brief Visit the elements via ExprOperand wrappers.
+ ///
+ /// These range iterators visit elements through \a ExprOperand wrappers.
+ /// This is not guaranteed to be a valid range unless \a isValid() gives \c
+ /// true.
+ ///
+ /// \pre \a isValid() gives \c true.
+ /// @{
+ expr_op_iterator expr_op_begin() const {
+ return expr_op_iterator(elements_begin());
+ }
+ expr_op_iterator expr_op_end() const {
+ return expr_op_iterator(elements_end());
+ }
+ /// @}
+
+ bool isValid() const;
+
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == MDExpressionKind;
}
Modified: llvm/trunk/lib/IR/DebugInfoMetadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfoMetadata.cpp?rev=229002&r1=229001&r2=229002&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DebugInfoMetadata.cpp (original)
+++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp Thu Feb 12 19:07:46 2015
@@ -350,6 +350,38 @@ MDExpression *MDExpression::getImpl(LLVM
DEFINE_GETIMPL_STORE_NO_OPS(MDExpression, (Elements));
}
+unsigned MDExpression::ExprOperand::getSize() const {
+ switch (getOp()) {
+ case dwarf::DW_OP_bit_piece:
+ return 3;
+ case dwarf::DW_OP_plus:
+ return 2;
+ default:
+ return 1;
+ }
+}
+
+bool MDExpression::isValid() const {
+ for (auto I = expr_op_begin(), E = expr_op_end(); I != E; ++I) {
+ // Check that there's space for the operand.
+ if (I->get() + I->getSize() > E->get())
+ return false;
+
+ // Check that the operand is valid.
+ switch (I->getOp()) {
+ default:
+ return false;
+ case dwarf::DW_OP_bit_piece:
+ // Piece expressions must be at the end.
+ return I->get() + I->getSize() == E->get();
+ case dwarf::DW_OP_plus:
+ case dwarf::DW_OP_deref:
+ break;
+ }
+ }
+ return true;
+}
+
MDObjCProperty *MDObjCProperty::getImpl(
LLVMContext &Context, MDString *Name, Metadata *File, unsigned Line,
MDString *GetterName, MDString *SetterName, unsigned Attributes,
Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=229002&r1=229001&r2=229002&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Thu Feb 12 19:07:46 2015
@@ -780,6 +780,7 @@ void Verifier::visitMDLocalVariable(cons
void Verifier::visitMDExpression(const MDExpression &N) {
Assert1(N.getTag() == dwarf::DW_TAG_expression, "invalid tag", &N);
+ Assert1(N.isValid(), "invalid expression", &N);
}
void Verifier::visitMDObjCProperty(const MDObjCProperty &N) {
Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=229002&r1=229001&r2=229002&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Thu Feb 12 19:07:46 2015
@@ -1407,6 +1407,42 @@ TEST_F(MDExpressionTest, get) {
EXPECT_EQ(0u, N->getElement(4));
}
+TEST_F(MDExpressionTest, isValid) {
+#define EXPECT_VALID(...) \
+ do { \
+ uint64_t Elements[] = {__VA_ARGS__}; \
+ EXPECT_TRUE(MDExpression::get(Context, Elements)->isValid()); \
+ } while (false)
+#define EXPECT_INVALID(...) \
+ do { \
+ uint64_t Elements[] = {__VA_ARGS__}; \
+ EXPECT_FALSE(MDExpression::get(Context, Elements)->isValid()); \
+ } while (false)
+
+ // Empty expression should be valid.
+ EXPECT_TRUE(MDExpression::get(Context, None));
+
+ // Valid constructions.
+ EXPECT_VALID(dwarf::DW_OP_plus, 6);
+ EXPECT_VALID(dwarf::DW_OP_deref);
+ EXPECT_VALID(dwarf::DW_OP_bit_piece, 3, 7);
+ EXPECT_VALID(dwarf::DW_OP_plus, 6, dwarf::DW_OP_deref);
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6);
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_bit_piece, 3, 7);
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6, dwarf::DW_OP_bit_piece, 3, 7);
+
+ // Invalid constructions.
+ EXPECT_INVALID(~0u);
+ EXPECT_INVALID(dwarf::DW_OP_plus);
+ EXPECT_INVALID(dwarf::DW_OP_bit_piece);
+ EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3);
+ EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3, 7, dwarf::DW_OP_plus, 3);
+ EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3, 7, dwarf::DW_OP_deref);
+
+#undef EXPECT_VALID
+#undef EXPECT_INVALID
+}
+
typedef MetadataTest MDObjCPropertyTest;
TEST_F(MDObjCPropertyTest, get) {
More information about the llvm-commits
mailing list