LLVM  16.0.0git
YAMLTraits.h
Go to the documentation of this file.
1 //===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===//
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 #ifndef LLVM_SUPPORT_YAMLTRAITS_H
10 #define LLVM_SUPPORT_YAMLTRAITS_H
11 
12 #include "llvm/ADT/BitVector.h"
13 #include "llvm/ADT/Optional.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ADT/Twine.h"
19 #include "llvm/Support/AlignOf.h"
20 #include "llvm/Support/Allocator.h"
21 #include "llvm/Support/Endian.h"
22 #include "llvm/Support/SMLoc.h"
23 #include "llvm/Support/SourceMgr.h"
26 #include <cassert>
27 #include <map>
28 #include <memory>
29 #include <new>
30 #include <string>
31 #include <system_error>
32 #include <type_traits>
33 #include <vector>
34 
35 namespace llvm {
36 
37 class VersionTuple;
38 
39 namespace yaml {
40 
41 enum class NodeKind : uint8_t {
42  Scalar,
43  Map,
44  Sequence,
45 };
46 
47 struct EmptyContext {};
48 
49 /// This class should be specialized by any type that needs to be converted
50 /// to/from a YAML mapping. For example:
51 ///
52 /// struct MappingTraits<MyStruct> {
53 /// static void mapping(IO &io, MyStruct &s) {
54 /// io.mapRequired("name", s.name);
55 /// io.mapRequired("size", s.size);
56 /// io.mapOptional("age", s.age);
57 /// }
58 /// };
59 template<class T>
60 struct MappingTraits {
61  // Must provide:
62  // static void mapping(IO &io, T &fields);
63  // Optionally may provide:
64  // static std::string validate(IO &io, T &fields);
65  // static void enumInput(IO &io, T &value);
66  //
67  // The optional flow flag will cause generated YAML to use a flow mapping
68  // (e.g. { a: 0, b: 1 }):
69  // static const bool flow = true;
70 };
71 
72 /// This class is similar to MappingTraits<T> but allows you to pass in
73 /// additional context for each map operation. For example:
74 ///
75 /// struct MappingContextTraits<MyStruct, MyContext> {
76 /// static void mapping(IO &io, MyStruct &s, MyContext &c) {
77 /// io.mapRequired("name", s.name);
78 /// io.mapRequired("size", s.size);
79 /// io.mapOptional("age", s.age);
80 /// ++c.TimesMapped;
81 /// }
82 /// };
83 template <class T, class Context> struct MappingContextTraits {
84  // Must provide:
85  // static void mapping(IO &io, T &fields, Context &Ctx);
86  // Optionally may provide:
87  // static std::string validate(IO &io, T &fields, Context &Ctx);
88  //
89  // The optional flow flag will cause generated YAML to use a flow mapping
90  // (e.g. { a: 0, b: 1 }):
91  // static const bool flow = true;
92 };
93 
94 /// This class should be specialized by any integral type that converts
95 /// to/from a YAML scalar where there is a one-to-one mapping between
96 /// in-memory values and a string in YAML. For example:
97 ///
98 /// struct ScalarEnumerationTraits<Colors> {
99 /// static void enumeration(IO &io, Colors &value) {
100 /// io.enumCase(value, "red", cRed);
101 /// io.enumCase(value, "blue", cBlue);
102 /// io.enumCase(value, "green", cGreen);
103 /// }
104 /// };
105 template <typename T, typename Enable = void> struct ScalarEnumerationTraits {
106  // Must provide:
107  // static void enumeration(IO &io, T &value);
108 };
109 
110 /// This class should be specialized by any integer type that is a union
111 /// of bit values and the YAML representation is a flow sequence of
112 /// strings. For example:
113 ///
114 /// struct ScalarBitSetTraits<MyFlags> {
115 /// static void bitset(IO &io, MyFlags &value) {
116 /// io.bitSetCase(value, "big", flagBig);
117 /// io.bitSetCase(value, "flat", flagFlat);
118 /// io.bitSetCase(value, "round", flagRound);
119 /// }
120 /// };
121 template <typename T, typename Enable = void> struct ScalarBitSetTraits {
122  // Must provide:
123  // static void bitset(IO &io, T &value);
124 };
125 
126 /// Describe which type of quotes should be used when quoting is necessary.
127 /// Some non-printable characters need to be double-quoted, while some others
128 /// are fine with simple-quoting, and some don't need any quoting.
129 enum class QuotingType { None, Single, Double };
130 
131 /// This class should be specialized by type that requires custom conversion
132 /// to/from a yaml scalar. For example:
133 ///
134 /// template<>
135 /// struct ScalarTraits<MyType> {
136 /// static void output(const MyType &val, void*, llvm::raw_ostream &out) {
137 /// // stream out custom formatting
138 /// out << llvm::format("%x", val);
139 /// }
140 /// static StringRef input(StringRef scalar, void*, MyType &value) {
141 /// // parse scalar and set `value`
142 /// // return empty string on success, or error string
143 /// return StringRef();
144 /// }
145 /// static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
146 /// };
147 template <typename T, typename Enable = void> struct ScalarTraits {
148  // Must provide:
149  //
150  // Function to write the value as a string:
151  // static void output(const T &value, void *ctxt, llvm::raw_ostream &out);
152  //
153  // Function to convert a string to a value. Returns the empty
154  // StringRef on success or an error string if string is malformed:
155  // static StringRef input(StringRef scalar, void *ctxt, T &value);
156  //
157  // Function to determine if the value should be quoted.
158  // static QuotingType mustQuote(StringRef);
159 };
160 
161 /// This class should be specialized by type that requires custom conversion
162 /// to/from a YAML literal block scalar. For example:
163 ///
164 /// template <>
165 /// struct BlockScalarTraits<MyType> {
166 /// static void output(const MyType &Value, void*, llvm::raw_ostream &Out)
167 /// {
168 /// // stream out custom formatting
169 /// Out << Value;
170 /// }
171 /// static StringRef input(StringRef Scalar, void*, MyType &Value) {
172 /// // parse scalar and set `value`
173 /// // return empty string on success, or error string
174 /// return StringRef();
175 /// }
176 /// };
177 template <typename T>
178 struct BlockScalarTraits {
179  // Must provide:
180  //
181  // Function to write the value as a string:
182  // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out);
183  //
184  // Function to convert a string to a value. Returns the empty
185  // StringRef on success or an error string if string is malformed:
186  // static StringRef input(StringRef Scalar, void *ctxt, T &Value);
187  //
188  // Optional:
189  // static StringRef inputTag(T &Val, std::string Tag)
190  // static void outputTag(const T &Val, raw_ostream &Out)
191 };
192 
193 /// This class should be specialized by type that requires custom conversion
194 /// to/from a YAML scalar with optional tags. For example:
195 ///
196 /// template <>
197 /// struct TaggedScalarTraits<MyType> {
198 /// static void output(const MyType &Value, void*, llvm::raw_ostream
199 /// &ScalarOut, llvm::raw_ostream &TagOut)
200 /// {
201 /// // stream out custom formatting including optional Tag
202 /// Out << Value;
203 /// }
204 /// static StringRef input(StringRef Scalar, StringRef Tag, void*, MyType
205 /// &Value) {
206 /// // parse scalar and set `value`
207 /// // return empty string on success, or error string
208 /// return StringRef();
209 /// }
210 /// static QuotingType mustQuote(const MyType &Value, StringRef) {
211 /// return QuotingType::Single;
212 /// }
213 /// };
214 template <typename T> struct TaggedScalarTraits {
215  // Must provide:
216  //
217  // Function to write the value and tag as strings:
218  // static void output(const T &Value, void *ctx, llvm::raw_ostream &ScalarOut,
219  // llvm::raw_ostream &TagOut);
220  //
221  // Function to convert a string to a value. Returns the empty
222  // StringRef on success or an error string if string is malformed:
223  // static StringRef input(StringRef Scalar, StringRef Tag, void *ctxt, T
224  // &Value);
225  //
226  // Function to determine if the value should be quoted.
227  // static QuotingType mustQuote(const T &Value, StringRef Scalar);
228 };
229 
230 /// This class should be specialized by any type that needs to be converted
231 /// to/from a YAML sequence. For example:
232 ///
233 /// template<>
234 /// struct SequenceTraits<MyContainer> {
235 /// static size_t size(IO &io, MyContainer &seq) {
236 /// return seq.size();
237 /// }
238 /// static MyType& element(IO &, MyContainer &seq, size_t index) {
239 /// if ( index >= seq.size() )
240 /// seq.resize(index+1);
241 /// return seq[index];
242 /// }
243 /// };
244 template<typename T, typename EnableIf = void>
245 struct SequenceTraits {
246  // Must provide:
247  // static size_t size(IO &io, T &seq);
248  // static T::value_type& element(IO &io, T &seq, size_t index);
249  //
250  // The following is option and will cause generated YAML to use
251  // a flow sequence (e.g. [a,b,c]).
252  // static const bool flow = true;
253 };
254 
255 /// This class should be specialized by any type for which vectors of that
256 /// type need to be converted to/from a YAML sequence.
257 template<typename T, typename EnableIf = void>
258 struct SequenceElementTraits {
259  // Must provide:
260  // static const bool flow;
261 };
262 
263 /// This class should be specialized by any type that needs to be converted
264 /// to/from a list of YAML documents.
265 template<typename T>
266 struct DocumentListTraits {
267  // Must provide:
268  // static size_t size(IO &io, T &seq);
269  // static T::value_type& element(IO &io, T &seq, size_t index);
270 };
271 
272 /// This class should be specialized by any type that needs to be converted
273 /// to/from a YAML mapping in the case where the names of the keys are not known
274 /// in advance, e.g. a string map.
275 template <typename T>
276 struct CustomMappingTraits {
277  // static void inputOne(IO &io, StringRef key, T &elem);
278  // static void output(IO &io, T &elem);
279 };
280 
281 /// This class should be specialized by any type that can be represented as
282 /// a scalar, map, or sequence, decided dynamically. For example:
283 ///
284 /// typedef std::unique_ptr<MyBase> MyPoly;
285 ///
286 /// template<>
287 /// struct PolymorphicTraits<MyPoly> {
288 /// static NodeKind getKind(const MyPoly &poly) {
289 /// return poly->getKind();
290 /// }
291 /// static MyScalar& getAsScalar(MyPoly &poly) {
292 /// if (!poly || !isa<MyScalar>(poly))
293 /// poly.reset(new MyScalar());
294 /// return *cast<MyScalar>(poly.get());
295 /// }
296 /// // ...
297 /// };
298 template <typename T> struct PolymorphicTraits {
299  // Must provide:
300  // static NodeKind getKind(const T &poly);
301  // static scalar_type &getAsScalar(T &poly);
302  // static map_type &getAsMap(T &poly);
303  // static sequence_type &getAsSequence(T &poly);
304 };
305 
306 // Only used for better diagnostics of missing traits
307 template <typename T>
308 struct MissingTrait;
309 
310 // Test if ScalarEnumerationTraits<T> is defined on type T.
311 template <class T>
312 struct has_ScalarEnumerationTraits
313 {
314  using Signature_enumeration = void (*)(class IO&, T&);
315 
316  template <typename U>
317  static char test(SameType<Signature_enumeration, &U::enumeration>*);
318 
319  template <typename U>
320  static double test(...);
321 
322  static bool const value =
323  (sizeof(test<ScalarEnumerationTraits<T>>(nullptr)) == 1);
324 };
325 
326 // Test if ScalarBitSetTraits<T> is defined on type T.
327 template <class T>
328 struct has_ScalarBitSetTraits
329 {
330  using Signature_bitset = void (*)(class IO&, T&);
331 
332  template <typename U>
333  static char test(SameType<Signature_bitset, &U::bitset>*);
334 
335  template <typename U>
336  static double test(...);
337 
338  static bool const value = (sizeof(test<ScalarBitSetTraits<T>>(nullptr)) == 1);
339 };
340 
341 // Test if ScalarTraits<T> is defined on type T.
342 template <class T>
343 struct has_ScalarTraits
344 {
345  using Signature_input = StringRef (*)(StringRef, void*, T&);
346  using Signature_output = void (*)(const T&, void*, raw_ostream&);
347  using Signature_mustQuote = QuotingType (*)(StringRef);
348 
349  template <typename U>
350  static char test(SameType<Signature_input, &U::input> *,
351  SameType<Signature_output, &U::output> *,
352  SameType<Signature_mustQuote, &U::mustQuote> *);
353 
354  template <typename U>
355  static double test(...);
356 
357  static bool const value =
358  (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
359 };
360 
361 // Test if BlockScalarTraits<T> is defined on type T.
362 template <class T>
363 struct has_BlockScalarTraits
364 {
365  using Signature_input = StringRef (*)(StringRef, void *, T &);
366  using Signature_output = void (*)(const T &, void *, raw_ostream &);
367 
368  template <typename U>
369  static char test(SameType<Signature_input, &U::input> *,
370  SameType<Signature_output, &U::output> *);
371 
372  template <typename U>
373  static double test(...);
374 
375  static bool const value =
376  (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1);
377 };
378 
379 // Test if TaggedScalarTraits<T> is defined on type T.
380 template <class T> struct has_TaggedScalarTraits {
381  using Signature_input = StringRef (*)(StringRef, StringRef, void *, T &);
382  using Signature_output = void (*)(const T &, void *, raw_ostream &,
383  raw_ostream &);
384  using Signature_mustQuote = QuotingType (*)(const T &, StringRef);
385 
386  template <typename U>
387  static char test(SameType<Signature_input, &U::input> *,
388  SameType<Signature_output, &U::output> *,
389  SameType<Signature_mustQuote, &U::mustQuote> *);
390 
391  template <typename U> static double test(...);
392 
393  static bool const value =
394  (sizeof(test<TaggedScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
395 };
396 
397 // Test if MappingContextTraits<T> is defined on type T.
398 template <class T, class Context> struct has_MappingTraits {
399  using Signature_mapping = void (*)(class IO &, T &, Context &);
400 
401  template <typename U>
402  static char test(SameType<Signature_mapping, &U::mapping>*);
403 
404  template <typename U>
405  static double test(...);
406 
407  static bool const value =
408  (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
409 };
410 
411 // Test if MappingTraits<T> is defined on type T.
412 template <class T> struct has_MappingTraits<T, EmptyContext> {
413  using Signature_mapping = void (*)(class IO &, T &);
414 
415  template <typename U>
416  static char test(SameType<Signature_mapping, &U::mapping> *);
417 
418  template <typename U> static double test(...);
419 
420  static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
421 };
422 
423 // Test if MappingContextTraits<T>::validate() is defined on type T.
424 template <class T, class Context> struct has_MappingValidateTraits {
425  using Signature_validate = std::string (*)(class IO &, T &, Context &);
426 
427  template <typename U>
428  static char test(SameType<Signature_validate, &U::validate>*);
429 
430  template <typename U>
431  static double test(...);
432 
433  static bool const value =
434  (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
435 };
436 
437 // Test if MappingTraits<T>::validate() is defined on type T.
438 template <class T> struct has_MappingValidateTraits<T, EmptyContext> {
439  using Signature_validate = std::string (*)(class IO &, T &);
440 
441  template <typename U>
442  static char test(SameType<Signature_validate, &U::validate> *);
443 
444  template <typename U> static double test(...);
445 
446  static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
447 };
448 
449 // Test if MappingContextTraits<T>::enumInput() is defined on type T.
450 template <class T, class Context> struct has_MappingEnumInputTraits {
451  using Signature_validate = void (*)(class IO &, T &);
452 
453  template <typename U>
454  static char test(SameType<Signature_validate, &U::enumInput> *);
455 
456  template <typename U> static double test(...);
457 
458  static bool const value =
459  (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
460 };
461 
462 // Test if MappingTraits<T>::enumInput() is defined on type T.
463 template <class T> struct has_MappingEnumInputTraits<T, EmptyContext> {
464  using Signature_validate = void (*)(class IO &, T &);
465 
466  template <typename U>
467  static char test(SameType<Signature_validate, &U::enumInput> *);
468 
469  template <typename U> static double test(...);
470 
471  static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
472 };
473 
474 // Test if SequenceTraits<T> is defined on type T.
475 template <class T>
476 struct has_SequenceMethodTraits
477 {
478  using Signature_size = size_t (*)(class IO&, T&);
479 
480  template <typename U>
481  static char test(SameType<Signature_size, &U::size>*);
482 
483  template <typename U>
484  static double test(...);
485 
486  static bool const value = (sizeof(test<SequenceTraits<T>>(nullptr)) == 1);
487 };
488 
489 // Test if CustomMappingTraits<T> is defined on type T.
490 template <class T>
491 struct has_CustomMappingTraits
492 {
493  using Signature_input = void (*)(IO &io, StringRef key, T &v);
494 
495  template <typename U>
496  static char test(SameType<Signature_input, &U::inputOne>*);
497 
498  template <typename U>
499  static double test(...);
500 
501  static bool const value =
502  (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1);
503 };
504 
505 // has_FlowTraits<int> will cause an error with some compilers because
506 // it subclasses int. Using this wrapper only instantiates the
507 // real has_FlowTraits only if the template type is a class.
508 template <typename T, bool Enabled = std::is_class<T>::value>
509 class has_FlowTraits
510 {
511 public:
512  static const bool value = false;
513 };
514 
515 // Some older gcc compilers don't support straight forward tests
516 // for members, so test for ambiguity cause by the base and derived
517 // classes both defining the member.
518 template <class T>
519 struct has_FlowTraits<T, true>
520 {
521  struct Fallback { bool flow; };
522  struct Derived : T, Fallback { };
523 
524  template<typename C>
525  static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
526 
527  template<typename C>
528  static char (&f(...))[2];
529 
530  static bool const value = sizeof(f<Derived>(nullptr)) == 2;
531 };
532 
533 // Test if SequenceTraits<T> is defined on type T
534 template<typename T>
535 struct has_SequenceTraits : public std::integral_constant<bool,
536  has_SequenceMethodTraits<T>::value > { };
537 
538 // Test if DocumentListTraits<T> is defined on type T
539 template <class T>
540 struct has_DocumentListTraits
541 {
542  using Signature_size = size_t (*)(class IO &, T &);
543 
544  template <typename U>
545  static char test(SameType<Signature_size, &U::size>*);
546 
547  template <typename U>
548  static double test(...);
549 
550  static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1);
551 };
552 
553 template <class T> struct has_PolymorphicTraits {
554  using Signature_getKind = NodeKind (*)(const T &);
555 
556  template <typename U>
557  static char test(SameType<Signature_getKind, &U::getKind> *);
558 
559  template <typename U> static double test(...);
560 
561  static bool const value = (sizeof(test<PolymorphicTraits<T>>(nullptr)) == 1);
562 };
563 
564 inline bool isNumeric(StringRef S) {
565  const auto skipDigits = [](StringRef Input) {
566  return Input.ltrim("0123456789");
567  };
568 
569  // Make S.front() and S.drop_front().front() (if S.front() is [+-]) calls
570  // safe.
571  if (S.empty() || S.equals("+") || S.equals("-"))
572  return false;
573 
574  if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN"))
575  return true;
576 
577  // Infinity and decimal numbers can be prefixed with sign.
578  StringRef Tail = (S.front() == '-' || S.front() == '+') ? S.drop_front() : S;
579 
580  // Check for infinity first, because checking for hex and oct numbers is more
581  // expensive.
582  if (Tail.equals(".inf") || Tail.equals(".Inf") || Tail.equals(".INF"))
583  return true;
584 
585  // Section 10.3.2 Tag Resolution
586  // YAML 1.2 Specification prohibits Base 8 and Base 16 numbers prefixed with
587  // [-+], so S should be used instead of Tail.
588  if (S.startswith("0o"))
589  return S.size() > 2 &&
590  S.drop_front(2).find_first_not_of("01234567") == StringRef::npos;
591 
592  if (S.startswith("0x"))
593  return S.size() > 2 && S.drop_front(2).find_first_not_of(
594  "0123456789abcdefABCDEF") == StringRef::npos;
595 
596  // Parse float: [-+]? (\. [0-9]+ | [0-9]+ (\. [0-9]* )?) ([eE] [-+]? [0-9]+)?
597  S = Tail;
598 
599  // Handle cases when the number starts with '.' and hence needs at least one
600  // digit after dot (as opposed by number which has digits before the dot), but
601  // doesn't have one.
602  if (S.startswith(".") &&
603  (S.equals(".") ||
604  (S.size() > 1 && std::strchr("0123456789", S[1]) == nullptr)))
605  return false;
606 
607  if (S.startswith("E") || S.startswith("e"))
608  return false;
609 
610  enum ParseState {
611  Default,
612  FoundDot,
613  FoundExponent,
614  };
615  ParseState State = Default;
616 
617  S = skipDigits(S);
618 
619  // Accept decimal integer.
620  if (S.empty())
621  return true;
622 
623  if (S.front() == '.') {
624  State = FoundDot;
625  S = S.drop_front();
626  } else if (S.front() == 'e' || S.front() == 'E') {
627  State = FoundExponent;
628  S = S.drop_front();
629  } else {
630  return false;
631  }
632 
633  if (State == FoundDot) {
634  S = skipDigits(S);
635  if (S.empty())
636  return true;
637 
638  if (S.front() == 'e' || S.front() == 'E') {
639  State = FoundExponent;
640  S = S.drop_front();
641  } else {
642  return false;
643  }
644  }
645 
646  assert(State == FoundExponent && "Should have found exponent at this point.");
647  if (S.empty())
648  return false;
649 
650  if (S.front() == '+' || S.front() == '-') {
651  S = S.drop_front();
652  if (S.empty())
653  return false;
654  }
655 
656  return skipDigits(S).empty();
657 }
658 
659 inline bool isNull(StringRef S) {
660  return S.equals("null") || S.equals("Null") || S.equals("NULL") ||
661  S.equals("~");
662 }
663 
664 inline bool isBool(StringRef S) {
665  // FIXME: using parseBool is causing multiple tests to fail.
666  return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
667  S.equals("false") || S.equals("False") || S.equals("FALSE");
668 }
669 
670 // 5.1. Character Set
671 // The allowed character range explicitly excludes the C0 control block #x0-#x1F
672 // (except for TAB #x9, LF #xA, and CR #xD which are allowed), DEL #x7F, the C1
673 // control block #x80-#x9F (except for NEL #x85 which is allowed), the surrogate
674 // block #xD800-#xDFFF, #xFFFE, and #xFFFF.
675 inline QuotingType needsQuotes(StringRef S) {
676  if (S.empty())
677  return QuotingType::Single;
678 
679  QuotingType MaxQuotingNeeded = QuotingType::None;
680  if (isSpace(static_cast<unsigned char>(S.front())) ||
681  isSpace(static_cast<unsigned char>(S.back())))
682  MaxQuotingNeeded = QuotingType::Single;
683  if (isNull(S))
684  MaxQuotingNeeded = QuotingType::Single;
685  if (isBool(S))
686  MaxQuotingNeeded = QuotingType::Single;
687  if (isNumeric(S))
688  MaxQuotingNeeded = QuotingType::Single;
689 
690  // 7.3.3 Plain Style
691  // Plain scalars must not begin with most indicators, as this would cause
692  // ambiguity with other YAML constructs.
693  if (std::strchr(R"(-?:\,[]{}#&*!|>'"%@`)", S[0]) != nullptr)
694  MaxQuotingNeeded = QuotingType::Single;
695 
696  for (unsigned char C : S) {
697  // Alphanum is safe.
698  if (isAlnum(C))
699  continue;
700 
701  switch (C) {
702  // Safe scalar characters.
703  case '_':
704  case '-':
705  case '^':
706  case '.':
707  case ',':
708  case ' ':
709  // TAB (0x9) is allowed in unquoted strings.
710  case 0x9:
711  continue;
712  // LF(0xA) and CR(0xD) may delimit values and so require at least single
713  // quotes. LLVM YAML parser cannot handle single quoted multiline so use
714  // double quoting to produce valid YAML.
715  case 0xA:
716  case 0xD:
717  return QuotingType::Double;
718  // DEL (0x7F) are excluded from the allowed character range.
719  case 0x7F:
720  return QuotingType::Double;
721  // Forward slash is allowed to be unquoted, but we quote it anyway. We have
722  // many tests that use FileCheck against YAML output, and this output often
723  // contains paths. If we quote backslashes but not forward slashes then
724  // paths will come out either quoted or unquoted depending on which platform
725  // the test is run on, making FileCheck comparisons difficult.
726  case '/':
727  default: {
728  // C0 control block (0x0 - 0x1F) is excluded from the allowed character
729  // range.
730  if (C <= 0x1F)
731  return QuotingType::Double;
732 
733  // Always double quote UTF-8.
734  if ((C & 0x80) != 0)
735  return QuotingType::Double;
736 
737  // The character is not safe, at least simple quoting needed.
738  MaxQuotingNeeded = QuotingType::Single;
739  }
740  }
741  }
742 
743  return MaxQuotingNeeded;
744 }
745 
746 template <typename T, typename Context>
747 struct missingTraits
748  : public std::integral_constant<bool,
749  !has_ScalarEnumerationTraits<T>::value &&
750  !has_ScalarBitSetTraits<T>::value &&
751  !has_ScalarTraits<T>::value &&
752  !has_BlockScalarTraits<T>::value &&
753  !has_TaggedScalarTraits<T>::value &&
754  !has_MappingTraits<T, Context>::value &&
755  !has_SequenceTraits<T>::value &&
756  !has_CustomMappingTraits<T>::value &&
757  !has_DocumentListTraits<T>::value &&
758  !has_PolymorphicTraits<T>::value> {};
759 
760 template <typename T, typename Context>
761 struct validatedMappingTraits
762  : public std::integral_constant<
763  bool, has_MappingTraits<T, Context>::value &&
764  has_MappingValidateTraits<T, Context>::value> {};
765 
766 template <typename T, typename Context>
767 struct unvalidatedMappingTraits
768  : public std::integral_constant<
769  bool, has_MappingTraits<T, Context>::value &&
770  !has_MappingValidateTraits<T, Context>::value> {};
771 
772 // Base class for Input and Output.
773 class IO {
774 public:
775  IO(void *Ctxt = nullptr);
776  virtual ~IO();
777 
778  virtual bool outputting() const = 0;
779 
780  virtual unsigned beginSequence() = 0;
781  virtual bool preflightElement(unsigned, void *&) = 0;
782  virtual void postflightElement(void*) = 0;
783  virtual void endSequence() = 0;
784  virtual bool canElideEmptySequence() = 0;
785 
786  virtual unsigned beginFlowSequence() = 0;
787  virtual bool preflightFlowElement(unsigned, void *&) = 0;
788  virtual void postflightFlowElement(void*) = 0;
789  virtual void endFlowSequence() = 0;
790 
791  virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
792  virtual void beginMapping() = 0;
793  virtual void endMapping() = 0;
794  virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
795  virtual void postflightKey(void*) = 0;
796  virtual std::vector<StringRef> keys() = 0;
797 
798  virtual void beginFlowMapping() = 0;
799  virtual void endFlowMapping() = 0;
800 
801  virtual void beginEnumScalar() = 0;
802  virtual bool matchEnumScalar(const char*, bool) = 0;
803  virtual bool matchEnumFallback() = 0;
804  virtual void endEnumScalar() = 0;
805 
806  virtual bool beginBitSetScalar(bool &) = 0;
807  virtual bool bitSetMatch(const char*, bool) = 0;
808  virtual void endBitSetScalar() = 0;
809 
810  virtual void scalarString(StringRef &, QuotingType) = 0;
811  virtual void blockScalarString(StringRef &) = 0;
812  virtual void scalarTag(std::string &) = 0;
813 
814  virtual NodeKind getNodeKind() = 0;
815 
816  virtual void setError(const Twine &) = 0;
817  virtual void setAllowUnknownKeys(bool Allow);
818 
819  template <typename T>
820  void enumCase(T &Val, const char* Str, const T ConstVal) {
821  if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
822  Val = ConstVal;
823  }
824  }
825 
826  // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
827  template <typename T>
828  void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
829  if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
830  Val = ConstVal;
831  }
832  }
833 
834  template <typename FBT, typename T>
835  void enumFallback(T &Val) {
836  if (matchEnumFallback()) {
837  EmptyContext Context;
838  // FIXME: Force integral conversion to allow strong typedefs to convert.
839  FBT Res = static_cast<typename FBT::BaseType>(Val);
840  yamlize(*this, Res, true, Context);
841  Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
842  }
843  }
844 
845  template <typename T>
846  void bitSetCase(T &Val, const char* Str, const T ConstVal) {
847  if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
848  Val = static_cast<T>(Val | ConstVal);
849  }
850  }
851 
852  // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
853  template <typename T>
854  void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
855  if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
856  Val = static_cast<T>(Val | ConstVal);
857  }
858  }
859 
860  template <typename T>
861  void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
862  if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
863  Val = Val | ConstVal;
864  }
865 
866  template <typename T>
867  void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
868  uint32_t Mask) {
869  if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
870  Val = Val | ConstVal;
871  }
872 
873  void *getContext() const;
874  void setContext(void *);
875 
876  template <typename T> void mapRequired(const char *Key, T &Val) {
877  EmptyContext Ctx;
878  this->processKey(Key, Val, true, Ctx);
879  }
880 
881  template <typename T, typename Context>
882  void mapRequired(const char *Key, T &Val, Context &Ctx) {
883  this->processKey(Key, Val, true, Ctx);
884  }
885 
886  template <typename T> void mapOptional(const char *Key, T &Val) {
887  EmptyContext Ctx;
888  mapOptionalWithContext(Key, Val, Ctx);
889  }
890 
891  template <typename T, typename DefaultT>
892  void mapOptional(const char *Key, T &Val, const DefaultT &Default) {
893  EmptyContext Ctx;
894  mapOptionalWithContext(Key, Val, Default, Ctx);
895  }
896 
897  template <typename T, typename Context>
898  std::enable_if_t<has_SequenceTraits<T>::value, void>
899  mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
900  // omit key/value instead of outputting empty sequence
901  if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
902  return;
903  this->processKey(Key, Val, false, Ctx);
904  }
905 
906  template <typename T, typename Context>
907  void mapOptionalWithContext(const char *Key, Optional<T> &Val, Context &Ctx) {
908  this->processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false,
909  Ctx);
910  }
911 
912  template <typename T, typename Context>
913  std::enable_if_t<!has_SequenceTraits<T>::value, void>
914  mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
915  this->processKey(Key, Val, false, Ctx);
916  }
917 
918  template <typename T, typename Context, typename DefaultT>
919  void mapOptionalWithContext(const char *Key, T &Val, const DefaultT &Default,
920  Context &Ctx) {
921  static_assert(std::is_convertible<DefaultT, T>::value,
922  "Default type must be implicitly convertible to value type!");
923  this->processKeyWithDefault(Key, Val, static_cast<const T &>(Default),
924  false, Ctx);
925  }
926 
927 private:
928  template <typename T, typename Context>
929  void processKeyWithDefault(const char *Key, Optional<T> &Val,
930  const Optional<T> &DefaultValue, bool Required,
931  Context &Ctx);
932 
933  template <typename T, typename Context>
934  void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
935  bool Required, Context &Ctx) {
936  void *SaveInfo;
937  bool UseDefault;
938  const bool sameAsDefault = outputting() && Val == DefaultValue;
939  if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
940  SaveInfo) ) {
941  yamlize(*this, Val, Required, Ctx);
942  this->postflightKey(SaveInfo);
943  }
944  else {
945  if ( UseDefault )
946  Val = DefaultValue;
947  }
948  }
949 
950  template <typename T, typename Context>
951  void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
952  void *SaveInfo;
953  bool UseDefault;
954  if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
955  yamlize(*this, Val, Required, Ctx);
956  this->postflightKey(SaveInfo);
957  }
958  }
959 
960 private:
961  void *Ctxt;
962 };
963 
964 namespace detail {
965 
966 template <typename T, typename Context>
967 void doMapping(IO &io, T &Val, Context &Ctx) {
968  MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
969 }
970 
971 template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
972  MappingTraits<T>::mapping(io, Val);
973 }
974 
975 } // end namespace detail
976 
977 template <typename T>
978 std::enable_if_t<has_ScalarEnumerationTraits<T>::value, void>
979 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
980  io.beginEnumScalar();
981  ScalarEnumerationTraits<T>::enumeration(io, Val);
982  io.endEnumScalar();
983 }
984 
985 template <typename T>
986 std::enable_if_t<has_ScalarBitSetTraits<T>::value, void>
987 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
988  bool DoClear;
989  if ( io.beginBitSetScalar(DoClear) ) {
990  if ( DoClear )
991  Val = T();
992  ScalarBitSetTraits<T>::bitset(io, Val);
993  io.endBitSetScalar();
994  }
995 }
996 
997 template <typename T>
998 std::enable_if_t<has_ScalarTraits<T>::value, void> yamlize(IO &io, T &Val, bool,
999  EmptyContext &Ctx) {
1000  if ( io.outputting() ) {
1001  std::string Storage;
1002  raw_string_ostream Buffer(Storage);
1003  ScalarTraits<T>::output(Val, io.getContext(), Buffer);
1004  StringRef Str = Buffer.str();
1005  io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
1006  }
1007  else {
1008  StringRef Str;
1009  io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
1010  StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
1011  if ( !Result.empty() ) {
1012  io.setError(Twine(Result));
1013  }
1014  }
1015 }
1016 
1017 template <typename T>
1018 std::enable_if_t<has_BlockScalarTraits<T>::value, void>
1019 yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
1020  if (YamlIO.outputting()) {
1021  std::string Storage;
1022  raw_string_ostream Buffer(Storage);
1023  BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
1024  StringRef Str = Buffer.str();
1025  YamlIO.blockScalarString(Str);
1026  } else {
1027  StringRef Str;
1028  YamlIO.blockScalarString(Str);
1029  StringRef Result =
1030  BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
1031  if (!Result.empty())
1032  YamlIO.setError(Twine(Result));
1033  }
1034 }
1035 
1036 template <typename T>
1037 std::enable_if_t<has_TaggedScalarTraits<T>::value, void>
1038 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1039  if (io.outputting()) {
1040  std::string ScalarStorage, TagStorage;
1041  raw_string_ostream ScalarBuffer(ScalarStorage), TagBuffer(TagStorage);
1042  TaggedScalarTraits<T>::output(Val, io.getContext(), ScalarBuffer,
1043  TagBuffer);
1044  io.scalarTag(TagBuffer.str());
1045  StringRef ScalarStr = ScalarBuffer.str();
1046  io.scalarString(ScalarStr,
1047  TaggedScalarTraits<T>::mustQuote(Val, ScalarStr));
1048  } else {
1049  std::string Tag;
1050  io.scalarTag(Tag);
1051  StringRef Str;
1052  io.scalarString(Str, QuotingType::None);
1053  StringRef Result =
1054  TaggedScalarTraits<T>::input(Str, Tag, io.getContext(), Val);
1055  if (!Result.empty()) {
1056  io.setError(Twine(Result));
1057  }
1058  }
1059 }
1060 
1061 template <typename T, typename Context>
1062 std::enable_if_t<validatedMappingTraits<T, Context>::value, void>
1063 yamlize(IO &io, T &Val, bool, Context &Ctx) {
1064  if (has_FlowTraits<MappingTraits<T>>::value)
1065  io.beginFlowMapping();
1066  else
1067  io.beginMapping();
1068  if (io.outputting()) {
1069  std::string Err = MappingTraits<T>::validate(io, Val);
1070  if (!Err.empty()) {
1071  errs() << Err << "\n";
1072  assert(Err.empty() && "invalid struct trying to be written as yaml");
1073  }
1074  }
1075  detail::doMapping(io, Val, Ctx);
1076  if (!io.outputting()) {
1077  std::string Err = MappingTraits<T>::validate(io, Val);
1078  if (!Err.empty())
1079  io.setError(Err);
1080  }
1081  if (has_FlowTraits<MappingTraits<T>>::value)
1082  io.endFlowMapping();
1083  else
1084  io.endMapping();
1085 }
1086 
1087 template <typename T, typename Context>
1088 std::enable_if_t<!has_MappingEnumInputTraits<T, Context>::value, bool>
1089 yamlizeMappingEnumInput(IO &io, T &Val) {
1090  return false;
1091 }
1092 
1093 template <typename T, typename Context>
1094 std::enable_if_t<has_MappingEnumInputTraits<T, Context>::value, bool>
1095 yamlizeMappingEnumInput(IO &io, T &Val) {
1096  if (io.outputting())
1097  return false;
1098 
1099  io.beginEnumScalar();
1100  MappingTraits<T>::enumInput(io, Val);
1101  bool Matched = !io.matchEnumFallback();
1102  io.endEnumScalar();
1103  return Matched;
1104 }
1105 
1106 template <typename T, typename Context>
1107 std::enable_if_t<unvalidatedMappingTraits<T, Context>::value, void>
1108 yamlize(IO &io, T &Val, bool, Context &Ctx) {
1109  if (yamlizeMappingEnumInput<T, Context>(io, Val))
1110  return;
1111  if (has_FlowTraits<MappingTraits<T>>::value) {
1112  io.beginFlowMapping();
1113  detail::doMapping(io, Val, Ctx);
1114  io.endFlowMapping();
1115  } else {
1116  io.beginMapping();
1117  detail::doMapping(io, Val, Ctx);
1118  io.endMapping();
1119  }
1120 }
1121 
1122 template <typename T>
1123 std::enable_if_t<has_CustomMappingTraits<T>::value, void>
1124 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1125  if ( io.outputting() ) {
1126  io.beginMapping();
1128  io.endMapping();
1129  } else {
1130  io.beginMapping();
1131  for (StringRef key : io.keys())
1132  CustomMappingTraits<T>::inputOne(io, key, Val);
1133  io.endMapping();
1134  }
1135 }
1136 
1137 template <typename T>
1138 std::enable_if_t<has_PolymorphicTraits<T>::value, void>
1139 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1140  switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val)
1141  : io.getNodeKind()) {
1142  case NodeKind::Scalar:
1143  return yamlize(io, PolymorphicTraits<T>::getAsScalar(Val), true, Ctx);
1144  case NodeKind::Map:
1145  return yamlize(io, PolymorphicTraits<T>::getAsMap(Val), true, Ctx);
1146  case NodeKind::Sequence:
1147  return yamlize(io, PolymorphicTraits<T>::getAsSequence(Val), true, Ctx);
1148  }
1149 }
1150 
1151 template <typename T>
1152 std::enable_if_t<missingTraits<T, EmptyContext>::value, void>
1153 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
1154  char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1155 }
1156 
1157 template <typename T, typename Context>
1158 std::enable_if_t<has_SequenceTraits<T>::value, void>
1159 yamlize(IO &io, T &Seq, bool, Context &Ctx) {
1160  if ( has_FlowTraits< SequenceTraits<T>>::value ) {
1161  unsigned incnt = io.beginFlowSequence();
1162  unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
1163  for(unsigned i=0; i < count; ++i) {
1164  void *SaveInfo;
1165  if ( io.preflightFlowElement(i, SaveInfo) ) {
1166  yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
1167  io.postflightFlowElement(SaveInfo);
1168  }
1169  }
1170  io.endFlowSequence();
1171  }
1172  else {
1173  unsigned incnt = io.beginSequence();
1174  unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
1175  for(unsigned i=0; i < count; ++i) {
1176  void *SaveInfo;
1177  if ( io.preflightElement(i, SaveInfo) ) {
1178  yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
1179  io.postflightElement(SaveInfo);
1180  }
1181  }
1182  io.endSequence();
1183  }
1184 }
1185 
1186 template<>
1187 struct ScalarTraits<bool> {
1188  static void output(const bool &, void* , raw_ostream &);
1189  static StringRef input(StringRef, void *, bool &);
1190  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1191 };
1192 
1193 template<>
1194 struct ScalarTraits<StringRef> {
1195  static void output(const StringRef &, void *, raw_ostream &);
1196  static StringRef input(StringRef, void *, StringRef &);
1197  static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1198 };
1199 
1200 template<>
1201 struct ScalarTraits<std::string> {
1202  static void output(const std::string &, void *, raw_ostream &);
1203  static StringRef input(StringRef, void *, std::string &);
1204  static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
1205 };
1206 
1207 template<>
1208 struct ScalarTraits<uint8_t> {
1209  static void output(const uint8_t &, void *, raw_ostream &);
1210  static StringRef input(StringRef, void *, uint8_t &);
1211  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1212 };
1213 
1214 template<>
1215 struct ScalarTraits<uint16_t> {
1216  static void output(const uint16_t &, void *, raw_ostream &);
1217  static StringRef input(StringRef, void *, uint16_t &);
1218  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1219 };
1220 
1221 template<>
1222 struct ScalarTraits<uint32_t> {
1223  static void output(const uint32_t &, void *, raw_ostream &);
1224  static StringRef input(StringRef, void *, uint32_t &);
1225  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1226 };
1227 
1228 template<>
1229 struct ScalarTraits<uint64_t> {
1230  static void output(const uint64_t &, void *, raw_ostream &);
1231  static StringRef input(StringRef, void *, uint64_t &);
1232  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1233 };
1234 
1235 template<>
1236 struct ScalarTraits<int8_t> {
1237  static void output(const int8_t &, void *, raw_ostream &);
1238  static StringRef input(StringRef, void *, int8_t &);
1239  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1240 };
1241 
1242 template<>
1243 struct ScalarTraits<int16_t> {
1244  static void output(const int16_t &, void *, raw_ostream &);
1245  static StringRef input(StringRef, void *, int16_t &);
1246  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1247 };
1248 
1249 template<>
1250 struct ScalarTraits<int32_t> {
1251  static void output(const int32_t &, void *, raw_ostream &);
1252  static StringRef input(StringRef, void *, int32_t &);
1253  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1254 };
1255 
1256 template<>
1257 struct ScalarTraits<int64_t> {
1258  static void output(const int64_t &, void *, raw_ostream &);
1259  static StringRef input(StringRef, void *, int64_t &);
1260  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1261 };
1262 
1263 template<>
1264 struct ScalarTraits<float> {
1265  static void output(const float &, void *, raw_ostream &);
1266  static StringRef input(StringRef, void *, float &);
1267  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1268 };
1269 
1270 template<>
1271 struct ScalarTraits<double> {
1272  static void output(const double &, void *, raw_ostream &);
1273  static StringRef input(StringRef, void *, double &);
1274  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1275 };
1276 
1277 // For endian types, we use existing scalar Traits class for the underlying
1278 // type. This way endian aware types are supported whenever the traits are
1279 // defined for the underlying type.
1280 template <typename value_type, support::endianness endian, size_t alignment>
1281 struct ScalarTraits<support::detail::packed_endian_specific_integral<
1282  value_type, endian, alignment>,
1283  std::enable_if_t<has_ScalarTraits<value_type>::value>> {
1284  using endian_type =
1285  support::detail::packed_endian_specific_integral<value_type, endian,
1286  alignment>;
1287 
1288  static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
1289  ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
1290  }
1291 
1292  static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
1293  value_type V;
1294  auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
1295  E = static_cast<endian_type>(V);
1296  return R;
1297  }
1298 
1299  static QuotingType mustQuote(StringRef Str) {
1300  return ScalarTraits<value_type>::mustQuote(Str);
1301  }
1302 };
1303 
1304 template <typename value_type, support::endianness endian, size_t alignment>
1305 struct ScalarEnumerationTraits<
1306  support::detail::packed_endian_specific_integral<value_type, endian,
1307  alignment>,
1308  std::enable_if_t<has_ScalarEnumerationTraits<value_type>::value>> {
1309  using endian_type =
1310  support::detail::packed_endian_specific_integral<value_type, endian,
1311  alignment>;
1312 
1313  static void enumeration(IO &io, endian_type &E) {
1314  value_type V = E;
1315  ScalarEnumerationTraits<value_type>::enumeration(io, V);
1316  E = V;
1317  }
1318 };
1319 
1320 template <typename value_type, support::endianness endian, size_t alignment>
1321 struct ScalarBitSetTraits<
1322  support::detail::packed_endian_specific_integral<value_type, endian,
1323  alignment>,
1324  std::enable_if_t<has_ScalarBitSetTraits<value_type>::value>> {
1325  using endian_type =
1326  support::detail::packed_endian_specific_integral<value_type, endian,
1327  alignment>;
1328  static void bitset(IO &io, endian_type &E) {
1329  value_type V = E;
1330  ScalarBitSetTraits<value_type>::bitset(io, V);
1331  E = V;
1332  }
1333 };
1334 
1335 // Utility for use within MappingTraits<>::mapping() method
1336 // to [de]normalize an object for use with YAML conversion.
1337 template <typename TNorm, typename TFinal>
1338 struct MappingNormalization {
1339  MappingNormalization(IO &i_o, TFinal &Obj)
1340  : io(i_o), BufPtr(nullptr), Result(Obj) {
1341  if ( io.outputting() ) {
1342  BufPtr = new (&Buffer) TNorm(io, Obj);
1343  }
1344  else {
1345  BufPtr = new (&Buffer) TNorm(io);
1346  }
1347  }
1348 
1349  ~MappingNormalization() {
1350  if ( ! io.outputting() ) {
1351  Result = BufPtr->denormalize(io);
1352  }
1353  BufPtr->~TNorm();
1354  }
1355 
1356  TNorm* operator->() { return BufPtr; }
1357 
1358 private:
1359  using Storage = AlignedCharArrayUnion<TNorm>;
1360 
1361  Storage Buffer;
1362  IO &io;
1363  TNorm *BufPtr;
1364  TFinal &Result;
1365 };
1366 
1367 // Utility for use within MappingTraits<>::mapping() method
1368 // to [de]normalize an object for use with YAML conversion.
1369 template <typename TNorm, typename TFinal>
1370 struct MappingNormalizationHeap {
1371  MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
1372  : io(i_o), Result(Obj) {
1373  if ( io.outputting() ) {
1374  BufPtr = new (&Buffer) TNorm(io, Obj);
1375  }
1376  else if (allocator) {
1377  BufPtr = allocator->Allocate<TNorm>();
1378  new (BufPtr) TNorm(io);
1379  } else {
1380  BufPtr = new TNorm(io);
1381  }
1382  }
1383 
1384  ~MappingNormalizationHeap() {
1385  if ( io.outputting() ) {
1386  BufPtr->~TNorm();
1387  }
1388  else {
1389  Result = BufPtr->denormalize(io);
1390  }
1391  }
1392 
1393  TNorm* operator->() { return BufPtr; }
1394 
1395 private:
1396  using Storage = AlignedCharArrayUnion<TNorm>;
1397 
1398  Storage Buffer;
1399  IO &io;
1400  TNorm *BufPtr = nullptr;
1401  TFinal &Result;
1402 };
1403 
1404 ///
1405 /// The Input class is used to parse a yaml document into in-memory structs
1406 /// and vectors.
1407 ///
1408 /// It works by using YAMLParser to do a syntax parse of the entire yaml
1409 /// document, then the Input class builds a graph of HNodes which wraps
1410 /// each yaml Node. The extra layer is buffering. The low level yaml
1411 /// parser only lets you look at each node once. The buffering layer lets
1412 /// you search and interate multiple times. This is necessary because
1413 /// the mapRequired() method calls may not be in the same order
1414 /// as the keys in the document.
1415 ///
1416 class Input : public IO {
1417 public:
1418  // Construct a yaml Input object from a StringRef and optional
1419  // user-data. The DiagHandler can be specified to provide
1420  // alternative error reporting.
1421  Input(StringRef InputContent,
1422  void *Ctxt = nullptr,
1424  void *DiagHandlerCtxt = nullptr);
1425  Input(MemoryBufferRef Input,
1426  void *Ctxt = nullptr,
1428  void *DiagHandlerCtxt = nullptr);
1429  ~Input() override;
1430 
1431  // Check if there was an syntax or semantic error during parsing.
1432  std::error_code error();
1433 
1434 private:
1435  bool outputting() const override;
1436  bool mapTag(StringRef, bool) override;
1437  void beginMapping() override;
1438  void endMapping() override;
1439  bool preflightKey(const char *, bool, bool, bool &, void *&) override;
1440  void postflightKey(void *) override;
1441  std::vector<StringRef> keys() override;
1442  void beginFlowMapping() override;
1443  void endFlowMapping() override;
1444  unsigned beginSequence() override;
1445  void endSequence() override;
1446  bool preflightElement(unsigned index, void *&) override;
1447  void postflightElement(void *) override;
1448  unsigned beginFlowSequence() override;
1449  bool preflightFlowElement(unsigned , void *&) override;
1450  void postflightFlowElement(void *) override;
1451  void endFlowSequence() override;
1452  void beginEnumScalar() override;
1453  bool matchEnumScalar(const char*, bool) override;
1454  bool matchEnumFallback() override;
1455  void endEnumScalar() override;
1456  bool beginBitSetScalar(bool &) override;
1457  bool bitSetMatch(const char *, bool ) override;
1458  void endBitSetScalar() override;
1459  void scalarString(StringRef &, QuotingType) override;
1460  void blockScalarString(StringRef &) override;
1461  void scalarTag(std::string &) override;
1462  NodeKind getNodeKind() override;
1463  void setError(const Twine &message) override;
1464  bool canElideEmptySequence() override;
1465 
1466  class HNode {
1467  virtual void anchor();
1468 
1469  public:
1470  HNode(Node *n) : _node(n) { }
1471  virtual ~HNode() = default;
1472 
1473  static bool classof(const HNode *) { return true; }
1474 
1475  Node *_node;
1476  };
1477 
1478  class EmptyHNode : public HNode {
1479  void anchor() override;
1480 
1481  public:
1482  EmptyHNode(Node *n) : HNode(n) { }
1483 
1484  static bool classof(const HNode *n) { return NullNode::classof(n->_node); }
1485 
1486  static bool classof(const EmptyHNode *) { return true; }
1487  };
1488 
1489  class ScalarHNode : public HNode {
1490  void anchor() override;
1491 
1492  public:
1493  ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
1494 
1495  StringRef value() const { return _value; }
1496 
1497  static bool classof(const HNode *n) {
1498  return ScalarNode::classof(n->_node) ||
1499  BlockScalarNode::classof(n->_node);
1500  }
1501 
1502  static bool classof(const ScalarHNode *) { return true; }
1503 
1504  protected:
1505  StringRef _value;
1506  };
1507 
1508  class MapHNode : public HNode {
1509  void anchor() override;
1510 
1511  public:
1512  MapHNode(Node *n) : HNode(n) { }
1513 
1514  static bool classof(const HNode *n) {
1515  return MappingNode::classof(n->_node);
1516  }
1517 
1518  static bool classof(const MapHNode *) { return true; }
1519 
1520  using NameToNodeAndLoc =
1521  StringMap<std::pair<std::unique_ptr<HNode>, SMRange>>;
1522 
1523  NameToNodeAndLoc Mapping;
1524  SmallVector<std::string, 6> ValidKeys;
1525  };
1526 
1527  class SequenceHNode : public HNode {
1528  void anchor() override;
1529 
1530  public:
1531  SequenceHNode(Node *n) : HNode(n) { }
1532 
1533  static bool classof(const HNode *n) {
1534  return SequenceNode::classof(n->_node);
1535  }
1536 
1537  static bool classof(const SequenceHNode *) { return true; }
1538 
1539  std::vector<std::unique_ptr<HNode>> Entries;
1540  };
1541 
1542  std::unique_ptr<Input::HNode> createHNodes(Node *node);
1543  void setError(HNode *hnode, const Twine &message);
1544  void setError(Node *node, const Twine &message);
1545  void setError(const SMRange &Range, const Twine &message);
1546 
1547  void reportWarning(HNode *hnode, const Twine &message);
1548  void reportWarning(Node *hnode, const Twine &message);
1549  void reportWarning(const SMRange &Range, const Twine &message);
1550 
1551 public:
1552  // These are only used by operator>>. They could be private
1553  // if those templated things could be made friends.
1554  bool setCurrentDocument();
1555  bool nextDocument();
1556 
1557  /// Returns the current node that's being parsed by the YAML Parser.
1558  const Node *getCurrentNode() const;
1559 
1560  void setAllowUnknownKeys(bool Allow) override;
1561 
1562 private:
1563  SourceMgr SrcMgr; // must be before Strm
1564  std::unique_ptr<llvm::yaml::Stream> Strm;
1565  std::unique_ptr<HNode> TopNode;
1566  std::error_code EC;
1567  BumpPtrAllocator StringAllocator;
1568  document_iterator DocIterator;
1569  llvm::BitVector BitValuesUsed;
1570  HNode *CurrentNode = nullptr;
1571  bool ScalarMatchFound = false;
1572  bool AllowUnknownKeys = false;
1573 };
1574 
1575 ///
1576 /// The Output class is used to generate a yaml document from in-memory structs
1577 /// and vectors.
1578 ///
1579 class Output : public IO {
1580 public:
1581  Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
1582  ~Output() override;
1583 
1584  /// Set whether or not to output optional values which are equal
1585  /// to the default value. By default, when outputting if you attempt
1586  /// to write a value that is equal to the default, the value gets ignored.
1587  /// Sometimes, it is useful to be able to see these in the resulting YAML
1588  /// anyway.
1589  void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
1590 
1591  bool outputting() const override;
1592  bool mapTag(StringRef, bool) override;
1593  void beginMapping() override;
1594  void endMapping() override;
1595  bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
1596  void postflightKey(void *) override;
1597  std::vector<StringRef> keys() override;
1598  void beginFlowMapping() override;
1599  void endFlowMapping() override;
1600  unsigned beginSequence() override;
1601  void endSequence() override;
1602  bool preflightElement(unsigned, void *&) override;
1603  void postflightElement(void *) override;
1604  unsigned beginFlowSequence() override;
1605  bool preflightFlowElement(unsigned, void *&) override;
1606  void postflightFlowElement(void *) override;
1607  void endFlowSequence() override;
1608  void beginEnumScalar() override;
1609  bool matchEnumScalar(const char*, bool) override;
1610  bool matchEnumFallback() override;
1611  void endEnumScalar() override;
1612  bool beginBitSetScalar(bool &) override;
1613  bool bitSetMatch(const char *, bool ) override;
1614  void endBitSetScalar() override;
1615  void scalarString(StringRef &, QuotingType) override;
1616  void blockScalarString(StringRef &) override;
1617  void scalarTag(std::string &) override;
1618  NodeKind getNodeKind() override;
1619  void setError(const Twine &message) override;
1620  bool canElideEmptySequence() override;
1621 
1622  // These are only used by operator<<. They could be private
1623  // if that templated operator could be made a friend.
1624  void beginDocuments();
1625  bool preflightDocument(unsigned);
1626  void postflightDocument();
1627  void endDocuments();
1628 
1629 private:
1630  void output(StringRef s);
1631  void outputUpToEndOfLine(StringRef s);
1632  void newLineCheck(bool EmptySequence = false);
1633  void outputNewLine();
1634  void paddedKey(StringRef key);
1635  void flowKey(StringRef Key);
1636 
1637  enum InState {
1638  inSeqFirstElement,
1639  inSeqOtherElement,
1640  inFlowSeqFirstElement,
1641  inFlowSeqOtherElement,
1642  inMapFirstKey,
1643  inMapOtherKey,
1644  inFlowMapFirstKey,
1645  inFlowMapOtherKey
1646  };
1647 
1648  static bool inSeqAnyElement(InState State);
1649  static bool inFlowSeqAnyElement(InState State);
1650  static bool inMapAnyKey(InState State);
1651  static bool inFlowMapAnyKey(InState State);
1652 
1653  raw_ostream &Out;
1654  int WrapColumn;
1655  SmallVector<InState, 8> StateStack;
1656  int Column = 0;
1657  int ColumnAtFlowStart = 0;
1658  int ColumnAtMapFlowStart = 0;
1659  bool NeedBitValueComma = false;
1660  bool NeedFlowSequenceComma = false;
1661  bool EnumerationMatchFound = false;
1662  bool WriteDefaultValues = false;
1663  StringRef Padding;
1664  StringRef PaddingBeforeContainer;
1665 };
1666 
1667 template <typename T, typename Context>
1668 void IO::processKeyWithDefault(const char *Key, Optional<T> &Val,
1669  const Optional<T> &DefaultValue, bool Required,
1670  Context &Ctx) {
1671  assert(!DefaultValue && "Optional<T> shouldn't have a value!");
1672  void *SaveInfo;
1673  bool UseDefault = true;
1674  const bool sameAsDefault = outputting() && !Val;
1675  if (!outputting() && !Val)
1676  Val = T();
1677  if (Val &&
1678  this->preflightKey(Key, Required, sameAsDefault, UseDefault, SaveInfo)) {
1679 
1680  // When reading an Optional<X> key from a YAML description, we allow the
1681  // special "<none>" value, which can be used to specify that no value was
1682  // requested, i.e. the DefaultValue will be assigned. The DefaultValue is
1683  // usually None.
1684  bool IsNone = false;
1685  if (!outputting())
1686  if (const auto *Node = dyn_cast<ScalarNode>(((Input *)this)->getCurrentNode()))
1687  // We use rtrim to ignore possible white spaces that might exist when a
1688  // comment is present on the same line.
1689  IsNone = Node->getRawValue().rtrim(' ') == "<none>";
1690 
1691  if (IsNone)
1692  Val = DefaultValue;
1693  else
1694  yamlize(*this, *Val, Required, Ctx);
1695  this->postflightKey(SaveInfo);
1696  } else {
1697  if (UseDefault)
1698  Val = DefaultValue;
1699  }
1700 }
1701 
1702 /// YAML I/O does conversion based on types. But often native data types
1703 /// are just a typedef of built in intergral types (e.g. int). But the C++
1704 /// type matching system sees through the typedef and all the typedefed types
1705 /// look like a built in type. This will cause the generic YAML I/O conversion
1706 /// to be used. To provide better control over the YAML conversion, you can
1707 /// use this macro instead of typedef. It will create a class with one field
1708 /// and automatic conversion operators to and from the base type.
1709 /// Based on BOOST_STRONG_TYPEDEF
1710 #define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \
1711  struct _type { \
1712  _type() = default; \
1713  _type(const _base v) : value(v) {} \
1714  _type(const _type &v) = default; \
1715  _type &operator=(const _type &rhs) = default; \
1716  _type &operator=(const _base &rhs) { value = rhs; return *this; } \
1717  operator const _base & () const { return value; } \
1718  bool operator==(const _type &rhs) const { return value == rhs.value; } \
1719  bool operator==(const _base &rhs) const { return value == rhs; } \
1720  bool operator<(const _type &rhs) const { return value < rhs.value; } \
1721  _base value; \
1722  using BaseType = _base; \
1723  };
1724 
1725 ///
1726 /// Use these types instead of uintXX_t in any mapping to have
1727 /// its yaml output formatted as hexadecimal.
1728 ///
1729 LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
1733 
1734 template<>
1735 struct ScalarTraits<Hex8> {
1736  static void output(const Hex8 &, void *, raw_ostream &);
1737  static StringRef input(StringRef, void *, Hex8 &);
1738  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1739 };
1740 
1741 template<>
1742 struct ScalarTraits<Hex16> {
1743  static void output(const Hex16 &, void *, raw_ostream &);
1744  static StringRef input(StringRef, void *, Hex16 &);
1745  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1746 };
1747 
1748 template<>
1749 struct ScalarTraits<Hex32> {
1750  static void output(const Hex32 &, void *, raw_ostream &);
1751  static StringRef input(StringRef, void *, Hex32 &);
1752  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1753 };
1754 
1755 template<>
1756 struct ScalarTraits<Hex64> {
1757  static void output(const Hex64 &, void *, raw_ostream &);
1758  static StringRef input(StringRef, void *, Hex64 &);
1759  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1760 };
1761 
1762 template <> struct ScalarTraits<VersionTuple> {
1763  static void output(const VersionTuple &Value, void *, llvm::raw_ostream &Out);
1764  static StringRef input(StringRef, void *, VersionTuple &);
1765  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1766 };
1767 
1768 // Define non-member operator>> so that Input can stream in a document list.
1769 template <typename T>
1770 inline std::enable_if_t<has_DocumentListTraits<T>::value, Input &>
1771 operator>>(Input &yin, T &docList) {
1772  int i = 0;
1773  EmptyContext Ctx;
1774  while ( yin.setCurrentDocument() ) {
1775  yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
1776  if ( yin.error() )
1777  return yin;
1778  yin.nextDocument();
1779  ++i;
1780  }
1781  return yin;
1782 }
1783 
1784 // Define non-member operator>> so that Input can stream in a map as a document.
1785 template <typename T>
1786 inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Input &>
1787 operator>>(Input &yin, T &docMap) {
1788  EmptyContext Ctx;
1789  yin.setCurrentDocument();
1790  yamlize(yin, docMap, true, Ctx);
1791  return yin;
1792 }
1793 
1794 // Define non-member operator>> so that Input can stream in a sequence as
1795 // a document.
1796 template <typename T>
1797 inline std::enable_if_t<has_SequenceTraits<T>::value, Input &>
1798 operator>>(Input &yin, T &docSeq) {
1799  EmptyContext Ctx;
1800  if (yin.setCurrentDocument())
1801  yamlize(yin, docSeq, true, Ctx);
1802  return yin;
1803 }
1804 
1805 // Define non-member operator>> so that Input can stream in a block scalar.
1806 template <typename T>
1807 inline std::enable_if_t<has_BlockScalarTraits<T>::value, Input &>
1808 operator>>(Input &In, T &Val) {
1809  EmptyContext Ctx;
1810  if (In.setCurrentDocument())
1811  yamlize(In, Val, true, Ctx);
1812  return In;
1813 }
1814 
1815 // Define non-member operator>> so that Input can stream in a string map.
1816 template <typename T>
1817 inline std::enable_if_t<has_CustomMappingTraits<T>::value, Input &>
1818 operator>>(Input &In, T &Val) {
1819  EmptyContext Ctx;
1820  if (In.setCurrentDocument())
1821  yamlize(In, Val, true, Ctx);
1822  return In;
1823 }
1824 
1825 // Define non-member operator>> so that Input can stream in a polymorphic type.
1826 template <typename T>
1827 inline std::enable_if_t<has_PolymorphicTraits<T>::value, Input &>
1828 operator>>(Input &In, T &Val) {
1829  EmptyContext Ctx;
1830  if (In.setCurrentDocument())
1831  yamlize(In, Val, true, Ctx);
1832  return In;
1833 }
1834 
1835 // Provide better error message about types missing a trait specialization
1836 template <typename T>
1837 inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Input &>
1838 operator>>(Input &yin, T &docSeq) {
1839  char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1840  return yin;
1841 }
1842 
1843 // Define non-member operator<< so that Output can stream out document list.
1844 template <typename T>
1845 inline std::enable_if_t<has_DocumentListTraits<T>::value, Output &>
1846 operator<<(Output &yout, T &docList) {
1847  EmptyContext Ctx;
1848  yout.beginDocuments();
1849  const size_t count = DocumentListTraits<T>::size(yout, docList);
1850  for(size_t i=0; i < count; ++i) {
1851  if ( yout.preflightDocument(i) ) {
1852  yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
1853  Ctx);
1854  yout.postflightDocument();
1855  }
1856  }
1857  yout.endDocuments();
1858  return yout;
1859 }
1860 
1861 // Define non-member operator<< so that Output can stream out a map.
1862 template <typename T>
1863 inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Output &>
1864 operator<<(Output &yout, T &map) {
1865  EmptyContext Ctx;
1866  yout.beginDocuments();
1867  if ( yout.preflightDocument(0) ) {
1868  yamlize(yout, map, true, Ctx);
1869  yout.postflightDocument();
1870  }
1871  yout.endDocuments();
1872  return yout;
1873 }
1874 
1875 // Define non-member operator<< so that Output can stream out a sequence.
1876 template <typename T>
1877 inline std::enable_if_t<has_SequenceTraits<T>::value, Output &>
1878 operator<<(Output &yout, T &seq) {
1879  EmptyContext Ctx;
1880  yout.beginDocuments();
1881  if ( yout.preflightDocument(0) ) {
1882  yamlize(yout, seq, true, Ctx);
1883  yout.postflightDocument();
1884  }
1885  yout.endDocuments();
1886  return yout;
1887 }
1888 
1889 // Define non-member operator<< so that Output can stream out a block scalar.
1890 template <typename T>
1891 inline std::enable_if_t<has_BlockScalarTraits<T>::value, Output &>
1892 operator<<(Output &Out, T &Val) {
1893  EmptyContext Ctx;
1894  Out.beginDocuments();
1895  if (Out.preflightDocument(0)) {
1896  yamlize(Out, Val, true, Ctx);
1897  Out.postflightDocument();
1898  }
1899  Out.endDocuments();
1900  return Out;
1901 }
1902 
1903 // Define non-member operator<< so that Output can stream out a string map.
1904 template <typename T>
1905 inline std::enable_if_t<has_CustomMappingTraits<T>::value, Output &>
1906 operator<<(Output &Out, T &Val) {
1907  EmptyContext Ctx;
1908  Out.beginDocuments();
1909  if (Out.preflightDocument(0)) {
1910  yamlize(Out, Val, true, Ctx);
1911  Out.postflightDocument();
1912  }
1913  Out.endDocuments();
1914  return Out;
1915 }
1916 
1917 // Define non-member operator<< so that Output can stream out a polymorphic
1918 // type.
1919 template <typename T>
1920 inline std::enable_if_t<has_PolymorphicTraits<T>::value, Output &>
1921 operator<<(Output &Out, T &Val) {
1922  EmptyContext Ctx;
1923  Out.beginDocuments();
1924  if (Out.preflightDocument(0)) {
1925  // FIXME: The parser does not support explicit documents terminated with a
1926  // plain scalar; the end-marker is included as part of the scalar token.
1927  assert(PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && "plain scalar documents are not supported");
1928  yamlize(Out, Val, true, Ctx);
1929  Out.postflightDocument();
1930  }
1931  Out.endDocuments();
1932  return Out;
1933 }
1934 
1935 // Provide better error message about types missing a trait specialization
1936 template <typename T>
1937 inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Output &>
1938 operator<<(Output &yout, T &seq) {
1939  char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1940  return yout;
1941 }
1942 
1943 template <bool B> struct IsFlowSequenceBase {};
1944 template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
1945 
1946 template <typename T, bool Flow>
1947 struct SequenceTraitsImpl : IsFlowSequenceBase<Flow> {
1948 private:
1949  using type = typename T::value_type;
1950 
1951 public:
1952  static size_t size(IO &io, T &seq) { return seq.size(); }
1953 
1954  static type &element(IO &io, T &seq, size_t index) {
1955  if (index >= seq.size())
1956  seq.resize(index + 1);
1957  return seq[index];
1958  }
1959 };
1960 
1961 // Simple helper to check an expression can be used as a bool-valued template
1962 // argument.
1963 template <bool> struct CheckIsBool { static const bool value = true; };
1964 
1965 // If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
1966 // SequenceTraits that do the obvious thing.
1967 template <typename T>
1968 struct SequenceTraits<
1969  std::vector<T>,
1970  std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
1971  : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
1972 template <typename T, unsigned N>
1973 struct SequenceTraits<
1974  SmallVector<T, N>,
1975  std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
1976  : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
1977 template <typename T>
1978 struct SequenceTraits<
1979  SmallVectorImpl<T>,
1980  std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
1981  : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
1982 
1983 // Sequences of fundamental types use flow formatting.
1984 template <typename T>
1985 struct SequenceElementTraits<T,
1986  std::enable_if_t<std::is_fundamental<T>::value>> {
1987  static const bool flow = true;
1988 };
1989 
1990 // Sequences of strings use block formatting.
1991 template<> struct SequenceElementTraits<std::string> {
1992  static const bool flow = false;
1993 };
1994 template<> struct SequenceElementTraits<StringRef> {
1995  static const bool flow = false;
1996 };
1997 template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
1998  static const bool flow = false;
1999 };
2000 
2001 /// Implementation of CustomMappingTraits for std::map<std::string, T>.
2002 template <typename T> struct StdMapStringCustomMappingTraitsImpl {
2003  using map_type = std::map<std::string, T>;
2004 
2005  static void inputOne(IO &io, StringRef key, map_type &v) {
2006  io.mapRequired(key.str().c_str(), v[std::string(key)]);
2007  }
2008 
2009  static void output(IO &io, map_type &v) {
2010  for (auto &p : v)
2011  io.mapRequired(p.first.c_str(), p.second);
2012  }
2013 };
2014 
2015 } // end namespace yaml
2016 } // end namespace llvm
2017 
2018 #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW) \
2019  namespace llvm { \
2020  namespace yaml { \
2021  static_assert( \
2022  !std::is_fundamental_v<TYPE> && !std::is_same_v<TYPE, std::string> && \
2023  !std::is_same_v<TYPE, llvm::StringRef>, \
2024  "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"); \
2025  template <> struct SequenceElementTraits<TYPE> { \
2026  static const bool flow = FLOW; \
2027  }; \
2028  } \
2029  }
2030 
2031 /// Utility for declaring that a std::vector of a particular type
2032 /// should be considered a YAML sequence.
2033 #define LLVM_YAML_IS_SEQUENCE_VECTOR(type) \
2034  LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
2035 
2036 /// Utility for declaring that a std::vector of a particular type
2037 /// should be considered a YAML flow sequence.
2038 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type) \
2039  LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
2040 
2041 #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type) \
2042  namespace llvm { \
2043  namespace yaml { \
2044  template <> struct MappingTraits<Type> { \
2045  static void mapping(IO &IO, Type &Obj); \
2046  }; \
2047  } \
2048  }
2049 
2050 #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type) \
2051  namespace llvm { \
2052  namespace yaml { \
2053  template <> struct ScalarEnumerationTraits<Type> { \
2054  static void enumeration(IO &io, Type &Value); \
2055  }; \
2056  } \
2057  }
2058 
2059 #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type) \
2060  namespace llvm { \
2061  namespace yaml { \
2062  template <> struct ScalarBitSetTraits<Type> { \
2063  static void bitset(IO &IO, Type &Options); \
2064  }; \
2065  } \
2066  }
2067 
2068 #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote) \
2069  namespace llvm { \
2070  namespace yaml { \
2071  template <> struct ScalarTraits<Type> { \
2072  static void output(const Type &Value, void *ctx, raw_ostream &Out); \
2073  static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \
2074  static QuotingType mustQuote(StringRef) { return MustQuote; } \
2075  }; \
2076  } \
2077  }
2078 
2079 /// Utility for declaring that a std::vector of a particular type
2080 /// should be considered a YAML document list.
2081 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \
2082  namespace llvm { \
2083  namespace yaml { \
2084  template <unsigned N> \
2085  struct DocumentListTraits<SmallVector<_type, N>> \
2086  : public SequenceTraitsImpl<SmallVector<_type, N>, false> {}; \
2087  template <> \
2088  struct DocumentListTraits<std::vector<_type>> \
2089  : public SequenceTraitsImpl<std::vector<_type>, false> {}; \
2090  } \
2091  }
2092 
2093 /// Utility for declaring that std::map<std::string, _type> should be considered
2094 /// a YAML map.
2095 #define LLVM_YAML_IS_STRING_MAP(_type) \
2096  namespace llvm { \
2097  namespace yaml { \
2098  template <> \
2099  struct CustomMappingTraits<std::map<std::string, _type>> \
2100  : public StdMapStringCustomMappingTraitsImpl<_type> {}; \
2101  } \
2102  }
2103 
2104 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
2105 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex32)
2106 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex16)
2107 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex8)
2108 
2109 #endif // LLVM_SUPPORT_YAMLTRAITS_H
i
i
Definition: README.txt:29
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::objcarc::Sequence
Sequence
Definition: PtrState.h:41
Optional.h
StringRef.h
YAMLParser.h
double
into xmm2 addss xmm2 xmm1 xmm3 addss xmm3 movaps xmm0 unpcklps xmm0 ret seems silly when it could just be one addps Expand libm rounding functions main should enable SSE DAZ mode and other fast SSE modes Think about doing i64 math in SSE regs on x86 This testcase should have no SSE instructions in and only one load from a constant double
Definition: README-SSE.txt:85
llvm::StringRef::npos
static constexpr size_t npos
Definition: StringRef.h:52
output
Current output
Definition: README.txt:1350
Allocator.h
true
basic Basic Alias true
Definition: BasicAliasAnalysis.cpp:1792
llvm::yaml::BlockScalarNode::classof
static bool classof(const Node *N)
Definition: YAMLParser.h:269
YamlIO
IO & YamlIO
Definition: ELFYAML.cpp:1250
error
#define error(X)
Definition: SymbolRecordMapping.cpp:14
llvm::BumpPtrAllocator
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition: Allocator.h:375
T
#define T
Definition: Mips16ISelLowering.cpp:341
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:891
AlignOf.h
llvm::RISCVFeatures::validate
void validate(const Triple &TT, const FeatureBitset &FeatureBits)
Definition: RISCVBaseInfo.cpp:97
llvm::dwarf::Tag
Tag
Definition: Dwarf.h:105
SpecialSubKind::allocator
@ allocator
llvm::yaml::NullNode::classof
static bool classof(const Node *N)
Definition: YAMLParser.h:203
p
the resulting code requires compare and branches when and if * p
Definition: README.txt:396
llvm::pdb::Double
@ Double
Definition: PDBTypes.h:402
size_t
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:265
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::support::endian
Definition: Endian.h:42
llvm::BitmaskEnumDetail::Mask
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:80
llvm::SmallVector
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Definition: SmallVector.h:1126
llvm::operator>>
ScaledNumber< DigitsT > operator>>(const ScaledNumber< DigitsT > &L, int16_t Shift)
Definition: ScaledNumber.h:736
llvm::msgpack::Type::Map
@ Map
f
Itanium Name Demangler i e convert the string _Z1fv into f()". You can also use the CRTP base ManglingParser to perform some simple analysis on the mangled name
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::cl::Required
@ Required
Definition: CommandLine.h:118
Twine.h
llvm::SrcMgr
SourceMgr SrcMgr
Definition: Error.cpp:24
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::AMDGPU::PALMD::Key
Key
PAL metadata keys.
Definition: AMDGPUMetadata.h:486
llvm::seq
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition: Sequence.h:305
SMLoc.h
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
llvm::yaml::ScalarNode::classof
static bool classof(const Node *N)
Definition: YAMLParser.h:235
llvm::operator<<
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:291
BitVector.h
llvm::yaml::MappingNode::classof
static bool classof(const Node *N)
Definition: YAMLParser.h:440
llvm::BitVector
Definition: BitVector.h:75
llvm::yaml::SequenceNode::classof
static bool classof(const Node *N)
Definition: YAMLParser.h:497
input
The initial backend is deliberately restricted to z10 We should add support for later architectures at some point If an asm ties an i32 r result to an i64 input
Definition: README.txt:10
llvm::NVPTX::PTXLdStInstCode::Scalar
@ Scalar
Definition: NVPTX.h:122
SourceMgr.h
llvm::tgtok::In
@ In
Definition: TGLexer.h:51
BaseType
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
Definition: SafepointIRVerifier.cpp:314
type
AMD64 Optimization Manual has some nice information about optimizing integer multiplication by a constant How much of it applies to Intel s X86 implementation There are definite trade offs to xmm0 cvttss2siq rdx jb L3 subss xmm0 rax cvttss2siq rdx xorq rdx rax ret instead of xmm1 cvttss2siq rcx movaps xmm2 subss xmm2 cvttss2siq rax rdx xorq rax ucomiss xmm0 cmovb rax ret Seems like the jb branch has high likelihood of being taken It would have saved a few instructions It s not possible to reference and DH registers in an instruction requiring REX prefix divb and mulb both produce results in AH If isel emits a CopyFromReg which gets turned into a movb and that can be allocated a r8b r15b To get around isel emits a CopyFromReg from AX and then right shift it down by and truncate it It s not pretty but it works We need some register allocation magic to make the hack go which would often require a callee saved register Callees usually need to keep this value live for most of their body so it doesn t add a significant burden on them We currently implement this in however this is suboptimal because it means that it would be quite awkward to implement the optimization for callers A better implementation would be to relax the LLVM IR rules for sret arguments to allow a function with an sret argument to have a non void return type
Definition: README-X86-64.txt:70
llvm::count
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:1870
index
splat index
Definition: README_ALTIVEC.txt:181
uint64_t
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR
#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type)
s
multiplies can be turned into SHL s
Definition: README.txt:370
LLVM_YAML_STRONG_TYPEDEF
#define LLVM_YAML_STRONG_TYPEDEF(_base, _type)
llvm::SourceMgr::DiagHandlerTy
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
Definition: SourceMgr.h:43
StringExtras.h
node
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper node
Definition: README-SSE.txt:406
size
i< reg-> size
Definition: README.txt:166
message
message(STATUS "Targeting ${t}") add_subdirectory($
Definition: CMakeLists.txt:34
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::codeview::CompileSym2Flags::EC
@ EC
mapOptional
static void mapOptional(yaml::IO &IO, const char *Key, EndianType &Val, typename EndianType::value_type Default)
Perform an optional yaml-mapping of an endian-aware type EndianType.
Definition: MinidumpYAML.cpp:20
llvm::size
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1690
Fallback
@ Fallback
Definition: WholeProgramDevirt.cpp:180
DiagHandler
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Definition: TextStub.cpp:1094
uint32_t
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
Node
Definition: ItaniumDemangle.h:156
llvm::pdb::Single
@ Single
Definition: PDBTypes.h:401
NodeKind
Determine the kind of a node from its type.
Definition: ItaniumDemangle.h:2373
std
Definition: BitVector.h:851
llvm::None
constexpr std::nullopt_t None
Definition: None.h:27
uint16_t
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::TargetStackID::Default
@ Default
Definition: TargetFrameLowering.h:28
llvm::pdb::PDB_ColorItem::Padding
@ Padding
llvm::ms_demangle::NodeKind
NodeKind
Definition: MicrosoftDemangleNodes.h:226
SmallVector.h
llvm::TPLoop::Allow
@ Allow
Definition: ARMTargetTransformInfo.h:53
N
#define N
llvm::CallingConv::Tail
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
Definition: CallingConv.h:76
support
Reimplement select in terms of SEL *We would really like to support but we need to prove that the add doesn t need to overflow between the two bit chunks *Implement pre post increment support(e.g. PR935) *Implement smarter const ant generation for binops with large immediates. A few ARMv6T2 ops should be pattern matched
Definition: README.txt:10
StringMap.h
llvm::pdb::OMFSegDescFlags::Write
@ Write
raw_ostream.h
n
The same transformation can work with an even modulo with the addition of a and shrink the compare RHS by the same amount Unless the target supports that transformation probably isn t worthwhile The transformation can also easily be made to work with non zero equality for n
Definition: README.txt:685
test
modulo schedule test
Definition: ModuloSchedule.cpp:2144
Endian.h
SpecialSubKind::string
@ string