[llvm-commits] [lld] r156136 - in /lld/trunk: lib/Core/InputFiles.cpp lib/Core/YamlKeyValues.cpp lib/Core/YamlKeyValues.h lib/Core/YamlReader.cpp lib/Core/YamlWriter.cpp test/archive-tentdef-search.objtxt test/error-atom-attribute.objtxt test/error-atom-content-byte-value.objtxt test/error-atom-content-bytes.objtxt test/error-atom-type.objtxt test/error-atom-undefined-wrong-attribue.objtxt test/error-file-attribute.objtxt test/error-fixup-attribute.objtxt test/error-fixup-target.objtxt

Nick Kledzik kledzik at apple.com
Thu May 3 16:55:35 PDT 2012


Author: kledzik
Date: Thu May  3 18:55:34 2012
New Revision: 156136

URL: http://llvm.org/viewvc/llvm-project?rev=156136&view=rev
Log:
Rework how YAMLReader is layered on top of YAMLParser.  Turn hand written
recursive descent functions into one table driven parser.  Add proper
error recovery and reporting.  Add lots of test cases with semantics errors
and verify error messages.



Added:
    lld/trunk/test/error-atom-attribute.objtxt
    lld/trunk/test/error-atom-content-byte-value.objtxt
    lld/trunk/test/error-atom-content-bytes.objtxt
    lld/trunk/test/error-atom-type.objtxt
    lld/trunk/test/error-atom-undefined-wrong-attribue.objtxt
    lld/trunk/test/error-file-attribute.objtxt
    lld/trunk/test/error-fixup-attribute.objtxt
    lld/trunk/test/error-fixup-target.objtxt
Modified:
    lld/trunk/lib/Core/InputFiles.cpp
    lld/trunk/lib/Core/YamlKeyValues.cpp
    lld/trunk/lib/Core/YamlKeyValues.h
    lld/trunk/lib/Core/YamlReader.cpp
    lld/trunk/lib/Core/YamlWriter.cpp
    lld/trunk/test/archive-tentdef-search.objtxt

Modified: lld/trunk/lib/Core/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputFiles.cpp?rev=156136&r1=156135&r2=156136&view=diff
==============================================================================
--- lld/trunk/lib/Core/InputFiles.cpp (original)
+++ lld/trunk/lib/Core/InputFiles.cpp Thu May  3 18:55:34 2012
@@ -1,4 +1,4 @@
-//===- Core/InputFiles.cpp - Manages list of Files -----------------------===//
+//===- Core/InputFiles.cpp - Manages list of Files ------------------------===//
 //
 //                             The LLVM Linker
 //

Modified: lld/trunk/lib/Core/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=156136&r1=156135&r2=156136&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)
+++ lld/trunk/lib/Core/YamlKeyValues.cpp Thu May  3 18:55:34 2012
@@ -18,35 +18,6 @@
 namespace yaml {
 
 
-const char* const KeyValues::nameKeyword            = "name";
-const char* const KeyValues::refNameKeyword         = "ref-name";
-const char* const KeyValues::definitionKeyword      = "definition";
-const char* const KeyValues::scopeKeyword           = "scope";
-const char* const KeyValues::contentTypeKeyword     = "type";
-const char* const KeyValues::deadStripKindKeyword   = "dead-strip";
-const char* const KeyValues::sectionChoiceKeyword   = "section-choice";
-const char* const KeyValues::interposableKeyword    = "interposable";
-const char* const KeyValues::mergeKeyword           = "merge";
-const char* const KeyValues::isThumbKeyword         = "is-thumb";
-const char* const KeyValues::isAliasKeyword         = "is-alias";
-const char* const KeyValues::sectionNameKeyword     = "section-name";
-const char* const KeyValues::contentKeyword         = "content";
-const char* const KeyValues::loadNameKeyword        = "load-name";
-const char* const KeyValues::sizeKeyword            = "size";
-const char* const KeyValues::valueKeyword           = "value";
-const char* const KeyValues::fixupsKeyword          = "fixups";
-const char* const KeyValues::permissionsKeyword     = "permissions";
-const char* const KeyValues::canBeNullKeyword       = "can-be-null";
-const char* const KeyValues::fixupsKindKeyword      = "kind";
-const char* const KeyValues::fixupsOffsetKeyword    = "offset";
-const char* const KeyValues::fixupsTargetKeyword    = "target";
-const char* const KeyValues::fixupsAddendKeyword    = "addend";
-const char* const KeyValues::fileAtomsKeyword       = "atoms";
-const char* const KeyValues::fileKindKeyword        = "kind";
-const char* const KeyValues::fileMembersKeyword     = "members";
-
-
-
 const DefinedAtom::Definition         KeyValues::definitionDefault = Atom::definitionRegular;
 const DefinedAtom::Scope              KeyValues::scopeDefault = DefinedAtom::scopeTranslationUnit;
 const DefinedAtom::ContentType        KeyValues::contentTypeDefault = DefinedAtom::typeData;
@@ -58,36 +29,8 @@
 const bool                            KeyValues::isThumbDefault = false;
 const bool                            KeyValues::isAliasDefault = false;
 const UndefinedAtom::CanBeNull        KeyValues::canBeNullDefault = UndefinedAtom::canBeNullNever;
-const File::Kind                      KeyValues::fileKindDefault = File::kindObject;
 
 
-struct FileKindMapping {
-  const char*       string;
-  File::Kind        value;
-};
-
-static const FileKindMapping fileKindMappings[] = {
-  { "object",         File::kindObject },
-  { "archive",        File::kindArchiveLibrary },
-  { "shared-library", File::kindSharedLibrary },
-  { nullptr,          File::kindObject }
-};
-
- File::Kind KeyValues::fileKind(StringRef str) {
-  for (const FileKindMapping* p = fileKindMappings; p->string != nullptr; ++p) {
-    if (str == p->string)
-      return p->value;
-  }
-  llvm::report_fatal_error("bad file kind value");
-}
-
-const char* KeyValues::fileKind(File::Kind k) {
-  for (const FileKindMapping* p = fileKindMappings; p->string != nullptr; ++p) {
-    if ( p->value == k )
-      return p->string;
-  }
-  llvm::report_fatal_error("bad file kind value");
-}
 
 
 struct DefinitionMapping {
@@ -103,13 +46,15 @@
   { nullptr,          Atom::definitionRegular }
 };
 
-Atom::Definition KeyValues::definition(StringRef s)
+bool KeyValues::definition(StringRef s, Atom::Definition &out)
 {
   for (const DefinitionMapping* p = defMappings; p->string != nullptr; ++p) {
-    if (s == p->string)
-      return p->value;
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
   }
-  llvm::report_fatal_error("bad definition value");
+  return true;
 }
 
 const char* KeyValues::definition(Atom::Definition s) {
@@ -136,13 +81,15 @@
   { nullptr,  DefinedAtom::scopeGlobal }
 };
 
-DefinedAtom::Scope KeyValues::scope(StringRef s)
+bool KeyValues::scope(StringRef s, DefinedAtom::Scope &out)
 {
   for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) {
-    if (s == p->string)
-      return p->value;
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
   }
-  llvm::report_fatal_error("bad scope value");
+  return true;
 }
 
 const char* KeyValues::scope(DefinedAtom::Scope s) {
@@ -197,13 +144,15 @@
   { nullptr,          DefinedAtom::typeUnknown }
 };
 
-DefinedAtom::ContentType KeyValues::contentType(StringRef s)
+bool KeyValues::contentType(StringRef s, DefinedAtom::ContentType &out)
 {
   for (const ContentTypeMapping* p = typeMappings; p->string != nullptr; ++p) {
-    if (s == p->string)
-      return p->value;
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
   }
-  llvm::report_fatal_error("bad content type value");
+  return true;
 }
 
 const char* KeyValues::contentType(DefinedAtom::ContentType s) {
@@ -225,26 +174,26 @@
   DefinedAtom::DeadStripKind   value;
 };
 
-static const DeadStripMapping deadStripMappings[] = {
+static const DeadStripMapping dsMappings[] = {
   { "normal",         DefinedAtom::deadStripNormal },
   { "never",          DefinedAtom::deadStripNever },
   { "always",         DefinedAtom::deadStripAlways },
   { nullptr,          DefinedAtom::deadStripNormal }
 };
 
-DefinedAtom::DeadStripKind KeyValues::deadStripKind(StringRef s)
+bool KeyValues::deadStripKind(StringRef s, DefinedAtom::DeadStripKind &out)
 {
-  for (const DeadStripMapping* p = deadStripMappings; p->string != nullptr; ++p)
-  {
-    if (s == p->string)
-      return p->value;
+  for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) {
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
   }
-  llvm::report_fatal_error("bad dead strip value");
+  return true;
 }
 
 const char* KeyValues::deadStripKind(DefinedAtom::DeadStripKind dsk) {
-  for (const DeadStripMapping* p = deadStripMappings; p->string != nullptr; ++p)
-  {
+  for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) {
     if ( p->value == dsk )
       return p->string;
   }
@@ -267,13 +216,15 @@
   { nullptr,        DefinedAtom::interposeNo }
 };
 
-DefinedAtom::Interposable KeyValues::interposable(StringRef s)
+bool KeyValues::interposable(StringRef s, DefinedAtom::Interposable &out)
 {
   for (const InterposableMapping* p = interMappings; p->string != nullptr; ++p){
-    if (s == p->string)
-      return p->value;
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
   }
-  llvm::report_fatal_error("bad interposable value");
+  return true;
 }
 
 const char* KeyValues::interposable(DefinedAtom::Interposable in) {
@@ -302,13 +253,15 @@
   { nullptr,          DefinedAtom::mergeNo }
 };
 
-DefinedAtom::Merge KeyValues::merge(StringRef s)
+bool KeyValues::merge(StringRef s, DefinedAtom::Merge& out)
 {
   for (const MergeMapping* p = mergeMappings; p->string != nullptr; ++p) {
-    if (s == p->string)
-      return p->value;
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
   }
-  llvm::report_fatal_error("bad merge value");
+  return true;
 }
 
 const char* KeyValues::merge(DefinedAtom::Merge in) {
@@ -336,13 +289,15 @@
   { nullptr,           DefinedAtom::sectionBasedOnContent }
 };
 
-DefinedAtom::SectionChoice KeyValues::sectionChoice(StringRef s)
+bool KeyValues::sectionChoice(StringRef s, DefinedAtom::SectionChoice &out)
 {
   for (const SectionChoiceMapping* p = sectMappings; p->string != nullptr; ++p){
-    if (s == p->string)
-      return p->value;
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
   }
-  llvm::report_fatal_error("bad dead strip value");
+  return true;
 }
 
 const char* KeyValues::sectionChoice(DefinedAtom::SectionChoice s) {
@@ -365,21 +320,23 @@
 };
 
 static const PermissionsMapping permMappings[] = {
-  { "content",         DefinedAtom::perm___ },
-  { "custom",          DefinedAtom::permR__ },
-  { "custom-required", DefinedAtom::permR_X },
-  { "custom-required", DefinedAtom::permRW_ },
-  { "custom-required", DefinedAtom::permRW_L },
-  { nullptr,           DefinedAtom::perm___ }
+  { "---",    DefinedAtom::perm___  },
+  { "r--",    DefinedAtom::permR__  },
+  { "r-x",    DefinedAtom::permR_X  },
+  { "rw-",    DefinedAtom::permRW_  },
+  { "rw-l",   DefinedAtom::permRW_L },
+  { nullptr,  DefinedAtom::perm___  }
 };
 
-DefinedAtom::ContentPermissions KeyValues::permissions(StringRef s)
+bool KeyValues::permissions(StringRef s, DefinedAtom::ContentPermissions &out)
 {
   for (const PermissionsMapping* p = permMappings; p->string != nullptr; ++p) {
-    if (s == p->string)
-      return p->value;
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
   }
-  llvm::report_fatal_error("bad permissions value");
+  return true;
 }
 
 const char* KeyValues::permissions(DefinedAtom::ContentPermissions s) {
@@ -390,10 +347,42 @@
   llvm::report_fatal_error("bad permissions value");
 }
 
+
+bool KeyValues::isThumb(StringRef s, bool &out)
+{
+  if ( s.equals("true") ) {
+    out = true;
+    return false;
+  }
+  
+  if ( s.equals("false") ) {
+    out = false;
+    return false;
+  }
+
+  return true;
+}
+
 const char* KeyValues::isThumb(bool b) {
   return b ? "true" : "false";
 }
 
+
+bool KeyValues::isAlias(StringRef s, bool &out)
+{
+  if ( s.equals("true") ) {
+    out = true;
+    return false;
+  }
+  
+  if ( s.equals("false") ) {
+    out = false;
+    return false;
+  }
+
+  return true;
+}
+
 const char* KeyValues::isAlias(bool b) {
   return b ? "true" : "false";
 }
@@ -414,13 +403,15 @@
 };
 
 
