LLVM  10.0.0svn
YAMLRemarkSerializer.cpp
Go to the documentation of this file.
1 //===- YAMLRemarkSerializer.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 // This file provides the implementation of the YAML remark serializer using
10 // LLVM's YAMLTraits.
11 //
12 //===----------------------------------------------------------------------===//
13 
16 
17 using namespace llvm;
18 using namespace llvm::remarks;
19 
20 // Use the same keys whether we use a string table or not (respectively, T is an
21 // unsigned or a StringRef).
22 template <typename T>
23 static void mapRemarkHeader(yaml::IO &io, T PassName, T RemarkName,
24  Optional<RemarkLocation> RL, T FunctionName,
25  Optional<uint64_t> Hotness,
27  io.mapRequired("Pass", PassName);
28  io.mapRequired("Name", RemarkName);
29  io.mapOptional("DebugLoc", RL);
30  io.mapRequired("Function", FunctionName);
31  io.mapOptional("Hotness", Hotness);
32  io.mapOptional("Args", Args);
33 }
34 
35 namespace llvm {
36 namespace yaml {
37 
38 template <> struct MappingTraits<remarks::Remark *> {
39  static void mapping(IO &io, remarks::Remark *&Remark) {
40  assert(io.outputting() && "input not yet implemented");
41 
42  if (io.mapTag("!Passed", (Remark->RemarkType == Type::Passed)))
43  ;
44  else if (io.mapTag("!Missed", (Remark->RemarkType == Type::Missed)))
45  ;
46  else if (io.mapTag("!Analysis", (Remark->RemarkType == Type::Analysis)))
47  ;
48  else if (io.mapTag("!AnalysisFPCommute",
49  (Remark->RemarkType == Type::AnalysisFPCommute)))
50  ;
51  else if (io.mapTag("!AnalysisAliasing",
52  (Remark->RemarkType == Type::AnalysisAliasing)))
53  ;
54  else if (io.mapTag("!Failure", (Remark->RemarkType == Type::Failure)))
55  ;
56  else
57  llvm_unreachable("Unknown remark type");
58 
59  if (auto *Serializer = dyn_cast<YAMLStrTabRemarkSerializer>(
60  reinterpret_cast<RemarkSerializer *>(io.getContext()))) {
61  assert(Serializer->StrTab.hasValue() &&
62  "YAMLStrTabSerializer with no StrTab.");
63  StringTable &StrTab = *Serializer->StrTab;
64  unsigned PassID = StrTab.add(Remark->PassName).first;
65  unsigned NameID = StrTab.add(Remark->RemarkName).first;
66  unsigned FunctionID = StrTab.add(Remark->FunctionName).first;
67  mapRemarkHeader(io, PassID, NameID, Remark->Loc, FunctionID,
68  Remark->Hotness, Remark->Args);
69  } else {
70  mapRemarkHeader(io, Remark->PassName, Remark->RemarkName, Remark->Loc,
71  Remark->FunctionName, Remark->Hotness, Remark->Args);
72  }
73  }
74 };
75 
76 template <> struct MappingTraits<RemarkLocation> {
77  static void mapping(IO &io, RemarkLocation &RL) {
78  assert(io.outputting() && "input not yet implemented");
79 
81  unsigned Line = RL.SourceLine;
82  unsigned Col = RL.SourceColumn;
83 
84  if (auto *Serializer = dyn_cast<YAMLStrTabRemarkSerializer>(
85  reinterpret_cast<RemarkSerializer *>(io.getContext()))) {
86  assert(Serializer->StrTab.hasValue() &&
87  "YAMLStrTabSerializer with no StrTab.");
88  StringTable &StrTab = *Serializer->StrTab;
89  unsigned FileID = StrTab.add(File).first;
90  io.mapRequired("File", FileID);
91  } else {
92  io.mapRequired("File", File);
93  }
94 
95  io.mapRequired("Line", Line);
96  io.mapRequired("Column", Col);
97  }
98 
99  static const bool flow = true;
100 };
101 
102 /// Helper struct for multiline string block literals. Use this type to preserve
103 /// newlines in strings.
106  StringBlockVal(StringRef R) : Value(R) {}
107 };
108 
109 template <> struct BlockScalarTraits<StringBlockVal> {
110  static void output(const StringBlockVal &S, void *Ctx, raw_ostream &OS) {
111  return ScalarTraits<StringRef>::output(S.Value, Ctx, OS);
112  }
113 
114  static StringRef input(StringRef Scalar, void *Ctx, StringBlockVal &S) {
115  return ScalarTraits<StringRef>::input(Scalar, Ctx, S.Value);
116  }
117 };
118 
119 /// ArrayRef is not really compatible with the YAMLTraits. Everything should be
120 /// immutable in an ArrayRef, while the SequenceTraits expect a mutable version
121 /// for inputting, but we're only using the outputting capabilities here.
122 /// This is a hack, but still nicer than having to manually call the YAMLIO
123 /// internal methods.
124 /// Keep this in this file so that it doesn't get misused from YAMLTraits.h.
125 template <typename T> struct SequenceTraits<ArrayRef<T>> {
126  static size_t size(IO &io, ArrayRef<T> &seq) { return seq.size(); }
127  static Argument &element(IO &io, ArrayRef<T> &seq, size_t index) {
128  assert(io.outputting() && "input not yet implemented");
129  // The assert above should make this "safer" to satisfy the YAMLTraits.
130  return const_cast<T &>(seq[index]);
131  }
132 };
133 
134 /// Implement this as a mapping for now to get proper quotation for the value.
135 template <> struct MappingTraits<Argument> {
136  static void mapping(IO &io, Argument &A) {
137  assert(io.outputting() && "input not yet implemented");
138 
139  if (auto *Serializer = dyn_cast<YAMLStrTabRemarkSerializer>(
140  reinterpret_cast<RemarkSerializer *>(io.getContext()))) {
141  assert(Serializer->StrTab.hasValue() &&
142  "YAMLStrTabSerializer with no StrTab.");
143  StringTable &StrTab = *Serializer->StrTab;
144  auto ValueID = StrTab.add(A.Val).first;
145  io.mapRequired(A.Key.data(), ValueID);
146  } else if (StringRef(A.Val).count('\n') > 1) {
147  StringBlockVal S(A.Val);
148  io.mapRequired(A.Key.data(), S);
149  } else {
150  io.mapRequired(A.Key.data(), A.Val);
151  }
152  io.mapOptional("DebugLoc", A.Loc);
153  }
154 };
155 
156 } // end namespace yaml
157 } // end namespace llvm
158 
159 LLVM_YAML_IS_SEQUENCE_VECTOR(Argument)
160 
162  Optional<StringTable> StrTabIn)
163  : YAMLRemarkSerializer(Format::YAML, OS, Mode, std::move(StrTabIn)) {}
164 
167  Optional<StringTable> StrTabIn)
168  : RemarkSerializer(SerializerFormat, OS, Mode),
169  YAMLOutput(OS, reinterpret_cast<void *>(this)) {
170  StrTab = std::move(StrTabIn);
171 }
172 
174  // Again, YAMLTraits expect a non-const object for inputting, but we're not
175  // using that here.
176  auto R = const_cast<remarks::Remark *>(&Remark);
177  YAMLOutput << R;
178 }
179 
180 std::unique_ptr<MetaSerializer>
182  Optional<StringRef> ExternalFilename) {
183  return std::make_unique<YAMLMetaSerializer>(OS, ExternalFilename);
184 }
185 
187  // In standalone mode, for the serializer with a string table, emit the
188  // metadata first and set DidEmitMeta to avoid emitting it again.
189  if (Mode == SerializerMode::Standalone && !DidEmitMeta) {
190  std::unique_ptr<MetaSerializer> MetaSerializer =
191  metaSerializer(OS, /*ExternalFilename=*/None);
192  MetaSerializer->emit();
193  DidEmitMeta = true;
194  }
195 
196  // Then do the usual remark emission.
198 }
199 
200 std::unique_ptr<MetaSerializer> YAMLStrTabRemarkSerializer::metaSerializer(
201  raw_ostream &OS, Optional<StringRef> ExternalFilename) {
202  assert(StrTab);
203  return std::make_unique<YAMLStrTabMetaSerializer>(OS, ExternalFilename,
204  *StrTab);
205 }
206 
207 static void emitMagic(raw_ostream &OS) {
208  // Emit the magic number.
209  OS << remarks::Magic;
210  // Explicitly emit a '\0'.
211  OS.write('\0');
212 }
213 
214 static void emitVersion(raw_ostream &OS) {
215  // Emit the version number: little-endian uint64_t.
216  std::array<char, 8> Version;
218  OS.write(Version.data(), Version.size());
219 }
220 
222  // Emit the string table in the section.
223  uint64_t StrTabSize = StrTab ? (*StrTab)->SerializedSize : 0;
224  // Emit the total size of the string table (the size itself excluded):
225  // little-endian uint64_t.
226  // Note: even if no string table is used, emit 0.
227  std::array<char, 8> StrTabSizeBuf;
228  support::endian::write64le(StrTabSizeBuf.data(), StrTabSize);
229  OS.write(StrTabSizeBuf.data(), StrTabSizeBuf.size());
230  if (StrTab)
231  (*StrTab)->serialize(OS);
232 }
233 
234 static void emitExternalFile(raw_ostream &OS, StringRef Filename) {
235  // Emit the null-terminated absolute path to the remark file.
236  SmallString<128> FilenameBuf = Filename;
237  sys::fs::make_absolute(FilenameBuf);
238  assert(!FilenameBuf.empty() && "The filename can't be empty.");
239  OS.write(FilenameBuf.data(), FilenameBuf.size());
240  OS.write('\0');
241 }
242 
244  emitMagic(OS);
245  emitVersion(OS);
246  emitStrTab(OS, None);
247  if (ExternalFilename)
248  emitExternalFile(OS, *ExternalFilename);
249 }
250 
252  emitMagic(OS);
253  emitVersion(OS);
254  emitStrTab(OS, &StrTab);
255  if (ExternalFilename)
256  emitExternalFile(OS, *ExternalFilename);
257 }
const NoneType None
Definition: None.h:23
This class represents an incoming formal argument to a Function.
Definition: Argument.h:29
SI Whole Quad Mode
This class represents lattice values for constants.
Definition: AllocatorList.h:23
StringRef PassName
Name of the pass that triggers the emission of this remark.
Definition: Remark.h:72
std::unique_ptr< MetaSerializer > metaSerializer(raw_ostream &OS, Optional< StringRef > ExternalFilename=None) override
Return the corresponding metadata serializer.
static void mapping(IO &io, RemarkLocation &RL)
Helper struct for multiline string block literals.
Optional< uint64_t > Hotness
If profile information is available, this is the number of times the corresponding code was executed ...
Definition: Remark.h:87
static void output(const StringBlockVal &S, void *Ctx, raw_ostream &OS)
static void emitVersion(raw_ostream &OS)
Format
The format used for serializing/deserializing remarks.
Definition: RemarkFormat.h:25
size_t SerializedSize
Total size of the string table when serialized.
Definition: BitVector.h:937
A remark type used for both emission and parsing.
Definition: Remark.h:67
void emit(const Remark &Remark) override
Override to emit the metadata if necessary.
LLVM_NODISCARD size_t count(char C) const
Return the number of occurrences of C in the string.
Definition: StringRef.h:471
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition: Path.cpp:853
StringRef RemarkName
Textual identifier for the remark (single-word, camel-case).
Definition: Remark.h:77
YAMLRemarkSerializer(raw_ostream &OS, SerializerMode Mode, Optional< StringTable > StrTab=None)
static void mapRemarkHeader(yaml::IO &io, T PassName, T RemarkName, Optional< RemarkLocation > RL, T FunctionName, Optional< uint64_t > Hotness, ArrayRef< Argument > Args)
static void mapping(IO &io, Argument &A)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
SerializerMode Mode
The serialization mode.
constexpr StringLiteral Magic("REMARKS")
The string table used for serializing remarks.
static void emitStrTab(raw_ostream &OS, Optional< const StringTable *> StrTab)
Optional< RemarkLocation > Loc
The location in the source file of the remark.
Definition: Remark.h:83
static StringRef input(StringRef Scalar, void *Ctx, StringBlockVal &S)
Instrumentation for Order File
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:148
The debug location used to track a remark back to the source file.
Definition: Remark.h:30
StringRef SourceFilePath
Absolute path of the source file corresponding to this remark.
Definition: Remark.h:32
static void emitExternalFile(raw_ostream &OS, StringRef Filename)
void emit(const Remark &Remark) override
Emit a remark to the stream.
size_t size() const
Definition: SmallVector.h:52
Serialize the remarks to YAML.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
raw_ostream & write(unsigned char C)
StringMap< unsigned, BumpPtrAllocator > StrTab
The string table containing all the unique strings used in the output.
This is the base class for a remark metadata serializer.
raw_ostream & OS
The open raw_ostream that the remark diagnostics are emitted to.
This is the base class for a remark serializer.
static Argument & element(IO &io, ArrayRef< T > &seq, size_t index)
iterator_range< detail::value_sequence_iterator< ValueT > > seq(ValueT Begin, ValueT End)
Definition: Sequence.h:75
Type RemarkType
The type of the remark.
Definition: Remark.h:69
StringRef FunctionName
Mangled name of the function that triggers the emssion of this remark.
Definition: Remark.h:80
static void emitMagic(raw_ostream &OS)
void write64le(void *P, uint64_t V)
Definition: Endian.h:419
pointer data()
Return a pointer to the vector&#39;s buffer, even if empty().
Definition: SmallVector.h:144
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:55
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::unique_ptr< MetaSerializer > metaSerializer(raw_ostream &OS, Optional< StringRef > ExternalFilename=None) override
Return the corresponding metadata serializer.
SmallVector< Argument, 5 > Args
Arguments collected via the streaming interface.
Definition: Remark.h:90
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
constexpr uint64_t CurrentRemarkVersion
The current version of the remark entry.
Definition: Remark.h:27
static size_t size(IO &io, ArrayRef< T > &seq)
Optional< StringTable > StrTab
The string table containing all the unique strings used in the output.
static void mapping(IO &io, remarks::Remark *&Remark)
const uint64_t Version
Definition: InstrProf.h:980
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
yaml::Output YAMLOutput
The YAML streamer.