[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