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