1 //===- RemarkConvert.cpp -------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Convert remarks from bitstream to yaml and the other way around.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "RemarkUtilHelpers.h"
14 #include "RemarkUtilRegistry.h"
15 
16 using namespace llvm;
17 using namespace remarks;
18 using namespace llvm::remarkutil;
19 
20 extern ExitOnError ExitOnErr;
21 static cl::SubCommand
22     YAML2Bitstream("yaml2bitstream",
23                    "Convert YAML remarks to bitstream remarks");
24 static cl::SubCommand
25     Bitstream2YAML("bitstream2yaml",
26                    "Convert bitstream remarks to YAML remarks");
27 
28 namespace yaml2bitstream {
29 /// Remark format to parse.
30 static constexpr Format InputFormat = Format::YAML;
31 /// Remark format to output.
32 static constexpr Format OutputFormat = Format::Bitstream;
33 INPUT_OUTPUT_COMMAND_LINE_OPTIONS(YAML2Bitstream)
34 } // namespace yaml2bitstream
35 
36 namespace bitstream2yaml {
37 /// Remark format to parse.
38 static constexpr Format InputFormat = Format::Bitstream;
39 /// Remark format to output.
40 static constexpr Format OutputFormat = Format::YAML;
41 INPUT_OUTPUT_COMMAND_LINE_OPTIONS(Bitstream2YAML)
42 } // namespace bitstream2yaml
43 
44 namespace yaml2bitstream {
45 /// Parses all remarks in the input YAML file.
46 /// \p [out] ParsedRemarks - Filled with remarks parsed from the input file.
47 /// \p [out] StrTab - A string table populated for later remark serialization.
48 /// \returns Error::success() if all remarks were successfully parsed, and an
49 /// Error otherwise.
50 static Error
tryParseRemarksFromYAMLFile(std::vector<std::unique_ptr<Remark>> & ParsedRemarks,StringTable & StrTab)51 tryParseRemarksFromYAMLFile(std::vector<std::unique_ptr<Remark>> &ParsedRemarks,
52                             StringTable &StrTab) {
53   auto MaybeBuf = getInputMemoryBuffer(InputFileName);
54   if (!MaybeBuf)
55     return MaybeBuf.takeError();
56   auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
57   if (!MaybeParser)
58     return MaybeParser.takeError();
59   auto &Parser = **MaybeParser;
60   auto MaybeRemark = Parser.next();
61   for (; MaybeRemark; MaybeRemark = Parser.next()) {
62     StrTab.internalize(**MaybeRemark);
63     ParsedRemarks.push_back(std::move(*MaybeRemark));
64   }
65   auto E = MaybeRemark.takeError();
66   if (!E.isA<EndOfFileError>())
67     return E;
68   consumeError(std::move(E));
69   return Error::success();
70 }
71 
72 /// Reserialize a list of parsed YAML remarks into bitstream remarks.
73 /// \p ParsedRemarks - A list of remarks.
74 /// \p StrTab - The string table for the remarks.
75 /// \returns Error::success() on success.
tryReserializeYAML2Bitstream(const std::vector<std::unique_ptr<Remark>> & ParsedRemarks,StringTable & StrTab)76 static Error tryReserializeYAML2Bitstream(
77     const std::vector<std::unique_ptr<Remark>> &ParsedRemarks,
78     StringTable &StrTab) {
79   auto MaybeOF = getOutputFileForRemarks(OutputFileName, OutputFormat);
80   if (!MaybeOF)
81     return MaybeOF.takeError();
82   auto OF = std::move(*MaybeOF);
83   auto MaybeSerializer = createRemarkSerializer(
84       OutputFormat, SerializerMode::Standalone, OF->os(), std::move(StrTab));
85   if (!MaybeSerializer)
86     return MaybeSerializer.takeError();
87   auto Serializer = std::move(*MaybeSerializer);
88   for (const auto &Remark : ParsedRemarks)
89     Serializer->emit(*Remark);
90   OF->keep();
91   return Error::success();
92 }
93 
94 /// Parse YAML remarks and reserialize as bitstream remarks.
95 /// \returns Error::success() on success, and an Error otherwise.
tryYAML2Bitstream()96 static Error tryYAML2Bitstream() {
97   StringTable StrTab;
98   std::vector<std::unique_ptr<Remark>> ParsedRemarks;
99   ExitOnErr(tryParseRemarksFromYAMLFile(ParsedRemarks, StrTab));
100   return tryReserializeYAML2Bitstream(ParsedRemarks, StrTab);
101 }
102 } // namespace yaml2bitstream
103 
104 namespace bitstream2yaml {
105 /// Parse bitstream remarks and reserialize as YAML remarks.
106 /// \returns An Error if reserialization fails, or Error::success() on success.
tryBitstream2YAML()107 static Error tryBitstream2YAML() {
108   // Create the serializer.
109   auto MaybeOF = getOutputFileForRemarks(OutputFileName, OutputFormat);
110   if (!MaybeOF)
111     return MaybeOF.takeError();
112   auto OF = std::move(*MaybeOF);
113   auto MaybeSerializer = createRemarkSerializer(
114       OutputFormat, SerializerMode::Standalone, OF->os());
115   if (!MaybeSerializer)
116     return MaybeSerializer.takeError();
117 
118   // Create the parser.
119   auto MaybeBuf = getInputMemoryBuffer(InputFileName);
120   if (!MaybeBuf)
121     return MaybeBuf.takeError();
122   auto Serializer = std::move(*MaybeSerializer);
123   auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
124   if (!MaybeParser)
125     return MaybeParser.takeError();
126   auto &Parser = **MaybeParser;
127 
128   // Parse + reserialize all remarks.
129   auto MaybeRemark = Parser.next();
130   for (; MaybeRemark; MaybeRemark = Parser.next())
131     Serializer->emit(**MaybeRemark);
132   auto E = MaybeRemark.takeError();
133   if (!E.isA<EndOfFileError>())
134     return E;
135   consumeError(std::move(E));
136   return Error::success();
137 }
138 } // namespace bitstream2yaml
139 
140 static CommandRegistration Bitstream2YamlReg(&Bitstream2YAML,
141                                              bitstream2yaml::tryBitstream2YAML);
142 static CommandRegistration Yaml2Bitstream(&YAML2Bitstream,
143                                           yaml2bitstream::tryYAML2Bitstream);
144