-UndefinedAtom::CanBeNull KeyValues::canBeNull(StringRef s)
+bool KeyValues::canBeNull(StringRef s, UndefinedAtom::CanBeNull &out)
 {
   for (const CanBeNullMapping* p = cbnMappings; p->string != nullptr; ++p) {
-    if (s == p->string)
-      return p->value;
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
   }
-  llvm::report_fatal_error("bad can-be-null value");
+  return true;
 }
 
 const char* KeyValues::canBeNull(UndefinedAtom::CanBeNull c) {

Modified: lld/trunk/lib/Core/YamlKeyValues.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.h?rev=156136&r1=156135&r2=156136&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.h (original)
+++ lld/trunk/lib/Core/YamlKeyValues.h Thu May  3 18:55:34 2012
@@ -20,81 +20,62 @@
 
 class KeyValues {
 public:
-  static const char* const                nameKeyword;
-  static const char* const                refNameKeyword;
-  static const char* const                sectionNameKeyword;
-  static const char* const                contentKeyword;
-  static const char* const                sizeKeyword;
-  static const char* const                loadNameKeyword;
-  static const char* const                valueKeyword;
-  static const char* const                fixupsKeyword;
-  static const char* const                fileAtomsKeyword;
-  static const char* const                fileMembersKeyword;
-
-  static const char* const                fileKindKeyword;
-  static const File::Kind                 fileKindDefault;
-  static File::Kind                       fileKind(StringRef);
-  static const char*                      fileKind(File::Kind);
 
   static const char* const                definitionKeyword;
   static const Atom::Definition           definitionDefault;
-  static Atom::Definition                 definition(StringRef);
+  static bool                             definition(StringRef, Atom::Definition&);
   static const char*                      definition(Atom::Definition);
 
   static const char* const                scopeKeyword;
   static const DefinedAtom::Scope         scopeDefault;
-  static DefinedAtom::Scope               scope(StringRef);
+  static bool                             scope(StringRef, DefinedAtom::Scope&);
   static const char*                      scope(DefinedAtom::Scope);
 
   static const char* const                contentTypeKeyword;
   static const DefinedAtom::ContentType   contentTypeDefault;
-  static DefinedAtom::ContentType         contentType(StringRef);
+  static bool                             contentType(StringRef, DefinedAtom::ContentType&);
   static const char*                      contentType(DefinedAtom::ContentType);
 
   static const char* const                deadStripKindKeyword;
   static const DefinedAtom::DeadStripKind deadStripKindDefault;
-  static DefinedAtom::DeadStripKind       deadStripKind(StringRef);
+  static bool                             deadStripKind(StringRef, DefinedAtom::DeadStripKind&);
   static const char*                      deadStripKind(DefinedAtom::DeadStripKind);
 
   static const char* const                sectionChoiceKeyword;
   static const DefinedAtom::SectionChoice sectionChoiceDefault;
-  static DefinedAtom::SectionChoice       sectionChoice(StringRef);
+  static bool                             sectionChoice(StringRef,  DefinedAtom::SectionChoice&);
   static const char*                      sectionChoice(DefinedAtom::SectionChoice);
 
   static const char* const                interposableKeyword;
   static const DefinedAtom::Interposable  interposableDefault;
-  static DefinedAtom::Interposable        interposable(StringRef);
+  static bool                             interposable(StringRef, DefinedAtom::Interposable&);
   static const char*                      interposable(DefinedAtom::Interposable);
 
   static const char* const                mergeKeyword;
   static const DefinedAtom::Merge         mergeDefault;
-  static DefinedAtom::Merge               merge(StringRef);
+  static bool                             merge(StringRef, DefinedAtom::Merge&);
   static const char*                      merge(DefinedAtom::Merge);
 
   static const char* const                      permissionsKeyword;
   static const DefinedAtom::ContentPermissions  permissionsDefault;
-  static DefinedAtom::ContentPermissions        permissions(StringRef);
+  static bool                                   permissions(StringRef, DefinedAtom::ContentPermissions&);
   static const char*                            permissions(DefinedAtom::ContentPermissions);
 
   static const char* const                isThumbKeyword;
   static const bool                       isThumbDefault;
+  static bool                             isThumb(StringRef, bool&);
   static const char*                      isThumb(bool);
 
   static const char* const                isAliasKeyword;
   static const bool                       isAliasDefault;
+  static bool                             isAlias(StringRef, bool&);
   static const char*                      isAlias(bool);
 
   static const char* const                canBeNullKeyword;
   static const UndefinedAtom::CanBeNull   canBeNullDefault;
-  static UndefinedAtom::CanBeNull         canBeNull(StringRef);
+  static bool                             canBeNull(StringRef, UndefinedAtom::CanBeNull&);
   static const char*                      canBeNull(UndefinedAtom::CanBeNull);
 
-
-  static const char* const                fixupsKindKeyword;
-  static const char* const                fixupsOffsetKeyword;
-  static const char* const                fixupsTargetKeyword;
-  static const char* const                fixupsAddendKeyword;
-
 };
 
 } // namespace yaml

Modified: lld/trunk/lib/Core/YamlReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=156136&r1=156135&r2=156136&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlReader.cpp (original)
+++ lld/trunk/lib/Core/YamlReader.cpp Thu May  3 18:55:34 2012
@@ -1,4 +1,4 @@
-//===- Core/YamlReader.cpp - Reads YAML -----------------------------------===//
+//===- Core/YamlReader.cpp - Reads YAML encode object files ---------------===//
 //
 //                             The LLVM Linker
 //
@@ -31,43 +31,25 @@
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/system_error.h"
 #include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Debug.h"
 
 #include <cstring>
-#include <set>
-#include <type_traits>
 #include <vector>
 
