[llvm-commits] [lld] r155847 - in /lld/trunk: include/lld/Core/YamlReader.h lib/Core/YamlKeyValues.cpp lib/Core/YamlKeyValues.h lib/Core/YamlReader.cpp test/archive-basic.objtxt test/archive-chain.objtxt test/archive-tentdef-search.objtxt tools/lld-core/lld-core.cpp

Michael J. Spencer bigcheesegs at gmail.com
Mon Apr 30 14:20:14 PDT 2012


Author: mspencer
Date: Mon Apr 30 16:20:13 2012
New Revision: 155847

URL: http://llvm.org/viewvc/llvm-project?rev=155847&view=rev
Log:
Convert the YAMLReader to use LLVM/Support/YAMLParser.

Modified:
    lld/trunk/include/lld/Core/YamlReader.h
    lld/trunk/lib/Core/YamlKeyValues.cpp
    lld/trunk/lib/Core/YamlKeyValues.h
    lld/trunk/lib/Core/YamlReader.cpp
    lld/trunk/test/archive-basic.objtxt
    lld/trunk/test/archive-chain.objtxt
    lld/trunk/test/archive-tentdef-search.objtxt
    lld/trunk/tools/lld-core/lld-core.cpp

Modified: lld/trunk/include/lld/Core/YamlReader.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/YamlReader.h?rev=155847&r1=155846&r2=155847&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/YamlReader.h (original)
+++ lld/trunk/include/lld/Core/YamlReader.h Mon Apr 30 16:20:13 2012
@@ -14,6 +14,7 @@
 
 #include "llvm/Support/system_error.h"
 
+#include <memory>
 #include <vector>
 
 namespace llvm {
@@ -33,14 +34,15 @@
   /// the specified vector<File*>.
   error_code parseObjectTextFileOrSTDIN( StringRef path
                                        , Platform&
-                                       , std::vector<const File *>&);
+                                       , std::vector<
+                                           std::unique_ptr<const File>>&);
 
 
   /// 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&
-                            , std::vector<const File *>&);
+                            , std::vector<std::unique_ptr<const File>>&);
 
 } // namespace yaml
 } // namespace lld

Modified: lld/trunk/lib/Core/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=155847&r1=155846&r2=155847&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)
+++ lld/trunk/lib/Core/YamlKeyValues.cpp Mon Apr 30 16:20:13 2012
@@ -73,9 +73,9 @@
   { nullptr,          File::kindObject }
 };
 
- File::Kind KeyValues::fileKind(const char* str) {
+ File::Kind KeyValues::fileKind(StringRef str) {
   for (const FileKindMapping* p = fileKindMappings; p->string != nullptr; ++p) {
-    if ( strcmp(p->string, str) == 0 )
+    if (str == p->string)
       return p->value;
   }
   llvm::report_fatal_error("bad file kind value");
@@ -103,10 +103,10 @@
   { nullptr,          Atom::definitionRegular }
 };
 
-Atom::Definition KeyValues::definition(const char* s)
+Atom::Definition KeyValues::definition(StringRef s)
 {
   for (const DefinitionMapping* p = defMappings; p->string != nullptr; ++p) {
-    if ( strcmp(p->string, s) == 0 )
+    if (s == p->string)
       return p->value;
   }
   llvm::report_fatal_error("bad definition value");
@@ -136,10 +136,10 @@
   { nullptr,  DefinedAtom::scopeGlobal }
 };
 
-DefinedAtom::Scope KeyValues::scope(const char* s)
+DefinedAtom::Scope KeyValues::scope(StringRef s)
 {
   for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) {
-    if ( strcmp(p->string, s) == 0 )
+    if (s == p->string)
       return p->value;
   }
   llvm::report_fatal_error("bad scope value");
@@ -197,10 +197,10 @@
   { nullptr,          DefinedAtom::typeUnknown }
 };
 
-DefinedAtom::ContentType KeyValues::contentType(const char* s)
+DefinedAtom::ContentType KeyValues::contentType(StringRef s)
 {
   for (const ContentTypeMapping* p = typeMappings; p->string != nullptr; ++p) {
-    if ( strcmp(p->string, s) == 0 )
+    if (s == p->string)
       return p->value;
   }
   llvm::report_fatal_error("bad content type value");
@@ -232,11 +232,11 @@
   { nullptr,          DefinedAtom::deadStripNormal }
 };
 
-DefinedAtom::DeadStripKind KeyValues::deadStripKind(const char* s)
+DefinedAtom::DeadStripKind KeyValues::deadStripKind(StringRef s)
 {
   for (const DeadStripMapping* p = deadStripMappings; p->string != nullptr; ++p)
   {
-    if ( strcmp(p->string, s) == 0 )
+    if (s == p->string)
       return p->value;
   }
   llvm::report_fatal_error("bad dead strip value");
@@ -267,10 +267,10 @@
   { nullptr,        DefinedAtom::interposeNo }
 };
 
-DefinedAtom::Interposable KeyValues::interposable(const char* s)
+DefinedAtom::Interposable KeyValues::interposable(StringRef s)
 {
   for (const InterposableMapping* p = interMappings; p->string != nullptr; ++p){
-    if ( strcmp(p->string, s) == 0 )
+    if (s == p->string)
       return p->value;
   }
   llvm::report_fatal_error("bad interposable value");
@@ -302,10 +302,10 @@
   { nullptr,          DefinedAtom::mergeNo }
 };
 
-DefinedAtom::Merge KeyValues::merge(const char* s)
+DefinedAtom::Merge KeyValues::merge(StringRef s)
 {
   for (const MergeMapping* p = mergeMappings; p->string != nullptr; ++p) {
-    if ( strcmp(p->string, s) == 0 )
+    if (s == p->string)
       return p->value;
   }
   llvm::report_fatal_error("bad merge value");
@@ -336,10 +336,10 @@
   { nullptr,           DefinedAtom::sectionBasedOnContent }
 };
 
-DefinedAtom::SectionChoice KeyValues::sectionChoice(const char* s)
+DefinedAtom::SectionChoice KeyValues::sectionChoice(StringRef s)
 {
   for (const SectionChoiceMapping* p = sectMappings; p->string != nullptr; ++p){
-    if ( strcmp(p->string, s) == 0 )
+    if (s == p->string)
       return p->value;
   }
   llvm::report_fatal_error("bad dead strip value");
@@ -373,10 +373,10 @@
   { nullptr,           DefinedAtom::perm___ }
 };
 
