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
16using namespace llvm;
17using namespace remarks;
18using namespace llvm::remarkutil;
19
20extern ExitOnError ExitOnErr;
21static cl::SubCommand
22 YAML2Bitstream("yaml2bitstream",
23 "Convert YAML remarks to bitstream remarks");
24static cl::SubCommand
25 Bitstream2YAML("bitstream2yaml",
26 "Convert bitstream remarks to YAML remarks");
27
28namespace yaml2bitstream {
29/// Remark format to parse.
30static constexpr Format InputFormat = Format::YAML;
31/// Remark format to output.
32static constexpr Format OutputFormat = Format::Bitstream;
33INPUT_OUTPUT_COMMAND_LINE_OPTIONS(YAML2Bitstream)
34} // namespace yaml2bitstream
35
36namespace bitstream2yaml {
37/// Remark format to parse.
38static constexpr Format InputFormat = Format::Bitstream;
39/// Remark format to output.
40static constexpr Format OutputFormat = Format::YAML;
41INPUT_OUTPUT_COMMAND_LINE_OPTIONS(Bitstream2YAML)
42} // namespace bitstream2yaml
43
44namespace 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.
50static Error
51tryParseRemarksFromYAMLFile(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(ParserFormat: InputFormat, Buf: (*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(R&: **MaybeRemark);
63 ParsedRemarks.push_back(x: std::move(*MaybeRemark));
64 }
65 auto E = MaybeRemark.takeError();
66 if (!E.isA<EndOfFileError>())
67 return E;
68 consumeError(Err: 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.
76static 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 RemarksFormat: OutputFormat, Mode: SerializerMode::Standalone, OS&: OF->os(), StrTab: 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: *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.
96static 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
104namespace bitstream2yaml {
105/// Parse bitstream remarks and reserialize as YAML remarks.
106/// \returns An Error if reserialization fails, or Error::success() on success.
107static 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 RemarksFormat: OutputFormat, Mode: SerializerMode::Standalone, OS&: 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(ParserFormat: InputFormat, Buf: (*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(Remark: **MaybeRemark);
132 auto E = MaybeRemark.takeError();
133 if (!E.isA<EndOfFileError>())
134 return E;
135 consumeError(Err: std::move(E));
136 return Error::success();
137}
138} // namespace bitstream2yaml
139
140static CommandRegistration Bitstream2YamlReg(&Bitstream2YAML,
141 bitstream2yaml::tryBitstream2YAML);
142static CommandRegistration Yaml2Bitstream(&YAML2Bitstream,
143 yaml2bitstream::tryYAML2Bitstream);
144