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 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. 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. 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. 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