LLVM  14.0.0git
JSON.cpp
Go to the documentation of this file.
1 //=== JSON.cpp - JSON value, parsing and serialization - 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 #include "llvm/Support/JSON.h"
10 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/Support/Error.h"
13 #include "llvm/Support/Format.h"
15 #include <cctype>
16 
17 namespace llvm {
18 namespace json {
19 
21  return try_emplace(K, nullptr).first->getSecond();
22 }
24  return try_emplace(std::move(K), nullptr).first->getSecond();
25 }
27  auto I = find(K);
28  if (I == end())
29  return nullptr;
30  return &I->second;
31 }
32 const Value *Object::get(StringRef K) const {
33  auto I = find(K);
34  if (I == end())
35  return nullptr;
36  return &I->second;
37 }
39  if (auto *V = get(K))
40  return V->getAsNull();
41  return llvm::None;
42 }
44  if (auto *V = get(K))
45  return V->getAsBoolean();
46  return llvm::None;
47 }
49  if (auto *V = get(K))
50  return V->getAsNumber();
51  return llvm::None;
52 }
54  if (auto *V = get(K))
55  return V->getAsInteger();
56  return llvm::None;
57 }
59  if (auto *V = get(K))
60  return V->getAsString();
61  return llvm::None;
62 }
64  if (auto *V = get(K))
65  return V->getAsObject();
66  return nullptr;
67 }
69  if (auto *V = get(K))
70  return V->getAsObject();
71  return nullptr;
72 }
74  if (auto *V = get(K))
75  return V->getAsArray();
76  return nullptr;
77 }
79  if (auto *V = get(K))
80  return V->getAsArray();
81  return nullptr;
82 }
83 bool operator==(const Object &LHS, const Object &RHS) {
84  if (LHS.size() != RHS.size())
85  return false;
86  for (const auto &L : LHS) {
87  auto R = RHS.find(L.first);
88  if (R == RHS.end() || L.second != R->second)
89  return false;
90  }
91  return true;
92 }
93 
94 Array::Array(std::initializer_list<Value> Elements) {
95  V.reserve(Elements.size());
96  for (const Value &V : Elements) {
97  emplace_back(nullptr);
98  back().moveFrom(std::move(V));
99  }
100 }
101 
102 Value::Value(std::initializer_list<Value> Elements)
103  : Value(json::Array(Elements)) {}
104 
105 void Value::copyFrom(const Value &M) {
106  Type = M.Type;
107  switch (Type) {
108  case T_Null:
109  case T_Boolean:
110  case T_Double:
111  case T_Integer:
112  memcpy(&Union, &M.Union, sizeof(Union));
113  break;
114  case T_StringRef:
115  create<StringRef>(M.as<StringRef>());
116  break;
117  case T_String:
118  create<std::string>(M.as<std::string>());
119  break;
120  case T_Object:
121  create<json::Object>(M.as<json::Object>());
122  break;
123  case T_Array:
124  create<json::Array>(M.as<json::Array>());
125  break;
126  }
127 }
128 
129 void Value::moveFrom(const Value &&M) {
130  Type = M.Type;
131  switch (Type) {
132  case T_Null:
133  case T_Boolean:
134  case T_Double:
135  case T_Integer:
136  memcpy(&Union, &M.Union, sizeof(Union));
137  break;
138  case T_StringRef:
139  create<StringRef>(M.as<StringRef>());
140  break;
141  case T_String:
142  create<std::string>(std::move(M.as<std::string>()));
143  M.Type = T_Null;
144  break;
145  case T_Object:
146  create<json::Object>(std::move(M.as<json::Object>()));
147  M.Type = T_Null;
148  break;
149  case T_Array:
150  create<json::Array>(std::move(M.as<json::Array>()));
151  M.Type = T_Null;
152  break;
153  }
154 }
155 
156 void Value::destroy() {
157  switch (Type) {
158  case T_Null:
159  case T_Boolean:
160  case T_Double:
161  case T_Integer:
162  break;
163  case T_StringRef:
164  as<StringRef>().~StringRef();
165  break;
166  case T_String:
167  as<std::string>().~basic_string();
168  break;
169  case T_Object:
170  as<json::Object>().~Object();
171  break;
172  case T_Array:
173  as<json::Array>().~Array();
174  break;
175  }
176 }
177 
178 bool operator==(const Value &L, const Value &R) {
179  if (L.kind() != R.kind())
180  return false;
181  switch (L.kind()) {
182  case Value::Null:
183  return *L.getAsNull() == *R.getAsNull();
184  case Value::Boolean:
185  return *L.getAsBoolean() == *R.getAsBoolean();
186  case Value::Number:
187  // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323
188  // The same integer must convert to the same double, per the standard.
189  // However we see 64-vs-80-bit precision comparisons with gcc-7 -O3 -m32.
190  // So we avoid floating point promotion for exact comparisons.
191  if (L.Type == Value::T_Integer || R.Type == Value::T_Integer)
192  return L.getAsInteger() == R.getAsInteger();
193  return *L.getAsNumber() == *R.getAsNumber();
194  case Value::String:
195  return *L.getAsString() == *R.getAsString();
196  case Value::Array:
197  return *L.getAsArray() == *R.getAsArray();
198  case Value::Object:
199  return *L.getAsObject() == *R.getAsObject();
200  }
201  llvm_unreachable("Unknown value kind");
202 }
203 
205  // Walk up to the root context, and count the number of segments.
206  unsigned Count = 0;
207  const Path *P;
208  for (P = this; P->Parent != nullptr; P = P->Parent)
209  ++Count;
210  Path::Root *R = P->Seg.root();
211  // Fill in the error message and copy the path (in reverse order).
212  R->ErrorMessage = Msg;
213  R->ErrorPath.resize(Count);
214  auto It = R->ErrorPath.begin();
215  for (P = this; P->Parent != nullptr; P = P->Parent)
216  *It++ = P->Seg;
217 }
218 
220  std::string S;
221  raw_string_ostream OS(S);
222  OS << (ErrorMessage.empty() ? "invalid JSON contents" : ErrorMessage);
223  if (ErrorPath.empty()) {
224  if (!Name.empty())
225  OS << " when parsing " << Name;
226  } else {
227  OS << " at " << (Name.empty() ? "(root)" : Name);
228  for (const Path::Segment &S : llvm::reverse(ErrorPath)) {
229  if (S.isField())
230  OS << '.' << S.field();
231  else
232  OS << '[' << S.index() << ']';
233  }
234  }
236 }
237 
238 namespace {
239 
240 std::vector<const Object::value_type *> sortedElements(const Object &O) {
241  std::vector<const Object::value_type *> Elements;
242  for (const auto &E : O)
243  Elements.push_back(&E);
244  llvm::sort(Elements,
245  [](const Object::value_type *L, const Object::value_type *R) {
246  return L->first < R->first;
247  });
248  return Elements;
249 }
250 
251 // Prints a one-line version of a value that isn't our main focus.
252 // We interleave writes to OS and JOS, exploiting the lack of extra buffering.
253 // This is OK as we own the implementation.
254 void abbreviate(const Value &V, OStream &JOS) {
255  switch (V.kind()) {
256  case Value::Array:
257  JOS.rawValue(V.getAsArray()->empty() ? "[]" : "[ ... ]");
258  break;
259  case Value::Object:
260  JOS.rawValue(V.getAsObject()->empty() ? "{}" : "{ ... }");
261  break;
262  case Value::String: {
263  llvm::StringRef S = *V.getAsString();
264  if (S.size() < 40) {
265  JOS.value(V);
266  } else {
267  std::string Truncated = fixUTF8(S.take_front(37));
268  Truncated.append("...");
269  JOS.value(Truncated);
270  }
271  break;
272  }
273  default:
274  JOS.value(V);
275  }
276 }
277 
278 // Prints a semi-expanded version of a value that is our main focus.
279 // Array/Object entries are printed, but not recursively as they may be huge.
280 void abbreviateChildren(const Value &V, OStream &JOS) {
281  switch (V.kind()) {
282  case Value::Array:
283  JOS.array([&] {
284  for (const auto &I : *V.getAsArray())
285  abbreviate(I, JOS);
286  });
287  break;
288  case Value::Object:
289  JOS.object([&] {
290  for (const auto *KV : sortedElements(*V.getAsObject())) {
291  JOS.attributeBegin(KV->first);
292  abbreviate(KV->second, JOS);
293  JOS.attributeEnd();
294  }
295  });
296  break;
297  default:
298  JOS.value(V);
299  }
300 }
301 
302 } // namespace
303 
305  OStream JOS(OS, /*IndentSize=*/2);
306  // PrintValue recurses down the path, printing the ancestors of our target.
307  // Siblings of nodes along the path are printed with abbreviate(), and the
308  // target itself is printed with the somewhat richer abbreviateChildren().
309  // 'Recurse' is the lambda itself, to allow recursive calls.
310  auto PrintValue = [&](const Value &V, ArrayRef<Segment> Path, auto &Recurse) {
311  // Print the target node itself, with the error as a comment.
312  // Also used if we can't follow our path, e.g. it names a field that
313  // *should* exist but doesn't.
314  auto HighlightCurrent = [&] {
315  std::string Comment = "error: ";
316  Comment.append(ErrorMessage.data(), ErrorMessage.size());
317  JOS.comment(Comment);
318  abbreviateChildren(V, JOS);
319  };
320  if (Path.empty()) // We reached our target.
321  return HighlightCurrent();
322  const Segment &S = Path.back(); // Path is in reverse order.
323  if (S.isField()) {
324  // Current node is an object, path names a field.
325  llvm::StringRef FieldName = S.field();
326  const Object *O = V.getAsObject();
327  if (!O || !O->get(FieldName))
328  return HighlightCurrent();
329  JOS.object([&] {
330  for (const auto *KV : sortedElements(*O)) {
331  JOS.attributeBegin(KV->first);
332  if (FieldName.equals(KV->first))
333  Recurse(KV->second, Path.drop_back(), Recurse);
334  else
335  abbreviate(KV->second, JOS);
336  JOS.attributeEnd();
337  }
338  });
339  } else {
340  // Current node is an array, path names an element.
341  const Array *A = V.getAsArray();
342  if (!A || S.index() >= A->size())
343  return HighlightCurrent();
344  JOS.array([&] {
345  unsigned Current = 0;
346  for (const auto &V : *A) {
347  if (Current++ == S.index())
348  Recurse(V, Path.drop_back(), Recurse);
349  else
350  abbreviate(V, JOS);
351  }
352  });
353  }
354  };
355  PrintValue(R, ErrorPath, PrintValue);
356 }
357 
358 namespace {
359 // Simple recursive-descent JSON parser.
360 class Parser {
361 public:
362  Parser(StringRef JSON)
363  : Start(JSON.begin()), P(JSON.begin()), End(JSON.end()) {}
364 
365  bool checkUTF8() {
366  size_t ErrOffset;
367  if (isUTF8(StringRef(Start, End - Start), &ErrOffset))
368  return true;
369  P = Start + ErrOffset; // For line/column calculation.
370  return parseError("Invalid UTF-8 sequence");
371  }
372 
373  bool parseValue(Value &Out);
374 
375  bool assertEnd() {
376  eatWhitespace();
377  if (P == End)
378  return true;
379  return parseError("Text after end of document");
380  }
381 
382  Error takeError() {
383  assert(Err);
384  return std::move(*Err);
385  }
386 
387 private:
388  void eatWhitespace() {
389  while (P != End && (*P == ' ' || *P == '\r' || *P == '\n' || *P == '\t'))
390  ++P;
391  }
392 
393  // On invalid syntax, parseX() functions return false and set Err.
394  bool parseNumber(char First, Value &Out);
395  bool parseString(std::string &Out);
396  bool parseUnicode(std::string &Out);
397  bool parseError(const char *Msg); // always returns false
398 
399  char next() { return P == End ? 0 : *P++; }
400  char peek() { return P == End ? 0 : *P; }
401  static bool isNumber(char C) {
402  return C == '0' || C == '1' || C == '2' || C == '3' || C == '4' ||
403  C == '5' || C == '6' || C == '7' || C == '8' || C == '9' ||
404  C == 'e' || C == 'E' || C == '+' || C == '-' || C == '.';
405  }
406 
407  Optional<Error> Err;
408  const char *Start, *P, *End;
409 };
410 
411 bool Parser::parseValue(Value &Out) {
412  eatWhitespace();
413  if (P == End)
414  return parseError("Unexpected EOF");
415  switch (char C = next()) {
416  // Bare null/true/false are easy - first char identifies them.
417  case 'n':
418  Out = nullptr;
419  return (next() == 'u' && next() == 'l' && next() == 'l') ||
420  parseError("Invalid JSON value (null?)");
421  case 't':
422  Out = true;
423  return (next() == 'r' && next() == 'u' && next() == 'e') ||
424  parseError("Invalid JSON value (true?)");
425  case 'f':
426  Out = false;
427  return (next() == 'a' && next() == 'l' && next() == 's' && next() == 'e') ||
428  parseError("Invalid JSON value (false?)");
429  case '"': {
430  std::string S;
431  if (parseString(S)) {
432  Out = std::move(S);
433  return true;
434  }
435  return false;
436  }
437  case '[': {
438  Out = Array{};
439  Array &A = *Out.getAsArray();
440  eatWhitespace();
441  if (peek() == ']') {
442  ++P;
443  return true;
444  }
445  for (;;) {
446  A.emplace_back(nullptr);
447  if (!parseValue(A.back()))
448  return false;
449  eatWhitespace();
450  switch (next()) {
451  case ',':
452  eatWhitespace();
453  continue;
454  case ']':
455  return true;
456  default:
457  return parseError("Expected , or ] after array element");
458  }
459  }
460  }
461  case '{': {
462  Out = Object{};
463  Object &O = *Out.getAsObject();
464  eatWhitespace();
465  if (peek() == '}') {
466  ++P;
467  return true;
468  }
469  for (;;) {
470  if (next() != '"')
471  return parseError("Expected object key");
472  std::string K;
473  if (!parseString(K))
474  return false;
475  eatWhitespace();
476  if (next() != ':')
477  return parseError("Expected : after object key");
478  eatWhitespace();
479  if (!parseValue(O[std::move(K)]))
480  return false;
481  eatWhitespace();
482  switch (next()) {
483  case ',':
484  eatWhitespace();
485  continue;
486  case '}':
487  return true;
488  default:
489  return parseError("Expected , or } after object property");
490  }
491  }
492  }
493  default:
494  if (isNumber(C))
495  return parseNumber(C, Out);
496  return parseError("Invalid JSON value");
497  }
498 }
499 
500 bool Parser::parseNumber(char First, Value &Out) {
501  // Read the number into a string. (Must be null-terminated for strto*).
502  SmallString<24> S;
503  S.push_back(First);
504  while (isNumber(peek()))
505  S.push_back(next());
506  char *End;
507  // Try first to parse as integer, and if so preserve full 64 bits.
508  // strtoll returns long long >= 64 bits, so check it's in range too.
509  auto I = std::strtoll(S.c_str(), &End, 10);
510  if (End == S.end() && I >= std::numeric_limits<int64_t>::min() &&
512  Out = int64_t(I);
513  return true;
514  }
515  // If it's not an integer
516  Out = std::strtod(S.c_str(), &End);
517  return End == S.end() || parseError("Invalid JSON value (number?)");
518 }
519 
520 bool Parser::parseString(std::string &Out) {
521  // leading quote was already consumed.
522  for (char C = next(); C != '"'; C = next()) {
523  if (LLVM_UNLIKELY(P == End))
524  return parseError("Unterminated string");
525  if (LLVM_UNLIKELY((C & 0x1f) == C))
526  return parseError("Control character in string");
527  if (LLVM_LIKELY(C != '\\')) {
528  Out.push_back(C);
529  continue;
530  }
531  // Handle escape sequence.
532  switch (C = next()) {
533  case '"':
534  case '\\':
535  case '/':
536  Out.push_back(C);
537  break;
538  case 'b':
539  Out.push_back('\b');
540  break;
541  case 'f':
542  Out.push_back('\f');
543  break;
544  case 'n':
545  Out.push_back('\n');
546  break;
547  case 'r':
548  Out.push_back('\r');
549  break;
550  case 't':
551  Out.push_back('\t');
552  break;
553  case 'u':
554  if (!parseUnicode(Out))
555  return false;
556  break;
557  default:
558  return parseError("Invalid escape sequence");
559  }
560  }
561  return true;
562 }
563 
564 static void encodeUtf8(uint32_t Rune, std::string &Out) {
565  if (Rune < 0x80) {
566  Out.push_back(Rune & 0x7F);
567  } else if (Rune < 0x800) {
568  uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6);
569  uint8_t SecondByte = 0x80 | (Rune & 0x3F);
570  Out.push_back(FirstByte);
571  Out.push_back(SecondByte);
572  } else if (Rune < 0x10000) {
573  uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12);
574  uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6);
575  uint8_t ThirdByte = 0x80 | (Rune & 0x3F);
576  Out.push_back(FirstByte);
577  Out.push_back(SecondByte);
578  Out.push_back(ThirdByte);
579  } else if (Rune < 0x110000) {
580  uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18);
581  uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12);
582  uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6);
583  uint8_t FourthByte = 0x80 | (Rune & 0x3F);
584  Out.push_back(FirstByte);
585  Out.push_back(SecondByte);
586  Out.push_back(ThirdByte);
587  Out.push_back(FourthByte);
588  } else {
589  llvm_unreachable("Invalid codepoint");
590  }
591 }
592 
593 // Parse a UTF-16 \uNNNN escape sequence. "\u" has already been consumed.
594 // May parse several sequential escapes to ensure proper surrogate handling.
595 // We do not use ConvertUTF.h, it can't accept and replace unpaired surrogates.
596 // These are invalid Unicode but valid JSON (RFC 8259, section 8.2).
597 bool Parser::parseUnicode(std::string &Out) {
598  // Invalid UTF is not a JSON error (RFC 8529§8.2). It gets replaced by U+FFFD.
599  auto Invalid = [&] { Out.append(/* UTF-8 */ {'\xef', '\xbf', '\xbd'}); };
600  // Decodes 4 hex digits from the stream into Out, returns false on error.
601  auto Parse4Hex = [this](uint16_t &Out) -> bool {
602  Out = 0;
603  char Bytes[] = {next(), next(), next(), next()};
604  for (unsigned char C : Bytes) {
605  if (!std::isxdigit(C))
606  return parseError("Invalid \\u escape sequence");
607  Out <<= 4;
608  Out |= (C > '9') ? (C & ~0x20) - 'A' + 10 : (C - '0');
609  }
610  return true;
611  };
612  uint16_t First; // UTF-16 code unit from the first \u escape.
613  if (!Parse4Hex(First))
614  return false;
615 
616  // We loop to allow proper surrogate-pair error handling.
617  while (true) {
618  // Case 1: the UTF-16 code unit is already a codepoint in the BMP.
619  if (LLVM_LIKELY(First < 0xD800 || First >= 0xE000)) {
620  encodeUtf8(First, Out);
621  return true;
622  }
623 
624  // Case 2: it's an (unpaired) trailing surrogate.
625  if (LLVM_UNLIKELY(First >= 0xDC00)) {
626  Invalid();
627  return true;
628  }
629 
630  // Case 3: it's a leading surrogate. We expect a trailing one next.
631  // Case 3a: there's no trailing \u escape. Don't advance in the stream.
632  if (LLVM_UNLIKELY(P + 2 > End || *P != '\\' || *(P + 1) != 'u')) {
633  Invalid(); // Leading surrogate was unpaired.
634  return true;
635  }
636  P += 2;
637  uint16_t Second;
638  if (!Parse4Hex(Second))
639  return false;
640  // Case 3b: there was another \u escape, but it wasn't a trailing surrogate.
641  if (LLVM_UNLIKELY(Second < 0xDC00 || Second >= 0xE000)) {
642  Invalid(); // Leading surrogate was unpaired.
643  First = Second; // Second escape still needs to be processed.
644  continue;
645  }
646  // Case 3c: a valid surrogate pair encoding an astral codepoint.
647  encodeUtf8(0x10000 | ((First - 0xD800) << 10) | (Second - 0xDC00), Out);
648  return true;
649  }
650 }
651 
652 bool Parser::parseError(const char *Msg) {
653  int Line = 1;
654  const char *StartOfLine = Start;
655  for (const char *X = Start; X < P; ++X) {
656  if (*X == 0x0A) {
657  ++Line;
658  StartOfLine = X + 1;
659  }
660  }
661  Err.emplace(
662  std::make_unique<ParseError>(Msg, Line, P - StartOfLine, P - Start));
663  return false;
664 }
665 } // namespace
666 
668  Parser P(JSON);
669  Value E = nullptr;
670  if (P.checkUTF8())
671  if (P.parseValue(E))
672  if (P.assertEnd())
673  return std::move(E);
674  return P.takeError();
675 }
676 char ParseError::ID = 0;
677 
678 bool isUTF8(llvm::StringRef S, size_t *ErrOffset) {
679  // Fast-path for ASCII, which is valid UTF-8.
680  if (LLVM_LIKELY(isASCII(S)))
681  return true;
682 
683  const UTF8 *Data = reinterpret_cast<const UTF8 *>(S.data()), *Rest = Data;
684  if (LLVM_LIKELY(isLegalUTF8String(&Rest, Data + S.size())))
685  return true;
686 
687  if (ErrOffset)
688  *ErrOffset = Rest - Data;
689  return false;
690 }
691 
692 std::string fixUTF8(llvm::StringRef S) {
693  // This isn't particularly efficient, but is only for error-recovery.
694  std::vector<UTF32> Codepoints(S.size()); // 1 codepoint per byte suffices.
695  const UTF8 *In8 = reinterpret_cast<const UTF8 *>(S.data());
696  UTF32 *Out32 = Codepoints.data();
697  ConvertUTF8toUTF32(&In8, In8 + S.size(), &Out32, Out32 + Codepoints.size(),
699  Codepoints.resize(Out32 - Codepoints.data());
700  std::string Res(4 * Codepoints.size(), 0); // 4 bytes per codepoint suffice
701  const UTF32 *In32 = Codepoints.data();
702  UTF8 *Out8 = reinterpret_cast<UTF8 *>(&Res[0]);
703  ConvertUTF32toUTF8(&In32, In32 + Codepoints.size(), &Out8, Out8 + Res.size(),
705  Res.resize(reinterpret_cast<char *>(Out8) - Res.data());
706  return Res;
707 }
708 
710  OS << '\"';
711  for (unsigned char C : S) {
712  if (C == 0x22 || C == 0x5C)
713  OS << '\\';
714  if (C >= 0x20) {
715  OS << C;
716  continue;
717  }
718  OS << '\\';
719  switch (C) {
720  // A few characters are common enough to make short escapes worthwhile.
721  case '\t':
722  OS << 't';
723  break;
724  case '\n':
725  OS << 'n';
726  break;
727  case '\r':
728  OS << 'r';
729  break;
730  default:
731  OS << 'u';
733  break;
734  }
735  }
736  OS << '\"';
737 }
738 
740  switch (V.kind()) {
741  case Value::Null:
742  valueBegin();
743  OS << "null";
744  return;
745  case Value::Boolean:
746  valueBegin();
747  OS << (*V.getAsBoolean() ? "true" : "false");
748  return;
749  case Value::Number:
750  valueBegin();
751  if (V.Type == Value::T_Integer)
752  OS << *V.getAsInteger();
753  else
754  OS << format("%.*g", std::numeric_limits<double>::max_digits10,
755  *V.getAsNumber());
756  return;
757  case Value::String:
758  valueBegin();
759  quote(OS, *V.getAsString());
760  return;
761  case Value::Array:
762  return array([&] {
763  for (const Value &E : *V.getAsArray())
764  value(E);
765  });
766  case Value::Object:
767  return object([&] {
768  for (const Object::value_type *E : sortedElements(*V.getAsObject()))
769  attribute(E->first, E->second);
770  });
771  }
772 }
773 
774 void llvm::json::OStream::valueBegin() {
775  assert(Stack.back().Ctx != Object && "Only attributes allowed here");
776  if (Stack.back().HasValue) {
777  assert(Stack.back().Ctx != Singleton && "Only one value allowed here");
778  OS << ',';
779  }
780  if (Stack.back().Ctx == Array)
781  newline();
782  flushComment();
783  Stack.back().HasValue = true;
784 }
785 
787  assert(PendingComment.empty() && "Only one comment per value!");
788  PendingComment = Comment;
789 }
790 
791 void OStream::flushComment() {
792  if (PendingComment.empty())
793  return;
794  OS << (IndentSize ? "/* " : "/*");
795  // Be sure not to accidentally emit "*/". Transform to "* /".
796  while (!PendingComment.empty()) {
797  auto Pos = PendingComment.find("*/");
798  if (Pos == StringRef::npos) {
799  OS << PendingComment;
800  PendingComment = "";
801  } else {
802  OS << PendingComment.take_front(Pos) << "* /";
803  PendingComment = PendingComment.drop_front(Pos + 2);
804  }
805  }
806  OS << (IndentSize ? " */" : "*/");
807  // Comments are on their own line unless attached to an attribute value.
808  if (Stack.size() > 1 && Stack.back().Ctx == Singleton) {
809  if (IndentSize)
810  OS << ' ';
811  } else {
812  newline();
813  }
814 }
815 
816 void llvm::json::OStream::newline() {
817  if (IndentSize) {
818  OS.write('\n');
819  OS.indent(Indent);
820  }
821 }
822 
824  valueBegin();
825  Stack.emplace_back();
826  Stack.back().Ctx = Array;
827  Indent += IndentSize;
828  OS << '[';
829 }
830 
832  assert(Stack.back().Ctx == Array);
833  Indent -= IndentSize;
834  if (Stack.back().HasValue)
835  newline();
836  OS << ']';
837  assert(PendingComment.empty());
838  Stack.pop_back();
839  assert(!Stack.empty());
840 }
841 
843  valueBegin();
844  Stack.emplace_back();
845  Stack.back().Ctx = Object;
846  Indent += IndentSize;
847  OS << '{';
848 }
849 
851  assert(Stack.back().Ctx == Object);
852  Indent -= IndentSize;
853  if (Stack.back().HasValue)
854  newline();
855  OS << '}';
856  assert(PendingComment.empty());
857  Stack.pop_back();
858  assert(!Stack.empty());
859 }
860 
862  assert(Stack.back().Ctx == Object);
863  if (Stack.back().HasValue)
864  OS << ',';
865  newline();
866  flushComment();
867  Stack.back().HasValue = true;
868  Stack.emplace_back();
869  Stack.back().Ctx = Singleton;
870  if (LLVM_LIKELY(isUTF8(Key))) {
871  quote(OS, Key);
872  } else {
873  assert(false && "Invalid UTF-8 in attribute key");
874  quote(OS, fixUTF8(Key));
875  }
876  OS.write(':');
877  if (IndentSize)
878  OS.write(' ');
879 }
880 
882  assert(Stack.back().Ctx == Singleton);
883  assert(Stack.back().HasValue && "Attribute must have a value");
884  assert(PendingComment.empty());
885  Stack.pop_back();
886  assert(Stack.back().Ctx == Object);
887 }
888 
890  valueBegin();
891  Stack.emplace_back();
892  Stack.back().Ctx = RawValue;
893  return OS;
894 }
895 
897  assert(Stack.back().Ctx == RawValue);
898  Stack.pop_back();
899 }
900 
901 } // namespace json
902 } // namespace llvm
903 
906  unsigned IndentAmount = 0;
907  if (!Options.empty() && Options.getAsInteger(/*Radix=*/10, IndentAmount))
908  llvm_unreachable("json::Value format options should be an integer");
909  json::OStream(OS, IndentAmount).value(E);
910 }
911 
llvm::json::OStream::comment
void comment(llvm::StringRef)
Emit a JavaScript comment associated with the next printed value.
Definition: JSON.cpp:786
llvm::json::OStream::attributeBegin
void attributeBegin(llvm::StringRef Key)
Definition: JSON.cpp:861
llvm::json::Path::Root
The root is the trivial Path to the root value.
Definition: JSON.h:617
llvm::json::Value
A Value is an JSON value of unknown type.
Definition: JSON.h:289
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::StringRef::empty
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:153
llvm::json::Value::kind
Kind kind() const
Definition: JSON.h:377
llvm::json::Value::Boolean
@ Boolean
Definition: JSON.h:293
llvm::json::Value::Object
friend class Object
Definition: JSON.h:456
P
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 which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
llvm::json::OStream::attributeEnd
void attributeEnd()
Definition: JSON.cpp:881
llvm::json::quote
static void quote(llvm::raw_ostream &OS, llvm::StringRef S)
Definition: JSON.cpp:709
llvm::json::Array::emplace_back
void emplace_back(Args &&... A)
Definition: JSON.h:192
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:625
llvm::StringRef::npos
static constexpr size_t npos
Definition: StringRef.h:60
llvm::StringRef::find
LLVM_NODISCARD size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:315
Error.h
llvm::MachO::Invalid
@ Invalid
Invalid file type.
Definition: InterfaceFile.h:59
llvm::json::Value::getAsNull
llvm::Optional< std::nullptr_t > getAsNull() const
Definition: JSON.h:398
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::reverse
auto reverse(ContainerTy &&C, std::enable_if_t< has_rbegin< ContainerTy >::value > *=nullptr)
Definition: STLExtras.h:329
llvm::sys::path::end
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:233
llvm::sys::path::begin
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:224
llvm::json::Path::Root::printErrorContext
void printErrorContext(const Value &, llvm::raw_ostream &) const
Print the root value with the error shown inline as a comment.
Definition: JSON.cpp:304
llvm::Optional
Definition: APInt.h:33
llvm::json::Value::Null
@ Null
Definition: JSON.h:292
llvm::msgpack::Type::Array
@ Array
llvm::json::Value::getAsNumber
llvm::Optional< double > getAsNumber() const
Definition: JSON.h:408
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
STLExtras.h
Format.h
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::detail::DenseMapPair< ObjectKey, Value >
llvm::json::Path::report
void report(llvm::StringLiteral Message)
Records that the value at the current path is invalid.
Definition: JSON.cpp:204
peek
static bool peek(struct InternalInstruction *insn, uint8_t &byte)
Definition: X86Disassembler.cpp:184
llvm::json::operator==
bool operator==(const Object &LHS, const Object &RHS)
Definition: JSON.cpp:83
llvm::ConvertUTF32toUTF8
ConversionResult ConvertUTF32toUTF8(const UTF32 **sourceStart, const UTF32 *sourceEnd, UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
Definition: ConvertUTF.cpp:317
llvm::StringLiteral
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition: StringRef.h:891
llvm::json::Object::getString
llvm::Optional< llvm::StringRef > getString(StringRef K) const
Definition: JSON.cpp:58
llvm::json::Value::Value
Value(const Value &M)
Definition: JSON.h:303
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::json::OStream::object
void object(Block Contents)
Emit an object whose elements are emitted in the provided Block.
Definition: JSON.h:916
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::ARM_PROC::A
@ A
Definition: ARMBaseInfo.h:34
llvm::json::OStream::array
void array(Block Contents)
Emit an array whose elements are emitted in the provided Block.
Definition: JSON.h:910
llvm::json::Object::getObject
const json::Object * getObject(StringRef K) const
Definition: JSON.cpp:63
llvm::AMDGPU::PALMD::Key
Key
PAL metadata keys.
Definition: AMDGPUMetadata.h:481
First
into llvm powi allowing the code generator to produce balanced multiplication trees First
Definition: README.txt:54
llvm::json::Value::Number
@ Number
Number values can store both int64s and doubles at full precision, depending on what they were constr...
Definition: JSON.h:296
llvm::json::Value::Array
friend class Array
Definition: JSON.h:455
llvm::json::Array
An Array is a JSON array, which contains heterogeneous JSON values.
Definition: JSON.h:156
Options
const char LLVMTargetMachineRef LLVMPassBuilderOptionsRef Options
Definition: PassBuilderBindings.cpp:48
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
JSON.h
llvm::json::parse
llvm::Expected< Value > parse(llvm::StringRef JSON)
Parses the provided JSON source, or returns a ParseError.
Definition: JSON.cpp:667
llvm::json::Object::try_emplace
std::pair< iterator, bool > try_emplace(const ObjectKey &K, Ts &&... Args)
Definition: JSON.h:118
llvm::None
const NoneType None
Definition: None.h:23
llvm::json::OStream::objectEnd
void objectEnd()
Definition: JSON.cpp:850
llvm::lenientConversion
@ lenientConversion
Definition: ConvertUTF.h:135
X
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
llvm::StringRef::equals
LLVM_NODISCARD bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
Definition: StringRef.h:187
llvm::json::Object::getNumber
llvm::Optional< double > getNumber(StringRef K) const
Definition: JSON.cpp:48
llvm::OutputFileType::Object
@ Object
llvm::json::Object::find
iterator find(StringRef K)
Definition: JSON.h:128
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:192
llvm::json::Value::getAsArray
const json::Array * getAsArray() const
Definition: JSON.h:441
llvm::json::OStream::rawValueEnd
void rawValueEnd()
Definition: JSON.cpp:896
object
bar al al movzbl eax ret Missed when stored in a memory object
Definition: README.txt:1411
llvm::json::OStream
json::OStream allows writing well-formed JSON without materializing all structures as json::Value ahe...
Definition: JSON.h:886
llvm::json::Object::get
Value * get(StringRef K)
Definition: JSON.cpp:26
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::json::OStream::arrayBegin
void arrayBegin()
Definition: JSON.cpp:823
llvm::json::Object::operator[]
Value & operator[](const ObjectKey &K)
Definition: JSON.cpp:20
llvm::json::Value::getAsInteger
llvm::Optional< int64_t > getAsInteger() const
Definition: JSON.h:416
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::pdb::PDB_MemoryType::Stack
@ Stack
llvm::json::Array::back
Value & back()
Definition: JSON.h:175
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::json::fixUTF8
std::string fixUTF8(llvm::StringRef S)
Replaces invalid UTF-8 sequences in S with the replacement character (U+FFFD).
Definition: JSON.cpp:692
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::json::Array::Array
Array()=default
llvm::ConvertUTF8toUTF32
ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, const UTF8 *sourceEnd, UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags)
Convert a partial UTF8 sequence to UTF32.
Definition: ConvertUTF.cpp:710
llvm::write_hex
void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, Optional< size_t > Width=None)
Definition: NativeFormatting.cpp:133
llvm::json::Value::getAsBoolean
llvm::Optional< bool > getAsBoolean() const
Definition: JSON.h:403
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::min
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Definition: FileCheck.cpp:357
llvm::json::Object::size
size_t size() const
Definition: JSON.h:113
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::json::Object::getInteger
llvm::Optional< int64_t > getInteger(StringRef K) const
Definition: JSON.cpp:53
llvm::json::Object::end
iterator end()
Definition: JSON.h:109
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
if
if(llvm_vc STREQUAL "") set(fake_version_inc "$
Definition: CMakeLists.txt:14
llvm::strictConversion
@ strictConversion
Definition: ConvertUTF.h:134
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
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::json::ParseError::ID
static char ID
Definition: JSON.h:807
ConvertUTF.h
llvm::json::Path::Root::getError
Error getError() const
Returns the last error reported, or else a generic error.
Definition: JSON.cpp:219
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1231
llvm::inconvertibleErrorCode
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:77
llvm::json::Value::getAsObject
const json::Object * getAsObject() const
Definition: JSON.h:435
uint16_t
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::HexPrintStyle::Lower
@ Lower
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1488
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::json::OStream::value
void value(const Value &V)
Emit a self-contained value (number, string, vector<string> etc).
Definition: JSON.cpp:739
llvm::json::Object::getArray
const json::Array * getArray(StringRef K) const
Definition: JSON.cpp:73
llvm::isLegalUTF8String
Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd)
Definition: ConvertUTF.cpp:529
llvm::json::Value::String
@ String
Definition: JSON.h:297
llvm::json::Path::Path
Path(Root &R)
The root may be treated as a Path.
Definition: JSON.h:580
llvm::UTF32
unsigned int UTF32
Definition: ConvertUTF.h:109
llvm::json::OStream::arrayEnd
void arrayEnd()
Definition: JSON.cpp:831
llvm::max
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:340
LLVM_LIKELY
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:219
llvm::json::isUTF8
bool isUTF8(llvm::StringRef S, size_t *ErrOffset=nullptr)
Returns true if S is valid UTF-8, which is required for use as JSON.
Definition: JSON.cpp:678
llvm::json::ObjectKey
ObjectKey is a used to capture keys in Object.
Definition: JSON.h:495
LLVM_UNLIKELY
#define LLVM_UNLIKELY(EXPR)
Definition: Compiler.h:220
raw_ostream.h
llvm::json::Object
An Object is a JSON object, which maps strings to heterogenous JSON values.
Definition: JSON.h:90
llvm::json::Value::getAsString
llvm::Optional< llvm::StringRef > getAsString() const
Definition: JSON.h:428
llvm::raw_string_ostream::str
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
Definition: raw_ostream.h:643
llvm::json::OStream::rawValueBegin
raw_ostream & rawValueBegin()
Definition: JSON.cpp:889
llvm::json::Object::getBoolean
llvm::Optional< bool > getBoolean(StringRef K) const
Definition: JSON.cpp:43
llvm::json::OStream::objectBegin
void objectBegin()
Definition: JSON.cpp:842
llvm::json::Path
A "cursor" marking a position within a Value.
Definition: JSON.h:570
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::UTF8
unsigned char UTF8
Definition: ConvertUTF.h:111
llvm::json::Object::getNull
llvm::Optional< std::nullptr_t > getNull(StringRef K) const
Definition: JSON.cpp:38