summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Auler <rafaelauler@fb.com>2024-02-06 11:18:23 -0800
committerRafael Auler <rafaelauler@fb.com>2024-02-09 19:12:23 -0800
commitc1781b770d1400b62b3c324157a7895c1b9bdaaa (patch)
tree7ad6ba005f52a88f4670d30d28cfe2018a5f7593
parent2df42fe0efd92a89ae191a598e2727c7b63de80b (diff)
[BOLT][NFC] Refactor logging and error handlingupstream/users/rafaelauler/bolt-logging-pr
Make core BOLT functionality more friendly to being used as a library instead of in our standalone driver llvm-bolt. To accomplish this, we augment BinaryContext with journaling streams that are to be used by most BOLT code whenever something needs to be logged to the screen. Users of the library can decide if logs should be printed to a file, no file or to the screen, as before. To illustrate this, this patch adds a new option --log-file that allows the user to redirect BOLT logging to a file on disk or completely hide it by using --log-file=/dev/null. Future BOLT code should now use BinaryContext::outs() for printing important messages instead of llvm::outs(). A new test log.test enforces this by verifying that no strings are print to screen once the --log-file option is used. We also refactor old error handling code that would directly call exit(1) inside BOLT libraries whenever a serious problem occurred. To overcome this, we add a new class BOLTError and auxiliary functions createFatalBOLTError() and createNonFatalBOLTError() that allows BOLT libs to bubble up the problem to the caller by using the Error class as a return type (or Expected). To easily handle problems as before (by quitting with exit(1)), callers can now use BinaryContext::logBOLTErrorsAndQuitOnFatal(Error) whenever code needs to deal with BOLT errors. To test this, we have fatal.s that checks we are correctly quitting and printing a fatal error to the screen. Because this is a significant change by itself, not all code was yet ported. Code from Profiler libs (DataAggregator and friends) still print errors directly to screen.
-rw-r--r--bolt/include/bolt/Core/BinaryContext.h51
-rw-r--r--bolt/include/bolt/Core/BinaryFunction.h21
-rw-r--r--bolt/include/bolt/Core/BinarySection.h4
-rw-r--r--bolt/include/bolt/Core/DIEBuilder.h17
-rw-r--r--bolt/include/bolt/Core/DynoStats.h15
-rw-r--r--bolt/include/bolt/Core/Exceptions.h4
-rw-r--r--bolt/include/bolt/Passes/ADRRelaxationPass.h2
-rw-r--r--bolt/include/bolt/Passes/Aligner.h2
-rw-r--r--bolt/include/bolt/Passes/AllocCombiner.h2
-rw-r--r--bolt/include/bolt/Passes/AsmDump.h2
-rw-r--r--bolt/include/bolt/Passes/BinaryPasses.h58
-rw-r--r--bolt/include/bolt/Passes/CMOVConversion.h4
-rw-r--r--bolt/include/bolt/Passes/CacheMetrics.h6
-rw-r--r--bolt/include/bolt/Passes/FixRISCVCallsPass.h2
-rw-r--r--bolt/include/bolt/Passes/FixRelaxationPass.h2
-rw-r--r--bolt/include/bolt/Passes/FrameOptimizer.h6
-rw-r--r--bolt/include/bolt/Passes/Hugify.h2
-rw-r--r--bolt/include/bolt/Passes/IdenticalCodeFolding.h2
-rw-r--r--bolt/include/bolt/Passes/IndirectCallPromotion.h2
-rw-r--r--bolt/include/bolt/Passes/Inliner.h2
-rw-r--r--bolt/include/bolt/Passes/Instrumentation.h2
-rw-r--r--bolt/include/bolt/Passes/JTFootprintReduction.h2
-rw-r--r--bolt/include/bolt/Passes/LongJmp.h6
-rw-r--r--bolt/include/bolt/Passes/LoopInversionPass.h2
-rw-r--r--bolt/include/bolt/Passes/PLTCall.h2
-rw-r--r--bolt/include/bolt/Passes/PatchEntries.h2
-rw-r--r--bolt/include/bolt/Passes/RegReAssign.h2
-rw-r--r--bolt/include/bolt/Passes/ReorderData.h5
-rw-r--r--bolt/include/bolt/Passes/ReorderFunctions.h8
-rw-r--r--bolt/include/bolt/Passes/RetpolineInsertion.h2
-rw-r--r--bolt/include/bolt/Passes/ShrinkWrapping.h26
-rw-r--r--bolt/include/bolt/Passes/SplitFunctions.h2
-rw-r--r--bolt/include/bolt/Passes/StokeInfo.h2
-rw-r--r--bolt/include/bolt/Passes/TailDuplication.h2
-rw-r--r--bolt/include/bolt/Passes/ThreeWayBranch.h2
-rw-r--r--bolt/include/bolt/Passes/ValidateInternalCalls.h2
-rw-r--r--bolt/include/bolt/Passes/ValidateMemRefs.h2
-rw-r--r--bolt/include/bolt/Passes/VeneerElimination.h2
-rw-r--r--bolt/include/bolt/Profile/BoltAddressTranslation.h2
-rw-r--r--bolt/include/bolt/Rewrite/BinaryPassManager.h4
-rw-r--r--bolt/include/bolt/Rewrite/RewriteInstance.h7
-rw-r--r--bolt/lib/Core/BinaryBasicBlock.cpp36
-rw-r--r--bolt/lib/Core/BinaryContext.cpp220
-rw-r--r--bolt/lib/Core/BinaryEmitter.cpp7
-rw-r--r--bolt/lib/Core/BinaryFunction.cpp236
-rw-r--r--bolt/lib/Core/BinarySection.cpp2
-rw-r--r--bolt/lib/Core/DIEBuilder.cpp68
-rw-r--r--bolt/lib/Core/DebugData.cpp2
-rw-r--r--bolt/lib/Core/DynoStats.cpp2
-rw-r--r--bolt/lib/Core/Exceptions.cpp104
-rw-r--r--bolt/lib/Core/ParallelUtilities.cpp5
-rw-r--r--bolt/lib/Passes/ADRRelaxationPass.cpp14
-rw-r--r--bolt/lib/Passes/Aligner.cpp5
-rw-r--r--bolt/lib/Passes/AllocCombiner.cpp11
-rw-r--r--bolt/lib/Passes/AsmDump.cpp19
-rw-r--r--bolt/lib/Passes/BinaryFunctionCallGraph.cpp14
-rw-r--r--bolt/lib/Passes/BinaryPasses.cpp381
-rw-r--r--bolt/lib/Passes/CMOVConversion.cpp27
-rw-r--r--bolt/lib/Passes/CacheMetrics.cpp39
-rw-r--r--bolt/lib/Passes/FixRISCVCallsPass.cpp6
-rw-r--r--bolt/lib/Passes/FixRelaxationPass.cpp5
-rw-r--r--bolt/lib/Passes/FrameAnalysis.cpp15
-rw-r--r--bolt/lib/Passes/FrameOptimizer.cpp58
-rw-r--r--bolt/lib/Passes/Hugify.cpp5
-rw-r--r--bolt/lib/Passes/IdenticalCodeFolding.cpp20
-rw-r--r--bolt/lib/Passes/IndirectCallPromotion.cpp201
-rw-r--r--bolt/lib/Passes/Inliner.cpp13
-rw-r--r--bolt/lib/Passes/Instrumentation.cpp79
-rw-r--r--bolt/lib/Passes/JTFootprintReduction.cpp33
-rw-r--r--bolt/lib/Passes/LongJmp.cpp55
-rw-r--r--bolt/lib/Passes/LoopInversionPass.cpp9
-rw-r--r--bolt/lib/Passes/PLTCall.cpp9
-rw-r--r--bolt/lib/Passes/PatchEntries.cpp25
-rw-r--r--bolt/lib/Passes/RegAnalysis.cpp10
-rw-r--r--bolt/lib/Passes/RegReAssign.cpp24
-rw-r--r--bolt/lib/Passes/ReorderData.cpp65
-rw-r--r--bolt/lib/Passes/ReorderFunctions.cpp143
-rw-r--r--bolt/lib/Passes/RetpolineInsertion.cpp13
-rw-r--r--bolt/lib/Passes/ShrinkWrapping.cpp105
-rw-r--r--bolt/lib/Passes/SplitFunctions.cpp22
-rw-r--r--bolt/lib/Passes/StokeInfo.cpp16
-rw-r--r--bolt/lib/Passes/TailDuplication.cpp31
-rw-r--r--bolt/lib/Passes/ThreeWayBranch.cpp7
-rw-r--r--bolt/lib/Passes/ValidateInternalCalls.cpp14
-rw-r--r--bolt/lib/Passes/ValidateMemRefs.cpp13
-rw-r--r--bolt/lib/Passes/VeneerElimination.cpp13
-rw-r--r--bolt/lib/Profile/BoltAddressTranslation.cpp6
-rw-r--r--bolt/lib/Rewrite/BinaryPassManager.cpp30
-rw-r--r--bolt/lib/Rewrite/BoltDiff.cpp8
-rw-r--r--bolt/lib/Rewrite/DWARFRewriter.cpp7
-rw-r--r--bolt/lib/Rewrite/MachORewriteInstance.cpp12
-rw-r--r--bolt/lib/Rewrite/RewriteInstance.cpp571
-rw-r--r--bolt/lib/Target/X86/X86MCSymbolizer.cpp18
-rw-r--r--bolt/lib/Target/X86/X86MCSymbolizer.h4
-rw-r--r--bolt/test/X86/fatal-error.s39
-rw-r--r--bolt/test/X86/log.test19
-rw-r--r--bolt/tools/bat-dump/bat-dump.cpp2
-rw-r--r--bolt/tools/driver/llvm-bolt.cpp26
-rw-r--r--bolt/unittests/Core/BinaryContext.cpp3
-rw-r--r--bolt/unittests/Core/MCPlusBuilder.cpp3
100 files changed, 1834 insertions, 1407 deletions
diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h
index f1db1fbded6a..30336c4e3a74 100644
--- a/bolt/include/bolt/Core/BinaryContext.h
+++ b/bolt/include/bolt/Core/BinaryContext.h
@@ -145,6 +145,35 @@ public:
}
};
+/// BOLT-exclusive errors generated in core BOLT libraries, optionally holding a
+/// string message and whether it is fatal or not. In case it is fatal and if
+/// BOLT is running as a standalone process, the process might be killed as soon
+/// as the error is checked.
+class BOLTError : public ErrorInfo<BOLTError> {
+public:
+ static char ID;
+
+ BOLTError(bool IsFatal, const Twine &S = Twine());
+ void log(raw_ostream &OS) const override;
+ bool isFatal() const { return IsFatal; }
+
+ const std::string &getMessage() const { return Msg; }
+ std::error_code convertToErrorCode() const override;
+
+private:
+ bool IsFatal;
+ std::string Msg;
+};
+
+/// Streams used by BOLT to log regular or error events
+struct JournalingStreams {
+ raw_ostream &Out;
+ raw_ostream &Err;
+};
+
+Error createNonFatalBOLTError(const Twine &S);
+Error createFatalBOLTError(const Twine &S);
+
class BinaryContext {
BinaryContext() = delete;
@@ -237,7 +266,8 @@ class BinaryContext {
public:
static Expected<std::unique_ptr<BinaryContext>>
createBinaryContext(const ObjectFile *File, bool IsPIC,
- std::unique_ptr<DWARFContext> DwCtx);
+ std::unique_ptr<DWARFContext> DwCtx,
+ JournalingStreams Logger);
/// Superset of compiler units that will contain overwritten code that needs
/// new debug info. In a few cases, functions may end up not being
@@ -605,6 +635,10 @@ public:
std::unique_ptr<MCAsmBackend> MAB;
+ /// Allows BOLT to print to log whenever it is necessary (with or without
+ /// const references)
+ mutable JournalingStreams Logger;
+
/// Indicates if the binary is Linux kernel.
bool IsLinuxKernel{false};
@@ -737,7 +771,8 @@ public:
std::unique_ptr<const MCInstrAnalysis> MIA,
std::unique_ptr<MCPlusBuilder> MIB,
std::unique_ptr<const MCRegisterInfo> MRI,
- std::unique_ptr<MCDisassembler> DisAsm);
+ std::unique_ptr<MCDisassembler> DisAsm,
+ JournalingStreams Logger);
~BinaryContext();
@@ -1349,8 +1384,12 @@ public:
return Offset;
}
- void exitWithBugReport(StringRef Message,
- const BinaryFunction &Function) const;
+ /// Log BOLT errors to journaling streams and quit process with non-zero error
+ /// code 1 if error is fatal.
+ void logBOLTErrorsAndQuitOnFatal(Error E);
+
+ std::string generateBugReportMessage(StringRef Message,
+ const BinaryFunction &Function) const;
struct IndependentCodeEmitter {
std::unique_ptr<MCObjectFileInfo> LocalMOFI;
@@ -1398,6 +1437,10 @@ public:
assert(IOAddressMap && "Address map not set yet");
return *IOAddressMap;
}
+
+ raw_ostream &outs() const { return Logger.Out; }
+
+ raw_ostream &errs() const { return Logger.Err; }
};
template <typename T, typename = std::enable_if_t<sizeof(T) == 1>>
diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h
index 3a1eae3311bd..a177178769e4 100644
--- a/bolt/include/bolt/Core/BinaryFunction.h
+++ b/bolt/include/bolt/Core/BinaryFunction.h
@@ -1910,12 +1910,11 @@ public:
/// Support dynamic relocations in constant islands, which may happen if
/// binary is linked with -z notext option.
- void markIslandDynamicRelocationAtAddress(uint64_t Address) {
- if (!isInConstantIsland(Address)) {
- errs() << "BOLT-ERROR: dynamic relocation found for text section at 0x"
- << Twine::utohexstr(Address) << "\n";
- exit(1);
- }
+ Error markIslandDynamicRelocationAtAddress(uint64_t Address) {
+ if (!isInConstantIsland(Address))
+ return createFatalBOLTError(
+ Twine("dynamic relocation found for text section at 0x") +
+ Twine::utohexstr(Address) + Twine("\n"));
// Mark island to have dynamic relocation
Islands->HasDynamicRelocations = true;
@@ -1924,6 +1923,7 @@ public:
// move binary data during updateOutputValues, making us emit
// dynamic relocation with the right offset value.
getOrCreateIslandAccess(Address);
+ return Error::success();
}
bool hasDynamicRelocationAtIsland() const {
@@ -2054,9 +2054,10 @@ public:
/// state to State:Disassembled.
///
/// Returns false if disassembly failed.
- bool disassemble();
+ Error disassemble();
- void handlePCRelOperand(MCInst &Instruction, uint64_t Address, uint64_t Size);
+ Error handlePCRelOperand(MCInst &Instruction, uint64_t Address,
+ uint64_t Size);
MCSymbol *handleExternalReference(MCInst &Instruction, uint64_t Size,
uint64_t Offset, uint64_t TargetAddress,
@@ -2100,7 +2101,7 @@ public:
///
/// Returns true on success and update the current function state to
/// State::CFG. Returns false if CFG cannot be built.
- bool buildCFG(MCPlusBuilder::AllocatorIdTy);
+ Error buildCFG(MCPlusBuilder::AllocatorIdTy);
/// Perform post-processing of the CFG.
void postProcessCFG();
@@ -2217,7 +2218,7 @@ public:
}
/// Process LSDA information for the function.
- void parseLSDA(ArrayRef<uint8_t> LSDAData, uint64_t LSDAAddress);
+ Error parseLSDA(ArrayRef<uint8_t> LSDAData, uint64_t LSDAAddress);
/// Update exception handling ranges for the function.
void updateEHRanges();
diff --git a/bolt/include/bolt/Core/BinarySection.h b/bolt/include/bolt/Core/BinarySection.h
index 70914f59157d..a85dbf28950e 100644
--- a/bolt/include/bolt/Core/BinarySection.h
+++ b/bolt/include/bolt/Core/BinarySection.h
@@ -112,7 +112,7 @@ class BinarySection {
static StringRef getName(SectionRef Section) {
return cantFail(Section.getName());
}
- static StringRef getContents(SectionRef Section) {
+ static StringRef getContentsOrQuit(SectionRef Section) {
if (Section.getObject()->isELF() &&
ELFSectionRef(Section).getType() == ELF::SHT_NOBITS)
return StringRef();
@@ -159,7 +159,7 @@ public:
BinarySection(BinaryContext &BC, SectionRef Section)
: BC(BC), Name(getName(Section)), Section(Section),
- Contents(getContents(Section)), Address(Section.getAddress()),
+ Contents(getContentsOrQuit(Section)), Address(Section.getAddress()),
Size(Section.getSize()), Alignment(Section.getAlignment().value()),
OutputName(Name), SectionNumber(++Count) {
if (isELF()) {
diff --git a/bolt/include/bolt/Core/DIEBuilder.h b/bolt/include/bolt/Core/DIEBuilder.h
index f89084065aae..f13d42ff4ab4 100644
--- a/bolt/include/bolt/Core/DIEBuilder.h
+++ b/bolt/include/bolt/Core/DIEBuilder.h
@@ -15,6 +15,7 @@
#ifndef BOLT_CORE_DIE_BUILDER_H
#define BOLT_CORE_DIE_BUILDER_H
+#include "bolt/Core/BinaryContext.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
@@ -32,6 +33,7 @@
namespace llvm {
namespace bolt {
+
class DIEStreamer;
class DebugStrOffsetsWriter;
@@ -120,6 +122,7 @@ private:
std::unique_ptr<State> BuilderState;
FoldingSet<DIEAbbrev> AbbreviationsSet;
std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
+ BinaryContext &BC;
DWARFContext *DwarfContext{nullptr};
bool IsDWO{false};
uint64_t UnitSize{0};
@@ -219,9 +222,10 @@ private:
if (getState().CloneUnitCtxMap[UnitId].DieInfoVector.size() > DIEId)
return *getState().CloneUnitCtxMap[UnitId].DieInfoVector[DIEId].get();
- errs() << "BOLT-WARNING: [internal-dwarf-error]: The DIE is not allocated "
- "before looking up, some"
- << "unexpected corner cases happened.\n";
+ BC.errs()
+ << "BOLT-WARNING: [internal-dwarf-error]: The DIE is not allocated "
+ "before looking up, some"
+ << "unexpected corner cases happened.\n";
return *getState().CloneUnitCtxMap[UnitId].DieInfoVector.front().get();
}
@@ -261,7 +265,7 @@ private:
DIE *constructDIEFast(DWARFDie &DDie, DWARFUnit &U, uint32_t UnitId);
public:
- DIEBuilder(DWARFContext *DwarfContext, bool IsDWO = false);
+ DIEBuilder(BinaryContext &BC, DWARFContext *DwarfContext, bool IsDWO = false);
/// Returns enum to what we are currently processing.
ProcessingType getCurrentProcessingState() { return getState().Type; }
@@ -295,8 +299,9 @@ public:
if (getState().TypeDIEMap.count(&DU))
return getState().TypeDIEMap[&DU];
- errs() << "BOLT-ERROR: unable to find TypeUnit for Type Unit at offset 0x"
- << DU.getOffset() << "\n";
+ BC.errs()
+ << "BOLT-ERROR: unable to find TypeUnit for Type Unit at offset 0x"
+ << DU.getOffset() << "\n";
return nullptr;
}
diff --git a/bolt/include/bolt/Core/DynoStats.h b/bolt/include/bolt/Core/DynoStats.h
index 65256719ba06..82a69668385b 100644
--- a/bolt/include/bolt/Core/DynoStats.h
+++ b/bolt/include/bolt/Core/DynoStats.h
@@ -159,8 +159,9 @@ inline DynoStats getDynoStats(FuncsType &Funcs, bool IsAArch64) {
/// Call a function with optional before and after dynostats printing.
template <typename FnType, typename FuncsType>
-inline void callWithDynoStats(FnType &&Func, FuncsType &Funcs, StringRef Phase,
- const bool Flag, bool IsAArch64) {
+inline void callWithDynoStats(raw_ostream &OS, FnType &&Func, FuncsType &Funcs,
+ StringRef Phase, const bool Flag,
+ bool IsAArch64) {
DynoStats DynoStatsBefore(IsAArch64);
if (Flag)
DynoStatsBefore = getDynoStats(Funcs, IsAArch64);
@@ -170,12 +171,12 @@ inline void callWithDynoStats(FnType &&Func, FuncsType &Funcs, StringRef Phase,
if (Flag) {
const DynoStats DynoStatsAfter = getDynoStats(Funcs, IsAArch64);
const bool Changed = (DynoStatsAfter != DynoStatsBefore);
- outs() << "BOLT-INFO: program-wide dynostats after running " << Phase
- << (Changed ? "" : " (no change)") << ":\n\n"
- << DynoStatsBefore << '\n';
+ OS << "BOLT-INFO: program-wide dynostats after running " << Phase
+ << (Changed ? "" : " (no change)") << ":\n\n"
+ << DynoStatsBefore << '\n';
if (Changed)
- DynoStatsAfter.print(outs(), &DynoStatsBefore);
- outs() << '\n';
+ DynoStatsAfter.print(OS, &DynoStatsBefore);
+ OS << '\n';
}
}
diff --git a/bolt/include/bolt/Core/Exceptions.h b/bolt/include/bolt/Core/Exceptions.h
index 7c09b5b768fe..422b86f6ddb7 100644
--- a/bolt/include/bolt/Core/Exceptions.h
+++ b/bolt/include/bolt/Core/Exceptions.h
@@ -30,13 +30,14 @@ class FDE;
namespace bolt {
+class BinaryContext;
class BinaryFunction;
/// \brief Wraps up information to read all CFI instructions and feed them to a
/// BinaryFunction, as well as rewriting CFI sections.
class CFIReaderWriter {
public:
- explicit CFIReaderWriter(const DWARFDebugFrame &EHFrame);
+ explicit CFIReaderWriter(BinaryContext &BC, const DWARFDebugFrame &EHFrame);
bool fillCFIInfoFor(BinaryFunction &Function) const;
@@ -59,6 +60,7 @@ public:
const FDEsMap &getFDEs() const { return FDEs; }
private:
+ BinaryContext &BC;
FDEsMap FDEs;
};
diff --git a/bolt/include/bolt/Passes/ADRRelaxationPass.h b/bolt/include/bolt/Passes/ADRRelaxationPass.h
index a5ff0c4a8003..1d35a335c025 100644
--- a/bolt/include/bolt/Passes/ADRRelaxationPass.h
+++ b/bolt/include/bolt/Passes/ADRRelaxationPass.h
@@ -30,7 +30,7 @@ public:
const char *getName() const override { return "adr-relaxation"; }
/// Pass entry point
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
void runOnFunction(BinaryFunction &BF);
};
diff --git a/bolt/include/bolt/Passes/Aligner.h b/bolt/include/bolt/Passes/Aligner.h
index 4cb44fdb121e..eb077182c945 100644
--- a/bolt/include/bolt/Passes/Aligner.h
+++ b/bolt/include/bolt/Passes/Aligner.h
@@ -39,7 +39,7 @@ public:
const char *getName() const override { return "aligner"; }
/// Pass entry point
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/AllocCombiner.h b/bolt/include/bolt/Passes/AllocCombiner.h
index 44c6fddd34de..8532f761c9ad 100644
--- a/bolt/include/bolt/Passes/AllocCombiner.h
+++ b/bolt/include/bolt/Passes/AllocCombiner.h
@@ -33,7 +33,7 @@ public:
}
/// Pass entry point
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/AsmDump.h b/bolt/include/bolt/Passes/AsmDump.h
index 7cc96f20a920..d993909f2794 100644
--- a/bolt/include/bolt/Passes/AsmDump.h
+++ b/bolt/include/bolt/Passes/AsmDump.h
@@ -28,7 +28,7 @@ public:
bool shouldPrint(const BinaryFunction &BF) const override { return false; }
/// Pass entry point
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/BinaryPasses.h b/bolt/include/bolt/Passes/BinaryPasses.h
index dace07e903e7..046765b16f19 100644
--- a/bolt/include/bolt/Passes/BinaryPasses.h
+++ b/bolt/include/bolt/Passes/BinaryPasses.h
@@ -50,8 +50,7 @@ public:
/// this pass is completed (printPass() must have returned true).
virtual bool shouldPrint(const BinaryFunction &BF) const;
- /// Execute this pass on the given functions.
- virtual void runOnFunctions(BinaryContext &BC) = 0;
+ virtual Error runOnFunctions(BinaryContext &BC) = 0;
};
/// A pass to print program-wide dynostats.
@@ -70,18 +69,19 @@ public:
bool shouldPrint(const BinaryFunction &BF) const override { return false; }
- void runOnFunctions(BinaryContext &BC) override {
+ Error runOnFunctions(BinaryContext &BC) override {
const DynoStats NewDynoStats =
getDynoStats(BC.getBinaryFunctions(), BC.isAArch64());
const bool Changed = (NewDynoStats != PrevDynoStats);
- outs() << "BOLT-INFO: program-wide dynostats " << Title
- << (Changed ? "" : " (no change)") << ":\n\n"
- << PrevDynoStats;
+ BC.outs() << "BOLT-INFO: program-wide dynostats " << Title
+ << (Changed ? "" : " (no change)") << ":\n\n"
+ << PrevDynoStats;
if (Changed) {
- outs() << '\n';
- NewDynoStats.print(outs(), &PrevDynoStats, BC.InstPrinter.get());
+ BC.outs() << '\n';
+ NewDynoStats.print(BC.outs(), &PrevDynoStats, BC.InstPrinter.get());
}
- outs() << '\n';
+ BC.outs() << '\n';
+ return Error::success();
}
};
@@ -100,7 +100,7 @@ public:
const char *getName() const override { return "normalize CFG"; }
- void runOnFunctions(BinaryContext &) override;
+ Error runOnFunctions(BinaryContext &) override;
};
/// Detect and eliminate unreachable basic blocks. We could have those
@@ -119,7 +119,7 @@ public:
bool shouldPrint(const BinaryFunction &BF) const override {
return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0;
}
- void runOnFunctions(BinaryContext &) override;
+ Error runOnFunctions(BinaryContext &) override;
};
// Reorder the basic blocks for each function based on hotness.
@@ -165,7 +165,7 @@ public:
const char *getName() const override { return "reorder-blocks"; }
bool shouldPrint(const BinaryFunction &BF) const override;
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Sync local branches with CFG.
@@ -175,7 +175,7 @@ public:
: BinaryFunctionPass(PrintPass) {}
const char *getName() const override { return "fix-branches"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Fix the CFI state and exception handling information after all other
@@ -186,7 +186,7 @@ public:
: BinaryFunctionPass(PrintPass) {}
const char *getName() const override { return "finalize-functions"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Perform any necessary adjustments for functions that do not fit into their
@@ -198,7 +198,7 @@ public:
const char *getName() const override { return "check-large-functions"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
bool shouldOptimize(const BinaryFunction &BF) const override;
};
@@ -210,7 +210,7 @@ public:
: BinaryFunctionPass(PrintPass) {}
const char *getName() const override { return "lower-annotations"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Clean the state of the MC representation before sending it to emission
@@ -220,7 +220,7 @@ public:
: BinaryFunctionPass(PrintPass) {}
const char *getName() const override { return "clean-mc-state"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// An optimization to simplify conditional tail calls by removing
@@ -292,7 +292,7 @@ public:
bool shouldPrint(const BinaryFunction &BF) const override {
return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0;
}
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Convert instructions to the form with the minimum operand width.
@@ -305,7 +305,7 @@ public:
const char *getName() const override { return "shorten-instructions"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Perform simple peephole optimizations.
@@ -339,7 +339,7 @@ public:
: BinaryFunctionPass(PrintPass) {}
const char *getName() const override { return "peepholes"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// An optimization to simplify loads from read-only sections.The pass converts
@@ -370,7 +370,7 @@ public:
bool shouldPrint(const BinaryFunction &BF) const override {
return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0;
}
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Assign output sections to all functions.
@@ -379,7 +379,7 @@ public:
explicit AssignSections() : BinaryFunctionPass(false) {}
const char *getName() const override { return "assign-sections"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Compute and report to the user the imbalance in flow equations for all
@@ -394,7 +394,7 @@ public:
const char *getName() const override { return "profile-stats"; }
bool shouldPrint(const BinaryFunction &) const override { return false; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Prints a list of the top 100 functions sorted by a set of
@@ -406,7 +406,7 @@ public:
const char *getName() const override { return "print-stats"; }
bool shouldPrint(const BinaryFunction &) const override { return false; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Pass for lowering any instructions that we have raised and that have
@@ -418,7 +418,7 @@ public:
const char *getName() const override { return "inst-lowering"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Pass for stripping 'repz' from 'repz retq' sequence of instructions.
@@ -429,7 +429,7 @@ public:
const char *getName() const override { return "strip-rep-ret"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Pass for inlining calls to memcpy using 'rep movsb' on X86.
@@ -440,7 +440,7 @@ public:
const char *getName() const override { return "inline-memcpy"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Pass for specializing memcpy for a size of 1 byte.
@@ -461,7 +461,7 @@ public:
const char *getName() const override { return "specialize-memcpy"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
/// Pass to remove nops in code
@@ -475,7 +475,7 @@ public:
const char *getName() const override { return "remove-nops"; }
/// Pass entry point
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
enum FrameOptimizationType : char {
diff --git a/bolt/include/bolt/Passes/CMOVConversion.h b/bolt/include/bolt/Passes/CMOVConversion.h
index 77ce2235001a..4046266fa39d 100644
--- a/bolt/include/bolt/Passes/CMOVConversion.h
+++ b/bolt/include/bolt/Passes/CMOVConversion.h
@@ -64,7 +64,7 @@ class CMOVConversion : public BinaryFunctionPass {
}
double getMPRatio() { return (double)RemovedMP / PossibleMP; }
- void dump();
+ void dumpTo(raw_ostream &OS);
};
// BinaryContext-wide stats
Stats Global;
@@ -76,7 +76,7 @@ public:
const char *getName() const override { return "CMOV conversion"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/CacheMetrics.h b/bolt/include/bolt/Passes/CacheMetrics.h
index 1e40ad66d933..5c88d98c76c1 100644
--- a/bolt/include/bolt/Passes/CacheMetrics.h
+++ b/bolt/include/bolt/Passes/CacheMetrics.h
@@ -17,12 +17,16 @@
#include <vector>
namespace llvm {
+
+class raw_ostream;
+
namespace bolt {
class BinaryFunction;
namespace CacheMetrics {
/// Calculate and print various metrics related to instruction cache performance
-void printAll(const std::vector<BinaryFunction *> &BinaryFunctions);
+void printAll(raw_ostream &OS,
+ const std::vector<BinaryFunction *> &BinaryFunctions);
} // namespace CacheMetrics
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/FixRISCVCallsPass.h b/bolt/include/bolt/Passes/FixRISCVCallsPass.h
index 46418c43d192..a5c3e5158d6d 100644
--- a/bolt/include/bolt/Passes/FixRISCVCallsPass.h
+++ b/bolt/include/bolt/Passes/FixRISCVCallsPass.h
@@ -33,7 +33,7 @@ public:
const char *getName() const override { return "fix-riscv-calls"; }
/// Pass entry point
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/FixRelaxationPass.h b/bolt/include/bolt/Passes/FixRelaxationPass.h
index 45ee9cb73603..50b64480aa62 100644
--- a/bolt/include/bolt/Passes/FixRelaxationPass.h
+++ b/bolt/include/bolt/Passes/FixRelaxationPass.h
@@ -31,7 +31,7 @@ public:
const char *getName() const override { return "fix-relaxations"; }
/// Pass entry point
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/FrameOptimizer.h b/bolt/include/bolt/Passes/FrameOptimizer.h
index 310bebfee266..64055bd25172 100644
--- a/bolt/include/bolt/Passes/FrameOptimizer.h
+++ b/bolt/include/bolt/Passes/FrameOptimizer.h
@@ -98,8 +98,8 @@ class FrameOptimizerPass : public BinaryFunctionPass {
void removeUnusedStores(const FrameAnalysis &FA, BinaryFunction &BF);
/// Perform shrinkwrapping step
- void performShrinkWrapping(const RegAnalysis &RA, const FrameAnalysis &FA,
- BinaryContext &BC);
+ Error performShrinkWrapping(const RegAnalysis &RA, const FrameAnalysis &FA,
+ BinaryContext &BC);
public:
explicit FrameOptimizerPass(const cl::opt<bool> &PrintPass)
@@ -108,7 +108,7 @@ public:
const char *getName() const override { return "frame-optimizer"; }
/// Pass entry point
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
bool shouldPrint(const BinaryFunction &BF) const override {
return BinaryFunctionPass::shouldPrint(BF) && FuncsChanged.count(&BF) > 0;
diff --git a/bolt/include/bolt/Passes/Hugify.h b/bolt/include/bolt/Passes/Hugify.h
index 0a7734059121..52c0ae19102b 100644
--- a/bolt/include/bolt/Passes/Hugify.h
+++ b/bolt/include/bolt/Passes/Hugify.h
@@ -18,7 +18,7 @@ class HugePage : public BinaryFunctionPass {
public:
HugePage(const cl::opt<bool> &PrintPass) : BinaryFunctionPass(PrintPass) {}
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
const char *getName() const override { return "HugePage"; }
};
diff --git a/bolt/include/bolt/Passes/IdenticalCodeFolding.h b/bolt/include/bolt/Passes/IdenticalCodeFolding.h
index c15cebc8af19..b4206fa36074 100644
--- a/bolt/include/bolt/Passes/IdenticalCodeFolding.h
+++ b/bolt/include/bolt/Passes/IdenticalCodeFolding.h
@@ -35,7 +35,7 @@ public:
: BinaryFunctionPass(PrintPass) {}
const char *getName() const override { return "identical-code-folding"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/IndirectCallPromotion.h b/bolt/include/bolt/Passes/IndirectCallPromotion.h
index 397a38663948..adc58d70ec0f 100644
--- a/bolt/include/bolt/Passes/IndirectCallPromotion.h
+++ b/bolt/include/bolt/Passes/IndirectCallPromotion.h
@@ -221,7 +221,7 @@ public:
return BF.isSimple() && !BF.isIgnored() && BF.hasProfile() &&
!BF.hasUnknownControlFlow();
}
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/Inliner.h b/bolt/include/bolt/Passes/Inliner.h
index 711eae69d1c9..5d9b96a2d915 100644
--- a/bolt/include/bolt/Passes/Inliner.h
+++ b/bolt/include/bolt/Passes/Inliner.h
@@ -86,7 +86,7 @@ public:
return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0;
}
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/Instrumentation.h b/bolt/include/bolt/Passes/Instrumentation.h
index 1a11f9eab511..76ffcf41db6e 100644
--- a/bolt/include/bolt/Passes/Instrumentation.h
+++ b/bolt/include/bolt/Passes/Instrumentation.h
@@ -31,7 +31,7 @@ public:
Summary(std::make_unique<InstrumentationSummary>()) {}
/// Modifies all functions by inserting instrumentation code (first step)
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
const char *getName() const override { return "instrumentation"; }
diff --git a/bolt/include/bolt/Passes/JTFootprintReduction.h b/bolt/include/bolt/Passes/JTFootprintReduction.h
index 084049d3b463..4b015e1f96b3 100644
--- a/bolt/include/bolt/Passes/JTFootprintReduction.h
+++ b/bolt/include/bolt/Passes/JTFootprintReduction.h
@@ -68,7 +68,7 @@ public:
bool shouldPrint(const BinaryFunction &BF) const override {
return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0;
}
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/LongJmp.h b/bolt/include/bolt/Passes/LongJmp.h
index c95181922dbc..3d02d75ac4a2 100644
--- a/bolt/include/bolt/Passes/LongJmp.h
+++ b/bolt/include/bolt/Passes/LongJmp.h
@@ -131,14 +131,14 @@ class LongJmpPass : public BinaryFunctionPass {
uint64_t DotAddress) const;
/// Expand the range of the stub in StubBB if necessary
- bool relaxStub(BinaryBasicBlock &StubBB);
+ Error relaxStub(BinaryBasicBlock &StubBB, bool &Modified);
/// Helper to resolve a symbol address according to our tentative layout
uint64_t getSymbolAddress(const BinaryContext &BC, const MCSymbol *Target,
const BinaryBasicBlock *TgtBB) const;
/// Relax function by adding necessary stubs or relaxing existing stubs
- bool relax(BinaryFunction &BF);
+ Error relax(BinaryFunction &BF, bool &Modified);
public:
/// BinaryPass public interface
@@ -148,7 +148,7 @@ public:
const char *getName() const override { return "long-jmp"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
} // namespace llvm
diff --git a/bolt/include/bolt/Passes/LoopInversionPass.h b/bolt/include/bolt/Passes/LoopInversionPass.h
index 472fb36640c1..aee441d72093 100644
--- a/bolt/include/bolt/Passes/LoopInversionPass.h
+++ b/bolt/include/bolt/Passes/LoopInversionPass.h
@@ -49,7 +49,7 @@ public:
const char *getName() const override { return "loop-inversion-opt"; }
/// Pass entry point
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
bool runOnFunction(BinaryFunction &Function);
};
diff --git a/bolt/include/bolt/Passes/PLTCall.h b/bolt/include/bolt/Passes/PLTCall.h
index 4fdbf60c7f9f..09ef96e27293 100644
--- a/bolt/include/bolt/Passes/PLTCall.h
+++ b/bolt/include/bolt/Passes/PLTCall.h
@@ -30,7 +30,7 @@ public:
bool shouldPrint(const BinaryFunction &BF) const override {
return BinaryFunctionPass::shouldPrint(BF);
}
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/PatchEntries.h b/bolt/include/bolt/Passes/PatchEntries.h
index b9ed4a5e4280..fa6b5811a4c3 100644
--- a/bolt/include/bolt/Passes/PatchEntries.h
+++ b/bolt/include/bolt/Passes/PatchEntries.h
@@ -34,7 +34,7 @@ public:
explicit PatchEntries() : BinaryFunctionPass(false) {}
const char *getName() const override { return "patch-entries"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/RegReAssign.h b/bolt/include/bolt/Passes/RegReAssign.h
index cd7bea6a62c1..c50e32ff46e2 100644
--- a/bolt/include/bolt/Passes/RegReAssign.h
+++ b/bolt/include/bolt/Passes/RegReAssign.h
@@ -55,7 +55,7 @@ public:
return BinaryFunctionPass::shouldPrint(BF) && FuncsChanged.count(&BF) > 0;
}
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
} // namespace llvm
diff --git a/bolt/include/bolt/Passes/ReorderData.h b/bolt/include/bolt/Passes/ReorderData.h
index 65b730652101..9cd17aecfd81 100644
--- a/bolt/include/bolt/Passes/ReorderData.h
+++ b/bolt/include/bolt/Passes/ReorderData.h
@@ -35,7 +35,8 @@ private:
sortedByFunc(BinaryContext &BC, const BinarySection &Section,
std::map<uint64_t, BinaryFunction> &BFs) const;
- void printOrder(const BinarySection &Section, DataOrder::const_iterator Begin,
+ void printOrder(BinaryContext &BC, const BinarySection &Section,
+ DataOrder::const_iterator Begin,
DataOrder::const_iterator End) const;
/// Set the ordering of the section with \p SectionName. \p NewOrder is a
@@ -51,7 +52,7 @@ public:
const char *getName() const override { return "reorder-data"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/ReorderFunctions.h b/bolt/include/bolt/Passes/ReorderFunctions.h
index 8f9507d0a824..4c88142c5887 100644
--- a/bolt/include/bolt/Passes/ReorderFunctions.h
+++ b/bolt/include/bolt/Passes/ReorderFunctions.h
@@ -20,10 +20,10 @@ class Cluster;
class ReorderFunctions : public BinaryFunctionPass {
BinaryFunctionCallGraph Cg;
- void reorder(std::vector<Cluster> &&Clusters,
+ void reorder(BinaryContext &BC, std::vector<Cluster> &&Clusters,
std::map<uint64_t, BinaryFunction> &BFs);
- void printStats(const std::vector<Cluster> &Clusters,
+ void printStats(BinaryContext &BC, const std::vector<Cluster> &Clusters,
const std::vector<uint64_t> &FuncAddr);
public:
@@ -42,9 +42,9 @@ public:
: BinaryFunctionPass(PrintPass) {}
const char *getName() const override { return "reorder-functions"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
- static std::vector<std::string> readFunctionOrderFile();
+ static Error readFunctionOrderFile(std::vector<std::string> &FunctionNames);
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/RetpolineInsertion.h b/bolt/include/bolt/Passes/RetpolineInsertion.h
index 12f46a95264c..2cdde7f07483 100644
--- a/bolt/include/bolt/Passes/RetpolineInsertion.h
+++ b/bolt/include/bolt/Passes/RetpolineInsertion.h
@@ -62,7 +62,7 @@ public:
const char *getName() const override { return "retpoline-insertion"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/ShrinkWrapping.h b/bolt/include/bolt/Passes/ShrinkWrapping.h
index cccbc518dd26..b7809f0bb069 100644
--- a/bolt/include/bolt/Passes/ShrinkWrapping.h
+++ b/bolt/include/bolt/Passes/ShrinkWrapping.h
@@ -467,8 +467,9 @@ private:
/// If \p CreatePushOrPop is true, create a push/pop instead. Current SP/FP
/// values, as determined by StackPointerTracking, should be informed via
/// \p SPVal and \p FPVal in order to emit the correct offset form SP/FP.
- MCInst createStackAccess(int SPVal, int FPVal, const FrameIndexEntry &FIE,
- bool CreatePushOrPop);
+ Expected<MCInst> createStackAccess(int SPVal, int FPVal,
+ const FrameIndexEntry &FIE,
+ bool CreatePushOrPop);
/// Update the CFI referenced by \p Inst with \p NewOffset, if the CFI has
/// an offset.
@@ -484,22 +485,23 @@ private:
/// InsertionPoint for other instructions that need to be inserted at the same
/// original location, since this insertion may have invalidated the previous
/// location.
- BBIterTy processInsertion(BBIterTy InsertionPoint, BinaryBasicBlock *CurBB,
- const WorklistItem &Item, int64_t SPVal,
- int64_t FPVal);
+ Expected<BBIterTy> processInsertion(BBIterTy InsertionPoint,
+ BinaryBasicBlock *CurBB,
+ const WorklistItem &Item, int64_t SPVal,
+ int64_t FPVal);
/// Auxiliary function to processInsertions(), helping perform all the
/// insertion tasks in the todo list associated with a single insertion point.
/// Return true if at least one insertion was performed.
- BBIterTy processInsertionsList(BBIterTy InsertionPoint,
- BinaryBasicBlock *CurBB,
- std::vector<WorklistItem> &TodoList,
- int64_t SPVal, int64_t FPVal);
+ Expected<BBIterTy> processInsertionsList(BBIterTy InsertionPoint,
+ BinaryBasicBlock *CurBB,
+ std::vector<WorklistItem> &TodoList,
+ int64_t SPVal, int64_t FPVal);
/// Apply all insertion todo tasks regarding insertion of new stores/loads or
/// push/pops at annotated points. Return false if the entire function had
/// no todo tasks annotation and this pass has nothing to do.
- bool processInsertions();
+ Expected<bool> processInsertions();
/// Apply all deletion todo tasks (or tasks to change a push/pop to a memory
/// access no-op)
@@ -519,9 +521,9 @@ public:
BC.MIB->removeAnnotation(Inst, getAnnotationIndex());
}
- bool perform(bool HotOnly = false);
+ Expected<bool> perform(bool HotOnly = false);
- static void printStats();
+ static void printStats(BinaryContext &BC);
};
} // end namespace bolt
diff --git a/bolt/include/bolt/Passes/SplitFunctions.h b/bolt/include/bolt/Passes/SplitFunctions.h
index 28e9e79d1b8f..8bdc48b68eb7 100644
--- a/bolt/include/bolt/Passes/SplitFunctions.h
+++ b/bolt/include/bolt/Passes/SplitFunctions.h
@@ -104,7 +104,7 @@ public:
const char *getName() const override { return "split-functions"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/StokeInfo.h b/bolt/include/bolt/Passes/StokeInfo.h
index 75cfa1e7de43..76417e6a2c3b 100644
--- a/bolt/include/bolt/Passes/StokeInfo.h
+++ b/bolt/include/bolt/Passes/StokeInfo.h
@@ -120,7 +120,7 @@ public:
bool checkFunction(BinaryFunction &BF, DataflowInfoManager &DInfo,
RegAnalysis &RA, StokeFuncInfo &FuncInfo);
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/TailDuplication.h b/bolt/include/bolt/Passes/TailDuplication.h
index b3f1d7b7d964..a2fcab0720ca 100644
--- a/bolt/include/bolt/Passes/TailDuplication.h
+++ b/bolt/include/bolt/Passes/TailDuplication.h
@@ -145,7 +145,7 @@ public:
const char *getName() const override { return "tail duplication"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/ThreeWayBranch.h b/bolt/include/bolt/Passes/ThreeWayBranch.h
index 3eabf1b27e9d..9abf4c34134f 100644
--- a/bolt/include/bolt/Passes/ThreeWayBranch.h
+++ b/bolt/include/bolt/Passes/ThreeWayBranch.h
@@ -32,7 +32,7 @@ public:
const char *getName() const override { return "three way branch"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Passes/ValidateInternalCalls.h b/bolt/include/bolt/Passes/ValidateInternalCalls.h
index 137b83b0179f..0cdb8584f92d 100644
--- a/bolt/include/bolt/Passes/ValidateInternalCalls.h
+++ b/bolt/include/bolt/Passes/ValidateInternalCalls.h
@@ -54,7 +54,7 @@ public:
const char *getName() const override { return "validate-internal-calls"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
private:
/// Fix the CFG to take into consideration internal calls that do not
diff --git a/bolt/include/bolt/Passes/ValidateMemRefs.h b/bolt/include/bolt/Passes/ValidateMemRefs.h
index d33862cf7b16..90acce370249 100644
--- a/bolt/include/bolt/Passes/ValidateMemRefs.h
+++ b/bolt/include/bolt/Passes/ValidateMemRefs.h
@@ -25,7 +25,7 @@ public:
const char *getName() const override { return "validate-mem-refs"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
private:
bool checkAndFixJTReference(BinaryFunction &BF, MCInst &Inst,
diff --git a/bolt/include/bolt/Passes/VeneerElimination.h b/bolt/include/bolt/Passes/VeneerElimination.h
index 10c849674ab6..9ba10408a4c8 100644
--- a/bolt/include/bolt/Passes/VeneerElimination.h
+++ b/bolt/include/bolt/Passes/VeneerElimination.h
@@ -22,7 +22,7 @@ public:
const char *getName() const override { return "veneer-elimination"; }
- void runOnFunctions(BinaryContext &BC) override;
+ Error runOnFunctions(BinaryContext &BC) override;
};
} // namespace bolt
diff --git a/bolt/include/bolt/Profile/BoltAddressTranslation.h b/bolt/include/bolt/Profile/BoltAddressTranslation.h
index fa29ece3287a..b9d1e865646b 100644
--- a/bolt/include/bolt/Profile/BoltAddressTranslation.h
+++ b/bolt/include/bolt/Profile/BoltAddressTranslation.h
@@ -85,7 +85,7 @@ public:
/// Read the serialized address translation tables and load them internally
/// in memory. Return a parse error if failed.
- std::error_code parse(StringRef Buf);
+ std::error_code parse(raw_ostream &OS, StringRef Buf);
/// Dump the parsed address translation tables
void dump(raw_ostream &OS);
diff --git a/bolt/include/bolt/Rewrite/BinaryPassManager.h b/bolt/include/bolt/Rewrite/BinaryPassManager.h
index 84ab192c415a..2297c3bf52fd 100644
--- a/bolt/include/bolt/Rewrite/BinaryPassManager.h
+++ b/bolt/include/bolt/Rewrite/BinaryPassManager.h
@@ -46,10 +46,10 @@ public:
}
/// Run all registered passes in the order they were added.
- void runPasses();
+ Error runPasses();
/// Runs all enabled implemented passes on all functions.
- static void runAllPasses(BinaryContext &BC);
+ static Error runAllPasses(BinaryContext &BC);
};
} // namespace bolt
diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h
index 170da78846b8..97ab65cd5a4a 100644
--- a/bolt/include/bolt/Rewrite/RewriteInstance.h
+++ b/bolt/include/bolt/Rewrite/RewriteInstance.h
@@ -47,11 +47,14 @@ public:
// construction. Constructors can’t return errors, so clients must test \p Err
// after the object is constructed. Use `create` method instead.
RewriteInstance(llvm::object::ELFObjectFileBase *File, const int Argc,
- const char *const *Argv, StringRef ToolPath, Error &Err);
+ const char *const *Argv, StringRef ToolPath,
+ raw_ostream &Stdout, raw_ostream &Stderr, Error &Err);
static Expected<std::unique_ptr<RewriteInstance>>
create(llvm::object::ELFObjectFileBase *File, const int Argc,
- const char *const *Argv, StringRef ToolPath);
+ const char *const *Argv, StringRef ToolPath,
+ raw_ostream &Stdout = llvm::outs(),
+ raw_ostream &Stderr = llvm::errs());
~RewriteInstance();
/// Assign profile from \p Filename to this instance.
diff --git a/bolt/lib/Core/BinaryBasicBlock.cpp b/bolt/lib/Core/BinaryBasicBlock.cpp
index 984bc6dbd220..4a83fece0e43 100644
--- a/bolt/lib/Core/BinaryBasicBlock.cpp
+++ b/bolt/lib/Core/BinaryBasicBlock.cpp
@@ -92,8 +92,8 @@ bool BinaryBasicBlock::validateSuccessorInvariants() {
// Work on the assumption that jump table blocks don't
// have a conditional successor.
Valid = false;
- errs() << "BOLT-WARNING: Jump table successor " << Succ->getName()
- << " not contained in the jump table.\n";
+ BC.errs() << "BOLT-WARNING: Jump table successor " << Succ->getName()
+ << " not contained in the jump table.\n";
}
}
// If there are any leftover entries in the jump table, they
@@ -103,8 +103,8 @@ bool BinaryBasicBlock::validateSuccessorInvariants() {
Valid &= (Sym == Function->getFunctionEndLabel() ||
Sym == Function->getFunctionEndLabel(getFragmentNum()));
if (!Valid) {
- errs() << "BOLT-WARNING: Jump table contains illegal entry: "
- << Sym->getName() << "\n";
+ BC.errs() << "BOLT-WARNING: Jump table contains illegal entry: "
+ << Sym->getName() << "\n";
}
}
}
@@ -141,11 +141,11 @@ bool BinaryBasicBlock::validateSuccessorInvariants() {
}
}
if (!Valid) {
- errs() << "BOLT-WARNING: CFG invalid in " << *getFunction() << " @ "
- << getName() << "\n";
+ BC.errs() << "BOLT-WARNING: CFG invalid in " << *getFunction() << " @ "
+ << getName() << "\n";
if (JT) {
- errs() << "Jump Table instruction addr = 0x"
- << Twine::utohexstr(BC.MIB->getJumpTable(*Inst)) << "\n";
+ BC.errs() << "Jump Table instruction addr = 0x"
+ << Twine::utohexstr(BC.MIB->getJumpTable(*Inst)) << "\n";
JT->print(errs());
}
getFunction()->dump();
@@ -520,9 +520,9 @@ uint32_t BinaryBasicBlock::getNumPseudos() const {
++N;
if (N != NumPseudos) {
- errs() << "BOLT-ERROR: instructions for basic block " << getName()
- << " in function " << *Function << ": calculated pseudos " << N
- << ", set pseudos " << NumPseudos << ", size " << size() << '\n';
+ BC.errs() << "BOLT-ERROR: instructions for basic block " << getName()
+ << " in function " << *Function << ": calculated pseudos " << N
+ << ", set pseudos " << NumPseudos << ", size " << size() << '\n';
llvm_unreachable("pseudos mismatch");
}
#endif
@@ -559,18 +559,18 @@ BinaryBasicBlock::getBranchStats(const BinaryBasicBlock *Succ) const {
void BinaryBasicBlock::dump() const {
BinaryContext &BC = Function->getBinaryContext();
if (Label)
- outs() << Label->getName() << ":\n";
- BC.printInstructions(outs(), Instructions.begin(), Instructions.end(),
+ BC.outs() << Label->getName() << ":\n";
+ BC.printInstructions(BC.outs(), Instructions.begin(), Instructions.end(),
getOffset(), Function);
- outs() << "preds:";
+ BC.outs() << "preds:";
for (auto itr = pred_begin(); itr != pred_end(); ++itr) {
- outs() << " " << (*itr)->getName();
+ BC.outs() << " " << (*itr)->getName();
}
- outs() << "\nsuccs:";
+ BC.outs() << "\nsuccs:";
for (auto itr = succ_begin(); itr != succ_end(); ++itr) {
- outs() << " " << (*itr)->getName();
+ BC.outs() << " " << (*itr)->getName();
}
- outs() << "\n";
+ BC.outs() << "\n";
}
uint64_t BinaryBasicBlock::estimateSize(const MCCodeEmitter *Emitter) const {
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index df835d287680..d544ece13a83 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -83,6 +83,46 @@ cl::opt<std::string> CompDirOverride(
namespace llvm {
namespace bolt {
+char BOLTError::ID = 0;
+
+BOLTError::BOLTError(bool IsFatal, const Twine &S)
+ : IsFatal(IsFatal), Msg(S.str()) {}
+
+void BOLTError::log(raw_ostream &OS) const {
+ if (IsFatal)
+ OS << "FATAL ";
+ StringRef ErrMsg = StringRef(Msg);
+ // Prepend our error prefix if it is missing
+ if (ErrMsg.empty()) {
+ OS << "BOLT-ERROR\n";
+ } else {
+ if (!ErrMsg.starts_with("BOLT-ERROR"))
+ OS << "BOLT-ERROR: ";
+ OS << ErrMsg << "\n";
+ }
+}
+
+std::error_code BOLTError::convertToErrorCode() const {
+ return inconvertibleErrorCode();
+}
+
+Error createNonFatalBOLTError(const Twine &S) {
+ return make_error<BOLTError>(/*IsFatal*/ false, S);
+}
+
+Error createFatalBOLTError(const Twine &S) {
+ return make_error<BOLTError>(/*IsFatal*/ true, S);
+}
+
+void BinaryContext::logBOLTErrorsAndQuitOnFatal(Error E) {
+ handleAllErrors(Error(std::move(E)), [&](const BOLTError &E) {
+ if (!E.getMessage().empty())
+ E.log(this->errs());
+ if (E.isFatal())
+ exit(1);
+ });
+}
+
BinaryContext::BinaryContext(std::unique_ptr<MCContext> Ctx,
std::unique_ptr<DWARFContext> DwCtx,
std::unique_ptr<Triple> TheTriple,
@@ -96,13 +136,15 @@ BinaryContext::BinaryContext(std::unique_ptr<MCContext> Ctx,
std::unique_ptr<const MCInstrAnalysis> MIA,
std::unique_ptr<MCPlusBuilder> MIB,
std::unique_ptr<const MCRegisterInfo> MRI,
- std::unique_ptr<MCDisassembler> DisAsm)
+ std::unique_ptr<MCDisassembler> DisAsm,
+ JournalingStreams Logger)
: Ctx(std::move(Ctx)), DwCtx(std::move(DwCtx)),
TheTriple(std::move(TheTriple)), TheTarget(TheTarget),
TripleName(TripleName), MCE(std::move(MCE)), MOFI(std::move(MOFI)),
AsmInfo(std::move(AsmInfo)), MII(std::move(MII)), STI(std::move(STI)),
InstPrinter(std::move(InstPrinter)), MIA(std::move(MIA)),
- MIB(std::move(MIB)), MRI(std::move(MRI)), DisAsm(std::move(DisAsm)) {
+ MIB(std::move(MIB)), MRI(std::move(MRI)), DisAsm(std::move(DisAsm)),
+ Logger(Logger) {
Relocation::Arch = this->TheTriple->getArch();
RegularPageSize = isAArch64() ? RegularPageSizeAArch64 : RegularPageSizeX86;
PageAlign = opts::NoHugePages ? RegularPageSize : HugePageSize;
@@ -122,7 +164,8 @@ BinaryContext::~BinaryContext() {
/// triple \p TripleName.
Expected<std::unique_ptr<BinaryContext>>
BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC,
- std::unique_ptr<DWARFContext> DwCtx) {
+ std::unique_ptr<DWARFContext> DwCtx,
+ JournalingStreams Logger) {
StringRef ArchName = "";
std::string FeaturesStr = "";
switch (File->getArch()) {
@@ -241,17 +284,12 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC,
std::unique_ptr<MCCodeEmitter> MCE(
TheTarget->createMCCodeEmitter(*MII, *Ctx));
- // Make sure we don't miss any output on core dumps.
- outs().SetUnbuffered();
- errs().SetUnbuffered();
- dbgs().SetUnbuffered();
-
auto BC = std::make_unique<BinaryContext>(
std::move(Ctx), std::move(DwCtx), std::move(TheTriple), TheTarget,
std::string(TripleName), std::move(MCE), std::move(MOFI),
std::move(AsmInfo), std::move(MII), std::move(STI),
std::move(InstructionPrinter), std::move(MIA), nullptr, std::move(MRI),
- std::move(DisAsm));
+ std::move(DisAsm), Logger);
BC->LSDAEncoding = LSDAEncoding;
@@ -304,9 +342,9 @@ bool BinaryContext::validateObjectNesting() const {
Itr->second->containsRange(Next->second->getAddress(),
Next->second->getSize())) {
if (Next->second->Parent != Itr->second) {
- errs() << "BOLT-WARNING: object nesting incorrect for:\n"
- << "BOLT-WARNING: " << *Itr->second << "\n"
- << "BOLT-WARNING: " << *Next->second << "\n";
+ this->errs() << "BOLT-WARNING: object nesting incorrect for:\n"
+ << "BOLT-WARNING: " << *Itr->second << "\n"
+ << "BOLT-WARNING: " << *Next->second << "\n";
Valid = false;
}
++Next;
@@ -323,14 +361,16 @@ bool BinaryContext::validateHoles() const {
uint64_t RelAddr = Rel.Offset + Section.getAddress();
const BinaryData *BD = getBinaryDataContainingAddress(RelAddr);
if (!BD) {
- errs() << "BOLT-WARNING: no BinaryData found for relocation at address"
- << " 0x" << Twine::utohexstr(RelAddr) << " in "
- << Section.getName() << "\n";
+ this->errs()
+ << "BOLT-WARNING: no BinaryData found for relocation at address"
+ << " 0x" << Twine::utohexstr(RelAddr) << " in " << Section.getName()
+ << "\n";
Valid = false;
} else if (!BD->getAtomicRoot()) {
- errs() << "BOLT-WARNING: no atomic BinaryData found for relocation at "
- << "address 0x" << Twine::utohexstr(RelAddr) << " in "
- << Section.getName() << "\n";
+ this->errs()
+ << "BOLT-WARNING: no atomic BinaryData found for relocation at "
+ << "address 0x" << Twine::utohexstr(RelAddr) << " in "
+ << Section.getName() << "\n";
Valid = false;
}
}
@@ -438,8 +478,9 @@ BinaryContext::handleAddressRef(uint64_t Address, BinaryFunction &BF,
// The address could potentially escape. Mark it as another entry
// point into the function.
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: potentially escaped address 0x"
- << Twine::utohexstr(Address) << " in function " << BF << '\n';
+ this->outs() << "BOLT-INFO: potentially escaped address 0x"
+ << Twine::utohexstr(Address) << " in function " << BF
+ << '\n';
}
BF.HasInternalLabelReference = true;
return std::make_pair(
@@ -482,9 +523,9 @@ MemoryContentsType BinaryContext::analyzeMemoryAt(uint64_t Address,
// internal function addresses to escape the function scope - we
// consider it a tail call.
if (opts::Verbosity > 1) {
- errs() << "BOLT-WARNING: no section for address 0x"
- << Twine::utohexstr(Address) << " referenced from function " << BF
- << '\n';
+ this->errs() << "BOLT-WARNING: no section for address 0x"
+ << Twine::utohexstr(Address) << " referenced from function "
+ << BF << '\n';
}
return MemoryContentsType::UNKNOWN;
}
@@ -730,7 +771,7 @@ void BinaryContext::skipMarkedFragments() {
assert(FragmentsToSkip.count(BF) &&
"internal error in traversing function fragments");
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: Ignoring " << BF->getPrintName() << '\n';
+ this->errs() << "BOLT-WARNING: Ignoring " << BF->getPrintName() << '\n';
BF->setSimple(false);
BF->setHasIndirectTargetToSplitFragment(true);
@@ -738,9 +779,9 @@ void BinaryContext::skipMarkedFragments() {
llvm::for_each(BF->ParentFragments, addToWorklist);
}
if (!FragmentsToSkip.empty())
- errs() << "BOLT-WARNING: skipped " << FragmentsToSkip.size() << " function"
- << (FragmentsToSkip.size() == 1 ? "" : "s")
- << " due to cold fragments\n";
+ this->errs() << "BOLT-WARNING: skipped " << FragmentsToSkip.size()
+ << " function" << (FragmentsToSkip.size() == 1 ? "" : "s")
+ << " due to cold fragments\n";
}
MCSymbol *BinaryContext::getOrCreateGlobalSymbol(uint64_t Address, Twine Prefix,
@@ -791,10 +832,10 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
// Duplicate the entry for the parent function for easy access
JT->Parents.push_back(&Function);
if (opts::Verbosity > 2) {
- outs() << "BOLT-INFO: Multiple fragments access same jump table: "
- << JT->Parents[0]->getPrintName() << "; "
- << Function.getPrintName() << "\n";
- JT->print(outs());
+ this->outs() << "BOLT-INFO: Multiple fragments access same jump table: "
+ << JT->Parents[0]->getPrintName() << "; "
+ << Function.getPrintName() << "\n";
+ JT->print(this->outs());
}
Function.JumpTables.emplace(Address, JT);
JT->Parents[0]->setHasIndirectTargetToSplitFragment(true);
@@ -832,7 +873,7 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
*getSectionForAddress(Address));
JT->Parents.push_back(&Function);
if (opts::Verbosity > 2)
- JT->print(outs());
+ JT->print(this->outs());
JumpTables.emplace(Address, JT);
// Duplicate the entry for the parent function for easy access.
@@ -961,12 +1002,13 @@ bool BinaryContext::hasValidCodePadding(const BinaryFunction &BF) {
return true;
if (opts::Verbosity >= 1) {
- errs() << "BOLT-WARNING: bad padding at address 0x"
- << Twine::utohexstr(BF.getAddress() + BF.getSize())
- << " starting at offset " << (Offset - BF.getSize())
- << " in function " << BF << '\n'
- << FunctionData->slice(BF.getSize(), BF.getMaxSize() - BF.getSize())
- << '\n';
+ this->errs() << "BOLT-WARNING: bad padding at address 0x"
+ << Twine::utohexstr(BF.getAddress() + BF.getSize())
+ << " starting at offset " << (Offset - BF.getSize())
+ << " in function " << BF << '\n'
+ << FunctionData->slice(BF.getSize(),
+ BF.getMaxSize() - BF.getSize())
+ << '\n';
}
return false;
@@ -981,8 +1023,8 @@ void BinaryContext::adjustCodePadding() {
if (!hasValidCodePadding(BF)) {
if (HasRelocations) {
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: function " << BF
- << " has invalid padding. Ignoring the function.\n";
+ this->outs() << "BOLT-INFO: function " << BF
+ << " has invalid padding. Ignoring the function.\n";
}
BF.setIgnored();
} else {
@@ -1130,8 +1172,8 @@ void BinaryContext::generateSymbolHashes() {
// (i.e. all zeros or a "hole")
if (!isPadding(BD)) {
if (opts::Verbosity) {
- errs() << "BOLT-WARNING: collision detected when hashing " << BD
- << " with new name (" << NewName << "), skipping.\n";
+ this->errs() << "BOLT-WARNING: collision detected when hashing " << BD
+ << " with new name (" << NewName << "), skipping.\n";
}
++NumCollisions;
}
@@ -1141,11 +1183,11 @@ void BinaryContext::generateSymbolHashes() {
GlobalSymbols[NewName] = &BD;
}
if (NumCollisions) {
- errs() << "BOLT-WARNING: " << NumCollisions
- << " collisions detected while hashing binary objects";
+ this->errs() << "BOLT-WARNING: " << NumCollisions
+ << " collisions detected while hashing binary objects";
if (!opts::Verbosity)
- errs() << ". Use -v=1 to see the list.";
- errs() << '\n';
+ this->errs() << ". Use -v=1 to see the list.";
+ this->errs() << '\n';
}
}
@@ -1161,8 +1203,8 @@ bool BinaryContext::registerFragment(BinaryFunction &TargetFunction,
Function.setSimple(false);
}
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: marking " << TargetFunction << " as a fragment of "
- << Function << '\n';
+ this->outs() << "BOLT-INFO: marking " << TargetFunction
+ << " as a fragment of " << Function << '\n';
}
return true;
}
@@ -1276,10 +1318,11 @@ void BinaryContext::processInterproceduralReferences() {
if (TargetFunction) {
if (TargetFunction->isFragment() &&
!TargetFunction->isChildOf(Function)) {
- errs() << "BOLT-WARNING: interprocedural reference between unrelated "
- "fragments: "
- << Function.getPrintName() << " and "
- << TargetFunction->getPrintName() << '\n';
+ this->errs()
+ << "BOLT-WARNING: interprocedural reference between unrelated "
+ "fragments: "
+ << Function.getPrintName() << " and "
+ << TargetFunction->getPrintName() << '\n';
}
if (uint64_t Offset = Address - TargetFunction->getAddress())
TargetFunction->addEntryPointAtOffset(Offset);
@@ -1305,9 +1348,10 @@ void BinaryContext::processInterproceduralReferences() {
continue;
if (opts::processAllFunctions()) {
- errs() << "BOLT-ERROR: cannot process binaries with unmarked "
- << "object in code at address 0x" << Twine::utohexstr(Address)
- << " belonging to section " << SectionName << " in current mode\n";
+ this->errs() << "BOLT-ERROR: cannot process binaries with unmarked "
+ << "object in code at address 0x"
+ << Twine::utohexstr(Address) << " belonging to section "
+ << SectionName << " in current mode\n";
exit(1);
}
@@ -1317,9 +1361,10 @@ void BinaryContext::processInterproceduralReferences() {
// We are not going to overwrite non-simple functions, but for simple
// ones - adjust the padding size.
if (TargetFunction && TargetFunction->isSimple()) {
- errs() << "BOLT-WARNING: function " << *TargetFunction
- << " has an object detected in a padding region at address 0x"
- << Twine::utohexstr(Address) << '\n';
+ this->errs()
+ << "BOLT-WARNING: function " << *TargetFunction
+ << " has an object detected in a padding region at address 0x"
+ << Twine::utohexstr(Address) << '\n';
TargetFunction->setMaxSize(TargetFunction->getSize());
}
}
@@ -1336,7 +1381,8 @@ void BinaryContext::postProcessSymbolTable() {
BD->getName().starts_with("DATAat")) &&
!BD->getParent() && !BD->getSize() && !BD->isAbsolute() &&
BD->getSection()) {
- errs() << "BOLT-WARNING: zero-sized top level symbol: " << *BD << "\n";
+ this->errs() << "BOLT-WARNING: zero-sized top level symbol: " << *BD
+ << "\n";
Valid = false;
}
}
@@ -1592,17 +1638,18 @@ void BinaryContext::preprocessDWODebugInfo() {
DWARFUnit *DWOCU =
DwarfUnit->getNonSkeletonUnitDIE(false, AbsolutePath).getDwarfUnit();
if (!DWOCU->isDWOUnit()) {
- outs() << "BOLT-WARNING: Debug Fission: DWO debug information for "
- << DWOName
- << " was not retrieved and won't be updated. Please check "
- "relative path.\n";
+ this->outs()
+ << "BOLT-WARNING: Debug Fission: DWO debug information for "
+ << DWOName
+ << " was not retrieved and won't be updated. Please check "
+ "relative path.\n";
continue;
}
DWOCUs[*DWOId] = DWOCU;
}
}
if (!DWOCUs.empty())
- outs() << "BOLT-INFO: processing split DWARF\n";
+ this->outs() << "BOLT-INFO: processing split DWARF\n";
}
void BinaryContext::preprocessDebugInfo() {
@@ -1663,8 +1710,8 @@ void BinaryContext::preprocessDebugInfo() {
}
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: " << ProcessedCUs.size() << " out of "
- << DwCtx->getNumCompileUnits() << " CUs will be updated\n";
+ this->outs() << "BOLT-INFO: " << ProcessedCUs.size() << " out of "
+ << DwCtx->getNumCompileUnits() << " CUs will be updated\n";
}
preprocessDWODebugInfo();
@@ -2245,23 +2292,26 @@ BinaryFunction *BinaryContext::getFunctionForSymbol(const MCSymbol *Symbol,
return BF;
}
-void BinaryContext::exitWithBugReport(StringRef Message,
- const BinaryFunction &Function) const {
- errs() << "=======================================\n";
- errs() << "BOLT is unable to proceed because it couldn't properly understand "
- "this function.\n";
- errs() << "If you are running the most recent version of BOLT, you may "
- "want to "
- "report this and paste this dump.\nPlease check that there is no "
- "sensitive contents being shared in this dump.\n";
- errs() << "\nOffending function: " << Function.getPrintName() << "\n\n";
- ScopedPrinter SP(errs());
+std::string
+BinaryContext::generateBugReportMessage(StringRef Message,
+ const BinaryFunction &Function) const {
+ std::string Msg;
+ raw_string_ostream SS(Msg);
+ SS << "=======================================\n";
+ SS << "BOLT is unable to proceed because it couldn't properly understand "
+ "this function.\n";
+ SS << "If you are running the most recent version of BOLT, you may "
+ "want to "
+ "report this and paste this dump.\nPlease check that there is no "
+ "sensitive contents being shared in this dump.\n";
+ SS << "\nOffending function: " << Function.getPrintName() << "\n\n";
+ ScopedPrinter SP(SS);
SP.printBinaryBlock("Function contents", *Function.getData());
- errs() << "\n";
- Function.dump();
- errs() << "ERROR: " << Message;
- errs() << "\n=======================================\n";
- exit(1);
+ SS << "\n";
+ const_cast<BinaryFunction &>(Function).print(SS, "");
+ SS << "ERROR: " << Message;
+ SS << "\n=======================================\n";
+ return Msg;
}
BinaryFunction *
@@ -2399,9 +2449,9 @@ bool BinaryContext::validateInstructionEncoding(
auto OutputSequence = ArrayRef<uint8_t>((uint8_t *)Code.data(), Code.size());
if (InputSequence != OutputSequence) {
if (opts::Verbosity > 1) {
- errs() << "BOLT-WARNING: mismatched encoding detected\n"
- << " input: " << InputSequence << '\n'
- << " output: " << OutputSequence << '\n';
+ this->errs() << "BOLT-WARNING: mismatched encoding detected\n"
+ << " input: " << InputSequence << '\n'
+ << " output: " << OutputSequence << '\n';
}
return false;
}
diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp
index 3bff3125a57a..d4b668c1d7e7 100644
--- a/bolt/lib/Core/BinaryEmitter.cpp
+++ b/bolt/lib/Core/BinaryEmitter.cpp
@@ -567,7 +567,8 @@ void BinaryEmitter::emitConstantIslands(BinaryFunction &BF, bool EmitColdPart,
BF.getAddress() - BF.getOriginSection()->getAddress(), BF.getMaxSize());
if (opts::Verbosity && !OnBehalfOf)
- outs() << "BOLT-INFO: emitting constant island for function " << BF << "\n";
+ BC.outs() << "BOLT-INFO: emitting constant island for function " << BF
+ << "\n";
// We split the island into smaller blocks and output labels between them.
auto IS = Islands.Offsets.begin();
@@ -766,7 +767,7 @@ void BinaryEmitter::emitJumpTables(const BinaryFunction &BF) {
return;
if (opts::PrintJumpTables)
- outs() << "BOLT-INFO: jump tables for function " << BF << ":\n";
+ BC.outs() << "BOLT-INFO: jump tables for function " << BF << ":\n";
for (auto &JTI : BF.jumpTables()) {
JumpTable &JT = *JTI.second;
@@ -774,7 +775,7 @@ void BinaryEmitter::emitJumpTables(const BinaryFunction &BF) {
if (JT.Parents.size() > 1 && JT.Parents[0] != &BF)
continue;
if (opts::PrintJumpTables)
- JT.print(outs());
+ JT.print(BC.outs());
if (opts::JumpTables == JTS_BASIC && BC.HasRelocations) {
JT.updateOriginal();
} else {
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index 0ac47a53a446..54f2f9d972a4 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -880,9 +880,9 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size,
// internal function addresses to escape the function scope - we
// consider it a tail call.
if (opts::Verbosity >= 1) {
- errs() << "BOLT-WARNING: no section for address 0x"
- << Twine::utohexstr(ArrayStart) << " referenced from function "
- << *this << '\n';
+ BC.errs() << "BOLT-WARNING: no section for address 0x"
+ << Twine::utohexstr(ArrayStart) << " referenced from function "
+ << *this << '\n';
}
return IndirectBranchType::POSSIBLE_TAIL_CALL;
}
@@ -899,11 +899,11 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size,
if (BC.getSectionForAddress(ArrayStart)->isWritable())
return IndirectBranchType::UNKNOWN;
- outs() << "BOLT-INFO: fixed indirect branch detected in " << *this
- << " at 0x" << Twine::utohexstr(getAddress() + Offset)
- << " referencing data at 0x" << Twine::utohexstr(ArrayStart)
- << " the destination value is 0x" << Twine::utohexstr(*Value)
- << '\n';
+ BC.outs() << "BOLT-INFO: fixed indirect branch detected in " << *this
+ << " at 0x" << Twine::utohexstr(getAddress() + Offset)
+ << " referencing data at 0x" << Twine::utohexstr(ArrayStart)
+ << " the destination value is 0x" << Twine::utohexstr(*Value)
+ << '\n';
TargetAddress = *Value;
return BranchType;
@@ -1021,28 +1021,29 @@ bool BinaryFunction::isZeroPaddingAt(uint64_t Offset) const {
return true;
}
-void BinaryFunction::handlePCRelOperand(MCInst &Instruction, uint64_t Address,
- uint64_t Size) {
+Error BinaryFunction::handlePCRelOperand(MCInst &Instruction, uint64_t Address,
+ uint64_t Size) {
auto &MIB = BC.MIB;
uint64_t TargetAddress = 0;
if (!MIB->evaluateMemOperandTarget(Instruction, TargetAddress, Address,
Size)) {
- errs() << "BOLT-ERROR: PC-relative operand can't be evaluated:\n";
- BC.InstPrinter->printInst(&Instruction, 0, "", *BC.STI, errs());
- errs() << '\n';
- Instruction.dump_pretty(errs(), BC.InstPrinter.get());
- errs() << '\n';
- errs() << "BOLT-ERROR: cannot handle PC-relative operand at 0x"
- << Twine::utohexstr(Address) << ". Skipping function " << *this
- << ".\n";
+ std::string Msg;
+ raw_string_ostream SS(Msg);
+ SS << "BOLT-ERROR: PC-relative operand can't be evaluated:\n";
+ BC.InstPrinter->printInst(&Instruction, 0, "", *BC.STI, SS);
+ SS << '\n';
+ Instruction.dump_pretty(SS, BC.InstPrinter.get());
+ SS << '\n';
+ SS << "BOLT-ERROR: cannot handle PC-relative operand at 0x"
+ << Twine::utohexstr(Address) << ". Skipping function " << *this << ".\n";
if (BC.HasRelocations)
- exit(1);
+ return createFatalBOLTError(Msg);
IsSimple = false;
- return;
+ return createNonFatalBOLTError(Msg);
}
if (TargetAddress == 0 && opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: PC-relative operand is zero in function " << *this
- << '\n';
+ BC.outs() << "BOLT-INFO: PC-relative operand is zero in function " << *this
+ << '\n';
}
const MCSymbol *TargetSymbol;
@@ -1054,6 +1055,7 @@ void BinaryFunction::handlePCRelOperand(MCInst &Instruction, uint64_t Address,
Instruction, TargetSymbol, static_cast<int64_t>(TargetOffset), &*BC.Ctx);
(void)ReplaceSuccess;
assert(ReplaceSuccess && "Failed to replace mem operand with symbol+off.");
+ return Error::success();
}
MCSymbol *BinaryFunction::handleExternalReference(MCInst &Instruction,
@@ -1066,9 +1068,9 @@ MCSymbol *BinaryFunction::handleExternalReference(MCInst &Instruction,
const uint64_t AbsoluteInstrAddr = getAddress() + Offset;
BC.addInterproceduralReference(this, TargetAddress);
if (opts::Verbosity >= 2 && !IsCall && Size == 2 && !BC.HasRelocations) {
- errs() << "BOLT-WARNING: relaxed tail call detected at 0x"
- << Twine::utohexstr(AbsoluteInstrAddr) << " in function " << *this
- << ". Code size will be increased.\n";
+ BC.errs() << "BOLT-WARNING: relaxed tail call detected at 0x"
+ << Twine::utohexstr(AbsoluteInstrAddr) << " in function " << *this
+ << ". Code size will be increased.\n";
}
assert(!MIB->isTailCall(Instruction) &&
@@ -1082,9 +1084,9 @@ MCSymbol *BinaryFunction::handleExternalReference(MCInst &Instruction,
assert(MIB->isConditionalBranch(Instruction) &&
"unknown tail call instruction");
if (opts::Verbosity >= 2) {
- errs() << "BOLT-WARNING: conditional tail call detected in "
- << "function " << *this << " at 0x"
- << Twine::utohexstr(AbsoluteInstrAddr) << ".\n";
+ BC.errs() << "BOLT-WARNING: conditional tail call detected in "
+ << "function " << *this << " at 0x"
+ << Twine::utohexstr(AbsoluteInstrAddr) << ".\n";
}
}
IsCall = true;
@@ -1094,8 +1096,8 @@ MCSymbol *BinaryFunction::handleExternalReference(MCInst &Instruction,
// We actually see calls to address 0 in presence of weak
// symbols originating from libraries. This code is never meant
// to be executed.
- outs() << "BOLT-INFO: Function " << *this
- << " has a call to address zero.\n";
+ BC.outs() << "BOLT-INFO: Function " << *this
+ << " has a call to address zero.\n";
}
return BC.getOrCreateGlobalSymbol(TargetAddress, "FUNCat");
@@ -1164,7 +1166,7 @@ void BinaryFunction::handleAArch64IndirectCall(MCInst &Instruction,
}
}
-bool BinaryFunction::disassemble() {
+Error BinaryFunction::disassemble() {
NamedRegionTimer T("disassemble", "Disassemble function", "buildfuncs",
"Build Binary Functions", opts::TimeBuild);
ErrorOr<ArrayRef<uint8_t>> ErrorOrFunctionData = getData();
@@ -1208,10 +1210,11 @@ bool BinaryFunction::disassemble() {
if (isZeroPaddingAt(Offset))
break;
- errs() << "BOLT-WARNING: unable to disassemble instruction at offset 0x"
- << Twine::utohexstr(Offset) << " (address 0x"
- << Twine::utohexstr(AbsoluteInstrAddr) << ") in function " << *this
- << '\n';
+ BC.errs()
+ << "BOLT-WARNING: unable to disassemble instruction at offset 0x"
+ << Twine::utohexstr(Offset) << " (address 0x"
+ << Twine::utohexstr(AbsoluteInstrAddr) << ") in function " << *this
+ << '\n';
// Some AVX-512 instructions could not be disassembled at all.
if (BC.HasRelocations && opts::TrapOnAVX512 && BC.isX86()) {
setTrapOnEntry();
@@ -1227,10 +1230,10 @@ bool BinaryFunction::disassemble() {
if (opts::CheckEncoding && !BC.MIB->isBranch(Instruction) &&
!BC.MIB->isCall(Instruction) && !BC.MIB->isNoop(Instruction)) {
if (!BC.validateInstructionEncoding(FunctionData.slice(Offset, Size))) {
- errs() << "BOLT-WARNING: mismatching LLVM encoding detected in "
- << "function " << *this << " for instruction :\n";
- BC.printInstruction(errs(), Instruction, AbsoluteInstrAddr);
- errs() << '\n';
+ BC.errs() << "BOLT-WARNING: mismatching LLVM encoding detected in "
+ << "function " << *this << " for instruction :\n";
+ BC.printInstruction(BC.errs(), Instruction, AbsoluteInstrAddr);
+ BC.errs() << '\n';
}
}
@@ -1243,10 +1246,10 @@ bool BinaryFunction::disassemble() {
}
if (!BC.validateInstructionEncoding(FunctionData.slice(Offset, Size))) {
- errs() << "BOLT-WARNING: internal assembler/disassembler error "
- "detected for AVX512 instruction:\n";
- BC.printInstruction(errs(), Instruction, AbsoluteInstrAddr);
- errs() << " in function " << *this << '\n';
+ BC.errs() << "BOLT-WARNING: internal assembler/disassembler error "
+ "detected for AVX512 instruction:\n";
+ BC.printInstruction(BC.errs(), Instruction, AbsoluteInstrAddr);
+ BC.errs() << " in function " << *this << '\n';
setIgnored();
break;
}
@@ -1282,9 +1285,9 @@ bool BinaryFunction::disassemble() {
// function, so preserve the function as is for now.
PreserveNops = true;
} else {
- errs() << "BOLT-WARNING: internal call detected at 0x"
- << Twine::utohexstr(AbsoluteInstrAddr) << " in function "
- << *this << ". Skipping.\n";
+ BC.errs() << "BOLT-WARNING: internal call detected at 0x"
+ << Twine::utohexstr(AbsoluteInstrAddr)
+ << " in function " << *this << ". Skipping.\n";
IsSimple = false;
}
}
@@ -1332,8 +1335,19 @@ bool BinaryFunction::disassemble() {
if (MIB->isIndirectBranch(Instruction))
handleIndirectBranch(Instruction, Size, Offset);
// Indirect call. We only need to fix it if the operand is RIP-relative.
- if (IsSimple && MIB->hasPCRelOperand(Instruction))
- handlePCRelOperand(Instruction, AbsoluteInstrAddr, Size);
+ if (IsSimple && MIB->hasPCRelOperand(Instruction)) {
+ if (auto NewE = handleErrors(
+ handlePCRelOperand(Instruction, AbsoluteInstrAddr, Size),
+ [&](const BOLTError &E) -> Error {
+ if (E.isFatal())
+ return Error(std::make_unique<BOLTError>(std::move(E)));
+ if (!E.getMessage().empty())
+ E.log(BC.errs());
+ return Error::success();
+ })) {
+ return Error(std::move(NewE));
+ }
+ }
if (BC.isAArch64())
handleAArch64IndirectCall(Instruction, Offset);
@@ -1372,8 +1386,18 @@ bool BinaryFunction::disassemble() {
UsedReloc = true;
}
- if (!BC.isRISCV() && MIB->hasPCRelOperand(Instruction) && !UsedReloc)
- handlePCRelOperand(Instruction, AbsoluteInstrAddr, Size);
+ if (!BC.isRISCV() && MIB->hasPCRelOperand(Instruction) && !UsedReloc) {
+ if (auto NewE = handleErrors(
+ handlePCRelOperand(Instruction, AbsoluteInstrAddr, Size),
+ [&](const BOLTError &E) -> Error {
+ if (E.isFatal())
+ return Error(std::make_unique<BOLTError>(std::move(E)));
+ if (!E.getMessage().empty())
+ E.log(BC.errs());
+ return Error::success();
+ }))
+ return Error(std::move(NewE));
+ }
}
add_instruction:
@@ -1413,12 +1437,12 @@ add_instruction:
if (!IsSimple) {
clearList(Instructions);
- return false;
+ return createNonFatalBOLTError("");
}
updateState(State::Disassembled);
- return true;
+ return Error::success();
}
bool BinaryFunction::scanExternalRefs() {
@@ -1467,10 +1491,11 @@ bool BinaryFunction::scanExternalRefs() {
FunctionData.slice(Offset),
AbsoluteInstrAddr, nulls())) {
if (opts::Verbosity >= 1 && !isZeroPaddingAt(Offset)) {
- errs() << "BOLT-WARNING: unable to disassemble instruction at offset 0x"
- << Twine::utohexstr(Offset) << " (address 0x"
- << Twine::utohexstr(AbsoluteInstrAddr) << ") in function "
- << *this << '\n';
+ BC.errs()
+ << "BOLT-WARNING: unable to disassemble instruction at offset 0x"
+ << Twine::utohexstr(Offset) << " (address 0x"
+ << Twine::utohexstr(AbsoluteInstrAddr) << ") in function " << *this
+ << '\n';
}
Success = false;
DisassemblyFailed = true;
@@ -1598,7 +1623,7 @@ bool BinaryFunction::scanExternalRefs() {
HasExternalRefRelocations = true;
if (opts::Verbosity >= 1 && !Success)
- outs() << "BOLT-INFO: failed to scan refs for " << *this << '\n';
+ BC.outs() << "BOLT-INFO: failed to scan refs for " << *this << '\n';
return Success;
}
@@ -1631,9 +1656,9 @@ void BinaryFunction::postProcessEntryPoints() {
if (BC.isAArch64() && Offset == getSize())
continue;
- errs() << "BOLT-WARNING: reference in the middle of instruction "
- "detected in function "
- << *this << " at offset 0x" << Twine::utohexstr(Offset) << '\n';
+ BC.errs() << "BOLT-WARNING: reference in the middle of instruction "
+ "detected in function "
+ << *this << " at offset 0x" << Twine::utohexstr(Offset) << '\n';
if (BC.HasRelocations)
setIgnored();
setSimple(false);
@@ -1647,9 +1672,9 @@ void BinaryFunction::postProcessJumpTables() {
JumpTable &JT = *JTI.second;
if (JT.Type == JumpTable::JTT_PIC && opts::JumpTables == JTS_BASIC) {
opts::JumpTables = JTS_MOVE;
- outs() << "BOLT-INFO: forcing -jump-tables=move as PIC jump table was "
- "detected in function "
- << *this << '\n';
+ BC.outs() << "BOLT-INFO: forcing -jump-tables=move as PIC jump table was "
+ "detected in function "
+ << *this << '\n';
}
const uint64_t BDSize =
BC.getBinaryDataAtAddress(JT.getAddress())->getSize();
@@ -1764,15 +1789,15 @@ bool BinaryFunction::validateExternallyReferencedOffsets() {
continue;
if (opts::Verbosity >= 1) {
- errs() << "BOLT-WARNING: unclaimed data to code reference (possibly "
- << "an unrecognized jump table entry) to " << BB->getName()
- << " in " << *this << "\n";
+ BC.errs() << "BOLT-WARNING: unclaimed data to code reference (possibly "
+ << "an unrecognized jump table entry) to " << BB->getName()
+ << " in " << *this << "\n";
}
auto L = BC.scopeLock();
addEntryPoint(*BB);
} else {
- errs() << "BOLT-WARNING: unknown data to code reference to offset "
- << Twine::utohexstr(Destination) << " in " << *this << "\n";
+ BC.errs() << "BOLT-WARNING: unknown data to code reference to offset "
+ << Twine::utohexstr(Destination) << " in " << *this << "\n";
setIgnored();
}
HasUnclaimedReference = true;
@@ -1872,9 +1897,9 @@ bool BinaryFunction::postProcessIndirectBranches(
}
if (opts::Verbosity >= 2) {
- outs() << "BOLT-INFO: rejected potential indirect tail call in "
- << "function " << *this << " in basic block " << BB.getName()
- << ".\n";
+ BC.outs() << "BOLT-INFO: rejected potential indirect tail call in "
+ << "function " << *this << " in basic block " << BB.getName()
+ << ".\n";
LLVM_DEBUG(BC.printInstructions(dbgs(), BB.begin(), BB.end(),
BB.getOffset(), this, true));
}
@@ -1946,17 +1971,17 @@ void BinaryFunction::recomputeLandingPads() {
}
}
-bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
+Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
auto &MIB = BC.MIB;
if (!isSimple()) {
assert(!BC.HasRelocations &&
"cannot process file with non-simple function in relocs mode");
- return false;
+ return createNonFatalBOLTError("");
}
if (CurrentState != State::Disassembled)
- return false;
+ return createNonFatalBOLTError("");
assert(BasicBlocks.empty() && "basic block list should be empty");
assert((Labels.find(getFirstInstructionOffset()) != Labels.end()) &&
@@ -2093,7 +2118,7 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
if (BasicBlocks.empty()) {
setSimple(false);
- return false;
+ return createNonFatalBOLTError("");
}
// Intermediate dump.
@@ -2111,11 +2136,12 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
BinaryBasicBlock *ToBB = getBasicBlockAtOffset(Branch.second);
if (!FromBB || !ToBB) {
if (!FromBB)
- errs() << "BOLT-ERROR: cannot find BB containing the branch.\n";
+ BC.errs() << "BOLT-ERROR: cannot find BB containing the branch.\n";
if (!ToBB)
- errs() << "BOLT-ERROR: cannot find BB containing branch destination.\n";
- BC.exitWithBugReport("disassembly failed - inconsistent branch found.",
- *this);
+ BC.errs()
+ << "BOLT-ERROR: cannot find BB containing branch destination.\n";
+ return createFatalBOLTError(BC.generateBugReportMessage(
+ "disassembly failed - inconsistent branch found.", *this));
}
FromBB->addSuccessor(ToBB);
@@ -2193,8 +2219,8 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
// Make any necessary adjustments for indirect branches.
if (!postProcessIndirectBranches(AllocatorId)) {
if (opts::Verbosity) {
- errs() << "BOLT-WARNING: failed to post-process indirect branches for "
- << *this << '\n';
+ BC.errs() << "BOLT-WARNING: failed to post-process indirect branches for "
+ << *this << '\n';
}
// In relocation mode we want to keep processing the function but avoid
// optimizing it.
@@ -2204,7 +2230,7 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
clearList(ExternallyReferencedOffsets);
clearList(UnknownIndirectBranchOffsets);
- return true;
+ return Error::success();
}
void BinaryFunction::postProcessCFG() {
@@ -3034,10 +3060,6 @@ static std::string constructFilename(std::string Filename,
Annotation.insert(0, "-");
if (Filename.size() + Annotation.size() + Suffix.size() > MAX_PATH) {
assert(Suffix.size() + Annotation.size() <= MAX_PATH);
- if (opts::Verbosity >= 1) {
- errs() << "BOLT-WARNING: Filename \"" << Filename << Annotation << Suffix
- << "\" exceeds the " << MAX_PATH << " size limit, truncating.\n";
- }
Filename.resize(MAX_PATH - (Suffix.size() + Annotation.size()));
}
Filename += Annotation;
@@ -3162,16 +3184,17 @@ void BinaryFunction::viewGraph() const {
SmallString<MAX_PATH> Filename;
if (std::error_code EC =
sys::fs::createTemporaryFile("bolt-cfg", "dot", Filename)) {
- errs() << "BOLT-ERROR: " << EC.message() << ", unable to create "
- << " bolt-cfg-XXXXX.dot temporary file.\n";
+ BC.errs() << "BOLT-ERROR: " << EC.message() << ", unable to create "
+ << " bolt-cfg-XXXXX.dot temporary file.\n";
return;
}
dumpGraphToFile(std::string(Filename));
if (DisplayGraph(Filename))
- errs() << "BOLT-ERROR: Can't display " << Filename << " with graphviz.\n";
+ BC.errs() << "BOLT-ERROR: Can't display " << Filename
+ << " with graphviz.\n";
if (std::error_code EC = sys::fs::remove(Filename)) {
- errs() << "BOLT-WARNING: " << EC.message() << ", failed to remove "
- << Filename << "\n";
+ BC.errs() << "BOLT-WARNING: " << EC.message() << ", failed to remove "
+ << Filename << "\n";
}
}
@@ -3181,7 +3204,7 @@ void BinaryFunction::dumpGraphForPass(std::string Annotation) const {
std::string Filename = constructFilename(getPrintName(), Annotation, ".dot");
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: dumping CFG to " << Filename << "\n";
+ BC.outs() << "BOLT-INFO: dumping CFG to " << Filename << "\n";
dumpGraphToFile(Filename);
}
@@ -3190,8 +3213,8 @@ void BinaryFunction::dumpGraphToFile(std::string Filename) const {
raw_fd_ostream of(Filename, EC, sys::fs::OF_None);
if (EC) {
if (opts::Verbosity >= 1) {
- errs() << "BOLT-WARNING: " << EC.message() << ", unable to open "
- << Filename << " for output.\n";
+ BC.errs() << "BOLT-WARNING: " << EC.message() << ", unable to open "
+ << Filename << " for output.\n";
}
return;
}
@@ -3213,8 +3236,8 @@ bool BinaryFunction::validateCFG() const {
// Make sure all blocks in CFG are valid.
auto validateBlock = [this](const BinaryBasicBlock *BB, StringRef Desc) {
if (!BB->isValid()) {
- errs() << "BOLT-ERROR: deleted " << Desc << " " << BB->getName()
- << " detected in:\n";
+ BC.errs() << "BOLT-ERROR: deleted " << Desc << " " << BB->getName()
+ << " detected in:\n";
this->dump();
return false;
}
@@ -3241,8 +3264,8 @@ bool BinaryFunction::validateCFG() const {
std::unordered_set<const BinaryBasicBlock *> BBLandingPads;
for (const BinaryBasicBlock *LP : BB->landing_pads()) {
if (BBLandingPads.count(LP)) {
- errs() << "BOLT-ERROR: duplicate landing pad detected in"
- << BB->getName() << " in function " << *this << '\n';
+ BC.errs() << "BOLT-ERROR: duplicate landing pad detected in"
+ << BB->getName() << " in function " << *this << '\n';
return false;
}
BBLandingPads.insert(LP);
@@ -3251,8 +3274,8 @@ bool BinaryFunction::validateCFG() const {
std::unordered_set<const BinaryBasicBlock *> BBThrowers;
for (const BinaryBasicBlock *Thrower : BB->throwers()) {
if (BBThrowers.count(Thrower)) {
- errs() << "BOLT-ERROR: duplicate thrower detected in" << BB->getName()
- << " in function " << *this << '\n';
+ BC.errs() << "BOLT-ERROR: duplicate thrower detected in"
+ << BB->getName() << " in function " << *this << '\n';
return false;
}
BBThrowers.insert(Thrower);
@@ -3260,17 +3283,18 @@ bool BinaryFunction::validateCFG() const {
for (const BinaryBasicBlock *LPBlock : BB->landing_pads()) {
if (!llvm::is_contained(LPBlock->throwers(), BB)) {
- errs() << "BOLT-ERROR: inconsistent landing pad detected in " << *this
- << ": " << BB->getName() << " is in LandingPads but not in "
- << LPBlock->getName() << " Throwers\n";
+ BC.errs() << "BOLT-ERROR: inconsistent landing pad detected in "
+ << *this << ": " << BB->getName()
+ << " is in LandingPads but not in " << LPBlock->getName()
+ << " Throwers\n";
return false;
}
}
for (const BinaryBasicBlock *Thrower : BB->throwers()) {
if (!llvm::is_contained(Thrower->landing_pads(), BB)) {
- errs() << "BOLT-ERROR: inconsistent thrower detected in " << *this
- << ": " << BB->getName() << " is in Throwers list but not in "
- << Thrower->getName() << " LandingPads\n";
+ BC.errs() << "BOLT-ERROR: inconsistent thrower detected in " << *this
+ << ": " << BB->getName() << " is in Throwers list but not in "
+ << Thrower->getName() << " LandingPads\n";
return false;
}
}
diff --git a/bolt/lib/Core/BinarySection.cpp b/bolt/lib/Core/BinarySection.cpp
index 97bc25193547..564c63e81914 100644
--- a/bolt/lib/Core/BinarySection.cpp
+++ b/bolt/lib/Core/BinarySection.cpp
@@ -198,7 +198,7 @@ BinarySection::~BinarySection() {
if (!isAllocatable() && !hasValidSectionID() &&
(!hasSectionRef() ||
- OutputContents.data() != getContents(Section).data())) {
+ OutputContents.data() != getContentsOrQuit(Section).data())) {
delete[] getOutputData();
}
}
diff --git a/bolt/lib/Core/DIEBuilder.cpp b/bolt/lib/Core/DIEBuilder.cpp
index 762d3419edd3..3c72c745086b 100644
--- a/bolt/lib/Core/DIEBuilder.cpp
+++ b/bolt/lib/Core/DIEBuilder.cpp
@@ -126,8 +126,8 @@ uint32_t DIEBuilder::allocDIE(const DWARFUnit &DU, const DWARFDie &DDie,
void DIEBuilder::constructFromUnit(DWARFUnit &DU) {
std::optional<uint32_t> UnitId = getUnitId(DU);
if (!UnitId) {
- errs() << "BOLT-WARNING: [internal-dwarf-error]: "
- << "Skip Unit at " << Twine::utohexstr(DU.getOffset()) << "\n";
+ BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: "
+ << "Skip Unit at " << Twine::utohexstr(DU.getOffset()) << "\n";
return;
}
@@ -178,8 +178,9 @@ void DIEBuilder::constructFromUnit(DWARFUnit &DU) {
getState().CloneUnitCtxMap[*UnitId].IsConstructed = true;
}
-DIEBuilder::DIEBuilder(DWARFContext *DwarfContext, bool IsDWO)
- : DwarfContext(DwarfContext), IsDWO(IsDWO) {}
+DIEBuilder::DIEBuilder(BinaryContext &BC, DWARFContext *DwarfContext,
+ bool IsDWO)
+ : BC(BC), DwarfContext(DwarfContext), IsDWO(IsDWO) {}
static unsigned int getCUNum(DWARFContext *DwarfContext, bool IsDWO) {
unsigned int CUNum = IsDWO ? DwarfContext->getNumDWOCompileUnits()
@@ -475,19 +476,21 @@ DWARFDie DIEBuilder::resolveDIEReference(
allocDIE(*RefCU, RefDie, getState().DIEAlloc, *UnitId);
return RefDie;
}
- errs() << "BOLT-WARNING: [internal-dwarf-error]: invalid referenced DIE "
- "at offset: "
- << Twine::utohexstr(RefOffset) << ".\n";
+ BC.errs()
+ << "BOLT-WARNING: [internal-dwarf-error]: invalid referenced DIE "
+ "at offset: "
+ << Twine::utohexstr(RefOffset) << ".\n";
} else {
- errs() << "BOLT-WARNING: [internal-dwarf-error]: could not parse "
- "referenced DIE at offset: "
- << Twine::utohexstr(RefOffset) << ".\n";
+ BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: could not parse "
+ "referenced DIE at offset: "
+ << Twine::utohexstr(RefOffset) << ".\n";
}
} else {
- errs() << "BOLT-WARNING: [internal-dwarf-error]: could not find referenced "
- "CU. Referenced DIE offset: "
- << Twine::utohexstr(RefOffset) << ".\n";
+ BC.errs()
+ << "BOLT-WARNING: [internal-dwarf-error]: could not find referenced "
+ "CU. Referenced DIE offset: "
+ << Twine::utohexstr(RefOffset) << ".\n";
}
return DWARFDie();
}
@@ -516,8 +519,8 @@ void DIEBuilder::cloneDieReferenceAttribute(
if (!DieInfo.Die) {
assert(Ref > InputDIE.getOffset());
(void)Ref;
- errs() << "BOLT-WARNING: [internal-dwarf-error]: encounter unexpected "
- "unallocated DIE. Should be alloc!\n";
+ BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: encounter unexpected "
+ "unallocated DIE. Should be alloc!\n";
// We haven't cloned this DIE yet. Just create an empty one and
// store it. It'll get really cloned when we process it.
DieInfo.Die = DIE::get(getState().DIEAlloc, dwarf::Tag(RefDie.getTag()));
@@ -580,8 +583,8 @@ bool DIEBuilder::cloneExpression(const DataExtractor &Data,
(Description.Op.size() == 2 &&
Description.Op[1] == Encoding::BaseTypeRef &&
Description.Op[0] != Encoding::Size1))
- outs() << "BOLT-WARNING: [internal-dwarf-error]: unsupported DW_OP "
- "encoding.\n";
+ BC.outs() << "BOLT-WARNING: [internal-dwarf-error]: unsupported DW_OP "
+ "encoding.\n";
if ((Description.Op.size() == 1 &&
Description.Op[0] == Encoding::BaseTypeRef) ||
@@ -616,9 +619,9 @@ bool DIEBuilder::cloneExpression(const DataExtractor &Data,
Offset = Stage == CloneExpressionStage::INIT ? RefOffset
: Clone->getOffset();
else
- errs() << "BOLT-WARNING: [internal-dwarf-error]: base type ref "
- "doesn't point to "
- "DW_TAG_base_type.\n";
+ BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: base type ref "
+ "doesn't point to "
+ "DW_TAG_base_type.\n";
}
}
uint8_t ULEB[16];
@@ -652,8 +655,9 @@ void DIEBuilder::cloneBlockAttribute(
U.getVersion())) {
Block = new (getState().DIEAlloc) DIEBlock;
} else {
- errs() << "BOLT-WARNING: [internal-dwarf-error]: Unexpected Form value in "
- "cloneBlockAttribute\n";
+ BC.errs()
+ << "BOLT-WARNING: [internal-dwarf-error]: Unexpected Form value in "
+ "cloneBlockAttribute\n";
return;
}
Attr = Loc ? static_cast<DIEValueList *>(Loc)
@@ -720,9 +724,9 @@ void DIEBuilder::cloneScalarAttribute(
else if (auto OptionalValue = Val.getAsSectionOffset())
Value = *OptionalValue;
else {
- errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar "
- "attribute form. Dropping "
- "attribute.\n";
+ BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar "
+ "attribute form. Dropping "
+ "attribute.\n";
return;
}
@@ -743,9 +747,9 @@ void DIEBuilder::cloneLoclistAttrubute(
else if (auto OptionalValue = Val.getAsSectionOffset())
Value = OptionalValue;
else
- errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar "
- "attribute form. Dropping "
- "attribute.\n";
+ BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar "
+ "attribute form. Dropping "
+ "attribute.\n";
if (!Value.has_value())
return;
@@ -808,10 +812,10 @@ void DIEBuilder::cloneAttribute(
cloneRefsigAttribute(Die, AttrSpec, Val);
break;
default:
- errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported attribute "
- "form " +
- dwarf::FormEncodingString(AttrSpec.Form).str() +
- " in cloneAttribute. Dropping.";
+ BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported attribute "
+ "form " +
+ dwarf::FormEncodingString(AttrSpec.Form).str() +
+ " in cloneAttribute. Dropping.";
}
}
void DIEBuilder::assignAbbrev(DIEAbbrev &Abbrev) {
diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp
index 415b0310b6ba..8c3f6bd2052f 100644
--- a/bolt/lib/Core/DebugData.cpp
+++ b/bolt/lib/Core/DebugData.cpp
@@ -1185,7 +1185,7 @@ static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection,
Error Err = Error::success();
const char *CStr = StrData.getCStr(&Offset, &Err);
if (Err) {
- errs() << "BOLT-ERROR: could not extract string from .debug_line_str";
+ BC.errs() << "BOLT-ERROR: could not extract string from .debug_line_str";
continue;
}
const size_t NewOffset = LineStr.addString(CStr);
diff --git a/bolt/lib/Core/DynoStats.cpp b/bolt/lib/Core/DynoStats.cpp
index 10f076915e92..5de0f9e0d6b8 100644
--- a/bolt/lib/Core/DynoStats.cpp
+++ b/bolt/lib/Core/DynoStats.cpp
@@ -99,7 +99,7 @@ void DynoStats::print(raw_ostream &OS, const DynoStats *Other,
printStatWithDelta(Desc[Stat], Stats[Stat], Other ? (*Other)[Stat] : 0);
}
if (opts::PrintDynoOpcodeStat && Printer) {
- outs() << "\nProgram-wide opcode histogram:\n";
+ OS << "\nProgram-wide opcode histogram:\n";
OS << " Opcode, Execution Count, Max Exec Count, "
"Function Name:Offset ...\n";
std::vector<std::pair<uint64_t, unsigned>> SortedHistogram;
diff --git a/bolt/lib/Core/Exceptions.cpp b/bolt/lib/Core/Exceptions.cpp
index ab1885f6bb58..54618aeb95cc 100644
--- a/bolt/lib/Core/Exceptions.cpp
+++ b/bolt/lib/Core/Exceptions.cpp
@@ -98,12 +98,12 @@ namespace bolt {
// site table will be the same size as GCC uses uleb encodings for PC offsets.
//
// Note: some functions have LSDA entries with 0 call site entries.
-void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
- uint64_t LSDASectionAddress) {
+Error BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
+ uint64_t LSDASectionAddress) {
assert(CurrentState == State::Disassembled && "unexpected function state");
if (!getLSDAAddress())
- return;
+ return Error::success();
DWARFDataExtractor Data(
StringRef(reinterpret_cast<const char *>(LSDASectionData.data()),
@@ -119,9 +119,9 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
std::optional<uint64_t> MaybeLPStart = Data.getEncodedPointer(
&Offset, LPStartEncoding, Offset + LSDASectionAddress);
if (!MaybeLPStart) {
- errs() << "BOLT-ERROR: unsupported LPStartEncoding: "
- << (unsigned)LPStartEncoding << '\n';
- exit(1);
+ BC.errs() << "BOLT-ERROR: unsupported LPStartEncoding: "
+ << (unsigned)LPStartEncoding << '\n';
+ return createFatalBOLTError("");
}
LPStart = *MaybeLPStart;
}
@@ -136,13 +136,14 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
}
if (opts::PrintExceptions) {
- outs() << "[LSDA at 0x" << Twine::utohexstr(getLSDAAddress())
- << " for function " << *this << "]:\n";
- outs() << "LPStart Encoding = 0x" << Twine::utohexstr(LPStartEncoding)
- << '\n';
- outs() << "LPStart = 0x" << Twine::utohexstr(LPStart) << '\n';
- outs() << "TType Encoding = 0x" << Twine::utohexstr(TTypeEncoding) << '\n';
- outs() << "TType End = " << TTypeEnd << '\n';
+ BC.outs() << "[LSDA at 0x" << Twine::utohexstr(getLSDAAddress())
+ << " for function " << *this << "]:\n";
+ BC.outs() << "LPStart Encoding = 0x" << Twine::utohexstr(LPStartEncoding)
+ << '\n';
+ BC.outs() << "LPStart = 0x" << Twine::utohexstr(LPStart) << '\n';
+ BC.outs() << "TType Encoding = 0x" << Twine::utohexstr(TTypeEncoding)
+ << '\n';
+ BC.outs() << "TType End = " << TTypeEnd << '\n';
}
// Table to store list of indices in type table. Entries are uleb128 values.
@@ -166,9 +167,9 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
uint64_t ActionTableStart = CallSiteTableEnd;
if (opts::PrintExceptions) {
- outs() << "CallSite Encoding = " << (unsigned)CallSiteEncoding << '\n';
- outs() << "CallSite table length = " << CallSiteTableLength << '\n';
- outs() << '\n';
+ BC.outs() << "CallSite Encoding = " << (unsigned)CallSiteEncoding << '\n';
+ BC.outs() << "CallSite table length = " << CallSiteTableLength << '\n';
+ BC.outs() << '\n';
}
this->HasEHRanges = CallSitePtr < CallSiteTableEnd;
@@ -185,12 +186,13 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
LandingPad += LPStart;
if (opts::PrintExceptions) {
- outs() << "Call Site: [0x" << Twine::utohexstr(RangeBase + Start)
- << ", 0x" << Twine::utohexstr(RangeBase + Start + Length)
- << "); landing pad: 0x" << Twine::utohexstr(LandingPad)
- << "; action entry: 0x" << Twine::utohexstr(ActionEntry) << "\n";
- outs() << " current offset is " << (CallSitePtr - CallSiteTableStart)
- << '\n';
+ BC.outs() << "Call Site: [0x" << Twine::utohexstr(RangeBase + Start)
+ << ", 0x" << Twine::utohexstr(RangeBase + Start + Length)
+ << "); landing pad: 0x" << Twine::utohexstr(LandingPad)
+ << "; action entry: 0x" << Twine::utohexstr(ActionEntry)
+ << "\n";
+ BC.outs() << " current offset is " << (CallSitePtr - CallSiteTableStart)
+ << '\n';
}
// Create a handler entry if necessary.
@@ -209,15 +211,16 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
"BOLT-ERROR: cannot have landing pads in different functions");
setHasIndirectTargetToSplitFragment(true);
BC.addFragmentsToSkip(this);
- return;
+ return Error::success();
}
const uint64_t LPOffset = LandingPad - getAddress();
if (!getInstructionAtOffset(LPOffset)) {
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: landing pad " << Twine::utohexstr(LPOffset)
- << " not pointing to an instruction in function " << *this
- << " - ignoring.\n";
+ BC.errs() << "BOLT-WARNING: landing pad "
+ << Twine::utohexstr(LPOffset)
+ << " not pointing to an instruction in function " << *this
+ << " - ignoring.\n";
} else {
auto Label = Labels.find(LPOffset);
if (Label != Labels.end()) {
@@ -271,7 +274,7 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
OS << "0x" << Twine::utohexstr(TypeAddress);
};
if (opts::PrintExceptions)
- outs() << " actions: ";
+ BC.outs() << " actions: ";
uint64_t ActionPtr = ActionTableStart + ActionEntry - 1;
int64_t ActionType;
int64_t ActionNext;
@@ -281,21 +284,21 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
const uint32_t Self = ActionPtr;
ActionNext = Data.getSLEB128(&ActionPtr);
if (opts::PrintExceptions)
- outs() << Sep << "(" << ActionType << ", " << ActionNext << ") ";
+ BC.outs() << Sep << "(" << ActionType << ", " << ActionNext << ") ";
if (ActionType == 0) {
if (opts::PrintExceptions)
- outs() << "cleanup";
+ BC.outs() << "cleanup";
} else if (ActionType > 0) {
// It's an index into a type table.
MaxTypeIndex =
std::max(MaxTypeIndex, static_cast<unsigned>(ActionType));
if (opts::PrintExceptions) {
- outs() << "catch type ";
- printType(ActionType, outs());
+ BC.outs() << "catch type ";
+ printType(ActionType, BC.outs());
}
} else { // ActionType < 0
if (opts::PrintExceptions)
- outs() << "filter exception types ";
+ BC.outs() << "filter exception types ";
const char *TSep = "";
// ActionType is a negative *byte* offset into *uleb128-encoded* table
// of indices with base 1.
@@ -305,8 +308,8 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
while (uint64_t Index = Data.getULEB128(&TypeIndexTablePtr)) {
MaxTypeIndex = std::max(MaxTypeIndex, static_cast<unsigned>(Index));
if (opts::PrintExceptions) {
- outs() << TSep;
- printType(Index, outs());
+ BC.outs() << TSep;
+ printType(Index, BC.outs());
TSep = ", ";
}
}
@@ -319,11 +322,11 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
ActionPtr = Self + ActionNext;
} while (ActionNext);
if (opts::PrintExceptions)
- outs() << '\n';
+ BC.outs() << '\n';
}
}
if (opts::PrintExceptions)
- outs() << '\n';
+ BC.outs() << '\n';
assert(TypeIndexTableStart + MaxTypeIndexTableOffset <=
Data.getData().size() &&
@@ -354,6 +357,7 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
LSDATypeIndexTable =
LSDASectionData.slice(TypeIndexTableStart, MaxTypeIndexTableOffset);
}
+ return Error::success();
}
void BinaryFunction::updateEHRanges() {
@@ -460,7 +464,9 @@ void BinaryFunction::updateEHRanges() {
const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
-CFIReaderWriter::CFIReaderWriter(const DWARFDebugFrame &EHFrame) {
+CFIReaderWriter::CFIReaderWriter(BinaryContext &BC,
+ const DWARFDebugFrame &EHFrame)
+ : BC(BC) {
// Prepare FDEs for fast lookup
for (const dwarf::FrameEntry &Entry : EHFrame.entries()) {
const auto *CurFDE = dyn_cast<dwarf::FDE>(&Entry);
@@ -475,10 +481,10 @@ CFIReaderWriter::CFIReaderWriter(const DWARFDebugFrame &EHFrame) {
if (FDEI->second->getAddressRange() == 0) {
FDEI->second = CurFDE;
} else if (opts::Verbosity > 0) {
- errs() << "BOLT-WARNING: different FDEs for function at 0x"
- << Twine::utohexstr(FDEI->first)
- << " detected; sizes: " << FDEI->second->getAddressRange()
- << " and " << CurFDE->getAddressRange() << '\n';
+ BC.errs() << "BOLT-WARNING: different FDEs for function at 0x"
+ << Twine::utohexstr(FDEI->first)
+ << " detected; sizes: " << FDEI->second->getAddressRange()
+ << " and " << CurFDE->getAddressRange() << '\n';
}
}
} else {
@@ -508,8 +514,8 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
*CurFDE.getLinkedCIE()->getPersonalityEncoding());
}
- auto decodeFrameInstruction = [&Function, &Offset, Address, CodeAlignment,
- DataAlignment](
+ auto decodeFrameInstruction = [this, &Function, &Offset, Address,
+ CodeAlignment, DataAlignment](
const CFIProgram::Instruction &Instr) {
uint8_t Opcode = Instr.Opcode;
if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
@@ -601,7 +607,7 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
case DW_CFA_val_offset_sf:
case DW_CFA_val_offset:
if (opts::Verbosity >= 1) {
- errs() << "BOLT-WARNING: DWARF val_offset() unimplemented\n";
+ BC.errs() << "BOLT-WARNING: DWARF val_offset() unimplemented\n";
}
return false;
case DW_CFA_def_cfa_expression:
@@ -622,7 +628,7 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
}
case DW_CFA_MIPS_advance_loc8:
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: DW_CFA_MIPS_advance_loc unimplemented\n";
+ BC.errs() << "BOLT-WARNING: DW_CFA_MIPS_advance_loc unimplemented\n";
return false;
case DW_CFA_GNU_window_save:
// DW_CFA_GNU_window_save and DW_CFA_GNU_NegateRAState just use the same
@@ -633,17 +639,17 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
break;
}
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: DW_CFA_GNU_window_save unimplemented\n";
+ BC.errs() << "BOLT-WARNING: DW_CFA_GNU_window_save unimplemented\n";
return false;
case DW_CFA_lo_user:
case DW_CFA_hi_user:
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: DW_CFA_*_user unimplemented\n";
+ BC.errs() << "BOLT-WARNING: DW_CFA_*_user unimplemented\n";
return false;
default:
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: Unrecognized CFI instruction: " << Instr.Opcode
- << '\n';
+ BC.errs() << "BOLT-WARNING: Unrecognized CFI instruction: "
+ << Instr.Opcode << '\n';
return false;
}
diff --git a/bolt/lib/Core/ParallelUtilities.cpp b/bolt/lib/Core/ParallelUtilities.cpp
index fb2b6dc7cd63..1a28bc4346ec 100644
--- a/bolt/lib/Core/ParallelUtilities.cpp
+++ b/bolt/lib/Core/ParallelUtilities.cpp
@@ -90,8 +90,9 @@ inline unsigned estimateTotalCost(const BinaryContext &BC,
// Switch to trivial scheduling if total estimated work is zero
if (TotalCost == 0) {
- outs() << "BOLT-WARNING: Running parallel work of 0 estimated cost, will "
- "switch to trivial scheduling.\n";
+ BC.outs()
+ << "BOLT-WARNING: Running parallel work of 0 estimated cost, will "
+ "switch to trivial scheduling.\n";
SchedPolicy = SP_TRIVIAL;
TotalCost = BC.getBinaryFunctions().size();
diff --git a/bolt/lib/Passes/ADRRelaxationPass.cpp b/bolt/lib/Passes/ADRRelaxationPass.cpp
index 27a1377adef1..24fddbc764cb 100644
--- a/bolt/lib/Passes/ADRRelaxationPass.cpp
+++ b/bolt/lib/Passes/ADRRelaxationPass.cpp
@@ -86,9 +86,10 @@ void ADRRelaxationPass::runOnFunction(BinaryFunction &BF) {
// invalidate this offset, so we have to rely on linker-inserted NOP to
// replace it with ADRP, and abort if it is not present.
auto L = BC.scopeLock();
- errs() << formatv("BOLT-ERROR: Cannot relax adr in non-simple function "
- "{0}. Use --strict option to override\n",
- BF.getOneName());
+ BC.errs() << formatv(
+ "BOLT-ERROR: Cannot relax adr in non-simple function "
+ "{0}. Use --strict option to override\n",
+ BF.getOneName());
PassFailed = true;
return;
}
@@ -97,9 +98,9 @@ void ADRRelaxationPass::runOnFunction(BinaryFunction &BF) {
}
}
-void ADRRelaxationPass::runOnFunctions(BinaryContext &BC) {
+Error ADRRelaxationPass::runOnFunctions(BinaryContext &BC) {
if (!opts::AdrPassOpt || !BC.HasRelocations)
- return;
+ return Error::success();
ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
runOnFunction(BF);
@@ -110,7 +111,8 @@ void ADRRelaxationPass::runOnFunctions(BinaryContext &BC) {
"ADRRelaxationPass");
if (PassFailed)
- exit(1);
+ return createFatalBOLTError("");
+ return Error::success();
}
} // end namespace bolt
diff --git a/bolt/lib/Passes/Aligner.cpp b/bolt/lib/Passes/Aligner.cpp
index 7c387525434b..555f82a5a817 100644
--- a/bolt/lib/Passes/Aligner.cpp
+++ b/bolt/lib/Passes/Aligner.cpp
@@ -147,9 +147,9 @@ void AlignerPass::alignBlocks(BinaryFunction &Function,
}
}
-void AlignerPass::runOnFunctions(BinaryContext &BC) {
+Error AlignerPass::runOnFunctions(BinaryContext &BC) {
if (!BC.HasRelocations)
- return;
+ return Error::success();
AlignHistogram.resize(opts::BlockAlignment);
@@ -179,6 +179,7 @@ void AlignerPass::runOnFunctions(BinaryContext &BC) {
dbgs() << "BOLT-DEBUG: total execution count of aligned blocks: "
<< AlignedBlocksCount << '\n';
);
+ return Error::success();
}
} // end namespace bolt
diff --git a/bolt/lib/Passes/AllocCombiner.cpp b/bolt/lib/Passes/AllocCombiner.cpp
index 6d3f2a56424c..38ef7d02a47d 100644
--- a/bolt/lib/Passes/AllocCombiner.cpp
+++ b/bolt/lib/Passes/AllocCombiner.cpp
@@ -103,17 +103,18 @@ void AllocCombinerPass::combineAdjustments(BinaryFunction &BF) {
}
}
-void AllocCombinerPass::runOnFunctions(BinaryContext &BC) {
+Error AllocCombinerPass::runOnFunctions(BinaryContext &BC) {
if (opts::FrameOptimization == FOP_NONE)
- return;
+ return Error::success();
runForAllWeCare(BC.getBinaryFunctions(), [&](BinaryFunction &Function) {
combineAdjustments(Function);
});
- outs() << "BOLT-INFO: Allocation combiner: " << NumCombined
- << " empty spaces coalesced (dyn count: " << DynamicCountCombined
- << ").\n";
+ BC.outs() << "BOLT-INFO: Allocation combiner: " << NumCombined
+ << " empty spaces coalesced (dyn count: " << DynamicCountCombined
+ << ").\n";
+ return Error::success();
}
} // end namespace bolt
diff --git a/bolt/lib/Passes/AsmDump.cpp b/bolt/lib/Passes/AsmDump.cpp
index 18d0395cbc4a..0a12eae8b5f7 100644
--- a/bolt/lib/Passes/AsmDump.cpp
+++ b/bolt/lib/Passes/AsmDump.cpp
@@ -43,7 +43,7 @@ void dumpCFI(const BinaryFunction &BF, const MCInst &Instr, AsmPrinter &MAP) {
case MCCFIInstruction::OpRememberState:
case MCCFIInstruction::OpRestoreState:
if (opts::Verbosity >= 2)
- errs()
+ BF.getBinaryContext().errs()
<< "BOLT-WARNING: AsmDump: skipping unsupported CFI instruction in "
<< BF << ".\n";
@@ -102,9 +102,9 @@ void dumpFunction(const BinaryFunction &BF) {
// Make sure the new directory exists, creating it if necessary.
if (!opts::AsmDump.empty()) {
if (std::error_code EC = sys::fs::create_directories(opts::AsmDump)) {
- errs() << "BOLT-ERROR: could not create directory '" << opts::AsmDump
- << "': " << EC.message() << '\n';
- exit(1);
+ BC.errs() << "BOLT-ERROR: could not create directory '" << opts::AsmDump
+ << "': " << EC.message() << '\n';
+ return;
}
}
@@ -115,14 +115,14 @@ void dumpFunction(const BinaryFunction &BF) {
? (PrintName + ".s")
: (opts::AsmDump + sys::path::get_separator() + PrintName + ".s")
.str();
- outs() << "BOLT-INFO: Dumping function assembly to " << Filename << "\n";
+ BC.outs() << "BOLT-INFO: Dumping function assembly to " << Filename << "\n";
std::error_code EC;
raw_fd_ostream OS(Filename, EC, sys::fs::OF_None);
if (EC) {
- errs() << "BOLT-ERROR: " << EC.message() << ", unable to open " << Filename
- << " for output.\n";
- exit(1);
+ BC.errs() << "BOLT-ERROR: " << EC.message() << ", unable to open "
+ << Filename << " for output.\n";
+ return;
}
OS.SetUnbuffered();
@@ -237,9 +237,10 @@ void dumpFunction(const BinaryFunction &BF) {
dumpBinaryDataSymbols(OS, BD, LastSection);
}
-void AsmDumpPass::runOnFunctions(BinaryContext &BC) {
+Error AsmDumpPass::runOnFunctions(BinaryContext &BC) {
for (const auto &BFIt : BC.getBinaryFunctions())
dumpFunction(BFIt.second);
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/BinaryFunctionCallGraph.cpp b/bolt/lib/Passes/BinaryFunctionCallGraph.cpp
index 28621a4640d3..2373710c9edd 100644
--- a/bolt/lib/Passes/BinaryFunctionCallGraph.cpp
+++ b/bolt/lib/Passes/BinaryFunctionCallGraph.cpp
@@ -278,13 +278,13 @@ buildCallGraph(BinaryContext &BC, CgFilterFunction Filter, bool CgFromPerfData,
bool PrintInfo = false;
#endif
if (PrintInfo || opts::Verbosity > 0)
- outs() << format("BOLT-INFO: buildCallGraph: %u nodes, %u callsites "
- "(%u recursive), density = %.6lf, %u callsites not "
- "processed, %u callsites with invalid profile, "
- "used perf data for %u stale functions.\n",
- Cg.numNodes(), TotalCallsites, RecursiveCallsites,
- Cg.density(), NotProcessed, NoProfileCallsites,
- NumFallbacks);
+ BC.outs() << format("BOLT-INFO: buildCallGraph: %u nodes, %u callsites "
+ "(%u recursive), density = %.6lf, %u callsites not "
+ "processed, %u callsites with invalid profile, "
+ "used perf data for %u stale functions.\n",
+ Cg.numNodes(), TotalCallsites, RecursiveCallsites,
+ Cg.density(), NotProcessed, NoProfileCallsites,
+ NumFallbacks);
if (opts::DumpCGDot.getNumOccurrences()) {
Cg.printDot(opts::DumpCGDot, [&](CallGraph::NodeId Id) {
diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp
index bcb12272d1b4..1dc463b655f5 100644
--- a/bolt/lib/Passes/BinaryPasses.cpp
+++ b/bolt/lib/Passes/BinaryPasses.cpp
@@ -301,19 +301,20 @@ void NormalizeCFG::runOnFunction(BinaryFunction &BF) {
NumBlocksRemoved += NumRemoved;
}
-void NormalizeCFG::runOnFunctions(BinaryContext &BC) {
+Error NormalizeCFG::runOnFunctions(BinaryContext &BC) {
ParallelUtilities::runOnEachFunction(
BC, ParallelUtilities::SchedulingPolicy::SP_BB_LINEAR,
[&](BinaryFunction &BF) { runOnFunction(BF); },
[&](const BinaryFunction &BF) { return !shouldOptimize(BF); },
"NormalizeCFG");
if (NumBlocksRemoved)
- outs() << "BOLT-INFO: removed " << NumBlocksRemoved << " empty block"
- << (NumBlocksRemoved == 1 ? "" : "s") << '\n';
+ BC.outs() << "BOLT-INFO: removed " << NumBlocksRemoved << " empty block"
+ << (NumBlocksRemoved == 1 ? "" : "s") << '\n';
if (NumDuplicateEdgesMerged)
- outs() << "BOLT-INFO: merged " << NumDuplicateEdgesMerged
- << " duplicate CFG edge" << (NumDuplicateEdgesMerged == 1 ? "" : "s")
- << '\n';
+ BC.outs() << "BOLT-INFO: merged " << NumDuplicateEdgesMerged
+ << " duplicate CFG edge"
+ << (NumDuplicateEdgesMerged == 1 ? "" : "s") << '\n';
+ return Error::success();
}
void EliminateUnreachableBlocks::runOnFunction(BinaryFunction &Function) {
@@ -339,13 +340,13 @@ void EliminateUnreachableBlocks::runOnFunction(BinaryFunction &Function) {
auto L = BC.scopeLock();
Modified.insert(&Function);
if (opts::Verbosity > 0)
- outs() << "BOLT-INFO: removed " << Count
- << " dead basic block(s) accounting for " << Bytes
- << " bytes in function " << Function << '\n';
+ BC.outs() << "BOLT-INFO: removed " << Count
+ << " dead basic block(s) accounting for " << Bytes
+ << " bytes in function " << Function << '\n';
}
}
-void EliminateUnreachableBlocks::runOnFunctions(BinaryContext &BC) {
+Error EliminateUnreachableBlocks::runOnFunctions(BinaryContext &BC) {
ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
runOnFunction(BF);
};
@@ -359,8 +360,9 @@ void EliminateUnreachableBlocks::runOnFunctions(BinaryContext &BC) {
SkipPredicate, "elimininate-unreachable");
if (DeletedBlocks)
- outs() << "BOLT-INFO: UCE removed " << DeletedBlocks << " blocks and "
- << DeletedBytes << " bytes of code\n";
+ BC.outs() << "BOLT-INFO: UCE removed " << DeletedBlocks << " blocks and "
+ << DeletedBytes << " bytes of code\n";
+ return Error::success();
}
bool ReorderBasicBlocks::shouldPrint(const BinaryFunction &BF) const {
@@ -376,9 +378,9 @@ bool ReorderBasicBlocks::shouldOptimize(const BinaryFunction &BF) const {
return BinaryFunctionPass::shouldOptimize(BF);
}
-void ReorderBasicBlocks::runOnFunctions(BinaryContext &BC) {
+Error ReorderBasicBlocks::runOnFunctions(BinaryContext &BC) {
if (opts::ReorderBlocks == ReorderBasicBlocks::LT_NONE)
- return;
+ return Error::success();
std::atomic_uint64_t ModifiedFuncCount(0);
std::mutex FunctionEditDistanceMutex;
@@ -411,8 +413,9 @@ void ReorderBasicBlocks::runOnFunctions(BinaryContext &BC) {
const size_t NumAllProfiledFunctions =
BC.NumProfiledFuncs + BC.NumStaleProfileFuncs;
- outs() << "BOLT-INFO: basic block reordering modified layout of "
- << format("%zu functions (%.2lf%% of profiled, %.2lf%% of total)\n",
+ BC.outs() << "BOLT-INFO: basic block reordering modified layout of "
+ << format(
+ "%zu functions (%.2lf%% of profiled, %.2lf%% of total)\n",
ModifiedFuncCount.load(std::memory_order_relaxed),
100.0 * ModifiedFuncCount.load(std::memory_order_relaxed) /
NumAllProfiledFunctions,
@@ -420,7 +423,7 @@ void ReorderBasicBlocks::runOnFunctions(BinaryContext &BC) {
BC.getBinaryFunctions().size());
if (opts::PrintFuncStat > 0) {
- raw_ostream &OS = outs();
+ raw_ostream &OS = BC.outs();
// Copy all the values into vector in order to sort them
std::map<uint64_t, BinaryFunction &> ScoreMap;
auto &BFs = BC.getBinaryFunctions();
@@ -452,6 +455,7 @@ void ReorderBasicBlocks::runOnFunctions(BinaryContext &BC) {
<< FunctionEditDistance.lookup(&Function) << "\n\n";
}
}
+ return Error::success();
}
bool ReorderBasicBlocks::modifyFunctionLayout(BinaryFunction &BF,
@@ -513,7 +517,7 @@ bool ReorderBasicBlocks::modifyFunctionLayout(BinaryFunction &BF,
return BF.getLayout().update(NewLayout);
}
-void FixupBranches::runOnFunctions(BinaryContext &BC) {
+Error FixupBranches::runOnFunctions(BinaryContext &BC) {
for (auto &It : BC.getBinaryFunctions()) {
BinaryFunction &Function = It.second;
if (!BC.shouldEmit(Function) || !Function.isSimple())
@@ -521,15 +525,18 @@ void FixupBranches::runOnFunctions(BinaryContext &BC) {
Function.fixBranches();
}
+ return Error::success();
}
-void FinalizeFunctions::runOnFunctions(BinaryContext &BC) {
+Error FinalizeFunctions::runOnFunctions(BinaryContext &BC) {
+ std::atomic<bool> HasFatal{false};
ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
if (!BF.finalizeCFIState()) {
if (BC.HasRelocations) {
- errs() << "BOLT-ERROR: unable to fix CFI state for function " << BF
- << ". Exiting.\n";
- exit(1);
+ BC.errs() << "BOLT-ERROR: unable to fix CFI state for function " << BF
+ << ". Exiting.\n";
+ HasFatal = true;
+ return;
}
BF.setSimple(false);
return;
@@ -548,14 +555,17 @@ void FinalizeFunctions::runOnFunctions(BinaryContext &BC) {
ParallelUtilities::runOnEachFunction(
BC, ParallelUtilities::SchedulingPolicy::SP_CONSTANT, WorkFun,
SkipPredicate, "FinalizeFunctions");
+ if (HasFatal)
+ return createFatalBOLTError("finalize CFI state failure");
+ return Error::success();
}
-void CheckLargeFunctions::runOnFunctions(BinaryContext &BC) {
+Error CheckLargeFunctions::runOnFunctions(BinaryContext &BC) {
if (BC.HasRelocations)
- return;
+ return Error::success();
if (!opts::UpdateDebugSections)
- return;
+ return Error::success();
// If the function wouldn't fit, mark it as non-simple. Otherwise, we may emit
// incorrect debug info.
@@ -574,6 +584,8 @@ void CheckLargeFunctions::runOnFunctions(BinaryContext &BC) {
ParallelUtilities::runOnEachFunction(
BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,
SkipFunc, "CheckLargeFunctions");
+
+ return Error::success();
}
bool CheckLargeFunctions::shouldOptimize(const BinaryFunction &BF) const {
@@ -581,7 +593,7 @@ bool CheckLargeFunctions::shouldOptimize(const BinaryFunction &BF) const {
return BF.isSimple() && !BF.isIgnored();
}
-void LowerAnnotations::runOnFunctions(BinaryContext &BC) {
+Error LowerAnnotations::runOnFunctions(BinaryContext &BC) {
// Convert GnuArgsSize annotations into CFIs.
for (BinaryFunction *BF : BC.getAllBinaryFunctions()) {
for (FunctionFragment &FF : BF->getLayout().fragments()) {
@@ -607,13 +619,14 @@ void LowerAnnotations::runOnFunctions(BinaryContext &BC) {
}
}
}
+ return Error::success();
}
// Check for dirty state in MCSymbol objects that might be a consequence
// of running calculateEmittedSize() in parallel, during split functions
// pass. If an inconsistent state is found (symbol already registered or
// already defined), clean it.
-void CleanMCState::runOnFunctions(BinaryContext &BC) {
+Error CleanMCState::runOnFunctions(BinaryContext &BC) {
MCContext &Ctx = *BC.Ctx;
for (const auto &SymMapEntry : Ctx.getSymbols()) {
const MCSymbol *S = SymMapEntry.second;
@@ -631,6 +644,7 @@ void CleanMCState::runOnFunctions(BinaryContext &BC) {
dbgs() << "BOLT-DEBUG: Symbol \"" << S->getName() << "\" is variable\n";
});
}
+ return Error::success();
}
// This peephole fixes jump instructions that jump to another basic
@@ -966,9 +980,9 @@ uint64_t SimplifyConditionalTailCalls::fixTailCalls(BinaryFunction &BF) {
return NumLocalCTCs > 0;
}
-void SimplifyConditionalTailCalls::runOnFunctions(BinaryContext &BC) {
+Error SimplifyConditionalTailCalls::runOnFunctions(BinaryContext &BC) {
if (!BC.isX86())
- return;
+ return Error::success();
for (auto &It : BC.getBinaryFunctions()) {
BinaryFunction &Function = It.second;
@@ -983,16 +997,17 @@ void SimplifyConditionalTailCalls::runOnFunctions(BinaryContext &BC) {
}
if (NumTailCallsPatched)
- outs() << "BOLT-INFO: SCTC: patched " << NumTailCallsPatched
- << " tail calls (" << NumOrigForwardBranches << " forward)"
- << " tail calls (" << NumOrigBackwardBranches << " backward)"
- << " from a total of " << NumCandidateTailCalls << " while removing "
- << NumDoubleJumps << " double jumps"
- << " and removing " << DeletedBlocks << " basic blocks"
- << " totalling " << DeletedBytes
- << " bytes of code. CTCs total execution count is " << CTCExecCount
- << " and the number of times CTCs are taken is " << CTCTakenCount
- << "\n";
+ BC.outs() << "BOLT-INFO: SCTC: patched " << NumTailCallsPatched
+ << " tail calls (" << NumOrigForwardBranches << " forward)"
+ << " tail calls (" << NumOrigBackwardBranches << " backward)"
+ << " from a total of " << NumCandidateTailCalls
+ << " while removing " << NumDoubleJumps << " double jumps"
+ << " and removing " << DeletedBlocks << " basic blocks"
+ << " totalling " << DeletedBytes
+ << " bytes of code. CTCs total execution count is "
+ << CTCExecCount << " and the number of times CTCs are taken is "
+ << CTCTakenCount << "\n";
+ return Error::success();
}
uint64_t ShortenInstructions::shortenInstructions(BinaryFunction &Function) {
@@ -1009,10 +1024,10 @@ uint64_t ShortenInstructions::shortenInstructions(BinaryFunction &Function) {
if (opts::Verbosity > 2) {
BC.scopeLock();
- outs() << "BOLT-INFO: shortening:\nBOLT-INFO: ";
- BC.printInstruction(outs(), OriginalInst, 0, &Function);
- outs() << "BOLT-INFO: to:";
- BC.printInstruction(outs(), Inst, 0, &Function);
+ BC.outs() << "BOLT-INFO: shortening:\nBOLT-INFO: ";
+ BC.printInstruction(BC.outs(), OriginalInst, 0, &Function);
+ BC.outs() << "BOLT-INFO: to:";
+ BC.printInstruction(BC.outs(), Inst, 0, &Function);
}
++Count;
@@ -1022,10 +1037,10 @@ uint64_t ShortenInstructions::shortenInstructions(BinaryFunction &Function) {
return Count;
}
-void ShortenInstructions::runOnFunctions(BinaryContext &BC) {
+Error ShortenInstructions::runOnFunctions(BinaryContext &BC) {
std::atomic<uint64_t> NumShortened{0};
if (!BC.isX86())
- return;
+ return Error::success();
ParallelUtilities::runOnEachFunction(
BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR,
@@ -1033,7 +1048,9 @@ void ShortenInstructions::runOnFunctions(BinaryContext &BC) {
nullptr, "ShortenInstructions");
if (NumShortened)
- outs() << "BOLT-INFO: " << NumShortened << " instructions were shortened\n";
+ BC.outs() << "BOLT-INFO: " << NumShortened
+ << " instructions were shortened\n";
+ return Error::success();
}
void Peepholes::addTailcallTraps(BinaryFunction &Function) {
@@ -1076,12 +1093,12 @@ void Peepholes::removeUselessCondBranches(BinaryFunction &Function) {
}
}
-void Peepholes::runOnFunctions(BinaryContext &BC) {
+Error Peepholes::runOnFunctions(BinaryContext &BC) {
const char Opts =
std::accumulate(opts::Peepholes.begin(), opts::Peepholes.end(), 0,
[](const char A, const PeepholeOpts B) { return A | B; });
if (Opts == PEEP_NONE)
- return;
+ return Error::success();
for (auto &It : BC.getBinaryFunctions()) {
BinaryFunction &Function = It.second;
@@ -1095,12 +1112,13 @@ void Peepholes::runOnFunctions(BinaryContext &BC) {
assert(Function.validateCFG());
}
}
- outs() << "BOLT-INFO: Peephole: " << NumDoubleJumps
- << " double jumps patched.\n"
- << "BOLT-INFO: Peephole: " << TailCallTraps
- << " tail call traps inserted.\n"
- << "BOLT-INFO: Peephole: " << NumUselessCondBranches
- << " useless conditional branches removed.\n";
+ BC.outs() << "BOLT-INFO: Peephole: " << NumDoubleJumps
+ << " double jumps patched.\n"
+ << "BOLT-INFO: Peephole: " << TailCallTraps
+ << " tail call traps inserted.\n"
+ << "BOLT-INFO: Peephole: " << NumUselessCondBranches
+ << " useless conditional branches removed.\n";
+ return Error::success();
}
bool SimplifyRODataLoads::simplifyRODataLoads(BinaryFunction &BF) {
@@ -1185,21 +1203,23 @@ bool SimplifyRODataLoads::simplifyRODataLoads(BinaryFunction &BF) {
return NumLocalLoadsSimplified > 0;
}
-void SimplifyRODataLoads::runOnFunctions(BinaryContext &BC) {
+Error SimplifyRODataLoads::runOnFunctions(BinaryContext &BC) {
for (auto &It : BC.getBinaryFunctions()) {
BinaryFunction &Function = It.second;
if (shouldOptimize(Function) && simplifyRODataLoads(Function))
Modified.insert(&Function);
}
- outs() << "BOLT-INFO: simplified " << NumLoadsSimplified << " out of "
- << NumLoadsFound << " loads from a statically computed address.\n"
- << "BOLT-INFO: dynamic loads simplified: " << NumDynamicLoadsSimplified
- << "\n"
- << "BOLT-INFO: dynamic loads found: " << NumDynamicLoadsFound << "\n";
+ BC.outs() << "BOLT-INFO: simplified " << NumLoadsSimplified << " out of "
+ << NumLoadsFound << " loads from a statically computed address.\n"
+ << "BOLT-INFO: dynamic loads simplified: "
+ << NumDynamicLoadsSimplified << "\n"
+ << "BOLT-INFO: dynamic loads found: " << NumDynamicLoadsFound
+ << "\n";
+ return Error::success();
}
-void AssignSections::runOnFunctions(BinaryContext &BC) {
+Error AssignSections::runOnFunctions(BinaryContext &BC) {
for (BinaryFunction *Function : BC.getInjectedBinaryFunctions()) {
Function->setCodeSectionName(BC.getInjectedCodeSectionName());
Function->setColdCodeSectionName(BC.getInjectedColdCodeSectionName());
@@ -1207,7 +1227,7 @@ void AssignSections::runOnFunctions(BinaryContext &BC) {
// In non-relocation mode functions have pre-assigned section names.
if (!BC.HasRelocations)
- return;
+ return Error::success();
const bool UseColdSection =
BC.NumProfiledFuncs > 0 ||
@@ -1228,9 +1248,10 @@ void AssignSections::runOnFunctions(BinaryContext &BC) {
if (Function.isSplit())
Function.setColdCodeSectionName(BC.getColdCodeSectionName());
}
+ return Error::success();
}
-void PrintProfileStats::runOnFunctions(BinaryContext &BC) {
+Error PrintProfileStats::runOnFunctions(BinaryContext &BC) {
double FlowImbalanceMean = 0.0;
size_t NumBlocksConsidered = 0;
double WorstBias = 0.0;
@@ -1314,16 +1335,17 @@ void PrintProfileStats::runOnFunctions(BinaryContext &BC) {
}
// Report to user
- outs() << format("BOLT-INFO: Profile bias score: %.4lf%% StDev: %.4lf%%\n",
- (100.0 * FlowImbalanceMean), (100.0 * FlowImbalanceVar));
+ BC.outs() << format("BOLT-INFO: Profile bias score: %.4lf%% StDev: %.4lf%%\n",
+ (100.0 * FlowImbalanceMean), (100.0 * FlowImbalanceVar));
if (WorstBiasFunc && opts::Verbosity >= 1) {
- outs() << "Worst average bias observed in " << WorstBiasFunc->getPrintName()
- << "\n";
+ BC.outs() << "Worst average bias observed in "
+ << WorstBiasFunc->getPrintName() << "\n";
LLVM_DEBUG(WorstBiasFunc->dump());
}
+ return Error::success();
}
-void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
+Error PrintProgramStats::runOnFunctions(BinaryContext &BC) {
uint64_t NumRegularFunctions = 0;
uint64_t NumStaleProfileFunctions = 0;
uint64_t NumAllStaleFunctions = 0;
@@ -1354,7 +1376,7 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
if (opts::PrintUnknownCFG)
Function.dump();
else if (opts::PrintUnknown)
- errs() << "function with unknown control flow: " << Function << '\n';
+ BC.errs() << "function with unknown control flow: " << Function << '\n';
++NumUnknownControlFlowFunctions;
}
@@ -1374,9 +1396,9 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
}
} else {
if (opts::ReportStaleFuncs) {
- outs() << StaleFuncsHeader;
+ BC.outs() << StaleFuncsHeader;
StaleFuncsHeader = "";
- outs() << " " << Function << '\n';
+ BC.outs() << " " << Function << '\n';
}
++NumStaleProfileFunctions;
StaleSampleCount += SampleCount;
@@ -1388,15 +1410,15 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
const size_t NumAllProfiledFunctions =
ProfiledFunctions.size() + NumStaleProfileFunctions;
- outs() << "BOLT-INFO: " << NumAllProfiledFunctions << " out of "
- << NumRegularFunctions << " functions in the binary ("
- << format("%.1f", NumAllProfiledFunctions /
- (float)NumRegularFunctions * 100.0f)
- << "%) have non-empty execution profile\n";
+ BC.outs() << "BOLT-INFO: " << NumAllProfiledFunctions << " out of "
+ << NumRegularFunctions << " functions in the binary ("
+ << format("%.1f", NumAllProfiledFunctions /
+ (float)NumRegularFunctions * 100.0f)
+ << "%) have non-empty execution profile\n";
if (NumNonSimpleProfiledFunctions) {
- outs() << "BOLT-INFO: " << NumNonSimpleProfiledFunctions << " function"
- << (NumNonSimpleProfiledFunctions == 1 ? "" : "s")
- << " with profile could not be optimized\n";
+ BC.outs() << "BOLT-INFO: " << NumNonSimpleProfiledFunctions << " function"
+ << (NumNonSimpleProfiledFunctions == 1 ? "" : "s")
+ << " with profile could not be optimized\n";
}
if (NumAllStaleFunctions) {
const float PctStale =
@@ -1409,52 +1431,54 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
BC.Stats.NumStaleBlocks * 100.0f;
auto printErrorOrWarning = [&]() {
if (PctStale > opts::StaleThreshold)
- errs() << "BOLT-ERROR: ";
+ BC.errs() << "BOLT-ERROR: ";
else
- errs() << "BOLT-WARNING: ";
+ BC.errs() << "BOLT-WARNING: ";
};
printErrorOrWarning();
- errs() << NumAllStaleFunctions
- << format(" (%.1f%% of all profiled)", PctStale) << " function"
- << (NumAllStaleFunctions == 1 ? "" : "s")
- << " have invalid (possibly stale) profile."
- " Use -report-stale to see the list.\n";
+ BC.errs() << NumAllStaleFunctions
+ << format(" (%.1f%% of all profiled)", PctStale) << " function"
+ << (NumAllStaleFunctions == 1 ? "" : "s")
+ << " have invalid (possibly stale) profile."
+ " Use -report-stale to see the list.\n";
if (TotalSampleCount > 0) {
printErrorOrWarning();
- errs() << (StaleSampleCount + InferredSampleCount) << " out of "
- << TotalSampleCount << " samples in the binary ("
- << format("%.1f",
- ((100.0f * (StaleSampleCount + InferredSampleCount)) /
- TotalSampleCount))
- << "%) belong to functions with invalid"
- " (possibly stale) profile.\n";
+ BC.errs() << (StaleSampleCount + InferredSampleCount) << " out of "
+ << TotalSampleCount << " samples in the binary ("
+ << format("%.1f",
+ ((100.0f * (StaleSampleCount + InferredSampleCount)) /
+ TotalSampleCount))
+ << "%) belong to functions with invalid"
+ " (possibly stale) profile.\n";
}
- outs() << "BOLT-INFO: " << BC.Stats.NumStaleFuncsWithEqualBlockCount
- << " stale function"
- << (BC.Stats.NumStaleFuncsWithEqualBlockCount == 1 ? "" : "s")
- << format(" (%.1f%% of all stale)", PctStaleFuncsWithEqualBlockCount)
- << " have matching block count.\n";
- outs() << "BOLT-INFO: " << BC.Stats.NumStaleBlocksWithEqualIcount
- << " stale block"
- << (BC.Stats.NumStaleBlocksWithEqualIcount == 1 ? "" : "s")
- << format(" (%.1f%% of all stale)", PctStaleBlocksWithEqualIcount)
- << " have matching icount.\n";
+ BC.outs() << "BOLT-INFO: " << BC.Stats.NumStaleFuncsWithEqualBlockCount
+ << " stale function"
+ << (BC.Stats.NumStaleFuncsWithEqualBlockCount == 1 ? "" : "s")
+ << format(" (%.1f%% of all stale)",
+ PctStaleFuncsWithEqualBlockCount)
+ << " have matching block count.\n";
+ BC.outs() << "BOLT-INFO: " << BC.Stats.NumStaleBlocksWithEqualIcount
+ << " stale block"
+ << (BC.Stats.NumStaleBlocksWithEqualIcount == 1 ? "" : "s")
+ << format(" (%.1f%% of all stale)", PctStaleBlocksWithEqualIcount)
+ << " have matching icount.\n";
if (PctStale > opts::StaleThreshold) {
- errs() << "BOLT-ERROR: stale functions exceed specified threshold of "
- << opts::StaleThreshold << "%. Exiting.\n";
- exit(1);
+ return createFatalBOLTError(
+ Twine("BOLT-ERROR: stale functions exceed specified threshold of ") +
+ Twine(opts::StaleThreshold.getValue()) + Twine("%. Exiting.\n"));
}
}
if (NumInferredFunctions) {
- outs() << format("BOLT-INFO: inferred profile for %d (%.2f%% of profiled, "
- "%.2f%% of stale) functions responsible for %.2f%% samples"
- " (%zu out of %zu)\n",
- NumInferredFunctions,
- 100.0 * NumInferredFunctions / NumAllProfiledFunctions,
- 100.0 * NumInferredFunctions / NumAllStaleFunctions,
- 100.0 * InferredSampleCount / TotalSampleCount,
- InferredSampleCount, TotalSampleCount);
- outs() << format(
+ BC.outs() << format(
+ "BOLT-INFO: inferred profile for %d (%.2f%% of profiled, "
+ "%.2f%% of stale) functions responsible for %.2f%% samples"
+ " (%zu out of %zu)\n",
+ NumInferredFunctions,
+ 100.0 * NumInferredFunctions / NumAllProfiledFunctions,
+ 100.0 * NumInferredFunctions / NumAllStaleFunctions,
+ 100.0 * InferredSampleCount / TotalSampleCount, InferredSampleCount,
+ TotalSampleCount);
+ BC.outs() << format(
"BOLT-INFO: inference found an exact match for %.2f%% of basic blocks"
" (%zu out of %zu stale) responsible for %.2f%% samples"
" (%zu out of %zu stale)\n",
@@ -1465,13 +1489,13 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
}
if (const uint64_t NumUnusedObjects = BC.getNumUnusedProfiledObjects()) {
- outs() << "BOLT-INFO: profile for " << NumUnusedObjects
- << " objects was ignored\n";
+ BC.outs() << "BOLT-INFO: profile for " << NumUnusedObjects
+ << " objects was ignored\n";
}
if (ProfiledFunctions.size() > 10) {
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: top called functions are:\n";
+ BC.outs() << "BOLT-INFO: top called functions are:\n";
llvm::sort(ProfiledFunctions,
[](const BinaryFunction *A, const BinaryFunction *B) {
return B->getExecutionCount() < A->getExecutionCount();
@@ -1480,7 +1504,8 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
auto SFIend = ProfiledFunctions.end();
for (unsigned I = 0u; I < opts::TopCalledLimit && SFI != SFIend;
++SFI, ++I)
- outs() << " " << **SFI << " : " << (*SFI)->getExecutionCount() << '\n';
+ BC.outs() << " " << **SFI << " : " << (*SFI)->getExecutionCount()
+ << '\n';
}
}
@@ -1520,70 +1545,70 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
});
}
- outs() << "BOLT-INFO: top functions sorted by ";
+ BC.outs() << "BOLT-INFO: top functions sorted by ";
if (SortAll) {
- outs() << "dyno stats";
+ BC.outs() << "dyno stats";
} else {
- outs() << "(";
+ BC.outs() << "(";
bool PrintComma = false;
for (const DynoStats::Category Category : opts::PrintSortedBy) {
if (PrintComma)
- outs() << ", ";
- outs() << DynoStats::Description(Category);
+ BC.outs() << ", ";
+ BC.outs() << DynoStats::Description(Category);
PrintComma = true;
}
- outs() << ")";
+ BC.outs() << ")";
}
- outs() << " are:\n";
+ BC.outs() << " are:\n";
auto SFI = Functions.begin();
for (unsigned I = 0; I < 100 && SFI != Functions.end(); ++SFI, ++I) {
const DynoStats Stats = getDynoStats(**SFI);
- outs() << " " << **SFI;
+ BC.outs() << " " << **SFI;
if (!SortAll) {
- outs() << " (";
+ BC.outs() << " (";
bool PrintComma = false;
for (const DynoStats::Category Category : opts::PrintSortedBy) {
if (PrintComma)
- outs() << ", ";
- outs() << dynoStatsOptName(Category) << "=" << Stats[Category];
+ BC.outs() << ", ";
+ BC.outs() << dynoStatsOptName(Category) << "=" << Stats[Category];
PrintComma = true;
}
- outs() << ")";
+ BC.outs() << ")";
}
- outs() << "\n";
+ BC.outs() << "\n";
}
}
if (!BC.TrappedFunctions.empty()) {
- errs() << "BOLT-WARNING: " << BC.TrappedFunctions.size() << " function"
- << (BC.TrappedFunctions.size() > 1 ? "s" : "")
- << " will trap on entry. Use -trap-avx512=0 to disable"
- " traps.";
+ BC.errs() << "BOLT-WARNING: " << BC.TrappedFunctions.size() << " function"
+ << (BC.TrappedFunctions.size() > 1 ? "s" : "")
+ << " will trap on entry. Use -trap-avx512=0 to disable"
+ " traps.";
if (opts::Verbosity >= 1 || BC.TrappedFunctions.size() <= 5) {
- errs() << '\n';
+ BC.errs() << '\n';
for (const BinaryFunction *Function : BC.TrappedFunctions)
- errs() << " " << *Function << '\n';
+ BC.errs() << " " << *Function << '\n';
} else {
- errs() << " Use -v=1 to see the list.\n";
+ BC.errs() << " Use -v=1 to see the list.\n";
}
}
// Print information on missed macro-fusion opportunities seen on input.
if (BC.Stats.MissedMacroFusionPairs) {
- outs() << format("BOLT-INFO: the input contains %zu (dynamic count : %zu)"
- " opportunities for macro-fusion optimization",
- BC.Stats.MissedMacroFusionPairs,
- BC.Stats.MissedMacroFusionExecCount);
+ BC.outs() << format(
+ "BOLT-INFO: the input contains %zu (dynamic count : %zu)"
+ " opportunities for macro-fusion optimization",
+ BC.Stats.MissedMacroFusionPairs, BC.Stats.MissedMacroFusionExecCount);
switch (opts::AlignMacroOpFusion) {
case MFT_NONE:
- outs() << ". Use -align-macro-fusion to fix.\n";
+ BC.outs() << ". Use -align-macro-fusion to fix.\n";
break;
case MFT_HOT:
- outs() << ". Will fix instances on a hot path.\n";
+ BC.outs() << ". Will fix instances on a hot path.\n";
break;
case MFT_ALL:
- outs() << " that are going to be fixed\n";
+ BC.outs() << " that are going to be fixed\n";
break;
}
}
@@ -1618,36 +1643,38 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
B->getKnownExecutionCount() / B->getSize();
});
- outs() << "BOLT-INFO: " << SuboptimalFuncs.size()
- << " functions have "
- "cold code in the middle of hot code. Top functions are:\n";
+ BC.outs() << "BOLT-INFO: " << SuboptimalFuncs.size()
+ << " functions have "
+ "cold code in the middle of hot code. Top functions are:\n";
for (unsigned I = 0;
I < std::min(static_cast<size_t>(opts::ReportBadLayout),
SuboptimalFuncs.size());
++I)
- SuboptimalFuncs[I]->print(outs());
+ SuboptimalFuncs[I]->print(BC.outs());
}
}
if (NumUnknownControlFlowFunctions) {
- outs() << "BOLT-INFO: " << NumUnknownControlFlowFunctions
- << " functions have instructions with unknown control flow";
+ BC.outs() << "BOLT-INFO: " << NumUnknownControlFlowFunctions
+ << " functions have instructions with unknown control flow";
if (!opts::PrintUnknown)
- outs() << ". Use -print-unknown to see the list.";
- outs() << '\n';
+ BC.outs() << ". Use -print-unknown to see the list.";
+ BC.outs() << '\n';
}
+ return Error::success();
}
-void InstructionLowering::runOnFunctions(BinaryContext &BC) {
+Error InstructionLowering::runOnFunctions(BinaryContext &BC) {
for (auto &BFI : BC.getBinaryFunctions())
for (BinaryBasicBlock &BB : BFI.second)
for (MCInst &Instruction : BB)
BC.MIB->lowerTailCall(Instruction);
+ return Error::success();
}
-void StripRepRet::runOnFunctions(BinaryContext &BC) {
+Error StripRepRet::runOnFunctions(BinaryContext &BC) {
if (!BC.isX86())
- return;
+ return Error::success();
uint64_t NumPrefixesRemoved = 0;
uint64_t NumBytesSaved = 0;
@@ -1664,15 +1691,16 @@ void StripRepRet::runOnFunctions(BinaryContext &BC) {
}
if (NumBytesSaved)
- outs() << "BOLT-INFO: removed " << NumBytesSaved
- << " 'repz' prefixes"
- " with estimated execution count of "
- << NumPrefixesRemoved << " times.\n";
+ BC.outs() << "BOLT-INFO: removed " << NumBytesSaved
+ << " 'repz' prefixes"
+ " with estimated execution count of "
+ << NumPrefixesRemoved << " times.\n";
+ return Error::success();
}
-void InlineMemcpy::runOnFunctions(BinaryContext &BC) {
+Error InlineMemcpy::runOnFunctions(BinaryContext &BC) {
if (!BC.isX86())
- return;
+ return Error::success();
uint64_t NumInlined = 0;
uint64_t NumInlinedDyno = 0;
@@ -1711,12 +1739,13 @@ void InlineMemcpy::runOnFunctions(BinaryContext &BC) {
}
if (NumInlined) {
- outs() << "BOLT-INFO: inlined " << NumInlined << " memcpy() calls";
+ BC.outs() << "BOLT-INFO: inlined " << NumInlined << " memcpy() calls";
if (NumInlinedDyno)
- outs() << ". The calls were executed " << NumInlinedDyno
- << " times based on profile.";
- outs() << '\n';
+ BC.outs() << ". The calls were executed " << NumInlinedDyno
+ << " times based on profile.";
+ BC.outs() << '\n';
}
+ return Error::success();
}
bool SpecializeMemcpy1::shouldOptimize(const BinaryFunction &Function) const {
@@ -1757,9 +1786,9 @@ std::set<size_t> SpecializeMemcpy1::getCallSitesToOptimize(
return Sites;
}
-void SpecializeMemcpy1::runOnFunctions(BinaryContext &BC) {
+Error SpecializeMemcpy1::runOnFunctions(BinaryContext &BC) {
if (!BC.isX86())
- return;
+ return Error::success();
uint64_t NumSpecialized = 0;
uint64_t NumSpecializedDyno = 0;
@@ -1844,13 +1873,14 @@ void SpecializeMemcpy1::runOnFunctions(BinaryContext &BC) {
}
if (NumSpecialized) {
- outs() << "BOLT-INFO: specialized " << NumSpecialized
- << " memcpy() call sites for size 1";
+ BC.outs() << "BOLT-INFO: specialized " << NumSpecialized
+ << " memcpy() call sites for size 1";
if (NumSpecializedDyno)
- outs() << ". The calls were executed " << NumSpecializedDyno
- << " times based on profile.";
- outs() << '\n';
+ BC.outs() << ". The calls were executed " << NumSpecializedDyno
+ << " times based on profile.";
+ BC.outs() << '\n';
}
+ return Error::success();
}
void RemoveNops::runOnFunction(BinaryFunction &BF) {
@@ -1864,7 +1894,7 @@ void RemoveNops::runOnFunction(BinaryFunction &BF) {
}
}
-void RemoveNops::runOnFunctions(BinaryContext &BC) {
+Error RemoveNops::runOnFunctions(BinaryContext &BC) {
ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
runOnFunction(BF);
};
@@ -1876,6 +1906,7 @@ void RemoveNops::runOnFunctions(BinaryContext &BC) {
ParallelUtilities::runOnEachFunction(
BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,
SkipFunc, "RemoveNops");
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/CMOVConversion.cpp b/bolt/lib/Passes/CMOVConversion.cpp
index 6213479a5090..2492ff217946 100644
--- a/bolt/lib/Passes/CMOVConversion.cpp
+++ b/bolt/lib/Passes/CMOVConversion.cpp
@@ -168,14 +168,14 @@ int calculateConditionBias(const BinaryBasicBlock &BB,
return -1;
}
-void CMOVConversion::Stats::dump() {
- outs() << "converted static " << StaticPerformed << "/" << StaticPossible
- << formatv(" ({0:P}) ", getStaticRatio())
- << "hammock(s) into CMOV sequences, with dynamic execution count "
- << DynamicPerformed << "/" << DynamicPossible
- << formatv(" ({0:P}), ", getDynamicRatio()) << "saving " << RemovedMP
- << "/" << PossibleMP << formatv(" ({0:P}) ", getMPRatio())
- << "mispredictions\n";
+void CMOVConversion::Stats::dumpTo(raw_ostream &OS) {
+ OS << "converted static " << StaticPerformed << "/" << StaticPossible
+ << formatv(" ({0:P}) ", getStaticRatio())
+ << "hammock(s) into CMOV sequences, with dynamic execution count "
+ << DynamicPerformed << "/" << DynamicPossible
+ << formatv(" ({0:P}), ", getDynamicRatio()) << "saving " << RemovedMP
+ << "/" << PossibleMP << formatv(" ({0:P}) ", getMPRatio())
+ << "mispredictions\n";
}
void CMOVConversion::runOnFunction(BinaryFunction &Function) {
@@ -265,13 +265,13 @@ void CMOVConversion::runOnFunction(BinaryFunction &Function) {
if (Modified)
Function.eraseInvalidBBs();
if (opts::Verbosity > 1) {
- outs() << "BOLT-INFO: CMOVConversion: " << Function << ", ";
- Local.dump();
+ BC.outs() << "BOLT-INFO: CMOVConversion: " << Function << ", ";
+ Local.dumpTo(BC.outs());
}
Global = Global + Local;
}
-void CMOVConversion::runOnFunctions(BinaryContext &BC) {
+Error CMOVConversion::runOnFunctions(BinaryContext &BC) {
for (auto &It : BC.getBinaryFunctions()) {
BinaryFunction &Function = It.second;
if (!shouldOptimize(Function))
@@ -279,8 +279,9 @@ void CMOVConversion::runOnFunctions(BinaryContext &BC) {
runOnFunction(Function);
}
- outs() << "BOLT-INFO: CMOVConversion total: ";
- Global.dump();
+ BC.outs() << "BOLT-INFO: CMOVConversion total: ";
+ Global.dumpTo(BC.outs());
+ return Error::success();
}
} // end namespace bolt
diff --git a/bolt/lib/Passes/CacheMetrics.cpp b/bolt/lib/Passes/CacheMetrics.cpp
index f6708997a433..b02d4303110b 100644
--- a/bolt/lib/Passes/CacheMetrics.cpp
+++ b/bolt/lib/Passes/CacheMetrics.cpp
@@ -189,7 +189,8 @@ double expectedCacheHitRatio(
} // namespace
-void CacheMetrics::printAll(const std::vector<BinaryFunction *> &BFs) {
+void CacheMetrics::printAll(raw_ostream &OS,
+ const std::vector<BinaryFunction *> &BFs) {
// Stats related to hot-cold code splitting
size_t NumFunctions = 0;
size_t NumProfiledFunctions = 0;
@@ -222,36 +223,36 @@ void CacheMetrics::printAll(const std::vector<BinaryFunction *> &BFs) {
}
}
- outs() << format(" There are %zu functions;", NumFunctions)
- << format(" %zu (%.2lf%%) are in the hot section,", NumHotFunctions,
- 100.0 * NumHotFunctions / NumFunctions)
- << format(" %zu (%.2lf%%) have profile\n", NumProfiledFunctions,
- 100.0 * NumProfiledFunctions / NumFunctions);
- outs() << format(" There are %zu basic blocks;", NumBlocks)
- << format(" %zu (%.2lf%%) are in the hot section\n", NumHotBlocks,
- 100.0 * NumHotBlocks / NumBlocks);
+ OS << format(" There are %zu functions;", NumFunctions)
+ << format(" %zu (%.2lf%%) are in the hot section,", NumHotFunctions,
+ 100.0 * NumHotFunctions / NumFunctions)
+ << format(" %zu (%.2lf%%) have profile\n", NumProfiledFunctions,
+ 100.0 * NumProfiledFunctions / NumFunctions);
+ OS << format(" There are %zu basic blocks;", NumBlocks)
+ << format(" %zu (%.2lf%%) are in the hot section\n", NumHotBlocks,
+ 100.0 * NumHotBlocks / NumBlocks);
assert(TotalCodeMinAddr <= TotalCodeMaxAddr && "incorrect output addresses");
size_t HotCodeSize = HotCodeMaxAddr - HotCodeMinAddr;
size_t TotalCodeSize = TotalCodeMaxAddr - TotalCodeMinAddr;
size_t HugePage2MB = 2 << 20;
- outs() << format(" Hot code takes %.2lf%% of binary (%zu bytes out of %zu, "
- "%.2lf huge pages)\n",
- 100.0 * HotCodeSize / TotalCodeSize, HotCodeSize,
- TotalCodeSize, double(HotCodeSize) / HugePage2MB);
+ OS << format(" Hot code takes %.2lf%% of binary (%zu bytes out of %zu, "
+ "%.2lf huge pages)\n",
+ 100.0 * HotCodeSize / TotalCodeSize, HotCodeSize, TotalCodeSize,
+ double(HotCodeSize) / HugePage2MB);
// Stats related to expected cache performance
std::unordered_map<BinaryBasicBlock *, uint64_t> BBAddr;
std::unordered_map<BinaryBasicBlock *, uint64_t> BBSize;
extractBasicBlockInfo(BFs, BBAddr, BBSize);
- outs() << " Expected i-TLB cache hit ratio: "
- << format("%.2lf%%\n", expectedCacheHitRatio(BFs, BBAddr, BBSize));
+ OS << " Expected i-TLB cache hit ratio: "
+ << format("%.2lf%%\n", expectedCacheHitRatio(BFs, BBAddr, BBSize));
auto Stats = calcTSPScore(BFs, BBAddr, BBSize);
- outs() << " TSP score: "
- << format("%.2lf%% (%zu out of %zu)\n",
- 100.0 * Stats.first / std::max<uint64_t>(Stats.second, 1),
- Stats.first, Stats.second);
+ OS << " TSP score: "
+ << format("%.2lf%% (%zu out of %zu)\n",
+ 100.0 * Stats.first / std::max<uint64_t>(Stats.second, 1),
+ Stats.first, Stats.second);
}
diff --git a/bolt/lib/Passes/FixRISCVCallsPass.cpp b/bolt/lib/Passes/FixRISCVCallsPass.cpp
index e2984deda16d..83c745facb29 100644
--- a/bolt/lib/Passes/FixRISCVCallsPass.cpp
+++ b/bolt/lib/Passes/FixRISCVCallsPass.cpp
@@ -68,9 +68,9 @@ void FixRISCVCallsPass::runOnFunction(BinaryFunction &BF) {
}
}
-void FixRISCVCallsPass::runOnFunctions(BinaryContext &BC) {
+Error FixRISCVCallsPass::runOnFunctions(BinaryContext &BC) {
if (!BC.isRISCV() || !BC.HasRelocations)
- return;
+ return Error::success();
ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
runOnFunction(BF);
@@ -79,6 +79,8 @@ void FixRISCVCallsPass::runOnFunctions(BinaryContext &BC) {
ParallelUtilities::runOnEachFunction(
BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun, nullptr,
"FixRISCVCalls");
+
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/FixRelaxationPass.cpp b/bolt/lib/Passes/FixRelaxationPass.cpp
index 3dd19b6b43b7..a49fb9894e80 100644
--- a/bolt/lib/Passes/FixRelaxationPass.cpp
+++ b/bolt/lib/Passes/FixRelaxationPass.cpp
@@ -47,9 +47,9 @@ void FixRelaxations::runOnFunction(BinaryFunction &BF) {
}
}
-void FixRelaxations::runOnFunctions(BinaryContext &BC) {
+Error FixRelaxations::runOnFunctions(BinaryContext &BC) {
if (!BC.isAArch64() || !BC.HasRelocations)
- return;
+ return Error::success();
ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
runOnFunction(BF);
@@ -58,6 +58,7 @@ void FixRelaxations::runOnFunctions(BinaryContext &BC) {
ParallelUtilities::runOnEachFunction(
BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun, nullptr,
"FixRelaxations");
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/FrameAnalysis.cpp b/bolt/lib/Passes/FrameAnalysis.cpp
index 1e6be498a479..7f1245e39f56 100644
--- a/bolt/lib/Passes/FrameAnalysis.cpp
+++ b/bolt/lib/Passes/FrameAnalysis.cpp
@@ -124,7 +124,7 @@ class FrameAccessAnalysis {
if (IsIndexed || (!FIE.Size && (FIE.IsLoad || FIE.IsStore))) {
LLVM_DEBUG(dbgs() << "Giving up on indexed memory access/unknown size\n");
LLVM_DEBUG(dbgs() << "Blame insn: ");
- LLVM_DEBUG(BC.printInstruction(outs(), Inst, 0, &BF, true, false, false));
+ LLVM_DEBUG(BC.printInstruction(dbgs(), Inst, 0, &BF, true, false, false));
LLVM_DEBUG(Inst.dump());
return false;
}
@@ -570,13 +570,14 @@ FrameAnalysis::FrameAnalysis(BinaryContext &BC, BinaryFunctionCallGraph &CG)
}
void FrameAnalysis::printStats() {
- outs() << "BOLT-INFO: FRAME ANALYSIS: " << NumFunctionsNotOptimized
- << " function(s) were not optimized.\n"
- << "BOLT-INFO: FRAME ANALYSIS: " << NumFunctionsFailedRestoreFI
- << " function(s) "
- << format("(%.1lf%% dyn cov)",
+ BC.outs() << "BOLT-INFO: FRAME ANALYSIS: " << NumFunctionsNotOptimized
+ << " function(s) were not optimized.\n"
+ << "BOLT-INFO: FRAME ANALYSIS: " << NumFunctionsFailedRestoreFI
+ << " function(s) "
+ << format(
+ "(%.1lf%% dyn cov)",
(100.0 * CountFunctionsFailedRestoreFI / CountDenominator))
- << " could not have its frame indices restored.\n";
+ << " could not have its frame indices restored.\n";
}
void FrameAnalysis::clearSPTMap() {
diff --git a/bolt/lib/Passes/FrameOptimizer.cpp b/bolt/lib/Passes/FrameOptimizer.cpp
index 6f6dea08950a..fb5f8eafa5cf 100644
--- a/bolt/lib/Passes/FrameOptimizer.cpp
+++ b/bolt/lib/Passes/FrameOptimizer.cpp
@@ -221,9 +221,9 @@ void FrameOptimizerPass::removeUnusedStores(const FrameAnalysis &FA,
LLVM_DEBUG(dbgs() << "FOP modified \"" << BF.getPrintName() << "\"\n");
}
-void FrameOptimizerPass::runOnFunctions(BinaryContext &BC) {
+Error FrameOptimizerPass::runOnFunctions(BinaryContext &BC) {
if (opts::FrameOptimization == FOP_NONE)
- return;
+ return Error::success();
std::unique_ptr<BinaryFunctionCallGraph> CG;
std::unique_ptr<FrameAnalysis> FA;
@@ -285,29 +285,31 @@ void FrameOptimizerPass::runOnFunctions(BinaryContext &BC) {
{
NamedRegionTimer T1("shrinkwrapping", "shrink wrapping", "FOP",
"FOP breakdown", opts::TimeOpts);
- performShrinkWrapping(*RA, *FA, BC);
+ if (Error E = performShrinkWrapping(*RA, *FA, BC))
+ return Error(std::move(E));
}
- outs() << "BOLT-INFO: FOP optimized " << NumRedundantLoads
- << " redundant load(s) and " << NumRedundantStores
- << " unused store(s)\n";
- outs() << "BOLT-INFO: Frequency of redundant loads is " << FreqRedundantLoads
- << " and frequency of unused stores is " << FreqRedundantStores
- << "\n";
- outs() << "BOLT-INFO: Frequency of loads changed to use a register is "
- << FreqLoadsChangedToReg
- << " and frequency of loads changed to use an immediate is "
- << FreqLoadsChangedToImm << "\n";
- outs() << "BOLT-INFO: FOP deleted " << NumLoadsDeleted
- << " load(s) (dyn count: " << FreqLoadsDeleted << ") and "
- << NumRedundantStores << " store(s)\n";
+ BC.outs() << "BOLT-INFO: FOP optimized " << NumRedundantLoads
+ << " redundant load(s) and " << NumRedundantStores
+ << " unused store(s)\n";
+ BC.outs() << "BOLT-INFO: Frequency of redundant loads is "
+ << FreqRedundantLoads << " and frequency of unused stores is "
+ << FreqRedundantStores << "\n";
+ BC.outs() << "BOLT-INFO: Frequency of loads changed to use a register is "
+ << FreqLoadsChangedToReg
+ << " and frequency of loads changed to use an immediate is "
+ << FreqLoadsChangedToImm << "\n";
+ BC.outs() << "BOLT-INFO: FOP deleted " << NumLoadsDeleted
+ << " load(s) (dyn count: " << FreqLoadsDeleted << ") and "
+ << NumRedundantStores << " store(s)\n";
FA->printStats();
- ShrinkWrapping::printStats();
+ ShrinkWrapping::printStats(BC);
+ return Error::success();
}
-void FrameOptimizerPass::performShrinkWrapping(const RegAnalysis &RA,
- const FrameAnalysis &FA,
- BinaryContext &BC) {
+Error FrameOptimizerPass::performShrinkWrapping(const RegAnalysis &RA,
+ const FrameAnalysis &FA,
+ BinaryContext &BC) {
// Initialize necessary annotations to allow safe parallel accesses to
// annotation index in MIB
BC.MIB->getOrCreateAnnotationIndex(CalleeSavedAnalysis::getSaveTagName());
@@ -357,12 +359,21 @@ void FrameOptimizerPass::performShrinkWrapping(const RegAnalysis &RA,
const bool HotOnly = opts::FrameOptimization == FOP_HOT;
+ Error SWError = Error::success();
+
ParallelUtilities::WorkFuncWithAllocTy WorkFunction =
[&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId) {
DataflowInfoManager Info(BF, &RA, &FA, AllocatorId);
ShrinkWrapping SW(FA, BF, Info, AllocatorId);
- if (SW.perform(HotOnly)) {
+ auto ChangedOrErr = SW.perform(HotOnly);
+ if (auto E = ChangedOrErr.takeError()) {
+ std::lock_guard<std::mutex> Lock(FuncsChangedMutex);
+ SWError = joinErrors(std::move(SWError), Error(std::move(E)));
+ return;
+ }
+ const bool Changed = *ChangedOrErr;
+ if (Changed) {
std::lock_guard<std::mutex> Lock(FuncsChangedMutex);
FuncsChanged.insert(&BF);
LLVM_DEBUG(LogFunc(BF));
@@ -374,10 +385,11 @@ void FrameOptimizerPass::performShrinkWrapping(const RegAnalysis &RA,
SkipPredicate, "shrink-wrapping");
if (!Top10Funcs.empty()) {
- outs() << "BOLT-INFO: top 10 functions changed by shrink wrapping:\n";
+ BC.outs() << "BOLT-INFO: top 10 functions changed by shrink wrapping:\n";
for (const auto &Elmt : Top10Funcs)
- outs() << Elmt.first << " : " << Elmt.second->getPrintName() << "\n";
+ BC.outs() << Elmt.first << " : " << Elmt.second->getPrintName() << "\n";
}
+ return SWError;
}
} // namespace bolt
diff --git a/bolt/lib/Passes/Hugify.cpp b/bolt/lib/Passes/Hugify.cpp
index d2a64fb97c19..b77356153bfd 100644
--- a/bolt/lib/Passes/Hugify.cpp
+++ b/bolt/lib/Passes/Hugify.cpp
@@ -16,10 +16,10 @@ using namespace llvm;
namespace llvm {
namespace bolt {
-void HugePage::runOnFunctions(BinaryContext &BC) {
+Error HugePage::runOnFunctions(BinaryContext &BC) {
auto *RtLibrary = BC.getRuntimeLibrary();
if (!RtLibrary || !BC.isELF() || !BC.StartFunctionAddress) {
- return;
+ return Error::success();
}
auto createSimpleFunction =
@@ -45,6 +45,7 @@ void HugePage::runOnFunctions(BinaryContext &BC) {
const MCSymbol *StartSym = Start->getSymbol();
createSimpleFunction("__bolt_hugify_start_program",
BC.MIB->createSymbolTrampoline(StartSym, BC.Ctx.get()));
+ return Error::success();
}
} // namespace bolt
} // namespace llvm
diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp
index dfbc72e48e5d..9f8d82b05ccf 100644
--- a/bolt/lib/Passes/IdenticalCodeFolding.cpp
+++ b/bolt/lib/Passes/IdenticalCodeFolding.cpp
@@ -341,7 +341,7 @@ typedef std::unordered_map<BinaryFunction *, std::vector<BinaryFunction *>,
namespace llvm {
namespace bolt {
-void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
+Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
const size_t OriginalFunctionCount = BC.getBinaryFunctions().size();
uint64_t NumFunctionsFolded = 0;
std::atomic<uint64_t> NumJTFunctionsFolded{0};
@@ -508,14 +508,16 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
});
if (NumFunctionsFolded)
- outs() << "BOLT-INFO: ICF folded " << NumFunctionsFolded << " out of "
- << OriginalFunctionCount << " functions in " << Iteration
- << " passes. " << NumJTFunctionsFolded
- << " functions had jump tables.\n"
- << "BOLT-INFO: Removing all identical functions will save "
- << format("%.2lf", (double)BytesSavedEstimate / 1024)
- << " KB of code space. Folded functions were called " << NumCalled
- << " times based on profile.\n";
+ BC.outs() << "BOLT-INFO: ICF folded " << NumFunctionsFolded << " out of "
+ << OriginalFunctionCount << " functions in " << Iteration
+ << " passes. " << NumJTFunctionsFolded
+ << " functions had jump tables.\n"
+ << "BOLT-INFO: Removing all identical functions will save "
+ << format("%.2lf", (double)BytesSavedEstimate / 1024)
+ << " KB of code space. Folded functions were called " << NumCalled
+ << " times based on profile.\n";
+
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/IndirectCallPromotion.cpp b/bolt/lib/Passes/IndirectCallPromotion.cpp
index 451758161ef5..55eede641fd2 100644
--- a/bolt/lib/Passes/IndirectCallPromotion.cpp
+++ b/bolt/lib/Passes/IndirectCallPromotion.cpp
@@ -171,9 +171,10 @@ static bool verifyProfile(std::map<uint64_t, BinaryFunction> &BFs) {
if (BI->Count != BinaryBasicBlock::COUNT_NO_PROFILE && BI->Count > 0) {
if (BB.getKnownExecutionCount() == 0 ||
SuccBB->getKnownExecutionCount() == 0) {
- errs() << "BOLT-WARNING: profile verification failed after ICP for "
- "function "
- << BF << '\n';
+ BF.getBinaryContext().errs()
+ << "BOLT-WARNING: profile verification failed after ICP for "
+ "function "
+ << BF << '\n';
IsValid = false;
}
}
@@ -526,6 +527,7 @@ IndirectCallPromotion::findCallTargetSymbols(std::vector<Callsite> &Targets,
size_t &N, BinaryBasicBlock &BB,
MCInst &CallInst,
MCInst *&TargetFetchInst) const {
+ const BinaryContext &BC = BB.getFunction()->getBinaryContext();
const JumpTable *JT = BB.getFunction()->getJumpTable(CallInst);
SymTargetsType SymTargets;
@@ -556,8 +558,9 @@ IndirectCallPromotion::findCallTargetSymbols(std::vector<Callsite> &Targets,
if (!HotTargets.empty()) {
if (opts::Verbosity >= 1)
for (size_t I = 0; I < HotTargets.size(); ++I)
- outs() << "BOLT-INFO: HotTarget[" << I << "] = (" << HotTargets[I].first
- << ", " << HotTargets[I].second << ")\n";
+ BC.outs() << "BOLT-INFO: HotTarget[" << I << "] = ("
+ << HotTargets[I].first << ", " << HotTargets[I].second
+ << ")\n";
// Recompute hottest targets, now discriminating which index is hot
// NOTE: This is a tradeoff. On one hand, we get index information. On the
@@ -611,9 +614,9 @@ IndirectCallPromotion::findCallTargetSymbols(std::vector<Callsite> &Targets,
N = I;
if (N == 0 && opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: ICP failed in " << *BB.getFunction() << " in "
- << BB.getName() << ": failed to meet thresholds after memory "
- << "profile data was loaded.\n";
+ BC.outs() << "BOLT-INFO: ICP failed in " << *BB.getFunction() << " in "
+ << BB.getName() << ": failed to meet thresholds after memory "
+ << "profile data was loaded.\n";
return SymTargets;
}
}
@@ -974,9 +977,9 @@ size_t IndirectCallPromotion::canPromoteCallsite(
if (Targets.empty() || !NumCalls) {
if (opts::Verbosity >= 1) {
const ptrdiff_t InstIdx = &Inst - &(*BB.begin());
- outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx << " in "
- << BB.getName() << ", calls = " << NumCalls
- << ", targets empty or NumCalls == 0.\n";
+ BC.outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx
+ << " in " << BB.getName() << ", calls = " << NumCalls
+ << ", targets empty or NumCalls == 0.\n";
}
return 0;
}
@@ -1015,10 +1018,10 @@ size_t IndirectCallPromotion::canPromoteCallsite(
if (TopNFrequency == 0 || TopNFrequency < opts::ICPMispredictThreshold) {
if (opts::Verbosity >= 1) {
const ptrdiff_t InstIdx = &Inst - &(*BB.begin());
- outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx
- << " in " << BB.getName() << ", calls = " << NumCalls
- << ", top N mis. frequency " << format("%.1f", TopNFrequency)
- << "% < " << opts::ICPMispredictThreshold << "%\n";
+ BC.outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx
+ << " in " << BB.getName() << ", calls = " << NumCalls
+ << ", top N mis. frequency " << format("%.1f", TopNFrequency)
+ << "% < " << opts::ICPMispredictThreshold << "%\n";
}
return 0;
}
@@ -1061,11 +1064,11 @@ size_t IndirectCallPromotion::canPromoteCallsite(
if (TopNMispredictFrequency < opts::ICPMispredictThreshold) {
if (opts::Verbosity >= 1) {
const ptrdiff_t InstIdx = &Inst - &(*BB.begin());
- outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx
- << " in " << BB.getName() << ", calls = " << NumCalls
- << ", top N mispredict frequency "
- << format("%.1f", TopNMispredictFrequency) << "% < "
- << opts::ICPMispredictThreshold << "%\n";
+ BC.outs() << "BOLT-INFO: ICP failed in " << *BF << " @ " << InstIdx
+ << " in " << BB.getName() << ", calls = " << NumCalls
+ << ", top N mispredict frequency "
+ << format("%.1f", TopNMispredictFrequency) << "% < "
+ << opts::ICPMispredictThreshold << "%\n";
}
return 0;
}
@@ -1106,29 +1109,29 @@ void IndirectCallPromotion::printCallsiteInfo(
const bool IsJumpTable = BB.getFunction()->getJumpTable(Inst);
const ptrdiff_t InstIdx = &Inst - &(*BB.begin());
- outs() << "BOLT-INFO: ICP candidate branch info: " << *BB.getFunction()
- << " @ " << InstIdx << " in " << BB.getName()
- << " -> calls = " << NumCalls
- << (IsTailCall ? " (tail)" : (IsJumpTable ? " (jump table)" : ""))
- << "\n";
+ BC.outs() << "BOLT-INFO: ICP candidate branch info: " << *BB.getFunction()
+ << " @ " << InstIdx << " in " << BB.getName()
+ << " -> calls = " << NumCalls
+ << (IsTailCall ? " (tail)" : (IsJumpTable ? " (jump table)" : ""))
+ << "\n";
for (size_t I = 0; I < N; I++) {
const double Frequency = 100.0 * Targets[I].Branches / NumCalls;
const double MisFrequency = 100.0 * Targets[I].Mispreds / NumCalls;
- outs() << "BOLT-INFO: ";
+ BC.outs() << "BOLT-INFO: ";
if (Targets[I].To.Sym)
- outs() << Targets[I].To.Sym->getName();
+ BC.outs() << Targets[I].To.Sym->getName();
else
- outs() << Targets[I].To.Addr;
- outs() << ", calls = " << Targets[I].Branches
- << ", mispreds = " << Targets[I].Mispreds
- << ", taken freq = " << format("%.1f", Frequency) << "%"
- << ", mis. freq = " << format("%.1f", MisFrequency) << "%";
+ BC.outs() << Targets[I].To.Addr;
+ BC.outs() << ", calls = " << Targets[I].Branches
+ << ", mispreds = " << Targets[I].Mispreds
+ << ", taken freq = " << format("%.1f", Frequency) << "%"
+ << ", mis. freq = " << format("%.1f", MisFrequency) << "%";
bool First = true;
for (uint64_t JTIndex : Targets[I].JTIndices) {
- outs() << (First ? ", indices = " : ", ") << JTIndex;
+ BC.outs() << (First ? ", indices = " : ", ") << JTIndex;
First = false;
}
- outs() << "\n";
+ BC.outs() << "\n";
}
LLVM_DEBUG({
@@ -1137,9 +1140,9 @@ void IndirectCallPromotion::printCallsiteInfo(
});
}
-void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) {
+Error IndirectCallPromotion::runOnFunctions(BinaryContext &BC) {
if (opts::ICP == ICP_NONE)
- return;
+ return Error::success();
auto &BFs = BC.getBinaryFunctions();
@@ -1222,9 +1225,9 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) {
Functions.insert(std::get<2>(IC));
++Num;
}
- outs() << "BOLT-INFO: ICP Total indirect calls = " << TotalIndirectCalls
- << ", " << Num << " callsites cover " << opts::ICPTopCallsites
- << "% of all indirect calls\n";
+ BC.outs() << "BOLT-INFO: ICP Total indirect calls = " << TotalIndirectCalls
+ << ", " << Num << " callsites cover " << opts::ICPTopCallsites
+ << "% of all indirect calls\n";
}
for (BinaryFunction *FuncPtr : Functions) {
@@ -1301,11 +1304,11 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) {
Info.getLivenessAnalysis().getStateBefore(Inst);
if (!State || (State && (*State)[BC.MIB->getFlagsReg()])) {
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: ICP failed in " << Function << " @ "
- << InstIdx << " in " << BB->getName()
- << ", calls = " << NumCalls
- << (State ? ", cannot clobber flags reg.\n"
- : ", no liveness data available.\n");
+ BC.outs() << "BOLT-INFO: ICP failed in " << Function << " @ "
+ << InstIdx << " in " << BB->getName()
+ << ", calls = " << NumCalls
+ << (State ? ", cannot clobber flags reg.\n"
+ : ", no liveness data available.\n");
continue;
}
}
@@ -1341,11 +1344,11 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) {
if (SymTargets.size() < N) {
const size_t LastTarget = SymTargets.size();
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: ICP failed in " << Function << " @ "
- << InstIdx << " in " << BB->getName()
- << ", calls = " << NumCalls
- << ", ICP failed to find target symbol for "
- << Targets[LastTarget].To.Sym->getName() << "\n";
+ BC.outs() << "BOLT-INFO: ICP failed in " << Function << " @ "
+ << InstIdx << " in " << BB->getName()
+ << ", calls = " << NumCalls
+ << ", ICP failed to find target symbol for "
+ << Targets[LastTarget].To.Sym->getName() << "\n";
continue;
}
@@ -1374,10 +1377,10 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) {
if (ICPcode.empty()) {
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: ICP failed in " << Function << " @ "
- << InstIdx << " in " << BB->getName()
- << ", calls = " << NumCalls
- << ", unable to generate promoted call code.\n";
+ BC.outs() << "BOLT-INFO: ICP failed in " << Function << " @ "
+ << InstIdx << " in " << BB->getName()
+ << ", calls = " << NumCalls
+ << ", unable to generate promoted call code.\n";
continue;
}
@@ -1410,9 +1413,9 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) {
BBs.push_back(MergeBlock);
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: ICP succeeded in " << Function << " @ "
- << InstIdx << " in " << BB->getName()
- << " -> calls = " << NumCalls << "\n";
+ BC.outs() << "BOLT-INFO: ICP succeeded in " << Function << " @ "
+ << InstIdx << " in " << BB->getName()
+ << " -> calls = " << NumCalls << "\n";
if (IsJumpTable)
++TotalOptimizedJumpTableCallsites;
@@ -1426,52 +1429,54 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) {
TotalIndirectJmps += FuncTotalIndirectJmps;
}
- outs() << "BOLT-INFO: ICP total indirect callsites with profile = "
- << TotalIndirectCallsites << "\n"
- << "BOLT-INFO: ICP total jump table callsites = "
- << TotalJumpTableCallsites << "\n"
- << "BOLT-INFO: ICP total number of calls = " << TotalCalls << "\n"
- << "BOLT-INFO: ICP percentage of calls that are indirect = "
- << format("%.1f", (100.0 * TotalIndirectCalls) / TotalCalls) << "%\n"
- << "BOLT-INFO: ICP percentage of indirect calls that can be "
- "optimized = "
- << format("%.1f", (100.0 * TotalNumFrequentCalls) /
- std::max<size_t>(TotalIndirectCalls, 1))
- << "%\n"
- << "BOLT-INFO: ICP percentage of indirect callsites that are "
- "optimized = "
- << format("%.1f", (100.0 * TotalOptimizedIndirectCallsites) /
- std::max<uint64_t>(TotalIndirectCallsites, 1))
- << "%\n"
- << "BOLT-INFO: ICP number of method load elimination candidates = "
- << TotalMethodLoadEliminationCandidates << "\n"
- << "BOLT-INFO: ICP percentage of method calls candidates that have "
- "loads eliminated = "
- << format("%.1f", (100.0 * TotalMethodLoadsEliminated) /
- std::max<uint64_t>(
- TotalMethodLoadEliminationCandidates, 1))
- << "%\n"
- << "BOLT-INFO: ICP percentage of indirect branches that are "
- "optimized = "
- << format("%.1f", (100.0 * TotalNumFrequentJmps) /
- std::max<uint64_t>(TotalIndirectJmps, 1))
- << "%\n"
- << "BOLT-INFO: ICP percentage of jump table callsites that are "
- << "optimized = "
- << format("%.1f", (100.0 * TotalOptimizedJumpTableCallsites) /
- std::max<uint64_t>(TotalJumpTableCallsites, 1))
- << "%\n"
- << "BOLT-INFO: ICP number of jump table callsites that can use hot "
- << "indices = " << TotalIndexBasedCandidates << "\n"
- << "BOLT-INFO: ICP percentage of jump table callsites that use hot "
- "indices = "
- << format("%.1f", (100.0 * TotalIndexBasedJumps) /
- std::max<uint64_t>(TotalIndexBasedCandidates, 1))
- << "%\n";
+ BC.outs()
+ << "BOLT-INFO: ICP total indirect callsites with profile = "
+ << TotalIndirectCallsites << "\n"
+ << "BOLT-INFO: ICP total jump table callsites = "
+ << TotalJumpTableCallsites << "\n"
+ << "BOLT-INFO: ICP total number of calls = " << TotalCalls << "\n"
+ << "BOLT-INFO: ICP percentage of calls that are indirect = "
+ << format("%.1f", (100.0 * TotalIndirectCalls) / TotalCalls) << "%\n"
+ << "BOLT-INFO: ICP percentage of indirect calls that can be "
+ "optimized = "
+ << format("%.1f", (100.0 * TotalNumFrequentCalls) /
+ std::max<size_t>(TotalIndirectCalls, 1))
+ << "%\n"
+ << "BOLT-INFO: ICP percentage of indirect callsites that are "
+ "optimized = "
+ << format("%.1f", (100.0 * TotalOptimizedIndirectCallsites) /
+ std::max<uint64_t>(TotalIndirectCallsites, 1))
+ << "%\n"
+ << "BOLT-INFO: ICP number of method load elimination candidates = "
+ << TotalMethodLoadEliminationCandidates << "\n"
+ << "BOLT-INFO: ICP percentage of method calls candidates that have "
+ "loads eliminated = "
+ << format("%.1f",
+ (100.0 * TotalMethodLoadsEliminated) /
+ std::max<uint64_t>(TotalMethodLoadEliminationCandidates, 1))
+ << "%\n"
+ << "BOLT-INFO: ICP percentage of indirect branches that are "
+ "optimized = "
+ << format("%.1f", (100.0 * TotalNumFrequentJmps) /
+ std::max<uint64_t>(TotalIndirectJmps, 1))
+ << "%\n"
+ << "BOLT-INFO: ICP percentage of jump table callsites that are "
+ << "optimized = "
+ << format("%.1f", (100.0 * TotalOptimizedJumpTableCallsites) /
+ std::max<uint64_t>(TotalJumpTableCallsites, 1))
+ << "%\n"
+ << "BOLT-INFO: ICP number of jump table callsites that can use hot "
+ << "indices = " << TotalIndexBasedCandidates << "\n"
+ << "BOLT-INFO: ICP percentage of jump table callsites that use hot "
+ "indices = "
+ << format("%.1f", (100.0 * TotalIndexBasedJumps) /
+ std::max<uint64_t>(TotalIndexBasedCandidates, 1))
+ << "%\n";
#ifndef NDEBUG
verifyProfile(BFs);
#endif
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/Inliner.cpp b/bolt/lib/Passes/Inliner.cpp
index 8dcb8934f2d2..a3b2017aa32a 100644
--- a/bolt/lib/Passes/Inliner.cpp
+++ b/bolt/lib/Passes/Inliner.cpp
@@ -496,11 +496,11 @@ bool Inliner::inlineCallsInFunction(BinaryFunction &Function) {
return DidInlining;
}
-void Inliner::runOnFunctions(BinaryContext &BC) {
+Error Inliner::runOnFunctions(BinaryContext &BC) {
opts::syncOptions();
if (!opts::inliningEnabled())
- return;
+ return Error::success();
bool InlinedOnce;
unsigned NumIters = 0;
@@ -540,10 +540,11 @@ void Inliner::runOnFunctions(BinaryContext &BC) {
} while (InlinedOnce && NumIters < opts::InlineMaxIters);
if (NumInlinedCallSites)
- outs() << "BOLT-INFO: inlined " << NumInlinedDynamicCalls << " calls at "
- << NumInlinedCallSites << " call sites in " << NumIters
- << " iteration(s). Change in binary size: " << TotalInlinedBytes
- << " bytes.\n";
+ BC.outs() << "BOLT-INFO: inlined " << NumInlinedDynamicCalls << " calls at "
+ << NumInlinedCallSites << " call sites in " << NumIters
+ << " iteration(s). Change in binary size: " << TotalInlinedBytes
+ << " bytes.\n";
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/Instrumentation.cpp b/bolt/lib/Passes/Instrumentation.cpp
index e54b0cacc4ca..760ca84b4ef1 100644
--- a/bolt/lib/Passes/Instrumentation.cpp
+++ b/bolt/lib/Passes/Instrumentation.cpp
@@ -96,8 +96,8 @@ static bool hasAArch64ExclusiveMemop(BinaryFunction &Function) {
for (const MCInst &Inst : BB)
if (BC.MIB->isAArch64Exclusive(Inst)) {
if (opts::Verbosity >= 1)
- outs() << "BOLT-INSTRUMENTER: Function " << Function
- << " has exclusive instructions, skip instrumentation\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Function " << Function
+ << " has exclusive instructions, skip instrumentation\n";
return true;
}
@@ -526,7 +526,7 @@ void Instrumentation::instrumentFunction(BinaryFunction &Function,
FuncDesc->EdgesSet.clear();
}
-void Instrumentation::runOnFunctions(BinaryContext &BC) {
+Error Instrumentation::runOnFunctions(BinaryContext &BC) {
const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/false,
/*IsText=*/false,
/*IsAllocatable=*/true);
@@ -567,17 +567,16 @@ void Instrumentation::runOnFunctions(BinaryContext &BC) {
ErrorOr<BinarySection &> SetupSection =
BC.getUniqueSectionByName("I__setup");
- if (!SetupSection) {
- llvm::errs() << "Cannot find I__setup section\n";
- exit(1);
- }
+ if (!SetupSection)
+ return createFatalBOLTError("Cannot find I__setup section\n");
+
MCSymbol *Target = BC.registerNameAtAddress(
"__bolt_instr_setup", SetupSection->getAddress(), 0, 0);
MCInst NewInst;
BC.MIB->createCall(NewInst, Target, BC.Ctx.get());
BB.insertInstruction(BB.begin(), std::move(NewInst));
} else {
- llvm::errs() << "BOLT-WARNING: Entry point not found\n";
+ BC.errs() << "BOLT-WARNING: Entry point not found\n";
}
if (BinaryData *BD = BC.getBinaryDataByName("___GLOBAL_init_65535/1")) {
@@ -586,10 +585,9 @@ void Instrumentation::runOnFunctions(BinaryContext &BC) {
BinaryBasicBlock &BB = Ctor->front();
ErrorOr<BinarySection &> FiniSection =
BC.getUniqueSectionByName("I__fini");
- if (!FiniSection) {
- llvm::errs() << "Cannot find I__fini section\n";
- exit(1);
- }
+ if (!FiniSection)
+ return createFatalBOLTError("Cannot find I__fini section");
+
MCSymbol *Target = BC.registerNameAtAddress(
"__bolt_instr_fini", FiniSection->getAddress(), 0, 0);
auto IsLEA = [&BC](const MCInst &Inst) { return BC.MIB->isLEA64r(Inst); };
@@ -598,11 +596,12 @@ void Instrumentation::runOnFunctions(BinaryContext &BC) {
LEA->getOperand(4).setExpr(
MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *BC.Ctx));
} else {
- llvm::errs() << "BOLT-WARNING: ___GLOBAL_init_65535 not found\n";
+ BC.errs() << "BOLT-WARNING: ___GLOBAL_init_65535 not found\n";
}
}
setupRuntimeLibrary(BC);
+ return Error::success();
}
void Instrumentation::createAuxiliaryFunctions(BinaryContext &BC) {
@@ -688,32 +687,34 @@ void Instrumentation::createAuxiliaryFunctions(BinaryContext &BC) {
void Instrumentation::setupRuntimeLibrary(BinaryContext &BC) {
uint32_t FuncDescSize = Summary->getFDSize();
- outs() << "BOLT-INSTRUMENTER: Number of indirect call site descriptors: "
- << Summary->IndCallDescriptions.size() << "\n";
- outs() << "BOLT-INSTRUMENTER: Number of indirect call target descriptors: "
- << Summary->IndCallTargetDescriptions.size() << "\n";
- outs() << "BOLT-INSTRUMENTER: Number of function descriptors: "
- << Summary->FunctionDescriptions.size() << "\n";
- outs() << "BOLT-INSTRUMENTER: Number of branch counters: " << BranchCounters
- << "\n";
- outs() << "BOLT-INSTRUMENTER: Number of ST leaf node counters: "
- << LeafNodeCounters << "\n";
- outs() << "BOLT-INSTRUMENTER: Number of direct call counters: "
- << DirectCallCounters << "\n";
- outs() << "BOLT-INSTRUMENTER: Total number of counters: "
- << Summary->Counters.size() << "\n";
- outs() << "BOLT-INSTRUMENTER: Total size of counters: "
- << (Summary->Counters.size() * 8) << " bytes (static alloc memory)\n";
- outs() << "BOLT-INSTRUMENTER: Total size of string table emitted: "
- << Summary->StringTable.size() << " bytes in file\n";
- outs() << "BOLT-INSTRUMENTER: Total size of descriptors: "
- << (FuncDescSize +
- Summary->IndCallDescriptions.size() * sizeof(IndCallDescription) +
- Summary->IndCallTargetDescriptions.size() *
- sizeof(IndCallTargetDescription))
- << " bytes in file\n";
- outs() << "BOLT-INSTRUMENTER: Profile will be saved to file "
- << opts::InstrumentationFilename << "\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Number of indirect call site descriptors: "
+ << Summary->IndCallDescriptions.size() << "\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Number of indirect call target descriptors: "
+ << Summary->IndCallTargetDescriptions.size() << "\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Number of function descriptors: "
+ << Summary->FunctionDescriptions.size() << "\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Number of branch counters: "
+ << BranchCounters << "\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Number of ST leaf node counters: "
+ << LeafNodeCounters << "\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Number of direct call counters: "
+ << DirectCallCounters << "\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Total number of counters: "
+ << Summary->Counters.size() << "\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Total size of counters: "
+ << (Summary->Counters.size() * 8)
+ << " bytes (static alloc memory)\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Total size of string table emitted: "
+ << Summary->StringTable.size() << " bytes in file\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Total size of descriptors: "
+ << (FuncDescSize +
+ Summary->IndCallDescriptions.size() *
+ sizeof(IndCallDescription) +
+ Summary->IndCallTargetDescriptions.size() *
+ sizeof(IndCallTargetDescription))
+ << " bytes in file\n";
+ BC.outs() << "BOLT-INSTRUMENTER: Profile will be saved to file "
+ << opts::InstrumentationFilename << "\n";
InstrumentationRuntimeLibrary *RtLibrary =
static_cast<InstrumentationRuntimeLibrary *>(BC.getRuntimeLibrary());
diff --git a/bolt/lib/Passes/JTFootprintReduction.cpp b/bolt/lib/Passes/JTFootprintReduction.cpp
index d690e4d0c003..fd291f96004d 100644
--- a/bolt/lib/Passes/JTFootprintReduction.cpp
+++ b/bolt/lib/Passes/JTFootprintReduction.cpp
@@ -246,9 +246,9 @@ void JTFootprintReduction::optimizeFunction(BinaryFunction &Function,
++I;
}
-void JTFootprintReduction::runOnFunctions(BinaryContext &BC) {
+Error JTFootprintReduction::runOnFunctions(BinaryContext &BC) {
if (opts::JumpTables == JTS_BASIC && BC.HasRelocations)
- return;
+ return Error::success();
std::unique_ptr<RegAnalysis> RA;
std::unique_ptr<BinaryFunctionCallGraph> CG;
@@ -272,23 +272,24 @@ void JTFootprintReduction::runOnFunctions(BinaryContext &BC) {
}
if (TotalJTs == TotalJTsDenied) {
- outs() << "BOLT-INFO: JT Footprint reduction: no changes were made.\n";
- return;
+ BC.outs() << "BOLT-INFO: JT Footprint reduction: no changes were made.\n";
+ return Error::success();
}
- outs() << "BOLT-INFO: JT Footprint reduction stats (simple funcs only):\n";
+ BC.outs() << "BOLT-INFO: JT Footprint reduction stats (simple funcs only):\n";
if (OptimizedScore)
- outs() << format("\t %.2lf%%", (OptimizedScore * 100.0 / TotalJTScore))
- << " of dynamic JT entries were reduced.\n";
- outs() << "\t " << TotalJTs - TotalJTsDenied << " of " << TotalJTs
- << " jump tables affected.\n";
- outs() << "\t " << IndJmps - IndJmpsDenied << " of " << IndJmps
- << " indirect jumps to JTs affected.\n";
- outs() << "\t " << NumJTsBadMatch
- << " JTs discarded due to unsupported jump pattern.\n";
- outs() << "\t " << NumJTsNoReg
- << " JTs discarded due to register unavailability.\n";
- outs() << "\t " << BytesSaved << " bytes saved.\n";
+ BC.outs() << format("\t %.2lf%%", (OptimizedScore * 100.0 / TotalJTScore))
+ << " of dynamic JT entries were reduced.\n";
+ BC.outs() << "\t " << TotalJTs - TotalJTsDenied << " of " << TotalJTs
+ << " jump tables affected.\n";
+ BC.outs() << "\t " << IndJmps - IndJmpsDenied << " of " << IndJmps
+ << " indirect jumps to JTs affected.\n";
+ BC.outs() << "\t " << NumJTsBadMatch
+ << " JTs discarded due to unsupported jump pattern.\n";
+ BC.outs() << "\t " << NumJTsNoReg
+ << " JTs discarded due to register unavailability.\n";
+ BC.outs() << "\t " << BytesSaved << " bytes saved.\n";
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/LongJmp.cpp b/bolt/lib/Passes/LongJmp.cpp
index ded0db2cd30b..c483f70a836e 100644
--- a/bolt/lib/Passes/LongJmp.cpp
+++ b/bolt/lib/Passes/LongJmp.cpp
@@ -459,13 +459,13 @@ uint64_t LongJmpPass::getSymbolAddress(const BinaryContext &BC,
return Iter->second;
}
-bool LongJmpPass::relaxStub(BinaryBasicBlock &StubBB) {
+Error LongJmpPass::relaxStub(BinaryBasicBlock &StubBB, bool &Modified) {
const BinaryFunction &Func = *StubBB.getFunction();
const BinaryContext &BC = Func.getBinaryContext();
const int Bits = StubBits[&StubBB];
// Already working with the largest range?
if (Bits == static_cast<int>(BC.AsmInfo->getCodePointerSize() * 8))
- return false;
+ return Error::success();
const static int RangeShortJmp = BC.MIB->getShortJmpEncodingSize();
const static int RangeSingleInstr = BC.MIB->getUncondBranchEncodingSize();
@@ -481,12 +481,12 @@ bool LongJmpPass::relaxStub(BinaryBasicBlock &StubBB) {
: TgtAddress - DotAddress;
// If it fits in one instruction, do not relax
if (!(PCRelTgtAddress & SingleInstrMask))
- return false;
+ return Error::success();
// Fits short jmp
if (!(PCRelTgtAddress & ShortJmpMask)) {
if (Bits >= RangeShortJmp)
- return false;
+ return Error::success();
LLVM_DEBUG(dbgs() << "Relaxing stub to short jump. PCRelTgtAddress = "
<< Twine::utohexstr(PCRelTgtAddress)
@@ -494,22 +494,23 @@ bool LongJmpPass::relaxStub(BinaryBasicBlock &StubBB) {
<< "\n");
relaxStubToShortJmp(StubBB, RealTargetSym);
StubBits[&StubBB] = RangeShortJmp;
- return true;
+ Modified = true;
+ return Error::success();
}
// The long jmp uses absolute address on AArch64
// So we could not use it for PIC binaries
- if (BC.isAArch64() && !BC.HasFixedLoadAddress) {
- errs() << "BOLT-ERROR: Unable to relax stub for PIC binary\n";
- exit(1);
- }
+ if (BC.isAArch64() && !BC.HasFixedLoadAddress)
+ return createFatalBOLTError(
+ "BOLT-ERROR: Unable to relax stub for PIC binary\n");
LLVM_DEBUG(dbgs() << "Relaxing stub to long jump. PCRelTgtAddress = "
<< Twine::utohexstr(PCRelTgtAddress)
<< " RealTargetSym = " << RealTargetSym->getName() << "\n");
relaxStubToLongJmp(StubBB, RealTargetSym);
StubBits[&StubBB] = static_cast<int>(BC.AsmInfo->getCodePointerSize() * 8);
- return true;
+ Modified = true;
+ return Error::success();
}
bool LongJmpPass::needsStub(const BinaryBasicBlock &BB, const MCInst &Inst,
@@ -539,9 +540,8 @@ bool LongJmpPass::needsStub(const BinaryBasicBlock &BB, const MCInst &Inst,
return PCOffset < MinVal || PCOffset > MaxVal;
}
-bool LongJmpPass::relax(BinaryFunction &Func) {
+Error LongJmpPass::relax(BinaryFunction &Func, bool &Modified) {
const BinaryContext &BC = Func.getBinaryContext();
- bool Modified = false;
assert(BC.isAArch64() && "Unsupported arch");
constexpr int InsnSize = 4; // AArch64
@@ -613,7 +613,8 @@ bool LongJmpPass::relax(BinaryFunction &Func) {
if (!Stubs[&Func].count(&BB) || !BB.isValid())
continue;
- Modified |= relaxStub(BB);
+ if (auto E = relaxStub(BB, Modified))
+ return Error(std::move(E));
}
for (std::pair<BinaryBasicBlock *, std::unique_ptr<BinaryBasicBlock>> &Elmt :
@@ -625,11 +626,11 @@ bool LongJmpPass::relax(BinaryFunction &Func) {
Func.insertBasicBlocks(Elmt.first, std::move(NewBBs), true);
}
- return Modified;
+ return Error::success();
}
-void LongJmpPass::runOnFunctions(BinaryContext &BC) {
- outs() << "BOLT-INFO: Starting stub-insertion pass\n";
+Error LongJmpPass::runOnFunctions(BinaryContext &BC) {
+ BC.outs() << "BOLT-INFO: Starting stub-insertion pass\n";
std::vector<BinaryFunction *> Sorted = BC.getSortedFunctions();
bool Modified;
uint32_t Iterations = 0;
@@ -639,19 +640,19 @@ void LongJmpPass::runOnFunctions(BinaryContext &BC) {
tentativeLayout(BC, Sorted);
updateStubGroups();
for (BinaryFunction *Func : Sorted) {
- if (relax(*Func)) {
- // Don't ruin non-simple functions, they can't afford to have the layout
- // changed.
- if (Func->isSimple())
- Func->fixBranches();
- Modified = true;
- }
+ if (auto E = relax(*Func, Modified))
+ return Error(std::move(E));
+ // Don't ruin non-simple functions, they can't afford to have the layout
+ // changed.
+ if (Modified && Func->isSimple())
+ Func->fixBranches();
}
} while (Modified);
- outs() << "BOLT-INFO: Inserted " << NumHotStubs
- << " stubs in the hot area and " << NumColdStubs
- << " stubs in the cold area. Shared " << NumSharedStubs
- << " times, iterated " << Iterations << " times.\n";
+ BC.outs() << "BOLT-INFO: Inserted " << NumHotStubs
+ << " stubs in the hot area and " << NumColdStubs
+ << " stubs in the cold area. Shared " << NumSharedStubs
+ << " times, iterated " << Iterations << " times.\n";
+ return Error::success();
}
} // namespace bolt
} // namespace llvm
diff --git a/bolt/lib/Passes/LoopInversionPass.cpp b/bolt/lib/Passes/LoopInversionPass.cpp
index f30e1a8f7450..250a971d204c 100644
--- a/bolt/lib/Passes/LoopInversionPass.cpp
+++ b/bolt/lib/Passes/LoopInversionPass.cpp
@@ -84,11 +84,11 @@ bool LoopInversionPass::runOnFunction(BinaryFunction &BF) {
return IsChanged;
}
-void LoopInversionPass::runOnFunctions(BinaryContext &BC) {
+Error LoopInversionPass::runOnFunctions(BinaryContext &BC) {
std::atomic<uint64_t> ModifiedFuncCount{0};
if (opts::ReorderBlocks == ReorderBasicBlocks::LT_NONE ||
opts::LoopReorder == false)
- return;
+ return Error::success();
ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
if (runOnFunction(BF))
@@ -103,8 +103,9 @@ void LoopInversionPass::runOnFunctions(BinaryContext &BC) {
BC, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL, WorkFun, SkipFunc,
"LoopInversionPass");
- outs() << "BOLT-INFO: " << ModifiedFuncCount
- << " Functions were reordered by LoopInversionPass\n";
+ BC.outs() << "BOLT-INFO: " << ModifiedFuncCount
+ << " Functions were reordered by LoopInversionPass\n";
+ return Error::success();
}
} // end namespace bolt
diff --git a/bolt/lib/Passes/PLTCall.cpp b/bolt/lib/Passes/PLTCall.cpp
index aec75be84bfa..d0276f22e14e 100644
--- a/bolt/lib/Passes/PLTCall.cpp
+++ b/bolt/lib/Passes/PLTCall.cpp
@@ -43,9 +43,9 @@ PLT("plt",
namespace llvm {
namespace bolt {
-void PLTCall::runOnFunctions(BinaryContext &BC) {
+Error PLTCall::runOnFunctions(BinaryContext &BC) {
if (opts::PLT == OT_NONE)
- return;
+ return Error::success();
uint64_t NumCallsOptimized = 0;
for (auto &It : BC.getBinaryFunctions()) {
@@ -80,9 +80,10 @@ void PLTCall::runOnFunctions(BinaryContext &BC) {
if (NumCallsOptimized) {
BC.RequiresZNow = true;
- outs() << "BOLT-INFO: " << NumCallsOptimized
- << " PLT calls in the binary were optimized.\n";
+ BC.outs() << "BOLT-INFO: " << NumCallsOptimized
+ << " PLT calls in the binary were optimized.\n";
}
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/PatchEntries.cpp b/bolt/lib/Passes/PatchEntries.cpp
index ee7512d89962..981d1b70af90 100644
--- a/bolt/lib/Passes/PatchEntries.cpp
+++ b/bolt/lib/Passes/PatchEntries.cpp
@@ -31,7 +31,7 @@ llvm::cl::opt<bool>
namespace llvm {
namespace bolt {
-void PatchEntries::runOnFunctions(BinaryContext &BC) {
+Error PatchEntries::runOnFunctions(BinaryContext &BC) {
if (!opts::ForcePatch) {
// Mark the binary for patching if we did not create external references
// for original code in any of functions we are not going to emit.
@@ -42,11 +42,11 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) {
});
if (!NeedsPatching)
- return;
+ return Error::success();
}
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: patching entries in original code\n";
+ BC.outs() << "BOLT-INFO: patching entries in original code\n";
// Calculate the size of the patch.
static size_t PatchSize = 0;
@@ -78,8 +78,8 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) {
const MCSymbol *Symbol) {
if (Offset < NextValidByte) {
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: unable to patch entry point in " << Function
- << " at offset 0x" << Twine::utohexstr(Offset) << '\n';
+ BC.outs() << "BOLT-INFO: unable to patch entry point in " << Function
+ << " at offset 0x" << Twine::utohexstr(Offset) << '\n';
return false;
}
@@ -89,8 +89,8 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) {
NextValidByte = Offset + PatchSize;
if (NextValidByte > Function.getMaxSize()) {
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: function " << Function
- << " too small to patch its entry point\n";
+ BC.outs() << "BOLT-INFO: function " << Function
+ << " too small to patch its entry point\n";
return false;
}
@@ -101,9 +101,9 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) {
// We can't change output layout for AArch64 due to LongJmp pass
if (BC.isAArch64()) {
if (opts::ForcePatch) {
- errs() << "BOLT-ERROR: unable to patch entries in " << Function
- << "\n";
- exit(1);
+ BC.errs() << "BOLT-ERROR: unable to patch entries in " << Function
+ << "\n";
+ return createFatalBOLTError("");
}
continue;
@@ -111,8 +111,8 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) {
// If the original function entries cannot be patched, then we cannot
// safely emit new function body.
- errs() << "BOLT-WARNING: failed to patch entries in " << Function
- << ". The function will not be optimized.\n";
+ BC.errs() << "BOLT-WARNING: failed to patch entries in " << Function
+ << ". The function will not be optimized.\n";
Function.setIgnored();
continue;
}
@@ -138,6 +138,7 @@ void PatchEntries::runOnFunctions(BinaryContext &BC) {
Function.setIsPatched(true);
}
+ return Error::success();
}
} // end namespace bolt
diff --git a/bolt/lib/Passes/RegAnalysis.cpp b/bolt/lib/Passes/RegAnalysis.cpp
index eab16cb09032..9054385c20b5 100644
--- a/bolt/lib/Passes/RegAnalysis.cpp
+++ b/bolt/lib/Passes/RegAnalysis.cpp
@@ -232,11 +232,11 @@ BitVector RegAnalysis::getFunctionClobberList(const BinaryFunction *Func) {
}
void RegAnalysis::printStats() {
- outs() << "BOLT-INFO REG ANALYSIS: Number of functions conservatively "
- "treated as clobbering all registers: "
- << NumFunctionsAllClobber
- << format(" (%.1lf%% dyn cov)\n",
- (100.0 * CountFunctionsAllClobber / CountDenominator));
+ BC.outs() << "BOLT-INFO REG ANALYSIS: Number of functions conservatively "
+ "treated as clobbering all registers: "
+ << NumFunctionsAllClobber
+ << format(" (%.1lf%% dyn cov)\n",
+ (100.0 * CountFunctionsAllClobber / CountDenominator));
}
} // namespace bolt
diff --git a/bolt/lib/Passes/RegReAssign.cpp b/bolt/lib/Passes/RegReAssign.cpp
index 8b9dc9c1fdd5..0becfb4a06a3 100644
--- a/bolt/lib/Passes/RegReAssign.cpp
+++ b/bolt/lib/Passes/RegReAssign.cpp
@@ -452,7 +452,7 @@ void RegReAssign::setupConservativePass(
});
}
-void RegReAssign::runOnFunctions(BinaryContext &BC) {
+Error RegReAssign::runOnFunctions(BinaryContext &BC) {
RegScore = std::vector<int64_t>(BC.MRI->getNumRegs(), 0);
RankedRegs = std::vector<size_t>(BC.MRI->getNumRegs(), 0);
@@ -480,18 +480,20 @@ void RegReAssign::runOnFunctions(BinaryContext &BC) {
}
if (FuncsChanged.empty()) {
- outs() << "BOLT-INFO: Reg Reassignment Pass: no changes were made.\n";
- return;
+ BC.outs() << "BOLT-INFO: Reg Reassignment Pass: no changes were made.\n";
+ return Error::success();
}
if (opts::UpdateDebugSections)
- outs() << "BOLT-WARNING: You used -reg-reassign and -update-debug-sections."
- << " Some registers were changed but associated AT_LOCATION for "
- << "impacted variables were NOT updated! This operation is "
- << "currently unsupported by BOLT.\n";
- outs() << "BOLT-INFO: Reg Reassignment Pass Stats:\n";
- outs() << "\t " << FuncsChanged.size() << " functions affected.\n";
- outs() << "\t " << StaticBytesSaved << " static bytes saved.\n";
- outs() << "\t " << DynBytesSaved << " dynamic bytes saved.\n";
+ BC.outs()
+ << "BOLT-WARNING: You used -reg-reassign and -update-debug-sections."
+ << " Some registers were changed but associated AT_LOCATION for "
+ << "impacted variables were NOT updated! This operation is "
+ << "currently unsupported by BOLT.\n";
+ BC.outs() << "BOLT-INFO: Reg Reassignment Pass Stats:\n";
+ BC.outs() << "\t " << FuncsChanged.size() << " functions affected.\n";
+ BC.outs() << "\t " << StaticBytesSaved << " static bytes saved.\n";
+ BC.outs() << "\t " << DynBytesSaved << " dynamic bytes saved.\n";
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/ReorderData.cpp b/bolt/lib/Passes/ReorderData.cpp
index 3a6654cf1e0b..2b04361c9463 100644
--- a/bolt/lib/Passes/ReorderData.cpp
+++ b/bolt/lib/Passes/ReorderData.cpp
@@ -133,7 +133,7 @@ bool filterSymbol(const BinaryData *BD) {
using DataOrder = ReorderData::DataOrder;
-void ReorderData::printOrder(const BinarySection &Section,
+void ReorderData::printOrder(BinaryContext &BC, const BinarySection &Section,
DataOrder::const_iterator Begin,
DataOrder::const_iterator End) const {
uint64_t TotalSize = 0;
@@ -142,19 +142,20 @@ void ReorderData::printOrder(const BinarySection &Section,
const BinaryData *BD = Begin->first;
if (!PrintHeader) {
- outs() << "BOLT-INFO: Hot global symbols for " << Section.getName()
- << ":\n";
+ BC.outs() << "BOLT-INFO: Hot global symbols for " << Section.getName()
+ << ":\n";
PrintHeader = true;
}
- outs() << "BOLT-INFO: " << *BD << ", moveable=" << BD->isMoveable()
- << format(", weight=%.5f\n", double(Begin->second) / BD->getSize());
+ BC.outs() << "BOLT-INFO: " << *BD << ", moveable=" << BD->isMoveable()
+ << format(", weight=%.5f\n",
+ double(Begin->second) / BD->getSize());
TotalSize += BD->getSize();
++Begin;
}
if (TotalSize)
- outs() << "BOLT-INFO: Total hot symbol size = " << TotalSize << "\n";
+ BC.outs() << "BOLT-INFO: Total hot symbol size = " << TotalSize << "\n";
}
DataOrder ReorderData::baseOrder(BinaryContext &BC,
@@ -208,19 +209,19 @@ void ReorderData::assignMemData(BinaryContext &BC) {
}
if (!Counts.empty()) {
- outs() << "BOLT-INFO: Memory stats breakdown:\n";
+ BC.outs() << "BOLT-INFO: Memory stats breakdown:\n";
for (const auto &KV : Counts) {
StringRef Section = KV.first;
const uint64_t Count = KV.second;
- outs() << "BOLT-INFO: " << Section << " = " << Count
- << format(" (%.1f%%)\n", 100.0 * Count / TotalCount);
+ BC.outs() << "BOLT-INFO: " << Section << " = " << Count
+ << format(" (%.1f%%)\n", 100.0 * Count / TotalCount);
if (JumpTableCounts.count(Section) != 0) {
const uint64_t JTCount = JumpTableCounts[Section];
- outs() << "BOLT-INFO: jump tables = " << JTCount
- << format(" (%.1f%%)\n", 100.0 * JTCount / Count);
+ BC.outs() << "BOLT-INFO: jump tables = " << JTCount
+ << format(" (%.1f%%)\n", 100.0 * JTCount / Count);
}
}
- outs() << "BOLT-INFO: Total memory events: " << TotalCount << "\n";
+ BC.outs() << "BOLT-INFO: Total memory events: " << TotalCount << "\n";
}
}
@@ -395,9 +396,9 @@ void ReorderData::setSectionOrder(BinaryContext &BC,
OutputSection.reorderContents(NewOrder, opts::ReorderInplace);
- outs() << "BOLT-INFO: reorder-data: " << Count << "/" << TotalCount
- << format(" (%.1f%%)", 100.0 * Count / TotalCount) << " events, "
- << Offset << " hot bytes\n";
+ BC.outs() << "BOLT-INFO: reorder-data: " << Count << "/" << TotalCount
+ << format(" (%.1f%%)", 100.0 * Count / TotalCount) << " events, "
+ << Offset << " hot bytes\n";
}
bool ReorderData::markUnmoveableSymbols(BinaryContext &BC,
@@ -435,17 +436,17 @@ bool ReorderData::markUnmoveableSymbols(BinaryContext &BC,
return FoundUnmoveable;
}
-void ReorderData::runOnFunctions(BinaryContext &BC) {
+Error ReorderData::runOnFunctions(BinaryContext &BC) {
static const char *DefaultSections[] = {".rodata", ".data", ".bss", nullptr};
if (!BC.HasRelocations || opts::ReorderData.empty())
- return;
+ return Error::success();
// For now
if (opts::JumpTables > JTS_BASIC) {
- outs() << "BOLT-WARNING: jump table support must be basic for "
- << "data reordering to work.\n";
- return;
+ BC.outs() << "BOLT-WARNING: jump table support must be basic for "
+ << "data reordering to work.\n";
+ return Error::success();
}
assignMemData(BC);
@@ -463,14 +464,14 @@ void ReorderData::runOnFunctions(BinaryContext &BC) {
ErrorOr<BinarySection &> Section = BC.getUniqueSectionByName(SectionName);
if (!Section) {
- outs() << "BOLT-WARNING: Section " << SectionName
- << " not found, skipping.\n";
+ BC.outs() << "BOLT-WARNING: Section " << SectionName
+ << " not found, skipping.\n";
continue;
}
if (!isSupported(*Section)) {
- outs() << "BOLT-ERROR: Section " << SectionName << " not supported.\n";
- exit(1);
+ BC.errs() << "BOLT-ERROR: Section " << SectionName << " not supported.\n";
+ return createFatalBOLTError("");
}
Sections.push_back(&*Section);
@@ -483,23 +484,23 @@ void ReorderData::runOnFunctions(BinaryContext &BC) {
unsigned SplitPointIdx;
if (opts::ReorderAlgorithm == opts::ReorderAlgo::REORDER_COUNT) {
- outs() << "BOLT-INFO: reorder-sections: ordering data by count\n";
+ BC.outs() << "BOLT-INFO: reorder-sections: ordering data by count\n";
std::tie(Order, SplitPointIdx) = sortedByCount(BC, *Section);
} else {
- outs() << "BOLT-INFO: reorder-sections: ordering data by funcs\n";
+ BC.outs() << "BOLT-INFO: reorder-sections: ordering data by funcs\n";
std::tie(Order, SplitPointIdx) =
sortedByFunc(BC, *Section, BC.getBinaryFunctions());
}
auto SplitPoint = Order.begin() + SplitPointIdx;
if (opts::PrintReorderedData)
- printOrder(*Section, Order.begin(), SplitPoint);
+ printOrder(BC, *Section, Order.begin(), SplitPoint);
if (!opts::ReorderInplace || FoundUnmoveable) {
if (opts::ReorderInplace && FoundUnmoveable)
- outs() << "BOLT-INFO: Found unmoveable symbols in "
- << Section->getName() << " falling back to splitting "
- << "instead of in-place reordering.\n";
+ BC.outs() << "BOLT-INFO: Found unmoveable symbols in "
+ << Section->getName() << " falling back to splitting "
+ << "instead of in-place reordering.\n";
// Rename sections.
BinarySection &Hot =
@@ -519,10 +520,12 @@ void ReorderData::runOnFunctions(BinaryContext &BC) {
}
}
} else {
- outs() << "BOLT-WARNING: Inplace section reordering not supported yet.\n";
+ BC.outs()
+ << "BOLT-WARNING: Inplace section reordering not supported yet.\n";
setSectionOrder(BC, *Section, Order.begin(), Order.end());
}
}
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/ReorderFunctions.cpp b/bolt/lib/Passes/ReorderFunctions.cpp
index 2446524c1ab4..c2d540135bda 100644
--- a/bolt/lib/Passes/ReorderFunctions.cpp
+++ b/bolt/lib/Passes/ReorderFunctions.cpp
@@ -114,7 +114,8 @@ using NodeId = CallGraph::NodeId;
using Arc = CallGraph::Arc;
using Node = CallGraph::Node;
-void ReorderFunctions::reorder(std::vector<Cluster> &&Clusters,
+void ReorderFunctions::reorder(BinaryContext &BC,
+ std::vector<Cluster> &&Clusters,
std::map<uint64_t, BinaryFunction> &BFs) {
std::vector<uint64_t> FuncAddr(Cg.numNodes()); // Just for computing stats
uint64_t TotalSize = 0;
@@ -139,10 +140,11 @@ void ReorderFunctions::reorder(std::vector<Cluster> &&Clusters,
if (opts::ReorderFunctions == RT_NONE)
return;
- printStats(Clusters, FuncAddr);
+ printStats(BC, Clusters, FuncAddr);
}
-void ReorderFunctions::printStats(const std::vector<Cluster> &Clusters,
+void ReorderFunctions::printStats(BinaryContext &BC,
+ const std::vector<Cluster> &Clusters,
const std::vector<uint64_t> &FuncAddr) {
if (opts::Verbosity == 0) {
#ifndef NDEBUG
@@ -167,11 +169,11 @@ void ReorderFunctions::printStats(const std::vector<Cluster> &Clusters,
double TotalCalls4KB = 0;
double TotalCalls2MB = 0;
if (PrintDetailed)
- outs() << "BOLT-INFO: Function reordering page layout\n"
- << "BOLT-INFO: ============== page 0 ==============\n";
+ BC.outs() << "BOLT-INFO: Function reordering page layout\n"
+ << "BOLT-INFO: ============== page 0 ==============\n";
for (const Cluster &Cluster : Clusters) {
if (PrintDetailed)
- outs() << format(
+ BC.outs() << format(
"BOLT-INFO: -------- density = %.3lf (%u / %u) --------\n",
Cluster.density(), Cluster.samples(), Cluster.size());
@@ -180,8 +182,8 @@ void ReorderFunctions::printStats(const std::vector<Cluster> &Clusters,
Hotfuncs++;
if (PrintDetailed)
- outs() << "BOLT-INFO: hot func " << *Cg.nodeIdToFunc(FuncId) << " ("
- << Cg.size(FuncId) << ")\n";
+ BC.outs() << "BOLT-INFO: hot func " << *Cg.nodeIdToFunc(FuncId)
+ << " (" << Cg.size(FuncId) << ")\n";
uint64_t Dist = 0;
uint64_t Calls = 0;
@@ -193,12 +195,13 @@ void ReorderFunctions::printStats(const std::vector<Cluster> &Clusters,
(FuncAddr[FuncId] + Arc.avgCallOffset()));
const double W = Arc.weight();
if (D < 64 && PrintDetailed && opts::Verbosity > 2)
- outs() << "BOLT-INFO: short (" << D << "B) call:\n"
- << "BOLT-INFO: Src: " << *Cg.nodeIdToFunc(FuncId) << "\n"
- << "BOLT-INFO: Dst: " << *Cg.nodeIdToFunc(Dst) << "\n"
- << "BOLT-INFO: Weight = " << W << "\n"
- << "BOLT-INFO: AvgOffset = " << Arc.avgCallOffset()
- << "\n";
+ BC.outs() << "BOLT-INFO: short (" << D << "B) call:\n"
+ << "BOLT-INFO: Src: " << *Cg.nodeIdToFunc(FuncId)
+ << "\n"
+ << "BOLT-INFO: Dst: " << *Cg.nodeIdToFunc(Dst) << "\n"
+ << "BOLT-INFO: Weight = " << W << "\n"
+ << "BOLT-INFO: AvgOffset = " << Arc.avgCallOffset()
+ << "\n";
Calls += W;
if (D < 64)
TotalCalls64B += W;
@@ -208,63 +211,64 @@ void ReorderFunctions::printStats(const std::vector<Cluster> &Clusters,
TotalCalls2MB += W;
Dist += Arc.weight() * D;
if (PrintDetailed)
- outs() << format("BOLT-INFO: arc: %u [@%lu+%.1lf] -> %u [@%lu]: "
- "weight = %.0lf, callDist = %f\n",
- Arc.src(), FuncAddr[Arc.src()],
- Arc.avgCallOffset(), Arc.dst(),
- FuncAddr[Arc.dst()], Arc.weight(), D);
+ BC.outs() << format("BOLT-INFO: arc: %u [@%lu+%.1lf] -> %u [@%lu]: "
+ "weight = %.0lf, callDist = %f\n",
+ Arc.src(), FuncAddr[Arc.src()],
+ Arc.avgCallOffset(), Arc.dst(),
+ FuncAddr[Arc.dst()], Arc.weight(), D);
}
TotalCalls += Calls;
TotalDistance += Dist;
TotalSize += Cg.size(FuncId);
if (PrintDetailed) {
- outs() << format("BOLT-INFO: start = %6u : avgCallDist = %lu : ",
- TotalSize, Calls ? Dist / Calls : 0)
- << Cg.nodeIdToFunc(FuncId)->getPrintName() << '\n';
+ BC.outs() << format("BOLT-INFO: start = %6u : avgCallDist = %lu : ",
+ TotalSize, Calls ? Dist / Calls : 0)
+ << Cg.nodeIdToFunc(FuncId)->getPrintName() << '\n';
const uint64_t NewPage = TotalSize / HugePageSize;
if (NewPage != CurPage) {
CurPage = NewPage;
- outs() << format(
+ BC.outs() << format(
"BOLT-INFO: ============== page %u ==============\n", CurPage);
}
}
}
}
}
- outs() << "BOLT-INFO: Function reordering stats\n"
- << format("BOLT-INFO: Number of hot functions: %u\n"
- "BOLT-INFO: Number of clusters: %lu\n",
- Hotfuncs, Clusters.size())
- << format("BOLT-INFO: Final average call distance = %.1lf "
- "(%.0lf / %.0lf)\n",
- TotalCalls ? TotalDistance / TotalCalls : 0, TotalDistance,
- TotalCalls)
- << format("BOLT-INFO: Total Calls = %.0lf\n", TotalCalls);
+ BC.outs() << "BOLT-INFO: Function reordering stats\n"
+ << format("BOLT-INFO: Number of hot functions: %u\n"
+ "BOLT-INFO: Number of clusters: %lu\n",
+ Hotfuncs, Clusters.size())
+ << format("BOLT-INFO: Final average call distance = %.1lf "
+ "(%.0lf / %.0lf)\n",
+ TotalCalls ? TotalDistance / TotalCalls : 0,
+ TotalDistance, TotalCalls)
+ << format("BOLT-INFO: Total Calls = %.0lf\n", TotalCalls);
if (TotalCalls)
- outs() << format("BOLT-INFO: Total Calls within 64B = %.0lf (%.2lf%%)\n",
- TotalCalls64B, 100 * TotalCalls64B / TotalCalls)
- << format("BOLT-INFO: Total Calls within 4KB = %.0lf (%.2lf%%)\n",
- TotalCalls4KB, 100 * TotalCalls4KB / TotalCalls)
- << format("BOLT-INFO: Total Calls within 2MB = %.0lf (%.2lf%%)\n",
- TotalCalls2MB, 100 * TotalCalls2MB / TotalCalls);
+ BC.outs()
+ << format("BOLT-INFO: Total Calls within 64B = %.0lf (%.2lf%%)\n",
+ TotalCalls64B, 100 * TotalCalls64B / TotalCalls)
+ << format("BOLT-INFO: Total Calls within 4KB = %.0lf (%.2lf%%)\n",
+ TotalCalls4KB, 100 * TotalCalls4KB / TotalCalls)
+ << format("BOLT-INFO: Total Calls within 2MB = %.0lf (%.2lf%%)\n",
+ TotalCalls2MB, 100 * TotalCalls2MB / TotalCalls);
}
-std::vector<std::string> ReorderFunctions::readFunctionOrderFile() {
- std::vector<std::string> FunctionNames;
+Error ReorderFunctions::readFunctionOrderFile(
+ std::vector<std::string> &FunctionNames) {
std::ifstream FuncsFile(opts::FunctionOrderFile, std::ios::in);
- if (!FuncsFile) {
- errs() << "Ordered functions file \"" << opts::FunctionOrderFile
- << "\" can't be opened.\n";
- exit(1);
- }
+ if (!FuncsFile)
+ return createFatalBOLTError(Twine("Ordered functions file \"") +
+ Twine(opts::FunctionOrderFile) +
+ Twine("\" can't be opened."));
+
std::string FuncName;
while (std::getline(FuncsFile, FuncName))
FunctionNames.push_back(FuncName);
- return FunctionNames;
+ return Error::success();
}
-void ReorderFunctions::runOnFunctions(BinaryContext &BC) {
+Error ReorderFunctions::runOnFunctions(BinaryContext &BC) {
auto &BFs = BC.getBinaryFunctions();
if (opts::ReorderFunctions != RT_NONE &&
opts::ReorderFunctions != RT_EXEC_COUNT &&
@@ -373,7 +377,11 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) {
uint32_t Index = 0;
uint32_t InvalidEntries = 0;
- for (const std::string &Function : readFunctionOrderFile()) {
+ std::vector<std::string> FunctionNames;
+ if (Error E = readFunctionOrderFile(FunctionNames))
+ return Error(std::move(E));
+
+ for (const std::string &Function : FunctionNames) {
std::vector<uint64_t> FuncAddrs;
BinaryData *BD = BC.getBinaryDataByName(Function);
@@ -399,8 +407,8 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) {
if (FuncAddrs.empty()) {
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: Reorder functions: can't find function "
- << "for " << Function << "\n";
+ BC.errs() << "BOLT-WARNING: Reorder functions: can't find function "
+ << "for " << Function << "\n";
++InvalidEntries;
continue;
}
@@ -412,28 +420,28 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) {
BinaryFunction *BF = BC.getFunctionForSymbol(FuncBD->getSymbol());
if (!BF) {
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: Reorder functions: can't find function "
- << "for " << Function << "\n";
+ BC.errs() << "BOLT-WARNING: Reorder functions: can't find function "
+ << "for " << Function << "\n";
++InvalidEntries;
break;
}
if (!BF->hasValidIndex())
BF->setIndex(Index++);
else if (opts::Verbosity > 0)
- errs() << "BOLT-WARNING: Duplicate reorder entry for " << Function
- << "\n";
+ BC.errs() << "BOLT-WARNING: Duplicate reorder entry for " << Function
+ << "\n";
}
}
if (InvalidEntries)
- errs() << "BOLT-WARNING: Reorder functions: can't find functions for "
- << InvalidEntries << " entries in -function-order list\n";
+ BC.errs() << "BOLT-WARNING: Reorder functions: can't find functions for "
+ << InvalidEntries << " entries in -function-order list\n";
} break;
default:
llvm_unreachable("unexpected layout type");
}
- reorder(std::move(Clusters), BFs);
+ reorder(BC, std::move(Clusters), BFs);
BC.HasFinalizedFunctionOrder = true;
@@ -442,9 +450,9 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) {
FuncsFile = std::make_unique<std::ofstream>(opts::GenerateFunctionOrderFile,
std::ios::out);
if (!FuncsFile) {
- errs() << "BOLT-ERROR: ordered functions file "
- << opts::GenerateFunctionOrderFile << " cannot be opened\n";
- exit(1);
+ BC.errs() << "BOLT-ERROR: ordered functions file "
+ << opts::GenerateFunctionOrderFile << " cannot be opened\n";
+ return createFatalBOLTError("");
}
}
@@ -453,9 +461,9 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) {
LinkSectionsFile =
std::make_unique<std::ofstream>(opts::LinkSectionsFile, std::ios::out);
if (!LinkSectionsFile) {
- errs() << "BOLT-ERROR: link sections file " << opts::LinkSectionsFile
- << " cannot be opened\n";
- exit(1);
+ BC.errs() << "BOLT-ERROR: link sections file " << opts::LinkSectionsFile
+ << " cannot be opened\n";
+ return createFatalBOLTError("");
}
}
@@ -505,16 +513,17 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) {
if (FuncsFile) {
FuncsFile->close();
- outs() << "BOLT-INFO: dumped function order to "
- << opts::GenerateFunctionOrderFile << '\n';
+ BC.outs() << "BOLT-INFO: dumped function order to "
+ << opts::GenerateFunctionOrderFile << '\n';
}
if (LinkSectionsFile) {
LinkSectionsFile->close();
- outs() << "BOLT-INFO: dumped linker section order to "
- << opts::LinkSectionsFile << '\n';
+ BC.outs() << "BOLT-INFO: dumped linker section order to "
+ << opts::LinkSectionsFile << '\n';
}
}
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/RetpolineInsertion.cpp b/bolt/lib/Passes/RetpolineInsertion.cpp
index 97eedb882f55..2808575cc6bb 100644
--- a/bolt/lib/Passes/RetpolineInsertion.cpp
+++ b/bolt/lib/Passes/RetpolineInsertion.cpp
@@ -271,9 +271,9 @@ IndirectBranchInfo::IndirectBranchInfo(MCInst &Inst, MCPlusBuilder &MIB) {
}
}
-void RetpolineInsertion::runOnFunctions(BinaryContext &BC) {
+Error RetpolineInsertion::runOnFunctions(BinaryContext &BC) {
if (!opts::InsertRetpolines)
- return;
+ return Error::success();
assert(BC.isX86() &&
"retpoline insertion not supported for target architecture");
@@ -327,10 +327,11 @@ void RetpolineInsertion::runOnFunctions(BinaryContext &BC) {
}
}
}
- outs() << "BOLT-INFO: The number of created retpoline functions is : "
- << CreatedRetpolines.size()
- << "\nBOLT-INFO: The number of retpolined branches is : "
- << RetpolinedBranches << "\n";
+ BC.outs() << "BOLT-INFO: The number of created retpoline functions is : "
+ << CreatedRetpolines.size()
+ << "\nBOLT-INFO: The number of retpolined branches is : "
+ << RetpolinedBranches << "\n";
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/ShrinkWrapping.cpp b/bolt/lib/Passes/ShrinkWrapping.cpp
index d7b25c1279dc..9a1f9d72623a 100644
--- a/bolt/lib/Passes/ShrinkWrapping.cpp
+++ b/bolt/lib/Passes/ShrinkWrapping.cpp
@@ -1646,9 +1646,9 @@ void ShrinkWrapping::rebuildCFIForSP() {
++I;
}
-MCInst ShrinkWrapping::createStackAccess(int SPVal, int FPVal,
- const FrameIndexEntry &FIE,
- bool CreatePushOrPop) {
+Expected<MCInst> ShrinkWrapping::createStackAccess(int SPVal, int FPVal,
+ const FrameIndexEntry &FIE,
+ bool CreatePushOrPop) {
MCInst NewInst;
if (SPVal != StackPointerTracking::SUPERPOSITION &&
SPVal != StackPointerTracking::EMPTY) {
@@ -1656,15 +1656,15 @@ MCInst ShrinkWrapping::createStackAccess(int SPVal, int FPVal,
if (!BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getStackPointer(),
FIE.StackOffset - SPVal, FIE.RegOrImm,
FIE.Size)) {
- errs() << "createRestoreFromStack: not supported on this platform\n";
- abort();
+ return createFatalBOLTError(
+ "createRestoreFromStack: not supported on this platform\n");
}
} else {
if (!BC.MIB->createSaveToStack(NewInst, BC.MIB->getStackPointer(),
FIE.StackOffset - SPVal, FIE.RegOrImm,
FIE.Size)) {
- errs() << "createSaveToStack: not supported on this platform\n";
- abort();
+ return createFatalBOLTError(
+ "createSaveToStack: not supported on this platform\n");
}
}
if (CreatePushOrPop)
@@ -1678,15 +1678,15 @@ MCInst ShrinkWrapping::createStackAccess(int SPVal, int FPVal,
if (!BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getFramePointer(),
FIE.StackOffset - FPVal, FIE.RegOrImm,
FIE.Size)) {
- errs() << "createRestoreFromStack: not supported on this platform\n";
- abort();
+ return createFatalBOLTError(
+ "createRestoreFromStack: not supported on this platform\n");
}
} else {
if (!BC.MIB->createSaveToStack(NewInst, BC.MIB->getFramePointer(),
FIE.StackOffset - FPVal, FIE.RegOrImm,
FIE.Size)) {
- errs() << "createSaveToStack: not supported on this platform\n";
- abort();
+ return createFatalBOLTError(
+ "createSaveToStack: not supported on this platform\n");
}
}
return NewInst;
@@ -1743,10 +1743,11 @@ BBIterTy ShrinkWrapping::insertCFIsForPushOrPop(BinaryBasicBlock &BB,
return Pos;
}
-BBIterTy ShrinkWrapping::processInsertion(BBIterTy InsertionPoint,
- BinaryBasicBlock *CurBB,
- const WorklistItem &Item,
- int64_t SPVal, int64_t FPVal) {
+Expected<BBIterTy> ShrinkWrapping::processInsertion(BBIterTy InsertionPoint,
+ BinaryBasicBlock *CurBB,
+ const WorklistItem &Item,
+ int64_t SPVal,
+ int64_t FPVal) {
// Trigger CFI reconstruction for this CSR if necessary - writing to
// PushOffsetByReg/PopOffsetByReg *will* trigger CFI update
if ((Item.FIEToInsert.IsStore &&
@@ -1772,9 +1773,12 @@ BBIterTy ShrinkWrapping::processInsertion(BBIterTy InsertionPoint,
<< " Is push = " << (Item.Action == WorklistItem::InsertPushOrPop)
<< "\n";
});
- MCInst NewInst =
+ Expected<MCInst> NewInstOrErr =
createStackAccess(SPVal, FPVal, Item.FIEToInsert,
Item.Action == WorklistItem::InsertPushOrPop);
+ if (auto E = NewInstOrErr.takeError())
+ return Error(std::move(E));
+ MCInst &NewInst = *NewInstOrErr;
if (InsertionPoint != CurBB->end()) {
LLVM_DEBUG({
dbgs() << "Adding before Inst: ";
@@ -1791,7 +1795,7 @@ BBIterTy ShrinkWrapping::processInsertion(BBIterTy InsertionPoint,
return CurBB->end();
}
-BBIterTy ShrinkWrapping::processInsertionsList(
+Expected<BBIterTy> ShrinkWrapping::processInsertionsList(
BBIterTy InsertionPoint, BinaryBasicBlock *CurBB,
std::vector<WorklistItem> &TodoList, int64_t SPVal, int64_t FPVal) {
bool HasInsertions = llvm::any_of(TodoList, [&](WorklistItem &Item) {
@@ -1840,8 +1844,11 @@ BBIterTy ShrinkWrapping::processInsertionsList(
Item.Action == WorklistItem::ChangeToAdjustment)
continue;
- InsertionPoint =
+ auto InsertionPointOrErr =
processInsertion(InsertionPoint, CurBB, Item, SPVal, FPVal);
+ if (auto E = InsertionPointOrErr.takeError())
+ return Error(std::move(E));
+ InsertionPoint = *InsertionPointOrErr;
if (Item.Action == WorklistItem::InsertPushOrPop &&
Item.FIEToInsert.IsStore)
SPVal -= Item.FIEToInsert.Size;
@@ -1852,7 +1859,7 @@ BBIterTy ShrinkWrapping::processInsertionsList(
return InsertionPoint;
}
-bool ShrinkWrapping::processInsertions() {
+Expected<bool> ShrinkWrapping::processInsertions() {
PredictiveStackPointerTracking PSPT(BF, Todo, Info, AllocatorId);
PSPT.run();
@@ -1875,14 +1882,20 @@ bool ShrinkWrapping::processInsertions() {
auto Iter = I;
std::pair<int, int> SPTState =
*PSPT.getStateAt(Iter == BB.begin() ? (ProgramPoint)&BB : &*(--Iter));
- I = processInsertionsList(I, &BB, List, SPTState.first, SPTState.second);
+ auto IterOrErr =
+ processInsertionsList(I, &BB, List, SPTState.first, SPTState.second);
+ if (auto E = IterOrErr.takeError())
+ return Error(std::move(E));
+ I = *IterOrErr;
}
// Process insertions at the end of bb
auto WRI = Todo.find(&BB);
if (WRI != Todo.end()) {
std::pair<int, int> SPTState = *PSPT.getStateAt(*BB.rbegin());
- processInsertionsList(BB.end(), &BB, WRI->second, SPTState.first,
- SPTState.second);
+ if (auto E = processInsertionsList(BB.end(), &BB, WRI->second,
+ SPTState.first, SPTState.second)
+ .takeError())
+ return Error(std::move(E));
Changes = true;
}
}
@@ -1945,7 +1958,7 @@ void ShrinkWrapping::rebuildCFI() {
}
}
-bool ShrinkWrapping::perform(bool HotOnly) {
+Expected<bool> ShrinkWrapping::perform(bool HotOnly) {
HasDeletedOffsetCFIs = BitVector(BC.MRI->getNumRegs(), false);
PushOffsetByReg = std::vector<int64_t>(BC.MRI->getNumRegs(), 0LL);
PopOffsetByReg = std::vector<int64_t>(BC.MRI->getNumRegs(), 0LL);
@@ -1998,7 +2011,11 @@ bool ShrinkWrapping::perform(bool HotOnly) {
});
SLM.performChanges();
// Early exit if processInsertions doesn't detect any todo items
- if (!processInsertions())
+ auto ModifiedOrErr = processInsertions();
+ if (auto E = ModifiedOrErr.takeError())
+ return Error(std::move(E));
+ const bool Modified = *ModifiedOrErr;
+ if (!Modified)
return false;
processDeletions();
if (foldIdenticalSplitEdges()) {
@@ -2018,28 +2035,28 @@ bool ShrinkWrapping::perform(bool HotOnly) {
return true;
}
-void ShrinkWrapping::printStats() {
- outs() << "BOLT-INFO: Shrink wrapping moved " << SpillsMovedRegularMode
- << " spills inserting load/stores and " << SpillsMovedPushPopMode
- << " spills inserting push/pops\n";
+void ShrinkWrapping::printStats(BinaryContext &BC) {
+ BC.outs() << "BOLT-INFO: Shrink wrapping moved " << SpillsMovedRegularMode
+ << " spills inserting load/stores and " << SpillsMovedPushPopMode
+ << " spills inserting push/pops\n";
if (!InstrDynamicCount || !StoreDynamicCount)
return;
- outs() << "BOLT-INFO: Shrink wrapping reduced " << SpillsMovedDynamicCount
- << " store executions ("
- << format("%.1lf%%",
- (100.0 * SpillsMovedDynamicCount / InstrDynamicCount))
- << " total instructions executed, "
- << format("%.1lf%%",
- (100.0 * SpillsMovedDynamicCount / StoreDynamicCount))
- << " store instructions)\n";
- outs() << "BOLT-INFO: Shrink wrapping failed at reducing "
- << SpillsFailedDynamicCount << " store executions ("
- << format("%.1lf%%",
- (100.0 * SpillsFailedDynamicCount / InstrDynamicCount))
- << " total instructions executed, "
- << format("%.1lf%%",
- (100.0 * SpillsFailedDynamicCount / StoreDynamicCount))
- << " store instructions)\n";
+ BC.outs() << "BOLT-INFO: Shrink wrapping reduced " << SpillsMovedDynamicCount
+ << " store executions ("
+ << format("%.1lf%%",
+ (100.0 * SpillsMovedDynamicCount / InstrDynamicCount))
+ << " total instructions executed, "
+ << format("%.1lf%%",
+ (100.0 * SpillsMovedDynamicCount / StoreDynamicCount))
+ << " store instructions)\n";
+ BC.outs() << "BOLT-INFO: Shrink wrapping failed at reducing "
+ << SpillsFailedDynamicCount << " store executions ("
+ << format("%.1lf%%",
+ (100.0 * SpillsFailedDynamicCount / InstrDynamicCount))
+ << " total instructions executed, "
+ << format("%.1lf%%",
+ (100.0 * SpillsFailedDynamicCount / StoreDynamicCount))
+ << " store instructions)\n";
}
// Operators necessary as a result of using MCAnnotation
diff --git a/bolt/lib/Passes/SplitFunctions.cpp b/bolt/lib/Passes/SplitFunctions.cpp
index 5de075973004..cdbb2a15f667 100644
--- a/bolt/lib/Passes/SplitFunctions.cpp
+++ b/bolt/lib/Passes/SplitFunctions.cpp
@@ -712,15 +712,15 @@ bool SplitFunctions::shouldOptimize(const BinaryFunction &BF) const {
return BinaryFunctionPass::shouldOptimize(BF);
}
-void SplitFunctions::runOnFunctions(BinaryContext &BC) {
+Error SplitFunctions::runOnFunctions(BinaryContext &BC) {
if (!opts::SplitFunctions)
- return;
+ return Error::success();
// If split strategy is not CDSplit, then a second run of the pass is not
// needed after function reordering.
if (BC.HasFinalizedFunctionOrder &&
opts::SplitStrategy != SplitFunctionsStrategy::CDSplit)
- return;
+ return Error::success();
std::unique_ptr<SplitStrategy> Strategy;
bool ForceSequential = false;
@@ -766,10 +766,12 @@ void SplitFunctions::runOnFunctions(BinaryContext &BC) {
"SplitFunctions", ForceSequential);
if (SplitBytesHot + SplitBytesCold > 0)
- outs() << "BOLT-INFO: splitting separates " << SplitBytesHot
- << " hot bytes from " << SplitBytesCold << " cold bytes "
- << format("(%.2lf%% of split functions is hot).\n",
- 100.0 * SplitBytesHot / (SplitBytesHot + SplitBytesCold));
+ BC.outs() << "BOLT-INFO: splitting separates " << SplitBytesHot
+ << " hot bytes from " << SplitBytesCold << " cold bytes "
+ << format("(%.2lf%% of split functions is hot).\n",
+ 100.0 * SplitBytesHot /
+ (SplitBytesHot + SplitBytesCold));
+ return Error::success();
}
void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) {
@@ -899,9 +901,9 @@ void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) {
if (alignTo(OriginalHotSize, opts::SplitAlignThreshold) <=
alignTo(HotSize, opts::SplitAlignThreshold) + opts::SplitThreshold) {
if (opts::Verbosity >= 2) {
- outs() << "BOLT-INFO: Reversing splitting of function "
- << formatv("{0}:\n {1:x}, {2:x} -> {3:x}\n", BF, HotSize,
- ColdSize, OriginalHotSize);
+ BC.outs() << "BOLT-INFO: Reversing splitting of function "
+ << formatv("{0}:\n {1:x}, {2:x} -> {3:x}\n", BF, HotSize,
+ ColdSize, OriginalHotSize);
}
// Reverse the action of createEHTrampolines(). The trampolines will be
diff --git a/bolt/lib/Passes/StokeInfo.cpp b/bolt/lib/Passes/StokeInfo.cpp
index 419ba236e134..499cac421709 100644
--- a/bolt/lib/Passes/StokeInfo.cpp
+++ b/bolt/lib/Passes/StokeInfo.cpp
@@ -97,7 +97,8 @@ bool StokeInfo::checkFunction(BinaryFunction &BF, DataflowInfoManager &DInfo,
if (!BF.isSimple() || BF.isMultiEntry() || BF.empty())
return false;
- outs() << " STOKE-INFO: analyzing function " << Name << "\n";
+ BF.getBinaryContext().outs()
+ << " STOKE-INFO: analyzing function " << Name << "\n";
FuncInfo.FuncName = Name;
FuncInfo.Offset = BF.getFileOffset();
@@ -140,19 +141,19 @@ bool StokeInfo::checkFunction(BinaryFunction &BF, DataflowInfoManager &DInfo,
LiveOutBV &= DefaultLiveOutMask;
getRegNameFromBitVec(BF.getBinaryContext(), LiveOutBV, &FuncInfo.LiveOut);
- outs() << " STOKE-INFO: end function \n";
+ BF.getBinaryContext().outs() << " STOKE-INFO: end function \n";
return true;
}
-void StokeInfo::runOnFunctions(BinaryContext &BC) {
- outs() << "STOKE-INFO: begin of stoke pass\n";
+Error StokeInfo::runOnFunctions(BinaryContext &BC) {
+ BC.outs() << "STOKE-INFO: begin of stoke pass\n";
std::ofstream Outfile;
if (!opts::StokeOutputDataFilename.empty()) {
Outfile.open(opts::StokeOutputDataFilename);
} else {
- errs() << "STOKE-INFO: output file is required\n";
- return;
+ BC.errs() << "STOKE-INFO: output file is required\n";
+ return Error::success();
}
// check some context meta data
@@ -185,7 +186,8 @@ void StokeInfo::runOnFunctions(BinaryContext &BC) {
FuncInfo.printData(Outfile);
}
- outs() << "STOKE-INFO: end of stoke pass\n";
+ BC.outs() << "STOKE-INFO: end of stoke pass\n";
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/TailDuplication.cpp b/bolt/lib/Passes/TailDuplication.cpp
index e63d4be1392f..2163e3a6a008 100644
--- a/bolt/lib/Passes/TailDuplication.cpp
+++ b/bolt/lib/Passes/TailDuplication.cpp
@@ -633,9 +633,9 @@ void TailDuplication::runOnFunction(BinaryFunction &Function) {
ModifiedFunctions++;
}
-void TailDuplication::runOnFunctions(BinaryContext &BC) {
+Error TailDuplication::runOnFunctions(BinaryContext &BC) {
if (opts::TailDuplicationMode == TailDuplication::TD_NONE)
- return;
+ return Error::success();
for (auto &It : BC.getBinaryFunctions()) {
BinaryFunction &Function = It.second;
@@ -644,23 +644,26 @@ void TailDuplication::runOnFunctions(BinaryContext &BC) {
runOnFunction(Function);
}
- outs() << "BOLT-INFO: tail duplication"
- << format(" modified %zu (%.2f%%) functions;", ModifiedFunctions,
- 100.0 * ModifiedFunctions / BC.getBinaryFunctions().size())
- << format(" duplicated %zu blocks (%zu bytes) responsible for",
- DuplicatedBlockCount, DuplicatedByteCount)
- << format(" %zu dynamic executions (%.2f%% of all block executions)",
- DuplicationsDynamicCount,
- 100.0 * DuplicationsDynamicCount / AllDynamicCount)
- << "\n";
+ BC.outs()
+ << "BOLT-INFO: tail duplication"
+ << format(" modified %zu (%.2f%%) functions;", ModifiedFunctions,
+ 100.0 * ModifiedFunctions / BC.getBinaryFunctions().size())
+ << format(" duplicated %zu blocks (%zu bytes) responsible for",
+ DuplicatedBlockCount, DuplicatedByteCount)
+ << format(" %zu dynamic executions (%.2f%% of all block executions)",
+ DuplicationsDynamicCount,
+ 100.0 * DuplicationsDynamicCount / AllDynamicCount)
+ << "\n";
if (opts::TailDuplicationConstCopyPropagation) {
- outs() << "BOLT-INFO: tail duplication "
- << format("applied %zu static and %zu dynamic propagation deletions",
+ BC.outs() << "BOLT-INFO: tail duplication "
+ << format(
+ "applied %zu static and %zu dynamic propagation deletions",
StaticInstructionDeletionCount,
DynamicInstructionDeletionCount)
- << "\n";
+ << "\n";
}
+ return Error::success();
}
} // end namespace bolt
diff --git a/bolt/lib/Passes/ThreeWayBranch.cpp b/bolt/lib/Passes/ThreeWayBranch.cpp
index dc320d53fb68..c69eac5614b9 100644
--- a/bolt/lib/Passes/ThreeWayBranch.cpp
+++ b/bolt/lib/Passes/ThreeWayBranch.cpp
@@ -147,7 +147,7 @@ void ThreeWayBranch::runOnFunction(BinaryFunction &Function) {
}
}
-void ThreeWayBranch::runOnFunctions(BinaryContext &BC) {
+Error ThreeWayBranch::runOnFunctions(BinaryContext &BC) {
for (auto &It : BC.getBinaryFunctions()) {
BinaryFunction &Function = It.second;
if (!shouldRunOnFunction(Function))
@@ -155,8 +155,9 @@ void ThreeWayBranch::runOnFunctions(BinaryContext &BC) {
runOnFunction(Function);
}
- outs() << "BOLT-INFO: number of three way branches order changed: "
- << BranchesAltered << "\n";
+ BC.outs() << "BOLT-INFO: number of three way branches order changed: "
+ << BranchesAltered << "\n";
+ return Error::success();
}
} // end namespace bolt
diff --git a/bolt/lib/Passes/ValidateInternalCalls.cpp b/bolt/lib/Passes/ValidateInternalCalls.cpp
index 516f91acb508..54ae621159cf 100644
--- a/bolt/lib/Passes/ValidateInternalCalls.cpp
+++ b/bolt/lib/Passes/ValidateInternalCalls.cpp
@@ -302,9 +302,9 @@ bool ValidateInternalCalls::analyzeFunction(BinaryFunction &Function) const {
return true;
}
-void ValidateInternalCalls::runOnFunctions(BinaryContext &BC) {
+Error ValidateInternalCalls::runOnFunctions(BinaryContext &BC) {
if (!BC.isX86())
- return;
+ return Error::success();
// Look for functions that need validation. This should be pretty rare.
std::set<BinaryFunction *> NeedsValidation;
@@ -323,7 +323,7 @@ void ValidateInternalCalls::runOnFunctions(BinaryContext &BC) {
// Skip validation for non-relocation mode
if (!BC.HasRelocations)
- return;
+ return Error::success();
// Since few functions need validation, we can work with our most expensive
// algorithms here. Fix the CFG treating internal calls as unconditional
@@ -339,13 +339,15 @@ void ValidateInternalCalls::runOnFunctions(BinaryContext &BC) {
}
if (!Invalid.empty()) {
- errs() << "BOLT-WARNING: will skip the following function(s) as unsupported"
- " internal calls were detected:\n";
+ BC.errs()
+ << "BOLT-WARNING: will skip the following function(s) as unsupported"
+ " internal calls were detected:\n";
for (BinaryFunction *Function : Invalid) {
- errs() << " " << *Function << "\n";
+ BC.errs() << " " << *Function << "\n";
Function->setIgnored();
}
}
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Passes/ValidateMemRefs.cpp b/bolt/lib/Passes/ValidateMemRefs.cpp
index 3324776830d1..f29a97c43f49 100644
--- a/bolt/lib/Passes/ValidateMemRefs.cpp
+++ b/bolt/lib/Passes/ValidateMemRefs.cpp
@@ -72,13 +72,13 @@ void ValidateMemRefs::runOnFunction(BinaryFunction &BF) {
}
}
-void ValidateMemRefs::runOnFunctions(BinaryContext &BC) {
+Error ValidateMemRefs::runOnFunctions(BinaryContext &BC) {
if (!BC.isX86())
- return;
+ return Error::success();
// Skip validation if not moving JT
if (opts::JumpTables == JTS_NONE || opts::JumpTables == JTS_BASIC)
- return;
+ return Error::success();
ParallelUtilities::WorkFuncWithAllocTy ProcessFunction =
[&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId) {
@@ -94,10 +94,11 @@ void ValidateMemRefs::runOnFunctions(BinaryContext &BC) {
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: memrefs validation is concluded\n");
if (!ReplacedReferences)
- return;
+ return Error::success();
- outs() << "BOLT-INFO: validate-mem-refs updated " << ReplacedReferences
- << " object references\n";
+ BC.outs() << "BOLT-INFO: validate-mem-refs updated " << ReplacedReferences
+ << " object references\n";
+ return Error::success();
}
} // namespace llvm::bolt
diff --git a/bolt/lib/Passes/VeneerElimination.cpp b/bolt/lib/Passes/VeneerElimination.cpp
index 929c7360b7ff..0bec11128c7c 100644
--- a/bolt/lib/Passes/VeneerElimination.cpp
+++ b/bolt/lib/Passes/VeneerElimination.cpp
@@ -29,9 +29,9 @@ static llvm::cl::opt<bool>
namespace llvm {
namespace bolt {
-void VeneerElimination::runOnFunctions(BinaryContext &BC) {
+Error VeneerElimination::runOnFunctions(BinaryContext &BC) {
if (!opts::EliminateVeneers || !BC.isAArch64())
- return;
+ return Error::success();
std::map<uint64_t, BinaryFunction> &BFs = BC.getBinaryFunctions();
std::unordered_map<const MCSymbol *, const MCSymbol *> VeneerDestinations;
@@ -51,8 +51,8 @@ void VeneerElimination::runOnFunctions(BinaryContext &BC) {
VeneerDestinations[Symbol] = VeneerTargetSymbol;
}
- outs() << "BOLT-INFO: number of removed linker-inserted veneers: "
- << VeneersCount << "\n";
+ BC.outs() << "BOLT-INFO: number of removed linker-inserted veneers: "
+ << VeneersCount << "\n";
// Handle veneers to veneers in case they occur
for (auto &Entry : VeneerDestinations) {
@@ -79,8 +79,8 @@ void VeneerElimination::runOnFunctions(BinaryContext &BC) {
VeneerCallers++;
if (!BC.MIB->replaceBranchTarget(
Instr, VeneerDestinations[TargetSymbol], BC.Ctx.get())) {
- errs() << "BOLT-ERROR: updating veneer call destination failed\n";
- exit(1);
+ return createFatalBOLTError(
+ "BOLT-ERROR: updating veneer call destination failed\n");
}
}
}
@@ -90,6 +90,7 @@ void VeneerElimination::runOnFunctions(BinaryContext &BC) {
dbgs() << "BOLT-INFO: number of linker-inserted veneers call sites: "
<< VeneerCallers << "\n");
(void)VeneerCallers;
+ return Error::success();
}
} // namespace bolt
diff --git a/bolt/lib/Profile/BoltAddressTranslation.cpp b/bolt/lib/Profile/BoltAddressTranslation.cpp
index 6901e482ddfd..8e18b21f696a 100644
--- a/bolt/lib/Profile/BoltAddressTranslation.cpp
+++ b/bolt/lib/Profile/BoltAddressTranslation.cpp
@@ -108,7 +108,7 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) {
writeMaps</*Cold=*/false>(Maps, PrevAddress, OS);
writeMaps</*Cold=*/true>(Maps, PrevAddress, OS);
- outs() << "BOLT-INFO: Wrote " << Maps.size() << " BAT maps\n";
+ BC.outs() << "BOLT-INFO: Wrote " << Maps.size() << " BAT maps\n";
}
APInt BoltAddressTranslation::calculateBranchEntriesBitMask(MapTy &Map,
@@ -201,7 +201,7 @@ void BoltAddressTranslation::writeMaps(std::map<uint64_t, MapTy> &Maps,
}
}
-std::error_code BoltAddressTranslation::parse(StringRef Buf) {
+std::error_code BoltAddressTranslation::parse(raw_ostream &OS, StringRef Buf) {
DataExtractor DE = DataExtractor(Buf, true, 8);
uint64_t Offset = 0;
if (Buf.size() < 12)
@@ -225,7 +225,7 @@ std::error_code BoltAddressTranslation::parse(StringRef Buf) {
uint64_t PrevAddress = 0;
parseMaps</*Cold=*/false>(HotFuncs, PrevAddress, DE, Offset, Err);
parseMaps</*Cold=*/true>(HotFuncs, PrevAddress, DE, Offset, Err);
- outs() << "BOLT-INFO: Parsed " << Maps.size() << " BAT entries\n";
+ OS << "BOLT-INFO: Parsed " << Maps.size() << " BAT entries\n";
return errorToErrorCode(std::move(Err));
}
diff --git a/bolt/lib/Rewrite/BinaryPassManager.cpp b/bolt/lib/Rewrite/BinaryPassManager.cpp
index 9946608c96d8..489b33fe1c7c 100644
--- a/bolt/lib/Rewrite/BinaryPassManager.cpp
+++ b/bolt/lib/Rewrite/BinaryPassManager.cpp
@@ -268,7 +268,7 @@ const char BinaryFunctionPassManager::TimerGroupName[] = "passman";
const char BinaryFunctionPassManager::TimerGroupDesc[] =
"Binary Function Pass Manager";
-void BinaryFunctionPassManager::runPasses() {
+Error BinaryFunctionPassManager::runPasses() {
auto &BFs = BC.getBinaryFunctions();
for (size_t PassIdx = 0; PassIdx < Passes.size(); PassIdx++) {
const std::pair<const bool, std::unique_ptr<BinaryFunctionPass>>
@@ -281,13 +281,20 @@ void BinaryFunctionPassManager::runPasses() {
formatv("{0:2}_{1}", PassIdx, Pass->getName()).str();
if (opts::Verbosity > 0)
- outs() << "BOLT-INFO: Starting pass: " << Pass->getName() << "\n";
+ BC.outs() << "BOLT-INFO: Starting pass: " << Pass->getName() << "\n";
NamedRegionTimer T(Pass->getName(), Pass->getName(), TimerGroupName,
TimerGroupDesc, TimeOpts);
- callWithDynoStats([this, &Pass] { Pass->runOnFunctions(BC); }, BFs,
- Pass->getName(), opts::DynoStatsAll, BC.isAArch64());
+ Error E = Error::success();
+ callWithDynoStats(
+ BC.outs(),
+ [this, &E, &Pass] {
+ E = joinErrors(std::move(E), Pass->runOnFunctions(BC));
+ },
+ BFs, Pass->getName(), opts::DynoStatsAll, BC.isAArch64());
+ if (E)
+ return Error(std::move(E));
if (opts::VerifyCFG &&
!std::accumulate(
@@ -296,13 +303,13 @@ void BinaryFunctionPassManager::runPasses() {
const std::pair<const uint64_t, BinaryFunction> &It) {
return Valid && It.second.validateCFG();
})) {
- errs() << "BOLT-ERROR: Invalid CFG detected after pass "
- << Pass->getName() << "\n";
- exit(1);
+ return createFatalBOLTError(
+ Twine("BOLT-ERROR: Invalid CFG detected after pass ") +
+ Twine(Pass->getName()) + Twine("\n"));
}
if (opts::Verbosity > 0)
- outs() << "BOLT-INFO: Finished pass: " << Pass->getName() << "\n";
+ BC.outs() << "BOLT-INFO: Finished pass: " << Pass->getName() << "\n";
if (!opts::PrintAll && !opts::DumpDotAll && !Pass->printPass())
continue;
@@ -315,15 +322,16 @@ void BinaryFunctionPassManager::runPasses() {
if (!Pass->shouldPrint(Function))
continue;
- Function.print(outs(), Message);
+ Function.print(BC.outs(), Message);
if (opts::DumpDotAll)
Function.dumpGraphForPass(PassIdName);
}
}
+ return Error::success();
}
-void BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
+Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
BinaryFunctionPassManager Manager(BC);
const DynoStats InitialDynoStats =
@@ -516,7 +524,7 @@ void BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
// in parallel and restore them
Manager.registerPass(std::make_unique<CleanMCState>(NeverPrint));
- Manager.runPasses();
+ return Manager.runPasses();
}
} // namespace bolt
diff --git a/bolt/lib/Rewrite/BoltDiff.cpp b/bolt/lib/Rewrite/BoltDiff.cpp
index 16a90510962e..fa43b7a2f92c 100644
--- a/bolt/lib/Rewrite/BoltDiff.cpp
+++ b/bolt/lib/Rewrite/BoltDiff.cpp
@@ -294,9 +294,9 @@ class RewriteInstanceDiff {
}
PrintProgramStats PPS(opts::NeverPrint);
outs() << "* BOLT-DIFF: Starting print program stats pass for binary 1\n";
- PPS.runOnFunctions(*RI1.BC);
+ RI1.BC->logBOLTErrorsAndQuitOnFatal(PPS.runOnFunctions(*RI1.BC));
outs() << "* BOLT-DIFF: Starting print program stats pass for binary 2\n";
- PPS.runOnFunctions(*RI2.BC);
+ RI1.BC->logBOLTErrorsAndQuitOnFatal(PPS.runOnFunctions(*RI2.BC));
outs() << "=====\n";
outs() << "Inputs share " << BothHaveProfile
<< " functions with valid profile.\n";
@@ -700,9 +700,9 @@ void RewriteInstance::compare(RewriteInstance &RI2) {
if (opts::ICF) {
IdenticalCodeFolding ICF(opts::NeverPrint);
outs() << "BOLT-DIFF: Starting ICF pass for binary 1";
- ICF.runOnFunctions(*BC);
+ BC->logBOLTErrorsAndQuitOnFatal(ICF.runOnFunctions(*BC));
outs() << "BOLT-DIFF: Starting ICF pass for binary 2";
- ICF.runOnFunctions(*RI2.BC);
+ BC->logBOLTErrorsAndQuitOnFatal(ICF.runOnFunctions(*RI2.BC));
}
RewriteInstanceDiff RID(*this, RI2);
diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp
index cefccbdfa2f0..27fa937c7508 100644
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -709,7 +709,7 @@ void DWARFRewriter::updateDebugInfo() {
: LegacyRangesSectionWriter.get();
// Skipping CUs that failed to load.
if (SplitCU) {
- DIEBuilder DWODIEBuilder(&(*SplitCU)->getContext(), true);
+ DIEBuilder DWODIEBuilder(BC, &(*SplitCU)->getContext(), true);
DWODIEBuilder.buildDWOUnit(**SplitCU);
std::string DWOName = updateDWONameCompDir(
*Unit, *DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit));
@@ -754,7 +754,7 @@ void DWARFRewriter::updateDebugInfo() {
AddrWriter->update(*DIEBlder, *Unit);
};
- DIEBuilder DIEBlder(BC.DwCtx.get());
+ DIEBuilder DIEBlder(BC, BC.DwCtx.get());
DIEBlder.buildTypeUnits(StrOffstsWriter.get());
SmallVector<char, 20> OutBuffer;
std::unique_ptr<raw_svector_ostream> ObjOS =
@@ -1655,7 +1655,8 @@ createDwarfOnlyBC(const object::ObjectFile &File) {
&File, false,
DWARFContext::create(File, DWARFContext::ProcessDebugRelocations::Ignore,
nullptr, "", WithColor::defaultErrorHandler,
- WithColor::defaultWarningHandler)));
+ WithColor::defaultWarningHandler),
+ {llvm::outs(), llvm::errs()}));
}
StringMap<DWARFRewriter::KnownSectionsEntry>
diff --git a/bolt/lib/Rewrite/MachORewriteInstance.cpp b/bolt/lib/Rewrite/MachORewriteInstance.cpp
index 8be8257f15c1..0970a0507ebe 100644
--- a/bolt/lib/Rewrite/MachORewriteInstance.cpp
+++ b/bolt/lib/Rewrite/MachORewriteInstance.cpp
@@ -103,7 +103,8 @@ MachORewriteInstance::MachORewriteInstance(object::MachOObjectFile *InputFile,
: InputFile(InputFile), ToolPath(ToolPath) {
ErrorAsOutParameter EAO(&Err);
auto BCOrErr = BinaryContext::createBinaryContext(
- InputFile, /* IsPIC */ true, DWARFContext::create(*InputFile));
+ InputFile, /* IsPIC */ true, DWARFContext::create(*InputFile),
+ {llvm::outs(), llvm::errs()});
if (Error E = BCOrErr.takeError()) {
Err = std::move(E);
return;
@@ -337,7 +338,7 @@ void MachORewriteInstance::disassembleFunctions() {
BinaryFunction &Function = BFI.second;
if (!Function.isSimple())
continue;
- Function.disassemble();
+ BC->logBOLTErrorsAndQuitOnFatal(Function.disassemble());
if (opts::PrintDisasm)
Function.print(outs(), "after disassembly");
}
@@ -348,10 +349,7 @@ void MachORewriteInstance::buildFunctionsCFG() {
BinaryFunction &Function = BFI.second;
if (!Function.isSimple())
continue;
- if (!Function.buildCFG(/*AllocId*/ 0)) {
- errs() << "BOLT-WARNING: failed to build CFG for the function "
- << Function << "\n";
- }
+ BC->logBOLTErrorsAndQuitOnFatal(Function.buildCFG(/*AllocId*/ 0));
}
}
@@ -387,7 +385,7 @@ void MachORewriteInstance::runOptimizationPasses() {
Manager.registerPass(
std::make_unique<FinalizeFunctions>(opts::PrintFinalized));
- Manager.runPasses();
+ BC->logBOLTErrorsAndQuitOnFatal(Manager.runPasses());
}
void MachORewriteInstance::mapInstrumentationSection(
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 9a242d94dd77..db093bfc2d8b 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -309,9 +309,11 @@ bool refersToReorderedSection(ErrorOr<BinarySection &> Section) {
Expected<std::unique_ptr<RewriteInstance>>
RewriteInstance::create(ELFObjectFileBase *File, const int Argc,
- const char *const *Argv, StringRef ToolPath) {
+ const char *const *Argv, StringRef ToolPath,
+ raw_ostream &Stdout, raw_ostream &Stderr) {
Error Err = Error::success();
- auto RI = std::make_unique<RewriteInstance>(File, Argc, Argv, ToolPath, Err);
+ auto RI = std::make_unique<RewriteInstance>(File, Argc, Argv, ToolPath,
+ Stdout, Stderr, Err);
if (Err)
return std::move(Err);
return std::move(RI);
@@ -319,6 +321,7 @@ RewriteInstance::create(ELFObjectFileBase *File, const int Argc,
RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc,
const char *const *Argv, StringRef ToolPath,
+ raw_ostream &Stdout, raw_ostream &Stderr,
Error &Err)
: InputFile(File), Argc(Argc), Argv(Argv), ToolPath(ToolPath),
SHStrTab(StringTableBuilder::ELF) {
@@ -333,17 +336,23 @@ RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc,
bool IsPIC = false;
const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();
if (Obj.getHeader().e_type != ELF::ET_EXEC) {
- outs() << "BOLT-INFO: shared object or position-independent executable "
+ Stdout << "BOLT-INFO: shared object or position-independent executable "
"detected\n";
IsPIC = true;
}
+ // Make sure we don't miss any output on core dumps.
+ Stdout.SetUnbuffered();
+ Stderr.SetUnbuffered();
+ LLVM_DEBUG(dbgs().SetUnbuffered());
+
auto BCOrErr = BinaryContext::createBinaryContext(
File, IsPIC,
DWARFContext::create(*File, DWARFContext::ProcessDebugRelocations::Ignore,
nullptr, opts::DWPPathName,
WithColor::defaultErrorHandler,
- WithColor::defaultWarningHandler));
+ WithColor::defaultWarningHandler),
+ JournalingStreams{Stdout, Stderr});
if (Error E = BCOrErr.takeError()) {
Err = std::move(E);
return;
@@ -457,22 +466,23 @@ void RewriteInstance::markGnuRelroSections() {
bool VMAContains = checkVMA<ELFT>(Phdr, *Sec, VMAOverlap);
if (ImageOverlap) {
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: GNU_RELRO segment has partial file offset "
- << "overlap with section " << BinarySection->getName() << '\n';
+ BC->errs() << "BOLT-WARNING: GNU_RELRO segment has partial file offset "
+ << "overlap with section " << BinarySection->getName()
+ << '\n';
return;
}
if (VMAOverlap) {
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: GNU_RELRO segment has partial VMA overlap "
- << "with section " << BinarySection->getName() << '\n';
+ BC->errs() << "BOLT-WARNING: GNU_RELRO segment has partial VMA overlap "
+ << "with section " << BinarySection->getName() << '\n';
return;
}
if (!ImageContains || !VMAContains)
return;
BinarySection->setRelro();
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: marking " << BinarySection->getName()
- << " as GNU_RELRO\n";
+ BC->outs() << "BOLT-INFO: marking " << BinarySection->getName()
+ << " as GNU_RELRO\n";
};
for (const ELFT::Phdr &Phdr : cantFail(Obj.program_headers()))
@@ -523,7 +533,7 @@ Error RewriteInstance::discoverStorage() {
}
if (BC->IsLinuxKernel)
- outs() << "BOLT-INFO: Linux kernel binary detected\n";
+ BC->outs() << "BOLT-INFO: Linux kernel binary detected\n";
for (const SectionRef &Section : InputFile->sections()) {
Expected<StringRef> SectionNameOrErr = Section.getName();
@@ -555,8 +565,8 @@ Error RewriteInstance::discoverStorage() {
return createStringError(errc::executable_format_error,
"no PT_LOAD pheader seen");
- outs() << "BOLT-INFO: first alloc address is 0x"
- << Twine::utohexstr(BC->FirstAllocAddress) << '\n';
+ BC->outs() << "BOLT-INFO: first alloc address is 0x"
+ << Twine::utohexstr(BC->FirstAllocAddress) << '\n';
FirstNonAllocatableOffset = NextAvailableOffset;
@@ -588,9 +598,9 @@ Error RewriteInstance::discoverStorage() {
NextAvailableAddress - BC->FirstAllocAddress &&
"PHDR table address calculation error");
- outs() << "BOLT-INFO: creating new program header table at address 0x"
- << Twine::utohexstr(NextAvailableAddress) << ", offset 0x"
- << Twine::utohexstr(NextAvailableOffset) << '\n';
+ BC->outs() << "BOLT-INFO: creating new program header table at address 0x"
+ << Twine::utohexstr(NextAvailableAddress) << ", offset 0x"
+ << Twine::utohexstr(NextAvailableOffset) << '\n';
PHDRTableAddress = NextAvailableAddress;
PHDRTableOffset = NextAvailableOffset;
@@ -685,7 +695,8 @@ void RewriteInstance::patchBuildID() {
uint64_t FileOffset = getFileOffsetForAddress(BuildIDSection->getAddress());
if (!FileOffset) {
- errs() << "BOLT-WARNING: Non-allocatable build-id will not be updated.\n";
+ BC->errs()
+ << "BOLT-WARNING: Non-allocatable build-id will not be updated.\n";
return;
}
@@ -693,17 +704,17 @@ void RewriteInstance::patchBuildID() {
LastIDByte ^= 1;
OS.pwrite(&LastIDByte, 1, FileOffset + IDOffset + BuildID.size() - 1);
- outs() << "BOLT-INFO: patched build-id (flipped last bit)\n";
+ BC->outs() << "BOLT-INFO: patched build-id (flipped last bit)\n";
}
Error RewriteInstance::run() {
assert(BC && "failed to create a binary context");
- outs() << "BOLT-INFO: Target architecture: "
- << Triple::getArchTypeName(
- (llvm::Triple::ArchType)InputFile->getArch())
- << "\n";
- outs() << "BOLT-INFO: BOLT version: " << BoltRevision << "\n";
+ BC->outs() << "BOLT-INFO: Target architecture: "
+ << Triple::getArchTypeName(
+ (llvm::Triple::ArchType)InputFile->getArch())
+ << "\n";
+ BC->outs() << "BOLT-INFO: BOLT version: " << BoltRevision << "\n";
if (Error E = discoverStorage())
return E;
@@ -758,10 +769,10 @@ Error RewriteInstance::run() {
updateRtFiniReloc();
if (opts::OutputFilename == "/dev/null") {
- outs() << "BOLT-INFO: skipping writing final binary to disk\n";
+ BC->outs() << "BOLT-INFO: skipping writing final binary to disk\n";
return Error::success();
} else if (BC->IsLinuxKernel) {
- errs() << "BOLT-WARNING: Linux kernel support is experimental\n";
+ BC->errs() << "BOLT-WARNING: Linux kernel support is experimental\n";
}
// Rewrite allocatable contents and copy non-allocatable parts with mods.
@@ -786,13 +797,15 @@ void RewriteInstance::discoverFileObjects() {
for (const ELFSymbolRef &Symbol : InputFile->symbols()) {
Expected<StringRef> NameOrError = Symbol.getName();
if (NameOrError && NameOrError->starts_with("__asan_init")) {
- errs() << "BOLT-ERROR: input file was compiled or linked with sanitizer "
- "support. Cannot optimize.\n";
+ BC->errs()
+ << "BOLT-ERROR: input file was compiled or linked with sanitizer "
+ "support. Cannot optimize.\n";
exit(1);
}
if (NameOrError && NameOrError->starts_with("__llvm_coverage_mapping")) {
- errs() << "BOLT-ERROR: input file was compiled or linked with coverage "
- "support. Cannot optimize.\n";
+ BC->errs()
+ << "BOLT-ERROR: input file was compiled or linked with coverage "
+ "support. Cannot optimize.\n";
exit(1);
}
@@ -924,7 +937,7 @@ void RewriteInstance::discoverFileObjects() {
StringRef SymName = cantFail(Symbol.getName(), "cannot get symbol name");
if (SymbolAddress == 0) {
if (opts::Verbosity >= 1 && SymbolType == SymbolRef::ST_Function)
- errs() << "BOLT-WARNING: function with 0 address seen\n";
+ BC->errs() << "BOLT-WARNING: function with 0 address seen\n";
continue;
}
@@ -965,13 +978,13 @@ void RewriteInstance::discoverFileObjects() {
if (BD->getSize() == ELFSymbolRef(Symbol).getSize() &&
BD->getAddress() == SymbolAddress) {
if (opts::Verbosity > 1)
- errs() << "BOLT-WARNING: ignoring duplicate global symbol " << Name
- << "\n";
+ BC->errs() << "BOLT-WARNING: ignoring duplicate global symbol "
+ << Name << "\n";
// Ignore duplicate entry - possibly a bug in the linker
continue;
}
- errs() << "BOLT-ERROR: bad input binary, global symbol \"" << Name
- << "\" is not unique\n";
+ BC->errs() << "BOLT-ERROR: bad input binary, global symbol \"" << Name
+ << "\" is not unique\n";
exit(1);
}
UniqueName = Name;
@@ -1059,9 +1072,9 @@ void RewriteInstance::discoverFileObjects() {
!SymbolSize) {
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring symbol as a marker\n");
} else if (opts::Verbosity > 1) {
- errs() << "BOLT-WARNING: symbol " << UniqueName
- << " seen in the middle of function " << *PreviousFunction
- << ". Could be a new entry.\n";
+ BC->errs() << "BOLT-WARNING: symbol " << UniqueName
+ << " seen in the middle of function " << *PreviousFunction
+ << ". Could be a new entry.\n";
}
registerName(SymbolSize);
continue;
@@ -1077,12 +1090,14 @@ void RewriteInstance::discoverFileObjects() {
PreviousFunction->getAddress() != SymbolAddress) {
if (PreviousFunction->isSymbolValidInScope(Symbol, SymbolSize)) {
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: skipping possibly another entry for function "
- << *PreviousFunction << " : " << UniqueName << '\n';
+ BC->outs()
+ << "BOLT-INFO: skipping possibly another entry for function "
+ << *PreviousFunction << " : " << UniqueName << '\n';
registerName(SymbolSize);
} else {
- outs() << "BOLT-INFO: using " << UniqueName << " as another entry to "
- << "function " << *PreviousFunction << '\n';
+ BC->outs() << "BOLT-INFO: using " << UniqueName
+ << " as another entry to "
+ << "function " << *PreviousFunction << '\n';
registerName(0);
@@ -1114,20 +1129,21 @@ void RewriteInstance::discoverFileObjects() {
uint64_t PrevLength = PrevFDE.getAddressRange();
if (SymbolAddress > PrevStart &&
SymbolAddress < PrevStart + PrevLength) {
- errs() << "BOLT-ERROR: function " << UniqueName
- << " is in conflict with FDE ["
- << Twine::utohexstr(PrevStart) << ", "
- << Twine::utohexstr(PrevStart + PrevLength)
- << "). Skipping.\n";
+ BC->errs() << "BOLT-ERROR: function " << UniqueName
+ << " is in conflict with FDE ["
+ << Twine::utohexstr(PrevStart) << ", "
+ << Twine::utohexstr(PrevStart + PrevLength)
+ << "). Skipping.\n";
IsSimple = false;
}
}
} else if (FDE.getAddressRange() != SymbolSize) {
if (SymbolSize) {
// Function addresses match but sizes differ.
- errs() << "BOLT-WARNING: sizes differ for function " << UniqueName
- << ". FDE : " << FDE.getAddressRange()
- << "; symbol table : " << SymbolSize << ". Using max size.\n";
+ BC->errs() << "BOLT-WARNING: sizes differ for function " << UniqueName
+ << ". FDE : " << FDE.getAddressRange()
+ << "; symbol table : " << SymbolSize
+ << ". Using max size.\n";
}
SymbolSize = std::max(SymbolSize, FDE.getAddressRange());
if (BC->getBinaryDataAtAddress(SymbolAddress)) {
@@ -1151,10 +1167,11 @@ void RewriteInstance::discoverFileObjects() {
if (SymbolSize != BF->getSize()) {
if (opts::Verbosity >= 1) {
if (SymbolSize && BF->getSize())
- errs() << "BOLT-WARNING: size mismatch for duplicate entries "
- << *BF << " and " << UniqueName << '\n';
- outs() << "BOLT-INFO: adjusting size of function " << *BF << " old "
- << BF->getSize() << " new " << SymbolSize << "\n";
+ BC->errs() << "BOLT-WARNING: size mismatch for duplicate entries "
+ << *BF << " and " << UniqueName << '\n';
+ BC->outs() << "BOLT-INFO: adjusting size of function " << *BF
+ << " old " << BF->getSize() << " new " << SymbolSize
+ << "\n";
}
BF->setSize(std::max(SymbolSize, BF->getSize()));
BC->setBinaryDataSize(SymbolAddress, BF->getSize());
@@ -1165,9 +1182,9 @@ void RewriteInstance::discoverFileObjects() {
BC->getSectionForAddress(SymbolAddress);
// Skip symbols from invalid sections
if (!Section) {
- errs() << "BOLT-WARNING: " << UniqueName << " (0x"
- << Twine::utohexstr(SymbolAddress)
- << ") does not have any section\n";
+ BC->errs() << "BOLT-WARNING: " << UniqueName << " (0x"
+ << Twine::utohexstr(SymbolAddress)
+ << ") does not have any section\n";
continue;
}
@@ -1186,12 +1203,12 @@ void RewriteInstance::discoverFileObjects() {
static bool PrintedWarning = false;
if (!PrintedWarning) {
PrintedWarning = true;
- errs() << "BOLT-WARNING: split function detected on input : "
- << SymName;
+ BC->errs() << "BOLT-WARNING: split function detected on input : "
+ << SymName;
if (BC->HasRelocations)
- errs() << ". The support is limited in relocation mode\n";
+ BC->errs() << ". The support is limited in relocation mode\n";
else
- errs() << '\n';
+ BC->errs() << '\n';
}
BC->HasSplitFunctions = true;
BF->IsFragment = true;
@@ -1222,16 +1239,16 @@ void RewriteInstance::discoverFileObjects() {
BF = BC->getBinaryFunctionContainingAddress(Address);
if (BF) {
- errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address) << ", 0x"
- << Twine::utohexstr(Address + FDE->getAddressRange())
- << ") conflicts with function " << *BF << '\n';
+ BC->errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address)
+ << ", 0x" << Twine::utohexstr(Address + FDE->getAddressRange())
+ << ") conflicts with function " << *BF << '\n';
continue;
}
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address) << ", 0x"
- << Twine::utohexstr(Address + FDE->getAddressRange())
- << ") has no corresponding symbol table entry\n";
+ BC->errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address)
+ << ", 0x" << Twine::utohexstr(Address + FDE->getAddressRange())
+ << ") has no corresponding symbol table entry\n";
ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address);
assert(Section && "cannot get section for address from FDE");
@@ -1283,7 +1300,8 @@ void RewriteInstance::discoverFileObjects() {
/*UseMaxSize*/ true);
if (BF) {
assert(Rel.isRelative() && "Expected relative relocation for island");
- BF->markIslandDynamicRelocationAtAddress(RelAddress);
+ BC->logBOLTErrorsAndQuitOnFatal(
+ BF->markIslandDynamicRelocationAtAddress(RelAddress));
}
}
}
@@ -1395,23 +1413,24 @@ void RewriteInstance::registerFragments() {
}
if (!BD) {
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: parent function not found for " << Name << "\n";
+ BC->outs() << "BOLT-INFO: parent function not found for " << Name
+ << "\n";
continue;
}
const uint64_t Address = BD->getAddress();
BinaryFunction *BF = BC->getBinaryFunctionAtAddress(Address);
if (!BF) {
if (opts::Verbosity >= 1)
- outs() << formatv("BOLT-INFO: parent function not found at {0:x}\n",
- Address);
+ BC->outs() << formatv(
+ "BOLT-INFO: parent function not found at {0:x}\n", Address);
continue;
}
BC->registerFragment(Function, *BF);
++ParentsFound;
}
if (!ParentsFound) {
- errs() << "BOLT-ERROR: parent function not found for " << Function
- << '\n';
+ BC->errs() << "BOLT-ERROR: parent function not found for " << Function
+ << '\n';
exit(1);
}
}
@@ -1449,7 +1468,7 @@ void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,
// IFUNC trampoline without symbol
BinaryFunction *TargetBF = BC->getBinaryFunctionAtAddress(Rel->Addend);
if (!TargetBF) {
- errs()
+ BC->errs()
<< "BOLT-WARNING: Expected BF to be presented as IFUNC resolver at "
<< Twine::utohexstr(Rel->Addend) << ", skipping\n";
return;
@@ -1483,8 +1502,9 @@ void RewriteInstance::disassemblePLTInstruction(const BinarySection &Section,
if (!BC->DisAsm->getInstruction(Instruction, InstrSize,
PLTData.slice(InstrOffset), InstrAddr,
nulls())) {
- errs() << "BOLT-ERROR: unable to disassemble instruction in PLT section "
- << Section.getName() << formatv(" at offset {0:x}\n", InstrOffset);
+ BC->errs()
+ << "BOLT-ERROR: unable to disassemble instruction in PLT section "
+ << Section.getName() << formatv(" at offset {0:x}\n", InstrOffset);
exit(1);
}
}
@@ -1546,9 +1566,10 @@ void RewriteInstance::disassemblePLTSectionRISCV(BinarySection &Section) {
if (!BC->DisAsm->getInstruction(Instruction, InstrSize,
PLTData.slice(InstrOffset), InstrAddr,
nulls())) {
- errs() << "BOLT-ERROR: unable to disassemble instruction in PLT section "
- << Section.getName() << " at offset 0x"
- << Twine::utohexstr(InstrOffset) << '\n';
+ BC->errs()
+ << "BOLT-ERROR: unable to disassemble instruction in PLT section "
+ << Section.getName() << " at offset 0x"
+ << Twine::utohexstr(InstrOffset) << '\n';
exit(1);
}
};
@@ -1606,8 +1627,8 @@ void RewriteInstance::disassemblePLTSectionX86(BinarySection &Section,
if (!BC->MIB->evaluateMemOperandTarget(Instruction, TargetAddress,
SectionAddress + InstrOffset,
InstrSize)) {
- errs() << "BOLT-ERROR: error evaluating PLT instruction at offset 0x"
- << Twine::utohexstr(SectionAddress + InstrOffset) << '\n';
+ BC->errs() << "BOLT-ERROR: error evaluating PLT instruction at offset 0x"
+ << Twine::utohexstr(SectionAddress + InstrOffset) << '\n';
exit(1);
}
@@ -1714,8 +1735,8 @@ void RewriteInstance::adjustFunctionBoundaries() {
const uint64_t MaxSize = NextObjectAddress - Function.getAddress();
if (MaxSize < Function.getSize()) {
- errs() << "BOLT-ERROR: symbol seen in the middle of the function "
- << Function << ". Skipping.\n";
+ BC->errs() << "BOLT-ERROR: symbol seen in the middle of the function "
+ << Function << ". Skipping.\n";
Function.setSimple(false);
Function.setMaxSize(Function.getSize());
continue;
@@ -1725,8 +1746,8 @@ void RewriteInstance::adjustFunctionBoundaries() {
// Some assembly functions have their size set to 0, use the max
// size as their real size.
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: setting size of function " << Function << " to "
- << Function.getMaxSize() << " (was 0)\n";
+ BC->outs() << "BOLT-INFO: setting size of function " << Function
+ << " to " << Function.getMaxSize() << " (was 0)\n";
Function.setSize(Function.getMaxSize());
}
}
@@ -1812,8 +1833,8 @@ Error RewriteInstance::readSpecialSections() {
markGnuRelroSections();
if (HasDebugInfo && !opts::UpdateDebugSections && !opts::AggregateOnly) {
- errs() << "BOLT-WARNING: debug info will be stripped from the binary. "
- "Use -update-debug-sections to keep it.\n";
+ BC->errs() << "BOLT-WARNING: debug info will be stripped from the binary. "
+ "Use -update-debug-sections to keep it.\n";
}
HasTextRelocations = (bool)BC->getUniqueSectionByName(".rela.text");
@@ -1825,22 +1846,23 @@ Error RewriteInstance::readSpecialSections() {
BC->getUniqueSectionByName(BoltAddressTranslation::SECTION_NAME)) {
// Do not read BAT when plotting a heatmap
if (!opts::HeatmapMode) {
- if (std::error_code EC = BAT->parse(BATSec->getContents())) {
- errs() << "BOLT-ERROR: failed to parse BOLT address translation "
- "table.\n";
+ if (std::error_code EC = BAT->parse(BC->outs(), BATSec->getContents())) {
+ BC->errs() << "BOLT-ERROR: failed to parse BOLT address translation "
+ "table.\n";
exit(1);
}
}
}
if (opts::PrintSections) {
- outs() << "BOLT-INFO: Sections from original binary:\n";
- BC->printSections(outs());
+ BC->outs() << "BOLT-INFO: Sections from original binary:\n";
+ BC->printSections(BC->outs());
}
if (opts::RelocationMode == cl::BOU_TRUE && !HasTextRelocations) {
- errs() << "BOLT-ERROR: relocations against code are missing from the input "
- "file. Cannot proceed in relocations mode (-relocs).\n";
+ BC->errs()
+ << "BOLT-ERROR: relocations against code are missing from the input "
+ "file. Cannot proceed in relocations mode (-relocs).\n";
exit(1);
}
@@ -1848,15 +1870,16 @@ Error RewriteInstance::readSpecialSections() {
HasTextRelocations && (opts::RelocationMode != cl::BOU_FALSE);
if (BC->IsLinuxKernel && BC->HasRelocations) {
- outs() << "BOLT-INFO: disabling relocation mode for Linux kernel\n";
+ BC->outs() << "BOLT-INFO: disabling relocation mode for Linux kernel\n";
BC->HasRelocations = false;
}
BC->IsStripped = !HasSymbolTable;
if (BC->IsStripped && !opts::AllowStripped) {
- errs() << "BOLT-ERROR: stripped binaries are not supported. If you know "
- "what you're doing, use --allow-stripped to proceed";
+ BC->errs()
+ << "BOLT-ERROR: stripped binaries are not supported. If you know "
+ "what you're doing, use --allow-stripped to proceed";
exit(1);
}
@@ -1865,14 +1888,14 @@ Error RewriteInstance::readSpecialSections() {
BC->HasRelocations = false;
if (BC->HasRelocations)
- outs() << "BOLT-INFO: enabling " << (opts::StrictMode ? "strict " : "")
- << "relocation mode\n";
+ BC->outs() << "BOLT-INFO: enabling " << (opts::StrictMode ? "strict " : "")
+ << "relocation mode\n";
// Read EH frame for function boundaries info.
Expected<const DWARFDebugFrame *> EHFrameOrError = BC->DwCtx->getEHFrame();
if (!EHFrameOrError)
report_error("expected valid eh_frame section", EHFrameOrError.takeError());
- CFIRdWrt.reset(new CFIReaderWriter(*EHFrameOrError.get()));
+ CFIRdWrt.reset(new CFIReaderWriter(*BC, *EHFrameOrError.get()));
// Parse build-id
parseBuildID();
@@ -1885,63 +1908,68 @@ Error RewriteInstance::readSpecialSections() {
void RewriteInstance::adjustCommandLineOptions() {
if (BC->isAArch64() && !BC->HasRelocations)
- errs() << "BOLT-WARNING: non-relocation mode for AArch64 is not fully "
- "supported\n";
+ BC->errs() << "BOLT-WARNING: non-relocation mode for AArch64 is not fully "
+ "supported\n";
if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary())
RtLibrary->adjustCommandLineOptions(*BC);
if (opts::AlignMacroOpFusion != MFT_NONE && !BC->isX86()) {
- outs() << "BOLT-INFO: disabling -align-macro-fusion on non-x86 platform\n";
+ BC->outs()
+ << "BOLT-INFO: disabling -align-macro-fusion on non-x86 platform\n";
opts::AlignMacroOpFusion = MFT_NONE;
}
if (BC->isX86() && BC->MAB->allowAutoPadding()) {
if (!BC->HasRelocations) {
- errs() << "BOLT-ERROR: cannot apply mitigations for Intel JCC erratum in "
- "non-relocation mode\n";
+ BC->errs()
+ << "BOLT-ERROR: cannot apply mitigations for Intel JCC erratum in "
+ "non-relocation mode\n";
exit(1);
}
- outs() << "BOLT-WARNING: using mitigation for Intel JCC erratum, layout "
- "may take several minutes\n";
+ BC->outs()
+ << "BOLT-WARNING: using mitigation for Intel JCC erratum, layout "
+ "may take several minutes\n";
opts::AlignMacroOpFusion = MFT_NONE;
}
if (opts::AlignMacroOpFusion != MFT_NONE && !BC->HasRelocations) {
- outs() << "BOLT-INFO: disabling -align-macro-fusion in non-relocation "
- "mode\n";
+ BC->outs() << "BOLT-INFO: disabling -align-macro-fusion in non-relocation "
+ "mode\n";
opts::AlignMacroOpFusion = MFT_NONE;
}
if (opts::SplitEH && !BC->HasRelocations) {
- errs() << "BOLT-WARNING: disabling -split-eh in non-relocation mode\n";
+ BC->errs() << "BOLT-WARNING: disabling -split-eh in non-relocation mode\n";
opts::SplitEH = false;
}
if (opts::StrictMode && !BC->HasRelocations) {
- errs() << "BOLT-WARNING: disabling strict mode (-strict) in non-relocation "
- "mode\n";
+ BC->errs()
+ << "BOLT-WARNING: disabling strict mode (-strict) in non-relocation "
+ "mode\n";
opts::StrictMode = false;
}
if (BC->HasRelocations && opts::AggregateOnly &&
!opts::StrictMode.getNumOccurrences()) {
- outs() << "BOLT-INFO: enabling strict relocation mode for aggregation "
- "purposes\n";
+ BC->outs() << "BOLT-INFO: enabling strict relocation mode for aggregation "
+ "purposes\n";
opts::StrictMode = true;
}
if (BC->isX86() && BC->HasRelocations &&
opts::AlignMacroOpFusion == MFT_HOT && !ProfileReader) {
- outs() << "BOLT-INFO: enabling -align-macro-fusion=all since no profile "
- "was specified\n";
+ BC->outs()
+ << "BOLT-INFO: enabling -align-macro-fusion=all since no profile "
+ "was specified\n";
opts::AlignMacroOpFusion = MFT_ALL;
}
if (!BC->HasRelocations &&
opts::ReorderFunctions != ReorderFunctions::RT_NONE) {
- errs() << "BOLT-ERROR: function reordering only works when "
- << "relocations are enabled\n";
+ BC->errs() << "BOLT-ERROR: function reordering only works when "
+ << "relocations are enabled\n";
exit(1);
}
@@ -1950,7 +1978,7 @@ void RewriteInstance::adjustCommandLineOptions() {
!opts::HotText.getNumOccurrences())) {
opts::HotText = true;
} else if (opts::HotText && !BC->HasRelocations) {
- errs() << "BOLT-WARNING: hot text is disabled in non-relocation mode\n";
+ BC->errs() << "BOLT-WARNING: hot text is disabled in non-relocation mode\n";
opts::HotText = false;
}
@@ -1961,12 +1989,13 @@ void RewriteInstance::adjustCommandLineOptions() {
}
if (opts::UseOldText && !BC->OldTextSectionAddress) {
- errs() << "BOLT-WARNING: cannot use old .text as the section was not found"
- "\n";
+ BC->errs()
+ << "BOLT-WARNING: cannot use old .text as the section was not found"
+ "\n";
opts::UseOldText = false;
}
if (opts::UseOldText && !BC->HasRelocations) {
- errs() << "BOLT-WARNING: cannot use old .text in non-relocation mode\n";
+ BC->errs() << "BOLT-WARNING: cannot use old .text in non-relocation mode\n";
opts::UseOldText = false;
}
@@ -1981,23 +2010,25 @@ void RewriteInstance::adjustCommandLineOptions() {
opts::Lite = true;
if (opts::Lite && opts::UseOldText) {
- errs() << "BOLT-WARNING: cannot combine -lite with -use-old-text. "
- "Disabling -use-old-text.\n";
+ BC->errs() << "BOLT-WARNING: cannot combine -lite with -use-old-text. "
+ "Disabling -use-old-text.\n";
opts::UseOldText = false;
}
if (opts::Lite && opts::StrictMode) {
- errs() << "BOLT-ERROR: -strict and -lite cannot be used at the same time\n";
+ BC->errs()
+ << "BOLT-ERROR: -strict and -lite cannot be used at the same time\n";
exit(1);
}
if (opts::Lite)
- outs() << "BOLT-INFO: enabling lite mode\n";
+ BC->outs() << "BOLT-INFO: enabling lite mode\n";
if (!opts::SaveProfile.empty() && BAT->enabledFor(InputFile)) {
- errs() << "BOLT-ERROR: unable to save profile in YAML format for input "
- "file processed by BOLT. Please remove -w option and use branch "
- "profile.\n";
+ BC->errs()
+ << "BOLT-ERROR: unable to save profile in YAML format for input "
+ "file processed by BOLT. Please remove -w option and use branch "
+ "profile.\n";
exit(1);
}
}
@@ -2252,8 +2283,8 @@ void RewriteInstance::processRelocations() {
}
if (NumFailedRelocations)
- errs() << "BOLT-WARNING: Failed to analyze " << NumFailedRelocations
- << " relocations\n";
+ BC->errs() << "BOLT-WARNING: Failed to analyze " << NumFailedRelocations
+ << " relocations\n";
}
void RewriteInstance::readDynamicRelocations(const SectionRef &Section,
@@ -2497,8 +2528,8 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,
assert(ContainingBF && "cannot find function for address in code");
if (!IsAArch64 && !ContainingBF->containsAddress(Rel.getOffset())) {
if (opts::Verbosity >= 1)
- outs() << formatv("BOLT-INFO: {0} has relocations in padding area\n",
- *ContainingBF);
+ BC->outs() << formatv(
+ "BOLT-INFO: {0} has relocations in padding area\n", *ContainingBF);
ContainingBF->setSize(ContainingBF->getMaxSize());
ContainingBF->setSimple(false);
return;
@@ -2593,12 +2624,13 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,
if (BF != ReferencedBF) {
// It's possible we are referencing a function without referencing any
// code, e.g. when taking a bitmask action on a function address.
- errs() << "BOLT-WARNING: non-standard function reference (e.g. bitmask)"
- << formatv(" detected against function {0} from ", *BF);
+ BC->errs()
+ << "BOLT-WARNING: non-standard function reference (e.g. bitmask)"
+ << formatv(" detected against function {0} from ", *BF);
if (IsFromCode)
- errs() << formatv("function {0}\n", *ContainingBF);
+ BC->errs() << formatv("function {0}\n", *ContainingBF);
else
- errs() << formatv("data section at {0:x}\n", Rel.getOffset());
+ BC->errs() << formatv("data section at {0:x}\n", Rel.getOffset());
LLVM_DEBUG(printRelocationInfo(Rel, SymbolName, SymbolAddress, Addend,
ExtractedValue));
ReferencedBF = BF;
@@ -2628,10 +2660,11 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,
llvm::make_second_range(ContainingBF->Relocations), CheckReloc);
if (Found) {
- errs() << "BOLT-WARNING: detected possible compiler de-virtualization "
- "bug: -1 addend used with non-pc-relative relocation against "
- << formatv("function {0} in function {1}\n", *RogueBF,
- *ContainingBF);
+ BC->errs()
+ << "BOLT-WARNING: detected possible compiler de-virtualization "
+ "bug: -1 addend used with non-pc-relative relocation against "
+ << formatv("function {0} in function {1}\n", *RogueBF,
+ *ContainingBF);
return;
}
}
@@ -2681,9 +2714,10 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,
}
if (opts::Verbosity > 1 &&
BinarySection(*BC, RelocatedSection).isWritable())
- errs() << "BOLT-WARNING: writable reference into the middle of the "
- << formatv("function {0} detected at address {1:x}\n",
- *ReferencedBF, Rel.getOffset());
+ BC->errs()
+ << "BOLT-WARNING: writable reference into the middle of the "
+ << formatv("function {0} detected at address {1:x}\n",
+ *ReferencedBF, Rel.getOffset());
}
SymbolAddress = Address;
Addend = 0;
@@ -2825,8 +2859,9 @@ void RewriteInstance::selectFunctionsToProcess() {
if ((!opts::ForceFunctionNames.empty() ||
!opts::ForceFunctionNamesNR.empty()) &&
!opts::SkipFunctionNames.empty()) {
- errs() << "BOLT-ERROR: cannot select functions to process and skip at the "
- "same time. Please use only one type of selection.\n";
+ BC->errs()
+ << "BOLT-ERROR: cannot select functions to process and skip at the "
+ "same time. Please use only one type of selection.\n";
exit(1);
}
@@ -2850,8 +2885,8 @@ void RewriteInstance::selectFunctionsToProcess() {
if (Index)
--Index;
LiteThresholdExecCount = TopFunctions[Index]->getKnownExecutionCount();
- outs() << "BOLT-INFO: limiting processing to functions with at least "
- << LiteThresholdExecCount << " invocations\n";
+ BC->outs() << "BOLT-INFO: limiting processing to functions with at least "
+ << LiteThresholdExecCount << " invocations\n";
}
LiteThresholdExecCount = std::max(
LiteThresholdExecCount, static_cast<uint64_t>(opts::LiteThresholdCount));
@@ -2859,8 +2894,10 @@ void RewriteInstance::selectFunctionsToProcess() {
StringSet<> ReorderFunctionsUserSet;
StringSet<> ReorderFunctionsLTOCommonSet;
if (opts::ReorderFunctions == ReorderFunctions::RT_USER) {
- for (const std::string &Function :
- ReorderFunctions::readFunctionOrderFile()) {
+ std::vector<std::string> FunctionNames;
+ BC->logBOLTErrorsAndQuitOnFatal(
+ ReorderFunctions::readFunctionOrderFile(FunctionNames));
+ for (const std::string &Function : FunctionNames) {
ReorderFunctionsUserSet.insert(Function);
if (std::optional<StringRef> LTOCommonName = getLTOCommonName(Function))
ReorderFunctionsLTOCommonSet.insert(*LTOCommonName);
@@ -2936,15 +2973,15 @@ void RewriteInstance::selectFunctionsToProcess() {
if (!shouldProcess(Function)) {
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: skipping processing " << Function
- << " per user request\n";
+ BC->outs() << "BOLT-INFO: skipping processing " << Function
+ << " per user request\n";
}
Function.setIgnored();
} else {
++NumFunctionsToProcess;
if (opts::MaxFunctions.getNumOccurrences() &&
NumFunctionsToProcess == opts::MaxFunctions)
- outs() << "BOLT-INFO: processing ending on " << Function << '\n';
+ BC->outs() << "BOLT-INFO: processing ending on " << Function << '\n';
}
}
@@ -2963,8 +3000,8 @@ void RewriteInstance::selectFunctionsToProcess() {
if (mustSkip(Function)) {
for (BinaryFunction *Parent : Function.ParentFragments) {
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: skipping processing " << *Parent
- << " together with fragment function\n";
+ BC->outs() << "BOLT-INFO: skipping processing " << *Parent
+ << " together with fragment function\n";
}
Parent->setIgnored();
--NumFunctionsToProcess;
@@ -2979,18 +3016,18 @@ void RewriteInstance::selectFunctionsToProcess() {
});
if (IgnoredParent) {
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: skipping processing " << Function
- << " together with parent function\n";
+ BC->outs() << "BOLT-INFO: skipping processing " << Function
+ << " together with parent function\n";
}
Function.setIgnored();
} else {
++NumFunctionsToProcess;
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: processing " << Function
- << " as a sibling of non-ignored function\n";
+ BC->outs() << "BOLT-INFO: processing " << Function
+ << " as a sibling of non-ignored function\n";
}
if (opts::MaxFunctions && NumFunctionsToProcess == opts::MaxFunctions)
- outs() << "BOLT-INFO: processing ending on " << Function << '\n';
+ BC->outs() << "BOLT-INFO: processing ending on " << Function << '\n';
}
}
}
@@ -3011,12 +3048,12 @@ void RewriteInstance::preprocessProfileData() {
NamedRegionTimer T("preprocessprofile", "pre-process profile data",
TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
- outs() << "BOLT-INFO: pre-processing profile using "
- << ProfileReader->getReaderName() << '\n';
+ BC->outs() << "BOLT-INFO: pre-processing profile using "
+ << ProfileReader->getReaderName() << '\n';
if (BAT->enabledFor(InputFile)) {
- outs() << "BOLT-INFO: profile collection done on a binary already "
- "processed by BOLT\n";
+ BC->outs() << "BOLT-INFO: profile collection done on a binary already "
+ "processed by BOLT\n";
ProfileReader->setBAT(&*BAT);
}
@@ -3024,10 +3061,11 @@ void RewriteInstance::preprocessProfileData() {
report_error("cannot pre-process profile", std::move(E));
if (!BC->hasSymbolsWithFileName() && ProfileReader->hasLocalsWithFileName()) {
- errs() << "BOLT-ERROR: input binary does not have local file symbols "
- "but profile data includes function names with embedded file "
- "names. It appears that the input binary was stripped while a "
- "profiled binary was not\n";
+ BC->errs()
+ << "BOLT-ERROR: input binary does not have local file symbols "
+ "but profile data includes function names with embedded file "
+ "names. It appears that the input binary was stripped while a "
+ "profiled binary was not\n";
exit(1);
}
}
@@ -3080,7 +3118,7 @@ void RewriteInstance::processProfileData() {
if (Function.empty())
continue;
- Function.print(outs(), "after attaching profile");
+ Function.print(BC->outs(), "after attaching profile");
}
}
@@ -3109,8 +3147,8 @@ void RewriteInstance::disassembleFunctions() {
ErrorOr<ArrayRef<uint8_t>> FunctionData = Function.getData();
if (!FunctionData) {
- errs() << "BOLT-ERROR: corresponding section is non-executable or "
- << "empty for function " << Function << '\n';
+ BC->errs() << "BOLT-ERROR: corresponding section is non-executable or "
+ << "empty for function " << Function << '\n';
exit(1);
}
@@ -3133,21 +3171,32 @@ void RewriteInstance::disassembleFunctions() {
continue;
}
- if (!Function.disassemble()) {
- if (opts::processAllFunctions())
- BC->exitWithBugReport("function cannot be properly disassembled. "
- "Unable to continue in relocation mode.",
- Function);
+ bool DisasmFailed{false};
+ handleAllErrors(Function.disassemble(), [&](const BOLTError &E) {
+ DisasmFailed = true;
+ if (E.isFatal()) {
+ E.log(BC->errs());
+ exit(1);
+ }
+ if (opts::processAllFunctions()) {
+ BC->errs() << BC->generateBugReportMessage(
+ "function cannot be properly disassembled. "
+ "Unable to continue in relocation mode.",
+ Function);
+ exit(1);
+ }
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: could not disassemble function " << Function
- << ". Will ignore.\n";
+ BC->outs() << "BOLT-INFO: could not disassemble function " << Function
+ << ". Will ignore.\n";
// Forcefully ignore the function.
Function.setIgnored();
+ });
+
+ if (DisasmFailed)
continue;
- }
if (opts::PrintAll || opts::PrintDisasm)
- Function.print(outs(), "after disassembly");
+ Function.print(BC->outs(), "after disassembly");
}
BC->processInterproceduralReferences();
@@ -3182,10 +3231,12 @@ void RewriteInstance::disassembleFunctions() {
// Fill in CFI information for this function
if (!Function.trapsOnEntry() && !CFIRdWrt->fillCFIInfoFor(Function)) {
if (BC->HasRelocations) {
- BC->exitWithBugReport("unable to fill CFI.", Function);
+ BC->errs() << BC->generateBugReportMessage("unable to fill CFI.",
+ Function);
+ exit(1);
} else {
- errs() << "BOLT-WARNING: unable to fill CFI for function " << Function
- << ". Skipping.\n";
+ BC->errs() << "BOLT-WARNING: unable to fill CFI for function "
+ << Function << ". Skipping.\n";
Function.setSimple(false);
continue;
}
@@ -3199,7 +3250,8 @@ void RewriteInstance::disassembleFunctions() {
check_error(LSDASection.getError(), "failed to get LSDA section");
ArrayRef<uint8_t> LSDAData = ArrayRef<uint8_t>(
LSDASection->getData(), LSDASection->getContents().size());
- Function.parseLSDA(LSDAData, LSDASection->getAddress());
+ BC->logBOLTErrorsAndQuitOnFatal(
+ Function.parseLSDA(LSDAData, LSDASection->getAddress()));
}
}
}
@@ -3214,12 +3266,21 @@ void RewriteInstance::buildFunctionsCFG() {
ParallelUtilities::WorkFuncWithAllocTy WorkFun =
[&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId) {
- if (!BF.buildCFG(AllocId))
+ bool HadErrors{false};
+ handleAllErrors(BF.buildCFG(AllocId), [&](const BOLTError &E) {
+ if (!E.getMessage().empty())
+ E.log(BC->errs());
+ if (E.isFatal())
+ exit(1);
+ HadErrors = true;
+ });
+
+ if (HadErrors)
return;
if (opts::PrintAll) {
auto L = BC->scopeLock();
- BF.print(outs(), "while building cfg");
+ BF.print(BC->outs(), "while building cfg");
}
};
@@ -3258,14 +3319,14 @@ void RewriteInstance::postProcessFunctions() {
Function.postProcessCFG();
if (opts::PrintAll || opts::PrintCFG)
- Function.print(outs(), "after building cfg");
+ Function.print(BC->outs(), "after building cfg");
if (opts::DumpDotAll)
Function.dumpGraphForPass("00_build-cfg");
if (opts::PrintLoopInfo) {
Function.calculateLoopInfo();
- Function.printLoopInfo(outs());
+ Function.printLoopInfo(BC->outs());
}
BC->TotalScore += Function.getFunctionScore();
@@ -3273,15 +3334,15 @@ void RewriteInstance::postProcessFunctions() {
}
if (opts::PrintGlobals) {
- outs() << "BOLT-INFO: Global symbols:\n";
- BC->printGlobalSymbols(outs());
+ BC->outs() << "BOLT-INFO: Global symbols:\n";
+ BC->printGlobalSymbols(BC->outs());
}
}
void RewriteInstance::runOptimizationPasses() {
NamedRegionTimer T("runOptimizationPasses", "run optimization passes",
TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
- BinaryFunctionPassManager::runAllPasses(*BC);
+ BC->logBOLTErrorsAndQuitOnFatal(BinaryFunctionPassManager::runAllPasses(*BC));
}
void RewriteInstance::preregisterSections() {
@@ -3331,7 +3392,7 @@ void RewriteInstance::emitAndLink() {
Streamer->finish();
if (Streamer->getContext().hadError()) {
- errs() << "BOLT-ERROR: Emission failed.\n";
+ BC->errs() << "BOLT-ERROR: Emission failed.\n";
exit(1);
}
@@ -3342,9 +3403,10 @@ void RewriteInstance::emitAndLink() {
raw_fd_ostream FOS(OutObjectPath, EC);
check_error(EC, "cannot create output object file");
FOS << ObjectBuffer;
- outs() << "BOLT-INFO: intermediary output object file saved for debugging "
- "purposes: "
- << OutObjectPath << "\n";
+ BC->outs()
+ << "BOLT-INFO: intermediary output object file saved for debugging "
+ "purposes: "
+ << OutObjectPath << "\n";
}
ErrorOr<BinarySection &> TextSection =
@@ -3409,8 +3471,8 @@ void RewriteInstance::emitAndLink() {
}
if (opts::PrintCacheMetrics) {
- outs() << "BOLT-INFO: cache metrics after emitting functions:\n";
- CacheMetrics::printAll(BC->getSortedFunctions());
+ BC->outs() << "BOLT-INFO: cache metrics after emitting functions:\n";
+ CacheMetrics::printAll(BC->outs(), BC->getSortedFunctions());
}
}
@@ -3576,14 +3638,15 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
allocateAt(BC->OldTextSectionAddress) - BC->OldTextSectionAddress;
if (CodeSize <= BC->OldTextSectionSize) {
- outs() << "BOLT-INFO: using original .text for new code with 0x"
- << Twine::utohexstr(opts::AlignText) << " alignment\n";
+ BC->outs() << "BOLT-INFO: using original .text for new code with 0x"
+ << Twine::utohexstr(opts::AlignText) << " alignment\n";
AllocationDone = true;
} else {
- errs() << "BOLT-WARNING: original .text too small to fit the new code"
- << " using 0x" << Twine::utohexstr(opts::AlignText)
- << " alignment. " << CodeSize << " bytes needed, have "
- << BC->OldTextSectionSize << " bytes available.\n";
+ BC->errs()
+ << "BOLT-WARNING: original .text too small to fit the new code"
+ << " using 0x" << Twine::utohexstr(opts::AlignText)
+ << " alignment. " << CodeSize << " bytes needed, have "
+ << BC->OldTextSectionSize << " bytes available.\n";
opts::UseOldText = false;
}
}
@@ -3604,9 +3667,9 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
// Check if we need to insert a padding section for hot text.
if (PaddingSize && !opts::UseOldText)
- outs() << "BOLT-INFO: padding code to 0x"
- << Twine::utohexstr(NextAvailableAddress)
- << " to accommodate hot text\n";
+ BC->outs() << "BOLT-INFO: padding code to 0x"
+ << Twine::utohexstr(NextAvailableAddress)
+ << " to accommodate hot text\n";
return;
}
@@ -3814,7 +3877,7 @@ void RewriteInstance::patchELFPHDRTable() {
assert(!PHDRTableAddress && "unexpected address for program header table");
PHDRTableOffset = Obj.getHeader().e_phoff;
if (NewWritableSegmentSize) {
- errs() << "Unable to add writable segment with UseGnuStack option\n";
+ BC->errs() << "Unable to add writable segment with UseGnuStack option\n";
exit(1);
}
}
@@ -4114,7 +4177,8 @@ void RewriteInstance::encodeBATSection() {
copyByteArray(BoltInfo), BoltInfo.size(),
/*Alignment=*/1,
/*IsReadOnly=*/true, ELF::SHT_NOTE);
- outs() << "BOLT-INFO: BAT section size (bytes): " << BoltInfo.size() << '\n';
+ BC->outs() << "BOLT-INFO: BAT section size (bytes): " << BoltInfo.size()
+ << '\n';
}
template <typename ELFShdrTy>
@@ -4175,14 +4239,14 @@ RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File,
if (Section.hasSectionRef() || Section.isAnonymous()) {
if (opts::Verbosity)
- outs() << "BOLT-INFO: not writing section header for section "
- << Section.getOutputName() << '\n';
+ BC->outs() << "BOLT-INFO: not writing section header for section "
+ << Section.getOutputName() << '\n';
continue;
}
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: writing section header for "
- << Section.getOutputName() << '\n';
+ BC->outs() << "BOLT-INFO: writing section header for "
+ << Section.getOutputName() << '\n';
ELFShdrTy NewSection;
NewSection.sh_type = ELF::SHT_PROGBITS;
NewSection.sh_addr = Section.getOutputAddress();
@@ -4216,8 +4280,8 @@ RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File,
if (PrevSection &&
PrevSection->sh_offset + PrevSection->sh_size > Section.sh_offset) {
if (opts::Verbosity > 1) {
- outs() << "BOLT-INFO: adjusting size for section "
- << PrevBinSec->getOutputName() << '\n';
+ BC->outs() << "BOLT-INFO: adjusting size for section "
+ << PrevBinSec->getOutputName() << '\n';
}
PrevSection->sh_size = Section.sh_offset - PrevSection->sh_offset;
}
@@ -4264,8 +4328,8 @@ RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File,
continue;
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: writing section header for "
- << Section.getOutputName() << '\n';
+ BC->outs() << "BOLT-INFO: writing section header for "
+ << Section.getOutputName() << '\n';
ELFShdrTy NewSection;
NewSection.sh_type = Section.getELFType();
@@ -4663,8 +4727,8 @@ void RewriteInstance::updateELFSymbolTable(
std::optional<uint64_t> Value = std::nullopt) {
NewSymbol.st_value = Value ? *Value : getNewValueForSymbol(Name);
NewSymbol.st_shndx = ELF::SHN_ABS;
- outs() << "BOLT-INFO: setting " << Name << " to 0x"
- << Twine::utohexstr(NewSymbol.st_value) << '\n';
+ BC->outs() << "BOLT-INFO: setting " << Name << " to 0x"
+ << Twine::utohexstr(NewSymbol.st_value) << '\n';
};
if (opts::HotText &&
@@ -4739,8 +4803,8 @@ void RewriteInstance::updateELFSymbolTable(
Symbol.st_other = 0;
Symbol.setBindingAndType(ELF::STB_WEAK, ELF::STT_NOTYPE);
- outs() << "BOLT-INFO: setting " << Name << " to 0x"
- << Twine::utohexstr(Symbol.st_value) << '\n';
+ BC->outs() << "BOLT-INFO: setting " << Name << " to 0x"
+ << Twine::utohexstr(Symbol.st_value) << '\n';
Symbols.emplace_back(Symbol);
};
@@ -4836,7 +4900,7 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
}
}
if (!SymTabSection) {
- errs() << "BOLT-WARNING: no symbol table found\n";
+ BC->errs() << "BOLT-WARNING: no symbol table found\n";
return;
}
@@ -4939,7 +5003,7 @@ void RewriteInstance::patchELFAllocatableRelrSection(
auto WriteRelr = [&](uint64_t Value) {
if (RelrDynOffset + DynamicRelrEntrySize > RelrDynEndOffset) {
- errs() << "BOLT-ERROR: Offset overflow for relr.dyn section\n";
+ BC->errs() << "BOLT-ERROR: Offset overflow for relr.dyn section\n";
exit(1);
}
@@ -5051,12 +5115,12 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
const uint64_t &EndOffset =
IsJmpRel ? RelPltEndOffset : RelDynEndOffset;
if (!Offset || !EndOffset) {
- errs() << "BOLT-ERROR: Invalid offsets for dynamic relocation\n";
+ BC->errs() << "BOLT-ERROR: Invalid offsets for dynamic relocation\n";
exit(1);
}
if (Offset + sizeof(NewRelA) > EndOffset) {
- errs() << "BOLT-ERROR: Offset overflow for dynamic relocation\n";
+ BC->errs() << "BOLT-ERROR: Offset overflow for dynamic relocation\n";
exit(1);
}
@@ -5105,7 +5169,7 @@ void RewriteInstance::patchELFGOT(ELFObjectFile<ELFT> *File) {
}
if (!GOTSection.getObject()) {
if (!BC->IsStaticExecutable)
- errs() << "BOLT-INFO: no .got section found\n";
+ BC->errs() << "BOLT-INFO: no .got section found\n";
return;
}
@@ -5209,9 +5273,10 @@ void RewriteInstance::patchELFDynamic(ELFObjectFile<ELFT> *File) {
}
if (BC->RequiresZNow && !ZNowSet) {
- errs() << "BOLT-ERROR: output binary requires immediate relocation "
- "processing which depends on DT_FLAGS or DT_FLAGS_1 presence in "
- ".dynamic. Please re-link the binary with -znow.\n";
+ BC->errs()
+ << "BOLT-ERROR: output binary requires immediate relocation "
+ "processing which depends on DT_FLAGS or DT_FLAGS_1 presence in "
+ ".dynamic. Please re-link the binary with -znow.\n";
exit(1);
}
}
@@ -5233,7 +5298,7 @@ Error RewriteInstance::readELFDynamic(ELFObjectFile<ELFT> *File) {
}
if (!DynamicPhdr) {
- outs() << "BOLT-INFO: static input executable detected\n";
+ BC->outs() << "BOLT-INFO: static input executable detected\n";
// TODO: static PIE executable might have dynamic header
BC->IsStaticExecutable = true;
return Error::success();
@@ -5307,12 +5372,12 @@ Error RewriteInstance::readELFDynamic(ELFObjectFile<ELFT> *File) {
DynamicRelrAddress.reset();
DynamicRelrSize = 0;
} else if (!DynamicRelrEntrySize) {
- errs() << "BOLT-ERROR: expected DT_RELRENT to be presented "
- << "in DYNAMIC section\n";
+ BC->errs() << "BOLT-ERROR: expected DT_RELRENT to be presented "
+ << "in DYNAMIC section\n";
exit(1);
} else if (DynamicRelrSize % DynamicRelrEntrySize) {
- errs() << "BOLT-ERROR: expected RELR table size to be divisible "
- << "by RELR entry size\n";
+ BC->errs() << "BOLT-ERROR: expected RELR table size to be divisible "
+ << "by RELR entry size\n";
exit(1);
}
@@ -5368,11 +5433,11 @@ void RewriteInstance::rewriteFile() {
if (Function->getImageSize() > Function->getMaxSize()) {
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: new function size (0x"
- << Twine::utohexstr(Function->getImageSize())
- << ") is larger than maximum allowed size (0x"
- << Twine::utohexstr(Function->getMaxSize()) << ") for function "
- << *Function << '\n';
+ BC->errs() << "BOLT-WARNING: new function size (0x"
+ << Twine::utohexstr(Function->getImageSize())
+ << ") is larger than maximum allowed size (0x"
+ << Twine::utohexstr(Function->getMaxSize())
+ << ") for function " << *Function << '\n';
// Remove jump table sections that this function owns in non-reloc mode
// because we don't want to write them anymore.
@@ -5408,7 +5473,7 @@ void RewriteInstance::rewriteFile() {
// Overwrite function in the output file.
if (opts::Verbosity >= 2)
- outs() << "BOLT: rewriting function \"" << *Function << "\"\n";
+ BC->outs() << "BOLT: rewriting function \"" << *Function << "\"\n";
OS.pwrite(reinterpret_cast<char *>(Function->getImageAddress()),
Function->getImageSize(), Function->getFileOffset());
@@ -5428,8 +5493,8 @@ void RewriteInstance::rewriteFile() {
// Write cold part
if (opts::Verbosity >= 2) {
- outs() << formatv("BOLT: rewriting function \"{0}\" (split parts)\n",
- *Function);
+ BC->outs() << formatv("BOLT: rewriting function \"{0}\" (split parts)\n",
+ *Function);
}
for (const FunctionFragment &FF :
@@ -5441,14 +5506,15 @@ void RewriteInstance::rewriteFile() {
// Print function statistics for non-relocation mode.
if (!BC->HasRelocations) {
- outs() << "BOLT: " << CountOverwrittenFunctions << " out of "
- << BC->getBinaryFunctions().size()
- << " functions were overwritten.\n";
+ BC->outs() << "BOLT: " << CountOverwrittenFunctions << " out of "
+ << BC->getBinaryFunctions().size()
+ << " functions were overwritten.\n";
if (BC->TotalScore != 0) {
double Coverage = OverwrittenScore / (double)BC->TotalScore * 100.0;
- outs() << format("BOLT-INFO: rewritten functions cover %.2lf", Coverage)
- << "% of the execution count of simple functions of "
- "this binary\n";
+ BC->outs() << format("BOLT-INFO: rewritten functions cover %.2lf",
+ Coverage)
+ << "% of the execution count of simple functions of "
+ "this binary\n";
}
}
@@ -5476,10 +5542,11 @@ void RewriteInstance::rewriteFile() {
continue;
if (opts::Verbosity >= 1)
- outs() << "BOLT: writing new section " << Section.getName()
- << "\n data at 0x" << Twine::utohexstr(Section.getAllocAddress())
- << "\n of size " << Section.getOutputSize() << "\n at offset "
- << Section.getOutputFileOffset() << '\n';
+ BC->outs() << "BOLT: writing new section " << Section.getName()
+ << "\n data at 0x"
+ << Twine::utohexstr(Section.getAllocAddress()) << "\n of size "
+ << Section.getOutputSize() << "\n at offset "
+ << Section.getOutputFileOffset() << '\n';
OS.pwrite(reinterpret_cast<const char *>(Section.getOutputData()),
Section.getOutputSize(), Section.getOutputFileOffset());
}
@@ -5529,8 +5596,8 @@ void RewriteInstance::rewriteFile() {
patchELFSectionHeaderTable();
if (opts::PrintSections) {
- outs() << "BOLT-INFO: Sections after processing:\n";
- BC->printSections(outs());
+ BC->outs() << "BOLT-INFO: Sections after processing:\n";
+ BC->printSections(BC->outs());
}
Out->keep();
diff --git a/bolt/lib/Target/X86/X86MCSymbolizer.cpp b/bolt/lib/Target/X86/X86MCSymbolizer.cpp
index ca7fe137152f..0e0ad9270550 100644
--- a/bolt/lib/Target/X86/X86MCSymbolizer.cpp
+++ b/bolt/lib/Target/X86/X86MCSymbolizer.cpp
@@ -134,7 +134,13 @@ bool X86MCSymbolizer::tryAddingSymbolicOperand(
// a PC-relative 8-byte fixup, which is what we need to cover this. The
// only way to do this is to use the symbol name _GLOBAL_OFFSET_TABLE_.
if (Relocation::isX86GOTPC64(Relocation->Type)) {
- auto [Sym, Addend] = handleGOTPC64(*Relocation, InstAddress);
+ auto PairOrErr = handleGOTPC64(*Relocation, InstAddress);
+ if (auto E = PairOrErr.takeError()) {
+ Function.setSimple(false);
+ BC.logBOLTErrorsAndQuitOnFatal(std::move(E));
+ return false;
+ }
+ auto [Sym, Addend] = *PairOrErr;
addOperand(Sym, Addend);
return true;
}
@@ -158,14 +164,16 @@ bool X86MCSymbolizer::tryAddingSymbolicOperand(
return true;
}
-std::pair<MCSymbol *, uint64_t>
+Expected<std::pair<MCSymbol *, uint64_t>>
X86MCSymbolizer::handleGOTPC64(const Relocation &R, uint64_t InstrAddr) {
BinaryContext &BC = Function.getBinaryContext();
const BinaryData *GOTSymBD = BC.getGOTSymbol();
if (!GOTSymBD || !GOTSymBD->getAddress()) {
- errs() << "BOLT-ERROR: R_X86_GOTPC64 relocation is present but we did "
- "not detect a valid _GLOBAL_OFFSET_TABLE_ in symbol table\n";
- exit(1);
+ // This error is pretty serious but we can't kill the disassembler
+ // because of it, so don't make it fatal. Log it and warn the user.
+ return createNonFatalBOLTError(
+ "R_X86_GOTPC64 relocation is present but we did not detect "
+ "a valid _GLOBAL_OFFSET_TABLE_ in symbol table\n");
}
// R_X86_GOTPC64 are not relative to the Reloc nor end of instruction,
// but the start of the MOVABSQ instruction. So the Target Address is
diff --git a/bolt/lib/Target/X86/X86MCSymbolizer.h b/bolt/lib/Target/X86/X86MCSymbolizer.h
index 9ed18b69c74c..189941e949e3 100644
--- a/bolt/lib/Target/X86/X86MCSymbolizer.h
+++ b/bolt/lib/Target/X86/X86MCSymbolizer.h
@@ -20,8 +20,8 @@ protected:
BinaryFunction &Function;
bool CreateNewSymbols{true};
- std::pair<MCSymbol *, uint64_t> handleGOTPC64(const Relocation &R,
- uint64_t InstrAddr);
+ Expected<std::pair<MCSymbol *, uint64_t>> handleGOTPC64(const Relocation &R,
+ uint64_t InstrAddr);
public:
X86MCSymbolizer(BinaryFunction &Function, bool CreateNewSymbols = true)
diff --git a/bolt/test/X86/fatal-error.s b/bolt/test/X86/fatal-error.s
new file mode 100644
index 000000000000..312d1d47429f
--- /dev/null
+++ b/bolt/test/X86/fatal-error.s
@@ -0,0 +1,39 @@
+# Tests whether llvm-bolt will correctly exit with error code and printing
+# fatal error message in case one occurs. Here we test opening a function
+# reordering file that does not exist.
+
+# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q
+# RUN: not llvm-bolt %t.exe -o %t.null \
+# RUN: --reorder-blocks=normal --reorder-functions=user \
+# RUN: --function-order=/DOES/NOT/EXIST 2>&1 \
+# RUN: | FileCheck --check-prefix=CHECK %s
+
+# CHECK: FATAL BOLT-ERROR: Ordered functions file "/DOES/NOT/EXIST" can't be opened
+
+# Sample function reordering input, based off function-order-lite.s
+ .globl main
+ .type main, %function
+main:
+ .cfi_startproc
+.LBB06:
+ callq func_a
+ retq
+ .cfi_endproc
+.size main, .-main
+
+ .globl func_a
+ .type func_a, %function
+func_a:
+ .cfi_startproc
+ retq
+ .cfi_endproc
+.size func_a, .-func_a
+
+ .globl func_b
+ .type func_b, %function
+func_b:
+ .cfi_startproc
+ retq
+ .cfi_endproc
+.size func_b, .-func_b
diff --git a/bolt/test/X86/log.test b/bolt/test/X86/log.test
new file mode 100644
index 000000000000..0cbb5b625d00
--- /dev/null
+++ b/bolt/test/X86/log.test
@@ -0,0 +1,19 @@
+# Tests whether llvm-bolt is able to redirect logs when processing a simple
+# input. If this test fails on your changes, please use BinaryContext::outs()
+# to print BOLT logging instead of llvm::outs().
+
+RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe
+RUN: llvm-bolt %t.exe -o %t.null --data %p/Inputs/blarge.fdata -v=2 \
+RUN: --reorder-blocks=normal --print-finalized --log-file=%t.log 2>&1 \
+RUN: | FileCheck --check-prefix=CHECK --allow-empty %s
+RUN: cat %t.log | FileCheck %s --check-prefix=CHECK-LOG
+
+CHECK-NOT: BOLT-INFO
+CHECK-NOT: BOLT-WARNING
+CHECK-NOT: BOLT-ERROR
+
+# Check some usual BOLT output lines are being redirected to the log file
+CHECK-LOG: BOLT-INFO: Target architecture
+CHECK-LOG: BOLT-INFO: BOLT version
+CHECK-LOG: BOLT-INFO: basic block reordering modified layout
+CHECK-LOG: Binary Function "usqrt"
diff --git a/bolt/tools/bat-dump/bat-dump.cpp b/bolt/tools/bat-dump/bat-dump.cpp
index 71efe008d409..2e9b26cc137a 100644
--- a/bolt/tools/bat-dump/bat-dump.cpp
+++ b/bolt/tools/bat-dump/bat-dump.cpp
@@ -109,7 +109,7 @@ void dumpBATFor(llvm::object::ELFObjectFileBase *InputFile) {
exit(1);
}
- if (std::error_code EC = BAT.parse(SectionContents)) {
+ if (std::error_code EC = BAT.parse(outs(), SectionContents)) {
errs() << "BOLT-ERROR: failed to parse BOLT address translation "
"table. Malformed BAT section\n";
exit(1);
diff --git a/bolt/tools/driver/llvm-bolt.cpp b/bolt/tools/driver/llvm-bolt.cpp
index cc215a5256d2..9b03524e9f18 100644
--- a/bolt/tools/driver/llvm-bolt.cpp
+++ b/bolt/tools/driver/llvm-bolt.cpp
@@ -63,6 +63,11 @@ BoltProfile("b",
cl::aliasopt(InputDataFilename),
cl::cat(BoltCategory));
+cl::opt<std::string>
+ LogFile("log-file",
+ cl::desc("redirect journaling to a file instead of stdout/stderr"),
+ cl::Hidden, cl::cat(BoltCategory));
+
static cl::opt<std::string>
InputDataFilename2("data2",
cl::desc("<data file>"),
@@ -207,6 +212,24 @@ int main(int argc, char **argv) {
if (!sys::fs::exists(opts::InputFilename))
report_error(opts::InputFilename, errc::no_such_file_or_directory);
+ // Initialize journaling streams
+ raw_ostream *BOLTJournalOut = &outs();
+ raw_ostream *BOLTJournalErr = &errs();
+ // RAII obj to keep log file open throughout execution
+ std::unique_ptr<raw_fd_ostream> LogFileStream;
+ if (!opts::LogFile.empty()) {
+ std::error_code LogEC;
+ LogFileStream = std::make_unique<raw_fd_ostream>(
+ opts::LogFile, LogEC, sys::fs::OpenFlags::OF_None);
+ if (LogEC) {
+ errs() << "BOLT-ERROR: cannot open requested log file for writing: "
+ << LogEC.message() << "\n";
+ exit(1);
+ }
+ BOLTJournalOut = LogFileStream.get();
+ BOLTJournalErr = LogFileStream.get();
+ }
+
// Attempt to open the binary.
if (!opts::DiffOnly) {
Expected<OwningBinary<Binary>> BinaryOrErr =
@@ -216,7 +239,8 @@ int main(int argc, char **argv) {
Binary &Binary = *BinaryOrErr.get().getBinary();
if (auto *e = dyn_cast<ELFObjectFileBase>(&Binary)) {
- auto RIOrErr = RewriteInstance::create(e, argc, argv, ToolPath);
+ auto RIOrErr = RewriteInstance::create(e, argc, argv, ToolPath,
+ *BOLTJournalOut, *BOLTJournalErr);
if (Error E = RIOrErr.takeError())
report_error(opts::InputFilename, std::move(E));
RewriteInstance &RI = *RIOrErr.get();
diff --git a/bolt/unittests/Core/BinaryContext.cpp b/bolt/unittests/Core/BinaryContext.cpp
index 7ac1c1435759..1fbb07bca966 100644
--- a/bolt/unittests/Core/BinaryContext.cpp
+++ b/bolt/unittests/Core/BinaryContext.cpp
@@ -40,7 +40,8 @@ protected:
void initializeBOLT() {
BC = cantFail(BinaryContext::createBinaryContext(
- ObjFile.get(), true, DWARFContext::create(*ObjFile.get())));
+ ObjFile.get(), true, DWARFContext::create(*ObjFile.get()),
+ {llvm::outs(), llvm::errs()}));
ASSERT_FALSE(!BC);
}
diff --git a/bolt/unittests/Core/MCPlusBuilder.cpp b/bolt/unittests/Core/MCPlusBuilder.cpp
index b851c756e796..63448039c53e 100644
--- a/bolt/unittests/Core/MCPlusBuilder.cpp
+++ b/bolt/unittests/Core/MCPlusBuilder.cpp
@@ -50,7 +50,8 @@ protected:
void initializeBolt() {
BC = cantFail(BinaryContext::createBinaryContext(
- ObjFile.get(), true, DWARFContext::create(*ObjFile.get())));
+ ObjFile.get(), true, DWARFContext::create(*ObjFile.get()),
+ {llvm::outs(), llvm::errs()}));
ASSERT_FALSE(!BC);
BC->initializeTarget(std::unique_ptr<MCPlusBuilder>(
createMCPlusBuilder(GetParam(), BC->MIA.get(), BC->MII.get(),