-DefinedAtom::ContentPermissions KeyValues::permissions(const char* s)
+DefinedAtom::ContentPermissions KeyValues::permissions(StringRef s)
 {
   for (const PermissionsMapping* p = permMappings; p->string != nullptr; ++p) {
-    if ( strcmp(p->string, s) == 0 )
+    if (s == p->string)
       return p->value;
   }
   llvm::report_fatal_error("bad permissions value");
@@ -390,37 +390,10 @@
   llvm::report_fatal_error("bad permissions value");
 }
 
-
-
-
-
-
-
-bool KeyValues::isThumb(const char* s)
-{
-  if ( strcmp(s, "true") == 0 )
-    return true;
-  else if ( strcmp(s, "false") == 0 )
-    return false;
-  llvm::report_fatal_error("bad is-thumb value");
-}
-
 const char* KeyValues::isThumb(bool b) {
   return b ? "true" : "false";
 }
 
-
-
-
-bool KeyValues::isAlias(const char* s)
-{
-  if ( strcmp(s, "true") == 0 )
-    return true;
-  else if ( strcmp(s, "false") == 0 )
-    return false;
-  llvm::report_fatal_error("bad is-alias value");
-}
-
 const char* KeyValues::isAlias(bool b) {
   return b ? "true" : "false";
 }
@@ -441,10 +414,10 @@
 };
 
 
