Skip to content

[BOLT][NFC] Log through JournalingStreams #81524

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions bolt/include/bolt/Core/BinaryContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ class BOLTError : public ErrorInfo<BOLTError> {
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);

Expand Down Expand Up @@ -260,7 +266,8 @@ class BinaryContext {
public:
static Expected<std::unique_ptr<BinaryContext>>
createBinaryContext(const ObjectFile *File, bool IsPIC,
std::unique_ptr<DWARFContext> DwCtx);
std::unique_ptr<DWARFContext> DwCtx,
JournalingStreams Logger);

/// Superset of compiler units that will contain overwritten code that needs
/// new debug info. In a few cases, functions may end up not being
Expand Down Expand Up @@ -628,6 +635,10 @@ class BinaryContext {

std::unique_ptr<MCAsmBackend> MAB;

/// Allows BOLT to print to log whenever it is necessary (with or without
/// const references)
mutable JournalingStreams Logger;

/// Indicates if the binary is Linux kernel.
bool IsLinuxKernel{false};

Expand Down Expand Up @@ -760,7 +771,8 @@ class BinaryContext {
std::unique_ptr<const MCInstrAnalysis> MIA,
std::unique_ptr<MCPlusBuilder> MIB,
std::unique_ptr<const MCRegisterInfo> MRI,
std::unique_ptr<MCDisassembler> DisAsm);
std::unique_ptr<MCDisassembler> DisAsm,
JournalingStreams Logger);

~BinaryContext();

Expand Down Expand Up @@ -1372,8 +1384,12 @@ class BinaryContext {
return Offset;
}

void exitWithBugReport(StringRef Message,
const BinaryFunction &Function) const;
/// Log BOLT errors to journaling streams and quit process with non-zero error
/// code 1 if error is fatal.
void logBOLTErrorsAndQuitOnFatal(Error E);

std::string generateBugReportMessage(StringRef Message,
const BinaryFunction &Function) const;

struct IndependentCodeEmitter {
std::unique_ptr<MCObjectFileInfo> LocalMOFI;
Expand Down Expand Up @@ -1421,6 +1437,10 @@ class BinaryContext {
assert(IOAddressMap && "Address map not set yet");
return *IOAddressMap;
}

raw_ostream &outs() const { return Logger.Out; }

raw_ostream &errs() const { return Logger.Err; }
};

