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