summaryrefslogtreecommitdiffstats
path: root/llvm/include/llvm/IR/DebugProgramInstruction.h
blob: 9f498749373960b0e2be15d257fb71119163d9b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
//===-- 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 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/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator.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 {
  TrackingMDNodeRef Ref;

public:
public:
  DbgRecordParamRef() = default;

  /// Construct from the templated type.
  DbgRecordParamRef(const T *Param);

  /// Construct from an \a MDNode.
  ///
  /// Note: if \c Param does not have the template type, a verifier check will
  /// fail, and accessors will crash.  However, construction from other nodes
  /// is supported in order to handle forward references when reading textual
  /// IR.
  explicit DbgRecordParamRef(const MDNode *Param);

  /// Get the underlying type.
  ///
  /// \pre !*this or \c isa<T>(getAsMDNode()).
  /// @{
  T *get() const;
  operator T *() const { return get(); }
  T *operator->() const { return get(); }
  T &operator*() const { return *get(); }
  /// @}

  /// Check for null.
  ///
  /// Check for null in a way that is safe with broken debug info.
  explicit operator bool() const { return Ref; }

  /// Return \c this as a \a MDNode.
  MDNode *getAsMDNode() const { return Ref; }

  bool operator==(const DbgRecordParamRef &Other) const {
    return Ref == Other.Ref;
  }
  bool operator!=(const DbgRecordParamRef &Other) const {
    return Ref != Other.Ref;
  }
};

/// 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
/// it's 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> {
public:
  /// Marker that this DbgRecord is linked into.
  DbgMarker *Marker = nullptr;
  /// Subclass discriminator.
  enum Kind : uint8_t { ValueKind, LabelKind };

protected:
  DebugLoc DbgLoc;
  Kind RecordKind; ///< Subclass discriminator.

public:
  DbgRecord(Kind RecordKind, DebugLoc DL)
      : DbgLoc(DL), RecordKind(RecordKind) {}

  /// Methods that dispatch to subclass implementations. These need to be
  /// manually updated when a new subclass is added.
  ///@{
  void deleteRecord();
  DbgRecord *clone() const;
  void print(raw_ostream &O, bool IsForDebug = false) const;
  void print(raw_ostream &O, ModuleSlotTracker &MST, bool IsForDebug) const;
  bool isIdenticalToWhenDefined(const DbgRecord &R) const;
  /// Convert this DbgRecord back into an appropriate llvm.dbg.* intrinsic.
  /// \p InsertBefore Optional position to insert this intrinsic.
  /// \returns A new llvm.dbg.* intrinsic representiung this DbgRecord.
  DbgInfoIntrinsic *createDebugIntrinsic(Module *M,
                                         Instruction *InsertBefore) const;
  ///@}

  /// Same as isIdenticalToWhenDefined but checks DebugLoc too.
  bool isEquivalentTo(const DbgRecord &R) const;

  Kind getRecordKind() const { return RecordKind; }

  void setMarker(DbgMarker *M) { Marker = M; }

  DbgMarker *getMarker() { return Marker; }
  const DbgMarker *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;

  const Instruction *getInstruction() const;
  const BasicBlock *getParent() const;
  BasicBlock *getParent();

  void removeFromParent();
  void eraseFromParent();

  DbgRecord *getNextNode() { return &*std::next(getIterator()); }
  DbgRecord *getPrevNode() { return &*std::prev(getIterator()); }
  void insertBefore(DbgRecord *InsertBefore);
  void insertAfter(DbgRecord *InsertAfter);
  void moveBefore(DbgRecord *MoveBefore);
  void moveAfter(DbgRecord *MoveAfter);

  DebugLoc getDebugLoc() const { return DbgLoc; }
  void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); }

  void dump() const;

  using self_iterator = simple_ilist<DbgRecord>::iterator;
  using const_self_iterator = simple_ilist<DbgRecord>::const_iterator;

protected:
  /// Similarly to Value, we avoid paying the cost of a vtable
  /// by protecting the dtor and having deleteRecord dispatch
  /// cleanup.
  /// Use deleteRecord to delete a generic record.
  ~DbgRecord() = default;
};

inline raw_ostream &operator<<(raw_ostream &OS, const DbgRecord &R) {
  R.print(OS);
  return OS;
}

/// Records a position in IR for a source label (DILabel). Corresponds to the
/// llvm.dbg.label intrinsic.
class DbgLabelRecord : public DbgRecord {
  DbgRecordParamRef<DILabel> Label;

  /// This constructor intentionally left private, so that it is only called via
  /// "createUnresolvedDbgLabelRecord", which clearly expresses that it is for
  /// parsing only.
  DbgLabelRecord(MDNode *Label, MDNode *DL);

public:
  DbgLabelRecord(DILabel *Label, DebugLoc DL);

