diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index 5dc5fdb150be..30336c4e3a74 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -165,6 +165,12 @@ private: 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); @@ -260,7 +266,8 @@ class BinaryContext { public: static Expected> createBinaryContext(const ObjectFile *File, bool IsPIC, - std::unique_ptr DwCtx); + std::unique_ptr 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 @@ -628,6 +635,10 @@ public: std::unique_ptr 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}; @@ -760,7 +771,8 @@ public: std::unique_ptr MIA, std::unique_ptr MIB, std::unique_ptr MRI, - std::unique_ptr DisAsm); + std::unique_ptr DisAsm, + JournalingStreams Logger); ~BinaryContext(); @@ -1372,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 LocalMOFI; @@ -1421,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 > 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 BuilderState; FoldingSet AbbreviationsSet; std::vector> 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 -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/BinaryPasses.h b/bolt/include/bolt/Passes/BinaryPasses.h index 8d52337b50ad..046765b16f19 100644 --- a/bolt/include/bolt/Passes/BinaryPasses.h +++ b/bolt/include/bolt/Passes/BinaryPasses.h @@ -50,7 +50,6 @@ 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 Error runOnFunctions(BinaryContext &BC) = 0; }; @@ -74,14 +73,14 @@ public: 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(); } }; diff --git a/bolt/include/bolt/Passes/CMOVConversion.h b/bolt/include/bolt/Passes/CMOVConversion.h index 29b5184254fe..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; 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 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 &BinaryFunctions); +void printAll(raw_ostream &OS, + const std::vector &BinaryFunctions); } // namespace CacheMetrics } // namespace bolt diff --git a/bolt/include/bolt/Passes/ReorderData.h b/bolt/include/bolt/Passes/ReorderData.h index ed183bfce00c..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 &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 diff --git a/bolt/include/bolt/Passes/ReorderFunctions.h b/bolt/include/bolt/Passes/ReorderFunctions.h index b75937da2314..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 &&Clusters, + void reorder(BinaryContext &BC, std::vector &&Clusters, std::map &BFs); - void printStats(const std::vector &Clusters, + void printStats(BinaryContext &BC, const std::vector &Clusters, const std::vector &FuncAddr); public: diff --git a/bolt/include/bolt/Passes/ShrinkWrapping.h b/bolt/include/bolt/Passes/ShrinkWrapping.h index 016bea75f649..b7809f0bb069 100644 --- a/bolt/include/bolt/Passes/ShrinkWrapping.h +++ b/bolt/include/bolt/Passes/ShrinkWrapping.h @@ -523,7 +523,7 @@ public: Expected perform(bool HotOnly = false); - static void printStats(); + static void printStats(BinaryContext &BC); }; } // end 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/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> 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 1c33544f40a1..d544ece13a83 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -114,6 +114,15 @@ Error createFatalBOLTError(const Twine &S) { return make_error(/*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 Ctx, std::unique_ptr DwCtx, std::unique_ptr TheTriple, @@ -127,13 +136,15 @@ BinaryContext::BinaryContext(std::unique_ptr Ctx, std::unique_ptr MIA, std::unique_ptr MIB, std::unique_ptr MRI, - std::unique_ptr DisAsm) + std::unique_ptr 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; @@ -153,7 +164,8 @@ BinaryContext::~BinaryContext() { /// triple \p TripleName. Expected> BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, - std::unique_ptr DwCtx) { + std::unique_ptr DwCtx, + JournalingStreams Logger) { StringRef ArchName = ""; std::string FeaturesStr = ""; switch (File->getArch()) { @@ -272,17 +284,12 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, std::unique_ptr 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( 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; @@ -335,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; @@ -354,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; } } @@ -469,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( @@ -513,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; } @@ -761,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); @@ -769,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, @@ -822,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); @@ -863,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. @@ -992,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; @@ -1012,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 { @@ -1161,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; } @@ -1172,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'; } } @@ -1192,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; } @@ -1307,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); @@ -1336,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); } @@ -1348,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()); } } @@ -1367,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; } } @@ -1623,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() { @@ -1694,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(); @@ -2276,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(Function).print(SS, ""); + SS << "ERROR: " << Message; + SS << "\n=======================================\n"; + return Msg; } BinaryFunction * @@ -2430,9 +2449,9 @@ bool BinaryContext::validateInstructionEncoding( auto OutputSequence = ArrayRef((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 3f3da3b80041..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; @@ -1042,8 +1042,8 @@ Error BinaryFunction::handlePCRelOperand(MCInst &Instruction, uint64_t Address, 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; @@ -1068,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) && @@ -1084,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; @@ -1096,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"); @@ -1210,10 +1210,11 @@ Error 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(); @@ -1229,10 +1230,10 @@ Error 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'; } } @@ -1245,10 +1246,10 @@ Error 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; } @@ -1284,9 +1285,9 @@ Error 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; } } @@ -1341,7 +1342,7 @@ Error BinaryFunction::disassemble() { if (E.isFatal()) return Error(std::make_unique(std::move(E))); if (!E.getMessage().empty()) - E.log(errs()); + E.log(BC.errs()); return Error::success(); })) { return Error(std::move(NewE)); @@ -1392,7 +1393,7 @@ Error BinaryFunction::disassemble() { if (E.isFatal()) return Error(std::make_unique(std::move(E))); if (!E.getMessage().empty()) - E.log(errs()); + E.log(BC.errs()); return Error::success(); })) return Error(std::move(NewE)); @@ -1490,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; @@ -1621,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; } @@ -1654,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); @@ -1670,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(); @@ -1787,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; @@ -1895,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)); } @@ -2134,11 +2136,12 @@ Error 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); @@ -2216,8 +2219,8 @@ Error 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. @@ -3057,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; @@ -3185,16 +3184,17 @@ void BinaryFunction::viewGraph() const { SmallString 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"; } } @@ -3204,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); } @@ -3213,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; } @@ -3236,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; } @@ -3264,8 +3264,8 @@ bool BinaryFunction::validateCFG() const { std::unordered_set 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); @@ -3274,8 +3274,8 @@ bool BinaryFunction::validateCFG() const { std::unordered_set 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); @@ -3283,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/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 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(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> SortedHistogram; diff --git a/bolt/lib/Core/Exceptions.cpp b/bolt/lib/Core/Exceptions.cpp index dd3fa46b6f12..54618aeb95cc 100644 --- a/bolt/lib/Core/Exceptions.cpp +++ b/bolt/lib/Core/Exceptions.cpp @@ -119,8 +119,8 @@ Error BinaryFunction::parseLSDA(ArrayRef LSDASectionData, std::optional MaybeLPStart = Data.getEncodedPointer( &Offset, LPStartEncoding, Offset + LSDASectionAddress); if (!MaybeLPStart) { - errs() << "BOLT-ERROR: unsupported LPStartEncoding: " - << (unsigned)LPStartEncoding << '\n'; + BC.errs() << "BOLT-ERROR: unsupported LPStartEncoding: " + << (unsigned)LPStartEncoding << '\n'; return createFatalBOLTError(""); } LPStart = *MaybeLPStart; @@ -136,13 +136,14 @@ Error BinaryFunction::parseLSDA(ArrayRef 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 @@ Error BinaryFunction::parseLSDA(ArrayRef 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 @@ Error BinaryFunction::parseLSDA(ArrayRef 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. @@ -215,9 +217,10 @@ Error BinaryFunction::parseLSDA(ArrayRef LSDASectionData, 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 @@ Error BinaryFunction::parseLSDA(ArrayRef 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 @@ Error BinaryFunction::parseLSDA(ArrayRef 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(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 @@ Error BinaryFunction::parseLSDA(ArrayRef LSDASectionData, while (uint64_t Index = Data.getULEB128(&TypeIndexTablePtr)) { MaxTypeIndex = std::max(MaxTypeIndex, static_cast(Index)); if (opts::PrintExceptions) { - outs() << TSep; - printType(Index, outs()); + BC.outs() << TSep; + printType(Index, BC.outs()); TSep = ", "; } } @@ -319,11 +322,11 @@ Error BinaryFunction::parseLSDA(ArrayRef 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() && @@ -461,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(&Entry); @@ -476,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 { @@ -509,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) @@ -602,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: @@ -623,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 @@ -634,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 aa715a3f3787..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; } diff --git a/bolt/lib/Passes/AllocCombiner.cpp b/bolt/lib/Passes/AllocCombiner.cpp index 2397dc49c0fb..38ef7d02a47d 100644 --- a/bolt/lib/Passes/AllocCombiner.cpp +++ b/bolt/lib/Passes/AllocCombiner.cpp @@ -111,9 +111,9 @@ Error AllocCombinerPass::runOnFunctions(BinaryContext &BC) { 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(); } diff --git a/bolt/lib/Passes/AsmDump.cpp b/bolt/lib/Passes/AsmDump.cpp index 1eaf890ff9b3..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(); 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 4d92b2746251..d2850b03e2e1 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -308,12 +308,12 @@ Error NormalizeCFG::runOnFunctions(BinaryContext &BC) { [&](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(); } @@ -340,9 +340,9 @@ 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'; } } @@ -360,8 +360,8 @@ Error 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(); } @@ -413,8 +413,9 @@ Error 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, @@ -422,7 +423,7 @@ Error 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 ScoreMap; auto &BFs = BC.getBinaryFunctions(); @@ -532,8 +533,8 @@ Error FinalizeFunctions::runOnFunctions(BinaryContext &BC) { ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { if (!BF.finalizeCFIState()) { if (BC.HasRelocations) { - errs() << "BOLT-ERROR: unable to fix CFI state for function " << BF - << ". Exiting.\n"; + BC.errs() << "BOLT-ERROR: unable to fix CFI state for function " << BF + << ". Exiting.\n"; HasFatal = true; return; } @@ -993,16 +994,16 @@ Error 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(); } @@ -1020,10 +1021,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; @@ -1044,7 +1045,8 @@ Error 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(); } @@ -1107,12 +1109,12 @@ Error 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(); } @@ -1205,11 +1207,12 @@ Error SimplifyRODataLoads::runOnFunctions(BinaryContext &BC) { 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(); } @@ -1329,11 +1332,11 @@ Error 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(); @@ -1370,7 +1373,7 @@ Error 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; } @@ -1390,9 +1393,9 @@ Error PrintProgramStats::runOnFunctions(BinaryContext &BC) { } } else { if (opts::ReportStaleFuncs) { - outs() << StaleFuncsHeader; + BC.outs() << StaleFuncsHeader; StaleFuncsHeader = ""; - outs() << " " << Function << '\n'; + BC.outs() << " " << Function << '\n'; } ++NumStaleProfileFunctions; StaleSampleCount += SampleCount; @@ -1404,15 +1407,15 @@ Error 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 = @@ -1425,36 +1428,37 @@ Error 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) { return createFatalBOLTError( Twine("BOLT-ERROR: stale functions exceed specified threshold of ") + @@ -1462,15 +1466,16 @@ Error PrintProgramStats::runOnFunctions(BinaryContext &BC) { } } 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", @@ -1481,13 +1486,13 @@ Error 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(); @@ -1496,7 +1501,8 @@ Error 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'; } } @@ -1536,70 +1542,70 @@ Error 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; } } @@ -1634,23 +1640,23 @@ Error 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(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(); } @@ -1682,10 +1688,10 @@ Error 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(); } @@ -1730,11 +1736,11 @@ Error 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(); } @@ -1864,12 +1870,12 @@ Error 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(); } diff --git a/bolt/lib/Passes/CMOVConversion.cpp b/bolt/lib/Passes/CMOVConversion.cpp index adb6115a61de..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,8 +265,8 @@ 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; } @@ -279,8 +279,8 @@ Error 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(); } 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 &BFs) { +void CacheMetrics::printAll(raw_ostream &OS, + const std::vector &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 &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 BBAddr; std::unordered_map 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(Stats.second, 1), - Stats.first, Stats.second); + OS << " TSP score: " + << format("%.2lf%% (%zu out of %zu)\n", + 100.0 * Stats.first / std::max(Stats.second, 1), + Stats.first, Stats.second); } 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 30bcfb9084e9..fb5f8eafa5cf 100644 --- a/bolt/lib/Passes/FrameOptimizer.cpp +++ b/bolt/lib/Passes/FrameOptimizer.cpp @@ -289,21 +289,21 @@ Error FrameOptimizerPass::runOnFunctions(BinaryContext &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(); } @@ -385,9 +385,9 @@ Error 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; } diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp index ba3afd27090d..9f8d82b05ccf 100644 --- a/bolt/lib/Passes/IdenticalCodeFolding.cpp +++ b/bolt/lib/Passes/IdenticalCodeFolding.cpp @@ -508,14 +508,14 @@ Error 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(); } diff --git a/bolt/lib/Passes/IndirectCallPromotion.cpp b/bolt/lib/Passes/IndirectCallPromotion.cpp index d1dc1af77e83..55eede641fd2 100644 --- a/bolt/lib/Passes/IndirectCallPromotion.cpp +++ b/bolt/lib/Passes/IndirectCallPromotion.cpp @@ -171,9 +171,10 @@ static bool verifyProfile(std::map &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 &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 &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 &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({ @@ -1222,9 +1225,9 @@ Error 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 @@ Error 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 @@ Error 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 @@ Error 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 @@ Error 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,48 +1429,49 @@ Error 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(TotalIndirectCalls, 1)) - << "%\n" - << "BOLT-INFO: ICP percentage of indirect callsites that are " - "optimized = " - << format("%.1f", (100.0 * TotalOptimizedIndirectCallsites) / - std::max(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( - TotalMethodLoadEliminationCandidates, 1)) - << "%\n" - << "BOLT-INFO: ICP percentage of indirect branches that are " - "optimized = " - << format("%.1f", (100.0 * TotalNumFrequentJmps) / - std::max(TotalIndirectJmps, 1)) - << "%\n" - << "BOLT-INFO: ICP percentage of jump table callsites that are " - << "optimized = " - << format("%.1f", (100.0 * TotalOptimizedJumpTableCallsites) / - std::max(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(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(TotalIndirectCalls, 1)) + << "%\n" + << "BOLT-INFO: ICP percentage of indirect callsites that are " + "optimized = " + << format("%.1f", (100.0 * TotalOptimizedIndirectCallsites) / + std::max(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(TotalMethodLoadEliminationCandidates, 1)) + << "%\n" + << "BOLT-INFO: ICP percentage of indirect branches that are " + "optimized = " + << format("%.1f", (100.0 * TotalNumFrequentJmps) / + std::max(TotalIndirectJmps, 1)) + << "%\n" + << "BOLT-INFO: ICP percentage of jump table callsites that are " + << "optimized = " + << format("%.1f", (100.0 * TotalOptimizedJumpTableCallsites) / + std::max(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(TotalIndexBasedCandidates, 1)) + << "%\n"; #ifndef NDEBUG verifyProfile(BFs); diff --git a/bolt/lib/Passes/Inliner.cpp b/bolt/lib/Passes/Inliner.cpp index d875ecbd0d44..a3b2017aa32a 100644 --- a/bolt/lib/Passes/Inliner.cpp +++ b/bolt/lib/Passes/Inliner.cpp @@ -540,10 +540,10 @@ Error 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(); } diff --git a/bolt/lib/Passes/Instrumentation.cpp b/bolt/lib/Passes/Instrumentation.cpp index 26b4a67fec42..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; } @@ -576,7 +576,7 @@ Error Instrumentation::runOnFunctions(BinaryContext &BC) { 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")) { @@ -596,7 +596,7 @@ Error 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"; } } @@ -687,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(BC.getRuntimeLibrary()); diff --git a/bolt/lib/Passes/JTFootprintReduction.cpp b/bolt/lib/Passes/JTFootprintReduction.cpp index 5d2e27affc8e..fd291f96004d 100644 --- a/bolt/lib/Passes/JTFootprintReduction.cpp +++ b/bolt/lib/Passes/JTFootprintReduction.cpp @@ -272,23 +272,23 @@ Error JTFootprintReduction::runOnFunctions(BinaryContext &BC) { } if (TotalJTs == TotalJTsDenied) { - outs() << "BOLT-INFO: JT Footprint reduction: no changes were made.\n"; + 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(); } diff --git a/bolt/lib/Passes/LongJmp.cpp b/bolt/lib/Passes/LongJmp.cpp index 72823b9c193d..c483f70a836e 100644 --- a/bolt/lib/Passes/LongJmp.cpp +++ b/bolt/lib/Passes/LongJmp.cpp @@ -630,7 +630,7 @@ Error LongJmpPass::relax(BinaryFunction &Func, bool &Modified) { } Error LongJmpPass::runOnFunctions(BinaryContext &BC) { - outs() << "BOLT-INFO: Starting stub-insertion pass\n"; + BC.outs() << "BOLT-INFO: Starting stub-insertion pass\n"; std::vector Sorted = BC.getSortedFunctions(); bool Modified; uint32_t Iterations = 0; @@ -648,10 +648,10 @@ Error LongJmpPass::runOnFunctions(BinaryContext &BC) { 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 diff --git a/bolt/lib/Passes/LoopInversionPass.cpp b/bolt/lib/Passes/LoopInversionPass.cpp index 10df715993f8..250a971d204c 100644 --- a/bolt/lib/Passes/LoopInversionPass.cpp +++ b/bolt/lib/Passes/LoopInversionPass.cpp @@ -103,8 +103,8 @@ Error 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(); } diff --git a/bolt/lib/Passes/PLTCall.cpp b/bolt/lib/Passes/PLTCall.cpp index c02f2c3ef367..d0276f22e14e 100644 --- a/bolt/lib/Passes/PLTCall.cpp +++ b/bolt/lib/Passes/PLTCall.cpp @@ -80,8 +80,8 @@ Error 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(); } diff --git a/bolt/lib/Passes/PatchEntries.cpp b/bolt/lib/Passes/PatchEntries.cpp index 0b0e15f1b5bd..981d1b70af90 100644 --- a/bolt/lib/Passes/PatchEntries.cpp +++ b/bolt/lib/Passes/PatchEntries.cpp @@ -46,7 +46,7 @@ Error PatchEntries::runOnFunctions(BinaryContext &BC) { } 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 @@ Error 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 @@ Error 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,8 +101,8 @@ Error 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"; + BC.errs() << "BOLT-ERROR: unable to patch entries in " << Function + << "\n"; return createFatalBOLTError(""); } @@ -111,8 +111,8 @@ Error 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; } 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 5f0cddbdf7dc..0becfb4a06a3 100644 --- a/bolt/lib/Passes/RegReAssign.cpp +++ b/bolt/lib/Passes/RegReAssign.cpp @@ -480,18 +480,19 @@ Error RegReAssign::runOnFunctions(BinaryContext &BC) { } if (FuncsChanged.empty()) { - outs() << "BOLT-INFO: Reg Reassignment Pass: no changes were made.\n"; + 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(); } diff --git a/bolt/lib/Passes/ReorderData.cpp b/bolt/lib/Passes/ReorderData.cpp index 13e3e8001ba5..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, @@ -443,8 +444,8 @@ Error ReorderData::runOnFunctions(BinaryContext &BC) { // For now if (opts::JumpTables > JTS_BASIC) { - outs() << "BOLT-WARNING: jump table support must be basic for " - << "data reordering to work.\n"; + BC.outs() << "BOLT-WARNING: jump table support must be basic for " + << "data reordering to work.\n"; return Error::success(); } @@ -463,14 +464,14 @@ Error ReorderData::runOnFunctions(BinaryContext &BC) { ErrorOr 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 @@ Error 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,7 +520,8 @@ Error 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()); } } diff --git a/bolt/lib/Passes/ReorderFunctions.cpp b/bolt/lib/Passes/ReorderFunctions.cpp index 77e51c34746e..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 &&Clusters, +void ReorderFunctions::reorder(BinaryContext &BC, + std::vector &&Clusters, std::map &BFs) { std::vector FuncAddr(Cg.numNodes()); // Just for computing stats uint64_t TotalSize = 0; @@ -139,10 +140,11 @@ void ReorderFunctions::reorder(std::vector &&Clusters, if (opts::ReorderFunctions == RT_NONE) return; - printStats(Clusters, FuncAddr); + printStats(BC, Clusters, FuncAddr); } -void ReorderFunctions::printStats(const std::vector &Clusters, +void ReorderFunctions::printStats(BinaryContext &BC, + const std::vector &Clusters, const std::vector &FuncAddr) { if (opts::Verbosity == 0) { #ifndef NDEBUG @@ -167,11 +169,11 @@ void ReorderFunctions::printStats(const std::vector &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 &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 &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,46 +211,47 @@ void ReorderFunctions::printStats(const std::vector &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); } Error ReorderFunctions::readFunctionOrderFile( @@ -403,8 +407,8 @@ Error 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; } @@ -416,28 +420,28 @@ Error 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; @@ -446,8 +450,8 @@ Error ReorderFunctions::runOnFunctions(BinaryContext &BC) { FuncsFile = std::make_unique(opts::GenerateFunctionOrderFile, std::ios::out); if (!FuncsFile) { - errs() << "BOLT-ERROR: ordered functions file " - << opts::GenerateFunctionOrderFile << " cannot be opened\n"; + BC.errs() << "BOLT-ERROR: ordered functions file " + << opts::GenerateFunctionOrderFile << " cannot be opened\n"; return createFatalBOLTError(""); } } @@ -457,8 +461,8 @@ Error ReorderFunctions::runOnFunctions(BinaryContext &BC) { LinkSectionsFile = std::make_unique(opts::LinkSectionsFile, std::ios::out); if (!LinkSectionsFile) { - errs() << "BOLT-ERROR: link sections file " << opts::LinkSectionsFile - << " cannot be opened\n"; + BC.errs() << "BOLT-ERROR: link sections file " << opts::LinkSectionsFile + << " cannot be opened\n"; return createFatalBOLTError(""); } } @@ -509,14 +513,14 @@ Error 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(); diff --git a/bolt/lib/Passes/RetpolineInsertion.cpp b/bolt/lib/Passes/RetpolineInsertion.cpp index 09ea3a853fbc..2808575cc6bb 100644 --- a/bolt/lib/Passes/RetpolineInsertion.cpp +++ b/bolt/lib/Passes/RetpolineInsertion.cpp @@ -327,10 +327,10 @@ Error 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(); } diff --git a/bolt/lib/Passes/ShrinkWrapping.cpp b/bolt/lib/Passes/ShrinkWrapping.cpp index 2f2405b9463a..9a1f9d72623a 100644 --- a/bolt/lib/Passes/ShrinkWrapping.cpp +++ b/bolt/lib/Passes/ShrinkWrapping.cpp @@ -2035,28 +2035,28 @@ Expected 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 26dd4b66eb9a..cdbb2a15f667 100644 --- a/bolt/lib/Passes/SplitFunctions.cpp +++ b/bolt/lib/Passes/SplitFunctions.cpp @@ -766,10 +766,11 @@ Error 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(); } @@ -900,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 df73293c824e..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,18 +141,18 @@ 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; } Error StokeInfo::runOnFunctions(BinaryContext &BC) { - outs() << "STOKE-INFO: begin of stoke pass\n"; + 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"; + BC.errs() << "STOKE-INFO: output file is required\n"; return Error::success(); } @@ -185,7 +186,7 @@ Error 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(); } diff --git a/bolt/lib/Passes/TailDuplication.cpp b/bolt/lib/Passes/TailDuplication.cpp index 4f3082e28e4e..2163e3a6a008 100644 --- a/bolt/lib/Passes/TailDuplication.cpp +++ b/bolt/lib/Passes/TailDuplication.cpp @@ -644,22 +644,24 @@ Error 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(); } diff --git a/bolt/lib/Passes/ThreeWayBranch.cpp b/bolt/lib/Passes/ThreeWayBranch.cpp index a30a2a016e59..c69eac5614b9 100644 --- a/bolt/lib/Passes/ThreeWayBranch.cpp +++ b/bolt/lib/Passes/ThreeWayBranch.cpp @@ -155,8 +155,8 @@ Error 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(); } diff --git a/bolt/lib/Passes/ValidateInternalCalls.cpp b/bolt/lib/Passes/ValidateInternalCalls.cpp index ce0b13bbff04..54ae621159cf 100644 --- a/bolt/lib/Passes/ValidateInternalCalls.cpp +++ b/bolt/lib/Passes/ValidateInternalCalls.cpp @@ -339,10 +339,11 @@ Error 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(); } } diff --git a/bolt/lib/Passes/ValidateMemRefs.cpp b/bolt/lib/Passes/ValidateMemRefs.cpp index 598a4c26c745..f29a97c43f49 100644 --- a/bolt/lib/Passes/ValidateMemRefs.cpp +++ b/bolt/lib/Passes/ValidateMemRefs.cpp @@ -96,8 +96,8 @@ Error ValidateMemRefs::runOnFunctions(BinaryContext &BC) { if (!ReplacedReferences) 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(); } diff --git a/bolt/lib/Passes/VeneerElimination.cpp b/bolt/lib/Passes/VeneerElimination.cpp index d844a068184d..0bec11128c7c 100644 --- a/bolt/lib/Passes/VeneerElimination.cpp +++ b/bolt/lib/Passes/VeneerElimination.cpp @@ -51,8 +51,8 @@ Error 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) { 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(Maps, PrevAddress, OS); writeMaps(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 &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(HotFuncs, PrevAddress, DE, Offset, Err); parseMaps(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 cad80189c23b..489b33fe1c7c 100644 --- a/bolt/lib/Rewrite/BinaryPassManager.cpp +++ b/bolt/lib/Rewrite/BinaryPassManager.cpp @@ -281,13 +281,14 @@ Error 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); Error E = Error::success(); callWithDynoStats( + BC.outs(), [this, &E, &Pass] { E = joinErrors(std::move(E), Pass->runOnFunctions(BC)); }, @@ -308,7 +309,7 @@ Error BinaryFunctionPassManager::runPasses() { } 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; @@ -321,7 +322,7 @@ Error BinaryFunctionPassManager::runPasses() { if (!Pass->shouldPrint(Function)) continue; - Function.print(outs(), Message); + Function.print(BC.outs(), Message); if (opts::DumpDotAll) Function.dumpGraphForPass(PassIdName); diff --git a/bolt/lib/Rewrite/BoltDiff.cpp b/bolt/lib/Rewrite/BoltDiff.cpp index 0de5a3d0b402..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"; - cantFail(PPS.runOnFunctions(*RI1.BC)); + RI1.BC->logBOLTErrorsAndQuitOnFatal(PPS.runOnFunctions(*RI1.BC)); outs() << "* BOLT-DIFF: Starting print program stats pass for binary 2\n"; - cantFail(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"; - cantFail(ICF.runOnFunctions(*BC)); + BC->logBOLTErrorsAndQuitOnFatal(ICF.runOnFunctions(*BC)); outs() << "BOLT-DIFF: Starting ICF pass for binary 2"; - cantFail(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 OutBuffer; std::unique_ptr 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 diff --git a/bolt/lib/Rewrite/MachORewriteInstance.cpp b/bolt/lib/Rewrite/MachORewriteInstance.cpp index c2a6c1f88ab0..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; - cantFail(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(opts::PrintFinalized)); - cantFail(Manager.runPasses()); + BC->logBOLTErrorsAndQuitOnFatal(Manager.runPasses()); } void MachORewriteInstance::mapInstrumentationSection( diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 829568cefff0..89ca13c427dc 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -309,9 +309,11 @@ bool refersToReorderedSection(ErrorOr Section) { Expected> 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(File, Argc, Argv, ToolPath, Err); + auto RI = std::make_unique(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 &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(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 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 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 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"); - cantFail(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 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(opts::LiteThresholdCount)); @@ -2860,7 +2895,8 @@ void RewriteInstance::selectFunctionsToProcess() { StringSet<> ReorderFunctionsLTOCommonSet; if (opts::ReorderFunctions == ReorderFunctions::RT_USER) { std::vector FunctionNames; - cantFail(ReorderFunctions::readFunctionOrderFile(FunctionNames)); + BC->logBOLTErrorsAndQuitOnFatal( + ReorderFunctions::readFunctionOrderFile(FunctionNames)); for (const std::string &Function : FunctionNames) { ReorderFunctionsUserSet.insert(Function); if (std::optional LTOCommonName = getLTOCommonName(Function)) @@ -2937,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'; } } @@ -2964,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; @@ -2980,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'; } } } @@ -3012,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); } @@ -3025,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); } } @@ -3081,7 +3118,7 @@ void RewriteInstance::processProfileData() { if (Function.empty()) continue; - Function.print(outs(), "after attaching profile"); + Function.print(BC->outs(), "after attaching profile"); } } @@ -3110,8 +3147,8 @@ void RewriteInstance::disassembleFunctions() { ErrorOr> 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); } @@ -3138,16 +3175,19 @@ void RewriteInstance::disassembleFunctions() { handleAllErrors(Function.disassemble(), [&](const BOLTError &E) { DisasmFailed = true; if (E.isFatal()) { - E.log(errs()); + 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::processAllFunctions()) - BC->exitWithBugReport("function cannot be properly disassembled. " - "Unable to continue in relocation mode.", - Function); 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(); }); @@ -3156,7 +3196,7 @@ void RewriteInstance::disassembleFunctions() { continue; if (opts::PrintAll || opts::PrintDisasm) - Function.print(outs(), "after disassembly"); + Function.print(BC->outs(), "after disassembly"); } BC->processInterproceduralReferences(); @@ -3191,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; } @@ -3208,7 +3250,8 @@ void RewriteInstance::disassembleFunctions() { check_error(LSDASection.getError(), "failed to get LSDA section"); ArrayRef LSDAData = ArrayRef( LSDASection->getData(), LSDASection->getContents().size()); - cantFail(Function.parseLSDA(LSDAData, LSDASection->getAddress())); + BC->logBOLTErrorsAndQuitOnFatal( + Function.parseLSDA(LSDAData, LSDASection->getAddress())); } } } @@ -3226,7 +3269,7 @@ void RewriteInstance::buildFunctionsCFG() { bool HadErrors{false}; handleAllErrors(BF.buildCFG(AllocId), [&](const BOLTError &E) { if (!E.getMessage().empty()) - E.log(errs()); + E.log(BC->errs()); if (E.isFatal()) exit(1); HadErrors = true; @@ -3237,7 +3280,7 @@ void RewriteInstance::buildFunctionsCFG() { if (opts::PrintAll) { auto L = BC->scopeLock(); - BF.print(outs(), "while building cfg"); + BF.print(BC->outs(), "while building cfg"); } }; @@ -3276,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(); @@ -3291,19 +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); - handleAllErrors(BinaryFunctionPassManager::runAllPasses(*BC), - [](const BOLTError &E) { - E.log(errs()); - exit(1); - }); + BC->logBOLTErrorsAndQuitOnFatal(BinaryFunctionPassManager::runAllPasses(*BC)); } void RewriteInstance::preregisterSections() { @@ -3353,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); } @@ -3364,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 TextSection = @@ -3431,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()); } } @@ -3598,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; } } @@ -3626,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; } @@ -3837,7 +3878,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); } } @@ -4137,7 +4178,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 @@ -4198,14 +4240,14 @@ RewriteInstance::getOutputSections(ELFObjectFile *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(); @@ -4239,8 +4281,8 @@ RewriteInstance::getOutputSections(ELFObjectFile *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; } @@ -4287,8 +4329,8 @@ RewriteInstance::getOutputSections(ELFObjectFile *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(); @@ -4686,8 +4728,8 @@ void RewriteInstance::updateELFSymbolTable( std::optional 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 && @@ -4762,8 +4804,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); }; @@ -4859,7 +4901,7 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile *File) { } } if (!SymTabSection) { - errs() << "BOLT-WARNING: no symbol table found\n"; + BC->errs() << "BOLT-WARNING: no symbol table found\n"; return; } @@ -4962,7 +5004,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); } @@ -5074,12 +5116,12 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile *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); } @@ -5128,7 +5170,7 @@ void RewriteInstance::patchELFGOT(ELFObjectFile *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; } @@ -5232,9 +5274,10 @@ void RewriteInstance::patchELFDynamic(ELFObjectFile *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); } } @@ -5256,7 +5299,7 @@ Error RewriteInstance::readELFDynamic(ELFObjectFile *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(); @@ -5330,12 +5373,12 @@ Error RewriteInstance::readELFDynamic(ELFObjectFile *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); } @@ -5392,11 +5435,11 @@ void RewriteInstance::rewriteFile() { if (Function->getImageSize() > Function->getMaxSize()) { assert(!BC->isX86() && "Unexpected large function."); 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. @@ -5432,7 +5475,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(Function->getImageAddress()), Function->getImageSize(), Function->getFileOffset()); @@ -5452,8 +5495,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 : @@ -5465,14 +5508,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"; } } @@ -5500,10 +5544,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(Section.getOutputData()), Section.getOutputSize(), Section.getOutputFileOffset()); } @@ -5553,8 +5598,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 dead6856d2f6..0e0ad9270550 100644 --- a/bolt/lib/Target/X86/X86MCSymbolizer.cpp +++ b/bolt/lib/Target/X86/X86MCSymbolizer.cpp @@ -137,6 +137,7 @@ bool X86MCSymbolizer::tryAddingSymbolicOperand( auto PairOrErr = handleGOTPC64(*Relocation, InstAddress); if (auto E = PairOrErr.takeError()) { Function.setSimple(false); + BC.logBOLTErrorsAndQuitOnFatal(std::move(E)); return false; } auto [Sym, Addend] = *PairOrErr; 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 + LogFile("log-file", + cl::desc("redirect journaling to a file instead of stdout/stderr"), + cl::Hidden, cl::cat(BoltCategory)); + static cl::opt InputDataFilename2("data2", cl::desc(""), @@ -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 LogFileStream; + if (!opts::LogFile.empty()) { + std::error_code LogEC; + LogFileStream = std::make_unique( + 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> BinaryOrErr = @@ -216,7 +239,8 @@ int main(int argc, char **argv) { Binary &Binary = *BinaryOrErr.get().getBinary(); if (auto *e = dyn_cast(&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( createMCPlusBuilder(GetParam(), BC->MIA.get(), BC->MII.get(),