-using namespace lld;
-
-static bool getAs(const llvm::yaml::ScalarNode *SN, bool &Result) {
-  SmallString<4> Storage;
-  StringRef Value = SN->getValue(Storage);
-  if (Value == "true")
-    Result = true;
-  else if (Value == "false")
-    Result = false;
-  else
-    return false;
-  return true;
-}
-
-template<class T>
-typename std::enable_if<std::numeric_limits<T>::is_integer, bool>::type
-getAs(const llvm::yaml::ScalarNode *SN, T &Result) {
-  SmallString<4> Storage;
-  StringRef Value = SN->getValue(Storage);
-  if (Value.getAsInteger(0, Result))
-    return false;
-  return true;
-}
 
 namespace lld {
 namespace yaml {
 
+
+///
+/// Concrete instance of lld::Reference created parsing YAML object files
+///
 class YAMLReference : public Reference {
 public:
   YAMLReference()
     : _target(nullptr)
+    , _targetNameNode(nullptr)
     , _offsetInAtom(0)
     , _addend(0)
     , _kind(0)
@@ -101,24 +83,31 @@
     _target = newAtom;
   }
 
+  typedef llvm::yaml::ScalarNode ScalarNode;
+  
   const Atom *_target;
-  StringRef   _targetName;
+  ScalarNode * _targetNameNode;
   uint64_t    _offsetInAtom;
   Addend      _addend;
   Kind        _kind;
 };
 
-class YAMLDefinedAtom;
 
+///
+/// Concrete instance of lld::File created parsing YAML object files.
+///
 class YAMLFile : public ArchiveLibraryFile {
 public:
   YAMLFile()
     : ArchiveLibraryFile("<anonymous>")
     , _lastRefIndex(0)
-    , _kind(File::kindObject)
-    , _inArchive(false) {
+    , _kind(File::kindObject) {
   }
 
+  ~YAMLFile();
+  
+  // Depending on the YAML description, this file can be either an
+  // lld::ArchiveLibraryFile or lld::File.
   virtual File::Kind kind() const {
     return _kind;
   }
@@ -140,10 +129,12 @@
     assert(0 && "cannot add atoms to YAML files");
   }
 
+  // Standard way that archives are searched.
   virtual const File *find(StringRef name, bool dataSymbolOnly) const;
 
-  void bindTargetReferences();
-  void addDefinedAtom(YAMLDefinedAtom *atom, StringRef refName);
+  error_code bindTargetReferences(llvm::yaml::Stream &stream);
+  
+  void addDefinedAtom(class YAMLDefinedAtom *atom, StringRef refName);
   void addUndefinedAtom(UndefinedAtom *atom);
   void addSharedLibraryAtom(SharedLibraryAtom *atom);
   void addAbsoluteAtom(AbsoluteAtom *atom);
@@ -151,6 +142,8 @@
   void addMember(StringRef);
   void setName(StringRef);
 
+  StringRef copyString(StringRef);
+  
   struct NameAtomPair {
                  NameAtomPair(StringRef n, Atom *a) : name(n), atom(a) {}
     StringRef name;
@@ -163,13 +156,17 @@
   atom_collection_vector<AbsoluteAtom>      _absoluteAtoms;
   std::vector<YAMLReference>                _references;
   std::vector<NameAtomPair>                 _nameToAtomMapping;
-  std::vector<StringRef>                    _memberNames;
   std::vector<std::unique_ptr<YAMLFile>>    _memberFiles;
+  std::vector<char*>                        _stringCopies;
   unsigned int                              _lastRefIndex;
   File::Kind                                _kind;
-  bool                                      _inArchive;
 };
 
+
+
+///
+/// Concrete instance of lld::DefinedAtom created parsing YAML object files.
+///
 class YAMLDefinedAtom : public DefinedAtom {
 public:
   YAMLDefinedAtom( uint32_t ord
@@ -187,13 +184,13 @@
           , StringRef name
           , StringRef sectionName
           , uint64_t size
-          , std::vector<uint8_t> content)
+          , std::vector<uint8_t>& content)
     : _file(file)
     , _name(name)
     , _sectionName(sectionName)
     , _size(size)
     , _ord(ord)
-    , _content(std::move(content))
+    , _content(content)
     , _alignment(alignment)
     , _scope(scope)
     , _type(type)
@@ -299,12 +296,23 @@
     it = reinterpret_cast<const void*>(index);
   }
 
-  void bindTargetReferences() const {
+  // Convert each target name to a pointer to an atom object
+  error_code bindTargetReferences(llvm::yaml::Stream &stream) const {
     for (unsigned int i=_refStartIndex; i < _refEndIndex; ++i) {
-      StringRef targetName = _file._references[i]._targetName;
-      Atom *targetAtom = _file.findAtom(targetName);
-      _file._references[i]._target = targetAtom;
+      llvm::SmallString<32> storage;
+      llvm::yaml::ScalarNode *node = _file._references[i]._targetNameNode;
+      StringRef name = node->getValue(storage);
+      Atom *targetAtom = _file.findAtom(name);
+      if ( targetAtom ) {
+        _file._references[i]._target = targetAtom;
+      }
+      else {
+        stream.printError(node, "Fixup has target '" + name 
+                            + "' which does not exist");
+        return make_error_code(yaml_reader_error::illegal_value);
+      }
     }
+    return make_error_code(yaml_reader_error::success);
   }
 
 private:
@@ -328,6 +336,11 @@
   unsigned int                _refEndIndex;
 };
 
+
+
+///
+/// Concrete instance of lld::UndefinedAtom created parsing YAML object files.
+///
 class YAMLUndefinedAtom : public UndefinedAtom {
 public:
   YAMLUndefinedAtom( YAMLFile &f
@@ -359,6 +372,11 @@
   UndefinedAtom::CanBeNull _canBeNull;
 };
 
+
+
+///
+/// Concrete instance of lld::SharedLibraryAtom created parsing YAML files.
+///
 class YAMLSharedLibraryAtom : public SharedLibraryAtom {
 public:
   YAMLSharedLibraryAtom( YAMLFile &f
@@ -397,6 +415,11 @@
   bool      _canBeNull;
 };
 
+
+
+///
+/// Concrete instance of lld::AbsoluteAtom created parsing YAML object files.
+///
 class YAMLAbsoluteAtom : public AbsoluteAtom {
 public:
   YAMLAbsoluteAtom(YAMLFile &f, int32_t ord, StringRef name, uint64_t v)
@@ -425,12 +448,30 @@
   uint64_t  _value;
 };
 
-void YAMLFile::bindTargetReferences() {
+
+
+
+//===----------------------------------------------------------------------===//
+//  YAMLFile methods
+//===----------------------------------------------------------------------===//
+
+YAMLFile::~YAMLFile() {
+  for (char *s : _stringCopies) {
+    delete [] s;
+  }
+}
+
+
+error_code YAMLFile::bindTargetReferences(llvm::yaml::Stream &stream) {
+  error_code ec;
   for (const DefinedAtom *defAtom : _definedAtoms) {
     const YAMLDefinedAtom *atom =
       reinterpret_cast<const YAMLDefinedAtom*>(defAtom);
-    atom->bindTargetReferences();
+    ec = atom->bindTargetReferences(stream);
+    if ( ec )
+      return ec;
   }
+  return ec;
 }
 
 Atom *YAMLFile::findAtom(StringRef name) {
@@ -438,7 +479,7 @@
     if (ci.name == name)
       return ci.atom;
   }
-  llvm::report_fatal_error("reference to atom that does not exist");
+  return nullptr;
 }
 
 void YAMLFile::addDefinedAtom(YAMLDefinedAtom *atom, StringRef refName) {
@@ -461,14 +502,20 @@
   _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom));
 }
 
-void YAMLFile::addMember(StringRef name) {
-  _memberNames.push_back(name);
-}
-
 void YAMLFile::setName(StringRef name) {
   _path = StringRef(name);
 }
 
+
+// Allocate a new copy of this string and keep track of allocations
+// in _stringCopies, so they can be freed when YAMLFile is destroyed.
+StringRef YAMLFile::copyString(StringRef str) {
+  char* s = new char[str.size()];
+  memcpy(s, str.data(), str.size());
+  _stringCopies.push_back(s);
+  return StringRef(s, str.size());
+}
+
 const File *YAMLFile::find(StringRef name, bool dataSymbolOnly) const {
   for (auto &file : _memberFiles) {
     for (const DefinedAtom *atom : file->defined() ) {
@@ -479,25 +526,96 @@
   return nullptr;
 }
 
-class YAMLAtomState {
+
+
+///
+/// The state machine that drives the YAMLParser stream and instantiates
+/// Files and Atoms.  This class also buffers all the attribures for the 
+/// current atom and current fixup.  Once all attributes are accumulated,  
+/// a new atom or fixup instance is instantiated.
+///
+class YAMLState {
 public:
-  YAMLAtomState(Platform &platform);
+  YAMLState(Platform &platform, llvm::yaml::Stream *s, YAMLFile *f);
 
-  void setName(StringRef n);
-  void setRefName(StringRef n);
+  void        parse(llvm::yaml::Node *node, StringRef keyword, 
+                                        llvm::yaml::Node *keywordNode=nullptr);
+  error_code  error() { return _error; }
+  
+private:
+  typedef llvm::yaml::Node Node;
+  typedef llvm::yaml::ScalarNode ScalarNode;
+  typedef llvm::yaml::SequenceNode SequenceNode;
+  typedef llvm::yaml::MappingNode MappingNode;
+  typedef llvm::yaml::Stream Stream;
+
+  void resetState();
   void setAlign2(StringRef n);
 
-  void setFixupKind(StringRef n);
-  void setFixupTarget(StringRef n);
-  void addFixup(YAMLFile *f);
+  void makeReference();
+  void makeAtom(Node *node);
+  void makeDefinedAtom(Node *node);
+  void makeUndefinedAtom(Node *node);
+  void makeSharedLibraryAtom(Node *node);
+  void makeAbsoluteAtom(Node *node);
+ 
+  void parseMemberName(ScalarNode *node);
+  void parseAtomName(ScalarNode *node);
+  void parseAtomRefName(ScalarNode *node);
+  void parseAtomType(ScalarNode *node);
+  void parseAtomScope(ScalarNode *node);
+  void parseAtomDefinition(ScalarNode *node);
+  void parseAtomDeadStrip(ScalarNode *node);
+  void parseAtomSectionChoice(ScalarNode *node);
+  void parseAtomInterposable(ScalarNode *node);
+  void parseAtomMerge(ScalarNode *node);
+  void parseAtomIsThumb(ScalarNode *node);
+  void parseAtomIsAlias(ScalarNode *node);
+  void parseAtomSectionName(ScalarNode *node);
+  void parseAtomSize(ScalarNode *node);
+  void parseAtomPermissions(ScalarNode *node);
+  void parseAtomCanBeNull(ScalarNode *node);
+  void parseFixUpOffset(ScalarNode *node);
+  void parseFixUpKind(ScalarNode *node);
+  void parseFixUpTarget(ScalarNode *node);
+  void parseFixUpAddend(ScalarNode *node);
+  void parseAtomContentByte(ScalarNode *node);
+  void parseAtomLoadName(ScalarNode *node);
+  void parseAtomValue(ScalarNode *node);
+
+  StringRef extractString(ScalarNode *node);
+
+  typedef void (YAMLState:: *ParseScalar)(ScalarNode *node);
+  typedef void (YAMLState:: *ParseSeq)(SequenceNode *node);
+  typedef void (YAMLState:: *ParseMap)(MappingNode *node);
+
+  enum State { inError, inTop, inDoc, inArch, inMemb, 
+              inAtoms, inAtom, inFixUps, inFixUp, inBytes };
+  struct Transistion {
+    State         state;
+    const char*   keyword;
+    State         newState;
+    ParseScalar   customAction;
+  };
+
+  static const char* stateName(State);
 
-  void makeAtom(YAMLFile&);
+  void moveToState(State s);
+  void returnToState(State s, Node *node);
+  
+  static const Transistion _s_transistions[];
 
   Platform                   &_platform;
+  error_code                  _error;
+  llvm::yaml::Stream         *_stream;
+  YAMLFile                   *_file;
+  YAMLFile                   *_archiveFile;
+  State                       _state;
   StringRef                   _name;
   StringRef                   _refName;
   StringRef                   _sectionName;
   StringRef                   _loadName;
+  StringRef                   _memberName;
   unsigned long long          _size;
   uint64_t                    _value;
   uint32_t                    _ordinal;
@@ -515,71 +633,164 @@
   bool                        _isAlias;
   UndefinedAtom::CanBeNull    _canBeNull;
   YAMLReference               _ref;
+  bool                        _hasDefinedAtomAttributes;
+  bool                        _hasUndefinedAtomAttributes;
+  bool                        _hasSharedLibraryAtomAttributes;
+  bool                        _hasAbsoluteAtomAttributes;
+};
+
+
+//
+// This transition table is the heart of the state machine.  
+// The table is read left-to-right columns A,B,C,D as:  
+//    If the state is A and key B is seen switch to state C then
+//    if D is not nullptr call that method with the key's value,
+//    if D is nullptr, recursively parse in the new state.
+//
+const YAMLState::Transistion YAMLState::_s_transistions[] = {
+  { inTop,   "<root>",         inDoc,   nullptr                            },
+  { inDoc,   "archive",        inArch,  nullptr                            },
+  { inArch,  "<any-seq-item>", inMemb,  nullptr                            },
+  { inMemb,  "atoms",          inAtoms, nullptr                            },
+  { inMemb,  "name",           inMemb,  &YAMLState::parseMemberName        },
+  { inDoc,   "atoms",          inAtoms, nullptr                            },
+  { inAtoms, "<any-seq-item>", inAtom,  nullptr                            },
+  { inAtom,  "name",           inAtom,  &YAMLState::parseAtomName          },
+  { inAtom,  "ref-name",       inAtom,  &YAMLState::parseAtomRefName       },
+  { inAtom,  "type",           inAtom,  &YAMLState::parseAtomType          },
+  { inAtom,  "scope",          inAtom,  &YAMLState::parseAtomScope         },
+  { inAtom,  "definition",     inAtom,  &YAMLState::parseAtomDefinition    },
+  { inAtom,  "dead-strip",     inAtom,  &YAMLState::parseAtomDeadStrip     },
+  { inAtom,  "section-choice", inAtom,  &YAMLState::parseAtomSectionChoice },
+  { inAtom,  "interposable",   inAtom,  &YAMLState::parseAtomInterposable  },
+  { inAtom,  "merge",          inAtom,  &YAMLState::parseAtomMerge         },
+  { inAtom,  "is-thumb",       inAtom,  &YAMLState::parseAtomIsThumb       },
+  { inAtom,  "is-alias",       inAtom,  &YAMLState::parseAtomIsAlias       },
+  { inAtom,  "section-name",   inAtom,  &YAMLState::parseAtomSectionName   },
+  { inAtom,  "size",           inAtom,  &YAMLState::parseAtomSize          },
+  { inAtom,  "permissions",    inAtom,  &YAMLState::parseAtomPermissions   },
+  { inAtom,  "can-be-null",    inAtom,  &YAMLState::parseAtomCanBeNull     },
+  { inAtom,  "content",        inBytes, nullptr                            },
+  { inAtom,  "fixups",         inFixUps,nullptr                            },
+  { inBytes, "<any-seq-item>", inBytes, &YAMLState::parseAtomContentByte   },
+  { inFixUps,"<any-seq-item>", inFixUp, nullptr                            },
+  { inFixUp, "offset",         inFixUp, &YAMLState::parseFixUpOffset       },
+  { inFixUp, "kind",           inFixUp, &YAMLState::parseFixUpKind         },
+  { inFixUp, "target",         inFixUp, &YAMLState::parseFixUpTarget       },
+  { inFixUp, "addend",         inFixUp, &YAMLState::parseFixUpAddend       },
+  { inAtom,  "load-name",      inAtom,  &YAMLState::parseAtomLoadName      },
+  { inAtom,  "value",          inAtom,  &YAMLState::parseAtomValue         },
+  { inError,  nullptr,         inAtom,  nullptr                            },
 };
 
 
-YAMLAtomState::YAMLAtomState(Platform &platform)
+
+YAMLState::YAMLState(Platform &platform, Stream *stream, YAMLFile *file)
   : _platform(platform)
-  , _size(0)
-  , _value(0)
-  , _ordinal(0)
-  , _alignment(0, 0)
-  , _definition(KeyValues::definitionDefault)
-  , _scope(KeyValues::scopeDefault)
-  , _type(KeyValues::contentTypeDefault)
-  , _sectionChoice(KeyValues::sectionChoiceDefault)
-  , _interpose(KeyValues::interposableDefault)
-  , _merge(KeyValues::mergeDefault)
-  , _deadStrip(KeyValues::deadStripKindDefault)
-  , _permissions(KeyValues::permissionsDefault)
-  , _isThumb(KeyValues::isThumbDefault)
-  , _isAlias(KeyValues::isAliasDefault)
-  , _canBeNull(KeyValues::canBeNullDefault) {
-}
-
-void YAMLAtomState::makeAtom(YAMLFile &f) {
-  if (_definition == Atom::definitionRegular) {
-    YAMLDefinedAtom *a =
-      new YAMLDefinedAtom( _ordinal
-                         , f
-                         , _scope
-                         , _type
-                         , _sectionChoice
-                         , _interpose
-                         , _merge
-                         , _deadStrip
-                         , _permissions
-                         , _isThumb
-                         , _isAlias
-                         , _alignment
-                         , _name
-                         , _sectionName
-                         , _size
-                         , _content
-                         );
-    f.addDefinedAtom(a, !_refName.empty() ? _refName : _name);
-    ++_ordinal;
-  } else if (_definition == Atom::definitionUndefined) {
-    UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _canBeNull);
-    f.addUndefinedAtom(a);
-    ++_ordinal;
-  } else if (_definition == Atom::definitionSharedLibrary) {
-    bool nullable = (_canBeNull == UndefinedAtom::canBeNullAtRuntime);
-    SharedLibraryAtom *a = new YAMLSharedLibraryAtom(f, _ordinal, _name,
-                                                      _loadName, nullable);
-    f.addSharedLibraryAtom(a);
-    ++_ordinal;
-  } else if (_definition == Atom::definitionAbsolute) {
-    AbsoluteAtom *a = new YAMLAbsoluteAtom(f, _ordinal, _name, _value);
-    f.addAbsoluteAtom(a);
-    ++_ordinal;
+  , _error(make_error_code(yaml_reader_error::success))
+  , _stream(stream)
+  , _file(file)
+  , _archiveFile(nullptr)
+  , _state(inTop) 
+  , _alignment(0, 0) {
+  this->resetState();
+}
+
+void YAMLState::makeAtom(Node *node) {
+  switch (_definition ) {
+    case Atom::definitionRegular:
+      this->makeDefinedAtom(node);
+      break;
+    case Atom::definitionUndefined:
+      this->makeUndefinedAtom(node);
+      break;
+    case Atom::definitionSharedLibrary:
+      this->makeSharedLibraryAtom(node);
+      break;
+    case Atom::definitionAbsolute:
+      this->makeAbsoluteAtom(node);
+      break;
   }
-
+  ++_ordinal;
+  
   // reset state for next atom
+  this->resetState();
+}
+
+void YAMLState::makeDefinedAtom(Node *node) {
+  if ( _hasAbsoluteAtomAttributes ) {
+    _stream->printError(node, "Defined atom '" + _name 
+                          + "' has attributes only allowed on absolute atoms");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  if ( _hasSharedLibraryAtomAttributes ) {
+    _stream->printError(node, "Defined atom '" + _name 
+                    + "' has attributes only allowed on shared library atoms");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+
+  YAMLDefinedAtom *a = new YAMLDefinedAtom(_ordinal, *_file, _scope, _type
+                         , _sectionChoice, _interpose, _merge, _deadStrip
+                         , _permissions, _isThumb, _isAlias, _alignment
+                         , _name, _sectionName, _size, _content);
+    _file->addDefinedAtom(a, !_refName.empty() ? _refName : _name);
+}
+
+void YAMLState::makeUndefinedAtom(Node *node) {
+  if ( _hasDefinedAtomAttributes ) {
+    _stream->printError(node, "Undefined atom '" + _name 
+                          + "' has attributes only allowed on defined atoms");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  if ( _hasAbsoluteAtomAttributes ) {
+    _stream->printError(node, "Defined atom '" + _name 
+                          + "' has attributes only allowed on absolute atoms");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  UndefinedAtom *a = new YAMLUndefinedAtom(*_file, _ordinal, _name, _canBeNull);
+  _file->addUndefinedAtom(a);
+}
+
+void YAMLState::makeSharedLibraryAtom(Node *node) {
+  if ( _hasDefinedAtomAttributes ) {
+    _stream->printError(node, "SharedLibrary atom '" + _name 
+                          + "' has attributes only allowed on defined atoms");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  if ( _hasAbsoluteAtomAttributes ) {
+    _stream->printError(node, "Defined atom '" + _name 
+                          + "' has attributes only allowed on absolute atoms");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  bool nullable = (_canBeNull == UndefinedAtom::canBeNullAtRuntime);
+  SharedLibraryAtom *a = new YAMLSharedLibraryAtom(*_file, _ordinal, _name,
+                                                    _loadName, nullable);
+  _file->addSharedLibraryAtom(a);
+}
+
+void YAMLState::makeAbsoluteAtom(Node *node) {
+  if ( _hasDefinedAtomAttributes ) {
+    _stream->printError(node, "Absolute atom '" + _name 
+                          + "' has attributes only allowed on defined atoms");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  if ( _hasSharedLibraryAtomAttributes ) {
+    _stream->printError(node, "Absolute atom '" + _name 
+                    + "' has attributes only allowed on shared library atoms");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  AbsoluteAtom *a = new YAMLAbsoluteAtom(*_file, _ordinal, _name, _value);
+  _file->addAbsoluteAtom(a);
+}
+
+
+
+void YAMLState::resetState() {
   _name               = StringRef();
   _refName            = StringRef();
   _sectionName        = StringRef();
   _loadName           = StringRef();
+  _memberName         = StringRef();
   _size               = 0;
   _value              = 0;
   _ordinal            = 0;
@@ -598,346 +809,429 @@
   _isAlias            = KeyValues::isAliasDefault;
   _canBeNull          = KeyValues::canBeNullDefault;
   _ref._target        = nullptr;
-  _ref._targetName    = StringRef();
+  _ref._targetNameNode= nullptr;
   _ref._addend        = 0;
   _ref._offsetInAtom  = 0;
   _ref._kind          = 0;
+  
+  _hasDefinedAtomAttributes = false;
+  _hasUndefinedAtomAttributes = false;
+  _hasSharedLibraryAtomAttributes = false;
+  _hasAbsoluteAtomAttributes = false;
 }
 
-void YAMLAtomState::setName(StringRef n) {
-  _name = n;
-}
 
-void YAMLAtomState::setRefName(StringRef n) {
-  _refName = n;
+void YAMLState::makeReference() {
+  _file->_references.push_back(_ref);
+  // clear for next ref
+  _ref._target        = nullptr;
+  _ref._targetNameNode= nullptr;
+  _ref._addend        = 0;
+  _ref._offsetInAtom  = 0;
+  _ref._kind          = 0;
 }
 
-void YAMLAtomState::setAlign2(StringRef s) {
+
+
+void YAMLState::setAlign2(StringRef s) {
   if (StringRef(s).getAsInteger(10, _alignment.powerOf2))
     _alignment.powerOf2 = 1;
 }
 
-void YAMLAtomState::setFixupKind(StringRef s) {
-  _ref._kind = _platform.kindFromString(StringRef(s));
+
+// For debug logging
+const char* YAMLState::stateName(State s) {
+  switch ( s ) {
+    case inError:
+      return "inError";
+    case inTop:
+      return "inTop";
+    case inDoc:
+      return "inDoc";
+    case inArch:
+      return "inArch";
+    case inMemb:
+      return "inMemb";
+    case inAtoms:
+      return "inAtoms";
+    case inAtom:
+      return "inAtom";
+    case inFixUps:
+      return "inFixUps";
+    case inFixUp:
+      return "inFixUp";
+    case inBytes:
+      return "inBytes";
+  }
+  return "unknown case";
+}
+
+// Called by parse() when recursing and switching to a new state.
+void YAMLState::moveToState(State newState) {
+  if ( newState == _state )
+    return;
+  DEBUG(llvm::dbgs() << "moveToState(" << stateName(newState) 
+                     << "), _state=" << stateName(_state) << "\n");
+  
+  if ( newState == inArch ) {
+    // Seen "archive:", repurpose existing YAMLFile to be archive file
+    _file->_kind = File::kindArchiveLibrary;
+    _archiveFile = _file;
+    _file = nullptr;
+  }
+  
+  if ( newState == inMemb ) {
+    assert(_state == inArch);
+    // Make new YAMLFile for this member
+    std::unique_ptr<YAMLFile> memberFile(new YAMLFile);
+    _file = memberFile.get();
+    assert(_archiveFile != nullptr);
+    _archiveFile->_memberFiles.emplace_back(memberFile.release());
+  }
+
+  _state = newState;
+}
+
+// Called by parse() when returning from recursion and restoring the old state.
+void YAMLState::returnToState(State prevState, Node *node) {
+  if ( prevState == _state )
+    return;
+  DEBUG(llvm::dbgs() << "returnToState(" << stateName(prevState) 
+                     << "), _state=" << stateName(_state) << "\n");
+  // If done with an atom, instantiate an object for it.
+  if ( (_state == inAtom) && (prevState == inAtoms) )
+    this->makeAtom(node);
+  // If done wit a fixup, instantiate an object for it.
+  if ( (_state == inFixUp) && (prevState == inFixUps) )
+    this->makeReference();
+  _state = prevState;
+}
+
+// If a string in the yaml document is quoted in a way that there is no
+// contiguous range of bytes that a StringRef can point to, then we make
+// a copy of the string and have the StringRef point to that.
+StringRef YAMLState::extractString(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  StringRef str = node->getValue(storage);
+  if ( str.data() == storage.begin() ) {
+    str = _file->copyString(str);
+  }
+  return str;
 }
 
-void YAMLAtomState::setFixupTarget(StringRef s) {
-  _ref._targetName = s;
+
+void YAMLState::parseMemberName(ScalarNode *node) {
+   _memberName = extractString(node);
 }
 
-void YAMLAtomState::addFixup(YAMLFile *f) {
-  f->_references.push_back(_ref);
-  // clear for next ref
-  _ref._target       = nullptr;
-  _ref._targetName   = StringRef();
-  _ref._addend       = 0;
-  _ref._offsetInAtom = 0;
-  _ref._kind         = 0;
+void YAMLState::parseAtomName(ScalarNode *node) {
+   _name = extractString(node);
 }
 
-llvm::error_code parseFixup( llvm::yaml::MappingNode *mn
-                           , llvm::yaml::Stream &s
-                           , Platform &p
-                           , YAMLFile &f
-                           , YAMLAtomState &yas) {
-  using namespace llvm::yaml;
+void YAMLState::parseAtomRefName(ScalarNode *node) {
+   _refName = extractString(node);
+}
+
+void YAMLState::parseAtomScope(ScalarNode *node) {
   llvm::SmallString<32> storage;
+  if ( KeyValues::scope(node->getValue(storage), _scope) ) {
+    _stream->printError(node, "Invalid value for 'scope:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  _hasDefinedAtomAttributes = true;
+}
 
-  for (auto &keyval : *mn) {
-    ScalarNode *key = llvm::dyn_cast<ScalarNode>(keyval.getKey());
-    if (!key) {
-      s.printError(key, "Expected a scalar value");
-      return make_error_code(yaml_reader_error::illegal_value);
-    }
-    ScalarNode *value = llvm::dyn_cast<ScalarNode>(keyval.getValue());
-    if (!value) {
-      s.printError(value, "Expected a scalar value");
-      return make_error_code(yaml_reader_error::illegal_value);
-    }
-    llvm::StringRef keyValue = key->getValue(storage);
-    if (keyValue == KeyValues::fixupsOffsetKeyword) {      
-      if (!getAs(value, yas._ref._offsetInAtom)) {
-        s.printError(value, "Invalid value for offset");
-        return make_error_code(yaml_reader_error::illegal_value);
-      }
-    } else if (keyValue == KeyValues::fixupsKindKeyword) {
-      yas._ref._kind = p.kindFromString(value->getValue(storage));
-    } else if (keyValue == KeyValues::fixupsTargetKeyword) {
-      // FIXME: string lifetime.
-      yas._ref._targetName = value->getValue(storage);
-    } else if (keyValue == KeyValues::fixupsAddendKeyword) {
-      if (!getAs(value, yas._ref._addend)) {
-        s.printError(value, "Invalid value for addend");
-        return make_error_code(yaml_reader_error::illegal_value);
-      }
-    } else {
-      s.printError(key, "Unrecognized key");
-      return make_error_code(yaml_reader_error::unknown_keyword);
-    }
+void YAMLState::parseAtomDefinition(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  if ( KeyValues::definition(node->getValue(storage), _definition) ) {
+    _stream->printError(node, "Invalid value for 'definition:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
   }
-  yas.addFixup(&f);
-  return make_error_code(yaml_reader_error::success);
 }
 
-llvm::error_code parseAtom( llvm::yaml::MappingNode *mn
-                          , llvm::yaml::Stream &s
-                          , Platform &p
-                          , YAMLFile &f) {
-  using namespace llvm::yaml;
-  YAMLAtomState yas(p);
+void YAMLState::parseAtomType(ScalarNode *node) {
   llvm::SmallString<32> storage;
+  if ( KeyValues::contentType(node->getValue(storage), _type) ) {
+    _stream->printError(node, "Invalid value for 'type:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  _hasDefinedAtomAttributes = true;
+}
 
-  for (MappingNode::iterator i = mn->begin(), e = mn->end(); i != e; ++i) {
-    ScalarNode *Key = llvm::dyn_cast<ScalarNode>(i->getKey());
-    if (!Key)
-      return make_error_code(yaml_reader_error::illegal_value);
-    llvm::StringRef KeyValue = Key->getValue(storage);
-    if (KeyValue == KeyValues::contentKeyword) {
-      ScalarNode *scalarValue = llvm::dyn_cast<ScalarNode>(i->getValue());
-      if (scalarValue) {
-        yas._type = KeyValues::contentType(scalarValue->getValue(storage));
-      } else {
-        SequenceNode *Value = llvm::dyn_cast<SequenceNode>(i->getValue());
-        if (!Value) {
-          s.printError(i->getValue(), "Expected a sequence");
-          return make_error_code(yaml_reader_error::illegal_value);
-        }
-        for (SequenceNode::iterator ci = Value->begin(), ce = Value->end();
-                                    ci != ce; ++ci) {
-          ScalarNode *Entry = llvm::dyn_cast<ScalarNode>(&*ci);
-          if (!Entry) {
-            s.printError(i->getValue(), "Expected a scalar value");
-            return make_error_code(yaml_reader_error::illegal_value);
-          }
-          unsigned int ContentByte;
-          if (Entry->getValue(storage).getAsInteger(16, ContentByte)) {
-            s.printError(i->getValue(), "Invalid content byte");
-            return make_error_code(yaml_reader_error::illegal_value);
-          }
-          if (ContentByte > 0xFF) {
-            s.printError(i->getValue(), "Byte out of range (> 0xFF)");
-            return make_error_code(yaml_reader_error::illegal_value);
-          }
-          yas._content.push_back(ContentByte & 0xFF);
-        }
-      }
-    } else if (KeyValue == KeyValues::fixupsKeyword) {
-      SequenceNode *Value = llvm::dyn_cast<SequenceNode>(i->getValue());
-      if (!Value) {
-        s.printError(i->getValue(), "Expected a sequence");
-        return make_error_code(yaml_reader_error::illegal_value);
-      }
-      for (auto &i : *Value) {
-        MappingNode *Fixup = llvm::dyn_cast<MappingNode>(&i);
-        if (!Fixup) {
-          s.printError(&i, "Expected a map");
-          return make_error_code(yaml_reader_error::illegal_value);
-        }
-        if (error_code ec = parseFixup(Fixup, s, p, f, yas))
-          return ec;
-      }
-    } else {
-      // The rest of theses all require value to be a scalar.
-      ScalarNode *Value = llvm::dyn_cast<ScalarNode>(i->getValue());
-      if (!Value) {
-        s.printError(i->getValue(), "Expected a scalar value");
-        return make_error_code(yaml_reader_error::illegal_value);
-      }
-      if (KeyValue == KeyValues::nameKeyword) {
-        // FIXME: String lifetime.
-        yas.setName(Value->getValue(storage));
-      } else if (KeyValue == KeyValues::refNameKeyword) {
-        // FIXME: String lifetime.
-        yas.setRefName(Value->getValue(storage));
-      } else if (KeyValue == KeyValues::valueKeyword) {
-        if (!getAs(Value, yas._value)) {
-          s.printError(Value, "Invalid value for value");
-          return make_error_code(yaml_reader_error::illegal_value);
-        }
-      } else if (KeyValue == KeyValues::loadNameKeyword)
-        // FIXME: String lifetime.
-        yas._loadName = Value->getValue(storage);
-      else if (KeyValue == KeyValues::definitionKeyword)
-        yas._definition = KeyValues::definition(Value->getValue(storage));
-      else if (KeyValue == KeyValues::scopeKeyword)
-        yas._scope = KeyValues::scope(Value->getValue(storage));
-      else if (KeyValue == KeyValues::contentTypeKeyword)
-        yas._type = KeyValues::contentType(Value->getValue(storage));
-      else if (KeyValue == KeyValues::deadStripKindKeyword)
-        yas._deadStrip = KeyValues::deadStripKind(Value->getValue(storage));
-      else if (KeyValue == KeyValues::sectionChoiceKeyword)
-        yas._sectionChoice = KeyValues::sectionChoice(Value->getValue(storage));
-      else if (KeyValue == KeyValues::mergeKeyword)
-        yas._merge = KeyValues::merge(Value->getValue(storage));
-      else if (KeyValue == KeyValues::interposableKeyword)
-        yas._interpose = KeyValues::interposable(Value->getValue(storage));
-      else if (KeyValue == KeyValues::isThumbKeyword) {
-        if (!getAs(Value, yas._isThumb)) {
-          s.printError(Value, "Invalid value for isThumb");
-          return make_error_code(yaml_reader_error::illegal_value);
-        }
-      } else if (KeyValue == KeyValues::isAliasKeyword) {
-        if (!getAs(Value, yas._isAlias)) {
-          s.printError(Value, "Invalid value for isAlias");
-          return make_error_code(yaml_reader_error::illegal_value);
-        }
-      } else if (KeyValue == KeyValues::canBeNullKeyword) {
-        yas._canBeNull = KeyValues::canBeNull(Value->getValue(storage));
-        if (yas._definition == Atom::definitionSharedLibrary
-            && yas._canBeNull == UndefinedAtom::canBeNullAtBuildtime) {
-          s.printError(Value, "Invalid value for can be null");
-          return make_error_code(yaml_reader_error::illegal_value);
-        }
-      } else if (KeyValue == KeyValues::sectionNameKeyword)
-        // FIXME: String lifetime.
-        yas._sectionName = Value->getValue(storage);
-      else if (KeyValue == KeyValues::sizeKeyword) {
-        if (!getAs(Value, yas._size)) {
-          s.printError(Value, "Invalid value for size");
-          return make_error_code(yaml_reader_error::illegal_value);
-        }
-      } else if (KeyValue == "align2")
-        yas.setAlign2(Value->getValue(storage));
-      else {
-        s.printError(Key, "Unrecognized key");
-        return make_error_code(yaml_reader_error::unknown_keyword);
-      }
-    }
+void YAMLState::parseAtomDeadStrip(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  if ( KeyValues::deadStripKind(node->getValue(storage), _deadStrip) ) {
+    _stream->printError(node, "Invalid value for 'dead-strip:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
   }
-  yas.makeAtom(f);
-  return make_error_code(yaml_reader_error::success);
+  _hasDefinedAtomAttributes = true;
 }
 
-llvm::error_code parseAtoms( llvm::yaml::SequenceNode *atoms
-                           , llvm::yaml::Stream &s
-                           , Platform &p
-                           , YAMLFile &f) {
-  using namespace llvm::yaml;
+void YAMLState::parseAtomSectionChoice(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  if ( KeyValues::sectionChoice(node->getValue(storage), _sectionChoice) ) {
+    _stream->printError(node, "Invalid value for 'section-choice:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  _hasDefinedAtomAttributes = true;
+}
 
-  for (auto &atom : *atoms) {
-    if (MappingNode *a = llvm::dyn_cast<MappingNode>(&atom)) {
-      if (llvm::error_code ec = parseAtom(a, s, p, f))
-        return ec;
-    } else {
-      s.printError(&atom, "Expected map");
-      return make_error_code(yaml_reader_error::illegal_value);
-    }
+void YAMLState::parseAtomInterposable(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  if ( KeyValues::interposable(node->getValue(storage), _interpose) ) {
+    _stream->printError(node, "Invalid value for 'interposable:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
   }
-  return make_error_code(yaml_reader_error::success);
+  _hasDefinedAtomAttributes = true;
 }
 
-llvm::error_code parseArchive( llvm::yaml::SequenceNode *archive
-                             , llvm::yaml::Stream &s
-                             , Platform &p
-                             , YAMLFile &f) {
-  using namespace llvm::yaml;
+void YAMLState::parseAtomMerge(ScalarNode *node) {
   llvm::SmallString<32> storage;
+  if ( KeyValues::merge(node->getValue(storage), _merge) ) {
+    _stream->printError(node, "Invalid value for 'merge:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  _hasDefinedAtomAttributes = true;
+}
 
-  for (auto &member : *archive) {
-    std::unique_ptr<YAMLFile> mf(new YAMLFile);
-    MappingNode *mem = llvm::dyn_cast<MappingNode>(&member);
-    if (!mem) {
-      s.printError(&member, "Expected map");
-      return make_error_code(yaml_reader_error::illegal_value);
+void YAMLState::parseAtomIsThumb(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  if ( KeyValues::isThumb(node->getValue(storage), _isThumb) ) {
+    _stream->printError(node, "Invalid value for 'thumb:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  _hasDefinedAtomAttributes = true;
+}
+
+void YAMLState::parseAtomIsAlias(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  if ( KeyValues::isAlias(node->getValue(storage), _isAlias) ) {
+    _stream->printError(node, "Invalid value for 'is-alias:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  _hasDefinedAtomAttributes = true;
+}
+
+void YAMLState::parseAtomSectionName(ScalarNode *node) {
+  _sectionName = extractString(node);
+  _hasDefinedAtomAttributes = true;
+}
+
+void YAMLState::parseAtomSize(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  StringRef offsetStr = node->getValue(storage);
+  if ( offsetStr.getAsInteger(0, _size) ) {
+    _stream->printError(node, "Invalid value for atom 'size:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  _hasDefinedAtomAttributes = true;
+}
+
+void YAMLState::parseAtomPermissions(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  if ( KeyValues::permissions(node->getValue(storage), _permissions) ) {
+    _stream->printError(node, "Invalid value for 'permissions:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  _hasDefinedAtomAttributes = true;
+}
+
+void YAMLState::parseAtomCanBeNull(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  if ( KeyValues::canBeNull(node->getValue(storage), _canBeNull) ) {
+    _stream->printError(node, "Invalid value for 'can-be-null:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+}
+
+void YAMLState::parseFixUpOffset(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  StringRef offsetStr = node->getValue(storage);
+  if ( offsetStr.getAsInteger(0, _ref._offsetInAtom) ) {
+    _stream->printError(node, "Invalid value for fixup 'offset:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  _hasDefinedAtomAttributes = true;
+}
+
+void YAMLState::parseFixUpKind(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  _ref._kind = _platform.kindFromString(node->getValue(storage));
+  _hasDefinedAtomAttributes = true;
+}
+
+void YAMLState::parseFixUpTarget(ScalarNode *node) {
+  _ref._targetNameNode = node;
+  _hasDefinedAtomAttributes = true;
+}
+
+void YAMLState::parseFixUpAddend(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  StringRef offsetStr = node->getValue(storage);
+  if ( offsetStr.getAsInteger(0, _ref._addend) ) {
+    _stream->printError(node, "Invalid value for fixup 'addend:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  _hasDefinedAtomAttributes = true;
+}
+
+void YAMLState::parseAtomContentByte(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  StringRef str = node->getValue(storage);
+  unsigned int contentByte;
+  if ( str.getAsInteger(16, contentByte) ) {
+    _stream->printError(node, "Invalid content hex byte '0x" + str + "'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+    return;
+  }
+  if (contentByte > 0xFF) {
+    _stream->printError(node, "Content hex byte out of range (0x" 
+                                                       + str + " > 0xFF)");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+    return;
+  }
+  _content.push_back(contentByte & 0xFF);
+  _hasDefinedAtomAttributes = true;
+}
+
+void YAMLState::parseAtomLoadName(ScalarNode *node) {
+  _loadName = extractString(node);
+  _hasSharedLibraryAtomAttributes = true;
+}
+
+
+void YAMLState::parseAtomValue(ScalarNode *node) {
+  llvm::SmallString<32> storage;
+  StringRef offsetStr = node->getValue(storage);
+  if ( offsetStr.getAsInteger(0, _value) ) {
+    _stream->printError(node, "Invalid value for fixup 'addend:'");
+    _error = make_error_code(yaml_reader_error::illegal_value);
+  }
+  _hasAbsoluteAtomAttributes = true;
+}
+
+//
+// This is the parsing engine that walks the nodes in the yaml document
+// stream.  It is table driven.  See _s_transistions.
+//
+void YAMLState::parse(Node *node, StringRef keyword, Node *keywordNode) {
+  using namespace llvm::yaml;
+  DEBUG(llvm::dbgs() << "parse(" << keyword << "), _state=" 
+                     << stateName(_state) << "\n");
+  if ( _error )
+    return;
+  State savedState = _state;
+  for(const Transistion* t=_s_transistions; t->state != inError; ++t) {
+    if ( t->state != _state )
+      continue;
+    if ( ! keyword.equals(t->keyword) )
+      continue;    
+    ParseScalar action = t->customAction;
+    this->moveToState(t->newState);
+    if ( ScalarNode *sc = llvm::dyn_cast<ScalarNode>(node) ) {
+      if ( action ) {
+        (*this.*action)(sc);
+      }
+      else {
+        _stream->printError(node, "unexpected scalar");
+        _error = make_error_code(yaml_reader_error::illegal_value);
+      }
     }
-    for (auto &keyVal : *mem) {
-      ScalarNode *key = llvm::dyn_cast<ScalarNode>(keyVal.getKey());
-      if (!key) {
-        s.printError(keyVal.getKey(), "Expected scalar value");
-        return make_error_code(yaml_reader_error::illegal_value);
+    else if ( SequenceNode *seq = llvm::dyn_cast<SequenceNode>(node) ) {
+      if ( action ) {
+        _stream->printError(node, "unexpected sequence");
+        _error = make_error_code(yaml_reader_error::illegal_value);
       }
-      if (key->getValue(storage) == "name") {
-        ScalarNode *value = llvm::dyn_cast<ScalarNode>(keyVal.getValue());
-        if (!value) {
-          s.printError(keyVal.getValue(), "Expected scalar value");
-          return make_error_code(yaml_reader_error::illegal_value);
+      else {
+        for (Node &seqEntry : *seq ) {
+          this->parse(&seqEntry, StringRef("<any-seq-item>"));
+          if ( _error )
+            break;
         }
-        // FIXME: String lifetime.
-        mf->setName(value->getValue(storage));
-      } else if (key->getValue(storage) == "atoms") {
-        SequenceNode *atoms = llvm::dyn_cast<SequenceNode>(keyVal.getValue());
-        if (!atoms) {
-          s.printError(keyVal.getValue(), "Expected sequence");
-          return make_error_code(yaml_reader_error::illegal_value);
+      }
+    }
+    else if ( MappingNode *map = llvm::dyn_cast<MappingNode>(node) ) {
+      if ( action ) {
+        _stream->printError(node, "unexpected map");
+        _error = make_error_code(yaml_reader_error::illegal_value);
+      }
+      else {
+        llvm::SmallString<32> storage;
+        for (auto &keyVal : *map) {
+          ScalarNode *keyScalar = llvm::dyn_cast<ScalarNode>(keyVal.getKey());
+          llvm::StringRef keyStr = keyScalar->getValue(storage);
+          this->parse(keyVal.getValue(), keyStr, keyScalar);
+          if ( _error )
+            break;
         }
-        if (error_code ec = parseAtoms(atoms, s, p, *mf))
-          return ec;
-      } else {
-        s.printError(key, "Unrecognized key");
-        return make_error_code(yaml_reader_error::unknown_keyword);
       }
     }
-    f._memberFiles.push_back(std::move(mf));
+    else {
+      _stream->printError(node, "unexpected node type");
+      _error = make_error_code(yaml_reader_error::illegal_value);
+    }
+    this->returnToState(savedState, node);
+    return;
   }
-  return make_error_code(yaml_reader_error::success);
+  switch (_state) {
+    case inAtom:
+      _stream->printError(keywordNode, "Unknown atom attribute '" 
+                                        + keyword + ":'");
+      break;
+    case inFixUp:
+      _stream->printError(keywordNode, "Unknown fixup attribute '" 
+                                        + keyword + ":'");
+      break;
+    case inDoc:
+      _stream->printError(keywordNode, "Unknown file attribute '" 
+                                        + keyword + ":'");
+      break;
+    default:
+      _stream->printError(keywordNode, "Unknown keyword '" 
+                                        + keyword + ":'");
+  }
+  _error = make_error_code(yaml_reader_error::illegal_value);
 }
 
+
 /// parseObjectText - Parse the specified YAML formatted MemoryBuffer
 /// into lld::File object(s) and append each to the specified vector<File*>.
 error_code parseObjectText( llvm::MemoryBuffer *mb
-                          , Platform& platform
-                          , std::vector<std::unique_ptr<const File>> &result) {
-  using namespace llvm::yaml;
-  llvm::SourceMgr sm;
-  Stream stream(mb->getBuffer(), sm);
-
-  llvm::SmallString<32> storage;
-  for (Document &d : stream) {
-    std::unique_ptr<YAMLFile> CurFile(new YAMLFile);
-    if (llvm::isa<NullNode>(d.getRoot()))
+                    , Platform& platform
+                    , std::vector<std::unique_ptr<const File>> &result) {
+  llvm::SourceMgr       srcMgr;
+  llvm::yaml::Stream    stream(mb->getBuffer(), srcMgr);
+
+  for (llvm::yaml::Document &d : stream) {
+    std::unique_ptr<YAMLFile> curFile(new YAMLFile);
+    if (llvm::isa<llvm::yaml::NullNode>(d.getRoot()))
       continue; // Empty files are allowed.
-    MappingNode *n = llvm::dyn_cast<MappingNode>(d.getRoot());
-    if (!n) {
-      stream.printError(d.getRoot(), "Expected map");
-      return make_error_code(yaml_reader_error::illegal_value);
-    }
-    for (MappingNode::iterator mi = n->begin(), me = n->end(); mi != me; ++mi) {
-      ScalarNode *key = llvm::dyn_cast<ScalarNode>(mi->getKey());
-      if (!key) {
-        stream.printError(mi->getValue(), "Expected scalar value");
-        return make_error_code(yaml_reader_error::illegal_value);
-      }
-      if (key->getValue(storage) == "atoms") {
-        SequenceNode *Atoms = llvm::dyn_cast<SequenceNode>(mi->getValue());
-        if (!Atoms) {
-          stream.printError(mi->getValue(), "Expected sequence");
-          return make_error_code(yaml_reader_error::illegal_value);
-        }
-        if (error_code ec = parseAtoms(Atoms, stream, platform, *CurFile))
-          return ec;
-      } else if (key->getValue(storage) == "archive") {
-        CurFile->_kind = YAMLFile::kindArchiveLibrary;
-        SequenceNode *members = llvm::dyn_cast<SequenceNode>(mi->getValue());
-        if (!members) {
-          stream.printError(mi->getValue(), "Expected sequence");
-          return make_error_code(yaml_reader_error::illegal_value);
-        }
-        if (error_code ec = parseArchive( members
-                                        , stream
-                                        , platform
-                                        , *CurFile))
-          return ec;
-      } else {
-        stream.printError(key, "Unrecognized key");
-        return make_error_code(yaml_reader_error::unknown_keyword);
-      }
-    }
-    if (stream.failed())
+    YAMLState yamlState(platform, &stream, curFile.get());
+    yamlState.parse(d.getRoot(), StringRef("<root>"));
+
+    if ( stream.failed() ) 
       return make_error_code(yaml_reader_error::illegal_value);
-    CurFile->bindTargetReferences();
-    result.emplace_back(CurFile.release());
+    if ( yamlState.error() ) 
+      return yamlState.error();
+    
+    error_code ec = curFile->bindTargetReferences(stream);
+    if ( ec )
+      return ec;
+    result.emplace_back(curFile.release());
   }
 
   return make_error_code(yaml_reader_error::success);
 }
 
+
+
 //
 // Fill in vector<File*> from path to input text file.
 //
-error_code parseObjectTextFileOrSTDIN( StringRef path
-                                     , Platform&  platform
-                                     , std::vector<
-                                         std::unique_ptr<const File>>& result) {
+error_code 
+parseObjectTextFileOrSTDIN( StringRef path
+                          , Platform&  platform
+                          , std::vector<std::unique_ptr<const File>>& result) {
   OwningPtr<llvm::MemoryBuffer> mb;
   if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb))
     return ec;

Modified: lld/trunk/lib/Core/YamlWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlWriter.cpp?rev=156136&r1=156135&r2=156136&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlWriter.cpp (original)
+++ lld/trunk/lib/Core/YamlWriter.cpp Thu May  3 18:55:34 2012
@@ -164,9 +164,8 @@
     bool hasDash = false;
     if ( !atom.name().empty() ) {
       out   << "    - "
-            << KeyValues::nameKeyword
-            << ":"
-            << spacePadding(KeyValues::nameKeyword)
+            << "name:"
+            << spacePadding(strlen("name"))
             << atom.name()
             << "\n";
       hasDash = true;
@@ -174,9 +173,8 @@
 
     if ( _rnb.hasRefName(&atom) ) {
       out   << (hasDash ? "      " : "    - ")
-            << KeyValues::refNameKeyword
-            << ":"
-            << spacePadding(KeyValues::refNameKeyword)
+            << "ref-name:"
+            << spacePadding(strlen("ref-name"))
             << _rnb.refName(&atom)
             << "\n";
       hasDash = true;
@@ -184,9 +182,8 @@
 
     if ( atom.definition() != KeyValues::definitionDefault ) {
       out   << (hasDash ? "      " : "    - ")
-            << KeyValues::definitionKeyword
-            << ":"
-            << spacePadding(KeyValues::definitionKeyword)
+            << "definition:"
+            << spacePadding(strlen("definition"))
             << KeyValues::definition(atom.definition())
             << "\n";
       hasDash = true;
@@ -194,9 +191,8 @@
 
     if ( atom.scope() != KeyValues::scopeDefault ) {
       out   << (hasDash ? "      " : "    - ")
-            << KeyValues::scopeKeyword
-            << ":"
-            << spacePadding(KeyValues::scopeKeyword)
+            << "scope:"
+            << spacePadding(strlen("scope"))
             << KeyValues::scope(atom.scope())
             << "\n";
       hasDash = true;
@@ -204,70 +200,62 @@
 
      if ( atom.interposable() != KeyValues::interposableDefault ) {
       out   << "      "
-            << KeyValues::interposableKeyword
-            << ":"
-            << spacePadding(KeyValues::interposableKeyword)
+            << "interposable:"
+            << spacePadding(strlen("interposable"))
             << KeyValues::interposable(atom.interposable())
             << "\n";
     }
 
     if ( atom.merge() != KeyValues::mergeDefault ) {
       out   << "      "
-            << KeyValues::mergeKeyword
-            << ":"
-            << spacePadding(KeyValues::mergeKeyword)
+            << "merge:"
+            << spacePadding(strlen("merge"))
             << KeyValues::merge(atom.merge())
             << "\n";
     }
 
     if ( atom.contentType() != KeyValues::contentTypeDefault ) {
       out   << "      "
-            << KeyValues::contentTypeKeyword
-            << ":"
-            << spacePadding(KeyValues::contentTypeKeyword)
+            << "type:"
+            << spacePadding(strlen("type"))
             << KeyValues::contentType(atom.contentType())
             << "\n";
     }
 
     if ( atom.deadStrip() != KeyValues::deadStripKindDefault ) {
       out   << "      "
-            << KeyValues::deadStripKindKeyword
-            << ":"
-            << spacePadding(KeyValues::deadStripKindKeyword)
+            << "dead-strip:"
+            << spacePadding(strlen("dead-strip"))
             << KeyValues::deadStripKind(atom.deadStrip())
             << "\n";
     }
 
     if ( atom.sectionChoice() != KeyValues::sectionChoiceDefault ) {
       out   << "      "
-            << KeyValues::sectionChoiceKeyword
-            << ":"
-            << spacePadding(KeyValues::sectionChoiceKeyword)
+            << "section-choice:"
+            << spacePadding(strlen("section-choice"))
             << KeyValues::sectionChoice(atom.sectionChoice())
             << "\n";
       assert( ! atom.customSectionName().empty() );
       out   << "      "
-            << KeyValues::sectionNameKeyword
-            << ":"
-            << spacePadding(KeyValues::sectionNameKeyword)
+            << "section-name:"
+            << spacePadding(strlen("section-name"))
             << atom.customSectionName()
             << "\n";
     }
 
     if ( atom.isThumb() != KeyValues::isThumbDefault ) {
       out   << "      "
-            << KeyValues::isThumbKeyword
-            << ":"
-            << spacePadding(KeyValues::isThumbKeyword)
+            << "is-thumb:"
+            << spacePadding(strlen("is-thumb"))
             << KeyValues::isThumb(atom.isThumb())
             << "\n";
     }
 
     if ( atom.isAlias() != KeyValues::isAliasDefault ) {
       out   << "      "
-            << KeyValues::isAliasKeyword
-            << ":"
-            << spacePadding(KeyValues::isAliasKeyword)
+            << "is-alias:"
+            << spacePadding(strlen("is-alias"))
             << KeyValues::isAlias(atom.isAlias())
             << "\n";
     }
@@ -275,9 +263,8 @@
     if ( (atom.contentType() != DefinedAtom::typeZeroFill)
                                    && (atom.size() != 0) ) {
       out   << "      "
-            << KeyValues::contentKeyword
-            << ":"
-            << spacePadding(KeyValues::contentKeyword)
+            << "content:"
+            << spacePadding(strlen("content"))
             << "[ ";
       ArrayRef<uint8_t> arr = atom.rawContent();
       bool needComma = false;
@@ -301,15 +288,13 @@
         wroteFirstFixup = true;
       }
       out   << "      - "
-            << KeyValues::fixupsOffsetKeyword
-            << ":"
-            << spacePadding(KeyValues::fixupsOffsetKeyword)
+            << "offset:"
+            << spacePadding(strlen("offset"))
             << ref->offsetInAtom()
             << "\n";
       out   << "        "
-            << KeyValues::fixupsKindKeyword
-            << ":"
-            << spacePadding(KeyValues::fixupsKindKeyword)
+            << "kind:"
+            << spacePadding(strlen("kind"))
             << _platform.kindToString(ref->kind())
             << "\n";
       const Atom* target = ref->target();
@@ -319,17 +304,15 @@
           refName = _rnb.refName(target);
         assert(!refName.empty());
         out   << "        "
-              << KeyValues::fixupsTargetKeyword
-              << ":"
-              << spacePadding(KeyValues::fixupsTargetKeyword)
+              << "target:"
+              << spacePadding(strlen("target"))
               << refName
               << "\n";
       }
       if ( ref->addend() != 0 ) {
         out   << "        "
-              << KeyValues::fixupsAddendKeyword
-              << ":"
-              << spacePadding(KeyValues::fixupsAddendKeyword)
+              << "addend:"
+              << spacePadding(strlen("addend"))
               << ref->addend()
               << "\n";
       }
@@ -348,24 +331,21 @@
     }
 
     out   << "    - "
-          << KeyValues::nameKeyword
-          << ":"
-          << spacePadding(KeyValues::nameKeyword)
+          << "name:"
+          << spacePadding(strlen("name"))
           << atom.name()
           << "\n";
 
     out   << "      "
-          << KeyValues::definitionKeyword
-          << ":"
-          << spacePadding(KeyValues::definitionKeyword)
+          << "definition:"
+          << spacePadding(strlen("definition"))
           << KeyValues::definition(atom.definition())
           << "\n";
 
     if ( atom.canBeNull() != KeyValues::canBeNullDefault ) {
       out   << "      "
-            << KeyValues::canBeNullKeyword
-            << ":"
-            << spacePadding(KeyValues::canBeNullKeyword)
+            << "can-be-null:"
+            << spacePadding(strlen("can-be-null"))
             << KeyValues::canBeNull(atom.canBeNull())
             << "\n";
     }
@@ -382,33 +362,29 @@
     }
 
     out   << "    - "
-          << KeyValues::nameKeyword
-          << ":"
-          << spacePadding(KeyValues::nameKeyword)
+          << "name:"
+          << spacePadding(strlen("name"))
           << atom.name()
           << "\n";
 
     out   << "      "
-          << KeyValues::definitionKeyword
-          << ":"
-          << spacePadding(KeyValues::definitionKeyword)
+          << "definition:"
+          << spacePadding(strlen("definition"))
           << KeyValues::definition(atom.definition())
           << "\n";
 
     if ( !atom.loadName().empty() ) {
       out   << "      "
-            << KeyValues::loadNameKeyword
-            << ":"
-            << spacePadding(KeyValues::loadNameKeyword)
+            << "load-name:"
+            << spacePadding(strlen("load-name"))
             << atom.loadName()
             << "\n";
     }
 
     if ( atom.canBeNullAtRuntime() ) {
       out   << "      "
-            << KeyValues::canBeNullKeyword
-            << ":"
-            << spacePadding(KeyValues::canBeNullKeyword)
+            << "can-be-null:"
+            << spacePadding(strlen("can-be-null"))
             << KeyValues::canBeNull(UndefinedAtom::canBeNullAtRuntime)
             << "\n";
     }
@@ -425,23 +401,20 @@
     }
 
     out   << "    - "
-          << KeyValues::nameKeyword
-          << ":"
-          << spacePadding(KeyValues::nameKeyword)
+          << "name:"
+          << spacePadding(strlen("name"))
           << atom.name()
           << "\n";
 
     out   << "      "
-          << KeyValues::definitionKeyword
-          << ":"
-          << spacePadding(KeyValues::definitionKeyword)
+          << "definition:"
+          << spacePadding(strlen("definition"))
           << KeyValues::definition(atom.definition())
           << "\n";
 
     out   << "      "
-          << KeyValues::valueKeyword
-          << ":"
-          << spacePadding(KeyValues::valueKeyword)
+          << "value:"
+          << spacePadding(strlen("value"))
           << "0x";
      out.write_hex(atom.value());
      out << "\n";
@@ -450,10 +423,10 @@
 
 private:
   // return a string of the correct number of spaces to align value
-  const char* spacePadding(const char* key) {
+  const char* spacePadding(int keyLen) {
     const char* spaces = "                  ";
-    assert(strlen(spaces) > strlen(key));
-    return &spaces[strlen(key)];
+    assert(strlen(spaces) > keyLen);
+    return &spaces[keyLen];
   }
 
   char hexdigit(uint8_t nibble) {

Modified: lld/trunk/test/archive-tentdef-search.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/archive-tentdef-search.objtxt?rev=156136&r1=156135&r2=156136&view=diff
==============================================================================
--- lld/trunk/test/archive-tentdef-search.objtxt (original)
+++ lld/trunk/test/archive-tentdef-search.objtxt Thu May  3 18:55:34 2012
@@ -14,7 +14,7 @@
 
     - name:              bar
       scope:             global
-      content:           zero-fill
+      type:              zero-fill
       merge:             asTentative
 
 ---

Added: lld/trunk/test/error-atom-attribute.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/error-atom-attribute.objtxt?rev=156136&view=auto
==============================================================================
--- lld/trunk/test/error-atom-attribute.objtxt (added)
+++ lld/trunk/test/error-atom-attribute.objtxt Thu May  3 18:55:34 2012
@@ -0,0 +1,19 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN:   FileCheck < %t.err %s
+
+#
+# Test that unknown atom attribute produces a readable error.
+#
+
+---
+atoms:
+    - name:         entry
+      scope:        hidden
+      foobar:       true
+      dead-strip:   never
+  
+...
+
+
+# CHECK:       error: Unknown atom attribute
+# CHECK:       foobar

Added: lld/trunk/test/error-atom-content-byte-value.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/error-atom-content-byte-value.objtxt?rev=156136&view=auto
==============================================================================
--- lld/trunk/test/error-atom-content-byte-value.objtxt (added)
+++ lld/trunk/test/error-atom-content-byte-value.objtxt Thu May  3 18:55:34 2012
@@ -0,0 +1,18 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN:   FileCheck < %t.err %s
+
+#
+# Test that an invalid hex byte produces a readable error.
+#
+
+---
+atoms:
+    - name:         entry
+      scope:        hidden
+      content:      [ A5, 00, 4G, 1F ]
+  
+...
+
+
+# CHECK:       error: Invalid content hex byte
+# CHECK:       4G

Added: lld/trunk/test/error-atom-content-bytes.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/error-atom-content-bytes.objtxt?rev=156136&view=auto
==============================================================================
--- lld/trunk/test/error-atom-content-bytes.objtxt (added)
+++ lld/trunk/test/error-atom-content-bytes.objtxt Thu May  3 18:55:34 2012
@@ -0,0 +1,19 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN:   FileCheck < %t.err %s
+
+#
+# Test that an out of range byte value produces a readable error.
+#
+
+---
+atoms:
+    - name:         entry
+      scope:        hidden
+      content:      [ A5, 1234, 00, 4F ]
+  
+...
+
+
+# CHECK:       error: Content hex byte out of range
+# CHECK:       1234
+

Added: lld/trunk/test/error-atom-type.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/error-atom-type.objtxt?rev=156136&view=auto
==============================================================================
--- lld/trunk/test/error-atom-type.objtxt (added)
+++ lld/trunk/test/error-atom-type.objtxt Thu May  3 18:55:34 2012
@@ -0,0 +1,19 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN:   FileCheck < %t.err %s
+
+#
+# Test that an unknown content type produces a readable error.
+#
+
+---
+atoms:
+    - name:         entry
+      scope:        hidden
+      type:         superluminal
+      dead-strip:   never
+  
+...
+
+
+# CHECK:       error: Invalid value for 'type:'
+# CHECK:       superluminal

Added: lld/trunk/test/error-atom-undefined-wrong-attribue.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/error-atom-undefined-wrong-attribue.objtxt?rev=156136&view=auto
==============================================================================
--- lld/trunk/test/error-atom-undefined-wrong-attribue.objtxt (added)
+++ lld/trunk/test/error-atom-undefined-wrong-attribue.objtxt Thu May  3 18:55:34 2012
@@ -0,0 +1,18 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN:   FileCheck < %t.err %s
+
+#
+# Test that a defined attribute on an undefined atom produces a readable error.
+#
+
+---
+atoms:
+    - name:         foo
+      type:         code
+      definition:   undefined
+  
+...
+
+
+# CHECK: error: Undefined atom 'foo' has attributes only allowed on defined atoms
+

Added: lld/trunk/test/error-file-attribute.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/error-file-attribute.objtxt?rev=156136&view=auto
==============================================================================
--- lld/trunk/test/error-file-attribute.objtxt (added)
+++ lld/trunk/test/error-file-attribute.objtxt Thu May  3 18:55:34 2012
@@ -0,0 +1,18 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN:   FileCheck < %t.err %s
+
+#
+# Test that unknown file attribute produces a readable error.
+#
+
+---
+aardvark:           true
+atoms:
+    - name:         entry
+      scope:        hidden
+  
+...
+
+
+# CHECK:       error: Unknown file attribute
+# CHECK:       aardvark

Added: lld/trunk/test/error-fixup-attribute.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/error-fixup-attribute.objtxt?rev=156136&view=auto
==============================================================================
--- lld/trunk/test/error-fixup-attribute.objtxt (added)
+++ lld/trunk/test/error-fixup-attribute.objtxt Thu May  3 18:55:34 2012
@@ -0,0 +1,22 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN:   FileCheck < %t.err %s
+
+#
+# Test that unknown fixup attribute produces a readable error.
+#
+
+---
+atoms:
+    - name:          entry
+      scope:         hidden
+      fixups:
+      - offset:      3
+        kind:        3
+        weasel:      bar
+        addend:      100
+
+...
+
+
+# CHECK:       error: Unknown fixup attribute
+# CHECK:       weasel

Added: lld/trunk/test/error-fixup-target.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/error-fixup-target.objtxt?rev=156136&view=auto
==============================================================================
--- lld/trunk/test/error-fixup-target.objtxt (added)
+++ lld/trunk/test/error-fixup-target.objtxt Thu May  3 18:55:34 2012
@@ -0,0 +1,27 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN:   FileCheck < %t.err %s
+
+#
+# Test that unbindable target name produces a readable error.
+#
+
+---
+atoms:
+    - name:          entry
+      scope:         hidden
+      fixups:
+      - offset:      3
+        kind:        3
+        target:      bar
+      - offset:      5
+        kind:        3
+        target:      baz
+
+    - name:          bar
+      definition:    undefined
+
+...
+
+
+# CHECK:  error: Fixup has target 'baz' which does not exist
+# CHECK:      baz





More information about the llvm-commits mailing list