87 lines · cpp
1//===- bolt/Core/MCInstUtils.cpp ------------------------------------------===//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 "bolt/Core/MCInstUtils.h"10#include "bolt/Core/BinaryBasicBlock.h"11#include "bolt/Core/BinaryFunction.h"12 13#include <type_traits>14 15using namespace llvm;16using namespace llvm::bolt;17 18// It is assumed in a few places that BinaryBasicBlock stores its instructions19// in a contiguous vector.20using BasicBlockStorageIsVector =21 std::is_same<BinaryBasicBlock::const_iterator,22 std::vector<MCInst>::const_iterator>;23static_assert(BasicBlockStorageIsVector::value);24 25MCInstReference MCInstReference::get(const MCInst &Inst,26 const BinaryFunction &BF) {27 if (BF.hasCFG()) {28 for (BinaryBasicBlock &BB : BF) {29 for (MCInst &MI : BB)30 if (&MI == &Inst)31 return MCInstReference(BB, Inst);32 }33 llvm_unreachable("Inst is not contained in BF");34 }35 36 for (auto I = BF.instrs().begin(), E = BF.instrs().end(); I != E; ++I) {37 if (&I->second == &Inst)38 return MCInstReference(BF, I);39 }40 llvm_unreachable("Inst is not contained in BF");41}42 43uint64_t MCInstReference::computeAddress(const MCCodeEmitter *Emitter) const {44 assert(!empty() && "Taking instruction address by empty reference");45 46 const BinaryContext &BC = getFunction()->getBinaryContext();47 if (auto *Ref = tryGetRefInBB()) {48 const uint64_t AddressOfBB =49 getFunction()->getAddress() + Ref->BB->getOffset();50 const MCInst *FirstInstInBB = &*Ref->BB->begin();51 const MCInst *ThisInst = &getMCInst();52 53 // Usage of plain 'const MCInst *' as iterators assumes the instructions54 // are stored in a vector, see BasicBlockStorageIsVector.55 const uint64_t OffsetInBB =56 BC.computeCodeSize(FirstInstInBB, ThisInst, Emitter);57 58 return AddressOfBB + OffsetInBB;59 }60 61 auto &Ref = getRefInBF();62 const uint64_t OffsetInBF = Ref.It->first;63 64 return getFunction()->getAddress() + OffsetInBF;65}66 67raw_ostream &MCInstReference::print(raw_ostream &OS) const {68 if (const RefInBB *Ref = tryGetRefInBB()) {69 OS << "MCInstBBRef<";70 if (Ref->BB == nullptr)71 OS << "BB:(null)";72 else73 OS << "BB:" << Ref->BB->getName() << ":" << Ref->Index;74 OS << ">";75 return OS;76 }77 78 const RefInBF &Ref = getRefInBF();79 OS << "MCInstBFRef<";80 if (Ref.BF == nullptr)81 OS << "BF:(null)";82 else83 OS << "BF:" << Ref.BF->getPrintName() << ":" << Ref.It->first;84 OS << ">";85 return OS;86}87