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 Ctx.getOrCreateValue(Op); 71 } 72 } 73 #if !defined(NDEBUG) 74 verify(); 75 #endif 76 } 77 78 BasicBlock::iterator BasicBlock::begin() const { 79 llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val); 80 llvm::BasicBlock::iterator It = BB->begin(); 81 if (!BB->empty()) { 82 auto *V = Ctx.getValue(&*BB->begin()); 83 assert(V != nullptr && "No SandboxIR for BB->begin()!"); 84 auto *I = cast<Instruction>(V); 85 unsigned Num = I->getNumOfIRInstrs(); 86 assert(Num >= 1u && "Bad getNumOfIRInstrs()"); 87 It = std::next(It, Num - 1); 88 } 89 return iterator(BB, It, &Ctx); 90 } 91 92 Instruction *BasicBlock::getTerminator() const { 93 auto *TerminatorV = 94 Ctx.getValue(cast<llvm::BasicBlock>(Val)->getTerminator()); 95 return cast_or_null<Instruction>(TerminatorV); 96 } 97 98 Instruction &BasicBlock::front() const { 99 auto *BB = cast<llvm::BasicBlock>(Val); 100 assert(!BB->empty() && "Empty block!"); 101 auto *SBI = cast<Instruction>(getContext().getValue(&*BB->begin())); 102 assert(SBI != nullptr && "Expected Instr!"); 103 return *SBI; 104 } 105 106 Instruction &BasicBlock::back() const { 107 auto *BB = cast<llvm::BasicBlock>(Val); 108 assert(!BB->empty() && "Empty block!"); 109 auto *SBI = cast<Instruction>(getContext().getValue(&*BB->rbegin())); 110 assert(SBI != nullptr && "Expected Instr!"); 111 return *SBI; 112 } 113 114 #ifndef NDEBUG 115 void BasicBlock::dumpOS(raw_ostream &OS) const { 116 llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val); 117 const auto &Name = BB->getName(); 118 OS << Name; 119 if (!Name.empty()) 120 OS << ":\n"; 121 // If there are Instructions in the BB that are not mapped to SandboxIR, then 122 // use a crash-proof dump. 123 if (any_of(*BB, [this](llvm::Instruction &I) { 124 return Ctx.getValue(&I) == nullptr; 125 })) { 126 OS << "<Crash-proof mode!>\n"; 127 DenseSet<Instruction *> Visited; 128 for (llvm::Instruction &IRef : *BB) { 129 Value *SBV = Ctx.getValue(&IRef); 130 if (SBV == nullptr) 131 OS << IRef << " *** No SandboxIR ***\n"; 132 else { 133 auto *SBI = dyn_cast<Instruction>(SBV); 134 if (SBI == nullptr) { 135 OS << IRef << " *** Not a SBInstruction!!! ***\n"; 136 } else { 137 if (Visited.insert(SBI).second) 138 OS << *SBI << "\n"; 139 } 140 } 141 } 142 } else { 143 for (auto &SBI : *this) { 144 SBI.dumpOS(OS); 145 OS << "\n"; 146 } 147 } 148 } 149 150 void BasicBlock::verify() const { 151 assert(isa<llvm::BasicBlock>(Val) && "Expected BasicBlock!"); 152 for (const auto &I : *this) { 153 I.verify(); 154 } 155 } 156 #endif // NDEBUG 157 158 } // namespace llvm::sandboxir 159