forked from OSchip/llvm-project
IR: Add MDExpression::ExprOperand
Port `DIExpression::Operand` over to `MDExpression::ExprOperand`. The logic is needed directly in `MDExpression` to support printing in assembly. llvm-svn: 229002
This commit is contained in:
parent
3b631d291e
commit
193a4fdafd
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -350,6 +350,38 @@ MDExpression *MDExpression::getImpl(LLVMContext &Context,
|
|||
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,
|
||||
|
|
|
@ -780,6 +780,7 @@ void Verifier::visitMDLocalVariable(const MDLocalVariable &N) {
|
|||
|
||||
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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue