Support more Atom attributes.  Add more test cases to lld-core

llvm-svn: 147571
diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/Core/YamlReader.cpp
index c35664e..7930d64 100644
--- a/lld/lib/Core/YamlReader.cpp
+++ b/lld/lib/Core/YamlReader.cpp
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "YamlKeyValues.h"
+
 #include "lld/Core/YamlReader.h"
 #include "lld/Core/Atom.h"
 #include "lld/Core/File.h"
@@ -21,10 +23,46 @@
 
 #include <vector>
 
-namespace { const llvm::error_code success; }
+
 
 namespace lld {
 namespace yaml {
+
+enum yaml_reader_errors {
+  success = 0,
+  unknown_keyword,
+  illegal_value
+};
+
+class reader_error_category : public llvm::_do_message {
+public:
+  virtual const char* name() const {
+    return "lld.yaml.reader";
+  }
+  virtual std::string message(int ev) const;
+};
+
+const reader_error_category reader_error_category_singleton;
+
+std::string reader_error_category::message(int ev) const {
+  switch (ev) {
+  case success: 
+    return "Success";
+  case unknown_keyword:
+    return "Unknown keyword found in yaml file";
+  case illegal_value: 
+    return "Bad value found in yaml file";
+  default:
+    llvm_unreachable("An enumerator of yaml_reader_errors does not have a "
+                     "message defined.");
+  }
+}
+
+inline llvm::error_code make_error_code(yaml_reader_errors e) {
+  return llvm::error_code(static_cast<int>(e), reader_error_category_singleton);
+}
+
+
 class YAML {
 public:
   struct Entry {
@@ -137,6 +175,7 @@
         state = inTriplePeriod;
       } else if (c == '\n') {
         // ignore empty lines
+        depth = 0;
       } else if (c == '\t') {
         llvm::report_fatal_error("TAB character found in yaml file");
       } else {
@@ -176,6 +215,8 @@
         state = inValueSequence;
       } else if (c == ' ') {
         // eat space
+      } else if (c == '\t') {
+        llvm::report_fatal_error("TAB character found in yaml file");
       } else {
         return;
       }
@@ -247,16 +288,20 @@
           , SectionChoice sc
           , bool intn
           , bool md
+          , bool ah
           , DeadStripKind dsk
           , bool tb
           , bool al
           , Alignment a
           , YAMLFile& f
-          , const char *n)
-    : Atom(ord, d, s, ct, sc, intn, md, dsk, tb, al, a)
+          , const char *n
+          , const char* sn
+          , uint64_t sz)
+    : Atom(ord, d, s, ct, sc, intn, md, ah, dsk, tb, al, a)
     , _file(f)
     , _name(n)
-    , _size(0)
+    , _sectionName(sn)
+    , _size(sz)
     , _refStartIndex(f._lastRefIndex)
     , _refEndIndex(f._references.size()) {
     f._lastRefIndex = _refEndIndex;
@@ -273,6 +318,10 @@
   virtual llvm::StringRef name() const {
     return _name;
   }
+  
+  virtual llvm::StringRef customSectionName() const {
+    return _sectionName;
+  }
 
   virtual uint64_t objectAddress() const {
     return 0;
@@ -286,11 +335,12 @@
   virtual Reference::iterator referencesBegin() const;
   virtual Reference::iterator referencesEnd() const;
 private:
-  YAMLFile& _file;
-  const char *_name;
-  unsigned long _size;
-  unsigned int _refStartIndex;
-  unsigned int _refEndIndex;
+  YAMLFile&      _file;
+  const char *   _name;
+  const char *   _sectionName;
+  unsigned long  _size;
+  unsigned int   _refStartIndex;
+  unsigned int   _refEndIndex;
 };
 
 Reference::iterator YAMLAtom::referencesBegin() const {
@@ -310,11 +360,7 @@
   YAMLAtomState();
 
   void setName(const char *n);
-  void setScope(const char *n);
-  void setType(const char *n);
   void setAlign2(const char *n);
-  void setDefinition(const char *n);
-  void setMergeDuplicates(const char *n);
 
   void setFixupKind(const char *n);
   void setFixupOffset(const char *n);
@@ -323,8 +369,8 @@
 
   void makeAtom(YAMLFile&);
 
-private:
   uint64_t  _ordinal;
+  long long _size;
   const char *_name;
   Atom::Alignment _align;
   Atom::ContentType _type;
@@ -333,23 +379,29 @@
   Atom::SectionChoice _sectionChoice;
   bool _internalName;
   bool _mergeDuplicates;
-  Atom::DeadStripKind _dontDeadStrip;
+  Atom::DeadStripKind _deadStrip;
   bool _thumb;
   bool _alias;
+  bool _autoHide;
+  const char *_sectionName;
   Reference _ref;
 };
 
 YAMLAtomState::YAMLAtomState()
   : _ordinal(0)
+  , _size(0)
   , _name(NULL)
   , _align(0, 0)
-  , _type(Atom::typeData)
-  , _scope(Atom::scopeGlobal)
-  , _internalName(false)
-  , _mergeDuplicates(false)
-  , _dontDeadStrip(Atom::deadStripNormal)
-  , _thumb(false)
-  , _alias(false) {
+  , _type(KeyValues::contentTypeDefault)
+  , _scope(KeyValues::scopeDefault)
+  , _def(KeyValues::definitionDefault)
+  , _internalName(KeyValues::internalNameDefault)
+  , _mergeDuplicates(KeyValues::mergeDuplicatesDefault)
+  , _deadStrip(KeyValues::deadStripKindDefault)
+  , _thumb(KeyValues::isThumbDefault)
+  , _alias(KeyValues::isAliasDefault) 
+  , _autoHide(KeyValues::autoHideDefault)
+  , _sectionName(NULL) {
   _ref.target       = NULL;
   _ref.addend       = 0;
   _ref.offsetInAtom = 0;
@@ -359,8 +411,9 @@
 
 void YAMLAtomState::makeAtom(YAMLFile& f) {
   Atom *a = new YAMLAtom(_ordinal, _def, _scope, _type, _sectionChoice,
-                         _internalName, _mergeDuplicates, _dontDeadStrip, 
-                         _thumb, _alias, _align, f, _name);
+                         _internalName, _mergeDuplicates, _autoHide,  
+                         _deadStrip, _thumb, _alias, _align, f, 
+                         _name, _sectionName, _size);
 
   f._atoms.push_back(a);
   ++_ordinal;
@@ -369,15 +422,17 @@
   _name             = NULL;
   _align.powerOf2   = 0;
   _align.modulus    = 0;
-  _type             = Atom::typeData;
-  _scope            = Atom::scopeGlobal;
-  _def              = Atom::definitionRegular;
-  _sectionChoice    = Atom::sectionBasedOnContent;
-  _internalName     = false;
-  _mergeDuplicates  = false;
-  _dontDeadStrip    = Atom::deadStripNormal;
-  _thumb            = false;
-  _alias            = false;
+  _type             = KeyValues::contentTypeDefault;
+  _scope            = KeyValues::scopeDefault;
+  _def              = KeyValues::definitionDefault;
+  _sectionChoice    = KeyValues::sectionChoiceDefault;
+  _internalName     = KeyValues::internalNameDefault;
+  _mergeDuplicates  = KeyValues::mergeDuplicatesDefault;
+  _deadStrip        = KeyValues::deadStripKindDefault;
+  _thumb            = KeyValues::isThumbDefault;
+  _alias            = KeyValues::isAliasDefault;
+  _autoHide         = KeyValues::autoHideDefault;
+  _sectionName      = NULL;
   _ref.target       = NULL;
   _ref.addend       = 0;
   _ref.offsetInAtom = 0;
@@ -389,29 +444,6 @@
   _name = n;
 }
 
-void YAMLAtomState::setScope(const char *s) {
-  if (strcmp(s, "global") == 0)
-    _scope = Atom::scopeGlobal;
-  else if (strcmp(s, "hidden") == 0)
-    _scope = Atom::scopeLinkageUnit;
-  else if (strcmp(s, "static") == 0)
-    _scope = Atom::scopeTranslationUnit;
-  else
-    llvm::report_fatal_error("bad scope value");
-}
-
-void YAMLAtomState::setType(const char *s) {
-  if (strcmp(s, "code") == 0)
-    _type = Atom::typeCode;
-  else if (strcmp(s, "c-string") == 0)
-    _type = Atom::typeCString;
-  else if (strcmp(s, "zero-fill") == 0)
-    _type = Atom::typeZeroFill;
-  else if (strcmp(s, "data") == 0)
-    _type = Atom::typeData;
-  else
-    llvm::report_fatal_error("bad type value");
-}
 
 void YAMLAtomState::setAlign2(const char *s) {
   llvm::StringRef str(s);
@@ -420,27 +452,6 @@
   _align.powerOf2 = static_cast<uint16_t>(res);
 }
 
-void YAMLAtomState::setDefinition(const char *s) {
-  if (strcmp(s, "regular") == 0)
-    _def = Atom::definitionRegular;
-  else if (strcmp(s, "tentative") == 0)
-    _def = Atom::definitionTentative;
-  else if (strcmp(s, "weak") == 0)
-    _def = Atom::definitionWeak;
-  else if (strcmp(s, "absolute") == 0)
-    _def = Atom::definitionAbsolute;
-  else
-    llvm::report_fatal_error("bad definition value");
-}
-
-void YAMLAtomState::setMergeDuplicates(const char *s) {
-  if (strcmp(s, "true") == 0)
-    _mergeDuplicates = true;
-  else if (strcmp(s, "false") == 0)
-    _mergeDuplicates = false;
-  else
-    llvm::report_fatal_error("bad merge-duplicates value");
-}
 
 void YAMLAtomState::setFixupKind(const char *s) {
   if (strcmp(s, "pcrel32") == 0)
@@ -527,28 +538,76 @@
             haveAtom = false;
           }
         }
-        if (strcmp(entry->key, "name") == 0) {
+        if (strcmp(entry->key, KeyValues::nameKeyword) == 0) {
           atomState.setName(entry->value);
           haveAtom = true;
-        } else if (strcmp(entry->key, "scope") == 0) {
-          atomState.setScope(entry->value);
+        } 
+        else if (strcmp(entry->key, KeyValues::internalNameKeyword) == 0) {
+          atomState._internalName = KeyValues::internalName(entry->value);
           haveAtom = true;
-        } else if (strcmp(entry->key, "type") == 0) {
-          atomState.setType(entry->value);
+        }
+        else if (strcmp(entry->key, KeyValues::definitionKeyword) == 0) {
+          atomState._def = KeyValues::definition(entry->value);
           haveAtom = true;
-        } else if (strcmp(entry->key, "align2") == 0) {
+        } 
+        else if (strcmp(entry->key, KeyValues::scopeKeyword) == 0) {
+          atomState._scope = KeyValues::scope(entry->value);
+          haveAtom = true;
+        }
+        else if (strcmp(entry->key, KeyValues::contentTypeKeyword) == 0) {
+          atomState._type = KeyValues::contentType(entry->value);
+          haveAtom = true;
+        }
+        else if (strcmp(entry->key, KeyValues::deadStripKindKeyword) == 0) {
+          atomState._deadStrip = KeyValues::deadStripKind(entry->value);
+          haveAtom = true;
+        }
+        else if (strcmp(entry->key, KeyValues::sectionChoiceKeyword) == 0) {
+          atomState._sectionChoice = KeyValues::sectionChoice(entry->value);
+          haveAtom = true;
+        }
+        else if (strcmp(entry->key, KeyValues::mergeDuplicatesKeyword) == 0) {
+          atomState._mergeDuplicates = KeyValues::mergeDuplicates(entry->value);
+          haveAtom = true;
+        }
+        else if (strcmp(entry->key, KeyValues::autoHideKeyword) == 0) {
+          atomState._autoHide = KeyValues::autoHide(entry->value);
+          haveAtom = true;
+        }
+        else if (strcmp(entry->key, KeyValues::isThumbKeyword) == 0) {
+          atomState._thumb = KeyValues::isThumb(entry->value);
+          haveAtom = true;
+        }
+        else if (strcmp(entry->key, KeyValues::isAliasKeyword) == 0) {
+          atomState._alias = KeyValues::isAlias(entry->value);
+          haveAtom = true;
+        }
+        else if (strcmp(entry->key, KeyValues::sectionNameKeyword) == 0) {
+          atomState._sectionName = entry->value;
+          haveAtom = true;
+        } 
+        else if (strcmp(entry->key, KeyValues::sizeKeyword) == 0) {
+          llvm::StringRef val = entry->value;
+          if ( val.getAsInteger(0, atomState._size) ) 
+            return make_error_code(illegal_value);
+          haveAtom = true;
+        } 
+        else if (strcmp(entry->key, KeyValues::contentKeyword) == 0) {
+          // TO DO: switch to content mode
+          haveAtom = true;
+        } 
+        else if (strcmp(entry->key, "align2") == 0) {
           atomState.setAlign2(entry->value);
           haveAtom = true;
-        } else if (strcmp(entry->key, "definition") == 0) {
-          atomState.setDefinition(entry->value);
-          haveAtom = true;
-        } else if (strcmp(entry->key, "merge-duplicates") == 0) {
-          atomState.setMergeDuplicates(entry->value);
-          haveAtom = true;
-        } else if (strcmp(entry->key, "fixups") == 0) {
+        } 
+        else if (strcmp(entry->key, "fixups") == 0) {
           inFixups = true;
         }
-      } else if (depthForFixups == entry->depth) {
+        else {
+          return make_error_code(unknown_keyword);
+        }
+      } 
+      else if (depthForFixups == entry->depth) {
         if (entry->beginSequence) {
           if (haveFixup) {
             atomState.addFixup(file);
@@ -574,7 +633,7 @@
   }
 
   result.push_back(file);
-  return success;
+  return make_error_code(success);
 }
 
 //