llvm.org GIT mirror llvm / 890aba4
[Remarks][NFC] Move the serialization to lib/Remarks Separate the remark serialization to YAML from the LLVM Diagnostics. This adds a new serialization abstraction: remarks::Serializer. It's completely independent from lib/IR and it provides an easy way to replace YAML by providing a new remarks::Serializer. Differential Revision: https://reviews.llvm.org/D62632 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362160 91177308-0d34-0410-b5e6-96231b3b80d8 Francis Visoiu Mistrih 2 months ago
11 changed file(s) with 353 addition(s) and 183 deletion(s). Raw diff Collapse all Expand all
464464 virtual bool isEnabled() const = 0;
465465
466466 StringRef getPassName() const { return PassName; }
467 StringRef getRemarkName() const { return RemarkName; }
467468 std::string getMsg() const;
468469 Optional getHotness() const { return Hotness; }
469470 void setHotness(Optional H) { Hotness = H; }
470471
471472 bool isVerbose() const { return IsVerbose; }
473
474 ArrayRef getArgs() const { return Args; }
472475
473476 static bool classof(const DiagnosticInfo *DI) {
474477 return (DI->getKind() >= DK_FirstRemark &&
499502 const char *PassName;
500503
501504 /// Textual identifier for the remark (single-word, camel-case). Can be used
502 /// by external tools reading the YAML output file for optimization remarks to
505 /// by external tools reading the output file for optimization remarks to
503506 /// identify the remark.
504507 StringRef RemarkName;
505508
517520 /// the optimization records and not in the remark printed in the compiler
518521 /// output.
519522 int FirstExtraArgIndex = -1;
520
521 friend struct yaml::MappingTraits;
522523 };
523524
524525 /// Allow the insertion operator to return the actual remark type rather than a
10001001 void print(DiagnosticPrinter &DP) const override;
10011002 };
10021003
1003 namespace yaml {
1004 template <> struct MappingTraits {
1005 static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag);
1006 };
1007 } // namespace yaml
1008
10091004 } // end namespace llvm
10101005
10111006 #endif // LLVM_IR_DIAGNOSTICINFO_H
1313 #define LLVM_IR_REMARKSTREAMER_H
1414
1515 #include "llvm/IR/DiagnosticInfo.h"
16 #include "llvm/Remarks/RemarkStringTable.h"
16 #include "llvm/Remarks/RemarkSerializer.h"
1717 #include "llvm/Support/Error.h"
1818 #include "llvm/Support/Regex.h"
19 #include "llvm/Support/YAMLTraits.h"
2019 #include "llvm/Support/raw_ostream.h"
2120 #include
2221 #include
2625 class RemarkStreamer {
2726 /// The filename that the remark diagnostics are emitted to.
2827 const std::string Filename;
29 /// The open raw_ostream that the remark diagnostics are emitted to.
30 raw_ostream &OS;
3128 /// The regex used to filter remarks based on the passes that emit them.
3229 Optional PassFilter;
30 /// The object used to serialize the remarks to a specific format.
31 std::unique_ptr Serializer;
3332
34 /// The YAML streamer.
35 yaml::Output YAMLOutput;
36
37 /// The string table containing all the unique strings used in the output.
38 /// The table will be serialized in a section to be consumed after the
39 /// compilation.
40 remarks::StringTable StrTab;
33 /// Temporary buffer for converting diagnostics into remark objects. This is
34 /// used for the remark arguments that are converted from a vector of
35 /// diagnostic arguments to a vector of remark arguments.
36 SmallVector TmpArgs;
37 /// Convert diagnostics into remark objects. The result uses \p TmpArgs as a
38 /// temporary buffer for the remark arguments, and relies on all the strings
39 /// to be kept in memory until the next call to `toRemark`.
40 /// The lifetime of the members of the result is bound to the lifetime of both
41 /// the remark streamer and the LLVM diagnostics.
42 remarks::Remark toRemark(const DiagnosticInfoOptimizationBase &Diag);
4143
4244 public:
43 RemarkStreamer(StringRef Filename, raw_ostream& OS);
45 RemarkStreamer(StringRef Filename,
46 std::unique_ptr Serializer);
4447 /// Return the filename that the remark diagnostics are emitted to.
4548 StringRef getFilename() const { return Filename; }
4649 /// Return stream that the remark diagnostics are emitted to.
47 raw_ostream &getStream() { return OS; }
50 raw_ostream &getStream() { return Serializer->OS; }
51 /// Return the serializer used for this stream.
52 remarks::Serializer &getSerializer() { return *Serializer; }
4853 /// Set a pass filter based on a regex \p Filter.
4954 /// Returns an error if the regex is invalid.
5055 Error setFilter(StringRef Filter);
5156 /// Emit a diagnostic through the streamer.
5257 void emit(const DiagnosticInfoOptimizationBase &Diag);
53 /// The string table used during emission.
54 remarks::StringTable &getStringTable() { return StrTab; }
55 const remarks::StringTable &getStringTable() const { return StrTab; }
5658 };
5759 } // end namespace llvm
5860
}
0 //===-- RemarkSerializer.h - Remark serialization interface -----*- C++ -*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file provides an interface for serializing remarks to different formats.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LLVM_REMARKS_REMARK_SERIALIZER_H
13 #define LLVM_REMARKS_REMARK_SERIALIZER_H
14
15 #include "llvm/Remarks/Remark.h"
16 #include "llvm/Remarks/RemarkStringTable.h"
17 #include "llvm/Support/YAMLTraits.h"
18 #include "llvm/Support/raw_ostream.h"
19
20 namespace llvm {
21 namespace remarks {
22
23 /// This is the base class for a remark serializer.
24 /// It includes support for using a string table while emitting.
25 struct Serializer {
26 /// The open raw_ostream that the remark diagnostics are emitted to.
27 raw_ostream &OS;
28 /// The string table containing all the unique strings used in the output.
29 /// The table can be serialized to be consumed after the compilation.
30 Optional StrTab;
31
32 Serializer(raw_ostream &OS) : OS(OS), StrTab() {}
33
34 /// This is just an interface.
35 virtual ~Serializer() = default;
36 virtual void emit(const Remark &Remark) = 0;
37 };
38
39 /// Wether the serializer should use a string table while emitting.
40 enum class UseStringTable { No, Yes };
41
42 /// Serialize the remarks to YAML. One remark entry looks like this:
43 /// --- !
44 /// Pass:
45 /// Name:
46 /// DebugLoc: { File: , Line: ,
47 /// Column: }
48 /// Function:
49 /// Args:
50 /// - :
51 /// DebugLoc: { File: , Line: , Column:
52 /// ...
53 struct YAMLSerializer : public Serializer {
54 /// The YAML streamer.
55 yaml::Output YAMLOutput;
56
57 YAMLSerializer(raw_ostream &OS,
58 UseStringTable UseStringTable = UseStringTable::No);
59
60 /// Emit a remark to the stream.
61 void emit(const Remark &Remark) override;
62 };
63
64 } // end namespace remarks
65 } // end namespace llvm
66
67 #endif /* LLVM_REMARKS_REMARK_SERIALIZER_H */
9999 #include "llvm/MC/SectionKind.h"
100100 #include "llvm/Pass.h"
101101 #include "llvm/Remarks/Remark.h"
102 #include "llvm/Remarks/RemarkStringTable.h"
102103 #include "llvm/Support/Casting.h"
103104 #include "llvm/Support/CommandLine.h"
104105 #include "llvm/Support/Compiler.h"
13461347 RemarkStreamer *RS = M.getContext().getRemarkStreamer();
13471348 if (!RS)
13481349 return;
1350 const remarks::Serializer &Serializer = RS->getSerializer();
13491351
13501352 // Switch to the right section: .remarks/__remarks.
13511353 MCSection *RemarksSection =
13671369 // Note: we need to use the streamer here to emit it in the section. We can't
13681370 // just use the serialize function with a raw_ostream because of the way
13691371 // MCStreamers work.
1370 const remarks::StringTable &StrTab = RS->getStringTable();
1371 std::vector StrTabStrings = StrTab.serialize();
1372 uint64_t StrTabSize = StrTab.SerializedSize;
1372 uint64_t StrTabSize =
1373 Serializer.StrTab ? Serializer.StrTab->SerializedSize : 0;
13731374 // Emit the total size of the string table (the size itself excluded):
13741375 // little-endian uint64_t.
13751376 // The total size is located after the version number.
1377 // Note: even if no string table is used, emit 0.
13761378 std::array StrTabSizeBuf;
13771379 support::endian::write64le(StrTabSizeBuf.data(), StrTabSize);
13781380 OutStreamer->EmitBinaryData(
13791381 StringRef(StrTabSizeBuf.data(), StrTabSizeBuf.size()));
1380 // Emit a list of null-terminated strings.
1381 // Note: the order is important here: the ID used in the remarks corresponds
1382 // to the position of the string in the section.
1383 for (StringRef Str : StrTabStrings) {
1384 OutStreamer->EmitBytes(Str);
1385 // Explicitly emit a '\0'.
1386 OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1);
1382
1383 if (const Optional &StrTab = Serializer.StrTab) {
1384 std::vector StrTabStrings = StrTab->serialize();
1385 // Emit a list of null-terminated strings.
1386 // Note: the order is important here: the ID used in the remarks corresponds
1387 // to the position of the string in the section.
1388 for (StringRef Str : StrTabStrings) {
1389 OutStreamer->EmitBytes(Str);
1390 // Explicitly emit a '\0'.
1391 OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1);
1392 }
13871393 }
13881394
13891395 // Emit the null-terminated absolute path to the remark file.
4242
4343 using namespace llvm;
4444
45 cl::opt UseStringTable("remarks-yaml-string-table", cl::init(false));
46
4745 int llvm::getNextAvailablePluginDiagnosticKind() {
4846 static std::atomic PluginKindID(DK_FirstPluginKind);
4947 return ++PluginKindID;
373371
374372 void OptimizationRemarkAnalysisFPCommute::anchor() {}
375373 void OptimizationRemarkAnalysisAliasing::anchor() {}
376
377 template
378 static void mapRemarkHeader(
379 yaml::IO &io, T PassName, T RemarkName, DiagnosticLocation DL,
380 T FunctionName, Optional Hotness,
381 SmallVectorImpl &Args) {
382 io.mapRequired("Pass", PassName);
383 io.mapRequired("Name", RemarkName);
384 if (!io.outputting() || DL.isValid())
385 io.mapOptional("DebugLoc", DL);
386 io.mapRequired("Function", FunctionName);
387 io.mapOptional("Hotness", Hotness);
388 io.mapOptional("Args", Args);
389 }
390
391 namespace llvm {
392 namespace yaml {
393
394 void MappingTraits::mapping(
395 IO &io, DiagnosticInfoOptimizationBase *&OptDiag) {
396 assert(io.outputting() && "input not yet implemented");
397
398 if (io.mapTag("!Passed",
399 (OptDiag->getKind() == DK_OptimizationRemark ||
400 OptDiag->getKind() == DK_MachineOptimizationRemark)))
401 ;
402 else if (io.mapTag(
403 "!Missed",
404 (OptDiag->getKind() == DK_OptimizationRemarkMissed ||
405 OptDiag->getKind() == DK_MachineOptimizationRemarkMissed)))
406 ;
407 else if (io.mapTag(
408 "!Analysis",
409 (OptDiag->getKind() == DK_OptimizationRemarkAnalysis ||
410 OptDiag->getKind() == DK_MachineOptimizationRemarkAnalysis)))
411 ;
412 else if (io.mapTag("!AnalysisFPCommute",
413 OptDiag->getKind() ==
414 DK_OptimizationRemarkAnalysisFPCommute))
415 ;
416 else if (io.mapTag("!AnalysisAliasing",
417 OptDiag->getKind() ==
418 DK_OptimizationRemarkAnalysisAliasing))
419 ;
420 else if (io.mapTag("!Failure", OptDiag->getKind() == DK_OptimizationFailure))
421 ;
422 else
423 llvm_unreachable("Unknown remark type");
424
425 // These are read-only for now.
426 DiagnosticLocation DL = OptDiag->getLocation();
427 StringRef FN =
428 GlobalValue::dropLLVMManglingEscape(OptDiag->getFunction().getName());
429
430 StringRef PassName(OptDiag->PassName);
431 if (UseStringTable) {
432 remarks::StringTable &StrTab =
433 reinterpret_cast(io.getContext())->getStringTable();
434 unsigned PassID = StrTab.add(PassName).first;
435 unsigned NameID = StrTab.add(OptDiag->RemarkName).first;
436 unsigned FunctionID = StrTab.add(FN).first;
437 mapRemarkHeader(io, PassID, NameID, DL, FunctionID, OptDiag->Hotness,
438 OptDiag->Args);
439 } else {
440 mapRemarkHeader(io, PassName, OptDiag->RemarkName, DL, FN, OptDiag->Hotness,
441 OptDiag->Args);
442 }
443 }
444
445 template <> struct MappingTraits {
446 static void mapping(IO &io, DiagnosticLocation &DL) {
447 assert(io.outputting() && "input not yet implemented");
448
449 StringRef File = DL.getRelativePath();
450 unsigned Line = DL.getLine();
451 unsigned Col = DL.getColumn();
452
453 if (UseStringTable) {
454 remarks::StringTable &StrTab =
455 reinterpret_cast(io.getContext())->getStringTable();
456 unsigned FileID = StrTab.add(File).first;
457 io.mapRequired("File", FileID);
458 } else {
459 io.mapRequired("File", File);
460 }
461
462 io.mapRequired("Line", Line);
463 io.mapRequired("Column", Col);
464 }
465
466 static const bool flow = true;
467 };
468
469 /// Helper struct for multiline string block literals. Use this type to preserve
470 /// newlines in strings.
471 struct StringBlockVal {
472 StringRef Value;
473 StringBlockVal(const std::string &Value) : Value(Value) {}
474 };
475
476 template <> struct BlockScalarTraits {
477 static void output(const StringBlockVal &S, void *Ctx, raw_ostream &OS) {
478 return ScalarTraits::output(S.Value, Ctx, OS);
479 }
480
481 static StringRef input(StringRef Scalar, void *Ctx, StringBlockVal &S) {
482 return ScalarTraits::input(Scalar, Ctx, S.Value);
483 }
484 };
485
486 // Implement this as a mapping for now to get proper quotation for the value.
487 template <> struct MappingTraits {
488 static void mapping(IO &io, DiagnosticInfoOptimizationBase::Argument &A) {
489 assert(io.outputting() && "input not yet implemented");
490
491 if (UseStringTable) {
492 remarks::StringTable &StrTab =
493 reinterpret_cast(io.getContext())->getStringTable();
494 auto ValueID = StrTab.add(A.Val).first;
495 io.mapRequired(A.Key.data(), ValueID);
496 } else if (StringRef(A.Val).count('\n') > 1) {
497 StringBlockVal S(A.Val);
498 io.mapRequired(A.Key.data(), S);
499 } else {
500 io.mapRequired(A.Key.data(), A.Val);
501 }
502 if (A.Loc.isValid())
503 io.mapOptional("DebugLoc", A.Loc);
504 }
505 };
506
507 } // end namespace yaml
508 } // end namespace llvm
509
510 LLVM_YAML_IS_SEQUENCE_VECTOR(DiagnosticInfoOptimizationBase::Argument)
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "llvm/IR/RemarkStreamer.h"
14 #include "llvm/IR/DiagnosticInfo.h"
15 #include "llvm/IR/Function.h"
16 #include "llvm/IR/GlobalValue.h"
1417
1518 using namespace llvm;
1619
17 RemarkStreamer::RemarkStreamer(StringRef Filename, raw_ostream &OS)
18 : Filename(Filename), OS(OS),
19 YAMLOutput(OS, reinterpret_cast(this)), StrTab() {
20 RemarkStreamer::RemarkStreamer(StringRef Filename,
21 std::unique_ptr Serializer)
22 : Filename(Filename), PassFilter(), Serializer(std::move(Serializer)) {
2023 assert(!Filename.empty() && "This needs to be a real filename.");
2124 }
2225
3033 return Error::success();
3134 }
3235
36 /// DiagnosticKind -> remarks::Type
37 static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
38 switch (Kind) {
39 default:
40 return remarks::Type::Unknown;
41 case DK_OptimizationRemark:
42 case DK_MachineOptimizationRemark:
43 return remarks::Type::Passed;
44 case DK_OptimizationRemarkMissed:
45 case DK_MachineOptimizationRemarkMissed:
46 return remarks::Type::Missed;
47 case DK_OptimizationRemarkAnalysis:
48 case DK_MachineOptimizationRemarkAnalysis:
49 return remarks::Type::Analysis;
50 case DK_OptimizationRemarkAnalysisFPCommute:
51 return remarks::Type::AnalysisFPCommute;
52 case DK_OptimizationRemarkAnalysisAliasing:
53 return remarks::Type::AnalysisAliasing;
54 case DK_OptimizationFailure:
55 return remarks::Type::Failure;
56 }
57 }
58
59 /// DiagnosticLocation -> remarks::RemarkLocation.
60 static Optional
61 toRemarkLocation(const DiagnosticLocation &DL) {
62 if (!DL.isValid())
63 return None;
64 StringRef File = DL.getRelativePath();
65 unsigned Line = DL.getLine();
66 unsigned Col = DL.getColumn();
67 return remarks::RemarkLocation{File, Line, Col};
68 }
69
70 /// LLVM Diagnostic -> Remark
71 remarks::Remark
72 RemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) {
73 // Re-use the buffer.
74 TmpArgs.clear();
75
76 remarks::Remark R; // The result.
77 R.RemarkType = toRemarkType(static_cast(Diag.getKind()));
78 R.PassName = Diag.getPassName();
79 R.RemarkName = Diag.getRemarkName();
80 R.FunctionName =
81 GlobalValue::dropLLVMManglingEscape(Diag.getFunction().getName());
82 R.Loc = toRemarkLocation(Diag.getLocation());
83 R.Hotness = Diag.getHotness();
84
85 // Use TmpArgs to build the list of arguments and re-use the memory allocated
86 // from previous remark conversions.
87 for (const DiagnosticInfoOptimizationBase::Argument &Arg : Diag.getArgs()) {
88 TmpArgs.emplace_back();
89 TmpArgs.back().Key = Arg.Key;
90 TmpArgs.back().Val = Arg.Val;
91 TmpArgs.back().Loc = toRemarkLocation(Arg.Loc);
92 }
93 R.Args = TmpArgs; // This is valid until the next call to this function.
94
95 return R;
96 }
97
3398 void RemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
3499 if (Optional &Filter = PassFilter)
35100 if (!Filter->match(Diag.getPassName()))
36101 return;
37102
38 DiagnosticInfoOptimizationBase *DiagPtr =
39 const_cast(&Diag);
40 YAMLOutput << DiagPtr;
103 // First, convert the diagnostic to a remark.
104 remarks::Remark R = toRemark(Diag);
105 // Then, emit the remark through the serializer.
106 Serializer->emit(R);
41107 }
13551355 llvm::make_unique(Filename, EC, sys::fs::F_None);
13561356 if (EC)
13571357 return errorCodeToError(EC);
1358 Context.setRemarkStreamer(
1359 llvm::make_unique(Filename, DiagnosticFile->os()));
1358 Context.setRemarkStreamer(llvm::make_unique(
1359 Filename,
1360 llvm::make_unique(DiagnosticFile->os())));
13601361
13611362 if (!LTORemarksPasses.empty())
13621363 if (Error E = Context.getRemarkStreamer()->setFilter(LTORemarksPasses))
22 RemarkParser.cpp
33 RemarkStringTable.cpp
44 YAMLRemarkParser.cpp
5 YAMLRemarkSerializer.cpp
56 )
0 //===- YAMLRemarkSerializer.cpp -------------------------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file provides the implementation of the YAML remark serializer using
9 // LLVM's YAMLTraits.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Remarks/RemarkSerializer.h"
14 #include "llvm/Support/CommandLine.h"
15
16 using namespace llvm;
17 using namespace llvm::remarks;
18
19 cl::opt RemarksYAMLStringTable("remarks-yaml-string-table",
20 cl::init(false));
21
22 // Use the same keys whether we use a string table or not (respectively, T is an
23 // unsigned or a StringRef).
24 template
25 static void mapRemarkHeader(yaml::IO &io, T PassName, T RemarkName,
26 Optional RL, T FunctionName,
27 Optional Hotness,
28 ArrayRef Args) {
29 io.mapRequired("Pass", PassName);
30 io.mapRequired("Name", RemarkName);
31 io.mapOptional("DebugLoc", RL);
32 io.mapRequired("Function", FunctionName);
33 io.mapOptional("Hotness", Hotness);
34 io.mapOptional("Args", Args);
35 }
36
37 namespace llvm {
38 namespace yaml {
39
40 template <> struct MappingTraits {
41 static void mapping(IO &io, remarks::Remark *&Remark) {
42 assert(io.outputting() && "input not yet implemented");
43
44 if (io.mapTag("!Passed", (Remark->RemarkType == Type::Passed)))
45 ;
46 else if (io.mapTag("!Missed", (Remark->RemarkType == Type::Missed)))
47 ;
48 else if (io.mapTag("!Analysis", (Remark->RemarkType == Type::Analysis)))
49 ;
50 else if (io.mapTag("!AnalysisFPCommute",
51 (Remark->RemarkType == Type::AnalysisFPCommute)))
52 ;
53 else if (io.mapTag("!AnalysisAliasing",
54 (Remark->RemarkType == Type::AnalysisAliasing)))
55 ;
56 else if (io.mapTag("!Failure", (Remark->RemarkType == Type::Failure)))
57 ;
58 else
59 llvm_unreachable("Unknown remark type");
60
61 if (Optional &StrTab =
62 reinterpret_cast(io.getContext())->StrTab) {
63 unsigned PassID = StrTab->add(Remark->PassName).first;
64 unsigned NameID = StrTab->add(Remark->RemarkName).first;
65 unsigned FunctionID = StrTab->add(Remark->FunctionName).first;
66 mapRemarkHeader(io, PassID, NameID, Remark->Loc, FunctionID,
67 Remark->Hotness, Remark->Args);
68 } else {
69 mapRemarkHeader(io, Remark->PassName, Remark->RemarkName, Remark->Loc,
70 Remark->FunctionName, Remark->Hotness, Remark->Args);
71 }
72 }
73 };
74
75 template <> struct MappingTraits {
76 static void mapping(IO &io, RemarkLocation &RL) {
77 assert(io.outputting() && "input not yet implemented");
78
79 StringRef File = RL.SourceFilePath;
80 unsigned Line = RL.SourceLine;
81 unsigned Col = RL.SourceColumn;
82
83 if (Optional &StrTab =
84 reinterpret_cast(io.getContext())->StrTab) {
85 unsigned FileID = StrTab->add(File).first;
86 io.mapRequired("File", FileID);
87 } else {
88 io.mapRequired("File", File);
89 }
90
91 io.mapRequired("Line", Line);
92 io.mapRequired("Column", Col);
93 }
94
95 static const bool flow = true;
96 };
97
98 /// Helper struct for multiline string block literals. Use this type to preserve
99 /// newlines in strings.
100 struct StringBlockVal {
101 StringRef Value;
102 StringBlockVal(const std::string &Value) : Value(Value) {}
103 };
104
105 template <> struct BlockScalarTraits {
106 static void output(const StringBlockVal &S, void *Ctx, raw_ostream &OS) {
107 return ScalarTraits::output(S.Value, Ctx, OS);
108 }
109
110 static StringRef input(StringRef Scalar, void *Ctx, StringBlockVal &S) {
111 return ScalarTraits::input(Scalar, Ctx, S.Value);
112 }
113 };
114
115 /// ArrayRef is not really compatible with the YAMLTraits. Everything should be
116 /// immutable in an ArrayRef, while the SequenceTraits expect a mutable version
117 /// for inputting, but we're only using the outputting capabilities here.
118 /// This is a hack, but still nicer than having to manually call the YAMLIO
119 /// internal methods.
120 /// Keep this in this file so that it doesn't get misused from YAMLTraits.h.
121 template struct SequenceTraits> {
122 static size_t size(IO &io, ArrayRef &seq) { return seq.size(); }
123 static Argument &element(IO &io, ArrayRef &seq, size_t index) {
124 assert(io.outputting() && "input not yet implemented");
125 // The assert above should make this "safer" to satisfy the YAMLTraits.
126 return const_cast(seq[index]);
127 }
128 };
129
130 /// Implement this as a mapping for now to get proper quotation for the value.
131 template <> struct MappingTraits {
132 static void mapping(IO &io, Argument &A) {
133 assert(io.outputting() && "input not yet implemented");
134
135 if (Optional &StrTab =
136 reinterpret_cast(io.getContext())->StrTab) {
137 auto ValueID = StrTab->add(A.Val).first;
138 io.mapRequired(A.Key.data(), ValueID);
139 } else if (StringRef(A.Val).count('\n') > 1) {
140 StringBlockVal S(A.Val);
141 io.mapRequired(A.Key.data(), S);
142 } else {
143 io.mapRequired(A.Key.data(), A.Val);
144 }
145 io.mapOptional("DebugLoc", A.Loc);
146 }
147 };
148
149 } // end namespace yaml
150 } // end namespace llvm
151
152 LLVM_YAML_IS_SEQUENCE_VECTOR(Argument)
153
154 YAMLSerializer::YAMLSerializer(raw_ostream &OS, UseStringTable UseStringTable)
155 : Serializer(OS), YAMLOutput(OS, reinterpret_cast(this)) {
156 if (UseStringTable == UseStringTable::Yes || RemarksYAMLStringTable)
157 StrTab.emplace();
158 }
159
160 void YAMLSerializer::emit(const Remark &Remark) {
161 // Again, YAMLTraits expect a non-const object for inputting, but we're not
162 // using that here.
163 auto R = const_cast(&Remark);
164 YAMLOutput << R;
165 }
339339 WithColor::error(errs(), argv[0]) << EC.message() << '\n';
340340 return 1;
341341 }
342 Context.setRemarkStreamer(
343 llvm::make_unique(RemarksFilename, YamlFile->os()));
342 Context.setRemarkStreamer(llvm::make_unique(
343 RemarksFilename,
344 llvm::make_unique(YamlFile->os())));
344345
345346 if (!RemarksPasses.empty())
346347 if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses)) {
562562 return 1;
563563 }
564564 Context.setRemarkStreamer(llvm::make_unique(
565 RemarksFilename, OptRemarkFile->os()));
565 RemarksFilename,
566 llvm::make_unique(OptRemarkFile->os())));
566567
567568 if (!RemarksPasses.empty())
568569 if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses)) {