-UndefinedAtom::CanBeNull KeyValues::canBeNull(const char* s)
+UndefinedAtom::CanBeNull KeyValues::canBeNull(StringRef s)
 {
   for (const CanBeNullMapping* p = cbnMappings; p->string != nullptr; ++p) {
-    if ( strcmp(p->string, s) == 0 )
+    if (s == p->string)
       return p->value;
   }
   llvm::report_fatal_error("bad can-be-null value");

Modified: lld/trunk/lib/Core/YamlKeyValues.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.h?rev=155847&r1=155846&r2=155847&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.h (original)
+++ lld/trunk/lib/Core/YamlKeyValues.h Mon Apr 30 16:20:13 2012
@@ -15,7 +15,6 @@
 #include "lld/Core/UndefinedAtom.h"
 #include "lld/Core/File.h"
 
-
 namespace lld {
 namespace yaml {
 
@@ -34,62 +33,60 @@
 
   static const char* const                fileKindKeyword;
   static const File::Kind                 fileKindDefault;
-  static File::Kind                       fileKind(const char*);
+  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(const char*);
+  static Atom::Definition                 definition(StringRef);
   static const char*                      definition(Atom::Definition);
 
   static const char* const                scopeKeyword;
   static const DefinedAtom::Scope         scopeDefault;
-  static DefinedAtom::Scope               scope(const char*);
+  static DefinedAtom::Scope               scope(StringRef);
   static const char*                      scope(DefinedAtom::Scope);
 
   static const char* const                contentTypeKeyword;
   static const DefinedAtom::ContentType   contentTypeDefault;
-  static DefinedAtom::ContentType         contentType(const char*);
+  static DefinedAtom::ContentType         contentType(StringRef);
   static const char*                      contentType(DefinedAtom::ContentType);
 
   static const char* const                deadStripKindKeyword;
   static const DefinedAtom::DeadStripKind deadStripKindDefault;
-  static DefinedAtom::DeadStripKind       deadStripKind(const char*);
+  static DefinedAtom::DeadStripKind       deadStripKind(StringRef);
   static const char*                      deadStripKind(DefinedAtom::DeadStripKind);
 
   static const char* const                sectionChoiceKeyword;
   static const DefinedAtom::SectionChoice sectionChoiceDefault;
-  static DefinedAtom::SectionChoice       sectionChoice(const char*);
+  static DefinedAtom::SectionChoice       sectionChoice(StringRef);
   static const char*                      sectionChoice(DefinedAtom::SectionChoice);
 
   static const char* const                interposableKeyword;
   static const DefinedAtom::Interposable  interposableDefault;
-  static DefinedAtom::Interposable        interposable(const char*);
+  static DefinedAtom::Interposable        interposable(StringRef);
   static const char*                      interposable(DefinedAtom::Interposable);
 
   static const char* const                mergeKeyword;
   static const DefinedAtom::Merge         mergeDefault;
-  static DefinedAtom::Merge               merge(const char*);
+  static DefinedAtom::Merge               merge(StringRef);
   static const char*                      merge(DefinedAtom::Merge);
 
   static const char* const                      permissionsKeyword;
   static const DefinedAtom::ContentPermissions  permissionsDefault;
-  static DefinedAtom::ContentPermissions        permissions(const char*);
+  static DefinedAtom::ContentPermissions        permissions(StringRef);
   static const char*                            permissions(DefinedAtom::ContentPermissions);
 
   static const char* const                isThumbKeyword;
   static const bool                       isThumbDefault;
-  static bool                             isThumb(const char*);
   static const char*                      isThumb(bool);
 
   static const char* const                isAliasKeyword;
   static const bool                       isAliasDefault;
-  static bool                             isAlias(const char*);
   static const char*                      isAlias(bool);
 
   static const char* const                canBeNullKeyword;
   static const UndefinedAtom::CanBeNull   canBeNullDefault;
-  static UndefinedAtom::CanBeNull         canBeNull(const char*);
+  static UndefinedAtom::CanBeNull         canBeNull(StringRef);
   static const char*                      canBeNull(UndefinedAtom::CanBeNull);
 
 
@@ -104,4 +101,3 @@
 } // namespace lld
 
 #endif // LLD_CORE_YAML_KEY_VALUES_H_
-

Modified: lld/trunk/lib/Core/YamlReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=155847&r1=155846&r2=155847&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlReader.cpp (original)
+++ lld/trunk/lib/Core/YamlReader.cpp Mon Apr 30 16:20:13 2012
@@ -24,244 +24,54 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/system_error.h"
+#include "llvm/Support/YAMLParser.h"
 
 #include <cstring>
-#include <vector>
 #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 {
 
-namespace {
-
-class YAML {
-public:
-  struct Entry {
-    Entry(const char *k, const char *v, std::vector<uint8_t>* vs,
-          int d, bool bd, bool bs)
-      : key(strdup(k))
-      , value(v ? strdup(v) : nullptr)
-      , valueSequenceBytes(vs)
-      , depth(d)
-      , beginSequence(bs)
-      , beginDocument(bd) {}
-
-    const char *          key;
-    const char *          value;
-    std::vector<uint8_t>* valueSequenceBytes;
-    int                   depth;
-    bool                  beginSequence;
-    bool                  beginDocument;
-  };
-
-  static void parse(llvm::MemoryBuffer *mb, std::vector<const Entry *>&);
-
-private:
-  enum State {
-    start,
-    inHeaderComment,
-    inTripleDash,
-    inTriplePeriod,
-    inDocument,
-    inKey,
-    inSpaceBeforeValue,
-    inValue,
-    inValueSequence,
-    inValueSequenceEnd
-  };
-};
-
-
-void YAML::parse(llvm::MemoryBuffer *mb, std::vector<const Entry *> &entries) {
-  State state = start;
-  char key[64];
-  char value[64];
-  char *p = nullptr;
-  unsigned int lineNumber = 1;
-  int depth = 0;
-  bool nextKeyIsStartOfDocument = false;
-  bool nextKeyIsStartOfSequence = false;
-  std::vector<uint8_t>* sequenceBytes = nullptr;
-  unsigned contentByte = 0;
-  for (const char *s = mb->getBufferStart(); s < mb->getBufferEnd(); ++s) {
-    char c = *s;
-    if (c == '\n')
-      ++lineNumber;
-    switch (state) {
-    case start:
-      if (c == '#')
-        state = inHeaderComment;
-      else if (c == '-') {
-        p = &key[0];
-        *p++ = c;
-        state = inTripleDash;
-      }
-      break;
-    case inHeaderComment:
-      if (c == '\n') {
-        state = start;
-      }
-      break;
-    case inTripleDash:
-      if (c == '-') {
-        *p++ = c;
-      } else if (c == '\n') {
-        *p = '\0';
-        if (strcmp(key, "---") != 0)
-          return;
-        depth = 0;
-        state = inDocument;
-        nextKeyIsStartOfDocument = true;
-      } else {
-        return;
-      }
-      break;
-    case inTriplePeriod:
-      if (c == '.') {
-        *p++ = c;
-      } else if (c == '\n') {
-        *p = '\0';
-        if (strcmp(key, "...") != 0)
-          return;
-        depth = 0;
-        state = inHeaderComment;
-      } else {
-        return;
-      }
-      break;
-    case inDocument:
-      if (isalnum(c)) {
-        state = inKey;
-        p = &key[0];
-        *p++ = c;
-      } else if (c == '-') {
-        if (depth == 0) {
-          p = &key[0];
-          *p++ = c;
-          state = inTripleDash;
-        } else {
-          nextKeyIsStartOfSequence = true;
-          ++depth;
-        }
-      } else if (c == ' ') {
-        ++depth;
-      } else if (c == '.') {
-        p = &key[0];
-        *p++ = c;
-        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 {
-        return;
-      }
-      break;
-    case inKey:
-      if (isalnum(c) || (c == '-')) {
-        *p++ = c;
-      } else if (c == ':') {
-        *p = '\0';
-        state = inSpaceBeforeValue;
-      } else if (c == '\n') {
-        *p = '\0';
-        if (strcmp(key, "---") == 0)
-          state = inDocument;
-        else
-          return;
-      } else {
-        return;
-      }
-      break;
-    case inSpaceBeforeValue:
-      if (isalnum(c) || (c == '-') || (c == '_') || (c == '/')) {
-        p = &value[0];
-        *p++ = c;
-        state = inValue;
-      } else if (c == '\n') {
-        entries.push_back(new Entry(key, "", nullptr, depth,
-                                    nextKeyIsStartOfDocument,
-                                    nextKeyIsStartOfSequence));
-        nextKeyIsStartOfSequence = false;
-        nextKeyIsStartOfDocument = false;
-        state = inDocument;
-        depth = 0;
-      } else if (c == '[') {
-        contentByte = 0;
-        sequenceBytes = new std::vector<uint8_t>();
-        state = inValueSequence;
-      } else if (c == ' ') {
-        // eat space
-      } else if (c == '\t') {
-        llvm::report_fatal_error("TAB character found in yaml file");
-      } else {
-        return;
-      }
-      break;
-    case inValue:
-      if (c == '\n') {
-        *p = '\0';
-        entries.push_back(new Entry(key, value, nullptr, depth,
-                                    nextKeyIsStartOfDocument,
-                                    nextKeyIsStartOfSequence));
-        nextKeyIsStartOfSequence = false;
-        nextKeyIsStartOfDocument = false;
-        state = inDocument;
-        depth = 0;
-      }
-      else {
-        *p++ = c;
-      }
-      break;
-    case inValueSequence:
-      if (c == ']') {
-        sequenceBytes->push_back(contentByte);
-        state = inValueSequenceEnd;
-      }
-      else if ( (c == ' ') || (c == '\n') ) {
-        // eat white space
-      }
-      else if (c == ',') {
-        sequenceBytes->push_back(contentByte);
-      }
-      else if ( isdigit(c) ) {
-        contentByte = (contentByte << 4) | (c-'0');
-      }
-      else if ( ('a' <= tolower(c)) && (tolower(c) <= 'f') ) {
-        contentByte = (contentByte << 4) | (tolower(c)-'a'+10);
-      }
-      else {
-        llvm::report_fatal_error("non-hex digit found in content [ ]");
-      }
-      break;
-    case inValueSequenceEnd:
-      if (c == '\n') {
-        entries.push_back(new Entry(key, nullptr, sequenceBytes, depth,
-                                    nextKeyIsStartOfDocument,
-                                    nextKeyIsStartOfSequence));
-        nextKeyIsStartOfSequence = false;
-        nextKeyIsStartOfDocument = false;
-        state = inDocument;
-        depth = 0;
-      }
-      break;
-    }
-  }
-}
-
-
-
 class YAMLReference : public Reference {
 public:
-                YAMLReference() : _target(nullptr), _targetName(nullptr),
-                                   _offsetInAtom(0), _addend(0), _kind(0) { }
+  YAMLReference()
+    : _target(nullptr)
+    , _offsetInAtom(0)
+    , _addend(0)
+    , _kind(0)
+  {}
 
   virtual uint64_t offsetInAtom() const {
     return _offsetInAtom;
@@ -275,7 +85,7 @@
     _kind = k;
   }
 
-  virtual const Atom* target() const {
+  virtual const Atom *target() const {
     return _target;
   }
 
@@ -287,19 +97,17 @@
     _addend = a;
   }
 
-  virtual void setTarget(const Atom* newAtom) {
+  virtual void setTarget(const Atom *newAtom) {
     _target = newAtom;
   }
 
-  const Atom*  _target;
-  const char*  _targetName;
-  uint64_t     _offsetInAtom;
-  Addend       _addend;
-  Kind         _kind;
+  const Atom *_target;
+  StringRef   _targetName;
+  uint64_t    _offsetInAtom;
+  Addend      _addend;
+  Kind        _kind;
 };
 
-
-
 class YAMLDefinedAtom;
 
 class YAMLFile : public ArchiveLibraryFile {
@@ -315,16 +123,16 @@
     return _kind;
   }
 
-  virtual const atom_collection<DefinedAtom>& defined() const {
+  virtual const atom_collection<DefinedAtom> &defined() const {
     return _definedAtoms;
   }
-  virtual const atom_collection<UndefinedAtom>& undefined() const {
+  virtual const atom_collection<UndefinedAtom> &undefined() const {
     return _undefinedAtoms;
   }
-  virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
+  virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
     return _sharedLibraryAtoms;
   }
-  virtual const atom_collection<AbsoluteAtom>& absolute() const {
+  virtual const atom_collection<AbsoluteAtom> &absolute() const {
     return _absoluteAtoms;
   }
 
@@ -335,39 +143,37 @@
   virtual const File *find(StringRef name, bool dataSymbolOnly) const;
 
   void bindTargetReferences();
-  void addDefinedAtom(YAMLDefinedAtom* atom, const char* refName);
-  void addUndefinedAtom(UndefinedAtom* atom);
-  void addSharedLibraryAtom(SharedLibraryAtom* atom);
-  void addAbsoluteAtom(AbsoluteAtom* atom);
-  Atom* findAtom(const char* name);
-  void addMember(const char*);
-  void setName(const char*);
+  void addDefinedAtom(YAMLDefinedAtom *atom, StringRef refName);
+  void addUndefinedAtom(UndefinedAtom *atom);
+  void addSharedLibraryAtom(SharedLibraryAtom *atom);
+  void addAbsoluteAtom(AbsoluteAtom *atom);
+  Atom *findAtom(StringRef name);
+  void addMember(StringRef);
+  void setName(StringRef);
 
   struct NameAtomPair {
-                 NameAtomPair(const char* n, Atom* a) : name(n), atom(a) {}
-    const char*  name;
-    Atom*        atom;
+                 NameAtomPair(StringRef n, Atom *a) : name(n), atom(a) {}
+    StringRef name;
+    Atom     *atom;
   };
 
-  atom_collection_vector<DefinedAtom>         _definedAtoms;
-  atom_collection_vector<UndefinedAtom>       _undefinedAtoms;
-  atom_collection_vector<SharedLibraryAtom>   _sharedLibraryAtoms;
-  atom_collection_vector<AbsoluteAtom>        _absoluteAtoms;
-  std::vector<YAMLReference>                  _references;
-  std::vector<NameAtomPair>                   _nameToAtomMapping;
-  std::vector<const char*>                    _memberNames;
-  std::vector<YAMLFile*>                      _memberFiles;
-  unsigned int                                _lastRefIndex;
-  File::Kind                                  _kind;
-  bool                                        _inArchive;
+  atom_collection_vector<DefinedAtom>       _definedAtoms;
+  atom_collection_vector<UndefinedAtom>     _undefinedAtoms;
+  atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
+  atom_collection_vector<AbsoluteAtom>      _absoluteAtoms;
+  std::vector<YAMLReference>                _references;
+  std::vector<NameAtomPair>                 _nameToAtomMapping;
+  std::vector<StringRef>                    _memberNames;
+  std::vector<std::unique_ptr<YAMLFile>>    _memberFiles;
+  unsigned int                              _lastRefIndex;
+  File::Kind                                _kind;
+  bool                                      _inArchive;
 };
 
-
-
 class YAMLDefinedAtom : public DefinedAtom {
 public:
   YAMLDefinedAtom( uint32_t ord
-          , YAMLFile& file
+          , YAMLFile &file
           , DefinedAtom::Scope scope
           , DefinedAtom::ContentType type
           , DefinedAtom::SectionChoice sectionChoice
@@ -378,16 +184,16 @@
           , bool isThumb
           , bool isAlias
           , DefinedAtom::Alignment alignment
-          , const char* name
-          , const char* sectionName
+          , 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(content)
+    , _content(std::move(content))
     , _alignment(alignment)
     , _scope(scope)
     , _type(type)
@@ -403,19 +209,16 @@
     file._lastRefIndex = _refEndIndex;
   }
 
-  virtual const class File& file() const {
+  virtual const class File &file() const {
     return _file;
   }
 
   virtual StringRef name() const {
-    if (_name == nullptr)
-      return StringRef();
-    else
-      return _name;
+    return _name;
   }
 
- virtual uint64_t size() const {
-    return (_content ? _content->size() : _size);
+  virtual uint64_t size() const {
+    return _content.empty() ? _size : _content.size();
   }
 
   virtual DefinedAtom::Scope scope() const {
@@ -462,11 +265,8 @@
     return _isAlias;
   }
 
- ArrayRef<uint8_t> rawContent() const {
-    if (_content != nullptr)
-      return ArrayRef<uint8_t>(*_content);
-    else
-      return ArrayRef<uint8_t>();
+  ArrayRef<uint8_t> rawContent() const {
+    return ArrayRef<uint8_t>(_content);
   }
 
   virtual uint64_t ordinal() const {
@@ -499,23 +299,21 @@
     it = reinterpret_cast<const void*>(index);
   }
 
-
-
   void bindTargetReferences() const {
     for (unsigned int i=_refStartIndex; i < _refEndIndex; ++i) {
-      const char* targetName = _file._references[i]._targetName;
-      Atom* targetAtom = _file.findAtom(targetName);
+      StringRef targetName = _file._references[i]._targetName;
+      Atom *targetAtom = _file.findAtom(targetName);
       _file._references[i]._target = targetAtom;
     }
   }
 
 private:
-  YAMLFile&                   _file;
-  const char *                _name;
-  const char *                _sectionName;
+  YAMLFile                   &_file;
+  StringRef                   _name;
+  StringRef                   _sectionName;
   unsigned long               _size;
   uint32_t                    _ord;
-  std::vector<uint8_t>*       _content;
+  std::vector<uint8_t>        _content;
   DefinedAtom::Alignment      _alignment;
   DefinedAtom::Scope          _scope;
   DefinedAtom::ContentType    _type;
@@ -530,14 +328,19 @@
   unsigned int                _refEndIndex;
 };
 
-
 class YAMLUndefinedAtom : public UndefinedAtom {
 public:
-        YAMLUndefinedAtom(YAMLFile& f, int32_t ord, const char* nm,
-                          UndefinedAtom::CanBeNull cbn)
-            : _file(f), _name(nm), _ordinal(ord), _canBeNull(cbn) { }
+  YAMLUndefinedAtom( YAMLFile &f
+                   , int32_t ord
+                   , StringRef name
+                   , UndefinedAtom::CanBeNull cbn)
+    : _file(f)
+    , _name(name)
+    , _ordinal(ord)
+    , _canBeNull(cbn) {
+  }
 
-  virtual const class File& file() const {
+  virtual const class File &file() const {
     return _file;
   }
 
@@ -549,24 +352,28 @@
     return _canBeNull;
   }
 
-
 private:
-  YAMLFile&                   _file;
-  const char *                _name;
-  uint32_t                    _ordinal;
-  UndefinedAtom::CanBeNull     _canBeNull;
+  YAMLFile                &_file;
+  StringRef                _name;
+  uint32_t                 _ordinal;
+  UndefinedAtom::CanBeNull _canBeNull;
 };
 
-
-
 class YAMLSharedLibraryAtom : public SharedLibraryAtom {
 public:
-        YAMLSharedLibraryAtom(YAMLFile& f, int32_t ord, const char* nm,
-                                const char* ldnm, bool cbn)
-            : _file(f), _name(nm), _ordinal(ord),
-              _loadName(ldnm), _canBeNull(cbn) { }
+  YAMLSharedLibraryAtom( YAMLFile &f
+                       , int32_t ord
+                       , StringRef name
+                       , StringRef loadName
+                       , bool cbn)
+    : _file(f)
+    , _name(name)
+    , _ordinal(ord)
+    , _loadName(loadName)
+    , _canBeNull(cbn) {
+  }
 
-  virtual const class File& file() const {
+  virtual const class File &file() const {
     return _file;
   }
 
@@ -575,33 +382,31 @@
   }
 
   virtual StringRef loadName() const {
-    if ( _loadName == nullptr )
-      return StringRef();
-    else
-      return StringRef(_loadName);
+    return _loadName;
   }
 
   virtual bool canBeNullAtRuntime() const {
     return _canBeNull;
   }
 
-
 private:
-  YAMLFile&                   _file;
-  const char *                _name;
-  uint32_t                    _ordinal;
-  const char *                _loadName;
-  bool                        _canBeNull;
+  YAMLFile &_file;
+  StringRef _name;
+  uint32_t  _ordinal;
+  StringRef _loadName;
+  bool      _canBeNull;
 };
 
-
-
 class YAMLAbsoluteAtom : public AbsoluteAtom {
 public:
-        YAMLAbsoluteAtom(YAMLFile& f, int32_t ord, const char* nm, uint64_t v)
-            : _file(f), _name(nm), _ordinal(ord), _value(v) { }
+  YAMLAbsoluteAtom(YAMLFile &f, int32_t ord, StringRef name, uint64_t v)
+    : _file(f)
+    , _name(name)
+    , _ordinal(ord)
+    , _value(v) {
+  }
 
-  virtual const class File& file() const {
+  virtual const class File &file() const {
     return _file;
   }
 
@@ -614,95 +419,89 @@
   }
 
 private:
-  YAMLFile&        _file;
-  const char *     _name;
-  uint32_t         _ordinal;
-  uint64_t         _value;
+  YAMLFile &_file;
+  StringRef _name;
+  uint32_t  _ordinal;
+  uint64_t  _value;
 };
 
-
-
 void YAMLFile::bindTargetReferences() {
-    for (const DefinedAtom *defAtom : _definedAtoms) {
-      const YAMLDefinedAtom* atom =
-                          reinterpret_cast<const YAMLDefinedAtom*>(defAtom);
-      atom->bindTargetReferences();
-    }
+  for (const DefinedAtom *defAtom : _definedAtoms) {
+    const YAMLDefinedAtom *atom =
+      reinterpret_cast<const YAMLDefinedAtom*>(defAtom);
+    atom->bindTargetReferences();
+  }
 }
 
-Atom* YAMLFile::findAtom(const char* name) {
-  for (std::vector<NameAtomPair>::const_iterator it = _nameToAtomMapping.begin();
-                                    it != _nameToAtomMapping.end(); ++it) {
-    if ( strcmp(name, it->name) == 0 )
-      return it->atom;
+Atom *YAMLFile::findAtom(StringRef name) {
+  for (auto &ci : _nameToAtomMapping) {
+    if (ci.name == name)
+      return ci.atom;
   }
   llvm::report_fatal_error("reference to atom that does not exist");
 }
 
-void YAMLFile::addDefinedAtom(YAMLDefinedAtom* atom, const char* refName) {
+void YAMLFile::addDefinedAtom(YAMLDefinedAtom *atom, StringRef refName) {
   _definedAtoms._atoms.push_back(atom);
-  assert(refName != nullptr);
   _nameToAtomMapping.push_back(NameAtomPair(refName, atom));
 }
 
-void YAMLFile::addUndefinedAtom(UndefinedAtom* atom) {
+void YAMLFile::addUndefinedAtom(UndefinedAtom *atom) {
   _undefinedAtoms._atoms.push_back(atom);
-  _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
+  _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom));
 }
 
-void YAMLFile::addSharedLibraryAtom(SharedLibraryAtom* atom) {
+void YAMLFile::addSharedLibraryAtom(SharedLibraryAtom *atom) {
   _sharedLibraryAtoms._atoms.push_back(atom);
-  _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
+  _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom));
 }
 
-void YAMLFile::addAbsoluteAtom(AbsoluteAtom* atom) {
+void YAMLFile::addAbsoluteAtom(AbsoluteAtom *atom) {
   _absoluteAtoms._atoms.push_back(atom);
-  _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
+  _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom));
 }
 
-void YAMLFile::addMember(const char* name) {
+void YAMLFile::addMember(StringRef name) {
   _memberNames.push_back(name);
 }
 
-void YAMLFile::setName(const char* name) {
+void YAMLFile::setName(StringRef name) {
   _path = StringRef(name);
 }
 
 const File *YAMLFile::find(StringRef name, bool dataSymbolOnly) const {
-  for (YAMLFile *file : _memberFiles) {
+  for (auto &file : _memberFiles) {
     for (const DefinedAtom *atom : file->defined() ) {
-      if ( name.equals(atom->name()) )
-        return file;
+      if (name == atom->name())
+        return file.get();
     }
   }
-  return NULL;
+  return nullptr;
 }
 
-
-
 class YAMLAtomState {
 public:
-  YAMLAtomState(Platform& platform);
+  YAMLAtomState(Platform &platform);
 
-  void setName(const char *n);
-  void setRefName(const char *n);
-  void setAlign2(const char *n);
+  void setName(StringRef n);
+  void setRefName(StringRef n);
+  void setAlign2(StringRef n);
 
-  void setFixupKind(const char *n);
-  void setFixupTarget(const char *n);
+  void setFixupKind(StringRef n);
+  void setFixupTarget(StringRef n);
   void addFixup(YAMLFile *f);
 
   void makeAtom(YAMLFile&);
 
-  Platform&                   _platform;
-  const char *                _name;
-  const char *                _refName;
-  const char *                _sectionName;
-  const char*                 _loadName;
+  Platform                   &_platform;
+  StringRef                   _name;
+  StringRef                   _refName;
+  StringRef                   _sectionName;
+  StringRef                   _loadName;
   unsigned long long          _size;
   uint64_t                    _value;
   uint32_t                    _ordinal;
-  std::vector<uint8_t>*       _content;
+  std::vector<uint8_t>        _content;
   DefinedAtom::Alignment      _alignment;
   Atom::Definition            _definition;
   DefinedAtom::Scope          _scope;
@@ -719,16 +518,11 @@
 };
 
 
-YAMLAtomState::YAMLAtomState(Platform& platform)
+YAMLAtomState::YAMLAtomState(Platform &platform)
   : _platform(platform)
-  , _name(nullptr)
-  , _refName(nullptr)
-  , _sectionName(nullptr)
-  , _loadName(nullptr)
   , _size(0)
   , _value(0)
   , _ordinal(0)
-  , _content(nullptr)
   , _alignment(0, 0)
   , _definition(KeyValues::definitionDefault)
   , _scope(KeyValues::scopeDefault)
@@ -740,357 +534,415 @@
   , _permissions(KeyValues::permissionsDefault)
   , _isThumb(KeyValues::isThumbDefault)
   , _isAlias(KeyValues::isAliasDefault)
-  , _canBeNull(KeyValues::canBeNullDefault)
-  {
-  }
-
+  , _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 ? _refName : _name);
+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 ) {
+  } else if (_definition == Atom::definitionUndefined) {
     UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _canBeNull);
     f.addUndefinedAtom(a);
     ++_ordinal;
-  }
-  else if ( _definition == Atom::definitionSharedLibrary ) {
+  } 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 ) {
+  } else if (_definition == Atom::definitionAbsolute) {
     AbsoluteAtom *a = new YAMLAbsoluteAtom(f, _ordinal, _name, _value);
     f.addAbsoluteAtom(a);
     ++_ordinal;
   }
 
   // reset state for next atom
-  _name             = nullptr;
-  _refName          = nullptr;
-  _sectionName      = nullptr;
-  _loadName         = nullptr;
-  _size             = 0;
-  _value            = 0;
-  _ordinal          = 0;
-  _content          = nullptr;
-  _alignment.powerOf2= 0;
-  _alignment.modulus = 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;
-  _ref._target       = nullptr;
-  _ref._targetName   = nullptr;
-  _ref._addend       = 0;
-  _ref._offsetInAtom = 0;
-  _ref._kind         = 0;
+  _name               = StringRef();
+  _refName            = StringRef();
+  _sectionName        = StringRef();
+  _loadName           = StringRef();
+  _size               = 0;
+  _value              = 0;
+  _ordinal            = 0;
+  _content.clear();
+  _alignment.powerOf2 = 0;
+  _alignment.modulus  = 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;
+  _ref._target        = nullptr;
+  _ref._targetName    = StringRef();
+  _ref._addend        = 0;
+  _ref._offsetInAtom  = 0;
+  _ref._kind          = 0;
 }
 
-void YAMLAtomState::setName(const char *n) {
+void YAMLAtomState::setName(StringRef n) {
   _name = n;
 }
 
-void YAMLAtomState::setRefName(const char *n) {
+void YAMLAtomState::setRefName(StringRef n) {
   _refName = n;
 }
 
-void YAMLAtomState::setAlign2(const char *s) {
+void YAMLAtomState::setAlign2(StringRef s) {
   if (StringRef(s).getAsInteger(10, _alignment.powerOf2))
     _alignment.powerOf2 = 1;
 }
 
-void YAMLAtomState::setFixupKind(const char *s) {
+void YAMLAtomState::setFixupKind(StringRef s) {
   _ref._kind = _platform.kindFromString(StringRef(s));
 }
 
-void YAMLAtomState::setFixupTarget(const char *s) {
+void YAMLAtomState::setFixupTarget(StringRef s) {
   _ref._targetName = s;
 }
 
-
 void YAMLAtomState::addFixup(YAMLFile *f) {
   f->_references.push_back(_ref);
   // clear for next ref
   _ref._target       = nullptr;
-  _ref._targetName   = nullptr;
+  _ref._targetName   = StringRef();
   _ref._addend       = 0;
   _ref._offsetInAtom = 0;
   _ref._kind         = 0;
 }
 
-
-} // anonymous namespace
-
-
-
-
-
-/// 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<const File *> &result) {
-  std::vector<const YAML::Entry *> entries;
-  std::vector<YAMLFile*> allFiles;
-  YAML::parse(mb, entries);
-
-  YAMLFile *file = nullptr;
-  YAMLAtomState atomState(platform);
-  bool inAtoms       = false;
-  bool inFixups      = false;
-  bool inMembers     = false;
-  int depthForAtoms  = -1;
-  int depthForFixups = -1;
-  int depthForMembers= -1;
-  int lastDepth      = -1;
-  bool haveAtom      = false;
-  bool haveFixup     = false;
-  bool hasArchives = false;
-
-  for (std::vector<const YAML::Entry *>::iterator it = entries.begin();
-       it != entries.end(); ++it) {
-    const YAML::Entry *entry = *it;
-
-    if (entry->beginDocument) {
-      if (file != nullptr) {
-        if (haveAtom) {
-          atomState.makeAtom(*file);
-          haveAtom = false;
-        }
-        file->bindTargetReferences();
-        allFiles.push_back(file);
-      }
-      file = new YAMLFile();
-      inAtoms = false;
-      depthForAtoms = -1;
-    }
-    if (lastDepth > entry->depth) {
-      // end of fixup sequence
-      if (haveFixup) {
-        atomState.addFixup(file);
-        haveFixup = false;
-      }
+llvm::error_code parseFixup( llvm::yaml::MappingNode *mn
+                           , llvm::yaml::Stream &s
+                           , Platform &p
+                           , YAMLFile &f
+                           , YAMLAtomState &yas) {
+  using namespace llvm::yaml;
+  llvm::SmallString<32> storage;
+
+  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);
     }
+  }
+  yas.addFixup(&f);
+  return make_error_code(yaml_reader_error::success);
+}
 
-    if (inAtoms && (depthForAtoms == -1)) {
-      depthForAtoms = entry->depth;
-    }
-    if (inFixups && (depthForFixups == -1)) {
-      depthForFixups = entry->depth;
-    }
-    if (inMembers && (depthForMembers == -1)) {
-      depthForMembers = entry->depth;
-    }
-    if ( !inFixups && (strcmp(entry->key, KeyValues::fileKindKeyword) == 0) ) {
-      file->_kind = KeyValues::fileKind(entry->value);
-      if ( file->_kind == File::kindArchiveLibrary )
-        hasArchives = true;
-    }
-    else if (strcmp(entry->key, KeyValues::fileMembersKeyword) == 0) {
-      inMembers = true;
-    }
-    else if (strcmp(entry->key, KeyValues::fileAtomsKeyword) == 0) {
-      inAtoms = true;
-    }
-    else if ( !inAtoms && !inMembers
-                       && (strcmp(entry->key, KeyValues::nameKeyword) == 0) ) {
-      file->setName(entry->value);
-    }
-    if (inAtoms) {
-      if (depthForAtoms == entry->depth) {
-        if (entry->beginSequence) {
-          if (haveAtom) {
-            atomState.makeAtom(*file);
-            haveAtom = false;
-          }
-        }
-        if (strcmp(entry->key, KeyValues::nameKeyword) == 0) {
-          atomState.setName(entry->value);
-          haveAtom = true;
-        }
-        else if (strcmp(entry->key, KeyValues::refNameKeyword) == 0) {
-          atomState.setRefName(entry->value);
-          haveAtom = true;
-        }
-        else if (strcmp(entry->key, KeyValues::definitionKeyword) == 0) {
-          atomState._definition = KeyValues::definition(entry->value);
-          haveAtom = true;
-        }
-        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::mergeKeyword) == 0) {
-          atomState._merge = KeyValues::merge(entry->value);
-          haveAtom = true;
-        }
-        else if (strcmp(entry->key, KeyValues::interposableKeyword) == 0) {
-          atomState._interpose = KeyValues::interposable(entry->value);
-          haveAtom = true;
-        }
-        else if (strcmp(entry->key, KeyValues::isThumbKeyword) == 0) {
-          atomState._isThumb = KeyValues::isThumb(entry->value);
-          haveAtom = true;
-        }
-        else if (strcmp(entry->key, KeyValues::isAliasKeyword) == 0) {
-          atomState._isAlias = KeyValues::isAlias(entry->value);
-          haveAtom = true;
-        }
-        else if (strcmp(entry->key, KeyValues::canBeNullKeyword) == 0) {
-          atomState._canBeNull = KeyValues::canBeNull(entry->value);
-          if ( atomState._definition == Atom::definitionSharedLibrary ) {
-            if ( atomState._canBeNull == UndefinedAtom::canBeNullAtBuildtime )
-              return make_error_code(yaml_reader_error::illegal_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) {
-          StringRef val = entry->value;
-          if (val.getAsInteger(0, atomState._size))
+llvm::error_code parseAtom( llvm::yaml::MappingNode *mn
+                          , llvm::yaml::Stream &s
+                          , Platform &p
+                          , YAMLFile &f) {
+  using namespace llvm::yaml;
+  YAMLAtomState yas(p);
+  llvm::SmallString<32> storage;
+
+  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);
-          haveAtom = true;
-        }
-        else if (strcmp(entry->key, KeyValues::contentKeyword) == 0) {
-          atomState._content = entry->valueSequenceBytes;
-          haveAtom = true;
-        }
-        else if (strcmp(entry->key, "align2") == 0) {
-          atomState.setAlign2(entry->value);
-          haveAtom = true;
-        }
-        else if (strcmp(entry->key, KeyValues::fixupsKeyword) == 0) {
-          inFixups = true;
-        }
-        else if (strcmp(entry->key, KeyValues::loadNameKeyword) == 0) {
-          atomState._loadName = entry->value;
-          haveAtom = true;
-        }
-        else if (strcmp(entry->key, KeyValues::valueKeyword) == 0) {
-          llvm::APInt Val;
-          StringRef(entry->value).getAsInteger(0, Val);
-          atomState._value = Val.getZExtValue();
-          haveAtom = true;
-        }
-        else {
-          return make_error_code(yaml_reader_error::unknown_keyword);
-        }
-      }
-      else if (depthForFixups == entry->depth) {
-        if (entry->beginSequence) {
-          if (haveFixup) {
-            atomState.addFixup(file);
-            haveFixup = false;
           }
-        }
-        if (strcmp(entry->key, KeyValues::fixupsKindKeyword) == 0) {
-          atomState.setFixupKind(entry->value);
-          haveFixup = true;
-        }
-        else if (strcmp(entry->key, KeyValues::fixupsOffsetKeyword) == 0) {
-          if (StringRef(entry->value).getAsInteger(0,
-               atomState._ref._offsetInAtom))
+          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);
-          haveFixup = true;
-        }
-        else if (strcmp(entry->key, KeyValues::fixupsTargetKeyword) == 0) {
-          atomState.setFixupTarget(entry->value);
-          haveFixup = true;
-        }
-        else if (strcmp(entry->key, KeyValues::fixupsAddendKeyword) == 0) {
-          StringRef Addend(entry->value);
-          if (Addend.getAsInteger(0, atomState._ref._addend))
+          }
+          if (ContentByte > 0xFF) {
+            s.printError(i->getValue(), "Byte out of range (> 0xFF)");
             return make_error_code(yaml_reader_error::illegal_value);
-          haveFixup = true;
+          }
+          yas._content.push_back(ContentByte & 0xFF);
         }
       }
-    }
-    else if (inMembers) {
-      if (depthForMembers == entry->depth) {
-        if (entry->beginSequence) {
-          if (strcmp(entry->key, KeyValues::nameKeyword) == 0) {
-            file->addMember(entry->value);
-          }
+    } 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);
       }
     }
-    lastDepth = entry->depth;
   }
-  if (haveAtom) {
-    atomState.makeAtom(*file);
+  yas.makeAtom(f);
+  return make_error_code(yaml_reader_error::success);
+}
+
+llvm::error_code parseAtoms( llvm::yaml::SequenceNode *atoms
+                           , llvm::yaml::Stream &s
+                           , Platform &p
+                           , YAMLFile &f) {
+  using namespace llvm::yaml;
+
+  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);
+    }
   }
-  if (file != nullptr) {
-    file->bindTargetReferences();
-    allFiles.push_back(file);
-  }
-
-  // If yaml contained archive files, push members down into archives
-  if ( hasArchives ) {
-    for (YAMLFile *f : allFiles) {
-      if ( f->kind() == File::kindArchiveLibrary ) {
-        for (const char *memberName : f->_memberNames ) {
-          for (YAMLFile *f2 : allFiles) {
-            if ( f2->path().equals(memberName) ) {
-              f2->_inArchive = true;
-              f->_memberFiles.push_back(f2);
-            }
-          }
+  return make_error_code(yaml_reader_error::success);
+}
+
+llvm::error_code parseArchive( llvm::yaml::SequenceNode *archive
+                             , llvm::yaml::Stream &s
+                             , Platform &p
+                             , YAMLFile &f) {
+  using namespace llvm::yaml;
+  llvm::SmallString<32> storage;
+
+  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);
+    }
+    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);
+      }
+      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);
+        }
+        // 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);
         }
+        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));
   }
