xref: /llvm-project/llvm/lib/SandboxIR/BasicBlock.cpp (revision e22b07e766e415d6a0ed4c73fe5286fcf25f8d98)
1491375ccSvporpo //===- BasicBlock.cpp - The BasicBlock class of Sandbox IR ----------------===//
2491375ccSvporpo //
3491375ccSvporpo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4491375ccSvporpo // See https://llvm.org/LICENSE.txt for license information.
5491375ccSvporpo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6491375ccSvporpo //
7491375ccSvporpo //===----------------------------------------------------------------------===//
8491375ccSvporpo 
9491375ccSvporpo #include "llvm/SandboxIR/BasicBlock.h"
10491375ccSvporpo #include "llvm/SandboxIR/Context.h"
11*e22b07e7Svporpo #include "llvm/SandboxIR/Function.h"
12eba106d4Svporpo #include "llvm/SandboxIR/Instruction.h"
13491375ccSvporpo 
14491375ccSvporpo namespace llvm::sandboxir {
15491375ccSvporpo 
16491375ccSvporpo BBIterator &BBIterator::operator++() {
17491375ccSvporpo   auto ItE = BB->end();
18491375ccSvporpo   assert(It != ItE && "Already at end!");
19491375ccSvporpo   ++It;
20491375ccSvporpo   if (It == ItE)
21491375ccSvporpo     return *this;
22491375ccSvporpo   Instruction &NextI = *cast<sandboxir::Instruction>(Ctx->getValue(&*It));
23491375ccSvporpo   unsigned Num = NextI.getNumOfIRInstrs();
24491375ccSvporpo   assert(Num > 0 && "Bad getNumOfIRInstrs()");
25491375ccSvporpo   It = std::next(It, Num - 1);
26491375ccSvporpo   return *this;
27491375ccSvporpo }
28491375ccSvporpo 
29491375ccSvporpo BBIterator &BBIterator::operator--() {
30491375ccSvporpo   assert(It != BB->begin() && "Already at begin!");
31491375ccSvporpo   if (It == BB->end()) {
32491375ccSvporpo     --It;
33491375ccSvporpo     return *this;
34491375ccSvporpo   }
35491375ccSvporpo   Instruction &CurrI = **this;
36491375ccSvporpo   unsigned Num = CurrI.getNumOfIRInstrs();
37491375ccSvporpo   assert(Num > 0 && "Bad getNumOfIRInstrs()");
38491375ccSvporpo   assert(std::prev(It, Num - 1) != BB->begin() && "Already at begin!");
39491375ccSvporpo   It = std::prev(It, Num);
40491375ccSvporpo   return *this;
41491375ccSvporpo }
42491375ccSvporpo 
43491375ccSvporpo BasicBlock *BBIterator::getNodeParent() const {
44491375ccSvporpo   llvm::BasicBlock *Parent = const_cast<BBIterator *>(this)->It.getNodeParent();
45491375ccSvporpo   return cast<BasicBlock>(Ctx->getValue(Parent));
46491375ccSvporpo }
47491375ccSvporpo 
48491375ccSvporpo BasicBlock::iterator::pointer
49491375ccSvporpo BasicBlock::iterator::getInstr(llvm::BasicBlock::iterator It) const {
50491375ccSvporpo   return cast_or_null<Instruction>(Ctx->getValue(&*It));
51491375ccSvporpo }
52491375ccSvporpo 
53491375ccSvporpo Function *BasicBlock::getParent() const {
54491375ccSvporpo   auto *BB = cast<llvm::BasicBlock>(Val);
55491375ccSvporpo   auto *F = BB->getParent();
56491375ccSvporpo   if (F == nullptr)
57491375ccSvporpo     // Detached
58491375ccSvporpo     return nullptr;
59491375ccSvporpo   return cast_or_null<Function>(Ctx.getValue(F));
60491375ccSvporpo }
61491375ccSvporpo 
62491375ccSvporpo void BasicBlock::buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB) {
63491375ccSvporpo   for (llvm::Instruction &IRef : reverse(*LLVMBB)) {
64491375ccSvporpo     llvm::Instruction *I = &IRef;
65491375ccSvporpo     Ctx.getOrCreateValue(I);
66491375ccSvporpo     for (auto [OpIdx, Op] : enumerate(I->operands())) {
67491375ccSvporpo       // Skip instruction's label operands
68491375ccSvporpo       if (isa<llvm::BasicBlock>(Op))
69491375ccSvporpo         continue;
70491375ccSvporpo       // Skip metadata
71491375ccSvporpo       if (isa<llvm::MetadataAsValue>(Op))
72491375ccSvporpo         continue;
73491375ccSvporpo       // Skip asm
74491375ccSvporpo       if (isa<llvm::InlineAsm>(Op))
75491375ccSvporpo         continue;
76491375ccSvporpo       Ctx.getOrCreateValue(Op);
77491375ccSvporpo     }
78491375ccSvporpo   }
79491375ccSvporpo #if !defined(NDEBUG)
80491375ccSvporpo   verify();
81491375ccSvporpo #endif
82491375ccSvporpo }
83491375ccSvporpo 
84491375ccSvporpo BasicBlock::iterator BasicBlock::begin() const {
85491375ccSvporpo   llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val);
86491375ccSvporpo   llvm::BasicBlock::iterator It = BB->begin();
87491375ccSvporpo   if (!BB->empty()) {
88491375ccSvporpo     auto *V = Ctx.getValue(&*BB->begin());
89491375ccSvporpo     assert(V != nullptr && "No SandboxIR for BB->begin()!");
90491375ccSvporpo     auto *I = cast<Instruction>(V);
91491375ccSvporpo     unsigned Num = I->getNumOfIRInstrs();
92491375ccSvporpo     assert(Num >= 1u && "Bad getNumOfIRInstrs()");
93491375ccSvporpo     It = std::next(It, Num - 1);
94491375ccSvporpo   }
95491375ccSvporpo   return iterator(BB, It, &Ctx);
96491375ccSvporpo }
97491375ccSvporpo 
98491375ccSvporpo Instruction *BasicBlock::getTerminator() const {
99491375ccSvporpo   auto *TerminatorV =
100491375ccSvporpo       Ctx.getValue(cast<llvm::BasicBlock>(Val)->getTerminator());
101491375ccSvporpo   return cast_or_null<Instruction>(TerminatorV);
102491375ccSvporpo }
103491375ccSvporpo 
104491375ccSvporpo Instruction &BasicBlock::front() const {
105491375ccSvporpo   auto *BB = cast<llvm::BasicBlock>(Val);
106491375ccSvporpo   assert(!BB->empty() && "Empty block!");
107491375ccSvporpo   auto *SBI = cast<Instruction>(getContext().getValue(&*BB->begin()));
108491375ccSvporpo   assert(SBI != nullptr && "Expected Instr!");
109491375ccSvporpo   return *SBI;
110491375ccSvporpo }
111491375ccSvporpo 
112491375ccSvporpo Instruction &BasicBlock::back() const {
113491375ccSvporpo   auto *BB = cast<llvm::BasicBlock>(Val);
114491375ccSvporpo   assert(!BB->empty() && "Empty block!");
115491375ccSvporpo   auto *SBI = cast<Instruction>(getContext().getValue(&*BB->rbegin()));
116491375ccSvporpo   assert(SBI != nullptr && "Expected Instr!");
117491375ccSvporpo   return *SBI;
118491375ccSvporpo }
119491375ccSvporpo 
120491375ccSvporpo #ifndef NDEBUG
121491375ccSvporpo void BasicBlock::dumpOS(raw_ostream &OS) const {
122491375ccSvporpo   llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val);
123491375ccSvporpo   const auto &Name = BB->getName();
124491375ccSvporpo   OS << Name;
125491375ccSvporpo   if (!Name.empty())
126491375ccSvporpo     OS << ":\n";
127491375ccSvporpo   // If there are Instructions in the BB that are not mapped to SandboxIR, then
128491375ccSvporpo   // use a crash-proof dump.
129491375ccSvporpo   if (any_of(*BB, [this](llvm::Instruction &I) {
130491375ccSvporpo         return Ctx.getValue(&I) == nullptr;
131491375ccSvporpo       })) {
132491375ccSvporpo     OS << "<Crash-proof mode!>\n";
133491375ccSvporpo     DenseSet<Instruction *> Visited;
134491375ccSvporpo     for (llvm::Instruction &IRef : *BB) {
135491375ccSvporpo       Value *SBV = Ctx.getValue(&IRef);
136491375ccSvporpo       if (SBV == nullptr)
137491375ccSvporpo         OS << IRef << " *** No SandboxIR ***\n";
138491375ccSvporpo       else {
139491375ccSvporpo         auto *SBI = dyn_cast<Instruction>(SBV);
140491375ccSvporpo         if (SBI == nullptr) {
141491375ccSvporpo           OS << IRef << " *** Not a SBInstruction!!! ***\n";
142491375ccSvporpo         } else {
143491375ccSvporpo           if (Visited.insert(SBI).second)
144491375ccSvporpo             OS << *SBI << "\n";
145491375ccSvporpo         }
146491375ccSvporpo       }
147491375ccSvporpo     }
148491375ccSvporpo   } else {
149491375ccSvporpo     for (auto &SBI : *this) {
150491375ccSvporpo       SBI.dumpOS(OS);
151491375ccSvporpo       OS << "\n";
152491375ccSvporpo     }
153491375ccSvporpo   }
154491375ccSvporpo }
155491375ccSvporpo 
156491375ccSvporpo void BasicBlock::verify() const {
157491375ccSvporpo   assert(isa<llvm::BasicBlock>(Val) && "Expected BasicBlock!");
158491375ccSvporpo   for (const auto &I : *this) {
159491375ccSvporpo     I.verify();
160491375ccSvporpo   }
161491375ccSvporpo }
162491375ccSvporpo #endif // NDEBUG
163491375ccSvporpo 
164491375ccSvporpo } // namespace llvm::sandboxir
165