159 lines · cpp
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-exception6//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 14namespace llvm::sandboxir {15 16BBIterator &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 29BBIterator &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 43BasicBlock *BBIterator::getNodeParent() const {44 llvm::BasicBlock *Parent = const_cast<BBIterator *>(this)->It.getNodeParent();45 return cast<BasicBlock>(Ctx->getValue(Parent));46}47 48BasicBlock::iterator::pointer49BasicBlock::iterator::getInstr(llvm::BasicBlock::iterator It) const {50 return cast_or_null<Instruction>(Ctx->getValue(&*It));51}52 53Function *BasicBlock::getParent() const {54 auto *BB = cast<llvm::BasicBlock>(Val);55 auto *F = BB->getParent();56 if (F == nullptr)57 // Detached58 return nullptr;59 return cast_or_null<Function>(Ctx.getValue(F));60}61 62void 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 operands68 if (isa<llvm::BasicBlock>(Op))69 continue;70 Ctx.getOrCreateValue(Op);71 }72 }73#if !defined(NDEBUG)74 verify();75#endif76}77 78BasicBlock::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 92Instruction *BasicBlock::getTerminator() const {93 auto *TerminatorV =94 Ctx.getValue(cast<llvm::BasicBlock>(Val)->getTerminator());95 return cast_or_null<Instruction>(TerminatorV);96}97 98Instruction &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 106Instruction &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 NDEBUG115void 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, then122 // 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 150void BasicBlock::verify() const {151 assert(isa<llvm::BasicBlock>(Val) && "Expected BasicBlock!");152 for (const auto &I : *this) {153 I.verify();154 }155}156#endif // NDEBUG157 158} // namespace llvm::sandboxir159