  /// For use during parsing; creates a DbgLabelRecord from as-of-yet unresolved
  /// MDNodes. Trying to access the resulting DbgLabelRecord's fields before
  /// they are resolved, or if they resolve to the wrong type, will result in a
  /// crash.
  static DbgLabelRecord *createUnresolvedDbgLabelRecord(MDNode *Label,
                                                        MDNode *DL);

  DbgLabelRecord *clone() const;
  void print(raw_ostream &O, bool IsForDebug = false) const;
  void print(raw_ostream &ROS, ModuleSlotTracker &MST, bool IsForDebug) const;
  DbgLabelInst *createDebugIntrinsic(Module *M,
                                     Instruction *InsertBefore) const;

  void setLabel(DILabel *NewLabel) { Label = NewLabel; }
  DILabel *getLabel() const { return Label.get(); }
  MDNode *getRawLabel() const { return Label.getAsMDNode(); };

  /// Support type inquiry through isa, cast, and dyn_cast.
  static bool classof(const DbgRecord *E) {
    return E->getRecordKind() == LabelKind;
  }
};

/// 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 {
  friend class DebugValueUser;

public:
  enum class LocationType : uint8_t {
    Declare,
    Value,
    Assign,

    End, ///< Marks the end of the concrete types.
    Any, ///< To indicate all LocationTypes in searches.
  };
  /// Classification of the debug-info record that this DbgVariableRecord
  /// represents. Essentially, "is this a dbg.value or dbg.declare?".
  /// dbg.declares are not currently supported, but it would be trivial to do
  /// so.
  /// FIXME: We could use spare padding bits from DbgRecord for this.
  LocationType Type;

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

  DbgRecordParamRef<DILocalVariable> Variable;
  DbgRecordParamRef<DIExpression> Expression;
  DbgRecordParamRef<DIExpression> AddressExpression;

public:
  /// Create a new DbgVariableRecord representing the intrinsic \p DVI, for
  /// example the assignment represented by a dbg.value.
  DbgVariableRecord(const DbgVariableIntrinsic *DVI);
  DbgVariableRecord(const DbgVariableRecord &DVR);
  /// Directly construct a new DbgVariableRecord representing a dbg.value
  /// intrinsic assigning \p Location to the DV / Expr / DI variable.
  DbgVariableRecord(Metadata *Location, DILocalVariable *DV, DIExpression *Expr,
                    const DILocation *DI,
                    LocationType Type = LocationType::Value);
  DbgVariableRecord(Metadata *Value, DILocalVariable *Variable,
                    DIExpression *Expression, DIAssignID *AssignID,
                    Metadata *Address, DIExpression *AddressExpression,
                    const DILocation *DI);

private:
  /// Private constructor for creating new instances during parsing only. Only
  /// called through `createUnresolvedDbgVariableRecord` below, which makes
  /// clear that this is used for parsing only, and will later return a subclass
  /// depending on which Type is passed.
  DbgVariableRecord(LocationType Type, Metadata *Val, MDNode *Variable,
                    MDNode *Expression, MDNode *AssignID, Metadata *Address,
                    MDNode *AddressExpression, MDNode *DI);

