diff options
Diffstat (limited to 'llvm')
25 files changed, 11 insertions, 1637 deletions
diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h index 347e140..ab291c2 100644 --- a/llvm/include/llvm/IR/BasicBlock.h +++ b/llvm/include/llvm/IR/BasicBlock.h @@ -19,7 +19,6 @@ #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" -#include "llvm/IR/DebugProgramInstruction.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/SymbolTableListTraits.h" #include "llvm/IR/Value.h" @@ -57,9 +56,6 @@ class BasicBlock final : public Value, // Basic blocks are data objects also public ilist_node_with_parent<BasicBlock, Function> { public: using InstListType = SymbolTableList<Instruction, ilist_iterator_bits<true>>; - /// Flag recording whether or not this block stores debug-info in the form - /// of intrinsic instructions (false) or non-instruction records (true). - bool IsNewDbgInfoFormat; private: friend class BlockAddress; @@ -68,55 +64,6 @@ private: InstListType InstList; Function *Parent; -public: - /// Attach a DPMarker to the given instruction. Enables the storage of any - /// debug-info at this position in the program. - DPMarker *createMarker(Instruction *I); - DPMarker *createMarker(InstListType::iterator It); - - /// Convert variable location debugging information stored in dbg.value - /// intrinsics into DPMarker / DPValue records. Deletes all dbg.values in - /// the process and sets IsNewDbgInfoFormat = true. Only takes effect if - /// the UseNewDbgInfoFormat LLVM command line option is given. - void convertToNewDbgValues(); - - /// Convert variable location debugging information stored in DPMarkers and - /// DPValues into the dbg.value intrinsic representation. Sets - /// IsNewDbgInfoFormat = false. - void convertFromNewDbgValues(); - - /// Ensure the block is in "old" dbg.value format (\p NewFlag == false) or - /// in the new format (\p NewFlag == true), converting to the desired format - /// if necessary. - void setIsNewDbgInfoFormat(bool NewFlag); - - /// Validate any DPMarkers / DPValues attached to instructions in this block, - /// and block-level stored data too (TrailingDPValues). - /// \p Assert Should this method fire an assertion if a problem is found? - /// \p Msg Should this method print a message to errs() if a problem is found? - /// \p OS Output stream to write errors to. - /// \returns True if a problem is found. - bool validateDbgValues(bool Assert = true, bool Msg = false, - raw_ostream *OS = nullptr); - - /// Record that the collection of DPValues in \p M "trails" after the last - /// instruction of this block. These are equivalent to dbg.value intrinsics - /// that exist at the end of a basic block with no terminator (a transient - /// state that occurs regularly). - void setTrailingDPValues(DPMarker *M); - - /// Fetch the collection of DPValues that "trail" after the last instruction - /// of this block, see \ref setTrailingDPValues. If there are none, returns - /// nullptr. - DPMarker *getTrailingDPValues(); - - /// Delete any trailing DPValues at the end of this block, see - /// \ref setTrailingDPValues. - void deleteTrailingDPValues(); - - void dumpDbgValues() const; - -private: void setParent(Function *parent); /// Constructor. diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 1fe0543..b347664 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -3765,10 +3765,6 @@ public: iterator args_begin() { return Args.begin(); } iterator args_end() { return Args.end(); } - ReplaceableMetadataImpl *getReplaceableUses() { - return Context.getReplaceableUses(); - } - static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIArgListKind; } diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h deleted file mode 100644 index 1a1f487..0000000 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ /dev/null @@ -1,384 +0,0 @@ -//===-- llvm/DebugProgramInstruction.h - Stream of debug info -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Data structures for storing variable assignment information in LLVM. In the -// dbg.value design, a dbg.value intrinsic specifies the position in a block -// a source variable take on an LLVM Value: -// -// %foo = add i32 1, %0 -// dbg.value(metadata i32 %foo, ...) -// %bar = void call @ext(%foo); -// -// and all information is stored in the Value / Metadata hierachy defined -// elsewhere in LLVM. In the "DPValue" design, each instruction /may/ have a -// connection with a DPMarker, which identifies a position immediately before the -// instruction, and each DPMarker /may/ then have connections to DPValues which -// record the variable assignment information. To illustrate: -// -// %foo = add i32 1, %0 -// ; foo->DbgMarker == nullptr -// ;; There are no variable assignments / debug records "in front" of -// ;; the instruction for %foo, therefore it has no DbgMarker. -// %bar = void call @ext(%foo) -// ; bar->DbgMarker = { -// ; StoredDPValues = { -// ; DPValue(metadata i32 %foo, ...) -// ; } -// ; } -// ;; There is a debug-info record in front of the %bar instruction, -// ;; thus it points at a DPMarker object. That DPMarker contains a -// ;; DPValue in it's ilist, storing the equivalent information to the -// ;; dbg.value above: the Value, DILocalVariable, etc. -// -// This structure separates the two concerns of the position of the debug-info -// in the function, and the Value that it refers to. It also creates a new -// "place" in-between the Value / Metadata hierachy where we can customise -// storage and allocation techniques to better suite debug-info workloads. -// NB: as of the initial prototype, none of that has actually been attempted -// yet. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_DEBUGPROGRAMINSTRUCTION_H -#define LLVM_IR_DEBUGPROGRAMINSTRUCTION_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Bitfields.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/ADT/iterator.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/SymbolTableListTraits.h" -#include "llvm/IR/TrackingMDRef.h" -#include "llvm/Support/AtomicOrdering.h" -#include <cstdint> -#include <utility> - -namespace llvm { - -class Instruction; -class BasicBlock; -class MDNode; -class Module; -class DbgVariableIntrinsic; -class DPMarker; -class DPValue; -class raw_ostream; - -/// Record of a variable value-assignment, aka a non instruction representation -/// of the dbg.value intrinsic. Features various methods copied across from the -/// Instruction class to aid ease-of-use. DPValue objects should always be -/// linked into a DPMarker's StoredDPValues list. The marker connects a DPValue -/// back to it's position in the BasicBlock. -/// -/// This class inherits from DebugValueUser to allow LLVM's metadata facilities -/// to update our references to metadata beneath our feet. -class DPValue : public ilist_node<DPValue>, private DebugValueUser { - friend class DebugValueUser; - - // NB: there is no explicit "Value" field in this class, it's effectively the - // DebugValueUser superclass instead. The referred to Value can either be a - // ValueAsMetadata or a DIArgList. - - DILocalVariable *Variable; - DIExpression *Expression; - DebugLoc DbgLoc; - -public: - void deleteInstr(); - - const BasicBlock *getParent() const; - BasicBlock *getParent(); - void dump() const; - void removeFromParent(); - void eraseFromParent(); - - using self_iterator = simple_ilist<DPValue>::iterator; - using const_self_iterator = simple_ilist<DPValue>::const_iterator; - - enum class LocationType { - Declare, - Value, - }; - /// Classification of the debug-info record that this DPValue represents. - /// Essentially, "is this a dbg.value or dbg.declare?". dbg.declares are not - /// currently supported, but it would be trivial to do so. - LocationType Type; - - /// Marker that this DPValue is linked into. - DPMarker *Marker = nullptr; - - /// Create a new DPValue representing the intrinsic \p DVI, for example the - /// assignment represented by a dbg.value. - DPValue(const DbgVariableIntrinsic *DVI); - DPValue(const DPValue &DPV); - /// Directly construct a new DPValue representing a dbg.value intrinsic - /// assigning \p Location to the DV / Expr / DI variable. - DPValue(Metadata *Location, DILocalVariable *DV, DIExpression *Expr, - const DILocation *DI); - - /// 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<location_op_iterator, - std::bidirectional_iterator_tag, Value *> { - PointerUnion<ValueAsMetadata *, ValueAsMetadata **> 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<ValueAsMetadata *>() - ? I.get<ValueAsMetadata *>() - : *I.get<ValueAsMetadata **>(); - return VAM->getValue(); - }; - Value *operator*() { - ValueAsMetadata *VAM = I.is<ValueAsMetadata *>() - ? I.get<ValueAsMetadata *>() - : *I.get<ValueAsMetadata **>(); - return VAM->getValue(); - } - location_op_iterator &operator++() { - if (I.is<ValueAsMetadata *>()) - I = I.get<ValueAsMetadata *>() + 1; - else - I = I.get<ValueAsMetadata **>() + 1; - return *this; - } - location_op_iterator &operator--() { - if (I.is<ValueAsMetadata *>()) - I = I.get<ValueAsMetadata *>() - 1; - else - I = I.get<ValueAsMetadata **>() - 1; - return *this; - } - }; - - /// 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_op_iterator> location_ops() const; - - Value *getVariableLocationOp(unsigned OpIdx) const; - - void replaceVariableLocationOp(Value *OldValue, Value *NewValue, - bool AllowEmpty = false); - void replaceVariableLocationOp(unsigned OpIdx, Value *NewValue); - /// Adding a new location operand will always result in this intrinsic using - /// an ArgList, and must always be accompanied by a new expression that uses - /// the new operand. - void addVariableLocationOps(ArrayRef<Value *> NewValues, - DIExpression *NewExpr); - - void setVariable(DILocalVariable *NewVar) { Variable = NewVar; } - - void setExpression(DIExpression *NewExpr) { Expression = NewExpr; } - - unsigned getNumVariableLocationOps() const { - if (hasArgList()) - return cast<DIArgList>(getRawLocation())->getArgs().size(); - return 1; - } - - bool hasArgList() const { return isa<DIArgList>(getRawLocation()); } - /// Returns true if this DPValue has no empty MDNodes in its location list. - bool hasValidLocation() const { return getVariableLocationOp(0) != nullptr; } - - /// Does this describe the address of a local variable. True for dbg.addr - /// and dbg.declare, but not dbg.value, which describes its value. - bool isAddressOfVariable() const { return Type != LocationType::Value; } - LocationType getType() const { return Type; } - - DebugLoc getDebugLoc() const { return DbgLoc; } - void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); } - - void setKillLocation() { - // TODO: When/if we remove duplicate values from DIArgLists, we don't need - // this set anymore. - SmallPtrSet<Value *, 4> RemovedValues; - for (Value *OldValue : location_ops()) { - if (!RemovedValues.insert(OldValue).second) - continue; - Value *Poison = PoisonValue::get(OldValue->getType()); - replaceVariableLocationOp(OldValue, Poison); - } - } - - bool isKillLocation() const { - return (getNumVariableLocationOps() == 0 && - !getExpression()->isComplex()) || - any_of(location_ops(), [](Value *V) { return isa<UndefValue>(V); }); - } - - DILocalVariable *getVariable() const { return Variable; } - - DIExpression *getExpression() const { return Expression; } - - Metadata *getRawLocation() const { return DebugValue; } - - /// Use of this should generally be avoided; instead, - /// replaceVariableLocationOp and addVariableLocationOps should be used where - /// possible to avoid creating invalid state. - void setRawLocation(Metadata *NewLocation) { - assert( - (isa<ValueAsMetadata>(NewLocation) || isa<DIArgList>(NewLocation) || - isa<MDNode>(NewLocation)) && - "Location for a DPValue must be either ValueAsMetadata or DIArgList"); - resetDebugValue(NewLocation); - } - - /// Get the size (in bits) of the variable, or fragment of the variable that - /// is described. - std::optional<uint64_t> getFragmentSizeInBits() const; - - DPValue *clone() const; - /// Convert this DPValue back into a dbg.value intrinsic. - /// \p InsertBefore Optional position to insert this intrinsic. - /// \returns A new dbg.value intrinsic representiung this DPValue. - DbgVariableIntrinsic *createDebugIntrinsic(Module *M, - Instruction *InsertBefore) const; - /// Handle changes to the location of the Value(s) that we refer to happening - /// "under our feet". - void handleChangedLocation(Metadata *NewLocation); - - void setMarker(DPMarker *M) { Marker = M; } - - DPMarker *getMarker() { return Marker; } - const DPMarker *getMarker() const { return Marker; } - - BasicBlock *getBlock(); - const BasicBlock *getBlock() const; - - Function *getFunction(); - const Function *getFunction() const; - - Module *getModule(); - const Module *getModule() const; - - LLVMContext &getContext(); - const LLVMContext &getContext() const; - - void print(raw_ostream &O, bool IsForDebug = false) const; - void print(raw_ostream &ROS, ModuleSlotTracker &MST, bool IsForDebug) const; -}; - -/// Per-instruction record of debug-info. If an Instruction is the position of -/// some debugging information, it points at a DPMarker storing that info. Each -/// marker points back at the instruction that owns it. Various utilities are -/// provided for manipulating the DPValues contained within this marker. -/// -/// This class has a rough surface area, because it's needed to preserve the one -/// arefact that we can't yet eliminate from the intrinsic / dbg.value -/// debug-info design: the order of DPValues/records is significant, and -/// duplicates can exist. Thus, if one has a run of debug-info records such as: -/// dbg.value(... -/// %foo = barinst -/// dbg.value(... -/// and remove barinst, then the dbg.values must be preserved in the correct -/// order. Hence, the use of iterators to select positions to insert things -/// into, or the occasional InsertAtHead parameter indicating that new records -/// should go at the start of the list. -/// -/// There are only five or six places in LLVM that truly rely on this ordering, -/// which we can improve in the future. Additionally, many improvements in the -/// way that debug-info is stored can be achieved in this class, at a future -/// date. -class DPMarker { -public: - DPMarker() {} - /// Link back to the Instruction that owns this marker. Can be null during - /// operations that move a marker from one instruction to another. - Instruction *MarkedInstr; - - /// List of DPValues, each recording a single variable assignment, the - /// equivalent of a dbg.value intrinsic. There is a one-to-one relationship - /// between each dbg.value in a block and each DPValue once the - /// representation has been converted, and the ordering of DPValues is - /// meaningful in the same was a dbg.values. - simple_ilist<DPValue> StoredDPValues; - - const BasicBlock *getParent() const; - BasicBlock *getParent(); - - /// Handle the removal of a marker: the position of debug-info has gone away, - /// but the stored debug records should not. Drop them onto the next - /// instruction, or otherwise work out what to do with them. - void removeMarker(); - void dump() const; - - void removeFromParent(); - void eraseFromParent(); - - /// Implement operator<< on DPMarker. - void print(raw_ostream &O, bool IsForDebug = false) const; - void print(raw_ostream &ROS, ModuleSlotTracker &MST, bool IsForDebug) const; - - /// Produce a range over all the DPValues in this Marker. - iterator_range<simple_ilist<DPValue>::iterator> getDbgValueRange(); - /// Transfer any DPValues from \p Src into this DPMarker. If \p InsertAtHead - /// is true, place them before existing DPValues, otherwise afterwards. - void absorbDebugValues(DPMarker &Src, bool InsertAtHead); - /// Insert a DPValue into this DPMarker, at the end of the list. If - /// \p InsertAtHead is true, at the start. - void insertDPValue(DPValue *New, bool InsertAtHead); - /// Clone all DPMarkers from \p From into this marker. There are numerous - /// options to customise the source/destination, due to gnarliness, see class - /// comment. - /// \p FromHere If non-null, copy from FromHere to the end of From's DPValues - /// \p InsertAtHead Place the cloned DPValues at the start of StoredDPValues - /// \returns Range over all the newly cloned DPValues - iterator_range<simple_ilist<DPValue>::iterator> - cloneDebugInfoFrom(DPMarker *From, - std::optional<simple_ilist<DPValue>::iterator> FromHere, - bool InsertAtHead = false); - /// Erase all DPValues in this DPMarker. - void dropDPValues(); - /// Erase a single DPValue from this marker. In an ideal future, we would - /// never erase an assignment in this way, but it's the equivalent to - /// erasing a dbg.value from a block. - void dropOneDPValue(DPValue *DPV); - - /// We generally act like all llvm Instructions have a range of DPValues - /// attached to them, but in reality sometimes we don't allocate the DPMarker - /// to save time and memory, but still have to return ranges of DPValues. When - /// we need to describe such an unallocated DPValue range, use this static - /// markers range instead. This will bite us if someone tries to insert a - /// DPValue in that range, but they should be using the Official (TM) API for - /// that. - static DPMarker EmptyDPMarker; - static iterator_range<simple_ilist<DPValue>::iterator> getEmptyDPValueRange(){ - return make_range(EmptyDPMarker.StoredDPValues.end(), EmptyDPMarker.StoredDPValues.end()); - } -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const DPMarker &Marker) { - Marker.print(OS); - return OS; -} - -inline raw_ostream &operator<<(raw_ostream &OS, const DPValue &Value) { - Value.print(OS); - return OS; -} - -} // namespace llvm - -#endif // LLVM_IR_DEBUGPROGRAMINSTRUCTION_H diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index 1628aaf..692ef75 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -97,28 +97,15 @@ private: friend class SymbolTableListTraits<Function>; -public: - /// Is this function using intrinsics to record the position of debugging - /// information, or non-intrinsic records? See IsNewDbgInfoFormat in - /// \ref BasicBlock. - bool IsNewDbgInfoFormat; - /// hasLazyArguments/CheckLazyArguments - The argument list of a function is /// built on demand, so that the list isn't allocated until the first client /// needs it. The hasLazyArguments predicate returns true if the arg list /// hasn't been set up yet. +public: bool hasLazyArguments() const { return getSubclassDataFromValue() & (1<<0); } - /// \see BasicBlock::convertToNewDbgValues. - void convertToNewDbgValues(); - - /// \see BasicBlock::convertFromNewDbgValues. - void convertFromNewDbgValues(); - - void setIsNewDbgInfoFormat(bool NewVal); - private: void CheckLazyArguments() const { if (hasLazyArguments()) @@ -705,7 +692,6 @@ public: /// Insert \p BB in the basic block list at \p Position. \Returns an iterator /// to the newly inserted BB. Function::iterator insert(Function::iterator Position, BasicBlock *BB) { - BB->setIsNewDbgInfoFormat(IsNewDbgInfoFormat); return BasicBlocks.insert(Position, BB); } diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h index c86c9e5..b5ccdf0 100644 --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -29,7 +29,6 @@ namespace llvm { class BasicBlock; -class DPMarker; class FastMathFlags; class MDNode; class Module; @@ -52,12 +51,6 @@ private: /// O(1) local dominance checks between instructions. mutable unsigned Order = 0; -public: - /// Optional marker recording the position for debugging information that - /// takes effect immediately before this instruction. Null unless there is - /// debugging information present. - DPMarker *DbgMarker = nullptr; - protected: // The 15 first bits of `Value::SubclassData` are available for subclasses of // `Instruction` to use. diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h index a245dab..9659dbe 100644 --- a/llvm/include/llvm/IR/Metadata.h +++ b/llvm/include/llvm/IR/Metadata.h @@ -43,7 +43,6 @@ namespace llvm { class Module; class ModuleSlotTracker; class raw_ostream; -class DPValue; template <typename T> class StringMapEntry; template <typename ValueTy> class StringMapEntryStorage; class Type; @@ -202,78 +201,6 @@ private: void untrack(); }; -/// Base class for tracking ValueAsMetadata/DIArgLists with user lookups and -/// Owner callbacks outside of ValueAsMetadata. -/// -/// Currently only inherited by DPValue; if other classes need to use it, then -/// a SubclassID will need to be added (either as a new field or by making -/// DebugValue into a PointerIntUnion) to discriminate between the subclasses in -/// lookup and callback handling. -class DebugValueUser { -protected: - Metadata *DebugValue; - -public: - DPValue *getUser(); - const DPValue *getUser() const; - void handleChangedValue(Metadata *NewDebugValue); - DebugValueUser() = default; - explicit DebugValueUser(Metadata *DebugValue) : DebugValue(DebugValue) { - trackDebugValue(); - } - - DebugValueUser(DebugValueUser &&X) : DebugValue(X.DebugValue) { - retrackDebugValue(X); - } - DebugValueUser(const DebugValueUser &X) : DebugValue(X.DebugValue) { - trackDebugValue(); - } - - DebugValueUser &operator=(DebugValueUser &&X) { - if (&X == this) - return *this; - - untrackDebugValue(); - DebugValue = X.DebugValue; - retrackDebugValue(X); - return *this; - } - - DebugValueUser &operator=(const DebugValueUser &X) { - if (&X == this) - return *this; - - untrackDebugValue(); - DebugValue = X.DebugValue; - trackDebugValue(); - return *this; - } - - ~DebugValueUser() { untrackDebugValue(); } - - void resetDebugValue() { - untrackDebugValue(); - DebugValue = nullptr; - } - void resetDebugValue(Metadata *DebugValue) { - untrackDebugValue(); - this->DebugValue = DebugValue; - trackDebugValue(); - } - - bool operator==(const DebugValueUser &X) const { - return DebugValue == X.DebugValue; - } - bool operator!=(const DebugValueUser &X) const { - return DebugValue != X.DebugValue; - } - -private: - void trackDebugValue(); - void untrackDebugValue(); - void retrackDebugValue(DebugValueUser &X); -}; - /// API for tracking metadata references through RAUW and deletion. /// /// Shared API for updating \a Metadata pointers in subclasses that support @@ -314,15 +241,6 @@ public: return track(Ref, MD, &Owner); } - /// Track the reference to metadata for \a DebugValueUser. - /// - /// As \a track(Metadata*&), but with support for calling back to \c Owner to - /// tell it that its operand changed. This could trigger \c Owner being - /// re-uniqued. - static bool track(void *Ref, Metadata &MD, DebugValueUser &Owner) { - return track(Ref, MD, &Owner); - } - /// Stop tracking a reference to metadata. /// /// Stops \c *MD from tracking \c MD. @@ -345,7 +263,7 @@ public: /// Check whether metadata is replaceable. static bool isReplaceable(const Metadata &MD); - using OwnerTy = PointerUnion<MetadataAsValue *, Metadata *, DebugValueUser *>; + using OwnerTy = PointerUnion<MetadataAsValue *, Metadata *>; private: /// Track a reference to metadata for an owner. @@ -357,8 +275,8 @@ private: /// Shared implementation of use-lists for replaceable metadata. /// /// Most metadata cannot be RAUW'ed. This is a shared implementation of -/// use-lists and associated API for the three that support it ( -/// \a ValueAsMetadata, \a TempMDNode, and \a DIArgList). +/// use-lists and associated API for the two that support it (\a ValueAsMetadata +/// and \a TempMDNode). class ReplaceableMetadataImpl { friend class MetadataTracking; @@ -387,8 +305,6 @@ public: static void SalvageDebugInfo(const Constant &C); /// Returns the list of all DIArgList users of this. SmallVector<Metadata *> getAllArgListUsers(); - /// Returns the list of all DPValue users of this. - SmallVector<DPValue *> getAllDPValueUsers(); /// Resolve all uses of this. /// @@ -472,9 +388,6 @@ public: SmallVector<Metadata *> getAllArgListUsers() { return ReplaceableMetadataImpl::getAllArgListUsers(); } - SmallVector<DPValue *> getAllDPValueUsers() { - return ReplaceableMetadataImpl::getAllDPValueUsers(); - } static void handleDeletion(Value *V); static void handleRAUW(Value *From, Value *To); @@ -1220,15 +1133,11 @@ public: bool isDistinct() const { return Storage == Distinct; } bool isTemporary() const { return Storage == Temporary; } - bool isReplaceable() const { - return isTemporary() || getMetadataID() == DIArgListKind; - } - /// RAUW a temporary. /// /// \pre \a isTemporary() must be \c true. void replaceAllUsesWith(Metadata *MD) { - assert(isReplaceable() && "Expected temporary/replaceable node"); + assert(isTemporary() && "Expected temporary node"); if (Context.hasReplaceableUses()) Context.getReplaceableUses()->replaceAllUsesWith(MD); } diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h index 68a89dc..70beddd 100644 --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -213,27 +213,6 @@ private: /// @name Constructors /// @{ public: - /// Is this Module using intrinsics to record the position of debugging - /// information, or non-intrinsic records? See IsNewDbgInfoFormat in - /// \ref BasicBlock. - bool IsNewDbgInfoFormat; - - /// \see BasicBlock::convertToNewDbgValues. - void convertToNewDbgValues() { - for (auto &F : *this) { - F.convertToNewDbgValues(); - } - IsNewDbgInfoFormat = true; - } - - /// \see BasicBlock::convertFromNewDbgValues. - void convertFromNewDbgValues() { - for (auto &F : *this) { - F.convertFromNewDbgValues(); - } - IsNewDbgInfoFormat = false; - } - /// The Module constructor. Note that there is no default constructor. You /// must provide a name for the module upon construction. explicit Module(StringRef ModuleID, LLVMContext& C); diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp index 0aba608..46b1a3b 100644 --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -20,171 +20,12 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Type.h" -#include "llvm/Support/CommandLine.h" - -#include "LLVMContextImpl.h" using namespace llvm; #define DEBUG_TYPE "ir" STATISTIC(NumInstrRenumberings, "Number of renumberings across all blocks"); -cl::opt<bool> - UseNewDbgInfoFormat("experimental-debuginfo-iterators", - cl::desc("Enable communicating debuginfo positions " - "through iterators, eliminating intrinsics"), - cl::init(false)); - -DPMarker *BasicBlock::createMarker(Instruction *I) { - assert(IsNewDbgInfoFormat && - "Tried to create a marker in a non new debug-info block!"); - assert(I->DbgMarker == nullptr && - "Tried to create marker for instuction that already has one!"); - DPMarker *Marker = new DPMarker(); - Marker->MarkedInstr = I; - I->DbgMarker = Marker; - return Marker; -} - -DPMarker *BasicBlock::createMarker(InstListType::iterator It) { - assert(IsNewDbgInfoFormat && - "Tried to create a marker in a non new debug-info block!"); - if (It != end()) - return createMarker(&*It); - DPMarker *DPM = getTrailingDPValues(); - if (DPM) - return DPM; - DPM = new DPMarker(); - setTrailingDPValues(DPM); - return DPM; -} - -void BasicBlock::convertToNewDbgValues() { - // Is the command line option set? - if (!UseNewDbgInfoFormat) - return; - - IsNewDbgInfoFormat = true; - - // Iterate over all instructions in the instruction list, collecting dbg.value - // instructions and converting them to DPValues. Once we find a "real" - // instruction, attach all those DPValues to a DPMarker in that instruction. - SmallVector<DPValue *, 4> DPVals; - for (Instruction &I : make_early_inc_range(InstList)) { - assert(!I.DbgMarker && "DbgMarker already set on old-format instrs?"); - if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(&I)) { - // Convert this dbg.value to a DPValue. - DPValue *Value = new DPValue(DVI); - DPVals.push_back(Value); - DVI->eraseFromParent(); - continue; - } - - // Create a marker to store DPValues in. Technically we don't need to store - // one marker per instruction, but that's a future optimisation. - createMarker(&I); - DPMarker *Marker = I.DbgMarker; - - for (DPValue *DPV : DPVals) - Marker->insertDPValue(DPV, false); - - DPVals.clear(); - } -} - -void BasicBlock::convertFromNewDbgValues() { - invalidateOrders(); - IsNewDbgInfoFormat = false; - - // Iterate over the block, finding instructions annotated with DPMarkers. - // Convert any attached DPValues to dbg.values and insert ahead of the - // instruction. - for (auto &Inst : *this) { - if (!Inst.DbgMarker) - continue; - - DPMarker &Marker = *Inst.DbgMarker; - for (DPValue &DPV : Marker.getDbgValueRange()) - InstList.insert(Inst.getIterator(), - DPV.createDebugIntrinsic(getModule(), nullptr)); - - Marker.eraseFromParent(); - }; - - // Assume no trailing DPValues: we could technically create them at the end - // of the block, after a terminator, but this would be non-cannonical and - // indicates that something else is broken somewhere. - assert(!getTrailingDPValues()); -} - -bool BasicBlock::validateDbgValues(bool Assert, bool Msg, raw_ostream *OS) { - bool RetVal = false; - if (!OS) - OS = &errs(); - - // Helper lambda for reporting failures: via assertion, printing, and return - // value. - auto TestFailure = [Assert, Msg, &RetVal, OS](bool Val, const char *Text) { - // Did the test fail? - if (Val) - return; - - // If we're asserting, then fire off an assertion. - if (Assert) - llvm_unreachable(Text); - - if (Msg) - *OS << Text << "\n"; - RetVal = true; - }; - - // We should have the same debug-format as the parent function. - TestFailure(getParent()->IsNewDbgInfoFormat == IsNewDbgInfoFormat, - "Parent function doesn't have the same debug-info format"); - - // Only validate if we are using the new format. - if (!IsNewDbgInfoFormat) - return RetVal; - - // Match every DPMarker to every Instruction and vice versa, and - // verify that there are no invalid DPValues. - for (auto It = begin(); It != end(); ++It) { - if (!It->DbgMarker) - continue; - - // Validate DebugProgramMarkers. - DPMarker *CurrentDebugMarker = It->DbgMarker; - - // If this is a marker, it should match the instruction and vice versa. - TestFailure(CurrentDebugMarker->MarkedInstr == &*It, - "Debug Marker points to incorrect instruction?"); - - // Now validate any DPValues in the marker. - for (DPValue &DPV : CurrentDebugMarker->getDbgValueRange()) { - // Validate DebugProgramValues. - TestFailure(DPV.getMarker() == CurrentDebugMarker, - "Not pointing at correct next marker!"); - - // Verify that no DbgValues appear prior to PHIs. - TestFailure( - !isa<PHINode>(It), - "DebugProgramValues must not appear before PHI nodes in a block!"); - } - } - - // Except transiently when removing + re-inserting the block terminator, there - // should be no trailing DPValues. - TestFailure(!getTrailingDPValues(), "Trailing DPValues in block"); - return RetVal; -} - -void BasicBlock::setIsNewDbgInfoFormat(bool NewFlag) { - if (NewFlag && !IsNewDbgInfoFormat) - convertToNewDbgValues(); - else if (!NewFlag && IsNewDbgInfoFormat) - convertFromNewDbgValues(); -} - ValueSymbolTable *BasicBlock::getValueSymbolTable() { if (Function *F = getParent()) return F->getValueSymbolTable(); @@ -206,8 +47,7 @@ template class llvm::SymbolTableListTraits<Instruction, BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent, BasicBlock *InsertBefore) - : Value(Type::getLabelTy(C), Value::BasicBlockVal), - IsNewDbgInfoFormat(false), Parent(nullptr) { + : Value(Type::getLabelTy(C), Value::BasicBlockVal), Parent(nullptr) { if (NewParent) insertInto(NewParent, InsertBefore); @@ -216,16 +56,12 @@ BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent, "Cannot insert block before another block with no function!"); setName(Name); - if (NewParent) - setIsNewDbgInfoFormat(NewParent->IsNewDbgInfoFormat); } void BasicBlock::insertInto(Function *NewParent, BasicBlock *InsertBefore) { assert(NewParent && "Expected a parent"); assert(!Parent && "Already has a parent"); - setIsNewDbgInfoFormat(NewParent->IsNewDbgInfoFormat); - if (InsertBefore) NewParent->insert(InsertBefore->getIterator(), this); else @@ -255,11 +91,6 @@ BasicBlock::~BasicBlock() { assert(getParent() == nullptr && "BasicBlock still linked into the program!"); dropAllReferences(); - for (auto &Inst : *this) { - if (!Inst.DbgMarker) - continue; - Inst.DbgMarker->eraseFromParent(); - } InstList.clear(); } @@ -757,16 +588,3 @@ void BasicBlock::validateInstrOrdering() const { } } #endif - -void BasicBlock::setTrailingDPValues(DPMarker *foo) { - getContext().pImpl->setTrailingDPValues(this, foo); -} - -DPMarker *BasicBlock::getTrailingDPValues() { - return getContext().pImpl->getTrailingDPValues(this); -} - -void BasicBlock::deleteTrailingDPValues() { - getContext().pImpl->deleteTrailingDPValues(this); -} - diff --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt index 5fe3d80..d9656a2 100644 --- a/llvm/lib/IR/CMakeLists.txt +++ b/llvm/lib/IR/CMakeLists.txt @@ -17,7 +17,6 @@ add_llvm_component_library(LLVMCore DataLayout.cpp DebugInfo.cpp DebugInfoMetadata.cpp - DebugProgramInstruction.cpp DebugLoc.cpp DiagnosticHandler.cpp DiagnosticInfo.cpp diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index e05fd29d..f7f3612 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -2135,14 +2135,8 @@ void DIArgList::handleChangedOperand(void *Ref, Metadata *New) { } } if (Uniq) { - MDNode *UniqueArgList = uniquify(); - if (UniqueArgList != this) { - replaceAllUsesWith(UniqueArgList); - // Clear this here so we don't try to untrack in the destructor. - Args.clear(); - delete this; - return; - } + if (uniquify() != this) + storeDistinctInContext(); } track(); } diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp deleted file mode 100644 index 3f39bae..0000000 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ /dev/null @@ -1,353 +0,0 @@ -//======-- DebugProgramInstruction.cpp - Implement DPValues/DPMarkers --======// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/IR/DebugProgramInstruction.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/IntrinsicInst.h" - -namespace llvm { - -DPValue::DPValue(const DbgVariableIntrinsic *DVI) - : DebugValueUser(DVI->getRawLocation()), Variable(DVI->getVariable()), - Expression(DVI->getExpression()), DbgLoc(DVI->getDebugLoc()) { - switch (DVI->getIntrinsicID()) { - case Intrinsic::dbg_value: - Type = LocationType::Value; - break; - case Intrinsic::dbg_declare: - Type = LocationType::Declare; - break; - default: - llvm_unreachable( - "Trying to create a DPValue with an invalid intrinsic type!"); - } -} - -DPValue::DPValue(const DPValue &DPV) - : DebugValueUser(DPV.getRawLocation()), - Variable(DPV.getVariable()), Expression(DPV.getExpression()), - DbgLoc(DPV.getDebugLoc()), Type(DPV.getType()) {} - -DPValue::DPValue(Metadata *Location, DILocalVariable *DV, DIExpression *Expr, - const DILocation *DI) - : DebugValueUser(Location), Variable(DV), Expression(Expr), DbgLoc(DI), - Type(LocationType::Value) { -} - -void DPValue::deleteInstr() { delete this; } - -iterator_range<DPValue::location_op_iterator> DPValue::location_ops() const { - auto *MD = getRawLocation(); - // If a Value has been deleted, the "location" for this DPValue will be - // replaced by nullptr. Return an empty range. - if (!MD) - return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)), - location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))}; - - // If operand is ValueAsMetadata, return a range over just that operand. - if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) - return {location_op_iterator(VAM), location_op_iterator(VAM + 1)}; - - // If operand is DIArgList, return a range over its args. - if (auto *AL = dyn_cast<DIArgList>(MD)) - return {location_op_iterator(AL->args_begin()), - location_op_iterator(AL->args_end())}; - - // Operand is an empty metadata tuple, so return empty iterator. - assert(cast<MDNode>(MD)->getNumOperands() == 0); - return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)), - location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))}; -} - -Value *DPValue::getVariableLocationOp(unsigned OpIdx) const { - auto *MD = getRawLocation(); - if (!MD) - return nullptr; - - if (auto *AL = dyn_cast<DIArgList>(MD)) - return AL->getArgs()[OpIdx]->getValue(); - if (isa<MDNode>(MD)) - return nullptr; - assert(isa<ValueAsMetadata>(MD) && - "Attempted to get location operand from DPValue with none."); - auto *V = cast<ValueAsMetadata>(MD); - assert(OpIdx == 0 && "Operand Index must be 0 for a debug intrinsic with a " - "single location operand."); - return V->getValue(); -} - -static ValueAsMetadata *getAsMetadata(Value *V) { - return isa<MetadataAsValue>(V) ? dyn_cast<ValueAsMetadata>( - cast<MetadataAsValue>(V)->getMetadata()) - : ValueAsMetadata::get(V); -} - -void DPValue::replaceVariableLocationOp(Value *OldValue, Value *NewValue, - bool AllowEmpty) { - assert(NewValue && "Values must be non-null"); - auto Locations = location_ops(); - auto OldIt = find(Locations, OldValue); - if (OldIt == Locations.end()) { - if (AllowEmpty) - return; - llvm_unreachable("OldValue must be a current location"); - } - - if (!hasArgList()) { - // Set our location to be the MAV wrapping the new Value. - setRawLocation(isa<MetadataAsValue>(NewValue) - ? cast<MetadataAsValue>(NewValue)->getMetadata() - : ValueAsMetadata::get(NewValue)); - return; - } - - // We must be referring to a DIArgList, produce a new operands vector with the - // old value replaced, generate a new DIArgList and set it as our location. - SmallVector<ValueAsMetadata *, 4> MDs; - ValueAsMetadata *NewOperand = getAsMetadata(NewValue); - for (auto *VMD : Locations) - MDs.push_back(VMD == *OldIt ? NewOperand : getAsMetadata(VMD)); - setRawLocation(DIArgList::get(getVariableLocationOp(0)->getContext(), MDs)); -} - -void DPValue::replaceVariableLocationOp(unsigned OpIdx, Value *NewValue) { - assert(OpIdx < getNumVariableLocationOps() && "Invalid Operand Index"); - - if (!hasArgList()) { - setRawLocation(isa<MetadataAsValue>(NewValue) - ? cast<MetadataAsValue>(NewValue)->getMetadata() - : ValueAsMetadata::get(NewValue)); - return; - } - - SmallVector<ValueAsMetadata *, 4> MDs; - ValueAsMetadata *NewOperand = getAsMetadata(NewValue); - for (unsigned Idx = 0; Idx < getNumVariableLocationOps(); ++Idx) - MDs.push_back(Idx == OpIdx ? NewOperand - : getAsMetadata(getVariableLocationOp(Idx))); - - setRawLocation(DIArgList::get(getVariableLocationOp(0)->getContext(), MDs)); -} - -void DPValue::addVariableLocationOps(ArrayRef<Value *> NewValues, - DIExpression *NewExpr) { - assert(NewExpr->hasAllLocationOps(getNumVariableLocationOps() + - NewValues.size()) && - "NewExpr for debug variable intrinsic does not reference every " - "location operand."); - assert(!is_contained(NewValues, nullptr) && "New values must be non-null"); - setExpression(NewExpr); - SmallVector<ValueAsMetadata *, 4> MDs; - for (auto *VMD : location_ops()) - MDs.push_back(getAsMetadata(VMD)); - for (auto *VMD : NewValues) - MDs.push_back(getAsMetadata(VMD)); - setRawLocation(DIArgList::get(getVariableLocationOp(0)->getContext(), MDs)); -} - -std::optional<uint64_t> DPValue::getFragmentSizeInBits() const { - if (auto Fragment = getExpression()->getFragmentInfo()) - return Fragment->SizeInBits; - return getVariable()->getSizeInBits(); -} - -DPValue *DPValue::clone() const { return new DPValue(*this); } - -DbgVariableIntrinsic * -DPValue::createDebugIntrinsic(Module *M, Instruction *InsertBefore) const { - [[maybe_unused]] DICompileUnit *Unit = - getDebugLoc().get()->getScope()->getSubprogram()->getUnit(); - assert(M && Unit && - "Cannot clone from BasicBlock that is not part of a Module or " - "DICompileUnit!"); - LLVMContext &Context = getDebugLoc()->getContext(); - Value *Args[] = {MetadataAsValue::get(Context, getRawLocation()), - MetadataAsValue::get(Context, getVariable()), - MetadataAsValue::get(Context, getExpression())}; - Function *IntrinsicFn; - - // Work out what sort of intrinsic we're going to produce. - switch (getType()) { - case DPValue::LocationType::Declare: - IntrinsicFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_declare); - break; - case DPValue::LocationType::Value: - IntrinsicFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_value); - break; - } - - // Create the intrinsic from this DPValue's information, optionally insert - // into the target location. - DbgVariableIntrinsic *DVI = cast<DbgVariableIntrinsic>( - CallInst::Create(IntrinsicFn->getFunctionType(), IntrinsicFn, Args)); - DVI->setTailCall(); - DVI->setDebugLoc(getDebugLoc()); - if (InsertBefore) - DVI->insertBefore(InsertBefore); - - return DVI; -} - -void DPValue::handleChangedLocation(Metadata *NewLocation) { - resetDebugValue(NewLocation); -} - -const BasicBlock *DPValue::getParent() const { - return Marker->MarkedInstr->getParent(); -} - -BasicBlock *DPValue::getParent() { return Marker->MarkedInstr->getParent(); } - -BasicBlock *DPValue::getBlock() { return Marker->getParent(); } - -const BasicBlock *DPValue::getBlock() const { return Marker->getParent(); } - -Function *DPValue::getFunction() { return getBlock()->getParent(); } - -const Function *DPValue::getFunction() const { return getBlock()->getParent(); } - -Module *DPValue::getModule() { return getFunction()->getParent(); } - -const Module *DPValue::getModule() const { return getFunction()->getParent(); } - -LLVMContext &DPValue::getContext() { return getBlock()->getContext(); } - -const LLVMContext &DPValue::getContext() const { - return getBlock()->getContext(); -} - -/////////////////////////////////////////////////////////////////////////////// - -// An empty, global, DPMarker for the purpose of describing empty ranges of -// DPValues. -DPMarker DPMarker::EmptyDPMarker; - -void DPMarker::dropDPValues() { - while (!StoredDPValues.empty()) { - auto It = StoredDPValues.begin(); - DPValue *DPV = &*It; - StoredDPValues.erase(It); - DPV->deleteInstr(); - } -} - -void DPMarker::dropOneDPValue(DPValue *DPV) { - assert(DPV->getMarker() == this); - StoredDPValues.erase(DPV->getIterator()); - DPV->deleteInstr(); -} - -const BasicBlock *DPMarker::getParent() const { - return MarkedInstr->getParent(); -} - -BasicBlock *DPMarker::getParent() { return MarkedInstr->getParent(); } - -void DPMarker::removeMarker() { - // Are there any DPValues in this DPMarker? If not, nothing to preserve. - Instruction *Owner = MarkedInstr; - if (StoredDPValues.empty()) { - eraseFromParent(); - Owner->DbgMarker = nullptr; - return; - } - - // The attached DPValues need to be preserved; attach them to the next - // instruction. If there isn't a next instruction, put them on the - // "trailing" list. - // (This logic gets refactored in a future patch, needed to break some - // dependencies here). - BasicBlock::iterator NextInst = std::next(Owner->getIterator()); - DPMarker *NextMarker; - if (NextInst == Owner->getParent()->end()) { - NextMarker = new DPMarker(); - Owner->getParent()->setTrailingDPValues(NextMarker); - } else { - NextMarker = NextInst->DbgMarker; - } - NextMarker->absorbDebugValues(*this, true); - - eraseFromParent(); -} - -void DPMarker::removeFromParent() { - MarkedInstr->DbgMarker = nullptr; - MarkedInstr = nullptr; -} - -void DPMarker::eraseFromParent() { - if (MarkedInstr) - removeFromParent(); - dropDPValues(); - delete this; -} - -iterator_range<DPValue::self_iterator> DPMarker::getDbgValueRange() { - return make_range(StoredDPValues.begin(), StoredDPValues.end()); -} - -void DPValue::removeFromParent() { - getMarker()->StoredDPValues.erase(getIterator()); -} - -void DPValue::eraseFromParent() { - removeFromParent(); - deleteInstr(); -} - -void DPMarker::insertDPValue(DPValue *New, bool InsertAtHead) { - auto It = InsertAtHead ? StoredDPValues.begin() : StoredDPValues.end(); - StoredDPValues.insert(It, *New); - New->setMarker(this); -} - -void DPMarker::absorbDebugValues(DPMarker &Src, bool InsertAtHead) { - auto It = InsertAtHead ? StoredDPValues.begin() : StoredDPValues.end(); - for (DPValue &DPV : Src.StoredDPValues) - DPV.setMarker(this); - - StoredDPValues.splice(It, Src.StoredDPValues); -} - -iterator_range<simple_ilist<DPValue>::iterator> DPMarker::cloneDebugInfoFrom( - DPMarker *From, std::optional<simple_ilist<DPValue>::iterator> from_here, - bool InsertAtHead) { - DPValue *First = nullptr; - // Work out what range of DPValues to clone: normally all the contents of the - // "From" marker, optionally we can start from the from_here position down to - // end(). - auto Range = - make_range(From->StoredDPValues.begin(), From->StoredDPValues.end()); - if (from_here.has_value()) - Range = make_range(*from_here, From->StoredDPValues.end()); - - // Clone each DPValue and insert into StoreDPValues; optionally place them at - // the start or the end of the list. - auto Pos = (InsertAtHead) ? StoredDPValues.begin() : StoredDPValues.end(); - for (DPValue &DPV : Range) { - DPValue *New = DPV.clone(); - New->setMarker(this); - StoredDPValues.insert(Pos, *New); - if (!First) - First = New; - } - - if (!First) - return {StoredDPValues.end(), StoredDPValues.end()}; - - if (InsertAtHead) - // If InsertAtHead is set, we cloned a range onto the front of of the - // StoredDPValues collection, return that range. - return {StoredDPValues.begin(), Pos}; - else - // We inserted a block at the end, return that range. - return {First->getIterator(), StoredDPValues.end()}; -} - -} // end namespace llvm - diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 49e0c1c..658aa67 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -81,27 +81,6 @@ static cl::opt<unsigned> NonGlobalValueMaxNameSize( "non-global-value-max-name-size", cl::Hidden, cl::init(1024), cl::desc("Maximum size for the name of non-global values.")); -void Function::convertToNewDbgValues() { - IsNewDbgInfoFormat = true; - for (auto &BB : *this) { - BB.convertToNewDbgValues(); - } -} - -void Function::convertFromNewDbgValues() { - IsNewDbgInfoFormat = false; - for (auto &BB : *this) { - BB.convertFromNewDbgValues(); - } -} - -void Function::setIsNewDbgInfoFormat(bool NewFlag) { - if (NewFlag && !IsNewDbgInfoFormat) - convertToNewDbgValues(); - else if (!NewFlag && IsNewDbgInfoFormat) - convertFromNewDbgValues(); -} - //===----------------------------------------------------------------------===// // Argument Implementation //===----------------------------------------------------------------------===// @@ -423,7 +402,7 @@ Function::Function(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, : GlobalObject(Ty, Value::FunctionVal, OperandTraits<Function>::op_begin(this), 0, Linkage, name, computeAddrSpace(AddrSpace, ParentModule)), - NumArgs(Ty->getNumParams()), IsNewDbgInfoFormat(false) { + NumArgs(Ty->getNumParams()) { assert(FunctionType::isValidReturnType(getReturnType()) && "invalid return type"); setGlobalObjectSubClassData(0); diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp index 406850b..2076eee 100644 --- a/llvm/lib/IR/LLVMContextImpl.cpp +++ b/llvm/lib/IR/LLVMContextImpl.cpp @@ -45,14 +45,6 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C) Int16Ty(C, 16), Int32Ty(C, 32), Int64Ty(C, 64), Int128Ty(C, 128) {} LLVMContextImpl::~LLVMContextImpl() { -#ifndef NDEBUG - // Check that any variable location records that fell off the end of a block - // when it's terminator was removed were eventually replaced. This assertion - // firing indicates that DPValues went missing during the lifetime of the - // LLVMContext. - assert(TrailingDPValues.empty() && "DPValue records in blocks not cleaned"); -#endif - // NOTE: We need to delete the contents of OwnedModules, but Module's dtor // will call LLVMContextImpl::removeModule, thus invalidating iterators into // the container. Avoid iterators during this operation: diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index ebc444f..4cc3f8d 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -57,7 +57,6 @@ class AttributeListImpl; class AttributeSetNode; class BasicBlock; struct DiagnosticHandler; -class DPMarker; class ElementCount; class Function; class GlobalObject; @@ -1634,36 +1633,6 @@ public: /// The lifetime of the object must be guaranteed to extend as long as the /// LLVMContext is used by compilation. void setOptPassGate(OptPassGate &); - - /// Mapping of blocks to collections of "trailing" DPValues. As part of the - /// "RemoveDIs" project, debug-info variable location records are going to - /// cease being instructions... which raises the problem of where should they - /// be recorded when we remove the terminator of a blocks, such as: - /// - /// %foo = add i32 0, 0 - /// br label %bar - /// - /// If the branch is removed, a legitimate transient state while editing a - /// block, any debug-records between those two instructions will not have a - /// location. Each block thus records any DPValue records that "trail" in - /// such a way. These are stored in LLVMContext because typically LLVM only - /// edits a small number of blocks at a time, so there's no need to bloat - /// BasicBlock with such a data structure. - SmallDenseMap<BasicBlock *, DPMarker *> TrailingDPValues; - - // Set, get and delete operations for TrailingDPValues. - void setTrailingDPValues(BasicBlock *B, DPMarker *M) { - assert(!TrailingDPValues.count(B)); - TrailingDPValues[B] = M; - } - - DPMarker *getTrailingDPValues(BasicBlock *B) { - return TrailingDPValues.lookup(B); - } - - void deleteTrailingDPValues(BasicBlock *B) { - TrailingDPValues.erase(B); - } }; } // end namespace llvm diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp index 5d0cd33..7860280 100644 --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -147,32 +147,6 @@ void MetadataAsValue::untrack() { MetadataTracking::untrack(MD); } -DPValue *DebugValueUser::getUser() { return static_cast<DPValue *>(this); } -const DPValue *DebugValueUser::getUser() const { - return static_cast<const DPValue *>(this); -} -void DebugValueUser::handleChangedValue(Metadata *NewMD) { - getUser()->handleChangedLocation(NewMD); -} - -void DebugValueUser::trackDebugValue() { - if (DebugValue) - MetadataTracking::track(&DebugValue, *DebugValue, *this); -} - -void DebugValueUser::untrackDebugValue() { - if (DebugValue) - MetadataTracking::untrack(DebugValue); -} - -void DebugValueUser::retrackDebugValue(DebugValueUser &X) { - assert(DebugValue == X.DebugValue && "Expected values to match"); - if (X.DebugValue) { - MetadataTracking::retrack(X.DebugValue, DebugValue); - X.DebugValue = nullptr; - } -} - bool MetadataTracking::track(void *Ref, Metadata &MD, OwnerTy Owner) { assert(Ref && "Expected live reference"); assert((Owner || *static_cast<Metadata **>(Ref) == &MD) && @@ -221,8 +195,6 @@ SmallVector<Metadata *> ReplaceableMetadataImpl::getAllArgListUsers() { SmallVector<std::pair<OwnerTy, uint64_t> *> MDUsersWithID; for (auto Pair : UseMap) { OwnerTy Owner = Pair.second.first; - if (Owner.isNull()) - continue; if (!isa<Metadata *>(Owner)) continue; Metadata *OwnerMD = cast<Metadata *>(Owner); @@ -238,25 +210,6 @@ SmallVector<Metadata *> ReplaceableMetadataImpl::getAllArgListUsers() { return MDUsers; } -SmallVector<DPValue *> ReplaceableMetadataImpl::getAllDPValueUsers() { - SmallVector<std::pair<OwnerTy, uint64_t> *> DPVUsersWithID; - for (auto Pair : UseMap) { - OwnerTy Owner = Pair.second.first; - if (Owner.isNull()) - continue; - if (!Owner.is<DebugValueUser *>()) - continue; - DPVUsersWithID.push_back(&UseMap[Pair.first]); - } - llvm::sort(DPVUsersWithID, [](auto UserA, auto UserB) { - return UserA->second < UserB->second; - }); - SmallVector<DPValue *> DPVUsers; - for (auto UserWithID : DPVUsersWithID) - DPVUsers.push_back(UserWithID->first.get<DebugValueUser *>()->getUser()); - return DPVUsers; -} - void ReplaceableMetadataImpl::addRef(void *Ref, OwnerTy Owner) { bool WasInserted = UseMap.insert(std::make_pair(Ref, std::make_pair(Owner, NextIndex))) @@ -355,11 +308,6 @@ void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) { continue; } - if (Owner.is<DebugValueUser *>()) { - Owner.get<DebugValueUser *>()->getUser()->handleChangedLocation(MD); - continue; - } - // There's a Metadata owner -- dispatch. Metadata *OwnerMD = cast<Metadata *>(Owner); switch (OwnerMD->getMetadataID()) { @@ -395,7 +343,7 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) { auto Owner = Pair.second.first; if (!Owner) continue; - if (!Owner.is<Metadata *>()) + if (isa<MetadataAsValue *>(Owner)) continue; // Resolve MDNodes that point at this. @@ -409,25 +357,18 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) { } ReplaceableMetadataImpl *ReplaceableMetadataImpl::getOrCreate(Metadata &MD) { - if (auto ArgList = dyn_cast<DIArgList>(&MD)) - return ArgList->Context.getOrCreateReplaceableUses(); if (auto *N = dyn_cast<MDNode>(&MD)) return N->isResolved() ? nullptr : N->Context.getOrCreateReplaceableUses(); return dyn_cast<ValueAsMetadata>(&MD); } ReplaceableMetadataImpl *ReplaceableMetadataImpl::getIfExists(Metadata &MD) { - if (auto ArgList = dyn_cast<DIArgList>(&MD)) { - return ArgList->Context.getOrCreateReplaceableUses(); - } if (auto *N = dyn_cast<MDNode>(&MD)) return N->isResolved() ? nullptr : N->Context.getReplaceableUses(); return dyn_cast<ValueAsMetadata>(&MD); } bool ReplaceableMetadataImpl::isReplaceable(const Metadata &MD) { - if (isa<DIArgList>(&MD)) - return true; if (auto *N = dyn_cast<MDNode>(&MD)) return !N->isResolved(); return isa<ValueAsMetadata>(&MD); diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index 17efe79..dba660b 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -71,8 +71,7 @@ template class llvm::SymbolTableListTraits<GlobalIFunc>; Module::Module(StringRef MID, LLVMContext &C) : Context(C), ValSymTab(std::make_unique<ValueSymbolTable>(-1)), - ModuleID(std::string(MID)), SourceFileName(std::string(MID)), DL(""), - IsNewDbgInfoFormat(false) { + ModuleID(std::string(MID)), SourceFileName(std::string(MID)), DL("") { Context.addModule(this); } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index e35f9fb..d3db7a1 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2941,14 +2941,6 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { { Check(I.getParent() == &BB, "Instruction has bogus parent pointer!"); } - - // Confirm that no issues arise from the debug program. - if (BB.IsNewDbgInfoFormat) { - // Configure the validate function to not fire assertions, instead print - // errors and return true if there's a problem. - bool RetVal = BB.validateDbgValues(false, true, OS); - Check(!RetVal, "Invalid configuration of new-debug-info data found"); - } } void Verifier::visitTerminator(Instruction &I) { diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp index e335def..2d45d85 100644 --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -1135,7 +1135,6 @@ Error IRLinker::linkFunctionBody(Function &Dst, Function &Src) { Dst.setPrologueData(Src.getPrologueData()); if (Src.hasPersonalityFn()) Dst.setPersonalityFn(Src.getPersonalityFn()); - assert(Src.IsNewDbgInfoFormat == Dst.IsNewDbgInfoFormat); // Copy over the metadata attachments without remapping. Dst.copyMetadata(&Src, 0); @@ -1546,8 +1545,6 @@ Error IRLinker::run() { if (Error Err = SrcM->getMaterializer()->materializeMetadata()) return Err; - DstM.IsNewDbgInfoFormat = SrcM->IsNewDbgInfoFormat; - // Inherit the target data from the source module if the destination module // doesn't have one already. if (DstM.getDataLayout().isDefault()) diff --git a/llvm/lib/Target/AMDGPU/AMDGPURewriteOutArguments.cpp b/llvm/lib/Target/AMDGPU/AMDGPURewriteOutArguments.cpp index e2055db..2fde7af 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPURewriteOutArguments.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPURewriteOutArguments.cpp @@ -331,8 +331,6 @@ bool AMDGPURewriteOutArguments::runOnFunction(Function &F) { NewFunc->removeRetAttrs(RetAttrs); // TODO: How to preserve metadata? - NewFunc->setIsNewDbgInfoFormat(F.IsNewDbgInfoFormat); - // Move the body of the function into the new rewritten function, and replace // this function with a stub. NewFunc->splice(NewFunc->begin(), &F); diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp index fb3fa8d..db9d5bc 100644 --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -161,7 +161,6 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM, F->getName()); NF->copyAttributesFrom(F); NF->copyMetadata(F, 0); - NF->setIsNewDbgInfoFormat(F->IsNewDbgInfoFormat); // The new function will have the !dbg metadata copied from the original // function. The original function may not be deleted, and dbg metadata need diff --git a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp index 3bd0888..0183401 100644 --- a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -174,7 +174,6 @@ bool DeadArgumentEliminationPass::deleteDeadVarargs(Function &F) { NF->setComdat(F.getComdat()); F.getParent()->getFunctionList().insert(F.getIterator(), NF); NF->takeName(&F); - NF->IsNewDbgInfoFormat = F.IsNewDbgInfoFormat; // Loop over all the callers of the function, transforming the call sites // to pass in a smaller number of arguments into the new function. @@ -878,7 +877,6 @@ bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(Function *F) { // it again. F->getParent()->getFunctionList().insert(F->getIterator(), NF); NF->takeName(F); - NF->IsNewDbgInfoFormat = F->IsNewDbgInfoFormat; // Loop over all the callers of the function, transforming the call sites to // pass in a smaller number of arguments into the new function. diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp index 1042105..39ac48c 100644 --- a/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -44,7 +44,6 @@ BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, ClonedCodeInfo *CodeInfo, DebugInfoFinder *DIFinder) { BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), "", F); - NewBB->IsNewDbgInfoFormat = BB->IsNewDbgInfoFormat; if (BB->hasName()) NewBB->setName(BB->getName() + NameSuffix); @@ -478,7 +477,6 @@ void PruningFunctionCloner::CloneBlock( BasicBlock *NewBB; Twine NewName(BB->hasName() ? Twine(BB->getName()) + NameSuffix : ""); BBEntry = NewBB = BasicBlock::Create(BB->getContext(), NewName, NewFunc); - NewBB->IsNewDbgInfoFormat = BB->IsNewDbgInfoFormat; // It is only legal to clone a function if a block address within that // function is never referenced outside of the function. Given that, we diff --git a/llvm/unittests/IR/DebugInfoTest.cpp b/llvm/unittests/IR/DebugInfoTest.cpp index f2cde8a..84ed733 100644 --- a/llvm/unittests/IR/DebugInfoTest.cpp +++ b/llvm/unittests/IR/DebugInfoTest.cpp @@ -23,8 +23,6 @@ using namespace llvm; -extern cl::opt<bool> UseNewDbgInfoFormat; - static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { SMDiagnostic Err; std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); @@ -745,307 +743,4 @@ TEST(AssignmentTrackingTest, InstrMethods) { } } -// Test some very straight-forward operations on DPValues -- these are -// dbg.values that have been converted to a non-instruction format. -TEST(MetadataTest, ConvertDbgToDPValue) { - LLVMContext C; - std::unique_ptr<Module> M = parseIR(C, R"( - define i16 @f(i16 %a) !dbg !6 { - call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 - %b = add i16 %a, 1, !dbg !11 - call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 - ret i16 0, !dbg !11 - - exit: - %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 - } - declare void @llvm.dbg.value(metadata, metadata, metadata) #0 - attributes #0 = { nounwind readnone speculatable willreturn } - - !llvm.dbg.cu = !{!0} - !llvm.module.flags = !{!5} - - !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) - !1 = !DIFile(filename: "t.ll", directory: "/") - !2 = !{} - !5 = !{i32 2, !"Debug Info Version", i32 3} - !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8) - !7 = !DISubroutineType(types: !2) - !8 = !{!9} - !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10) - !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned) - !11 = !DILocation(line: 1, column: 1, scope: !6) -)"); - - // Find the first dbg.value, - Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI(); - const DILocalVariable *Var = nullptr; - const DIExpression *Expr = nullptr; - const DILocation *Loc = nullptr; - const Metadata *MLoc = nullptr; - DPValue *DPV1 = nullptr; - { - DbgValueInst *DPI = dyn_cast<DbgValueInst>(&I); - ASSERT_TRUE(DPI); - Var = DPI->getVariable(); - Expr = DPI->getExpression(); - Loc = DPI->getDebugLoc().get(); - MLoc = DPI->getRawLocation(); - - // Test the creation of a DPValue and it's conversion back to a dbg.value. - DPV1 = new DPValue(DPI); - EXPECT_EQ(DPV1->getVariable(), Var); - EXPECT_EQ(DPV1->getExpression(), Expr); - EXPECT_EQ(DPV1->getDebugLoc().get(), Loc); - EXPECT_EQ(DPV1->getRawLocation(), MLoc); - - // Erase dbg.value, - DPI->eraseFromParent(); - // Re-create from DPV1, inserting at front. - DPV1->createDebugIntrinsic(&*M, - &M->getFunction("f")->getEntryBlock().front()); - - Instruction *NewDPI = &M->getFunction("f")->getEntryBlock().front(); - DbgValueInst *DPI2 = dyn_cast<DbgValueInst>(NewDPI); - ASSERT_TRUE(DPI2); - EXPECT_EQ(DPI2->getVariable(), Var); - EXPECT_EQ(DPI2->getExpression(), Expr); - EXPECT_EQ(DPI2->getDebugLoc().get(), Loc); - EXPECT_EQ(DPI2->getRawLocation(), MLoc); - } - - // Fetch the second dbg.value, convert it to a DPValue, - BasicBlock::iterator It = M->getFunction("f")->getEntryBlock().begin(); - It = std::next(std::next(It)); - DbgValueInst *DPI3 = dyn_cast<DbgValueInst>(It); - ASSERT_TRUE(DPI3); - DPValue *DPV2 = new DPValue(DPI3); - - // These dbg.values are supposed to refer to different values. - EXPECT_NE(DPV1->getRawLocation(), DPV2->getRawLocation()); - - // Try manipulating DPValues and markers in the exit block. - BasicBlock *ExitBlock = &*std::next(M->getFunction("f")->getEntryBlock().getIterator()); - Instruction *FirstInst = &ExitBlock->front(); - Instruction *RetInst = &*std::next(FirstInst->getIterator()); - - // Set-up DPMarkers in this block. - ExitBlock->IsNewDbgInfoFormat = true; - ExitBlock->createMarker(FirstInst); - ExitBlock->createMarker(RetInst); - - // Insert DPValues into markers, order should come out DPV2, DPV1. - FirstInst->DbgMarker->insertDPValue(DPV1, false); - FirstInst->DbgMarker->insertDPValue(DPV2, true); - unsigned int ItCount = 0; - for (DPValue &Item : FirstInst->DbgMarker->getDbgValueRange()) { - EXPECT_TRUE((&Item == DPV2 && ItCount == 0) || - (&Item == DPV1 && ItCount == 1)); - EXPECT_EQ(Item.getMarker(), FirstInst->DbgMarker); - ++ItCount; - } - - // Clone them onto the second marker -- should allocate new DPVs. - RetInst->DbgMarker->cloneDebugInfoFrom(FirstInst->DbgMarker, std::nullopt, false); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 2u); - ItCount = 0; - // Check these things store the same information; but that they're not the same - // objects. - for (DPValue &Item : RetInst->DbgMarker->getDbgValueRange()) { - EXPECT_TRUE((Item.getRawLocation() == DPV2->getRawLocation() && ItCount == 0) || - (Item.getRawLocation() == DPV1->getRawLocation() && ItCount == 1)); - - EXPECT_EQ(Item.getMarker(), RetInst->DbgMarker); - EXPECT_NE(&Item, DPV1); - EXPECT_NE(&Item, DPV2); - ++ItCount; - } - - RetInst->DbgMarker->dropDPValues(); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 0u); - - // Try cloning one single DPValue. - auto DIIt = std::next(FirstInst->DbgMarker->getDbgValueRange().begin()); - RetInst->DbgMarker->cloneDebugInfoFrom(FirstInst->DbgMarker, DIIt, false); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 1u); - // The second DPValue should have been cloned; it should have the same values - // as DPV1. - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.begin()->getRawLocation(), - DPV1->getRawLocation()); - // We should be able to drop individual DPValues. - RetInst->DbgMarker->dropOneDPValue(&*RetInst->DbgMarker->StoredDPValues.begin()); - - // "Aborb" a DPMarker: this means pretend that the instruction it's attached - // to is disappearing so it needs to be transferred into "this" marker. - RetInst->DbgMarker->absorbDebugValues(*FirstInst->DbgMarker, true); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 2u); - // Should be the DPV1 and DPV2 objects. - ItCount = 0; - for (DPValue &Item : RetInst->DbgMarker->getDbgValueRange()) { - EXPECT_TRUE((&Item == DPV2 && ItCount == 0) || - (&Item == DPV1 && ItCount == 1)); - EXPECT_EQ(Item.getMarker(), RetInst->DbgMarker); - ++ItCount; - } - - // Finally -- there are two DPValues left over. If we remove evrything in the - // basic block, then they should sink down into the "TrailingDPValues" - // container for dangling debug-info. Future facilities will restore them - // back when a terminator is inserted. - FirstInst->DbgMarker->removeMarker(); - FirstInst->eraseFromParent(); - RetInst->DbgMarker->removeMarker(); - RetInst->eraseFromParent(); - - DPMarker *EndMarker = ExitBlock->getTrailingDPValues(); - ASSERT_NE(EndMarker, nullptr); - EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); - // Test again that it's those two DPValues, DPV1 and DPV2. - ItCount = 0; - for (DPValue &Item : EndMarker->getDbgValueRange()) { - EXPECT_TRUE((&Item == DPV2 && ItCount == 0) || - (&Item == DPV1 && ItCount == 1)); - EXPECT_EQ(Item.getMarker(), EndMarker); - ++ItCount; - } - - // Those trailing DPValues would dangle and cause an assertion failure if - // they lived until the end of the LLVMContext, - ExitBlock->deleteTrailingDPValues(); -} - -TEST(MetadataTest, DPValueConversionRoutines) { - LLVMContext C; - - // For the purpose of this test, set and un-set the command line option - // corresponding to UseNewDbgInfoFormat. - UseNewDbgInfoFormat = true; - - std::unique_ptr<Module> M = parseIR(C, R"( - define i16 @f(i16 %a) !dbg !6 { - call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 - %b = add i16 %a, 1, !dbg !11 - call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 - ret i16 0, !dbg !11 - - exit: - %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 - } - declare void @llvm.dbg.value(metadata, metadata, metadata) #0 - attributes #0 = { nounwind readnone speculatable willreturn } - - !llvm.dbg.cu = !{!0} - !llvm.module.flags = !{!5} - - !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) - !1 = !DIFile(filename: "t.ll", directory: "/") - !2 = !{} - !5 = !{i32 2, !"Debug Info Version", i32 3} - !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8) - !7 = !DISubroutineType(types: !2) - !8 = !{!9} - !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10) - !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned) - !11 = !DILocation(line: 1, column: 1, scope: !6) -)"); - - // Check that the conversion routines and utilities between dbg.value - // debug-info format and DPValues works. - Function *F = M->getFunction("f"); - BasicBlock *BB1 = &F->getEntryBlock(); - // First instruction should be a dbg.value. - EXPECT_TRUE(isa<DbgValueInst>(BB1->front())); - EXPECT_FALSE(BB1->IsNewDbgInfoFormat); - // Validating the block for DPValues / DPMarkers shouldn't fail -- there's - // no data stored right now. - EXPECT_FALSE(BB1->validateDbgValues(false, false)); - - // Function and module should be marked as not having the new format too. - EXPECT_FALSE(F->IsNewDbgInfoFormat); - EXPECT_FALSE(M->IsNewDbgInfoFormat); - - // Now convert. - M->convertToNewDbgValues(); - EXPECT_TRUE(M->IsNewDbgInfoFormat); - EXPECT_TRUE(F->IsNewDbgInfoFormat); - EXPECT_TRUE(BB1->IsNewDbgInfoFormat); - - // There should now be no dbg.value instructions! - // Ensure the first instruction exists, the test all of them. - EXPECT_FALSE(isa<DbgValueInst>(BB1->front())); - for (auto &BB : *F) - for (auto &I : BB) - EXPECT_FALSE(isa<DbgValueInst>(I)); - - // There should be a DPMarker on each of the two instructions in the entry - // block, each containing one DPValue. - EXPECT_EQ(BB1->size(), 2u); - Instruction *FirstInst = &BB1->front(); - Instruction *SecondInst = FirstInst->getNextNode(); - ASSERT_TRUE(FirstInst->DbgMarker); - ASSERT_TRUE(SecondInst->DbgMarker); - EXPECT_NE(FirstInst->DbgMarker, SecondInst->DbgMarker); - EXPECT_EQ(FirstInst, FirstInst->DbgMarker->MarkedInstr); - EXPECT_EQ(SecondInst, SecondInst->DbgMarker->MarkedInstr); - - EXPECT_EQ(FirstInst->DbgMarker->StoredDPValues.size(), 1u); - DPValue *DPV1 = &*FirstInst->DbgMarker->getDbgValueRange().begin(); - EXPECT_EQ(DPV1->getMarker(), FirstInst->DbgMarker); - // Should point at %a, an argument. - EXPECT_TRUE(isa<Argument>(DPV1->getVariableLocationOp(0))); - - EXPECT_EQ(SecondInst->DbgMarker->StoredDPValues.size(), 1u); - DPValue *DPV2 = &*SecondInst->DbgMarker->getDbgValueRange().begin(); - EXPECT_EQ(DPV2->getMarker(), SecondInst->DbgMarker); - // Should point at FirstInst. - EXPECT_EQ(DPV2->getVariableLocationOp(0), FirstInst); - - // There should be no DPValues / DPMarkers in the second block, but it should - // be marked as being in the new format. - BasicBlock *BB2 = BB1->getNextNode(); - EXPECT_TRUE(BB2->IsNewDbgInfoFormat); - for (auto &Inst : *BB2) - // Either there should be no marker, or it should be empty. - EXPECT_TRUE(!Inst.DbgMarker || Inst.DbgMarker->StoredDPValues.empty()); - - // Validating the first block should continue to not be a problem, - EXPECT_FALSE(BB1->validateDbgValues(false, false)); - // But if we were to break something, it should be able to fire. Don't attempt - // to comprehensively test the validator, it's a smoke-test rather than a - // "proper" verification pass. - DPV1->setMarker(nullptr); - // A marker pointing the wrong way should be an error. - EXPECT_TRUE(BB1->validateDbgValues(false, false)); - DPV1->setMarker(FirstInst->DbgMarker); - - DILocalVariable *DLV1 = DPV1->getVariable(); - DIExpression *Expr1 = DPV1->getExpression(); - DILocalVariable *DLV2 = DPV2->getVariable(); - DIExpression *Expr2 = DPV2->getExpression(); - - // Convert everything back to the "old" format and ensure it's right. - M->convertFromNewDbgValues(); - EXPECT_FALSE(M->IsNewDbgInfoFormat); - EXPECT_FALSE(F->IsNewDbgInfoFormat); - EXPECT_FALSE(BB1->IsNewDbgInfoFormat); - - EXPECT_EQ(BB1->size(), 4u); - ASSERT_TRUE(isa<DbgValueInst>(BB1->front())); - DbgValueInst *DVI1 = cast<DbgValueInst>(&BB1->front()); - // These dbg.values should still point at the same places. - EXPECT_TRUE(isa<Argument>(DVI1->getVariableLocationOp(0))); - DbgValueInst *DVI2 = cast<DbgValueInst>(DVI1->getNextNode()->getNextNode()); - EXPECT_EQ(DVI2->getVariableLocationOp(0), FirstInst); - - // Check a few fields too, - EXPECT_EQ(DVI1->getVariable(), DLV1); - EXPECT_EQ(DVI1->getExpression(), Expr1); - EXPECT_EQ(DVI2->getVariable(), DLV2); - EXPECT_EQ(DVI2->getExpression(), Expr2); - - UseNewDbgInfoFormat = false; -} - } // end namespace diff --git a/llvm/unittests/Transforms/Utils/LocalTest.cpp b/llvm/unittests/Transforms/Utils/LocalTest.cpp index 1318163..a27af6e 100644 --- a/llvm/unittests/Transforms/Utils/LocalTest.cpp +++ b/llvm/unittests/Transforms/Utils/LocalTest.cpp @@ -1277,69 +1277,3 @@ TEST(Local, ExpressionForConstant) { Expr = createExpression(ConstantFP::get(PPC_FP128Ty, 32), PPC_FP128Ty); EXPECT_EQ(Expr, nullptr); } - -TEST(Local, ReplaceDPValue) { - LLVMContext C; - - // Test that RAUW also replaces the operands of DPValue objects, i.e. - // non-instruction stored debugging information. - std::unique_ptr<Module> M = parseIR(C, - R"( - declare void @llvm.dbg.value(metadata, metadata, metadata) - define void @f(i32 %a) !dbg !8 { - entry: - %foo = add i32 %a, 1, !dbg !13 - %bar = add i32 %foo, 0, !dbg !13 - call void @llvm.dbg.value(metadata i32 %bar, metadata !11, metadata !DIExpression()), !dbg !13 - ret void, !dbg !14 - } - !llvm.dbg.cu = !{!0} - !llvm.module.flags = !{!3, !4} - !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) - !1 = !DIFile(filename: "t2.c", directory: "foo") - !2 = !{} - !3 = !{i32 2, !"Dwarf Version", i32 4} - !4 = !{i32 2, !"Debug Info Version", i32 3} - !8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2) - !9 = !DISubroutineType(types: !10) - !10 = !{null} - !11 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !12) - !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) - !13 = !DILocation(line: 2, column: 7, scope: !8) - !14 = !DILocation(line: 3, column: 1, scope: !8) - )"); - auto *GV = M->getNamedValue("f"); - ASSERT_TRUE(GV); - auto *F = dyn_cast<Function>(GV); - ASSERT_TRUE(F); - BasicBlock::iterator It = F->front().begin(); - Instruction *FooInst = &*It; - It = std::next(It); - Instruction *BarInst = &*It; - It = std::next(It); - DbgValueInst *DVI = dyn_cast<DbgValueInst>(It); - ASSERT_TRUE(DVI); - It = std::next(It); - Instruction *RetInst = &*It; - - // Convert DVI into a DPValue. - RetInst->DbgMarker = new DPMarker(); - RetInst->DbgMarker->MarkedInstr = RetInst; - DPValue *DPV = new DPValue(DVI); - RetInst->DbgMarker->insertDPValue(DPV, false); - // ... and erase the dbg.value. - DVI->eraseFromParent(); - - // DPV should originally refer to %bar, - EXPECT_EQ(DPV->getVariableLocationOp(0), BarInst); - - // Now try to replace the computation of %bar with %foo -- this should cause - // the DPValue's to have it's operand updated beneath it. - BarInst->replaceAllUsesWith(FooInst); - // Check DPV now points at %foo. - EXPECT_EQ(DPV->getVariableLocationOp(0), FooInst); - - // Teardown. - RetInst->DbgMarker->eraseFromParent(); -} - diff --git a/llvm/utils/gn/secondary/llvm/lib/IR/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/IR/BUILD.gn index 8c2e8ab..298f449 100644 --- a/llvm/utils/gn/secondary/llvm/lib/IR/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/IR/BUILD.gn @@ -31,7 +31,6 @@ static_library("IR") { "DataLayout.cpp", "DebugInfo.cpp", "DebugInfoMetadata.cpp", - "DebugProgramInstruction.cpp", "DebugLoc.cpp", "DiagnosticHandler.cpp", "DiagnosticInfo.cpp", |