llvm/llvm/include/llvm/IR/DebugProgramInstruction.h

//===-- 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