public:
  /// Used to create DbgVariableRecords during parsing, where some metadata
  /// references may still be unresolved. Although for some fields a generic
  /// `Metadata*` argument is accepted for forward type-references, the verifier
  /// and accessors will reject incorrect types later on. The function is used
  /// for all types of DbgVariableRecords for simplicity while parsing, but
  /// asserts if any necessary fields are empty or unused fields are not empty,
  /// i.e. if the #dbg_assign fields are used for a non-dbg-assign type.
  static DbgVariableRecord *
  createUnresolvedDbgVariableRecord(LocationType Type, Metadata *Val,
                                    MDNode *Variable, MDNode *Expression,
                                    MDNode *AssignID, Metadata *Address,
                                    MDNode *AddressExpression, MDNode *DI);

  static DbgVariableRecord *
  createDVRAssign(Value *Val, DILocalVariable *Variable,
                  DIExpression *Expression, DIAssignID *AssignID,
                  Value *Address, DIExpression *AddressExpression,
                  const DILocation *DI);
  static DbgVariableRecord *
  createLinkedDVRAssign(Instruction *LinkedInstr, Value *Val,
                        DILocalVariable *Variable, DIExpression *Expression,
                        Value *Address, DIExpression *AddressExpression,
                        const DILocation *DI);

  static DbgVariableRecord *createDbgVariableRecord(Value *Location,
                                                    DILocalVariable *DV,
                                                    DIExpression *Expr,
                                                    const DILocation *DI);
  static DbgVariableRecord *
  createDbgVariableRecord(Value *Location, DILocalVariable *DV,
                          DIExpression *Expr, const DILocation *DI,
                          DbgVariableRecord &InsertBefore);
  static DbgVariableRecord *createDVRDeclare(Value *Address,
                                             DILocalVariable *DV,
                                             DIExpression *Expr,
                                             const DILocation *DI);
  static DbgVariableRecord *
  createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr,
                   const DILocation *DI, DbgVariableRecord &InsertBefore);

  /// 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;
    }
  };

  bool isDbgDeclare() { return Type == LocationType::Declare; }
  bool isDbgValue() { return Type == LocationType::Value; }

  /// 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);

  unsigned getNumVariableLocationOps() const;

  bool hasArgList() const { return isa<DIArgList>(getRawLocation()); }
  /// Returns true if this DbgVariableRecord 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::Declare; }
  LocationType getType() const { return Type; }

  void setKillLocation();
  bool isKillLocation() const;

  void setVariable(DILocalVariable *NewVar) { Variable = NewVar; }
  DILocalVariable *getVariable() const { return Variable.get(); };
  MDNode *getRawVariable() const { return Variable.getAsMDNode(); }

  void setExpression(DIExpression *NewExpr) { Expression = NewExpr; }
  DIExpression *getExpression() const { return Expression.get(); }
  MDNode *getRawExpression() const { return Expression.getAsMDNode(); }

  /// Returns the metadata operand for the first location description. i.e.,
  /// dbg intrinsic dbg.value,declare operand and dbg.assign 1st location
  /// operand (the "value componenet"). Note the operand (singular) may be
  /// a DIArgList which is a list of values.
  Metadata *getRawLocation() const { return DebugValues[0]; }

  Value *getValue(unsigned OpIdx = 0) const {
    return getVariableLocationOp(OpIdx);
  }

  /// 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 DbgVariableRecord must be either ValueAsMetadata or "
           "DIArgList");
    resetDebugValue(0, NewLocation);
  }

  /// Get the size (in bits) of the variable, or fragment of the variable that
  /// is described.
  std::optional<uint64_t> getFragmentSizeInBits() const;

  bool isEquivalentTo(const DbgVariableRecord &Other) const {
    return DbgLoc == Other.DbgLoc && isIdenticalToWhenDefined(Other);
  }
  // Matches the definition of the Instruction version, equivalent to above but
  // without checking DbgLoc.
  bool isIdenticalToWhenDefined(const DbgVariableRecord &Other) const {
    return std::tie(Type, DebugValues, Variable, Expression,
                    AddressExpression) ==
           std::tie(Other.Type, Other.DebugValues, Other.Variable,
                    Other.Expression, Other.AddressExpression);
  }

  /// @name DbgAssign Methods
  /// @{
  bool isDbgAssign() const { return getType() == LocationType::Assign; }

  Value *getAddress() const;
  Metadata *getRawAddress() const {
    return isDbgAssign() ? DebugValues[1] : DebugValues[0];
  }
  Metadata *getRawAssignID() const { return DebugValues[2]; }
  DIAssignID *getAssignID() const;
  DIExpression *getAddressExpression() const { return AddressExpression.get(); }
  MDNode *getRawAddressExpression() const {
    return AddressExpression.getAsMDNode();
  }
  void setAddressExpression(DIExpression *NewExpr) {
    AddressExpression = NewExpr;
  }
  void setAssignId(DIAssignID *New);
  void setAddress(Value *V) { resetDebugValue(1, ValueAsMetadata::get(V)); }
  /// Kill the address component.
  void setKillAddress();
  /// Check whether this kills the address component. This doesn't take into
  /// account the position of the intrinsic, therefore a returned value of false
  /// does not guarentee the address is a valid location for the variable at the
  /// intrinsic's position in IR.
  bool isKillAddress() const;

  /// @}

  DbgVariableRecord *clone() const;
  /// Convert this DbgVariableRecord back into a dbg.value intrinsic.
  /// \p InsertBefore Optional position to insert this intrinsic.
  /// \returns A new dbg.value intrinsic representiung this DbgVariableRecord.
  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 print(raw_ostream &O, bool IsForDebug = false) const;
  void print(raw_ostream &ROS, ModuleSlotTracker &MST, bool IsForDebug) const;

  /// Support type inquiry through isa, cast, and dyn_cast.
  static bool classof(const DbgRecord *E) {
    return E->getRecordKind() == ValueKind;
  }
};

/// Filter the DbgRecord range to DbgVariableRecord types only and downcast.
static inline auto
filterDbgVars(iterator_range<simple_ilist<DbgRecord>::iterator> R) {
  return map_range(
      make_filter_range(R,
                        [](DbgRecord &E) { return isa<DbgVariableRecord>(E); }),
      [](DbgRecord &E) { return std::ref(cast<DbgVariableRecord>(E)); });
}

