LLVM 22.0.0git
Tracker.h
Go to the documentation of this file.
1//===- Tracker.h ------------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is the component of SandboxIR that tracks all changes made to its
10// state, such that we can revert the state when needed.
11//
12// Tracking changes
13// ----------------
14// The user needs to call `Tracker::save()` to enable tracking changes
15// made to SandboxIR. From that point on, any change made to SandboxIR, will
16// automatically create a change tracking object and register it with the
17// tracker. IR-change objects are subclasses of `IRChangeBase` and get
18// registered with the `Tracker::track()` function. The change objects
19// are saved in the order they are registered with the tracker and are stored in
20// the `Tracker::Changes` vector. All of this is done transparently to
21// the user.
22//
23// Reverting changes
24// -----------------
25// Calling `Tracker::revert()` will restore the state saved when
26// `Tracker::save()` was called. Internally this goes through the
27// change objects in `Tracker::Changes` in reverse order, calling their
28// `IRChangeBase::revert()` function one by one.
29//
30// Accepting changes
31// -----------------
32// The user needs to either revert or accept changes before the tracker object
33// is destroyed. This is enforced in the tracker's destructor.
34// This is the job of `Tracker::accept()`. Internally this will go
35// through the change objects in `Tracker::Changes` in order, calling
36// `IRChangeBase::accept()`.
37//
38//===----------------------------------------------------------------------===//
39
40#ifndef LLVM_SANDBOXIR_TRACKER_H
41#define LLVM_SANDBOXIR_TRACKER_H
42
46#include "llvm/IR/IRBuilder.h"
47#include "llvm/IR/Instruction.h"
48#include "llvm/SandboxIR/Use.h"
51#include "llvm/Support/Debug.h"
52#include <memory>
53
54namespace llvm::sandboxir {
55
56class BasicBlock;
57class CallBrInst;
58class LoadInst;
59class StoreInst;
60class Instruction;
61class Tracker;
62class AllocaInst;
63class CatchSwitchInst;
64class SwitchInst;
65class ConstantInt;
66class ShuffleVectorInst;
67class CmpInst;
68class GlobalVariable;
69
70#ifndef NDEBUG
71
72/// A class that saves hashes and textual IR snapshots of functions in a
73/// SandboxIR Context, and does hash comparison when `expectNoDiff` is called.
74/// If hashes differ, it prints textual IR for both old and new versions to
75/// aid debugging.
76///
77/// This is used as an additional debug check when reverting changes to
78/// SandboxIR, to verify the reverted state matches the initial state.
80 Context &Ctx;
81
82 // A snapshot of textual IR for a function, with a hash for quick comparison.
83 struct FunctionSnapshot {
85 std::string TextualIR;
86 };
87
88 // A snapshot for each llvm::Function found in every module in the SandboxIR
89 // Context. In practice there will always be one module, but sandbox IR
90 // save/restore ops work at the Context level, so we must take the full state
91 // into account.
93
94 ContextSnapshot OrigContextSnapshot;
95
96 // Dumps to a string the textual IR for a single Function.
97 std::string dumpIR(const llvm::Function &F) const;
98
99 // Returns a snapshot of all the modules in the sandbox IR context.
100 ContextSnapshot takeSnapshot() const;
101
102 // Compares two snapshots and returns true if they differ.
103 bool diff(const ContextSnapshot &Orig, const ContextSnapshot &Curr) const;
104
105public:
106 IRSnapshotChecker(Context &Ctx) : Ctx(Ctx) {}
107
108 /// Saves a snapshot of the current state. If there was any previous snapshot,
109 /// it will be replaced with the new one.
110 void save();
111
112 /// Checks current state against saved state, crashes if different.
113 void expectNoDiff();
114};
115
116#endif // NDEBUG
117
118/// The base class for IR Change classes.
120protected:
121 friend class Tracker; // For Parent.
122
123public:
124 /// This runs when changes get reverted.
125 virtual void revert(Tracker &Tracker) = 0;
126 /// This runs when changes get accepted.
127 virtual void accept() = 0;
128 virtual ~IRChangeBase() = default;
129#ifndef NDEBUG
130 virtual void dump(raw_ostream &OS) const = 0;
131 LLVM_DUMP_METHOD virtual void dump() const = 0;
133 C.dump(OS);
134 return OS;
135 }
136#endif
137};
138
139/// Tracks the change of the source Value of a sandboxir::Use.
140class UseSet : public IRChangeBase {
141 Use U;
142 Value *OrigV = nullptr;
143
144public:
145 UseSet(const Use &U) : U(U), OrigV(U.get()) {}
146 void revert(Tracker &Tracker) final { U.set(OrigV); }
147 void accept() final {}
148#ifndef NDEBUG
149 void dump(raw_ostream &OS) const final { OS << "UseSet"; }
150 LLVM_DUMP_METHOD void dump() const final;
151#endif
152};
153
155 PHINode *PHI;
156 unsigned RemovedIdx;
157 Value *RemovedV;
158 BasicBlock *RemovedBB;
159
160public:
161 PHIRemoveIncoming(PHINode *PHI, unsigned RemovedIdx);
162 void revert(Tracker &Tracker) final;
163 void accept() final {}
164#ifndef NDEBUG
165 void dump(raw_ostream &OS) const final { OS << "PHISetIncoming"; }
166 LLVM_DUMP_METHOD void dump() const final;
167#endif
168};
169
171 PHINode *PHI;
172 unsigned Idx;
173
174public:
176 void revert(Tracker &Tracker) final;
177 void accept() final {}
178#ifndef NDEBUG
179 void dump(raw_ostream &OS) const final { OS << "PHISetIncoming"; }
180 LLVM_DUMP_METHOD void dump() const final;
181#endif
182};
183
185 CmpInst *Cmp;
186
187public:
189 void revert(Tracker &Tracker) final;
190 void accept() final {}
191#ifndef NDEBUG
192 void dump(raw_ostream &OS) const final { OS << "CmpSwapOperands"; }
193 LLVM_DUMP_METHOD void dump() const final;
194#endif
195};
196
197/// Tracks swapping a Use with another Use.
198class UseSwap : public IRChangeBase {
199 Use ThisUse;
200 Use OtherUse;
201
202public:
203 UseSwap(const Use &ThisUse, const Use &OtherUse)
204 : ThisUse(ThisUse), OtherUse(OtherUse) {
205 assert(ThisUse.getUser() == OtherUse.getUser() && "Expected same user!");
206 }
207 void revert(Tracker &Tracker) final { ThisUse.swap(OtherUse); }
208 void accept() final {}
209#ifndef NDEBUG
210 void dump(raw_ostream &OS) const final { OS << "UseSwap"; }
211 LLVM_DUMP_METHOD void dump() const final;
212#endif
213};
214
216 /// Contains all the data we need to restore an "erased" (i.e., detached)
217 /// instruction: the instruction itself and its operands in order.
218 struct InstrAndOperands {
219 /// The operands that got dropped.
221 /// The instruction that got "erased".
222 llvm::Instruction *LLVMI;
223 };
224 /// The instruction data is in reverse program order, which helps create the
225 /// original program order during revert().
227 /// This is either the next Instruction in the stream, or the parent
228 /// BasicBlock if at the end of the BB.
230 /// We take ownership of the "erased" instruction.
231 std::unique_ptr<sandboxir::Value> ErasedIPtr;
232
233public:
234 EraseFromParent(std::unique_ptr<sandboxir::Value> &&IPtr);
235 void revert(Tracker &Tracker) final;
236 void accept() final;
237#ifndef NDEBUG
238 void dump(raw_ostream &OS) const final { OS << "EraseFromParent"; }
239 LLVM_DUMP_METHOD void dump() const final;
241 C.dump(OS);
242 return OS;
243 }
244#endif
245};
246
248 /// The instruction that is about to get removed.
249 Instruction *RemovedI = nullptr;
250 /// This is either the next instr, or the parent BB if at the end of the BB.
252
253public:
254 RemoveFromParent(Instruction *RemovedI);
255 void revert(Tracker &Tracker) final;
256 void accept() final {};
257 Instruction *getInstruction() const { return RemovedI; }
258#ifndef NDEBUG
259 void dump(raw_ostream &OS) const final { OS << "RemoveFromParent"; }
260 LLVM_DUMP_METHOD void dump() const final;
261#endif // NDEBUG
262};
263
264/// This class can be used for tracking most instruction setters.
265/// The two template arguments are:
266/// - GetterFn: The getter member function pointer (e.g., `&Foo::get`)
267/// - SetterFn: The setter member function pointer (e.g., `&Foo::set`)
268/// Upon construction, it saves a copy of the original value by calling the
269/// getter function. Revert sets the value back to the one saved, using the
270/// setter function provided.
271///
272/// Example:
273/// Tracker.track(std::make_unique<
274/// GenericSetter<&FooInst::get, &FooInst::set>>(I, Tracker));
275///
276template <auto GetterFn, auto SetterFn>
277class GenericSetter final : public IRChangeBase {
278 /// Traits for getting the class type from GetterFn type.
279 template <typename> struct GetClassTypeFromGetter;
280 template <typename RetT, typename ClassT>
281 struct GetClassTypeFromGetter<RetT (ClassT::*)() const> {
282 using ClassType = ClassT;
283 };
284 using InstrT = typename GetClassTypeFromGetter<decltype(GetterFn)>::ClassType;
285 using SavedValT = std::invoke_result_t<decltype(GetterFn), InstrT>;
286 InstrT *I;
287 SavedValT OrigVal;
288
289public:
290 GenericSetter(InstrT *I) : I(I), OrigVal((I->*GetterFn)()) {}
291 void revert(Tracker &Tracker) final { (I->*SetterFn)(OrigVal); }
292 void accept() final {}
293#ifndef NDEBUG
294 void dump(raw_ostream &OS) const final { OS << "GenericSetter"; }
296 dump(dbgs());
297 dbgs() << "\n";
298 }
299#endif
300};
301
302/// Similar to GenericSetter but the setters/getters have an index as their
303/// first argument. This is commont in cases like: getOperand(unsigned Idx)
304template <auto GetterFn, auto SetterFn>
305class GenericSetterWithIdx final : public IRChangeBase {
306 /// Helper for getting the class type from the getter
307 template <typename ClassT, typename RetT>
308 static ClassT getClassTypeFromGetter(RetT (ClassT::*Fn)(unsigned) const);
309 template <typename ClassT, typename RetT>
310 static ClassT getClassTypeFromGetter(RetT (ClassT::*Fn)(unsigned));
311
312 using InstrT = decltype(getClassTypeFromGetter(GetterFn));
313 using SavedValT = std::invoke_result_t<decltype(GetterFn), InstrT, unsigned>;
314 InstrT *I;
315 SavedValT OrigVal;
316 unsigned Idx;
317
318public:
319 GenericSetterWithIdx(InstrT *I, unsigned Idx)
320 : I(I), OrigVal((I->*GetterFn)(Idx)), Idx(Idx) {}
321 void revert(Tracker &Tracker) final { (I->*SetterFn)(Idx, OrigVal); }
322 void accept() final {}
323#ifndef NDEBUG
324 void dump(raw_ostream &OS) const final { OS << "GenericSetterWithIdx"; }
326 dump(dbgs());
327 dbgs() << "\n";
328 }
329#endif
330};
331
333 CatchSwitchInst *CSI;
334 unsigned HandlerIdx;
335
336public:
338 void revert(Tracker &Tracker) final;
339 void accept() final {}
340#ifndef NDEBUG
341 void dump(raw_ostream &OS) const final { OS << "CatchSwitchAddHandler"; }
343 dump(dbgs());
344 dbgs() << "\n";
345 }
346#endif // NDEBUG
347};
348
350 SwitchInst *Switch;
351 ConstantInt *Val;
352
353public:
355 : Switch(Switch), Val(Val) {}
356 void revert(Tracker &Tracker) final;
357 void accept() final {}
358#ifndef NDEBUG
359 void dump(raw_ostream &OS) const final { OS << "SwitchAddCase"; }
360 LLVM_DUMP_METHOD void dump() const final;
361#endif // NDEBUG
362};
363
365 SwitchInst *Switch;
366 struct Case {
367 ConstantInt *Val;
368 BasicBlock *Dest;
369 };
370 SmallVector<Case> Cases;
371
372public:
374
375 void revert(Tracker &Tracker) final;
376 void accept() final {}
377#ifndef NDEBUG
378 void dump(raw_ostream &OS) const final { OS << "SwitchRemoveCase"; }
379 LLVM_DUMP_METHOD void dump() const final;
380#endif // NDEBUG
381};
382
384 /// The instruction that moved.
385 Instruction *MovedI;
386 /// This is either the next instruction in the block, or the parent BB if at
387 /// the end of the BB.
389
390public:
392 void revert(Tracker &Tracker) final;
393 void accept() final {}
394#ifndef NDEBUG
395 void dump(raw_ostream &OS) const final { OS << "MoveInstr"; }
396 LLVM_DUMP_METHOD void dump() const final;
397#endif // NDEBUG
398};
399
400class LLVM_ABI InsertIntoBB final : public IRChangeBase {
401 Instruction *InsertedI = nullptr;
402
403public:
404 InsertIntoBB(Instruction *InsertedI);
405 void revert(Tracker &Tracker) final;
406 void accept() final {}
407#ifndef NDEBUG
408 void dump(raw_ostream &OS) const final { OS << "InsertIntoBB"; }
409 LLVM_DUMP_METHOD void dump() const final;
410#endif // NDEBUG
411};
412
414 Instruction *NewI = nullptr;
415
416public:
417 CreateAndInsertInst(Instruction *NewI) : NewI(NewI) {}
418 void revert(Tracker &Tracker) final;
419 void accept() final {}
420#ifndef NDEBUG
421 void dump(raw_ostream &OS) const final { OS << "CreateAndInsertInst"; }
422 LLVM_DUMP_METHOD void dump() const final;
423#endif
424};
425
428 SmallVector<int, 8> PrevMask;
429
430public:
432 void revert(Tracker &Tracker) final;
433 void accept() final {}
434#ifndef NDEBUG
435 void dump(raw_ostream &OS) const final { OS << "ShuffleVectorSetMask"; }
436 LLVM_DUMP_METHOD void dump() const final;
437#endif
438};
439
440/// The tracker collects all the change objects and implements the main API for
441/// saving / reverting / accepting.
442class Tracker {
443public:
444 enum class TrackerState {
445 Disabled, ///> Tracking is disabled
446 Record, ///> Tracking changes
447 Reverting, ///> Reverting changes
448 };
449
450private:
451 /// The list of changes that are being tracked.
453 /// The current state of the tracker.
455 Context &Ctx;
456
457#ifndef NDEBUG
458 IRSnapshotChecker SnapshotChecker;
459#endif
460
461public:
462#ifndef NDEBUG
463 /// Helps catch bugs where we are creating new change objects while in the
464 /// middle of creating other change objects.
466#endif // NDEBUG
467
468 explicit Tracker(Context &Ctx)
469 : Ctx(Ctx)
470#ifndef NDEBUG
471 ,
472 SnapshotChecker(Ctx)
473#endif
474 {
475 }
476
478 Context &getContext() const { return Ctx; }
479 /// \Returns true if there are no changes tracked.
480 bool empty() const { return Changes.empty(); }
481 /// Record \p Change and take ownership. This is the main function used to
482 /// track Sandbox IR changes.
483 void track(std::unique_ptr<IRChangeBase> &&Change) {
484 assert(State == TrackerState::Record && "The tracker should be tracking!");
485#ifndef NDEBUG
487 "We are in the middle of creating another change!");
488 if (isTracking())
490#endif // NDEBUG
491 Changes.push_back(std::move(Change));
492
493#ifndef NDEBUG
495#endif
496 }
497 /// A convenience wrapper for `track()` that constructs and tracks the Change
498 /// object if tracking is enabled. \Returns true if tracking is enabled.
499 template <typename ChangeT, typename... ArgsT>
500 bool emplaceIfTracking(ArgsT... Args) {
501 if (!isTracking())
502 return false;
503 track(std::make_unique<ChangeT>(Args...));
504 return true;
505 }
506 /// \Returns true if the tracker is recording changes.
507 bool isTracking() const { return State == TrackerState::Record; }
508 /// \Returns the current state of the tracker.
509 TrackerState getState() const { return State; }
510 /// Turns on IR tracking.
511 LLVM_ABI void save();
512 /// Stops tracking and accept changes.
513 LLVM_ABI void accept();
514 /// Stops tracking and reverts to saved state.
515 LLVM_ABI void revert();
516
517#ifndef NDEBUG
518 void dump(raw_ostream &OS) const;
519 LLVM_DUMP_METHOD void dump() const;
521 Tracker.dump(OS);
522 return OS;
523 }
524#endif // NDEBUG
525};
526
527} // namespace llvm::sandboxir
528
529#endif // LLVM_SANDBOXIR_TRACKER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
Rewrite undef for PHI
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define LLVM_ABI
Definition: Compiler.h:213
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:638
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
mir Rename Register Operands
This file defines the PointerUnion class, which is a discriminated union of pointer types.
raw_pwrite_stream & OS
This file defines the SmallVector class.
A discriminated union of two or more pointer types, with the discriminator in the low bit of the poin...
Definition: PointerUnion.h:118
bool empty() const
Definition: SmallVector.h:82
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
Contains a list of sandboxir::Instruction's.
Definition: BasicBlock.h:68
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.h:342
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:339
void dump(raw_ostream &OS) const final
Definition: Tracker.h:341
void dump(raw_ostream &OS) const final
Definition: Tracker.h:192
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:190
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:419
CreateAndInsertInst(Instruction *NewI)
Definition: Tracker.h:417
void dump(raw_ostream &OS) const final
Definition: Tracker.h:421
void dump(raw_ostream &OS) const final
Definition: Tracker.h:238
Similar to GenericSetter but the setters/getters have an index as their first argument.
Definition: Tracker.h:305
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.h:321
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.h:325
void dump(raw_ostream &OS) const final
Definition: Tracker.h:324
GenericSetterWithIdx(InstrT *I, unsigned Idx)
Definition: Tracker.h:319
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:322
This class can be used for tracking most instruction setters.
Definition: Tracker.h:277
void dump(raw_ostream &OS) const final
Definition: Tracker.h:294
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:292
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.h:291
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.h:295
The base class for IR Change classes.
Definition: Tracker.h:119
virtual LLVM_DUMP_METHOD void dump() const =0
virtual void revert(Tracker &Tracker)=0
This runs when changes get reverted.
friend raw_ostream & operator<<(raw_ostream &OS, const IRChangeBase &C)
Definition: Tracker.h:132
virtual ~IRChangeBase()=default
virtual void accept()=0
This runs when changes get accepted.
virtual void dump(raw_ostream &OS) const =0
A class that saves hashes and textual IR snapshots of functions in a SandboxIR Context,...
Definition: Tracker.h:79
void expectNoDiff()
Checks current state against saved state, crashes if different.
Definition: Tracker.cpp:72
void save()
Saves a snapshot of the current state.
Definition: Tracker.cpp:70
void dump(raw_ostream &OS) const final
Definition: Tracker.h:408
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:406
A sandboxir::User with operands, opcode and linked with previous/next instructions in an instruction ...
Definition: Instruction.h:43
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:393
void dump(raw_ostream &OS) const final
Definition: Tracker.h:395
void dump(raw_ostream &OS) const final
Definition: Tracker.h:179
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:177
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:163
void dump(raw_ostream &OS) const final
Definition: Tracker.h:165
void dump(raw_ostream &OS) const final
Definition: Tracker.h:259
Instruction * getInstruction() const
Definition: Tracker.h:257
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:256
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:433
void dump(raw_ostream &OS) const final
Definition: Tracker.h:435
SwitchAddCase(SwitchInst *Switch, ConstantInt *Val)
Definition: Tracker.h:354
void dump(raw_ostream &OS) const final
Definition: Tracker.h:359
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:357
void dump(raw_ostream &OS) const final
Definition: Tracker.h:378
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:376
The tracker collects all the change objects and implements the main API for saving / reverting / acce...
Definition: Tracker.h:442
@ Record
‍Tracking is disabled
LLVM_ABI void revert()
Stops tracking and reverts to saved state.
Definition: Tracker.cpp:346
TrackerState getState() const
\Returns the current state of the tracker.
Definition: Tracker.h:509
bool empty() const
\Returns true if there are no changes tracked.
Definition: Tracker.h:480
friend raw_ostream & operator<<(raw_ostream &OS, const Tracker &Tracker)
Definition: Tracker.h:520
void dump(raw_ostream &OS) const
Definition: Tracker.cpp:367
bool isTracking() const
\Returns true if the tracker is recording changes.
Definition: Tracker.h:507
LLVM_ABI void save()
Turns on IR tracking.
Definition: Tracker.cpp:339
Tracker(Context &Ctx)
Definition: Tracker.h:468
void track(std::unique_ptr< IRChangeBase > &&Change)
Record Change and take ownership.
Definition: Tracker.h:483
bool InMiddleOfCreatingChange
Helps catch bugs where we are creating new change objects while in the middle of creating other chang...
Definition: Tracker.h:465
Context & getContext() const
Definition: Tracker.h:478
bool emplaceIfTracking(ArgsT... Args)
A convenience wrapper for track() that constructs and tracks the Change object if tracking is enabled...
Definition: Tracker.h:500
LLVM_ABI void accept()
Stops tracking and accept changes.
Definition: Tracker.cpp:358
LLVM_DUMP_METHOD void dump() const
Definition: Tracker.cpp:374
Tracks the change of the source Value of a sandboxir::Use.
Definition: Tracker.h:140
UseSet(const Use &U)
Definition: Tracker.h:145
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.h:146
void dump(raw_ostream &OS) const final
Definition: Tracker.h:149
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:147
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:80
Tracks swapping a Use with another Use.
Definition: Tracker.h:198
void revert(Tracker &Tracker) final
This runs when changes get reverted.
Definition: Tracker.h:207
LLVM_DUMP_METHOD void dump() const final
Definition: Tracker.cpp:85
void accept() final
This runs when changes get accepted.
Definition: Tracker.h:208
void dump(raw_ostream &OS) const final
Definition: Tracker.h:210
UseSwap(const Use &ThisUse, const Use &OtherUse)
Definition: Tracker.h:203
Represents a Def-use/Use-def edge in SandboxIR.
Definition: Use.h:33
LLVM_ABI void swap(Use &OtherUse)
Definition: Use.cpp:24
class User * getUser() const
Definition: Use.h:55
A SandboxIR Value has users. This is the base class.
Definition: Value.h:66
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ BasicBlock
Various leaf nodes.
Definition: ISDOpcodes.h:81
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
#define NDEBUG
Definition: regutils.h:48