template <typename T, typename = std::enable_if_t<sizeof(T) == 1>>
Expand Down
17 changes: 11 additions & 6 deletions bolt/include/bolt/Core/DIEBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -32,6 +33,7 @@
namespace llvm {

namespace bolt {

class DIEStreamer;
class DebugStrOffsetsWriter;

Expand Down Expand Up @@ -120,6 +122,7 @@ class DIEBuilder {
std::unique_ptr<State> BuilderState;
FoldingSet<DIEAbbrev> AbbreviationsSet;
std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
BinaryContext &BC;
DWARFContext *DwarfContext{nullptr};
bool IsDWO{false};
uint64_t UnitSize{0};
Expand Down Expand Up @@ -219,9 +222,10 @@ class DIEBuilder {
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();
}

Expand Down Expand Up @@ -261,7 +265,7 @@ class DIEBuilder {
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; }
Expand Down Expand Up @@ -295,8 +299,9 @@ class DIEBuilder {
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;
}

Expand Down
15 changes: 8 additions & 7 deletions bolt/include/bolt/Core/DynoStats.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,9 @@ inline DynoStats getDynoStats(FuncsType &Funcs, bool IsAArch64) {

/// Call a function with optional before and after dynostats printing.
template <typename FnType, typename FuncsType>
inline void callWithDynoStats(FnType &&Func, FuncsType &Funcs, StringRef Phase,
const bool Flag, bool IsAArch64) {
inline void callWithDynoStats(raw_ostream &OS, FnType &&Func, FuncsType &Funcs,
StringRef Phase, const bool Flag,
bool IsAArch64) {
DynoStats DynoStatsBefore(IsAArch64);
if (Flag)
DynoStatsBefore = getDynoStats(Funcs, IsAArch64);
Expand All @@ -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';
}
}

Expand Down
4 changes: 3 additions & 1 deletion bolt/include/bolt/Core/Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -59,6 +60,7 @@ class CFIReaderWriter {
const FDEsMap &getFDEs() const { return FDEs; }

private:
BinaryContext &BC;
FDEsMap FDEs;
};

Expand Down
13 changes: 6 additions & 7 deletions bolt/include/bolt/Passes/BinaryPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ class BinaryFunctionPass {
/// 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;
};

Expand All @@ -74,14 +73,14 @@ class DynoStatsPrintPass : public BinaryFunctionPass {
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();
}
};
Expand Down
2 changes: 1 addition & 1 deletion bolt/include/bolt/Passes/CMOVConversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 5 additions & 1 deletion bolt/include/bolt/Passes/CacheMetrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@
#include <vector>

namespace llvm {

class raw_ostream;

namespace bolt {
class BinaryFunction;
namespace CacheMetrics {

/// Calculate and print various metrics related to instruction cache performance
void printAll(const std::vector<BinaryFunction *> &BinaryFunctions);
void printAll(raw_ostream &OS,
const std::vector<BinaryFunction *> &BinaryFunctions);

} // namespace CacheMetrics
} // namespace bolt
Expand Down
3 changes: 2 additions & 1 deletion bolt/include/bolt/Passes/ReorderData.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ class ReorderData : public BinaryFunctionPass {
sortedByFunc(BinaryContext &BC, const BinarySection &Section,
std::map<uint64_t, BinaryFunction> &BFs) const;

void printOrder(const BinarySection &Section, DataOrder::const_iterator Begin,
void printOrder(BinaryContext &BC, const BinarySection &Section,
DataOrder::const_iterator Begin,
DataOrder::const_iterator End) const;

/// Set the ordering of the section with \p SectionName. \p NewOrder is a
Expand Down
4 changes: 2 additions & 2 deletions bolt/include/bolt/Passes/ReorderFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ class Cluster;
class ReorderFunctions : public BinaryFunctionPass {
BinaryFunctionCallGraph Cg;

void reorder(std::vector<Cluster> &&Clusters,
void reorder(BinaryContext &BC, std::vector<Cluster> &&Clusters,
std::map<uint64_t, BinaryFunction> &BFs);

void printStats(const std::vector<Cluster> &Clusters,
void printStats(BinaryContext &BC, const std::vector<Cluster> &Clusters,
const std::vector<uint64_t> &FuncAddr);

public:
Expand Down
2 changes: 1 addition & 1 deletion bolt/include/bolt/Passes/ShrinkWrapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ class ShrinkWrapping {

Expected<bool> perform(bool HotOnly = false);

static void printStats();
static void printStats(BinaryContext &BC);
};

} // end namespace bolt
Expand Down
2 changes: 1 addition & 1 deletion bolt/include/bolt/Profile/BoltAddressTranslation.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class BoltAddressTranslation {

/// 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);
Expand Down
7 changes: 5 additions & 2 deletions bolt/include/bolt/Rewrite/RewriteInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ class RewriteInstance {
// construction. Constructors can’t return errors, so clients must test \p Err
// after the object is constructed. Use `create` method instead.
RewriteInstance(llvm::object::ELFObjectFileBase *File, const int Argc,
const char *const *Argv, StringRef ToolPath, Error &Err);
const char *const *Argv, StringRef ToolPath,
raw_ostream &Stdout, raw_ostream &Stderr, Error &Err);

static Expected<std::unique_ptr<RewriteInstance>>
create(llvm::object::ELFObjectFileBase *File, const int Argc,
const char *const *Argv, StringRef ToolPath);
const char *const *Argv, StringRef ToolPath,
raw_ostream &Stdout = llvm::outs(),
raw_ostream &Stderr = llvm::errs());
~RewriteInstance();

/// Assign profile from \p Filename to this instance.
Expand Down
36 changes: 18 additions & 18 deletions bolt/lib/Core/BinaryBasicBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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";
}
}
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
Loading