/// 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 {
public:
  DbgMarker() {}
  /// 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 = nullptr;

  /// List of DbgRecords, the non-instruction equivalent of llvm.dbg.*
  /// intrinsics. There is a one-to-one relationship between each debug
  /// intrinsic in a block and each DbgRecord once the representation has been
  /// converted, and the ordering is meaningful in the same way.
  simple_ilist<DbgRecord> StoredDbgRecords;
  bool empty() const { return StoredDbgRecords.empty(); }

  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 DbgMarker.
  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 DbgRecords in this Marker.
  iterator_range<simple_ilist<DbgRecord>::iterator> getDbgRecordRange();
  iterator_range<simple_ilist<DbgRecord>::const_iterator>
  getDbgRecordRange() const;
  /// Transfer any DbgRecords from \p Src into this DbgMarker. If \p
  /// InsertAtHead is true, place them before existing DbgRecords, otherwise
  /// afterwards.
  void absorbDebugValues(DbgMarker &Src, bool InsertAtHead);
  /// Transfer the DbgRecords in \p Range from \p Src into this DbgMarker. If
  /// \p InsertAtHead is true, place them before existing DbgRecords, otherwise
  // afterwards.
  void absorbDebugValues(iterator_range<DbgRecord::self_iterator> Range,
                         DbgMarker &Src, bool InsertAtHead);
  /// Insert a DbgRecord into this DbgMarker, at the end of the list. If
  /// \p InsertAtHead is true, at the start.
  void insertDbgRecord(DbgRecord *New, bool InsertAtHead);
  /// Insert a DbgRecord prior to a DbgRecord contained within this marker.
  void insertDbgRecord(DbgRecord *New, DbgRecord *InsertBefore);
  /// Insert a DbgRecord after a DbgRecord contained within this marker.
  void insertDbgRecordAfter(DbgRecord *New, DbgRecord *InsertAfter);
  /// Clone all DbgMarkers 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
  /// DbgRecords
  /// \p InsertAtHead Place the cloned DbgRecords at the start of
  /// StoredDbgRecords
  /// \returns Range over all the newly cloned DbgRecords
  iterator_range<simple_ilist<DbgRecord>::iterator>
  cloneDebugInfoFrom(DbgMarker *From,
                     std::optional<simple_ilist<DbgRecord>::iterator> FromHere,
                     bool InsertAtHead = false);
  /// Erase all DbgRecords in this DbgMarker.
  void dropDbgRecords();
  /// Erase a single DbgRecord from this marker. In an ideal future, we would
  /// never erase an assignment in this way, but it's the equivalent to
  /// erasing a debug intrinsic from a block.
  void dropOneDbgRecord(DbgRecord *DR);

  /// We generally act like all llvm Instructions have a range of DbgRecords
  /// attached to them, but in reality sometimes we don't allocate the DbgMarker
  /// to save time and memory, but still have to return ranges of DbgRecords.
  /// When we need to describe such an unallocated DbgRecord range, use this
  /// static markers range instead. This will bite us if someone tries to insert
  /// a DbgRecord in that range, but they should be using the Official (TM) API
  /// for that.
  static DbgMarker EmptyDbgMarker;
  static iterator_range<simple_ilist<DbgRecord>::iterator>
  getEmptyDbgRecordRange() {
    return make_range(EmptyDbgMarker.StoredDbgRecords.end(),
                      EmptyDbgMarker.StoredDbgRecords.end());
  }
};

inline raw_ostream &operator<<(raw_ostream &OS, const DbgMarker &Marker) {
  Marker.print(OS);
  return OS;
}

/// 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) {
  if (!DebugMarker)
    return DbgMarker::getEmptyDbgRecordRange();
  return DebugMarker->getDbgRecordRange();
}

DEFINE_ISA_CONVERSION_FUNCTIONS(DbgRecord, LLVMDbgRecordRef)

/// 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 {
  T &Obj;
  bool OldState;

public:
  ScopedDbgInfoFormatSetter(T &Obj, bool NewState)
      : Obj(Obj), OldState(Obj.IsNewDbgInfoFormat) {
    Obj.setIsNewDbgInfoFormat(NewState);
  }
  ~ScopedDbgInfoFormatSetter() { Obj.setIsNewDbgInfoFormat(OldState); }
};

template <typename T>
ScopedDbgInfoFormatSetter(T &Obj,
                          bool NewState) -> ScopedDbgInfoFormatSetter<T>;

} // namespace llvm

#endif // LLVM_IR_DEBUGPROGRAMINSTRUCTION_H