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