diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -176,57 +176,114 @@ /// @} }; -/// This is the common base class for debug info intrinsics for variables. -class DbgVariableIntrinsic : public DbgInfoIntrinsic { +// Iterator for ValueAsMetadata that internally uses direct pointer iteration +// over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the +// ValueAsMetadata . +class location_op_iterator + : public iterator_facade_base { + PointerUnion I; + public: - // Iterator for ValueAsMetadata that internally uses direct pointer iteration - // over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the - // ValueAsMetadata . - class location_op_iterator - : public iterator_facade_base { - PointerUnion I; - - public: - location_op_iterator(ValueAsMetadata *SingleIter) : I(SingleIter) {} - location_op_iterator(ValueAsMetadata **MultiIter) : I(MultiIter) {} - - location_op_iterator(const location_op_iterator &R) : I(R.I) {} - location_op_iterator &operator=(const location_op_iterator &R) { - I = R.I; - return *this; - } - bool operator==(const location_op_iterator &RHS) const { - return I == RHS.I; - } - const Value *operator*() const { - ValueAsMetadata *VAM = I.is() - ? I.get() - : *I.get(); - return VAM->getValue(); - }; - Value *operator*() { - ValueAsMetadata *VAM = I.is() - ? I.get() - : *I.get(); - return VAM->getValue(); - } - location_op_iterator &operator++() { - if (I.is()) - I = I.get() + 1; - else - I = I.get() + 1; - return *this; - } - location_op_iterator &operator--() { - if (I.is()) - I = I.get() - 1; - else - I = I.get() - 1; - return *this; - } + location_op_iterator(ValueAsMetadata *SingleIter) : I(SingleIter) {} + location_op_iterator(ValueAsMetadata **MultiIter) : I(MultiIter) {} + + location_op_iterator(const location_op_iterator &R) : I(R.I) {} + location_op_iterator &operator=(const location_op_iterator &R) { + I = R.I; + return *this; + } + bool operator==(const location_op_iterator &RHS) const { return I == RHS.I; } + const Value *operator*() const { + ValueAsMetadata *VAM = I.is() + ? I.get() + : *I.get(); + return VAM->getValue(); }; + Value *operator*() { + ValueAsMetadata *VAM = I.is() + ? I.get() + : *I.get(); + return VAM->getValue(); + } + location_op_iterator &operator++() { + if (I.is()) + I = I.get() + 1; + else + I = I.get() + 1; + return *this; + } + location_op_iterator &operator--() { + if (I.is()) + I = I.get() - 1; + else + I = I.get() - 1; + return *this; + } +}; + +/// Lightweight class that wraps the location operand metadata of a debug +/// intrinsic. The raw location may be a ValueAsMetadata, an empty MDTuple, +/// or a DIArgList. +class RawLocationWrapper { + Metadata *RawLocation = nullptr; + +public: + RawLocationWrapper() = default; + explicit RawLocationWrapper(Metadata *RawLocation) + : RawLocation(RawLocation) { + // Allow ValueAsMetadata, empty MDTuple, DIArgList. + assert(RawLocation && "unexpected null RawLocation"); + assert(isa(RawLocation) || isa(RawLocation) || + (isa(RawLocation) && + !cast(RawLocation)->getNumOperands())); + } + Metadata *getRawLocation() const { return RawLocation; } + /// Get the locations corresponding to the variable referenced by the debug + /// info intrinsic. Depending on the intrinsic, this could be the + /// variable's value or its address. + iterator_range location_ops() const; + Value *getVariableLocationOp(unsigned OpIdx) const; + unsigned getNumVariableLocationOps() const { + if (hasArgList()) + return cast(getRawLocation())->getArgs().size(); + return 1; + } + bool hasArgList() const { return isa(getRawLocation()); } + bool isKillLocation(const DIExpression *Expression) const { + return (getNumVariableLocationOps() == 0 && !Expression->isComplex()) || + any_of(location_ops(), [](Value *V) { return isa(V); }); + } + + friend bool operator==(const RawLocationWrapper &A, + const RawLocationWrapper &B) { + return A.RawLocation == B.RawLocation; + } + friend bool operator!=(const RawLocationWrapper &A, + const RawLocationWrapper &B) { + return !(A == B); + } + friend bool operator>(const RawLocationWrapper &A, + const RawLocationWrapper &B) { + return A.RawLocation > B.RawLocation; + } + friend bool operator>=(const RawLocationWrapper &A, + const RawLocationWrapper &B) { + return A.RawLocation >= B.RawLocation; + } + friend bool operator<(const RawLocationWrapper &A, + const RawLocationWrapper &B) { + return A.RawLocation < B.RawLocation; + } + friend bool operator<=(const RawLocationWrapper &A, + const RawLocationWrapper &B) { + return A.RawLocation <= B.RawLocation; + } +}; +/// This is the common base class for debug info intrinsics for variables. +class DbgVariableIntrinsic : public DbgInfoIntrinsic { +public: /// Get the locations corresponding to the variable referenced by the debug /// info intrinsic. Depending on the intrinsic, this could be the /// variable's value or its address. @@ -251,12 +308,10 @@ } unsigned getNumVariableLocationOps() const { - if (hasArgList()) - return cast(getRawLocation())->getArgs().size(); - return 1; + return getWrappedLocation().getNumVariableLocationOps(); } - bool hasArgList() const { return isa(getRawLocation()); } + bool hasArgList() const { return getWrappedLocation().hasArgList(); } /// Does this describe the address of a local variable. True for dbg.declare, /// but not dbg.value, which describes its value, or dbg.assign, which @@ -278,9 +333,7 @@ } bool isKillLocation() const { - return (getNumVariableLocationOps() == 0 && - !getExpression()->isComplex()) || - any_of(location_ops(), [](Value *V) { return isa(V); }); + return getWrappedLocation().isKillLocation(getExpression()); } DILocalVariable *getVariable() const { @@ -295,6 +348,10 @@ return cast(getArgOperand(0))->getMetadata(); } + RawLocationWrapper getWrappedLocation() const { + return RawLocationWrapper(getRawLocation()); + } + Metadata *getRawVariable() const { return cast(getArgOperand(1))->getMetadata(); } diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp --- a/llvm/lib/IR/IntrinsicInst.cpp +++ b/llvm/lib/IR/IntrinsicInst.cpp @@ -71,11 +71,9 @@ /// intrinsics for variables. /// -iterator_range -DbgVariableIntrinsic::location_ops() const { - auto *MD = getRawLocation(); +iterator_range RawLocationWrapper::location_ops() const { + Metadata *MD = getRawLocation(); assert(MD && "First operand of DbgVariableIntrinsic should be non-null."); - // If operand is ValueAsMetadata, return a range over just that operand. if (auto *VAM = dyn_cast(MD)) { return {location_op_iterator(VAM), location_op_iterator(VAM + 1)}; @@ -89,8 +87,17 @@ location_op_iterator(static_cast(nullptr))}; } +iterator_range +DbgVariableIntrinsic::location_ops() const { + return getWrappedLocation().location_ops(); +} + Value *DbgVariableIntrinsic::getVariableLocationOp(unsigned OpIdx) const { - auto *MD = getRawLocation(); + return getWrappedLocation().getVariableLocationOp(OpIdx); +} + +Value *RawLocationWrapper::getVariableLocationOp(unsigned OpIdx) const { + Metadata *MD = getRawLocation(); assert(MD && "First operand of DbgVariableIntrinsic should be non-null."); if (auto *AL = dyn_cast(MD)) return AL->getArgs()[OpIdx]->getValue();