[llvm] r229002 - IR: Add MDExpression::ExprOperand
Duncan P. N. Exon Smith
dexonsmith at apple.com
Thu Feb 12 18:39:16 PST 2015
> On 2015-Feb-12, at 18:31, David Blaikie <dblaikie at gmail.com> wrote:
>
>
>
> On Thu, Feb 12, 2015 at 5:07 PM, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote:
> 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`.
>
> Any particular reason for the extra "Expr" in there - since it's the MDExpression's operand it seems clear that it's an expression operand?
>
> (but I guess it conflicts with the MDNode operands in some way?)
Yup. It's not a name clash, but it's a concept clash, so I wanted
to be clear.
(MDNode operands are called `MDOperand`.)
>
> 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) {
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
More information about the llvm-commits
mailing list