Initial implementation of a utility for converting native data
[oota-llvm.git] / lib / Support / YAMLTraits.cpp
1 //===- 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
22 namespace llvm {
23 namespace yaml {
24
25
26
27 //===----------------------------------------------------------------------===//
28 //  IO
29 //===----------------------------------------------------------------------===//
30
31 IO::IO(void *Context) : Ctxt(Context) {
32 }
33
34 IO::~IO() {
35 }
36
37 void *IO::getContext() {
38   return Ctxt;
39 }
40
41 void IO::setContext(void *Context) {
42   Ctxt = Context;
43 }
44
45
46 //===----------------------------------------------------------------------===//
47 //  Input
48 //===----------------------------------------------------------------------===//
49
50 Input::Input(StringRef InputContent, void *Ctxt)
51     : IO(Ctxt), CurrentNode(NULL) {
52   Strm = new Stream(InputContent, SrcMgr);
53   DocIterator = Strm->begin();
54 }
55
56
57 llvm::error_code Input::error() {
58   return EC;
59 }
60
61 void Input::setDiagHandler(llvm::SourceMgr::DiagHandlerTy Handler, void *Ctxt) {
62   SrcMgr.setDiagHandler(Handler, Ctxt);
63 }
64
65 bool Input::outputting() {
66   return false;
67 }
68
69 bool 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
83 void Input::nextDocument() {
84   ++DocIterator;
85 }
86
87 void 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
96 bool 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
120 void Input::postflightKey(void *saveInfo) {
121   CurrentNode = reinterpret_cast<HNode*>(saveInfo);
122 }
123
124 void 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
140 unsigned Input::beginSequence() {
141   if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
142     return SQ->Entries.size();
143   }
144   return 0;
145 }
146 void Input::endSequence() {
147 }
148 bool 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 }
158 void Input::postflightElement(void *SaveInfo) {
159   CurrentNode = reinterpret_cast<HNode*>(SaveInfo);
160 }
161
162 unsigned Input::beginFlowSequence() {
163    if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
164     return SQ->Entries.size();
165   }
166   return 0;
167 }
168 bool 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 }
178 void Input::postflightFlowElement(void *SaveInfo) {
179   CurrentNode = reinterpret_cast<HNode*>(SaveInfo);
180 }
181 void Input::endFlowSequence() {
182 }
183
184
185 void Input::beginEnumScalar() {
186   ScalarMatchFound = false;
187 }
188
189 bool 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
201 void Input::endEnumScalar() {
202   if ( !ScalarMatchFound ) {
203     setError(CurrentNode, "unknown enumerated scalar");
204   }
205 }
206
207
208
209 bool 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
221 bool 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
246 void 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
261 void 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
270 void Input::setError(HNode *hnode, const Twine &message) {
271   this->setError(hnode->_node, message);
272 }
273
274 void Input::setError(Node *node, const Twine &message) {
275   Strm->printError(node, message);
276   EC = make_error_code(errc::invalid_argument);
277 }
278
279 Input::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
332 bool 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
341 void Input::setError(const Twine &Message) {
342   this->setError(CurrentNode, Message);
343 }
344
345
346 //===----------------------------------------------------------------------===//
347 //  Output
348 //===----------------------------------------------------------------------===//
349
350 Output::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
356 Output::~Output() {
357 }
358
359 bool Output::outputting() {
360   return true;
361 }
362
363 void Output::beginMapping() {
364   StateStack.push_back(inMapFirstKey);
365   NeedsNewLine = true;
366 }
367
368 void Output::endMapping() {
369   StateStack.pop_back();
370 }
371
372
373 bool 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
384 void Output::postflightKey(void*) {
385   if ( StateStack.back() == inMapFirstKey ) {
386     StateStack.pop_back();
387     StateStack.push_back(inMapOtherKey);
388   }
389 }
390
391 void Output::beginDocuments() {
392   this->outputUpToEndOfLine("---");
393 }
394
395 bool Output::preflightDocument(unsigned index) {
396   if ( index > 0 )
397     this->outputUpToEndOfLine("\n---");
398   return true;
399 }
400
401 void Output::postflightDocument() {
402 }
403
404 void Output::endDocuments() {
405   output("\n...\n");
406 }
407
408 unsigned Output::beginSequence() {
409   StateStack.push_back(inSeq);
410   NeedsNewLine = true;
411   return 0;
412 }
413 void Output::endSequence() {
414   StateStack.pop_back();
415 }
416 bool Output::preflightElement(unsigned , void *&) {
417   return true;
418 }
419 void Output::postflightElement(void*) {
420 }
421
422 unsigned Output::beginFlowSequence() {
423   this->newLineCheck();
424   StateStack.push_back(inFlowSeq);
425   ColumnAtFlowStart = Column;
426   output("[ ");
427   NeedFlowSequenceComma = false;
428   return 0;
429 }
430 void Output::endFlowSequence() {
431   StateStack.pop_back();
432   this->outputUpToEndOfLine(" ]");
433 }
434 bool 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 }
446 void Output::postflightFlowElement(void*) {
447   NeedFlowSequenceComma = true;
448 }
449
450
451
452 void Output::beginEnumScalar() {
453   EnumerationMatchFound = false;
454 }
455
456 bool 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
465 void Output::endEnumScalar() {
466   if ( !EnumerationMatchFound )
467     llvm_unreachable("bad runtime enum value");
468 }
469
470
471
472 bool Output::beginBitSetScalar(bool &DoClear) {
473   this->newLineCheck();
474   output("[ ");
475   NeedBitValueComma = false;
476   DoClear = false;
477   return true;
478 }
479
480 bool 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
490 void Output::endBitSetScalar() {
491   this->outputUpToEndOfLine(" ]");
492 }
493
494 void 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
519 void Output::setError(const Twine &message) {
520 }
521
522
523 void Output::output(StringRef s) {
524   Column += s.size();
525   Out << s;
526 }
527
528 void Output::outputUpToEndOfLine(StringRef s) {
529   this->output(s);
530   if ( StateStack.back() != inFlowSeq )
531     NeedsNewLine = true;
532 }
533
534 void 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
543 void 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
573 void 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
587 template<>
588 struct 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
606 template<>
607 struct 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
618 template<>
619 struct 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
637 template<>
638 struct 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
653 template<>
654 struct 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
670 template<>
671 struct 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
683 template<>
684 struct 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
702 template<>
703 struct 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
719 template<>
720 struct 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
735 template<>
736 struct 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
747 template<>
748 struct 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
762 template<>
763 struct 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
779 template<>
780 struct 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
797 template<>
798 struct 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
814 template<>
815 struct 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
832 template<>
833 struct 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.
852 template <typename T>
853 struct 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
859 static ForceUse<bool>            Dummy1;
860 static ForceUse<llvm::StringRef> Dummy2;
861 static ForceUse<uint8_t>         Dummy3;
862 static ForceUse<uint16_t>        Dummy4;
863 static ForceUse<uint32_t>        Dummy5;
864 static ForceUse<uint64_t>        Dummy6;
865 static ForceUse<int8_t>          Dummy7;
866 static ForceUse<int16_t>         Dummy8;
867 static ForceUse<int32_t>         Dummy9;
868 static ForceUse<int64_t>         Dummy10;
869 static ForceUse<float>           Dummy11;
870 static ForceUse<double>          Dummy12;
871 static ForceUse<Hex8>            Dummy13;
872 static ForceUse<Hex16>           Dummy14;
873 static ForceUse<Hex32>           Dummy15;
874 static ForceUse<Hex64>           Dummy16;
875
876
877
878 } // namespace yaml
879 } // namespace llvm
880
881