Skip to content

Commit 2a25f3a

Browse files
committed
Use Index inside the BB instead of direct MCInst* in RefInBB
1 parent 3d8ac8c commit 2a25f3a

File tree

2 files changed

+35
-27
lines changed

2 files changed

+35
-27
lines changed

bolt/include/bolt/Core/MCInstUtils.h

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,21 @@ class BinaryFunction;
2525
/// MCInstReference represents a reference to a constant MCInst as stored either
2626
/// in a BinaryFunction (i.e. before a CFG is created), or in a BinaryBasicBlock
2727
/// (after a CFG is created).
28+
///
29+
/// The reference may be invalidated when the function containing the referenced
30+
/// instruction is modified.
2831
class MCInstReference {
2932
public:
3033
using nocfg_const_iterator = std::map<uint32_t, MCInst>::const_iterator;
3134

3235
/// Constructs an empty reference.
33-
MCInstReference() : Reference(RefInBB(nullptr, nullptr)) {}
36+
MCInstReference() : Reference(RefInBB(nullptr, /*Index=*/0)) {}
3437
/// Constructs a reference to the instruction inside the basic block.
3538
MCInstReference(const BinaryBasicBlock *BB, const MCInst *Inst)
36-
: Reference(RefInBB(BB, Inst)) {
37-
assert(BB && Inst && "Neither BB nor Inst should be nullptr");
38-
}
39+
: Reference(RefInBB(BB, getInstIndexInBB(BB, Inst))) {}
3940
/// Constructs a reference to the instruction inside the basic block.
4041
MCInstReference(const BinaryBasicBlock *BB, unsigned Index)
41-
: Reference(RefInBB(BB, &BB->getInstructionAtIndex(Index))) {
42+
: Reference(RefInBB(BB, Index)) {
4243
assert(BB && "Basic block should not be nullptr");
4344
}
4445
/// Constructs a reference to the instruction inside the function without
@@ -57,8 +58,11 @@ class MCInstReference {
5758

5859
const MCInst &getMCInst() const {
5960
assert(!empty() && "Empty reference");
60-
if (auto *Ref = tryGetRefInBB())
61-
return *Ref->Inst;
61+
if (auto *Ref = tryGetRefInBB()) {
62+
[[maybe_unused]] unsigned NumInstructions = Ref->BB->size();
63+
assert(Ref->Index < NumInstructions && "Invalid reference");
64+
return Ref->BB->getInstructionAtIndex(Ref->Index);
65+
}
6266
return getRefInBF().It->second;
6367
}
6468

@@ -92,28 +96,36 @@ class MCInstReference {
9296
raw_ostream &print(raw_ostream &OS) const;
9397

9498
private:
99+
static unsigned getInstIndexInBB(const BinaryBasicBlock *BB,
100+
const MCInst *Inst) {
101+
assert(BB && Inst && "Neither BB nor Inst should be nullptr");
102+
// Usage of pointer arithmetic assumes the instructions are stored in a
103+
// vector, see BasicBlockStorageIsVector in MCInstUtils.cpp.
104+
const MCInst *FirstInstInBB = &*BB->begin();
105+
return Inst - FirstInstInBB;
106+
}
107+
95108
// Two cases are possible:
96109
// * functions with CFG reconstructed - a function stores a collection of
97110
// basic blocks, each basic block stores a contiguous vector of MCInst
98111
// * functions without CFG - there are no basic blocks created,
99112
// the instructions are directly stored in std::map in BinaryFunction
100113
//
101114
// In both cases, the direct parent of MCInst is stored together with an
102-
// iterator pointing to the instruction.
115+
// index or iterator pointing to the instruction.
103116

104-
// Helper struct: CFG is available, the direct parent is a basic block,
105-
// iterator's type is `MCInst *`.
117+
// Helper struct: CFG is available, the direct parent is a basic block.
106118
struct RefInBB {
107-
RefInBB(const BinaryBasicBlock *BB, const MCInst *Inst)
108-
: BB(BB), Inst(Inst) {}
119+
RefInBB(const BinaryBasicBlock *BB, unsigned Index)
120+
: BB(BB), Index(Index) {}
109121
RefInBB(const RefInBB &Other) = default;
110122
RefInBB &operator=(const RefInBB &Other) = default;
111123

112124
const BinaryBasicBlock *BB;
113-
const MCInst *Inst;
125+
unsigned Index;
114126

115127
bool operator==(const RefInBB &Other) const {
116-
return BB == Other.BB && Inst == Other.Inst;
128+
return BB == Other.BB && Index == Other.Index;
117129
}
118130
};
119131

bolt/lib/Core/MCInstUtils.cpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ using namespace llvm;
1717
using namespace llvm::bolt;
1818

1919
// It is assumed in a few places that BinaryBasicBlock stores its instructions
20-
// in a contiguous vector. Give this assumption a name to simplify marking the
21-
// particular places with static_assert.
20+
// in a contiguous vector.
2221
using BasicBlockStorageIsVector =
2322
std::is_same<BinaryBasicBlock::const_iterator,
2423
std::vector<MCInst>::const_iterator>;
24+
static_assert(BasicBlockStorageIsVector::value);
2525

2626
namespace {
2727
// Cannot reuse MCPlusBuilder::InstructionIterator because it has to be
@@ -58,12 +58,13 @@ uint64_t MCInstReference::getAddress(const MCCodeEmitter *Emitter) const {
5858

5959
const BinaryContext &BC = getFunction()->getBinaryContext();
6060
if (auto *Ref = tryGetRefInBB()) {
61-
static_assert(BasicBlockStorageIsVector::value,
62-
"Cannot use 'const MCInst *' as iterator type");
6361
uint64_t AddressOfBB = getFunction()->getAddress() + Ref->BB->getOffset();
6462
const MCInst *FirstInstInBB = &*Ref->BB->begin();
63+
const MCInst *ThisInst = &getMCInst();
6564

66-
uint64_t OffsetInBB = BC.computeCodeSize(FirstInstInBB, Ref->Inst, Emitter);
65+
// Usage of plain 'const MCInst *' as iterators assumes the instructions
66+
// are stored in a vector, see BasicBlockStorageIsVector.
67+
uint64_t OffsetInBB = BC.computeCodeSize(FirstInstInBB, ThisInst, Emitter);
6768

6869
return AddressOfBB + OffsetInBB;
6970
}
@@ -80,15 +81,10 @@ uint64_t MCInstReference::getAddress(const MCCodeEmitter *Emitter) const {
8081
raw_ostream &MCInstReference::print(raw_ostream &OS) const {
8182
if (const RefInBB *Ref = tryGetRefInBB()) {
8283
OS << "MCInstBBRef<";
83-
if (Ref->BB == nullptr) {
84+
if (Ref->BB == nullptr)
8485
OS << "BB:(null)";
85-
} else {
86-
static_assert(BasicBlockStorageIsVector::value,
87-
"Cannot use pointer arithmetic on 'const MCInst *'");
88-
const MCInst *FirstInstInBB = &*Ref->BB->begin();
89-
unsigned IndexInBB = Ref->Inst - FirstInstInBB;
90-
OS << "BB:" << Ref->BB->getName() << ":" << IndexInBB;
91-
}
86+
else
87+
OS << "BB:" << Ref->BB->getName() << ":" << Ref->Index;
9288
OS << ">";
9389
return OS;
9490
}

0 commit comments

Comments
 (0)