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