xref: /llvm-project/llvm/lib/SandboxIR/BasicBlock.cpp (revision e22b07e766e415d6a0ed4c73fe5286fcf25f8d98)
1 //===- BasicBlock.cpp - The BasicBlock class of Sandbox IR ----------------===//
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 #include "llvm/SandboxIR/BasicBlock.h"
10 #include "llvm/SandboxIR/Context.h"
11 #include "llvm/SandboxIR/Function.h"
12 #include "llvm/SandboxIR/Instruction.h"
13 
14 namespace llvm::sandboxir {
15 
16 BBIterator &BBIterator::operator++() {
17   auto ItE = BB->end();
18   assert(It != ItE && "Already at end!");
19   ++It;
20   if (It == ItE)
21     return *this;
22   Instruction &NextI = *cast<sandboxir::Instruction>(Ctx->getValue(&*It));
23   unsigned Num = NextI.getNumOfIRInstrs();
24   assert(Num > 0 && "Bad getNumOfIRInstrs()");
25   It = std::next(It, Num - 1);
26   return *this;
27 }
28 
29 BBIterator &BBIterator::operator--() {
30   assert(It != BB->begin() && "Already at begin!");
31   if (It == BB->end()) {
32     --It;
33     return *this;
34   }
35   Instruction &CurrI = **this;
36   unsigned Num = CurrI.getNumOfIRInstrs();
37   assert(Num > 0 && "Bad getNumOfIRInstrs()");
38   assert(std::prev(It, Num - 1) != BB->begin() && "Already at begin!");
39   It = std::prev(It, Num);
40   return *this;
41 }
42 
43 BasicBlock *BBIterator::getNodeParent() const {
44   llvm::BasicBlock *Parent = const_cast<BBIterator *>(this)->It.getNodeParent();
45   return cast<BasicBlock>(Ctx->getValue(Parent));
46 }
47 
48 BasicBlock::iterator::pointer
49 BasicBlock::iterator::getInstr(llvm::BasicBlock::iterator It) const {
50   return cast_or_null<Instruction>(Ctx->getValue(&*It));
51 }
52 
53 Function *BasicBlock::getParent() const {
54   auto *BB = cast<llvm::BasicBlock>(Val);
55   auto *F = BB->getParent();
56   if (F == nullptr)
57     // Detached
58     return nullptr;
59   return cast_or_null<Function>(Ctx.getValue(F));
60 }
61 
62 void BasicBlock::buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB) {
63   for (llvm::Instruction &IRef : reverse(*LLVMBB)) {
64     llvm::Instruction *I = &IRef;
65     Ctx.getOrCreateValue(I);
66     for (auto [OpIdx, Op] : enumerate(I->operands())) {
67       // Skip instruction's label operands
68       if (isa<llvm::BasicBlock>(Op))
69         continue;
70       // Skip metadata
71       if (isa<llvm::MetadataAsValue>(Op))
72         continue;
73       // Skip asm
74       if (isa<llvm::InlineAsm>(Op))
75         continue;
76       Ctx.getOrCreateValue(Op);
77     }
78   }
79 #if !defined(NDEBUG)
80   verify();
81 #endif
82 }
83 
84 BasicBlock::iterator BasicBlock::begin() const {
85   llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val);
86   llvm::BasicBlock::iterator It = BB->begin();
87   if (!BB->empty()) {
88     auto *V = Ctx.getValue(&*BB->begin());
89     assert(V != nullptr && "No SandboxIR for BB->begin()!");
90     auto *I = cast<Instruction>(V);
91     unsigned Num = I->getNumOfIRInstrs();
92     assert(Num >= 1u && "Bad getNumOfIRInstrs()");
93     It = std::next(It, Num - 1);
94   }
95   return iterator(BB, It, &Ctx);
96 }
97 
98 Instruction *BasicBlock::getTerminator() const {
99   auto *TerminatorV =
100       Ctx.getValue(cast<llvm::BasicBlock>(Val)->getTerminator());
101   return cast_or_null<Instruction>(TerminatorV);
102 }
103 
104 Instruction &BasicBlock::front() const {
105   auto *BB = cast<llvm::BasicBlock>(Val);
106   assert(!BB->empty() && "Empty block!");
107   auto *SBI = cast<Instruction>(getContext().getValue(&*BB->begin()));
108   assert(SBI != nullptr && "Expected Instr!");
109   return *SBI;
110 }
111 
112 Instruction &BasicBlock::back() const {
113   auto *BB = cast<llvm::BasicBlock>(Val);
114   assert(!BB->empty() && "Empty block!");
115   auto *SBI = cast<Instruction>(getContext().getValue(&*BB->rbegin()));
116   assert(SBI != nullptr && "Expected Instr!");
117   return *SBI;
118 }
119 
120 #ifndef NDEBUG
121 void BasicBlock::dumpOS(raw_ostream &OS) const {
122   llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val);
123   const auto &Name = BB->getName();
124   OS << Name;
125   if (!Name.empty())
126     OS << ":\n";
127   // If there are Instructions in the BB that are not mapped to SandboxIR, then
128   // use a crash-proof dump.
129   if (any_of(*BB, [this](llvm::Instruction &I) {
130         return Ctx.getValue(&I) == nullptr;
131       })) {
132     OS << "<Crash-proof mode!>\n";
133     DenseSet<Instruction *> Visited;
134     for (llvm::Instruction &IRef : *BB) {
135       Value *SBV = Ctx.getValue(&IRef);
136       if (SBV == nullptr)
137         OS << IRef << " *** No SandboxIR ***\n";
138       else {
139         auto *SBI = dyn_cast<Instruction>(SBV);
140         if (SBI == nullptr) {
141           OS << IRef << " *** Not a SBInstruction!!! ***\n";
142         } else {
143           if (Visited.insert(SBI).second)
144             OS << *SBI << "\n";
145         }
146       }
147     }
148   } else {
149     for (auto &SBI : *this) {
150       SBI.dumpOS(OS);
151       OS << "\n";
152     }
153   }
154 }
155 
156 void BasicBlock::verify() const {
157   assert(isa<llvm::BasicBlock>(Val) && "Expected BasicBlock!");
158   for (const auto &I : *this) {
159     I.verify();
160   }
161 }
162 #endif // NDEBUG
163 
164 } // namespace llvm::sandboxir
165