#include "bolt/Core/BinaryFunction.h"
#include "bolt/Core/BinaryBasicBlock.h"
#include "bolt/Core/DynoStats.h"
#include "bolt/Core/HashUtilities.h"
#include "bolt/Core/MCPlusBuilder.h"
#include "bolt/Utils/NameResolver.h"
#include "bolt/Utils/NameShortener.h"
#include "bolt/Utils/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GenericDomTreeConstruction.h"
#include "llvm/Support/GenericLoopInfoImpl.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/xxhash.h"
#include <functional>
#include <limits>
#include <numeric>
#include <stack>
#include <string>
#define DEBUG_TYPE …
usingnamespacellvm;
usingnamespacebolt;
namespace opts {
extern cl::OptionCategory BoltCategory;
extern cl::OptionCategory BoltOptCategory;
extern cl::opt<bool> EnableBAT;
extern cl::opt<bool> Instrument;
extern cl::opt<bool> StrictMode;
extern cl::opt<bool> UpdateDebugSections;
extern cl::opt<unsigned> Verbosity;
extern bool processAllFunctions();
cl::opt<bool> CheckEncoding(
"check-encoding",
cl::desc("perform verification of LLVM instruction encoding/decoding. "
"Every instruction in the input is decoded and re-encoded. "
"If the resulting bytes do not match the input, a warning message "
"is printed."),
cl::Hidden, cl::cat(BoltCategory));
static cl::opt<bool> DotToolTipCode(
"dot-tooltip-code",
cl::desc("add basic block instructions as tool tips on nodes"), cl::Hidden,
cl::cat(BoltCategory));
cl::opt<JumpTableSupportLevel>
JumpTables("jump-tables",
cl::desc("jump tables support (default=basic)"),
cl::init(JTS_BASIC),
cl::values(
clEnumValN(JTS_NONE, "none",
"do not optimize functions with jump tables"),
clEnumValN(JTS_BASIC, "basic",
"optimize functions with jump tables"),
clEnumValN(JTS_MOVE, "move",
"move jump tables to a separate section"),
clEnumValN(JTS_SPLIT, "split",
"split jump tables section into hot and cold based on "
"function execution frequency"),
clEnumValN(JTS_AGGRESSIVE, "aggressive",
"aggressively split jump tables section based on usage "
"of the tables")),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
static cl::opt<bool> NoScan(
"no-scan",
cl::desc(
"do not scan cold functions for external references (may result in "
"slower binary)"),
cl::Hidden, cl::cat(BoltOptCategory));
cl::opt<bool>
PreserveBlocksAlignment("preserve-blocks-alignment",
cl::desc("try to preserve basic block alignment"),
cl::cat(BoltOptCategory));
static cl::opt<bool> PrintOutputAddressRange(
"print-output-address-range",
cl::desc(
"print output address range for each basic block in the function when"
"BinaryFunction::print is called"),
cl::Hidden, cl::cat(BoltOptCategory));
cl::opt<bool>
PrintDynoStats("dyno-stats",
cl::desc("print execution info based on profile"),
cl::cat(BoltCategory));
static cl::opt<bool>
PrintDynoStatsOnly("print-dyno-stats-only",
cl::desc("while printing functions output dyno-stats and skip instructions"),
cl::init(false),
cl::Hidden,
cl::cat(BoltCategory));
static cl::list<std::string>
PrintOnly("print-only",
cl::CommaSeparated,
cl::desc("list of functions to print"),
cl::value_desc("func1,func2,func3,..."),
cl::Hidden,
cl::cat(BoltCategory));
cl::opt<bool>
TimeBuild("time-build",
cl::desc("print time spent constructing binary functions"),
cl::Hidden, cl::cat(BoltCategory));
cl::opt<bool>
TrapOnAVX512("trap-avx512",
cl::desc("in relocation mode trap upon entry to any function that uses "
"AVX-512 instructions"),
cl::init(false),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
bool shouldPrint(const BinaryFunction &Function) { … }
}
namespace llvm {
namespace bolt {
template <typename R> static bool emptyRange(const R &Range) { … }
static SMLoc findDebugLineInformationForInstructionAt(
uint64_t Address, DWARFUnit *Unit,
const DWARFDebugLine::LineTable *LineTable) { … }
static std::string buildSectionName(StringRef Prefix, StringRef Name,
const BinaryContext &BC) { … }
static raw_ostream &operator<<(raw_ostream &OS,
const BinaryFunction::State State) { … }
std::string BinaryFunction::buildCodeSectionName(StringRef Name,
const BinaryContext &BC) { … }
std::string BinaryFunction::buildColdCodeSectionName(StringRef Name,
const BinaryContext &BC) { … }
uint64_t BinaryFunction::Count = …;
std::optional<StringRef>
BinaryFunction::hasNameRegex(const StringRef Name) const { … }
std::optional<StringRef>
BinaryFunction::hasRestoredNameRegex(const StringRef Name) const { … }
std::string BinaryFunction::getDemangledName() const { … }
BinaryBasicBlock *
BinaryFunction::getBasicBlockContainingOffset(uint64_t Offset) { … }
void BinaryFunction::markUnreachableBlocks() { … }
std::pair<unsigned, uint64_t>
BinaryFunction::eraseInvalidBBs(const MCCodeEmitter *Emitter) { … }
bool BinaryFunction::isForwardCall(const MCSymbol *CalleeSymbol) const { … }
void BinaryFunction::dump() const { … }
void BinaryFunction::print(raw_ostream &OS, std::string Annotation) { … }
void BinaryFunction::printRelocations(raw_ostream &OS, uint64_t Offset,
uint64_t Size) const { … }
static std::string mutateDWARFExpressionTargetReg(const MCCFIInstruction &Instr,
MCPhysReg NewReg) { … }
void BinaryFunction::mutateCFIRegisterFor(const MCInst &Instr,
MCPhysReg NewReg) { … }
const MCCFIInstruction *BinaryFunction::mutateCFIOffsetFor(const MCInst &Instr,
int64_t NewOffset) { … }
IndirectBranchType
BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size,
uint64_t Offset,
uint64_t &TargetAddress) { … }
MCSymbol *BinaryFunction::getOrCreateLocalLabel(uint64_t Address,
bool CreatePastEnd) { … }
ErrorOr<ArrayRef<uint8_t>> BinaryFunction::getData() const { … }
size_t BinaryFunction::getSizeOfDataInCodeAt(uint64_t Offset) const { … }
bool BinaryFunction::isZeroPaddingAt(uint64_t Offset) const { … }
Error BinaryFunction::handlePCRelOperand(MCInst &Instruction, uint64_t Address,
uint64_t Size) { … }
MCSymbol *BinaryFunction::handleExternalReference(MCInst &Instruction,
uint64_t Size,
uint64_t Offset,
uint64_t TargetAddress,
bool &IsCall) { … }
void BinaryFunction::handleIndirectBranch(MCInst &Instruction, uint64_t Size,
uint64_t Offset) { … }
void BinaryFunction::handleAArch64IndirectCall(MCInst &Instruction,
const uint64_t Offset) { … }
std::optional<MCInst>
BinaryFunction::disassembleInstructionAtOffset(uint64_t Offset) const { … }
Error BinaryFunction::disassemble() { … }
MCSymbol *BinaryFunction::registerBranch(uint64_t Src, uint64_t Dst) { … }
bool BinaryFunction::scanExternalRefs() { … }
void BinaryFunction::postProcessEntryPoints() { … }
void BinaryFunction::postProcessJumpTables() { … }
bool BinaryFunction::validateExternallyReferencedOffsets() { … }
bool BinaryFunction::postProcessIndirectBranches(
MCPlusBuilder::AllocatorIdTy AllocId) { … }
void BinaryFunction::recomputeLandingPads() { … }
Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { … }
void BinaryFunction::postProcessCFG() { … }
void BinaryFunction::removeTagsFromProfile() { … }
void BinaryFunction::removeConditionalTailCalls() { … }
uint64_t BinaryFunction::getFunctionScore() const { … }
void BinaryFunction::annotateCFIState() { … }
namespace {
struct CFISnapshot { … };
struct CFISnapshotDiff : public CFISnapshot { … };
}
bool BinaryFunction::replayCFIInstrs(int32_t FromState, int32_t ToState,
BinaryBasicBlock *InBB,
BinaryBasicBlock::iterator InsertIt) { … }
SmallVector<int32_t, 4>
BinaryFunction::unwindCFIState(int32_t FromState, int32_t ToState,
BinaryBasicBlock *InBB,
BinaryBasicBlock::iterator &InsertIt) { … }
void BinaryFunction::normalizeCFIState() { … }
bool BinaryFunction::finalizeCFIState() { … }
bool BinaryFunction::requiresAddressTranslation() const { … }
bool BinaryFunction::requiresAddressMap() const { … }
uint64_t BinaryFunction::getInstructionCount() const { … }
void BinaryFunction::clearDisasmState() { … }
void BinaryFunction::setTrapOnEntry() { … }
void BinaryFunction::setIgnored() { … }
void BinaryFunction::duplicateConstantIslands() { … }
#ifndef MAX_PATH
#define MAX_PATH …
#endif
static std::string constructFilename(std::string Filename,
std::string Annotation,
std::string Suffix) { … }
static std::string formatEscapes(const std::string &Str) { … }
void BinaryFunction::dumpGraph(raw_ostream &OS) const { … }
void BinaryFunction::viewGraph() const { … }
void BinaryFunction::dumpGraphForPass(std::string Annotation) const { … }
void BinaryFunction::dumpGraphToFile(std::string Filename) const { … }
bool BinaryFunction::validateCFG() const { … }
void BinaryFunction::fixBranches() { … }
void BinaryFunction::propagateGnuArgsSizeInfo(
MCPlusBuilder::AllocatorIdTy AllocId) { … }
void BinaryFunction::postProcessBranches() { … }
MCSymbol *BinaryFunction::addEntryPointAtOffset(uint64_t Offset) { … }
MCSymbol *BinaryFunction::addEntryPoint(const BinaryBasicBlock &BB) { … }
MCSymbol *BinaryFunction::getSymbolForEntryID(uint64_t EntryID) { … }
uint64_t BinaryFunction::getEntryIDForSymbol(const MCSymbol *Symbol) const { … }
bool BinaryFunction::forEachEntryPoint(EntryPointCallbackTy Callback) const { … }
BinaryFunction::BasicBlockListType BinaryFunction::dfs() const { … }
size_t BinaryFunction::computeHash(bool UseDFS, HashFunction HashFunction,
OperandHashFuncTy OperandHashFunc) const { … }
void BinaryFunction::insertBasicBlocks(
BinaryBasicBlock *Start,
std::vector<std::unique_ptr<BinaryBasicBlock>> &&NewBBs,
const bool UpdateLayout, const bool UpdateCFIState,
const bool RecomputeLandingPads) { … }
BinaryFunction::iterator BinaryFunction::insertBasicBlocks(
BinaryFunction::iterator StartBB,
std::vector<std::unique_ptr<BinaryBasicBlock>> &&NewBBs,
const bool UpdateLayout, const bool UpdateCFIState,
const bool RecomputeLandingPads) { … }
void BinaryFunction::updateBBIndices(const unsigned StartIndex) { … }
void BinaryFunction::updateCFIState(BinaryBasicBlock *Start,
const unsigned NumNewBlocks) { … }
void BinaryFunction::updateLayout(BinaryBasicBlock *Start,
const unsigned NumNewBlocks) { … }
bool BinaryFunction::checkForAmbiguousJumpTables() { … }
void BinaryFunction::disambiguateJumpTables(
MCPlusBuilder::AllocatorIdTy AllocId) { … }
bool BinaryFunction::replaceJumpTableEntryIn(BinaryBasicBlock *BB,
BinaryBasicBlock *OldDest,
BinaryBasicBlock *NewDest) { … }
BinaryBasicBlock *BinaryFunction::splitEdge(BinaryBasicBlock *From,
BinaryBasicBlock *To) { … }
void BinaryFunction::deleteConservativeEdges() { … }
bool BinaryFunction::isSymbolValidInScope(const SymbolRef &Symbol,
uint64_t SymbolSize) const { … }
void BinaryFunction::adjustExecutionCount(uint64_t Count) { … }
BinaryFunction::~BinaryFunction() { … }
void BinaryFunction::constructDomTree() { … }
void BinaryFunction::calculateLoopInfo() { … }
void BinaryFunction::updateOutputValues(const BOLTLinker &Linker) { … }
DebugAddressRangesVector BinaryFunction::getOutputAddressRanges() const { … }
uint64_t BinaryFunction::translateInputToOutputAddress(uint64_t Address) const { … }
DebugAddressRangesVector
BinaryFunction::translateInputToOutputRange(DebugAddressRange InRange) const { … }
MCInst *BinaryFunction::getInstructionAtOffset(uint64_t Offset) { … }
MCInst *BinaryFunction::getInstructionContainingOffset(uint64_t Offset) { … }
void BinaryFunction::printLoopInfo(raw_ostream &OS) const { … }
bool BinaryFunction::isAArch64Veneer() const { … }
void BinaryFunction::addRelocation(uint64_t Address, MCSymbol *Symbol,
uint64_t RelType, uint64_t Addend,
uint64_t Value) { … }
}
}