1 //===- BasicBlock.cpp - The BasicBlock class of Sandbox IR ----------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/SandboxIR/BasicBlock.h"
10 #include "llvm/SandboxIR/Context.h"
11 #include "llvm/SandboxIR/Function.h"
12 #include "llvm/SandboxIR/Instruction.h"
14 namespace llvm::sandboxir
{
16 BBIterator
&BBIterator::operator++() {
18 assert(It
!= ItE
&& "Already at end!");
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);
29 BBIterator
&BBIterator::operator--() {
30 assert(It
!= BB
->begin() && "Already at begin!");
31 if (It
== BB
->end()) {
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
);
43 BasicBlock
*BBIterator::getNodeParent() const {
44 llvm::BasicBlock
*Parent
= const_cast<BBIterator
*>(this)->It
.getNodeParent();
45 return cast
<BasicBlock
>(Ctx
->getValue(Parent
));
48 BasicBlock::iterator::pointer
49 BasicBlock::iterator::getInstr(llvm::BasicBlock::iterator It
) const {
50 return cast_or_null
<Instruction
>(Ctx
->getValue(&*It
));
53 Function
*BasicBlock::getParent() const {
54 auto *BB
= cast
<llvm::BasicBlock
>(Val
);
55 auto *F
= BB
->getParent();
59 return cast_or_null
<Function
>(Ctx
.getValue(F
));
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
))
71 if (isa
<llvm::MetadataAsValue
>(Op
))
74 if (isa
<llvm::InlineAsm
>(Op
))
76 Ctx
.getOrCreateValue(Op
);
84 BasicBlock::iterator
BasicBlock::begin() const {
85 llvm::BasicBlock
*BB
= cast
<llvm::BasicBlock
>(Val
);
86 llvm::BasicBlock::iterator It
= BB
->begin();
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);
95 return iterator(BB
, It
, &Ctx
);
98 Instruction
*BasicBlock::getTerminator() const {
100 Ctx
.getValue(cast
<llvm::BasicBlock
>(Val
)->getTerminator());
101 return cast_or_null
<Instruction
>(TerminatorV
);
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!");
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!");
121 void BasicBlock::dumpOS(raw_ostream
&OS
) const {
122 llvm::BasicBlock
*BB
= cast
<llvm::BasicBlock
>(Val
);
123 const auto &Name
= BB
->getName();
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;
132 OS
<< "<Crash-proof mode!>\n";
133 DenseSet
<Instruction
*> Visited
;
134 for (llvm::Instruction
&IRef
: *BB
) {
135 Value
*SBV
= Ctx
.getValue(&IRef
);
137 OS
<< IRef
<< " *** No SandboxIR ***\n";
139 auto *SBI
= dyn_cast
<Instruction
>(SBV
);
140 if (SBI
== nullptr) {
141 OS
<< IRef
<< " *** Not a SBInstruction!!! ***\n";
143 if (Visited
.insert(SBI
).second
)
149 for (auto &SBI
: *this) {
156 void BasicBlock::verify() const {
157 assert(isa
<llvm::BasicBlock
>(Val
) && "Expected BasicBlock!");
158 for (const auto &I
: *this) {
164 } // namespace llvm::sandboxir