-  // Copy files that have not been pushed into archives to result.
-  for (YAMLFile *f : allFiles) {
-    if ( ! f->_inArchive ) {
-      result.push_back(f);
+  return make_error_code(yaml_reader_error::success);
+}
+
+/// 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()))
+      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())
+      return make_error_code(yaml_reader_error::illegal_value);
+    CurFile->bindTargetReferences();
+    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<const File*>& result) {
+                                     , std::vector<
+                                         std::unique_ptr<const File>>& result) {
   OwningPtr<llvm::MemoryBuffer> mb;
   if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb))
     return ec;
 
-  return parseObjectText(mb.get(), platform, result);
+  return parseObjectText(mb.take(), platform, result);
 }
 
 } // namespace yaml

Modified: lld/trunk/test/archive-basic.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/archive-basic.objtxt?rev=155847&r1=155846&r2=155847&view=diff
==============================================================================
--- lld/trunk/test/archive-basic.objtxt (original)
+++ lld/trunk/test/archive-basic.objtxt Mon Apr 30 16:20:13 2012
@@ -9,34 +9,29 @@
 atoms:
     - name:              foo
       type:              code
-      
+
     - name:              bar
       definition:        undefined
 
 ---
-name: bar.o
-atoms:
-    - name:              bar
-      scope:             global
-      type:              code
-      
-    - name:              bar2
-      type:              code
-  
----
-name: baz.o
-atoms:
-    - name:              baz
-      scope:             global
-      type:              code
-      
-    - name:              baz2
-      type:              code
----
-kind: archive
-members:  
-    - name:    bar.o
-    - name:    baz.o
+archive:
+    - name: bar.o
+      atoms:
+      - name:              bar
+        scope:             global
+        type:              code
+
+      - name:              bar2
+        type:              code
+
+    - name: baz.o
+      atoms:
+      - name:              baz
+        scope:             global
+        type:              code
+
+      - name:              baz2
+        type:              code
 ...
 
 # CHECK:       name:       foo

