1//===- SandboxIR.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// Sandbox IR is a lightweight overlay transactional IR on top of LLVM IR.
10// Features:
11// - You can save/rollback the state of the IR at any time.
12// - Any changes made to Sandbox IR will automatically update the underlying
13// LLVM IR so both IRs are always in sync.
14// - Feels like LLVM IR, similar API.
15//
16// SandboxIR forms a class hierarchy that resembles that of LLVM IR
17// but is in the `sandboxir` namespace:
18//
19// namespace sandboxir {
20//
21// +- Argument +- BinaryOperator
22// | |
23// Value -+- BasicBlock +- BranchInst
24// | |
25// +- Function +- Constant +- CastInst
26// | | |
27// +- User ------+- Instruction -+- CallInst
28// |
29// +- CmpInst
30// |
31// +- ExtractElementInst
32// |
33// +- GetElementPtrInst
34// |
35// +- InsertElementInst
36// |
37// +- LoadInst
38// |
39// +- OpaqueInst
40// |
41// +- PHINode
42// |
43// +- ReturnInst
44// |
45// +- SelectInst
46// |
47// +- ShuffleVectorInst
48// |
49// +- StoreInst
50// |
51// +- UnaryOperator
52//
53// Use
54//
55// } // namespace sandboxir
56//
57
58#ifndef LLVM_SANDBOXIR_SANDBOXIR_H
59#define LLVM_SANDBOXIR_SANDBOXIR_H
60
61#include "llvm/IR/Function.h"
62#include "llvm/IR/IRBuilder.h"
63#include "llvm/IR/User.h"
64#include "llvm/IR/Value.h"
65#include "llvm/SandboxIR/Tracker.h"
66#include "llvm/SandboxIR/Use.h"
67#include "llvm/Support/raw_ostream.h"
68#include <iterator>
69
70namespace llvm {
71
72namespace sandboxir {
73
74class BasicBlock;
75class Context;
76class Function;
77class Instruction;
78class SelectInst;
79class LoadInst;
80class ReturnInst;
81class StoreInst;
82class User;
83class Value;
84
85/// Iterator for the `Use` edges of a User's operands.
86/// \Returns the operand `Use` when dereferenced.
87class OperandUseIterator {
88 sandboxir::Use Use;
89 /// Don't let the user create a non-empty OperandUseIterator.
90 OperandUseIterator(const class Use &Use) : Use(Use) {}
91 friend class User; // For constructor
92#define DEF_INSTR(ID, OPC, CLASS) friend class CLASS; // For constructor
93#include "llvm/SandboxIR/SandboxIRValues.def"
94
95public:
96 using difference_type = std::ptrdiff_t;
97 using value_type = sandboxir::Use;
98 using pointer = value_type *;
99 using reference = value_type &;
100 using iterator_category = std::input_iterator_tag;
101
102 OperandUseIterator() = default;
103 value_type operator*() const;
104 OperandUseIterator &operator++();
105 bool operator==(const OperandUseIterator &Other) const {
106 return Use == Other.Use;
107 }
108 bool operator!=(const OperandUseIterator &Other) const {
109 return !(*this == Other);
110 }
111};
112
113/// Iterator for the `Use` edges of a Value's users.
114/// \Returns a `Use` when dereferenced.
115class UserUseIterator {
116 sandboxir::Use Use;
117 /// Don't let the user create a non-empty UserUseIterator.
118 UserUseIterator(const class Use &Use) : Use(Use) {}
119 friend class Value; // For constructor
120
121public:
122 using difference_type = std::ptrdiff_t;
123 using value_type = sandboxir::Use;
124 using pointer = value_type *;
125 using reference = value_type &;
126 using iterator_category = std::input_iterator_tag;
127
128 UserUseIterator() = default;
129 value_type operator*() const { return Use; }
130 UserUseIterator &operator++();
131 bool operator==(const UserUseIterator &Other) const {
132 return Use == Other.Use;
133 }
134 bool operator!=(const UserUseIterator &Other) const {
135 return !(*this == Other);
136 }
137};
138
139/// A SandboxIR Value has users. This is the base class.
140class Value {
141public:
142 enum class ClassID : unsigned {
143#define DEF_VALUE(ID, CLASS) ID,
144#define DEF_USER(ID, CLASS) ID,
145#define DEF_INSTR(ID, OPC, CLASS) ID,
146#include "llvm/SandboxIR/SandboxIRValues.def"
147 };
148
149protected:
150 static const char *getSubclassIDStr(ClassID ID) {
151 switch (ID) {
152#define DEF_VALUE(ID, CLASS) \
153 case ClassID::ID: \
154 return #ID;
155#define DEF_USER(ID, CLASS) \
156 case ClassID::ID: \
157 return #ID;
158#define DEF_INSTR(ID, OPC, CLASS) \
159 case ClassID::ID: \
160 return #ID;
161#include "llvm/SandboxIR/SandboxIRValues.def"
162 }
163 llvm_unreachable("Unimplemented ID");
164 }
165
166 /// For isa/dyn_cast.
167 ClassID SubclassID;
168#ifndef NDEBUG
169 /// A unique ID used for forming the name (used for debugging).
170 unsigned UID;
171#endif
172 /// The LLVM Value that corresponds to this SandboxIR Value.
173 /// NOTE: Some sandboxir Instructions, like Packs, may include more than one
174 /// value and in these cases `Val` points to the last instruction in program
175 /// order.
176 llvm::Value *Val = nullptr;
177
178 friend class Context; // For getting `Val`.
179 friend class User; // For getting `Val`.
180 friend class Use; // For getting `Val`.
181 friend class SelectInst; // For getting `Val`.
182 friend class LoadInst; // For getting `Val`.
183 friend class StoreInst; // For getting `Val`.
184 friend class ReturnInst; // For getting `Val`.
185
186 /// All values point to the context.
187 Context &Ctx;
188 // This is used by eraseFromParent().
189 void clearValue() { Val = nullptr; }
190 template <typename ItTy, typename SBTy> friend class LLVMOpUserItToSBTy;
191
192 Value(ClassID SubclassID, llvm::Value *Val, Context &Ctx);
193
194public:
195 virtual ~Value() = default;
196 ClassID getSubclassID() const { return SubclassID; }
197
198 using use_iterator = UserUseIterator;
199 using const_use_iterator = UserUseIterator;
200
201 use_iterator use_begin();
202 const_use_iterator use_begin() const {
203 return const_cast<Value *>(this)->use_begin();
204 }
205 use_iterator use_end() { return use_iterator(Use(nullptr, nullptr, Ctx)); }
206 const_use_iterator use_end() const {
207 return const_cast<Value *>(this)->use_end();
208 }
209
210 iterator_range<use_iterator> uses() {
211 return make_range<use_iterator>(x: use_begin(), y: use_end());
212 }
213 iterator_range<const_use_iterator> uses() const {
214 return make_range<const_use_iterator>(x: use_begin(), y: use_end());
215 }
216
217 /// Helper for mapped_iterator.
218 struct UseToUser {
219 User *operator()(const Use &Use) const { return &*Use.getUser(); }
220 };
221
222 using user_iterator = mapped_iterator<sandboxir::UserUseIterator, UseToUser>;
223 using const_user_iterator = user_iterator;
224
225 user_iterator user_begin();
226 user_iterator user_end() {
227 return user_iterator(Use(nullptr, nullptr, Ctx), UseToUser());
228 }
229 const_user_iterator user_begin() const {
230 return const_cast<Value *>(this)->user_begin();
231 }
232 const_user_iterator user_end() const {
233 return const_cast<Value *>(this)->user_end();
234 }
235
236 iterator_range<user_iterator> users() {
237 return make_range<user_iterator>(x: user_begin(), y: user_end());
238 }
239 iterator_range<const_user_iterator> users() const {
240 return make_range<const_user_iterator>(x: user_begin(), y: user_end());
241 }
242 /// \Returns the number of user edges (not necessarily to unique users).
243 /// WARNING: This is a linear-time operation.
244 unsigned getNumUses() const;
245 /// Return true if this value has N uses or more.
246 /// This is logically equivalent to getNumUses() >= N.
247 /// WARNING: This can be expensive, as it is linear to the number of users.
248 bool hasNUsesOrMore(unsigned Num) const {
249 unsigned Cnt = 0;
250 for (auto It = use_begin(), ItE = use_end(); It != ItE; ++It) {
251 if (++Cnt >= Num)
252 return true;
253 }
254 return false;
255 }
256 /// Return true if this Value has exactly N uses.
257 bool hasNUses(unsigned Num) const {
258 unsigned Cnt = 0;
259 for (auto It = use_begin(), ItE = use_end(); It != ItE; ++It) {
260 if (++Cnt > Num)
261 return false;
262 }
263 return Cnt == Num;
264 }
265
266 Type *getType() const { return Val->getType(); }
267
268 Context &getContext() const { return Ctx; }
269
270 void replaceUsesWithIf(Value *OtherV,
271 llvm::function_ref<bool(const Use &)> ShouldReplace);
272 void replaceAllUsesWith(Value *Other);
273
274 /// \Returns the LLVM IR name of the bottom-most LLVM value.
275 StringRef getName() const { return Val->getName(); }
276
277#ifndef NDEBUG
278 /// Should crash if there is something wrong with the instruction.
279 virtual void verify() const = 0;
280 /// Returns the unique id in the form 'SB<number>.' like 'SB1.'
281 std::string getUid() const;
282 virtual void dumpCommonHeader(raw_ostream &OS) const;
283 void dumpCommonFooter(raw_ostream &OS) const;
284 void dumpCommonPrefix(raw_ostream &OS) const;
285 void dumpCommonSuffix(raw_ostream &OS) const;
286 void printAsOperandCommon(raw_ostream &OS) const;
287 friend raw_ostream &operator<<(raw_ostream &OS, const sandboxir::Value &V) {
288 V.dump(OS);
289 return OS;
290 }
291 virtual void dump(raw_ostream &OS) const = 0;
292 LLVM_DUMP_METHOD virtual void dump() const = 0;
293#endif
294};
295
296/// Argument of a sandboxir::Function.
297class Argument : public sandboxir::Value {
298 Argument(llvm::Argument *Arg, sandboxir::Context &Ctx)
299 : sandboxir::Value(ClassID::Argument, Arg, Ctx) {}
300 friend class Context; // For constructor.
301
302public:
303 static bool classof(const sandboxir::Value *From) {
304 return From->getSubclassID() == ClassID::Argument;
305 }
306#ifndef NDEBUG
307 void verify() const final {
308 assert(isa<llvm::Argument>(Val) && "Expected Argument!");
309 }
310 friend raw_ostream &operator<<(raw_ostream &OS,
311 const sandboxir::Argument &TArg) {
312 TArg.dump(OS);
313 return OS;
314 }
315 void printAsOperand(raw_ostream &OS) const;
316 void dump(raw_ostream &OS) const final;
317 LLVM_DUMP_METHOD void dump() const final;
318#endif
319};
320
321/// A sandboxir::User has operands.
322class User : public Value {
323protected:
324 User(ClassID ID, llvm::Value *V, Context &Ctx) : Value(ID, V, Ctx) {}
325
326 /// \Returns the Use edge that corresponds to \p OpIdx.
327 /// Note: This is the default implementation that works for instructions that
328 /// match the underlying LLVM instruction. All others should use a different
329 /// implementation.
330 Use getOperandUseDefault(unsigned OpIdx, bool Verify) const;
331 /// \Returns the Use for the \p OpIdx'th operand. This is virtual to allow
332 /// instructions to deviate from the LLVM IR operands, which is a requirement
333 /// for sandboxir Instructions that consist of more than one LLVM Instruction.
334 virtual Use getOperandUseInternal(unsigned OpIdx, bool Verify) const = 0;
335 friend class OperandUseIterator; // for getOperandUseInternal()
336
337 /// The default implementation works only for single-LLVMIR-instruction
338 /// Users and only if they match exactly the LLVM instruction.
339 unsigned getUseOperandNoDefault(const Use &Use) const {
340 return Use.LLVMUse->getOperandNo();
341 }
342 /// \Returns the operand index of \p Use.
343 virtual unsigned getUseOperandNo(const Use &Use) const = 0;
344 friend unsigned Use::getOperandNo() const; // For getUseOperandNo()
345
346#ifndef NDEBUG
347 void verifyUserOfLLVMUse(const llvm::Use &Use) const;
348#endif // NDEBUG
349
350public:
351 /// For isa/dyn_cast.
352 static bool classof(const Value *From);
353 using op_iterator = OperandUseIterator;
354 using const_op_iterator = OperandUseIterator;
355 using op_range = iterator_range<op_iterator>;
356 using const_op_range = iterator_range<const_op_iterator>;
357
358 virtual op_iterator op_begin() {
359 assert(isa<llvm::User>(Val) && "Expect User value!");
360 return op_iterator(getOperandUseInternal(OpIdx: 0, /*Verify=*/Verify: false));
361 }
362 virtual op_iterator op_end() {
363 assert(isa<llvm::User>(Val) && "Expect User value!");
364 return op_iterator(
365 getOperandUseInternal(OpIdx: getNumOperands(), /*Verify=*/Verify: false));
366 }
367 virtual const_op_iterator op_begin() const {
368 return const_cast<User *>(this)->op_begin();
369 }
370 virtual const_op_iterator op_end() const {
371 return const_cast<User *>(this)->op_end();
372 }
373
374 op_range operands() { return make_range<op_iterator>(x: op_begin(), y: op_end()); }
375 const_op_range operands() const {
376 return make_range<const_op_iterator>(x: op_begin(), y: op_end());
377 }
378 Value *getOperand(unsigned OpIdx) const { return getOperandUse(OpIdx).get(); }
379 /// \Returns the operand edge for \p OpIdx. NOTE: This should also work for
380 /// OpIdx == getNumOperands(), which is used for op_end().
381 Use getOperandUse(unsigned OpIdx) const {
382 return getOperandUseInternal(OpIdx, /*Verify=*/Verify: true);
383 }
384 virtual unsigned getNumOperands() const {
385 return isa<llvm::User>(Val) ? cast<llvm::User>(Val)->getNumOperands() : 0;
386 }
387
388 virtual void setOperand(unsigned OperandIdx, Value *Operand);
389 /// Replaces any operands that match \p FromV with \p ToV. Returns whether any
390 /// operands were replaced.
391 bool replaceUsesOfWith(Value *FromV, Value *ToV);
392
393#ifndef NDEBUG
394 void verify() const override {
395 assert(isa<llvm::User>(Val) && "Expected User!");
396 }
397 void dumpCommonHeader(raw_ostream &OS) const final;
398 void dump(raw_ostream &OS) const override {
399 // TODO: Remove this tmp implementation once we get the Instruction classes.
400 }
401 LLVM_DUMP_METHOD void dump() const override {
402 // TODO: Remove this tmp implementation once we get the Instruction classes.
403 }
404#endif
405};
406
407class Constant : public sandboxir::User {
408 Constant(llvm::Constant *C, sandboxir::Context &SBCtx)
409 : sandboxir::User(ClassID::Constant, C, SBCtx) {}
410 friend class Context; // For constructor.
411 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
412 return getOperandUseDefault(OpIdx, Verify);
413 }
414
415public:
416 static Constant *createInt(Type *Ty, uint64_t V, Context &Ctx,
417 bool IsSigned = false);
418 /// For isa/dyn_cast.
419 static bool classof(const sandboxir::Value *From) {
420 return From->getSubclassID() == ClassID::Constant ||
421 From->getSubclassID() == ClassID::Function;
422 }
423 sandboxir::Context &getParent() const { return getContext(); }
424 unsigned getUseOperandNo(const Use &Use) const final {
425 return getUseOperandNoDefault(Use);
426 }
427#ifndef NDEBUG
428 void verify() const final {
429 assert(isa<llvm::Constant>(Val) && "Expected Constant!");
430 }
431 friend raw_ostream &operator<<(raw_ostream &OS,
432 const sandboxir::Constant &SBC) {
433 SBC.dump(OS);
434 return OS;
435 }
436 void dump(raw_ostream &OS) const override;
437 LLVM_DUMP_METHOD void dump() const override;
438#endif
439};
440
441/// Iterator for `Instruction`s in a `BasicBlock.
442/// \Returns an sandboxir::Instruction & when derereferenced.
443class BBIterator {
444public:
445 using difference_type = std::ptrdiff_t;
446 using value_type = Instruction;
447 using pointer = value_type *;
448 using reference = value_type &;
449 using iterator_category = std::bidirectional_iterator_tag;
450
451private:
452 llvm::BasicBlock *BB;
453 llvm::BasicBlock::iterator It;
454 Context *Ctx;
455 pointer getInstr(llvm::BasicBlock::iterator It) const;
456
457public:
458 BBIterator() : BB(nullptr), Ctx(nullptr) {}
459 BBIterator(llvm::BasicBlock *BB, llvm::BasicBlock::iterator It, Context *Ctx)
460 : BB(BB), It(It), Ctx(Ctx) {}
461 reference operator*() const { return *getInstr(It); }
462 BBIterator &operator++();
463 BBIterator operator++(int) {
464 auto Copy = *this;
465 ++*this;
466 return Copy;
467 }
468 BBIterator &operator--();
469 BBIterator operator--(int) {
470 auto Copy = *this;
471 --*this;
472 return Copy;
473 }
474 bool operator==(const BBIterator &Other) const {
475 assert(Ctx == Other.Ctx && "BBIterators in different context!");
476 return It == Other.It;
477 }
478 bool operator!=(const BBIterator &Other) const { return !(*this == Other); }
479 /// \Returns the SBInstruction that corresponds to this iterator, or null if
480 /// the instruction is not found in the IR-to-SandboxIR tables.
481 pointer get() const { return getInstr(It); }
482};
483
484/// A sandboxir::User with operands, opcode and linked with previous/next
485/// instructions in an instruction list.
486class Instruction : public sandboxir::User {
487public:
488 enum class Opcode {
489#define DEF_VALUE(ID, CLASS)
490#define DEF_USER(ID, CLASS)
491#define OP(OPC) OPC,
492#define DEF_INSTR(ID, OPC, CLASS) OPC
493#include "llvm/SandboxIR/SandboxIRValues.def"
494 };
495
496protected:
497 Instruction(ClassID ID, Opcode Opc, llvm::Instruction *I,
498 sandboxir::Context &SBCtx)
499 : sandboxir::User(ID, I, SBCtx), Opc(Opc) {}
500
501 Opcode Opc;
502
503 /// A SandboxIR Instruction may map to multiple LLVM IR Instruction. This
504 /// returns its topmost LLVM IR instruction.
505 llvm::Instruction *getTopmostLLVMInstruction() const;
506 friend class SelectInst; // For getTopmostLLVMInstruction().
507 friend class LoadInst; // For getTopmostLLVMInstruction().
508 friend class StoreInst; // For getTopmostLLVMInstruction().
509 friend class ReturnInst; // For getTopmostLLVMInstruction().
510
511 /// \Returns the LLVM IR Instructions that this SandboxIR maps to in program
512 /// order.
513 virtual SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const = 0;
514 friend class EraseFromParent; // For getLLVMInstrs().
515
516public:
517 static const char *getOpcodeName(Opcode Opc);
518#ifndef NDEBUG
519 friend raw_ostream &operator<<(raw_ostream &OS, Opcode Opc) {
520 OS << getOpcodeName(Opc);
521 return OS;
522 }
523#endif
524 /// This is used by BasicBlock::iterator.
525 virtual unsigned getNumOfIRInstrs() const = 0;
526 /// \Returns a BasicBlock::iterator for this Instruction.
527 BBIterator getIterator() const;
528 /// \Returns the next sandboxir::Instruction in the block, or nullptr if at
529 /// the end of the block.
530 Instruction *getNextNode() const;
531 /// \Returns the previous sandboxir::Instruction in the block, or nullptr if
532 /// at the beginning of the block.
533 Instruction *getPrevNode() const;
534 /// \Returns this Instruction's opcode. Note that SandboxIR has its own opcode
535 /// state to allow for new SandboxIR-specific instructions.
536 Opcode getOpcode() const { return Opc; }
537 /// Detach this from its parent BasicBlock without deleting it.
538 void removeFromParent();
539 /// Detach this Value from its parent and delete it.
540 void eraseFromParent();
541 /// Insert this detached instruction before \p BeforeI.
542 void insertBefore(Instruction *BeforeI);
543 /// Insert this detached instruction after \p AfterI.
544 void insertAfter(Instruction *AfterI);
545 /// Insert this detached instruction into \p BB at \p WhereIt.
546 void insertInto(BasicBlock *BB, const BBIterator &WhereIt);
547 /// Move this instruction to \p WhereIt.
548 void moveBefore(BasicBlock &BB, const BBIterator &WhereIt);
549 /// Move this instruction before \p Before.
550 void moveBefore(Instruction *Before) {
551 moveBefore(BB&: *Before->getParent(), WhereIt: Before->getIterator());
552 }
553 /// Move this instruction after \p After.
554 void moveAfter(Instruction *After) {
555 moveBefore(BB&: *After->getParent(), WhereIt: std::next(x: After->getIterator()));
556 }
557 /// \Returns the BasicBlock containing this Instruction, or null if it is
558 /// detached.
559 BasicBlock *getParent() const;
560 /// For isa/dyn_cast.
561 static bool classof(const sandboxir::Value *From);
562
563#ifndef NDEBUG
564 friend raw_ostream &operator<<(raw_ostream &OS,
565 const sandboxir::Instruction &SBI) {
566 SBI.dump(OS);
567 return OS;
568 }
569 void dump(raw_ostream &OS) const override;
570 LLVM_DUMP_METHOD void dump() const override;
571#endif
572};
573
574class SelectInst : public Instruction {
575 /// Use Context::createSelectInst(). Don't call the
576 /// constructor directly.
577 SelectInst(llvm::SelectInst *CI, Context &Ctx)
578 : Instruction(ClassID::Select, Opcode::Select, CI, Ctx) {}
579 friend Context; // for SelectInst()
580 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
581 return getOperandUseDefault(OpIdx, Verify);
582 }
583 SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
584 return {cast<llvm::Instruction>(Val)};
585 }
586 static Value *createCommon(Value *Cond, Value *True, Value *False,
587 const Twine &Name, IRBuilder<> &Builder,
588 Context &Ctx);
589
590public:
591 unsigned getUseOperandNo(const Use &Use) const final {
592 return getUseOperandNoDefault(Use);
593 }
594 unsigned getNumOfIRInstrs() const final { return 1u; }
595 static Value *create(Value *Cond, Value *True, Value *False,
596 Instruction *InsertBefore, Context &Ctx,
597 const Twine &Name = "");
598 static Value *create(Value *Cond, Value *True, Value *False,
599 BasicBlock *InsertAtEnd, Context &Ctx,
600 const Twine &Name = "");
601 Value *getCondition() { return getOperand(OpIdx: 0); }
602 Value *getTrueValue() { return getOperand(OpIdx: 1); }
603 Value *getFalseValue() { return getOperand(OpIdx: 2); }
604
605 void setCondition(Value *New) { setOperand(OperandIdx: 0, Operand: New); }
606 void setTrueValue(Value *New) { setOperand(OperandIdx: 1, Operand: New); }
607 void setFalseValue(Value *New) { setOperand(OperandIdx: 2, Operand: New); }
608 void swapValues() { cast<llvm::SelectInst>(Val)->swapValues(); }
609 /// For isa/dyn_cast.
610 static bool classof(const Value *From);
611#ifndef NDEBUG
612 void verify() const final {
613 assert(isa<llvm::SelectInst>(Val) && "Expected SelectInst!");
614 }
615 void dump(raw_ostream &OS) const override;
616 LLVM_DUMP_METHOD void dump() const override;
617#endif
618};
619
620class LoadInst final : public Instruction {
621 /// Use LoadInst::create() instead of calling the constructor.
622 LoadInst(llvm::LoadInst *LI, Context &Ctx)
623 : Instruction(ClassID::Load, Opcode::Load, LI, Ctx) {}
624 friend Context; // for LoadInst()
625 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
626 return getOperandUseDefault(OpIdx, Verify);
627 }
628 SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
629 return {cast<llvm::Instruction>(Val)};
630 }
631
632public:
633 unsigned getUseOperandNo(const Use &Use) const final {
634 return getUseOperandNoDefault(Use);
635 }
636
637 unsigned getNumOfIRInstrs() const final { return 1u; }
638 static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
639 Instruction *InsertBefore, Context &Ctx,
640 const Twine &Name = "");
641 static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
642 BasicBlock *InsertAtEnd, Context &Ctx,
643 const Twine &Name = "");
644 /// For isa/dyn_cast.
645 static bool classof(const Value *From);
646 Value *getPointerOperand() const;
647 Align getAlign() const { return cast<llvm::LoadInst>(Val)->getAlign(); }
648 bool isUnordered() const { return cast<llvm::LoadInst>(Val)->isUnordered(); }
649 bool isSimple() const { return cast<llvm::LoadInst>(Val)->isSimple(); }
650#ifndef NDEBUG
651 void verify() const final {
652 assert(isa<llvm::LoadInst>(Val) && "Expected LoadInst!");
653 }
654 void dump(raw_ostream &OS) const override;
655 LLVM_DUMP_METHOD void dump() const override;
656#endif
657};
658
659class StoreInst final : public Instruction {
660 /// Use StoreInst::create().
661 StoreInst(llvm::StoreInst *SI, Context &Ctx)
662 : Instruction(ClassID::Store, Opcode::Store, SI, Ctx) {}
663 friend Context; // for StoreInst()
664 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
665 return getOperandUseDefault(OpIdx, Verify);
666 }
667 SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
668 return {cast<llvm::Instruction>(Val)};
669 }
670
671public:
672 unsigned getUseOperandNo(const Use &Use) const final {
673 return getUseOperandNoDefault(Use);
674 }
675 unsigned getNumOfIRInstrs() const final { return 1u; }
676 static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
677 Instruction *InsertBefore, Context &Ctx);
678 static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
679 BasicBlock *InsertAtEnd, Context &Ctx);
680 /// For isa/dyn_cast.
681 static bool classof(const Value *From);
682 Value *getValueOperand() const;
683 Value *getPointerOperand() const;
684 Align getAlign() const { return cast<llvm::StoreInst>(Val)->getAlign(); }
685 bool isSimple() const { return cast<llvm::StoreInst>(Val)->isSimple(); }
686 bool isUnordered() const { return cast<llvm::StoreInst>(Val)->isUnordered(); }
687#ifndef NDEBUG
688 void verify() const final {
689 assert(isa<llvm::StoreInst>(Val) && "Expected StoreInst!");
690 }
691 void dump(raw_ostream &OS) const override;
692 LLVM_DUMP_METHOD void dump() const override;
693#endif
694};
695
696class ReturnInst final : public Instruction {
697 /// Use ReturnInst::create() instead of calling the constructor.
698 ReturnInst(llvm::Instruction *I, Context &Ctx)
699 : Instruction(ClassID::Ret, Opcode::Ret, I, Ctx) {}
700 ReturnInst(ClassID SubclassID, llvm::Instruction *I, Context &Ctx)
701 : Instruction(SubclassID, Opcode::Ret, I, Ctx) {}
702 friend class Context; // For accessing the constructor in create*()
703 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
704 return getOperandUseDefault(OpIdx, Verify);
705 }
706 SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
707 return {cast<llvm::Instruction>(Val)};
708 }
709 static ReturnInst *createCommon(Value *RetVal, IRBuilder<> &Builder,
710 Context &Ctx);
711
712public:
713 static ReturnInst *create(Value *RetVal, Instruction *InsertBefore,
714 Context &Ctx);
715 static ReturnInst *create(Value *RetVal, BasicBlock *InsertAtEnd,
716 Context &Ctx);
717 static bool classof(const Value *From) {
718 return From->getSubclassID() == ClassID::Ret;
719 }
720 unsigned getUseOperandNo(const Use &Use) const final {
721 return getUseOperandNoDefault(Use);
722 }
723 unsigned getNumOfIRInstrs() const final { return 1u; }
724 /// \Returns null if there is no return value.
725 Value *getReturnValue() const;
726#ifndef NDEBUG
727 void verify() const final {}
728 void dump(raw_ostream &OS) const override;
729 LLVM_DUMP_METHOD void dump() const override;
730#endif
731};
732
733/// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to
734/// an OpaqueInstr.
735class OpaqueInst : public sandboxir::Instruction {
736 OpaqueInst(llvm::Instruction *I, sandboxir::Context &Ctx)
737 : sandboxir::Instruction(ClassID::Opaque, Opcode::Opaque, I, Ctx) {}
738 OpaqueInst(ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx)
739 : sandboxir::Instruction(SubclassID, Opcode::Opaque, I, Ctx) {}
740 friend class Context; // For constructor.
741 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
742 return getOperandUseDefault(OpIdx, Verify);
743 }
744 SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
745 return {cast<llvm::Instruction>(Val)};
746 }
747
748public:
749 static bool classof(const sandboxir::Value *From) {
750 return From->getSubclassID() == ClassID::Opaque;
751 }
752 unsigned getUseOperandNo(const Use &Use) const final {
753 return getUseOperandNoDefault(Use);
754 }
755 unsigned getNumOfIRInstrs() const final { return 1u; }
756#ifndef NDEBUG
757 void verify() const final {
758 // Nothing to do
759 }
760 friend raw_ostream &operator<<(raw_ostream &OS,
761 const sandboxir::OpaqueInst &OI) {
762 OI.dump(OS);
763 return OS;
764 }
765 void dump(raw_ostream &OS) const override;
766 LLVM_DUMP_METHOD void dump() const override;
767#endif
768};
769
770/// Contains a list of sandboxir::Instruction's.
771class BasicBlock : public Value {
772 /// Builds a graph that contains all values in \p BB in their original form
773 /// i.e., no vectorization is taking place here.
774 void buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB);
775 friend class Context; // For `buildBasicBlockFromIR`
776 friend class Instruction; // For LLVM Val.
777
778 BasicBlock(llvm::BasicBlock *BB, Context &SBCtx)
779 : Value(ClassID::Block, BB, SBCtx) {
780 buildBasicBlockFromLLVMIR(LLVMBB: BB);
781 }
782
783public:
784 ~BasicBlock() = default;
785 /// For isa/dyn_cast.
786 static bool classof(const Value *From) {
787 return From->getSubclassID() == Value::ClassID::Block;
788 }
789 Function *getParent() const;
790 using iterator = BBIterator;
791 iterator begin() const;
792 iterator end() const {
793 auto *BB = cast<llvm::BasicBlock>(Val);
794 return iterator(BB, BB->end(), &Ctx);
795 }
796 std::reverse_iterator<iterator> rbegin() const {
797 return std::make_reverse_iterator(i: end());
798 }
799 std::reverse_iterator<iterator> rend() const {
800 return std::make_reverse_iterator(i: begin());
801 }
802 Context &getContext() const { return Ctx; }
803 Instruction *getTerminator() const;
804 bool empty() const { return begin() == end(); }
805 Instruction &front() const;
806 Instruction &back() const;
807
808#ifndef NDEBUG
809 void verify() const final {
810 assert(isa<llvm::BasicBlock>(Val) && "Expected BasicBlock!");
811 }
812 friend raw_ostream &operator<<(raw_ostream &OS, const BasicBlock &SBBB) {
813 SBBB.dump(OS);
814 return OS;
815 }
816 void dump(raw_ostream &OS) const final;
817 LLVM_DUMP_METHOD void dump() const final;
818#endif
819};
820
821class Context {
822protected:
823 LLVMContext &LLVMCtx;
824 Tracker IRTracker;
825
826 /// Maps LLVM Value to the corresponding sandboxir::Value. Owns all
827 /// SandboxIR objects.
828 DenseMap<llvm::Value *, std::unique_ptr<sandboxir::Value>>
829 LLVMValueToValueMap;
830
831 /// Remove \p V from the maps and returns the unique_ptr.
832 std::unique_ptr<Value> detachLLVMValue(llvm::Value *V);
833 /// Remove \p SBV from all SandboxIR maps and stop owning it. This effectively
834 /// detaches \p V from the underlying IR.
835 std::unique_ptr<Value> detach(Value *V);
836 friend void Instruction::eraseFromParent(); // For detach().
837 /// Take ownership of VPtr and store it in `LLVMValueToValueMap`.
838 Value *registerValue(std::unique_ptr<Value> &&VPtr);
839 friend class EraseFromParent; // For registerValue().
840 /// This is the actual function that creates sandboxir values for \p V,
841 /// and among others handles all instruction types.
842 Value *getOrCreateValueInternal(llvm::Value *V, llvm::User *U = nullptr);
843 /// Get or create a sandboxir::Argument for an existing LLVM IR \p LLVMArg.
844 Argument *getOrCreateArgument(llvm::Argument *LLVMArg) {
845 auto Pair = LLVMValueToValueMap.insert(KV: {LLVMArg, nullptr});
846 auto It = Pair.first;
847 if (Pair.second) {
848 It->second = std::unique_ptr<Argument>(new Argument(LLVMArg, *this));
849 return cast<Argument>(Val: It->second.get());
850 }
851 return cast<Argument>(Val: It->second.get());
852 }
853 /// Get or create a sandboxir::Value for an existing LLVM IR \p LLVMV.
854 Value *getOrCreateValue(llvm::Value *LLVMV) {
855 return getOrCreateValueInternal(V: LLVMV, U: 0);
856 }
857 /// Get or create a sandboxir::Constant from an existing LLVM IR \p LLVMC.
858 Constant *getOrCreateConstant(llvm::Constant *LLVMC) {
859 return cast<Constant>(Val: getOrCreateValueInternal(V: LLVMC, U: 0));
860 }
861 friend class Constant; // For getOrCreateConstant().
862 /// Create a sandboxir::BasicBlock for an existing LLVM IR \p BB. This will
863 /// also create all contents of the block.
864 BasicBlock *createBasicBlock(llvm::BasicBlock *BB);
865
866 friend class BasicBlock; // For getOrCreateValue().
867
868 IRBuilder<ConstantFolder> LLVMIRBuilder;
869 auto &getLLVMIRBuilder() { return LLVMIRBuilder; }
870
871 SelectInst *createSelectInst(llvm::SelectInst *SI);
872 friend SelectInst; // For createSelectInst()
873 LoadInst *createLoadInst(llvm::LoadInst *LI);
874 friend LoadInst; // For createLoadInst()
875 StoreInst *createStoreInst(llvm::StoreInst *SI);
876 friend StoreInst; // For createStoreInst()
877 ReturnInst *createReturnInst(llvm::ReturnInst *I);
878 friend ReturnInst; // For createReturnInst()
879
880public:
881 Context(LLVMContext &LLVMCtx)
882 : LLVMCtx(LLVMCtx), IRTracker(*this),
883 LLVMIRBuilder(LLVMCtx, ConstantFolder()) {}
884
885 Tracker &getTracker() { return IRTracker; }
886 /// Convenience function for `getTracker().save()`
887 void save() { IRTracker.save(); }
888 /// Convenience function for `getTracker().revert()`
889 void revert() { IRTracker.revert(); }
890 /// Convenience function for `getTracker().accept()`
891 void accept() { IRTracker.accept(); }
892
893 sandboxir::Value *getValue(llvm::Value *V) const;
894 const sandboxir::Value *getValue(const llvm::Value *V) const {
895 return getValue(V: const_cast<llvm::Value *>(V));
896 }
897 /// Create a sandboxir::Function for an existing LLVM IR \p F, including all
898 /// blocks and instructions.
899 /// This is the main API function for creating Sandbox IR.
900 Function *createFunction(llvm::Function *F);
901
902 /// \Returns the number of values registered with Context.
903 size_t getNumValues() const { return LLVMValueToValueMap.size(); }
904};
905
906class Function : public sandboxir::Value {
907 /// Helper for mapped_iterator.
908 struct LLVMBBToBB {
909 Context &Ctx;
910 LLVMBBToBB(Context &Ctx) : Ctx(Ctx) {}
911 BasicBlock &operator()(llvm::BasicBlock &LLVMBB) const {
912 return *cast<BasicBlock>(Val: Ctx.getValue(V: &LLVMBB));
913 }
914 };
915 /// Use Context::createFunction() instead.
916 Function(llvm::Function *F, sandboxir::Context &Ctx)
917 : sandboxir::Value(ClassID::Function, F, Ctx) {}
918 friend class Context; // For constructor.
919
920public:
921 /// For isa/dyn_cast.
922 static bool classof(const sandboxir::Value *From) {
923 return From->getSubclassID() == ClassID::Function;
924 }
925
926 Argument *getArg(unsigned Idx) const {
927 llvm::Argument *Arg = cast<llvm::Function>(Val)->getArg(i: Idx);
928 return cast<Argument>(Val: Ctx.getValue(V: Arg));
929 }
930
931 size_t arg_size() const { return cast<llvm::Function>(Val)->arg_size(); }
932 bool arg_empty() const { return cast<llvm::Function>(Val)->arg_empty(); }
933
934 using iterator = mapped_iterator<llvm::Function::iterator, LLVMBBToBB>;
935 iterator begin() const {
936 LLVMBBToBB BBGetter(Ctx);
937 return iterator(cast<llvm::Function>(Val)->begin(), BBGetter);
938 }
939 iterator end() const {
940 LLVMBBToBB BBGetter(Ctx);
941 return iterator(cast<llvm::Function>(Val)->end(), BBGetter);
942 }
943
944#ifndef NDEBUG
945 void verify() const final {
946 assert(isa<llvm::Function>(Val) && "Expected Function!");
947 }
948 void dumpNameAndArgs(raw_ostream &OS) const;
949 void dump(raw_ostream &OS) const final;
950 LLVM_DUMP_METHOD void dump() const final;
951#endif
952};
953
954} // namespace sandboxir
955} // namespace llvm
956
957#endif // LLVM_SANDBOXIR_SANDBOXIR_H
958