diff options
-rw-r--r-- | llvm/include/llvm/Remarks/RemarkSerializer.h | 9 | ||||
-rw-r--r-- | llvm/include/llvm/Remarks/YAMLRemarkSerializer.h | 4 | ||||
-rw-r--r-- | llvm/lib/IR/RemarkStreamer.cpp | 23 | ||||
-rw-r--r-- | llvm/lib/Remarks/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Remarks/RemarkFormat.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Remarks/RemarkSerializer.cpp | 48 | ||||
-rw-r--r-- | llvm/tools/llvm-opt-report/OptReport.cpp | 19 | ||||
-rw-r--r-- | llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp | 54 |
8 files changed, 134 insertions, 26 deletions
diff --git a/llvm/include/llvm/Remarks/RemarkSerializer.h b/llvm/include/llvm/Remarks/RemarkSerializer.h index bcf63814b5b..cf12a9af7c8 100644 --- a/llvm/include/llvm/Remarks/RemarkSerializer.h +++ b/llvm/include/llvm/Remarks/RemarkSerializer.h @@ -36,6 +36,15 @@ struct Serializer { virtual void emit(const Remark &Remark) = 0; }; +/// Create a remark serializer. +Expected<std::unique_ptr<Serializer>> +createRemarkSerializer(Format RemarksFormat, raw_ostream &OS); + +/// Create a remark serializer that uses a pre-filled string table. +Expected<std::unique_ptr<Serializer>> +createRemarkSerializer(Format RemarksFormat, raw_ostream &OS, + remarks::StringTable StrTab); + } // end namespace remarks } // end namespace llvm diff --git a/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h b/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h index 9bb5c6e83ed..0d8d39cfdbc 100644 --- a/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h +++ b/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h @@ -48,6 +48,10 @@ struct YAMLStrTabSerializer : public YAMLSerializer { // Having a string table set up enables the serializer to use it. StrTab.emplace(); } + YAMLStrTabSerializer(raw_ostream &OS, StringTable StrTabIn) + : YAMLSerializer(OS) { + StrTab = std::move(StrTabIn); + } }; } // end namespace remarks diff --git a/llvm/lib/IR/RemarkStreamer.cpp b/llvm/lib/IR/RemarkStreamer.cpp index cb2eeeb8616..2c01c8a0c5e 100644 --- a/llvm/lib/IR/RemarkStreamer.cpp +++ b/llvm/lib/IR/RemarkStreamer.cpp @@ -16,7 +16,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" #include "llvm/Remarks/RemarkFormat.h" -#include "llvm/Remarks/YAMLRemarkSerializer.h" +#include "llvm/Remarks/RemarkSerializer.h" using namespace llvm; @@ -107,20 +107,6 @@ char RemarkSetupFileError::ID = 0; char RemarkSetupPatternError::ID = 0; char RemarkSetupFormatError::ID = 0; -static std::unique_ptr<remarks::Serializer> -formatToSerializer(remarks::Format RemarksFormat, raw_ostream &OS) { - switch (RemarksFormat) { - case remarks::Format::Unknown: - llvm_unreachable("Unknown remark serializer format."); - return nullptr; - case remarks::Format::YAML: - return llvm::make_unique<remarks::YAMLSerializer>(OS); - case remarks::Format::YAMLStrTab: - return llvm::make_unique<remarks::YAMLStrTabSerializer>(OS); - }; - llvm_unreachable("Unknown remarks::Format enum"); -} - Expected<std::unique_ptr<ToolOutputFile>> llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, @@ -147,8 +133,13 @@ llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, if (Error E = Format.takeError()) return make_error<RemarkSetupFormatError>(std::move(E)); + Expected<std::unique_ptr<remarks::Serializer>> Serializer = + remarks::createRemarkSerializer(*Format, RemarksFile->os()); + if (Error E = Serializer.takeError()) + return make_error<RemarkSetupFormatError>(std::move(E)); + Context.setRemarkStreamer(llvm::make_unique<RemarkStreamer>( - RemarksFilename, formatToSerializer(*Format, RemarksFile->os()))); + RemarksFilename, std::move(*Serializer))); if (!RemarksPasses.empty()) if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses)) diff --git a/llvm/lib/Remarks/CMakeLists.txt b/llvm/lib/Remarks/CMakeLists.txt index 06ddbab6de5..fff7367f1f7 100644 --- a/llvm/lib/Remarks/CMakeLists.txt +++ b/llvm/lib/Remarks/CMakeLists.txt @@ -2,6 +2,7 @@ add_llvm_library(LLVMRemarks Remark.cpp RemarkFormat.cpp RemarkParser.cpp + RemarkSerializer.cpp RemarkStringTable.cpp YAMLRemarkParser.cpp YAMLRemarkSerializer.cpp diff --git a/llvm/lib/Remarks/RemarkFormat.cpp b/llvm/lib/Remarks/RemarkFormat.cpp index 4e9ada63188..8dcf3e19345 100644 --- a/llvm/lib/Remarks/RemarkFormat.cpp +++ b/llvm/lib/Remarks/RemarkFormat.cpp @@ -24,7 +24,7 @@ Expected<Format> llvm::remarks::parseFormat(StringRef FormatStr) { if (Result == Format::Unknown) return createStringError(std::make_error_code(std::errc::invalid_argument), - "Unknown remark serializer format: '%s'", + "Unknown remark format: '%s'", FormatStr.data()); return Result; diff --git a/llvm/lib/Remarks/RemarkSerializer.cpp b/llvm/lib/Remarks/RemarkSerializer.cpp new file mode 100644 index 00000000000..b1cfd098134 --- /dev/null +++ b/llvm/lib/Remarks/RemarkSerializer.cpp @@ -0,0 +1,48 @@ +//===- RemarkSerializer.cpp -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file provides tools for serializing remarks. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Remarks/RemarkSerializer.h" +#include "llvm/Remarks/YAMLRemarkSerializer.h" + +using namespace llvm; +using namespace llvm::remarks; + +Expected<std::unique_ptr<Serializer>> +remarks::createRemarkSerializer(Format RemarksFormat, raw_ostream &OS) { + switch (RemarksFormat) { + case Format::Unknown: + return createStringError(std::errc::invalid_argument, + "Unknown remark serializer format."); + case Format::YAML: + return llvm::make_unique<YAMLSerializer>(OS); + case Format::YAMLStrTab: + return llvm::make_unique<YAMLStrTabSerializer>(OS); + } + llvm_unreachable("Unknown remarks::Format enum"); +} + +Expected<std::unique_ptr<Serializer>> +remarks::createRemarkSerializer(Format RemarksFormat, raw_ostream &OS, + remarks::StringTable StrTab) { + switch (RemarksFormat) { + case Format::Unknown: + return createStringError(std::errc::invalid_argument, + "Unknown remark serializer format."); + case Format::YAML: + return createStringError(std::errc::invalid_argument, + "Unable to use a string table with the yaml " + "format. Use 'yaml-strtab' instead."); + case Format::YAMLStrTab: + return llvm::make_unique<YAMLStrTabSerializer>(OS, std::move(StrTab)); + } + llvm_unreachable("Unknown remarks::Format enum"); +} diff --git a/llvm/tools/llvm-opt-report/OptReport.cpp b/llvm/tools/llvm-opt-report/OptReport.cpp index 5662c9fbd7b..297b798dc9d 100644 --- a/llvm/tools/llvm-opt-report/OptReport.cpp +++ b/llvm/tools/llvm-opt-report/OptReport.cpp @@ -15,6 +15,7 @@ #include "llvm-c/Remarks.h" #include "llvm/Demangle/Demangle.h" +#include "llvm/Remarks/RemarkFormat.h" #include "llvm/Remarks/RemarkParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" @@ -27,14 +28,12 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "llvm/Support/WithColor.h" -#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" #include <cstdlib> #include <map> #include <set> using namespace llvm; -using namespace llvm::yaml; // Mark all our options with this category, everything else (except for -version // and -help) will be hidden. @@ -61,6 +60,11 @@ static cl::opt<bool> NoDemangle("no-demangle", cl::desc("Don't demangle function names"), cl::init(false), cl::cat(OptReportCategory)); +static cl::opt<std::string> ParserFormat("format", + cl::desc("The format of the remarks."), + cl::init("yaml"), + cl::cat(OptReportCategory)); + namespace { // For each location in the source file, the common per-transformation state // collected. @@ -150,8 +154,17 @@ static bool readLocationInfo(LocationInfoTy &LocationInfo) { return false; } + Expected<remarks::Format> Format = remarks::parseFormat(ParserFormat); + if (!Format) { + handleAllErrors(Format.takeError(), [&](const ErrorInfoBase &PE) { + PE.log(WithColor::error()); + WithColor::error() << '\n'; + }); + return false; + } + Expected<std::unique_ptr<remarks::Parser>> MaybeParser = - remarks::createRemarkParser(remarks::Format::YAML, (*Buf)->getBuffer()); + remarks::createRemarkParser(*Format, (*Buf)->getBuffer()); if (!MaybeParser) { handleAllErrors(MaybeParser.takeError(), [&](const ErrorInfoBase &PE) { PE.log(WithColor::error()); diff --git a/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp b/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp index 629811a8ba1..e1340b4f2e0 100644 --- a/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp +++ b/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp @@ -8,21 +8,32 @@ #include "llvm/Remarks/Remark.h" #include "llvm/Remarks/YAMLRemarkSerializer.h" +#include "llvm/Support/Error.h" #include "gtest/gtest.h" using namespace llvm; -static void check(const remarks::Remark &R, StringRef Expected, - Optional<StringRef> ExpectedStrTab = None) { +static void check(const remarks::Remark &R, StringRef ExpectedR, + Optional<StringRef> ExpectedStrTab = None, + Optional<remarks::StringTable> StrTab = None) { std::string Buf; raw_string_ostream OS(Buf); bool UseStrTab = ExpectedStrTab.hasValue(); - std::unique_ptr<remarks::Serializer> S = - UseStrTab ? llvm::make_unique<remarks::YAMLStrTabSerializer>(OS) - : llvm::make_unique<remarks::YAMLSerializer>(OS); + Expected<std::unique_ptr<remarks::Serializer>> MaybeS = [&] { + if (UseStrTab) { + if (StrTab) + return createRemarkSerializer(remarks::Format::YAMLStrTab, OS, + std::move(*StrTab)); + else + return createRemarkSerializer(remarks::Format::YAMLStrTab, OS); + } else + return createRemarkSerializer(remarks::Format::YAML, OS); + }(); + EXPECT_FALSE(errorToBool(MaybeS.takeError())); + std::unique_ptr<remarks::Serializer> S = std::move(*MaybeS); S->emit(R); - EXPECT_EQ(OS.str(), Expected); + EXPECT_EQ(OS.str(), ExpectedR); if (ExpectedStrTab) { Buf.clear(); EXPECT_TRUE(S->StrTab); @@ -88,3 +99,34 @@ TEST(YAMLRemarks, SerializerRemarkStrTab) { "...\n", StringRef("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45)); } + +TEST(YAMLRemarks, SerializerRemarkParsedStrTab) { + StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45); + remarks::Remark R; + R.RemarkType = remarks::Type::Missed; + R.PassName = "pass"; + R.RemarkName = "name"; + R.FunctionName = "func"; + R.Loc = remarks::RemarkLocation{"path", 3, 4}; + R.Hotness = 5; + R.Args.emplace_back(); + R.Args.back().Key = "key"; + R.Args.back().Val = "value"; + R.Args.emplace_back(); + R.Args.back().Key = "keydebug"; + R.Args.back().Val = "valuedebug"; + R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; + check(R, + "--- !Missed\n" + "Pass: 0\n" + "Name: 1\n" + "DebugLoc: { File: 3, Line: 3, Column: 4 }\n" + "Function: 2\n" + "Hotness: 5\n" + "Args:\n" + " - key: 4\n" + " - keydebug: 5\n" + " DebugLoc: { File: 6, Line: 6, Column: 7 }\n" + "...\n", + StrTab, remarks::StringTable(remarks::ParsedStringTable(StrTab))); +} |