Modified: lld/trunk/test/archive-chain.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/archive-chain.objtxt?rev=155847&r1=155846&r2=155847&view=diff
==============================================================================
--- lld/trunk/test/archive-chain.objtxt (original)
+++ lld/trunk/test/archive-chain.objtxt Mon Apr 30 16:20:13 2012
@@ -8,60 +8,52 @@
 atoms:
     - name:              foo
       type:              code
-      
-    - name:              bar1
-      definition:        undefined
 
----
-name: bar1.o
-atoms:
     - name:              bar1
-      scope:             global
-      type:              code
-      
-    - name:              bar1b
-      type:              code
-  
-    - name:              baz1
       definition:        undefined
+
 ---
-name: bar2.o
-atoms:
-    - name:              bar2
-      scope:             global
-      type:              code
-      
-    - name:              bar2b
-      type:              code
-  
----
-name: baz1.o
-atoms:
-    - name:              baz1
-      scope:             global
-      type:              code
-      
-    - name:              baz1b
-      type:              code
----
-name: baz2.o
-atoms:
-    - name:              baz2
-      scope:             global
-      type:              code
-      
-    - name:              baz2b
-      type:              code
----
-kind: archive
-members:  
-    - name:    bar1.o
-    - name:    bar2.o
+archive:
+    - name: bar1.o
+    - atoms:
+      - name:              bar1
+        scope:             global
+        type:              code
+
+      - name:              bar1b
+        type:              code
+
+      - name:              baz1
+        definition:        undefined
+
+    - name: bar2.o
+    - atoms:
+      - name:              bar2
+        scope:             global
+        type:              code
+
+      - name:              bar2b
+        type:              code
+
 ---
