//===-- 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 "DbgRecord" design, each instruction /may/ have a // connection with a DbgMarker, which identifies a position immediately before // the instruction, and each DbgMarker /may/ then have connections to DbgRecords // which record the variable assignment information. To illustrate: // // %foo = add i32 1, %0 // ; foo->DebugMarker == nullptr // ;; There are no variable assignments / debug records "in front" of // ;; the instruction for %foo, therefore it has no DebugMarker. // %bar = void call @ext(%foo) // ; bar->DebugMarker = { // ; StoredDbgRecords = { // ; DbgVariableRecord(metadata i32 %foo, ...) // ; } // ; } // ;; There is a debug-info record in front of the %bar instruction, // ;; thus it points at a DbgMarker object. That DbgMarker contains a // ;; DbgVariableRecord in its 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/ilist.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator.h" #include "llvm/IR/DbgVariableFragmentInfo.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/SymbolTableListTraits.h" #include "llvm/Support/Casting.h" namespace llvm { class Instruction; class BasicBlock; class MDNode; class Module; class DbgVariableIntrinsic; class DbgInfoIntrinsic; class DbgLabelInst; class DIAssignID; class DbgMarker; class DbgVariableRecord; class raw_ostream; /// A typed tracking MDNode reference that does not require a definition for its /// parameter type. Necessary to avoid including DebugInfoMetadata.h, which has /// a significant impact on compile times if included in this file. template <typename T> class DbgRecordParamRef { … }; /// Base class for non-instruction debug metadata records that have positions /// within IR. Features various methods copied across from the Instruction /// class to aid ease-of-use. DbgRecords should always be linked into a /// DbgMarker's StoredDbgRecords list. The marker connects a DbgRecord back to /// its position in the BasicBlock. /// /// We need a discriminator for dyn/isa casts. In order to avoid paying for a /// vtable for "virtual" functions too, subclasses must add a new discriminator /// value (RecordKind) and cases to a few functions in the base class: /// deleteRecord /// clone /// isIdenticalToWhenDefined /// both print methods /// createDebugIntrinsic class DbgRecord : public ilist_node<DbgRecord> { … }; inline raw_ostream &operator<<(raw_ostream &OS, const DbgRecord &R) { … } /// Records a position in IR for a source label (DILabel). Corresponds to the /// llvm.dbg.label intrinsic. class DbgLabelRecord : public DbgRecord { … }; /// Record of a variable value-assignment, aka a non instruction representation /// of the dbg.value intrinsic. /// /// This class inherits from DebugValueUser to allow LLVM's metadata facilities /// to update our references to metadata beneath our feet. class DbgVariableRecord : public DbgRecord, protected DebugValueUser { … }; /// Filter the DbgRecord range to DbgVariableRecord types only and downcast. static inline auto filterDbgVars(iterator_range<simple_ilist<DbgRecord>::iterator> R) { … } /// Per-instruction record of debug-info. If an Instruction is the position of /// some debugging information, it points at a DbgMarker storing that info. Each /// marker points back at the instruction that owns it. Various utilities are /// provided for manipulating the DbgRecords 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 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 DbgMarker { … }; inline raw_ostream &operator<<(raw_ostream &OS, const DbgMarker &Marker) { … } /// Inline helper to return a range of DbgRecords attached to a marker. It needs /// to be inlined as it's frequently called, but also come after the declaration /// of DbgMarker. Thus: it's pre-declared by users like Instruction, then an /// inlineable body defined here. inline iterator_range<simple_ilist<DbgRecord>::iterator> getDbgRecordRange(DbgMarker *DebugMarker) { … } DEFINE_ISA_CONVERSION_FUNCTIONS(…) /// Used to temporarily set the debug info format of a function, module, or /// basic block for the duration of this object's lifetime, after which the /// prior state will be restored. template <typename T> class ScopedDbgInfoFormatSetter { … }; template <typename T> ScopedDbgInfoFormatSetter(T &Obj, bool NewState) -> ScopedDbgInfoFormatSetter<T>; } // namespace llvm #endif // LLVM_IR_DEBUGPROGRAMINSTRUCTION_H