From e75b4debb9b13367a3bc705f1cf8a748e59795a8 Mon Sep 17 00:00:00 2001 From: Francis Visoiu Mistrih Date: Wed, 18 Sep 2019 01:04:45 +0000 Subject: [PATCH] [Remarks] Allow the RemarkStreamer to be used directly with a stream The filename in the RemarkStreamer should be optional to allow clients to stream remarks to memory or to existing streams. This introduces a new overload of `setupOptimizationRemarks`, and avoids enforcing the presence of a filename at different places. llvm-svn: 372195 --- include/llvm/IR/RemarkStreamer.h | 22 +++++++++---- lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 13 +++++--- lib/IR/RemarkStreamer.cpp | 46 ++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 19 deletions(-) diff --git a/include/llvm/IR/RemarkStreamer.h b/include/llvm/IR/RemarkStreamer.h index 7b2fc95d15e..2abf6f99cb0 100644 --- a/include/llvm/IR/RemarkStreamer.h +++ b/include/llvm/IR/RemarkStreamer.h @@ -25,12 +25,12 @@ namespace llvm { /// Streamer for remarks. class RemarkStreamer { - /// The filename that the remark diagnostics are emitted to. - const std::string Filename; /// The regex used to filter remarks based on the passes that emit them. Optional PassFilter; /// The object used to serialize the remarks to a specific format. std::unique_ptr RemarkSerializer; + /// The filename that the remark diagnostics are emitted to. + const Optional Filename; /// Convert diagnostics into remark objects. /// The lifetime of the members of the result is bound to the lifetime of @@ -38,10 +38,12 @@ class RemarkStreamer { remarks::Remark toRemark(const DiagnosticInfoOptimizationBase &Diag); public: - RemarkStreamer(StringRef Filename, - std::unique_ptr RemarkSerializer); + RemarkStreamer(std::unique_ptr RemarkSerializer, + Optional Filename = None); /// Return the filename that the remark diagnostics are emitted to. - StringRef getFilename() const { return Filename; } + Optional getFilename() const { + return Filename ? Optional(*Filename) : None; + } /// Return stream that the remark diagnostics are emitted to. raw_ostream &getStream() { return RemarkSerializer->OS; } /// Return the serializer used for this stream. @@ -84,13 +86,21 @@ struct RemarkSetupFormatError : RemarkSetupErrorInfo { using RemarkSetupErrorInfo::RemarkSetupErrorInfo; }; -/// Setup optimization remarks. +/// Setup optimization remarks that output to a file. Expected> setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, unsigned RemarksHotnessThreshold = 0); +/// Setup optimization remarks that output directly to a raw_ostream. +/// \p OS is managed by the caller and should be open for writing as long as \p +/// Context is streaming remarks to it. +Error setupOptimizationRemarks(LLVMContext &Context, raw_ostream &OS, + StringRef RemarksPasses, StringRef RemarksFormat, + bool RemarksWithHotness, + unsigned RemarksHotnessThreshold = 0); + } // end namespace llvm #endif // LLVM_IR_REMARKSTREAMER_H diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index ca223f78c16..20c50bb8a2a 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1349,15 +1349,18 @@ void AsmPrinter::emitRemarksSection(Module &M) { return; remarks::RemarkSerializer &RemarkSerializer = RS->getSerializer(); - StringRef FilenameRef = RS->getFilename(); - SmallString<128> Filename = FilenameRef; - sys::fs::make_absolute(Filename); - assert(!Filename.empty() && "The filename can't be empty."); + Optional> Filename; + if (Optional FilenameRef = RS->getFilename()) { + Filename = *FilenameRef; + sys::fs::make_absolute(*Filename); + assert(!Filename->empty() && "The filename can't be empty."); + } std::string Buf; raw_string_ostream OS(Buf); std::unique_ptr MetaSerializer = - RemarkSerializer.metaSerializer(OS, StringRef(Filename)); + Filename ? RemarkSerializer.metaSerializer(OS, StringRef(*Filename)) + : RemarkSerializer.metaSerializer(OS); MetaSerializer->emit(); // Switch to the right section: .remarks/__remarks. diff --git a/lib/IR/RemarkStreamer.cpp b/lib/IR/RemarkStreamer.cpp index 73387ecbac1..8a70862de72 100644 --- a/lib/IR/RemarkStreamer.cpp +++ b/lib/IR/RemarkStreamer.cpp @@ -22,12 +22,10 @@ using namespace llvm; RemarkStreamer::RemarkStreamer( - StringRef Filename, - std::unique_ptr RemarkSerializer) - : Filename(Filename), PassFilter(), - RemarkSerializer(std::move(RemarkSerializer)) { - assert(!Filename.empty() && "This needs to be a real filename."); -} + std::unique_ptr RemarkSerializer, + Optional FilenameIn) + : PassFilter(), RemarkSerializer(std::move(RemarkSerializer)), + Filename(FilenameIn ? Optional(FilenameIn->str()) : None) {} Error RemarkStreamer::setFilter(StringRef Filter) { Regex R = Regex(Filter); @@ -137,12 +135,13 @@ llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, return make_error(std::move(E)); Expected> RemarkSerializer = - remarks::createRemarkSerializer(*Format, remarks::SerializerMode::Separate, RemarksFile->os()); + remarks::createRemarkSerializer( + *Format, remarks::SerializerMode::Separate, RemarksFile->os()); if (Error E = RemarkSerializer.takeError()) return make_error(std::move(E)); Context.setRemarkStreamer(std::make_unique( - RemarksFilename, std::move(*RemarkSerializer))); + std::move(*RemarkSerializer), RemarksFilename)); if (!RemarksPasses.empty()) if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses)) @@ -150,3 +149,34 @@ llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, return std::move(RemarksFile); } + +Error llvm::setupOptimizationRemarks(LLVMContext &Context, raw_ostream &OS, + StringRef RemarksPasses, + StringRef RemarksFormat, + bool RemarksWithHotness, + unsigned RemarksHotnessThreshold) { + if (RemarksWithHotness) + Context.setDiagnosticsHotnessRequested(true); + + if (RemarksHotnessThreshold) + Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold); + + Expected Format = remarks::parseFormat(RemarksFormat); + if (Error E = Format.takeError()) + return make_error(std::move(E)); + + Expected> RemarkSerializer = + remarks::createRemarkSerializer(*Format, + remarks::SerializerMode::Separate, OS); + if (Error E = RemarkSerializer.takeError()) + return make_error(std::move(E)); + + Context.setRemarkStreamer( + std::make_unique(std::move(*RemarkSerializer))); + + if (!RemarksPasses.empty()) + if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses)) + return make_error(std::move(E)); + + return Error::success(); +}