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