blob: c200004954a4f32023e56c461e22822efa00cbb3 [file] [log] [blame]
Nick Kledzik8ceb8b72012-12-12 20:46:15 +00001//===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#define BUILDING_YAMLIO
11#include "llvm/Support/YAMLTraits.h"
Nick Kledzik8ceb8b72012-12-12 20:46:15 +000012#include "llvm/ADT/Twine.h"
13#include "llvm/Support/Casting.h"
14#include "llvm/Support/ErrorHandling.h"
Benjamin Kramer11b07f62012-12-12 20:55:44 +000015#include "llvm/Support/Format.h"
Nick Kledzik8ceb8b72012-12-12 20:46:15 +000016#include "llvm/Support/YAMLParser.h"
Benjamin Kramer11b07f62012-12-12 20:55:44 +000017#include "llvm/Support/raw_ostream.h"
Nick Kledzik8ceb8b72012-12-12 20:46:15 +000018#include <cstring>
19
20namespace llvm {
21namespace yaml {
22
23
24
25//===----------------------------------------------------------------------===//
26// IO
27//===----------------------------------------------------------------------===//
28
29IO::IO(void *Context) : Ctxt(Context) {
30}
31
32IO::~IO() {
33}
34
35void *IO::getContext() {
36 return Ctxt;
37}
38
39void IO::setContext(void *Context) {
40 Ctxt = Context;
41}
42
43
44//===----------------------------------------------------------------------===//
45// Input
46//===----------------------------------------------------------------------===//
47
48Input::Input(StringRef InputContent, void *Ctxt)
49 : IO(Ctxt), CurrentNode(NULL) {
50 Strm = new Stream(InputContent, SrcMgr);
51 DocIterator = Strm->begin();
52}
53
54
55llvm::error_code Input::error() {
56 return EC;
57}
58
59void Input::setDiagHandler(llvm::SourceMgr::DiagHandlerTy Handler, void *Ctxt) {
60 SrcMgr.setDiagHandler(Handler, Ctxt);
61}
62
63bool Input::outputting() {
64 return false;
65}
66
67bool Input::setCurrentDocument() {
68 if ( DocIterator != Strm->end() ) {
69 Node *N = DocIterator->getRoot();
70 if (llvm::isa<NullNode>(N)) {
71 // Empty files are allowed and ignored
72 ++DocIterator;
73 return setCurrentDocument();
74 }
75 CurrentNode = this->createHNodes(N);
76 return true;
77 }
78 return false;
79}
80
81void Input::nextDocument() {
82 ++DocIterator;
83}
84
85void Input::beginMapping() {
86 if ( EC )
87 return;
88 MapHNode *MN = llvm::dyn_cast<MapHNode>(CurrentNode);
89 if ( MN ) {
90 MN->ValidKeys.clear();
91 }
92}
93
94bool Input::preflightKey(const char *Key, bool Required, bool,
95 bool &UseDefault, void *&SaveInfo) {
96 UseDefault = false;
97 if ( EC )
98 return false;
99 MapHNode *MN = llvm::dyn_cast<MapHNode>(CurrentNode);
100 if ( !MN ) {
101 setError(CurrentNode, "not a mapping");
102 return false;
103 }
104 MN->ValidKeys.push_back(Key);
105 HNode *Value = MN->Mapping[Key];
106 if ( !Value ) {
107 if ( Required )
108 setError(CurrentNode, Twine("missing required key '") + Key + "'");
109 else
110 UseDefault = true;
111 return false;
112 }
113 SaveInfo = CurrentNode;
114 CurrentNode = Value;
115 return true;
116}
117
118void Input::postflightKey(void *saveInfo) {
119 CurrentNode = reinterpret_cast<HNode*>(saveInfo);
120}
121
122void Input::endMapping() {
123 if ( EC )
124 return;
125 MapHNode *MN = llvm::dyn_cast<MapHNode>(CurrentNode);
126 if ( !MN )
127 return;
128 for (MapHNode::NameToNode::iterator i=MN->Mapping.begin(),
129 End=MN->Mapping.end(); i != End; ++i) {
130 if ( ! MN->isValidKey(i->first) ) {
131 setError(i->second, Twine("unknown key '") + i->first + "'" );
132 break;
133 }
134 }
135}
136
137
138unsigned Input::beginSequence() {
139 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
140 return SQ->Entries.size();
141 }
142 return 0;
143}
144void Input::endSequence() {
145}
146bool Input::preflightElement(unsigned Index, void *&SaveInfo) {
147 if ( EC )
148 return false;
149 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
150 SaveInfo = CurrentNode;
151 CurrentNode = SQ->Entries[Index];
152 return true;
153 }
154 return false;
155}
156void Input::postflightElement(void *SaveInfo) {
157 CurrentNode = reinterpret_cast<HNode*>(SaveInfo);
158}
159
160unsigned Input::beginFlowSequence() {
161 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
162 return SQ->Entries.size();
163 }
164 return 0;
165}
166bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
167 if ( EC )
168 return false;
169 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
170 SaveInfo = CurrentNode;
171 CurrentNode = SQ->Entries[index];
172 return true;
173 }
174 return false;
175}
176void Input::postflightFlowElement(void *SaveInfo) {
177 CurrentNode = reinterpret_cast<HNode*>(SaveInfo);
178}
179void Input::endFlowSequence() {
180}
181
182
183void Input::beginEnumScalar() {
184 ScalarMatchFound = false;
185}
186
187bool Input::matchEnumScalar(const char *Str, bool) {
188 if ( ScalarMatchFound )
189 return false;
190 if ( ScalarHNode *SN = llvm::dyn_cast<ScalarHNode>(CurrentNode) ) {
191 if ( SN->value().equals(Str) ) {
192 ScalarMatchFound = true;
193 return true;
194 }
195 }
196 return false;
197}
198
199void Input::endEnumScalar() {
200 if ( !ScalarMatchFound ) {
201 setError(CurrentNode, "unknown enumerated scalar");
202 }
203}
204
205
206
207bool Input::beginBitSetScalar(bool &DoClear) {
208 BitValuesUsed.clear();
209 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
210 BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false);
211 }
212 else {
213 setError(CurrentNode, "expected sequence of bit values");
214 }
215 DoClear = true;
216 return true;
217}
218
219bool Input::bitSetMatch(const char *Str, bool) {
220 if ( EC )
221 return false;
222 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
223 unsigned Index = 0;
224 for (std::vector<HNode*>::iterator i=SQ->Entries.begin(),
225 End=SQ->Entries.end(); i != End; ++i) {
226 if ( ScalarHNode *SN = llvm::dyn_cast<ScalarHNode>(*i) ) {
227 if ( SN->value().equals(Str) ) {
228 BitValuesUsed[Index] = true;
229 return true;
230 }
231 }
232 else {
233 setError(CurrentNode, "unexpected scalar in sequence of bit values");
234 }
235 ++Index;
236 }
237 }
238 else {
239 setError(CurrentNode, "expected sequence of bit values");
240 }
241 return false;
242}
243
244void Input::endBitSetScalar() {
245 if ( EC )
246 return;
247 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
248 assert(BitValuesUsed.size() == SQ->Entries.size());
249 for ( unsigned i=0; i < SQ->Entries.size(); ++i ) {
250 if ( !BitValuesUsed[i] ) {
251 setError(SQ->Entries[i], "unknown bit value");
252 return;
253 }
254 }
255 }
256}
257
258
259void Input::scalarString(StringRef &S) {
260 if ( ScalarHNode *SN = llvm::dyn_cast<ScalarHNode>(CurrentNode) ) {
261 S = SN->value();
262 }
263 else {
264 setError(CurrentNode, "unexpected scalar");
265 }
266}
267
268void Input::setError(HNode *hnode, const Twine &message) {
269 this->setError(hnode->_node, message);
270}
271
272void Input::setError(Node *node, const Twine &message) {
273 Strm->printError(node, message);
274 EC = make_error_code(errc::invalid_argument);
275}
276
277Input::HNode *Input::createHNodes(Node *N) {
278 llvm::SmallString<128> StringStorage;
279 if ( ScalarNode *SN = llvm::dyn_cast<ScalarNode>(N) ) {
280 StringRef KeyStr = SN->getValue(StringStorage);
281 if ( !StringStorage.empty() ) {
282 // Copy string to permanent storage
283 unsigned Len = StringStorage.size();
284 char* Buf = Allocator.Allocate<char>(Len);
285 memcpy(Buf, &StringStorage[0], Len);
286 KeyStr = StringRef(Buf, Len);
287 }
288 return new (Allocator) ScalarHNode(N, KeyStr);
289 }
290 else if ( SequenceNode *SQ = llvm::dyn_cast<SequenceNode>(N) ) {
291 SequenceHNode *SQHNode = new (Allocator) SequenceHNode(N);
292 for (SequenceNode::iterator i=SQ->begin(),End=SQ->end(); i != End; ++i ) {
293 HNode *Entry = this->createHNodes(i);
294 if ( EC )
295 break;
296 SQHNode->Entries.push_back(Entry);
297 }
298 return SQHNode;
299 }
300 else if ( MappingNode *Map = llvm::dyn_cast<MappingNode>(N) ) {
301 MapHNode *mapHNode = new (Allocator) MapHNode(N);
302 for (MappingNode::iterator i=Map->begin(), End=Map->end(); i != End; ++i ) {
303 ScalarNode *KeyScalar = llvm::dyn_cast<ScalarNode>(i->getKey());
304 StringStorage.clear();
305 llvm::StringRef KeyStr = KeyScalar->getValue(StringStorage);
306 if ( !StringStorage.empty() ) {
307 // Copy string to permanent storage
308 unsigned Len = StringStorage.size();
309 char* Buf = Allocator.Allocate<char>(Len);
310 memcpy(Buf, &StringStorage[0], Len);
311 KeyStr = StringRef(Buf, Len);
312 }
313 HNode *ValueHNode = this->createHNodes(i->getValue());
314 if ( EC )
315 break;
316 mapHNode->Mapping[KeyStr] = ValueHNode;
317 }
318 return mapHNode;
319 }
320 else if ( llvm::isa<NullNode>(N) ) {
321 return new (Allocator) EmptyHNode(N);
322 }
323 else {
324 setError(N, "unknown node kind");
325 return NULL;
326 }
327}
328
329
330bool Input::MapHNode::isValidKey(StringRef Key) {
331 for (SmallVector<const char*, 6>::iterator i=ValidKeys.begin(),
332 End=ValidKeys.end(); i != End; ++i) {
333 if ( Key.equals(*i) )
334 return true;
335 }
336 return false;
337}
338
339void Input::setError(const Twine &Message) {
340 this->setError(CurrentNode, Message);
341}
342
343
344//===----------------------------------------------------------------------===//
345// Output
346//===----------------------------------------------------------------------===//
347
348Output::Output(llvm::raw_ostream &yout, void *context)
349 : IO(context), Out(yout), Column(0), ColumnAtFlowStart(0),
350 NeedBitValueComma(false), NeedFlowSequenceComma(false),
351 EnumerationMatchFound(false), NeedsNewLine(false) {
352}
353
354Output::~Output() {
355}
356
357bool Output::outputting() {
358 return true;
359}
360
361void Output::beginMapping() {
362 StateStack.push_back(inMapFirstKey);
363 NeedsNewLine = true;
364}
365
366void Output::endMapping() {
367 StateStack.pop_back();
368}
369
370
371bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
372 bool &UseDefault, void *&) {
373 UseDefault = false;
374 if ( Required || !SameAsDefault ) {
375 this->newLineCheck();
376 this->paddedKey(Key);
377 return true;
378 }
379 return false;
380}
381
382void Output::postflightKey(void*) {
383 if ( StateStack.back() == inMapFirstKey ) {
384 StateStack.pop_back();
385 StateStack.push_back(inMapOtherKey);
386 }
387}
388
389void Output::beginDocuments() {
390 this->outputUpToEndOfLine("---");
391}
392
393bool Output::preflightDocument(unsigned index) {
394 if ( index > 0 )
395 this->outputUpToEndOfLine("\n---");
396 return true;
397}
398
399void Output::postflightDocument() {
400}
401
402void Output::endDocuments() {
403 output("\n...\n");
404}
405
406unsigned Output::beginSequence() {
407 StateStack.push_back(inSeq);
408 NeedsNewLine = true;
409 return 0;
410}
411void Output::endSequence() {
412 StateStack.pop_back();
413}
414bool Output::preflightElement(unsigned , void *&) {
415 return true;
416}
417void Output::postflightElement(void*) {
418}
419
420unsigned Output::beginFlowSequence() {
421 this->newLineCheck();
422 StateStack.push_back(inFlowSeq);
423 ColumnAtFlowStart = Column;
424 output("[ ");
425 NeedFlowSequenceComma = false;
426 return 0;
427}
428void Output::endFlowSequence() {
429 StateStack.pop_back();
430 this->outputUpToEndOfLine(" ]");
431}
432bool Output::preflightFlowElement(unsigned , void *&) {
433 if ( NeedFlowSequenceComma )
434 output(", ");
435 if ( Column > 70 ) {
436 output("\n");
437 for(int i=0; i < ColumnAtFlowStart; ++i)
438 output(" ");
439 Column = ColumnAtFlowStart;
440 output(" ");
441 }
442 return true;
443}
444void Output::postflightFlowElement(void*) {
445 NeedFlowSequenceComma = true;
446}
447
448
449
450void Output::beginEnumScalar() {
451 EnumerationMatchFound = false;
452}
453
454bool Output::matchEnumScalar(const char *Str, bool Match) {
455 if ( Match && !EnumerationMatchFound ) {
456 this->newLineCheck();
457 this->outputUpToEndOfLine(Str);
458 EnumerationMatchFound = true;
459 }
460 return false;
461}
462
463void Output::endEnumScalar() {
464 if ( !EnumerationMatchFound )
465 llvm_unreachable("bad runtime enum value");
466}
467
468
469
470bool Output::beginBitSetScalar(bool &DoClear) {
471 this->newLineCheck();
472 output("[ ");
473 NeedBitValueComma = false;
474 DoClear = false;
475 return true;
476}
477
478bool Output::bitSetMatch(const char *Str, bool Matches) {
479 if ( Matches ) {
480 if ( NeedBitValueComma )
481 output(", ");
482 this->output(Str);
483 NeedBitValueComma = true;
484 }
485 return false;
486}
487
488void Output::endBitSetScalar() {
489 this->outputUpToEndOfLine(" ]");
490}
491
492void Output::scalarString(StringRef &S) {
493 this->newLineCheck();
494 if (S.find('\n') == StringRef::npos) {
495 // No embedded new-line chars, just print string.
496 this->outputUpToEndOfLine(S);
497 return;
498 }
499 unsigned i = 0;
500 unsigned j = 0;
501 unsigned End = S.size();
502 output("'"); // Starting single quote.
503 const char *Base = S.data();
504 while (j < End) {
505 // Escape a single quote by doubling it.
506 if (S[j] == '\'') {
507 output(StringRef(&Base[i], j - i + 1));
508 output("'");
509 i = j + 1;
510 }
511 ++j;
512 }
513 output(StringRef(&Base[i], j - i));
514 this->outputUpToEndOfLine("'"); // Ending single quote.
515}
516
517void Output::setError(const Twine &message) {
518}
519
520
521void Output::output(StringRef s) {
522 Column += s.size();
523 Out << s;
524}
525
526void Output::outputUpToEndOfLine(StringRef s) {
527 this->output(s);
528 if ( StateStack.back() != inFlowSeq )
529 NeedsNewLine = true;
530}
531
532void Output::outputNewLine() {
533 Out << "\n";
534 Column = 0;
535}
536
537// if seq at top, indent as if map, then add "- "
538// if seq in middle, use "- " if firstKey, else use " "
539//
540
541void Output::newLineCheck() {
542 if ( ! NeedsNewLine )
543 return;
544 NeedsNewLine = false;
545
546 this->outputNewLine();
547
548 assert(StateStack.size() > 0);
549 unsigned Indent = StateStack.size() - 1;
550 bool OutputDash = false;
551
552 if ( StateStack.back() == inSeq ) {
553 OutputDash = true;
554 }
555 else if ( (StateStack.size() > 1)
556 && (StateStack.back() == inMapFirstKey)
557 && (StateStack[StateStack.size()-2] == inSeq) ) {
558 --Indent;
559 OutputDash = true;
560 }
561
562 for (unsigned i=0; i < Indent; ++i) {
563 output(" ");
564 }
565 if ( OutputDash ) {
566 output("- ");
567 }
568
569}
570
571void Output::paddedKey(StringRef key) {
572 output(key);
573 output(":");
574 const char *spaces = " ";
575 if ( key.size() < strlen(spaces) )
576 output(&spaces[key.size()]);
577 else
578 output(" ");
579}
580
581//===----------------------------------------------------------------------===//
582// traits for built-in types
583//===----------------------------------------------------------------------===//
584
585template<>
586struct ScalarTraits<bool> {
587 static void output(const bool &Val, void*, llvm::raw_ostream &Out) {
588 Out << ( Val ? "true" : "false");
589 }
590 static llvm::StringRef input(llvm::StringRef Scalar, void*, bool &Val) {
591 if ( Scalar.equals("true") ) {
592 Val = true;
593 return StringRef();
594 }
595 else if ( Scalar.equals("false") ) {
596 Val = false;
597 return StringRef();
598 }
599 return "invalid boolean";
600 }
601};
602
603
604template<>
605struct ScalarTraits<StringRef> {
606 static void output(const StringRef &Val, void*, llvm::raw_ostream &Out) {
607 Out << Val;
608 }
609 static llvm::StringRef input(llvm::StringRef Scalar, void*, StringRef &Val){
610 Val = Scalar;
611 return StringRef();
612 }
613};
614
615
616template<>
617struct ScalarTraits<uint8_t> {
618 static void output(const uint8_t &Val, void*, llvm::raw_ostream &Out) {
619 // use temp uin32_t because ostream thinks uint8_t is a character
620 uint32_t Num = Val;
621 Out << Num;
622 }
623 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint8_t &Val) {
624 uint64_t n;
625 if ( getAsUnsignedInteger(Scalar, 0, n) )
626 return "invalid number";
627 if ( n > 0xFF )
628 return "out of range number";
629 Val = n;
630 return StringRef();
631 }
632};
633
634
635template<>
636struct ScalarTraits<uint16_t> {
637 static void output(const uint16_t &Val, void*, llvm::raw_ostream &Out) {
638 Out << Val;
639 }
640 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint16_t &Val) {
641 uint64_t n;
642 if ( getAsUnsignedInteger(Scalar, 0, n) )
643 return "invalid number";
644 if ( n > 0xFFFF )
645 return "out of range number";
646 Val = n;
647 return StringRef();
648 }
649};
650
651template<>
652struct ScalarTraits<uint32_t> {
653 static void output(const uint32_t &Val, void*, llvm::raw_ostream &Out) {
654 Out << Val;
655 }
656 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint32_t &Val) {
657 uint64_t n;
658 if ( getAsUnsignedInteger(Scalar, 0, n) )
659 return "invalid number";
660 if ( n > 0xFFFFFFFFUL )
661 return "out of range number";
662 Val = n;
663 return StringRef();
664 }
665};
666
667
668template<>
669struct ScalarTraits<uint64_t> {
670 static void output(const uint64_t &Val, void*, llvm::raw_ostream &Out) {
671 Out << Val;
672 }
673 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint64_t &Val) {
674 if ( getAsUnsignedInteger(Scalar, 0, Val) )
675 return "invalid number";
676 return StringRef();
677 }
678};
679
680
681template<>
682struct ScalarTraits<int8_t> {
683 static void output(const int8_t &Val, void*, llvm::raw_ostream &Out) {
684 // use temp in32_t because ostream thinks int8_t is a character
685 int32_t Num = Val;
686 Out << Num;
687 }
688 static llvm::StringRef input(llvm::StringRef Scalar, void*, int8_t &Val) {
689 int64_t n;
690 if ( getAsSignedInteger(Scalar, 0, n) )
691 return "invalid number";
692 if ( (n > 127) || (n < -128) )
693 return "out of range number";
694 Val = n;
695 return StringRef();
696 }
697};
698
699
700template<>
701struct ScalarTraits<int16_t> {
702 static void output(const int16_t &Val, void*, llvm::raw_ostream &Out) {
703 Out << Val;
704 }
705 static llvm::StringRef input(llvm::StringRef Scalar, void*, int16_t &Val) {
706 int64_t n;
707 if ( getAsSignedInteger(Scalar, 0, n) )
708 return "invalid number";
709 if ( (n > INT16_MAX) || (n < INT16_MIN) )
710 return "out of range number";
711 Val = n;
712 return StringRef();
713 }
714};
715
716
717template<>
718struct ScalarTraits<int32_t> {
719 static void output(const int32_t &Val, void*, llvm::raw_ostream &Out) {
720 Out << Val;
721 }
722 static llvm::StringRef input(llvm::StringRef Scalar, void*, int32_t &Val) {
723 int64_t n;
724 if ( getAsSignedInteger(Scalar, 0, n) )
725 return "invalid number";
726 if ( (n > INT32_MAX) || (n < INT32_MIN) )
727 return "out of range number";
728 Val = n;
729 return StringRef();
730 }
731};
732
733template<>
734struct ScalarTraits<int64_t> {
735 static void output(const int64_t &Val, void*, llvm::raw_ostream &Out) {
736 Out << Val;
737 }
738 static llvm::StringRef input(llvm::StringRef Scalar, void*, int64_t &Val) {
739 if ( getAsSignedInteger(Scalar, 0, Val) )
740 return "invalid number";
741 return StringRef();
742 }
743};
744
745template<>
746struct ScalarTraits<double> {
747 static void output(const double &Val, void*, llvm::raw_ostream &Out) {
748 Out << format("%g", Val);
749 }
750 static llvm::StringRef input(llvm::StringRef Scalar, void*, double &Val) {
751 SmallString<32> buff(Scalar.begin(), Scalar.end());
752 char *end;
753 Val = strtod(buff.c_str(), &end);
754 if ( *end != '\0' )
755 return "invalid floating point number";
756 return StringRef();
757 }
758};
759
760template<>
761struct ScalarTraits<float> {
762 static void output(const float &Val, void*, llvm::raw_ostream &Out) {
763 Out << format("%g", Val);
764 }
765 static llvm::StringRef input(llvm::StringRef Scalar, void*, float &Val) {
766 SmallString<32> buff(Scalar.begin(), Scalar.end());
767 char *end;
768 Val = strtod(buff.c_str(), &end);
769 if ( *end != '\0' )
770 return "invalid floating point number";
771 return StringRef();
772 }
773};
774
775
776
777template<>
778struct ScalarTraits<Hex8> {
779 static void output(const Hex8 &Val, void*, llvm::raw_ostream &Out) {
780 uint8_t Num = Val;
781 Out << format("0x%02X", Num);
782 }
783 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex8 &Val) {
784 uint64_t n;
785 if ( getAsUnsignedInteger(Scalar, 0, n) )
786 return "invalid hex8 number";
787 if ( n > 0xFF )
788 return "out of range hex8 number";
789 Val = n;
790 return StringRef();
791 }
792};
793
794
795template<>
796struct ScalarTraits<Hex16> {
797 static void output(const Hex16 &Val, void*, llvm::raw_ostream &Out) {
798 uint16_t Num = Val;
799 Out << format("0x%04X", Num);
800 }
801 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex16 &Val) {
802 uint64_t n;
803 if ( getAsUnsignedInteger(Scalar, 0, n) )
804 return "invalid hex16 number";
805 if ( n > 0xFFFF )
806 return "out of range hex16 number";
807 Val = n;
808 return StringRef();
809 }
810};
811
812template<>
813struct ScalarTraits<Hex32> {
814 static void output(const Hex32 &Val, void*, llvm::raw_ostream &Out) {
815 uint32_t Num = Val;
816 Out << format("0x%08X", Num);
817 }
818 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex32 &Val) {
819 uint64_t n;
820 if ( getAsUnsignedInteger(Scalar, 0, n) )
821 return "invalid hex32 number";
822 if ( n > 0xFFFFFFFFUL )
823 return "out of range hex32 number";
824 Val = n;
825 return StringRef();
826 }
827};
828
829
830template<>
831struct ScalarTraits<Hex64> {
832 static void output(const Hex64 &Val, void*, llvm::raw_ostream &Out) {
833 uint64_t Num = Val;
834 Out << format("0x%016llX", Num);
835 }
836 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex64 &Val) {
837 uint64_t Num;
838 if ( getAsUnsignedInteger(Scalar, 0, Num) )
839 return "invalid hex64 number";
840 Val = Num;
841 return StringRef();
842 }
843};
844
845
846
847
848// We want all the ScalarTrait specialized on built-in types
849// to be instantiated here.
850template <typename T>
851struct ForceUse {
852 ForceUse() : oproc(ScalarTraits<T>::output), iproc(ScalarTraits<T>::input) {}
853 void (*oproc)(const T &, void*, llvm::raw_ostream &);
854 llvm::StringRef (*iproc)(llvm::StringRef, void*, T &);
855};
856
857static ForceUse<bool> Dummy1;
858static ForceUse<llvm::StringRef> Dummy2;
859static ForceUse<uint8_t> Dummy3;
860static ForceUse<uint16_t> Dummy4;
861static ForceUse<uint32_t> Dummy5;
862static ForceUse<uint64_t> Dummy6;
863static ForceUse<int8_t> Dummy7;
864static ForceUse<int16_t> Dummy8;
865static ForceUse<int32_t> Dummy9;
866static ForceUse<int64_t> Dummy10;
867static ForceUse<float> Dummy11;
868static ForceUse<double> Dummy12;
869static ForceUse<Hex8> Dummy13;
870static ForceUse<Hex16> Dummy14;
871static ForceUse<Hex32> Dummy15;
872static ForceUse<Hex64> Dummy16;
873
874
875
876} // namespace yaml
877} // namespace llvm
878
879