-kind: archive
-members:  
-    - name:    baz1.o
-    - name:    baz2.o
+archive:
+    - name: baz1.o
+    - atoms:
+      - name:              baz1
+        scope:             global
+        type:              code
+
+      - name:              baz1b
+        type:              code
+
+    - name: baz2.o
+    - atoms:
+      - name:              baz2
+        scope:             global
+        type:              code
+
+      - name:              baz2b
+        type:              code
 ...
 
 # CHECK:       name:       foo

Modified: lld/trunk/test/archive-tentdef-search.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/archive-tentdef-search.objtxt?rev=155847&r1=155846&r2=155847&view=diff
==============================================================================
--- lld/trunk/test/archive-tentdef-search.objtxt (original)
+++ lld/trunk/test/archive-tentdef-search.objtxt Mon Apr 30 16:20:13 2012
@@ -11,26 +11,22 @@
 atoms:
     - name:              foo
       type:              code
-      
+
     - name:              bar
       scope:             global
       content:           zero-fill
       merge:             asTentative
 
 ---
-name: bar.o
-atoms:
-    - name:              bar
-      scope:             global
-      type:              data
-      
-    - name:              bar2
-      type:              data
-  
----
-kind: archive
-members:  
-    - name:    bar.o
+archive:
+    - name: bar.o
+    - atoms:
+      - name:              bar
+        scope:             global
+        type:              data
+
+      - name:              bar2
+        type:              data
 ...
 
 # CHK1:       name:       foo

Modified: lld/trunk/tools/lld-core/lld-core.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/lld-core.cpp?rev=155847&r1=155846&r2=155847&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Mon Apr 30 16:20:13 2012
@@ -422,7 +422,7 @@
   llvm::cl::ParseCommandLineOptions(argc, argv);
 
   // create platform for testing
-  Platform* platform = NULL;
+  Platform* platform = nullptr;
   switch ( platformSelected ) {
     case platformTesting:
       platform = new TestingPlatform();
@@ -433,7 +433,7 @@
   }
   
   // read input YAML doc into object file(s)
-  std::vector<const File *> files;
+  std::vector<std::unique_ptr<const File>> files;
   if (error(yaml::parseObjectTextFileOrSTDIN(cmdLineInputFilePath, 
                                             *platform, files))) {
     return 1;
@@ -444,7 +444,7 @@
 
   // create object to mange input files
   InputFiles inputFiles;
-  for (const File *file : files) {
+  for (const auto &file : files) {
     inputFiles.appendFile(*file);
   }
   





More information about the llvm-commits mailing list