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