[llvm-commits] [lld] r157774 - in /lld/trunk: docs/ include/lld/Core/ include/lld/Platform/ include/lld/Reader/ include/lld/ReaderWriter/ lib/ lib/Core/ lib/Passes/ lib/Platforms/ lib/Reader/ lib/ReaderWriter/ lib/ReaderWriter/ELF/ lib/ReaderWriter/MachO/ lib/ReaderWriter/Native/ lib/ReaderWriter/PECOFF/ lib/ReaderWriter/YAML/ tools/lld-core/

Nick Kledzik kledzik at apple.com
Thu May 31 15:34:01 PDT 2012


Author: kledzik
Date: Thu May 31 17:34:00 2012
New Revision: 157774

URL: http://llvm.org/viewvc/llvm-project?rev=157774&view=rev
Log:
Major refactoring:  Remove Platform concept.  In its place there are 
now Reader and Writer subclasses for each file format.  Each Reader and
Writer subclass defines an "options" class which controls how that Reader
or Writer operates.



Added:
    lld/trunk/include/lld/ReaderWriter/
    lld/trunk/include/lld/ReaderWriter/Reader.h
    lld/trunk/include/lld/ReaderWriter/ReaderELF.h
    lld/trunk/include/lld/ReaderWriter/ReaderMachO.h
    lld/trunk/include/lld/ReaderWriter/ReaderNative.h
    lld/trunk/include/lld/ReaderWriter/ReaderPECOFF.h
    lld/trunk/include/lld/ReaderWriter/ReaderYAML.h
    lld/trunk/include/lld/ReaderWriter/Writer.h
    lld/trunk/include/lld/ReaderWriter/WriterELF.h
    lld/trunk/include/lld/ReaderWriter/WriterMachO.h
    lld/trunk/include/lld/ReaderWriter/WriterNative.h
    lld/trunk/include/lld/ReaderWriter/WriterPECOFF.h
    lld/trunk/include/lld/ReaderWriter/WriterYAML.h
    lld/trunk/lib/ReaderWriter/
    lld/trunk/lib/ReaderWriter/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/ELF/
    lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp
    lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp
    lld/trunk/lib/ReaderWriter/MachO/
    lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
    lld/trunk/lib/ReaderWriter/MachO/GOTPass.hpp
    lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp
    lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp
    lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h
    lld/trunk/lib/ReaderWriter/MachO/SimpleAtoms.hpp
    lld/trunk/lib/ReaderWriter/MachO/StubAtoms.hpp
    lld/trunk/lib/ReaderWriter/MachO/StubsPass.hpp
    lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp
    lld/trunk/lib/ReaderWriter/Native/
    lld/trunk/lib/ReaderWriter/Native/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/Native/NativeFileFormat.h
    lld/trunk/lib/ReaderWriter/Native/ReaderNative.cpp
    lld/trunk/lib/ReaderWriter/Native/WriterNative.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/
    lld/trunk/lib/ReaderWriter/PECOFF/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
    lld/trunk/lib/ReaderWriter/Reader.cpp
    lld/trunk/lib/ReaderWriter/Writer.cpp
    lld/trunk/lib/ReaderWriter/YAML/
    lld/trunk/lib/ReaderWriter/YAML/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/YAML/ReaderYAML.cpp
    lld/trunk/lib/ReaderWriter/YAML/WriterYAML.cpp
    lld/trunk/lib/ReaderWriter/YAML/YamlKeyValues.cpp
    lld/trunk/lib/ReaderWriter/YAML/YamlKeyValues.h
    lld/trunk/tools/lld-core/TestingHelpers.hpp
Removed:
    lld/trunk/include/lld/Core/AliasAtom.h
    lld/trunk/include/lld/Core/NativeReader.h
    lld/trunk/include/lld/Core/NativeWriter.h
    lld/trunk/include/lld/Core/Platform.h
    lld/trunk/include/lld/Core/YamlReader.h
    lld/trunk/include/lld/Core/YamlWriter.h
    lld/trunk/include/lld/Platform/
    lld/trunk/include/lld/Reader/
    lld/trunk/lib/Core/NativeFileFormat.h
    lld/trunk/lib/Core/NativeReader.cpp
    lld/trunk/lib/Core/NativeWriter.cpp
    lld/trunk/lib/Core/Platform.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/lib/Platforms/
    lld/trunk/lib/Reader/
Modified:
    lld/trunk/docs/README.txt
    lld/trunk/docs/design.rst
    lld/trunk/include/lld/Core/ArchiveLibraryFile.h
    lld/trunk/include/lld/Core/DefinedAtom.h
    lld/trunk/include/lld/Core/InputFiles.h
    lld/trunk/include/lld/Core/LLVM.h
    lld/trunk/include/lld/Core/Pass.h
    lld/trunk/include/lld/Core/SharedLibraryFile.h
    lld/trunk/lib/CMakeLists.txt
    lld/trunk/lib/Core/CMakeLists.txt
    lld/trunk/lib/Core/InputFiles.cpp
    lld/trunk/lib/Core/Resolver.cpp
    lld/trunk/lib/Core/SymbolTable.cpp
    lld/trunk/lib/Passes/GOTPass.cpp
    lld/trunk/lib/Passes/StubsPass.cpp
    lld/trunk/tools/lld-core/CMakeLists.txt
    lld/trunk/tools/lld-core/lld-core.cpp

Modified: lld/trunk/docs/README.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/README.txt?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/docs/README.txt (original)
+++ lld/trunk/docs/README.txt Thu May 31 17:34:00 2012
@@ -5,3 +5,8 @@
 currently tested with Sphinx 1.1.3.
 
 We currently use the 'nature' theme and a Beaker inspired structure.
+
+To rebuild documents into html:
+
+   [/lld/docs]> make html
+

Modified: lld/trunk/docs/design.rst
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/design.rst?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/docs/design.rst (original)
+++ lld/trunk/docs/design.rst Thu May 31 17:34:00 2012
@@ -108,13 +108,32 @@
 The Resolving and Passes steps are done purely on the master graph of atoms, so
 they have no notion of file formats such as mach-o or ELF.
 
+
+Input Files
+~~~~~~~~~~~
+
+Existing developer tools using different file formats for object files. 
+A goal of lld is to be file format independent.  This is done
+through a plug-in model for reading object files. The lld::Reader is the base
+class for all object file readers.  A Reader follows the factory method pattern.
+A Reader instantiates an lld::File object (which is a graph of Atoms) from a
+given object file (on disk or in-memory).
+
+Every Reader subclass defines its own "options" class (for instance the mach-o 
+Reader defines the class ReaderOptionsMachO).  This options class is the 
+one-and-only way to control how the Reader operates when parsing an input file
+into an Atom graph.  For instance, you may want the Reader to only accept
+certain architectures.  The options class can be instantiated from command
+line options, or it can be subclassed and the ivars programatically set. 
+
+
 Resolving
 ~~~~~~~~~
 
-The resolving step takes all the atoms' graphs from each object file and combines
-them into one master object graph.  Unfortunately, it is not as simple as
-appending the atom list from each file into one big list.  There are many cases
-where atoms need to be coalesced.  That is, two or more atoms need to be
+The resolving step takes all the atoms' graphs from each object file and 
+combines them into one master object graph.  Unfortunately, it is not as simple 
+as appending the atom list from each file into one big list.  There are many 
+cases where atoms need to be coalesced.  That is, two or more atoms need to be
 coalesced into one atom.  This is necessary to support: C language "tentative
 definitions", C++ weak symbols for templates and inlines defined in headers,
 replacing undefined atoms with actual definition atoms, and for merging copies
@@ -189,6 +208,7 @@
 object.  Next, all the noted call sites to shared library atoms have their
 References altered to point to the stub atom instead of the shared library atom.
 
+
 Generate Output File
 ~~~~~~~~~~~~~~~~~~~~
 
@@ -196,17 +216,31 @@
 object.  The writer's job is to create the executable content file wrapper and
 place the content of the atoms into it.
 
-Sometimes the output generator needs access to particular atoms (for instance,
-it may need to know which atom is "main" in order to specifiy the entry 
-point in the executable.  The way to do this is to have the platform create
-an Atom with a Reference to the required atom(s) and provide this atom
-in the initialize set of atoms for the resolver.  If a particular symbol name
-is required, this arrangment will also cause core linking to fail if the
-symbol is not defined (e.g. "main" is undefined).
-
-Sometimes a platform supports lazily created symbols.  To support this, the
-platform can create a File object which vends no initial atoms, but does
-lazily supply atoms by name as needed.  
+lld uses a plug-in model for writing output files. All concrete writers (e.g.
+ELF, mach-o, etc) are subclasses of the lld::Writer classs.  
+
+Unlike the Reader class which has just one method to instantiate an lld::File,
+the Writer class has multiple methods.  The crucial method is to generate the 
+output file, but there are also methods which allow the Writer to contribute
+Atoms to the resolver and specify passes to run.  
+
+An example of contributing
+atoms is that if the Writer knows a main executable is being linked and such
+an executable requires a specially named entry point (e.g. "_main"), the Writer
+can add an UndefinedAtom with that special name to the resolver.  This will 
+cause the resolver to issue an error if that symbol is not defined.  
+
+Sometimes a Writer supports lazily created symbols, such as names for the start
+of sections. To support this, the Writer can create a File object which vends 
+no initial atoms, but does lazily supply atoms by name as needed.  
+
+Every Writer subclass defines its own "options" class (for instance the mach-o 
+Writer defines the class WriterOptionsMachO).  This options class is the 
+one-and-only way to control how the Writer operates when producing an output 
+file from an Atom graph.  For instance, you may want the Writer to optimize
+the output for certain OS versions, or strip local symbols, etc. The options 
+class can be instantiated from command line options, or it can be subclassed 
+and the ivars programatically set. 
 
 
 lld::File representations
@@ -262,6 +296,10 @@
 into the in-memory graph of lld::Atoms with just a few memory allocations.  
 And the format can easily adapt over time to new features.
 
+The binary file format follows the ReaderWriter patterns used in lld. The lld 
+library comes with the classes: ReaderNative and WriterNative.  So, switching 
+between file formats is as easy as switching which Reader subclass is used.
+
 
 Textual representations in YAML
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -300,8 +338,12 @@
 format, we can exactly specify every attribute of every atom and thus target
 specific linker logic.
 
+The textual/YAML format follows the ReaderWriter patterns used in lld. The lld 
+library comes with the classes: ReaderYAML and WriterYAML.  
+
+
 Testing
-~~~~~~~
+-------
 
 The lld project contains a test suite which is being built up as new code is
 added to lld.  All new lld functionality should have a tests added to the test

Removed: lld/trunk/include/lld/Core/AliasAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/AliasAtom.h?rev=157773&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/AliasAtom.h (original)
+++ lld/trunk/include/lld/Core/AliasAtom.h (removed)
@@ -1,56 +0,0 @@
-//===- Core/AliasAtom.h - Alias to another Atom ---------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_ALIAS_ATOM_H_
-#define LLD_CORE_ALIAS_ATOM_H_
-
-#include "lld/Core/Atom.h"
-
-#include "llvm/ADT/StringRef.h"
-
-namespace lld {
-
-class AliasAtom : public Atom {
-public:
-  AliasAtom(StringRef nm, const Atom &target,  Atom::Scope scope)
-    : Atom( target.definition()
-          , Atom::combineNever
-          , scope
-          , target.contentType()
-          , target.sectionChoice()
-          , target.userVisibleName()
-          , target.deadStrip()
-          , target.isThumb()
-          , true
-          , target.alignment()
-          )
-    , _name(nm)
-    , _aliasOf(target) {}
-
-  // overrides of Atom
-  virtual const File *file() const {
-    return _aliasOf.file();
-  }
-
-  virtual bool translationUnitSource(StringRef &path) const {
-    return _aliasOf.translationUnitSource(path);
-  }
-
-  virtual StringRef name() const {
-    return _name;
-  }
-
-private:
-  const StringRef _name;
-  const Atom &_aliasOf;
-};
-
-} // namespace lld
-
-#endif // LLD_CORE_ALIAS_ATOM_H_

Modified: lld/trunk/include/lld/Core/ArchiveLibraryFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/ArchiveLibraryFile.h?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/ArchiveLibraryFile.h (original)
+++ lld/trunk/include/lld/Core/ArchiveLibraryFile.h Thu May 31 17:34:00 2012
@@ -26,8 +26,6 @@
 /// 
 class ArchiveLibraryFile : public File {
 public:
-          ArchiveLibraryFile(StringRef path) : File(path) {
-  }
 
   virtual ~ArchiveLibraryFile() {
   }
@@ -47,6 +45,9 @@
   /// specified name and return the File object for that member, or nullptr.
   virtual const File *find(StringRef name, bool dataSymbolOnly) const = 0;
 
+protected:
+  /// only subclasses of ArchiveLibraryFile can be instantiated 
+  ArchiveLibraryFile(StringRef path) : File(path) { }
 };
 
 } // namespace lld

Modified: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Thu May 31 17:34:00 2012
@@ -1,4 +1,4 @@
-//===- Core/DefinedAtom.h - The Fundamental Unit of Linking ---------------===//
+//===- Core/DefinedAtom.h - An Atom with content --------------------------===//
 //
 //                             The LLVM Linker
 //

Modified: lld/trunk/include/lld/Core/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputFiles.h?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/InputFiles.h (original)
+++ lld/trunk/include/lld/Core/InputFiles.h Thu May 31 17:34:00 2012
@@ -37,12 +37,14 @@
   InputFiles();
   virtual ~InputFiles();
 
-  /// Used by platforms to insert platform specific files.
+  /// Used by Writers to insert writer specific files.
   virtual void prependFile(const File&);
   
-  /// Used by platforms to insert platform specific files.
+  /// Used by Writers to insert writer specific files.
   virtual void appendFile(const File&);
  
+ /// Transfers ownership of a vector of Files to this InputFile object.
+  virtual void appendFiles(std::vector<std::unique_ptr<File>> &files);
 
   /// @brief iterates all atoms in initial files
   virtual void forEachInitialAtom(Handler &) const;

Modified: lld/trunk/include/lld/Core/LLVM.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/LLVM.h?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/LLVM.h (original)
+++ lld/trunk/include/lld/Core/LLVM.h Thu May 31 17:34:00 2012
@@ -23,6 +23,7 @@
   // ADT's.
   class StringRef;
   class Twine;
+  class MemoryBuffer;
   template<typename T> class ArrayRef;
   template<class T> class OwningPtr;
   template<unsigned InternalLen> class SmallString;
@@ -55,6 +56,7 @@
   // ADT's.
   using llvm::StringRef;
   using llvm::Twine;
+  using llvm::MemoryBuffer;
   using llvm::ArrayRef;
   using llvm::OwningPtr;
   using llvm::SmallString;

Removed: lld/trunk/include/lld/Core/NativeReader.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/NativeReader.h?rev=157773&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/NativeReader.h (original)
+++ lld/trunk/include/lld/Core/NativeReader.h (removed)
@@ -1,40 +0,0 @@
-//===- Core/NativeReader.h - Reads llvm native object files ---------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_NATIVE_READER_H_
-#define LLD_CORE_NATIVE_READER_H_
-
-#include "lld/Core/File.h"
-
-#include "llvm/Support/system_error.h"
-
-#include <memory>
-#include <vector>
-
-namespace llvm {
-  class MemoryBuffer;
-  class StringRef;
-}
-
-namespace lld {
-  /// parseNativeObjectFileOrSTDIN - Open the specified native object file (use
-  /// stdin if the path is "-") and instantiate into an lld::File object.
-  error_code parseNativeObjectFileOrSTDIN( StringRef path
-                                         , std::unique_ptr<File> &result);
-
-
-  /// parseNativeObjectFile - Parse the specified native object file
-  /// (in a buffer) and instantiate into an lld::File object.
-  error_code parseNativeObjectFile( std::unique_ptr<llvm::MemoryBuffer> &mb
-                                  , StringRef path
-                                  , std::unique_ptr<File> &result);
-
-} // namespace lld
-
-#endif // LLD_CORE_NATIVE_READER_H_

Removed: lld/trunk/include/lld/Core/NativeWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/NativeWriter.h?rev=157773&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/NativeWriter.h (original)
+++ lld/trunk/include/lld/Core/NativeWriter.h (removed)
@@ -1,34 +0,0 @@
-//===- Core/NativeWriter.h - Writes native object file --------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_NATIVE_WRITER_H_
-#define LLD_CORE_NATIVE_WRITER_H_
-
-#include "lld/Core/File.h"
-
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-  class StringRef;
-}
-
-
-namespace lld {
-
-  /// writeNativeObjectFile - writes the lld::File object in native object
-  /// file format to the specified file path.
-  int writeNativeObjectFile(const lld::File &, StringRef path);
-
-  /// writeNativeObjectFile - writes the lld::File object in native object
-  /// file format to the specified stream.
-  int writeNativeObjectFile(const lld::File &, raw_ostream &);
-
-} // namespace lld
-
-#endif // LLD_CORE_NATIVE_WRITER_H_

Modified: lld/trunk/include/lld/Core/Pass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Pass.h?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Pass.h (original)
+++ lld/trunk/include/lld/Core/Pass.h Thu May 31 17:34:00 2012
@@ -11,11 +11,12 @@
 #define LLD_CORE_PASS_H_
 
 #include "lld/Core/Atom.h"
-#include "lld/Core/Platform.h"
+#include "lld/Core/Reference.h"
 
 #include <vector>
 
 namespace lld {
+class DefinedAtom;
 
 
 ///
@@ -34,43 +35,88 @@
 class Pass {
 public:
     /// Do the actual work of the Pass.
-    virtual void perform() = 0;
+    virtual void perform(File& mergedFile) = 0;
 
 protected:
   // Only subclassess can be instantiated.
-  Pass(File& f, Platform& p) : _file(f), _platform(p) {}
-
-
-  File&       _file;
-  Platform&   _platform;
+  Pass() { }
 };
 
 
 ///
 /// Pass for adding stubs (PLT entries) for calls to functions
-/// outside the linkage unit.
+/// outside the linkage unit.  This class is subclassed by each 
+/// file format Writer which implements the pure virtual methods.
 ///
 class StubsPass : public Pass {
 public:
-  StubsPass(File& f, Platform& p) : Pass(f, p) {}
+  StubsPass() : Pass() {}
 
   /// Scans all Atoms looking for call-site uses of SharedLibraryAtoms
-  /// and transfroms the call-site to call a stub instead.
-  virtual void perform();
+  /// and transfroms the call-site to call a stub instead using the
+  /// helper methods below.
+  virtual void perform(File& mergedFile);
+
+  /// If true, the pass should use stubs for references
+  /// to shared library symbols. If false, the pass
+  /// will generate relocations on the text segment which the
+  /// runtime loader will use to patch the program at runtime.
+  virtual bool noTextRelocs() = 0;
+
+  /// Returns whether the Reference kind is for a call site.  The pass 
+  /// uses this to find calls that need to be indirected through a stub.
+  virtual bool isCallSite(Reference::Kind) = 0;
+  
+  /// Returns a file format specific atom for a stub/PLT entry which contains
+  /// instructions which jump to the specified atom.  May be called multiple  
+  /// times for the same target atom, in which case this method should return 
+  /// the same stub atom.  
+  virtual const DefinedAtom* getStub(const Atom &target) = 0;
+
+  /// After the default implementation of perform() is done calling getStub(),
+  /// it will call this method to add all the stub (and support) atoms to the 
+  /// master file object.
+  virtual void addStubAtoms(File &masterFile) = 0;
 };
 
 
+
 ///
 /// Pass for adding GOT entries for pointers to functions/data
-/// outside the linkage unit.
+/// outside the linkage unit. This class is subclassed by each 
+/// file format Writer which implements the pure virtual methods.
 ///
 class GOTPass : public Pass {
 public:
-  GOTPass(File& f, Platform& p) : Pass(f, p) {}
+  GOTPass() : Pass() {}
 
   /// Scans all Atoms looking for pointer to SharedLibraryAtoms
-  /// and transfroms them to a pointer to a GOT entry.
-  virtual void perform();
+  /// and transfroms them to a pointer to a GOT entry using the
+  /// helper methods below.
+  virtual void perform(File& mergedFile);
+
+  /// If true, the pass will use GOT entries for references
+  /// to shared library symbols. If false, the pass
+  /// will generate relocations on the text segment which the
+  /// runtime loader will use to patch the program at runtime.
+  virtual bool noTextRelocs() = 0;
+
+  /// Returns whether the Reference kind is a pre-instantiated GOT access.
+  /// The default implementation of perform() uses this to figure out 
+  /// what GOT entries to instantiate.
+  virtual bool isGOTAccess(Reference::Kind, bool& canBypassGOT) = 0;
+
+  /// The file format Writer needs to alter the reference kind from a 
+  /// pre-instantiated GOT access to an actual access.  If targetIsNowGOT is
+  /// true, the pass has instantiated a GOT atom and altered the reference's 
+  /// target to point to that atom.  If targetIsNowGOT is false, the pass
+  /// determined a GOT entry is not needed because the reference site can
+  /// directly access the target.
+  virtual void updateReferenceToGOT(const Reference*, bool targetIsNowGOT) = 0;
+
+  /// Returns a file format specific atom for a GOT entry targeting
+  /// the specified atom.
+  virtual const DefinedAtom* makeGOTEntry(const Atom& target) = 0;
 };
 
 

Removed: lld/trunk/include/lld/Core/Platform.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Platform.h?rev=157773&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/Platform.h (original)
+++ lld/trunk/include/lld/Core/Platform.h (removed)
@@ -1,99 +0,0 @@
-//===- Core/Platform.h - Platform Interface -------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_PLATFORM_H_
-#define LLD_CORE_PLATFORM_H_
-
-#include "lld/Core/Reference.h"
-#include "lld/Core/LLVM.h"
-#include <vector>
-
-namespace lld {
-class Atom;
-class DefinedAtom;
-class UndefinedAtom;
-class SharedLibraryAtom;
-class File;
-class InputFiles;
-
-
-/// The Platform class encapsulated plaform specific linking knowledge.
-///
-/// Much of what it does is driving by platform specific linker options.
-class Platform {
-public:
-  virtual ~Platform();
-  
-  virtual void addFiles(InputFiles&) = 0;
-  
-  /// Converts a reference kind string to a in-memory numeric value.
-  /// For use with parsing YAML encoded object files.
-  virtual Reference::Kind kindFromString(StringRef) = 0;
-
-  /// Converts an in-memory reference kind value to a string.
-  /// For use with writing YAML encoded object files.
-  virtual StringRef kindToString(Reference::Kind) = 0;
-
-  /// If true, the linker will use stubs and GOT entries for
-  /// references to shared library symbols. If false, the linker
-  /// will generate relocations on the text segment which the
-  /// runtime loader will use to patch the program at runtime.
-  virtual bool noTextRelocs() = 0;
-
-  /// Returns if the Reference kind is for a call site.  The "stubs" Pass uses
-  /// this to find calls that need to be indirected through a stub.
-  virtual bool isCallSite(Reference::Kind) = 0;
-
-  /// Returns if the Reference kind is a pre-instantiated GOT access.
-  /// The "got" Pass uses this to figure out what GOT entries to instantiate.
-  virtual bool isGOTAccess(Reference::Kind, bool& canBypassGOT) = 0;
-
-  /// The platform needs to alter the reference kind from a pre-instantiated
-  /// GOT access to an actual access.  If targetIsNowGOT is true, the "got"
-  /// Pass has instantiated a GOT atom and altered the reference's target
-  /// to point to that atom.  If targetIsNowGOT is false, the "got" Pass
-  /// determined a GOT entry is not needed because the reference site can
-  /// directly access the target.
-  virtual void updateReferenceToGOT(const Reference*, bool targetIsNowGOT) = 0;
-
-  /// Returns a platform specific atom for a stub/PLT entry which will
-  /// jump to the specified atom.  May be called multiple times for the same
-  /// target atom, in which case this method should return the same stub
-  /// atom.  The platform needs to maintain a list of all stubs (and 
-  /// associated atoms) it has created for use by addStubAtoms().
-  virtual const DefinedAtom* getStub(const Atom &target, File&) = 0;
-
-  /// After the stubs Pass is done calling getStub(), the Pass will call
-  /// this method to add all the stub (and support) atoms to the master
-  /// file object.
-  virtual void addStubAtoms(File &file) = 0;
-
-  /// Create a platform specific GOT atom.
-  virtual const DefinedAtom* makeGOTEntry(const Atom&, File&) = 0;
-  
-  /// Write an executable file from the supplied file object to the 
-  /// supplied stream.
-  virtual void writeExecutable(const lld::File &, raw_ostream &out) = 0;
-  
-protected:
-  Platform();
-};
-
-
-
-///
-/// Creates a platform object for linking as done on Darwin (iOS/OSX).
-///
-extern Platform *createDarwinPlatform();
-
-
-
-} // namespace lld
-
-#endif // LLD_CORE_PLATFORM_H_

Modified: lld/trunk/include/lld/Core/SharedLibraryFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/SharedLibraryFile.h?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/SharedLibraryFile.h (original)
+++ lld/trunk/include/lld/Core/SharedLibraryFile.h Thu May 31 17:34:00 2012
@@ -22,8 +22,6 @@
 ///
 class SharedLibraryFile : public File {
 public:
-           SharedLibraryFile(StringRef path) : File(path) {
-  }
   virtual ~SharedLibraryFile() {
   }
 
@@ -44,7 +42,9 @@
   /// symbol.  Otherwise return nullptr.
   virtual const SharedLibraryAtom *exports(StringRef name, 
                                           bool dataSymbolOnly) const;
-  
+protected:
+  /// only subclasses of SharedLibraryFile can be instantiated 
+  SharedLibraryFile(StringRef path) : File(path) { }
 };
 
 } // namespace lld

Removed: lld/trunk/include/lld/Core/YamlReader.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/YamlReader.h?rev=157773&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/YamlReader.h (original)
+++ lld/trunk/include/lld/Core/YamlReader.h (removed)
@@ -1,50 +0,0 @@
-//===- Core/YamlReader.h - Reads YAML -------------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_YAML_READER_H_
-#define LLD_CORE_YAML_READER_H_
-
-#include "lld/Core/LLVM.h"
-
-#include "llvm/Support/system_error.h"
-
-#include <memory>
-#include <vector>
-
-namespace llvm {
-class MemoryBuffer;
-class StringRef;
-}
-
-namespace lld {
-
-class Platform;
-class File;
-
-namespace yaml {
-
-  /// parseObjectTextFileOrSTDIN - Open the specified YAML file (use stdin if
-  /// the path is "-") and parse into lld::File object(s) and append each to
-  /// the specified vector<File*>.
-  error_code parseObjectTextFileOrSTDIN( StringRef path
-                                       , Platform&
-                                       , 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<std::unique_ptr<const File>>&);
-
-} // namespace yaml
-} // namespace lld
-
-#endif // LLD_CORE_YAML_READER_H_

Removed: lld/trunk/include/lld/Core/YamlWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/YamlWriter.h?rev=157773&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/YamlWriter.h (original)
+++ lld/trunk/include/lld/Core/YamlWriter.h (removed)
@@ -1,31 +0,0 @@
-//===- Core/YamlWriter.h - Writes YAML formatted object files -------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_YAML_WRITER_H_
-#define LLD_CORE_YAML_WRITER_H_
-
-#include "lld/Core/LLVM.h"
-
-#include "llvm/Support/raw_ostream.h"
-
-namespace lld {
-
-class Platform;
-class File;
-
-namespace yaml {
-
-  /// writeObjectText - writes the lld::File object as in YAML
-  /// format to the specified stream.
-  void writeObjectText(const lld::File &, Platform &, raw_ostream &);
-
-} // namespace yaml
-} // namespace lld
-
-#endif // LLD_CORE_YAML_WRITER_H_

Added: lld/trunk/include/lld/ReaderWriter/Reader.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/Reader.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/Reader.h (added)
+++ lld/trunk/include/lld/ReaderWriter/Reader.h Thu May 31 17:34:00 2012
@@ -0,0 +1,74 @@
+//===- ReaderWriter/Reader.h - Abstract File Format Reading Interface -----===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_READER_H_
+#define LLD_READERWRITER_READER_H_
+
+#include "lld/Core/LLVM.h"
+#include <memory>
+#include <vector>
+
+namespace lld {
+class File;
+
+///
+/// The Reader is an abstract class for reading object files, 
+/// library files, and executable files.  Each file format
+/// (e.g. ELF, mach-o, PECOFF, native, etc) have a concrete subclass
+/// of Reader.  
+///
+class Reader {
+public:
+  virtual ~Reader();
+  
+ 
+  /// Parse a file given its file system path and create a File object. 
+  virtual error_code readFile(StringRef path,
+                              std::vector<std::unique_ptr<File>> &result);
+
+  /// Parse a supplied buffer (already filled with the contents of a file)
+  /// and create a File object. 
+  /// On success, the resulting File object takes ownership of 
+  /// the MemoryBuffer.
+  virtual error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
+                               std::vector<std::unique_ptr<File>> &result) = 0;
+  
+protected:
+  // only concrete subclasses can be instantiated
+  Reader();
+};
+
+
+
+///
+/// The ReaderOptions encapsulates the options used by all Readers.  
+/// Each file format defines a subclass of ReaderOptions
+/// to hold file format specific options.  The option objects are the only
+/// way to control the behaviour of Readers.
+///
+class ReaderOptions {
+public:
+  // Any options common to all file format Readers will go here.
+
+protected:
+  // only concrete subclasses can be instantiated
+  ReaderOptions();
+};
+
+
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_READER_H_
+
+
+
+

Added: lld/trunk/include/lld/ReaderWriter/ReaderELF.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ReaderELF.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ReaderELF.h (added)
+++ lld/trunk/include/lld/ReaderWriter/ReaderELF.h Thu May 31 17:34:00 2012
@@ -0,0 +1,65 @@
+//===- ReaderWriter/ReaderELF.h - ELF File Format Reading Interface -------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_READER_ELF_H_
+#define LLD_READERWRITER_READER_ELF_H_
+
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/Core/LLVM.h"
+
+
+namespace lld {
+
+/// 
+/// The ReaderOptionsELF class encapsulates options needed 
+/// to process mach-o files.  You can create an ReaderOptionsELF 
+/// instance from command line arguments or by subclassing and setting the 
+/// instance variables in the subclass's constructor.
+///
+class ReaderOptionsELF : public ReaderOptions {
+public:
+  virtual ~ReaderOptionsELF();
+
+  ///
+  /// Creates a Options object from darwin linker command line arguments.
+  /// FIXME: to be replaced with new option processing mechanism.
+  ///
+  ReaderOptionsELF(int argc, const char* argv[]);
+  
+  ///
+  /// Creates a Options object with default settings. For use when 
+  /// programmatically constructing options.
+  ///
+  ReaderOptionsELF();
+
+
+  
+protected:
+};
+ 
+
+
+
+///
+/// The only way to instantiate a ReaderELF object  
+/// is via this createReaderELF function.  The is no public 
+/// ReaderELF class that you might be tempted to subclass.
+/// Support for all variants must be represented in the ReaderOptionsELF
+/// object.
+/// The Reader object created retains a reference to the 
+/// ReaderOptionsELF object supplied, so the objects object must not be  
+/// destroyed before the Reader object. 
+///
+Reader* createReaderELF(const ReaderOptionsELF &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_READER_ELF_H_

Added: lld/trunk/include/lld/ReaderWriter/ReaderMachO.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ReaderMachO.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ReaderMachO.h (added)
+++ lld/trunk/include/lld/ReaderWriter/ReaderMachO.h Thu May 31 17:34:00 2012
@@ -0,0 +1,68 @@
+//===- ReaderWriter/ReaderMachO.h - MachO File Format Reading Interface ---===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_READER_MACHO_H_
+#define LLD_READER_WRITER_READER_MACHO_H_
+
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+/// 
+/// The ReaderOptionsMachO class encapsulates options needed 
+/// to process mach-o files.  You can create an ReaderOptionsMachO 
+/// instance from command line arguments or by subclassing and setting the 
+/// instance variables in the subclass's constructor.
+///
+class ReaderOptionsMachO : public ReaderOptions {
+public:
+  virtual ~ReaderOptionsMachO()  { }
+
+  ///
+  /// Creates a Options object from darwin linker command line arguments.
+  /// FIXME: to be replaced with new option processing mechanism.
+  ///
+  ReaderOptionsMachO(int argc, const char* argv[]);
+  
+  ///
+  /// Creates a Options object with default settings. For use when 
+  /// programmatically constructing options.
+  ///
+  ReaderOptionsMachO();
+
+
+  StringRef archName() const    { return _archName; }
+  
+protected:
+  StringRef       _archName;
+};
+ 
+
+
+
+///
+/// The only way to instantiate a ReaderMachO object  
+/// is via this createReaderMachO function.  The is no public 
+/// ReaderMachO class that you might be tempted to subclass.
+/// Support for all variants must be represented in the ReaderOptionsMachO
+/// object.
+/// The Reader object created retains a reference to the 
+/// ReaderOptionsMachO object supplied, so the objects object must not be  
+/// destroyed before the Reader object. 
+///
+Reader* createReaderMachO(const ReaderOptionsMachO &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READER_WRITER_READER_MACHO_H_

Added: lld/trunk/include/lld/ReaderWriter/ReaderNative.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ReaderNative.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ReaderNative.h (added)
+++ lld/trunk/include/lld/ReaderWriter/ReaderNative.h Thu May 31 17:34:00 2012
@@ -0,0 +1,63 @@
+//===- ReaderWriter/ReaderNative.h - Native File Format Reading Interface ---===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_READER_NATIVE_H_
+#define LLD_READERWRITER_READER_NATIVE_H_
+
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/Core/LLVM.h"
+
+
+namespace lld {
+
+/// 
+/// The ReaderOptionsNative class encapsulates options needed 
+/// to process mach-o files.  You can create an ReaderOptionsNative 
+/// instance from command line arguments or by subclassing and setting the 
+/// instance variables in the subclass's constructor.
+///
+class ReaderOptionsNative : public ReaderOptions {
+public:
+  virtual ~ReaderOptionsNative();
+
+  ///
+  /// Creates a Options object from darwin linker command line arguments.
+  /// FIXME: to be replaced with new option processing mechanism.
+  ///
+  ReaderOptionsNative(int argc, const char* argv[]);
+  
+  ///
+  /// Creates a Options object with default settings. For use when 
+  /// programmatically constructing options.
+  ///
+  ReaderOptionsNative();
+  
+protected:
+};
+ 
+
+
+
+///
+/// The only way to instantiate a ReaderNative object  
+/// is via this createReaderNative function.  The is no public 
+/// ReaderNative class that you might be tempted to subclass.
+/// Support for all variants must be represented in the ReaderOptionsNative
+/// object.
+/// The Reader object created retains a reference to the 
+/// ReaderOptionsNative object supplied, so the objects object must not be  
+/// destroyed before the Reader object. 
+///
+Reader* createReaderNative(const ReaderOptionsNative &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_READER_NATIVE_H_

Added: lld/trunk/include/lld/ReaderWriter/ReaderPECOFF.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ReaderPECOFF.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ReaderPECOFF.h (added)
+++ lld/trunk/include/lld/ReaderWriter/ReaderPECOFF.h Thu May 31 17:34:00 2012
@@ -0,0 +1,64 @@
+//===- ReaderWriter/ReaderPECOFF.h - PECOFF File Format Reading Interface ---===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_READER_PECOFF_H_
+#define LLD_READERWRITER_READER_PECOFF_H_
+
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/Core/LLVM.h"
+
+
+namespace lld {
+
+/// 
+/// The ReaderOptionsPECOFF class encapsulates options needed 
+/// to process mach-o files.  You can create an ReaderOptionsPECOFF 
+/// instance from command line arguments or by subclassing and setting the 
+/// instance variables in the subclass's constructor.
+///
+class ReaderOptionsPECOFF : public ReaderOptions {
+public:
+  virtual ~ReaderOptionsPECOFF();
+
+  ///
+  /// Creates a Options object from darwin linker command line arguments.
+  /// FIXME: to be replaced with new option processing mechanism.
+  ///
+  ReaderOptionsPECOFF(int argc, const char* argv[]);
+  
+  ///
+  /// Creates a Options object with default settings. For use when 
+  /// programmatically constructing options.
+  ///
+  ReaderOptionsPECOFF();
+
+  
+protected:
+};
+ 
+
+
+
+///
+/// The only way to instantiate a ReaderPECOFF object  
+/// is via this createReaderPECOFF function.  The is no public 
+/// ReaderPECOFF class that you might be tempted to subclass.
+/// Support for all variants must be represented in the ReaderOptionsPECOFF
+/// object.
+/// The Reader object created retains a reference to the 
+/// ReaderOptionsPECOFF object supplied, so the objects object must not be  
+/// destroyed before the Reader object. 
+///
+Reader* createReaderPECOFF(const ReaderOptionsPECOFF &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_READER_PECOFF_H_

Added: lld/trunk/include/lld/ReaderWriter/ReaderYAML.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ReaderYAML.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ReaderYAML.h (added)
+++ lld/trunk/include/lld/ReaderWriter/ReaderYAML.h Thu May 31 17:34:00 2012
@@ -0,0 +1,73 @@
+//===- ReaderWriter/ReaderYAML.h - YAML File Format Reading Interface -----===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_READER_YAML_H_
+#define LLD_READERWRITER_READER_YAML_H_
+
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Reference.h"
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+/// 
+/// The ReaderOptionsYAML class encapsulates options needed 
+/// to process mach-o files.  You can create an ReaderOptionsYAML 
+/// instance from command line arguments or by subclassing and setting the 
+/// instance variables in the subclass's constructor.
+///
+class ReaderOptionsYAML : public ReaderOptions {
+public:
+  virtual ~ReaderOptionsYAML();
+
+  ///
+  /// Creates a Options object from darwin linker command line arguments.
+  /// FIXME: to be replaced with new option processing mechanism.
+  ///
+  ReaderOptionsYAML(int argc, const char* argv[]);
+  
+  ///
+  /// Creates a Options object with default settings. For use when 
+  /// programmatically constructing options.
+  ///
+  ReaderOptionsYAML();
+
+
+  /// Converts a reference kind string to a in-memory numeric value.
+  /// Used when parsing YAML encoded object files.
+  virtual Reference::Kind kindFromString(StringRef) const = 0;
+
+  
+protected:
+};
+ 
+
+
+
+///
+/// The only way to instantiate a ReaderYAML object  
+/// is via this createReaderYAML function.  The is no public 
+/// ReaderYAML class that you might be tempted to subclass.
+/// Support for all variants must be represented in the ReaderOptionsYAML
+/// object.
+/// The Reader object created retains a reference to the 
+/// ReaderOptionsYAML object supplied, so the objects object must not be  
+/// destroyed before the Reader object. 
+///
+Reader* createReaderYAML(const ReaderOptionsYAML &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_READER_YAML_H_
+
+

Added: lld/trunk/include/lld/ReaderWriter/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/Writer.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/Writer.h (added)
+++ lld/trunk/include/lld/ReaderWriter/Writer.h Thu May 31 17:34:00 2012
@@ -0,0 +1,86 @@
+//===- ReaderWriter/Writer.h - Abstract File Format Interface -------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_H_
+#define LLD_READERWRITER_WRITER_H_
+
+#include "lld/Core/LLVM.h"
+#include <memory>
+#include <vector>
+
+namespace lld {
+class File;
+class InputFiles;
+class StubsPass;
+class GOTPass;
+
+
+///
+/// The Writer is an abstract class for writing object files, 
+/// shared library files, and executable files.  Each file format
+/// (e.g. ELF, mach-o, PECOFF, native, etc) have a concrete subclass
+/// of Writer.  
+///
+class Writer {
+public:
+  virtual ~Writer();
+  
+  /// Write a file from the supplied File object 
+  virtual error_code writeFile(const lld::File &linkedFile, StringRef path) = 0;
+  
+  /// Return a Pass object for creating stubs/PLT entries
+  virtual StubsPass *stubPass() {
+    return nullptr;
+  }
+  
+  /// Return a Pass object for creating GOT entries
+  virtual GOTPass *gotPass() {
+    return nullptr;
+  }
+  
+  /// This method is called by Core Linking to give the Writer a chance to
+  /// add file format specific "files" to set of files to be linked.
+  /// This is how file format specific atoms can be added to the link.
+  virtual void addFiles(InputFiles&) {
+  }
+  
+  
+protected:
+  // only concrete subclasses can be instantiated
+  Writer();
+};
+
+
+
+///
+/// The WriterOptions encapsulates the options used by Writers.  
+/// Each file format defines a subclass of WriterOptions
+/// to hold file format specific options.  The option objects are the only
+/// way to control the behaviour of Writers.
+///
+class WriterOptions {
+public:
+  // Any options common to all file formats will go here.
+
+protected:
+  // only concrete subclasses can be instantiated
+  WriterOptions();
+};
+
+
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_H_
+
+
+
+

Added: lld/trunk/include/lld/ReaderWriter/WriterELF.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/WriterELF.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/WriterELF.h (added)
+++ lld/trunk/include/lld/ReaderWriter/WriterELF.h Thu May 31 17:34:00 2012
@@ -0,0 +1,64 @@
+//===- ReaderWriter/WriterELF.h - ELF File Format Writing Interface -------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_ELF_H_
+#define LLD_READERWRITER_WRITER_ELF_H_
+
+#include "lld/ReaderWriter/Writer.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+/// 
+/// The WriterOptionsELF class encapsulates options needed 
+/// to process mach-o files.  You can create an WriterOptionsELF 
+/// instance from command line arguments or by subclassing and setting the 
+/// instance variables in the subclass's constructor.
+///
+class WriterOptionsELF : public WriterOptions {
+public:
+  virtual ~WriterOptionsELF();
+
+  ///
+  /// Creates a Options object from darwin linker command line arguments.
+  /// FIXME: to be replaced with new option processing mechanism.
+  ///
+  WriterOptionsELF(int argc, const char* argv[]);
+  
+  ///
+  /// Creates a Options object with default settings. For use when 
+  /// programmatically constructing options.
+  ///
+  WriterOptionsELF();
+  
+protected:
+};
+ 
+
+
+
+///
+/// The only way to instantiate a WriterELF object  
+/// is via this createWriterELF function.  The is no public 
+/// WriterELF class that you might be tempted to subclass.
+/// Support for all variants must be represented in the WriterOptionsELF
+/// object.
+/// The Writer object created retains a reference to the 
+/// WriterOptionsELF object supplied, so it must not be destroyed 
+/// before the Writer object. 
+///
+Writer* createWriterELF(const WriterOptionsELF &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_ELF_H_

Added: lld/trunk/include/lld/ReaderWriter/WriterMachO.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/WriterMachO.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/WriterMachO.h (added)
+++ lld/trunk/include/lld/ReaderWriter/WriterMachO.h Thu May 31 17:34:00 2012
@@ -0,0 +1,109 @@
+//===- ReaderWriter/WriterMachO.h - MachO File Format Reading Interface ---===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_MACHO_H_
+#define LLD_READERWRITER_WRITER_MACHO_H_
+
+#include "lld/ReaderWriter/Writer.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+/// 
+/// The WriterOptionsMachO class encapsulates options needed 
+/// to process mach-o files.  You can create an WriterOptionsMachO 
+/// instance from command line arguments or by subclassing and setting the 
+/// instance variables in the subclass's constructor.
+///
+class WriterOptionsMachO : public WriterOptions {
+public:
+  virtual ~WriterOptionsMachO();
+
+  ///
+  /// Creates a Options object from darwin linker command line arguments.
+  /// FIXME: to be replaced with new option processing mechanism.
+  ///
+  WriterOptionsMachO(int argc, const char* argv[]);
+  
+  ///
+  /// Creates a Options object with default settings. For use when 
+  /// programmatically constructing options.
+  ///
+  WriterOptionsMachO();
+
+
+
+  enum OutputKind {
+    outputDynamicExecutable,
+    outputDylib,
+    outputBundle,
+    outputObjectFile
+  };
+  
+  enum Architecture {
+    arch_x86_64,
+    arch_x86,
+    arch_arm,
+  };
+  
+  OutputKind outputKind() const       { return _outputkind; }
+  Architecture architecture() const   { return _architecture; }
+  StringRef archName() const          { return _archName; }
+  uint64_t  pageZeroSize() const      { return _pageZeroSize; }
+  uint32_t  cpuType() const           { return _cpuType; }
+  uint32_t  cpuSubtype() const        { return _cpuSubtype; }
+  bool      noTextRelocations() const { return _noTextRelocations; }
+  
+protected:
+  OutputKind      _outputkind;
+  StringRef       _archName;
+  Architecture    _architecture;
+  uint64_t        _pageZeroSize;
+  uint32_t        _cpuType;
+  uint32_t        _cpuSubtype;
+  bool            _noTextRelocations;
+};
+ 
+
+
+
+///
+/// The only way to instantiate a WriterMachO object  
+/// is via this createWriterMachO function.  The is no public 
+/// WriterMachO class that you might be tempted to subclass.
+/// Support for all variants must be represented in the 
+/// WriterOptionsMachO object.
+/// The Writer object created retains a reference to the 
+/// WriterOptionsMachO object supplied, so it must not be destroyed 
+/// before the Writer object. 
+///
+Writer* createWriterMachO(const WriterOptionsMachO &options);
+
+
+///
+/// Returns an options object that can be used with the 
+/// WriterYAML to write mach-o object files as YAML.
+///
+const class WriterOptionsYAML& writerOptionsMachOAsYAML(); 
+
+
+///
+/// Returns an options object that can be used with the 
+/// ReaderYAML to reader YAML encoded mach-o files.
+///
+const class ReaderOptionsYAML& readerOptionsMachOAsYAML(); 
+ 
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_MACHO_H_

Added: lld/trunk/include/lld/ReaderWriter/WriterNative.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/WriterNative.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/WriterNative.h (added)
+++ lld/trunk/include/lld/ReaderWriter/WriterNative.h Thu May 31 17:34:00 2012
@@ -0,0 +1,63 @@
+//===- ReaderWriter/WriterNative.h - Native File Format Reading Interface ---===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_NATIVE_H_
+#define LLD_READERWRITER_WRITER_NATIVE_H_
+
+#include "lld/ReaderWriter/Writer.h"
+#include "lld/Core/LLVM.h"
+
+
+namespace lld {
+
+/// 
+/// The WriterOptionsNative class encapsulates options needed 
+/// to process mach-o files.  You can create an WriterOptionsNative 
+/// instance from command line arguments or by subclassing and setting the 
+/// instance variables in the subclass's constructor.
+///
+class WriterOptionsNative : public WriterOptions {
+public:
+  virtual ~WriterOptionsNative();
+
+  ///
+  /// Creates a Options object from darwin linker command line arguments.
+  /// FIXME: to be replaced with new option processing mechanism.
+  ///
+  WriterOptionsNative(int argc, const char* argv[]);
+  
+  ///
+  /// Creates a Options object with default settings. For use when 
+  /// programmatically constructing options.
+  ///
+  WriterOptionsNative();
+  
+protected:
+};
+ 
+
+
+
+///
+/// The only way to instantiate a WriterNative object  
+/// is via this createWriterNative function.  The is no public 
+/// WriterNative class that you might be tempted to subclass.
+/// Support for all variants must be represented in the WriterOptionsNative
+/// object.
+/// The Writer object created retains a reference to the 
+/// WriterOptionsNative object supplied, so it must not be destroyed 
+/// before the Writer object. 
+///
+Writer* createWriterNative(const WriterOptionsNative &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_NATIVE_H_

Added: lld/trunk/include/lld/ReaderWriter/WriterPECOFF.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/WriterPECOFF.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/WriterPECOFF.h (added)
+++ lld/trunk/include/lld/ReaderWriter/WriterPECOFF.h Thu May 31 17:34:00 2012
@@ -0,0 +1,63 @@
+//===- ReaderWriter/WriterPECOFF.h - PECOFF File Format Writing Interface -===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_PECOFF_H_
+#define LLD_READERWRITER_WRITER_PECOFF_H_
+
+#include "lld/ReaderWriter/Writer.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+/// 
+/// The WriterOptionsPECOFF class encapsulates options needed 
+/// to process mach-o files.  You can create an WriterOptionsPECOFF 
+/// instance from command line arguments or by subclassing and setting the 
+/// instance variables in the subclass's constructor.
+///
+class WriterOptionsPECOFF : public WriterOptions {
+public:
+  virtual ~WriterOptionsPECOFF();
+
+  ///
+  /// Creates a Options object from darwin linker command line arguments.
+  /// FIXME: to be replaced with new option processing mechanism.
+  ///
+  WriterOptionsPECOFF(int argc, const char* argv[]);
+
+  ///
+  /// Creates a Options object with default settings. For use when 
+  /// programmatically constructing options.
+  ///
+  WriterOptionsPECOFF();
+
+protected:
+};
+
+
+
+///
+/// The only way to instantiate a WriterPECOFF object  
+/// is via this createWriterPECOFF function.  The is no public 
+/// WriterPECOFF class that you might be tempted to subclass.
+/// Support for all variants must be represented in the WriterOptionsPECOFF
+/// object.
+/// The Writer object created retains a reference to the 
+/// WriterOptionsPECOFF object supplied, so it must not be destroyed 
+/// before the Writer object. 
+///
+Writer* createWriterPECOFF(const WriterOptionsPECOFF &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_PECOFF_H_

Added: lld/trunk/include/lld/ReaderWriter/WriterYAML.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/WriterYAML.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/WriterYAML.h (added)
+++ lld/trunk/include/lld/ReaderWriter/WriterYAML.h Thu May 31 17:34:00 2012
@@ -0,0 +1,82 @@
+//===- ReaderWriter/WriterYAML.h - YAML File Format Writing Interface -----===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_YAML_H_
+#define LLD_READERWRITER_WRITER_YAML_H_
+
+#include "lld/ReaderWriter/Writer.h"
+
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/Pass.h"
+
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+/// 
+/// The WriterOptionsYAML class encapsulates options needed 
+/// to process mach-o files.  You can create an WriterOptionsYAML 
+/// instance from command line arguments or by subclassing and setting the 
+/// instance variables in the subclass's constructor.
+///
+class WriterOptionsYAML : public WriterOptions {
+public:
+  virtual ~WriterOptionsYAML();
+
+  ///
+  /// Creates a Options object from darwin linker command line arguments.
+  /// FIXME: to be replaced with new option processing mechanism.
+  ///
+  WriterOptionsYAML(int argc, const char* argv[]);
+  
+  ///
+  /// Creates a Options object with default settings. For use when 
+  /// programmatically constructing options.
+  ///
+  WriterOptionsYAML();
+  
+  
+  /// Converts an in-memory reference kind value to a string.
+  /// Used when writing YAML encoded object files.
+  virtual StringRef kindToString(Reference::Kind) const = 0;
+
+
+  /// Enable Stubs pass to be run
+  virtual StubsPass *stubPass() const {
+    return nullptr;
+  }
+  
+  /// Enable GOT pass to be run
+  virtual GOTPass *gotPass() const {
+    return nullptr;
+  }
+  
+};
+ 
+
+
+
+///
+/// The only way to instantiate a WriterYAML object  
+/// is via this createWriterYAML function.  The is no public 
+/// WriterYAML class that you might be tempted to subclass.
+/// Support for all variants must be represented in the WriterOptionsYAML
+/// object.
+/// The Writer object created retains a reference to the 
+/// WriterOptionsYAML object supplied, so it must not be destroyed 
+/// before the Writer object. 
+///
+Writer* createWriterYAML(const WriterOptionsYAML &options);
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_YAML_H_

Modified: lld/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/CMakeLists.txt?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/lib/CMakeLists.txt (original)
+++ lld/trunk/lib/CMakeLists.txt Thu May 31 17:34:00 2012
@@ -1,4 +1,3 @@
 add_subdirectory(Core)
 add_subdirectory(Passes)
-add_subdirectory(Platforms)
-add_subdirectory(Reader)
+add_subdirectory(ReaderWriter)

Modified: lld/trunk/lib/Core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/CMakeLists.txt?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/lib/Core/CMakeLists.txt (original)
+++ lld/trunk/lib/Core/CMakeLists.txt Thu May 31 17:34:00 2012
@@ -2,14 +2,6 @@
   Error.cpp
   File.cpp
   InputFiles.cpp
-  NativeFileFormat.h
-  NativeReader.cpp
-  NativeWriter.cpp
-  Platform.cpp
   Resolver.cpp
   SymbolTable.cpp
-  YamlKeyValues.cpp
-  YamlKeyValues.h
-  YamlReader.cpp
-  YamlWriter.cpp
   )

Modified: lld/trunk/lib/Core/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputFiles.cpp?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/lib/Core/InputFiles.cpp (original)
+++ lld/trunk/lib/Core/InputFiles.cpp Thu May 31 17:34:00 2012
@@ -35,6 +35,12 @@
   _files.push_back(&file);
 }
 
+void InputFiles::appendFiles(std::vector<std::unique_ptr<File>> &files) {
+  for (std::unique_ptr<File> &f : files) {
+    _files.push_back(f.release());
+  }
+}
+
 
 bool InputFiles::searchLibraries(StringRef name, bool searchSharedLibs,
                                bool searchArchives, bool dataSymbolOnly,

Removed: lld/trunk/lib/Core/NativeFileFormat.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeFileFormat.h?rev=157773&view=auto
==============================================================================
--- lld/trunk/lib/Core/NativeFileFormat.h (original)
+++ lld/trunk/lib/Core/NativeFileFormat.h (removed)
@@ -1,243 +0,0 @@
-//===- Core/NativeFileFormat.h - Describes native object file -------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_NATIVE_FILE_FORMAT_H_
-#define LLD_CORE_NATIVE_FILE_FORMAT_H_
-
-#include "llvm/Support/DataTypes.h"
-
-namespace lld {
-
-
-//
-// Overview:
-//
-// The number one design goal of this file format is enable the linker to
-// read object files into in-memory Atom objects extremely quickly.
-// The second design goal is to enable future modifications to the
-// Atom attribute model.
-//
-// The llvm native object file format is not like traditional object file
-// formats (e.g. ELF, COFF, mach-o).  There is no symbol table and no
-// sections.  Instead the file is essentially an array of archived Atoms.
-// It is *not* serialized Atoms which would require deserialization into
-// in memory objects.  Instead it is an array of read-only info about each
-// Atom.  The NativeReader bulk creates in-memory Atoms which just have
-// an ivar which points to the read-only info for that Atom. No additional
-// processing is done to construct the in-memory Atoms. All Atom attribute
-// getter methods are virtual calls which dig up the info they need from the
-// ivar data.
-//
-// To support the gradual evolution of Atom attributes, the Atom read-only
-// data is versioned. The NativeReader chooses which in-memory Atom class
-// to use based on the version. What this means is that if new attributes
-// are added (or changed) in the Atom model, a new native atom class and
-// read-only atom info struct needs to be defined.  Then, all the existing
-// native reader atom classes need to be modified to do their best effort
-// to map their old style read-only data to the new Atom model.  At some point
-// some classes to support old versions may be dropped.
-//
-//
-// Details:
-//
-// The native object file format consists of a header that specifies the
-// endianness of the file and the architecture along with a list of "chunks"
-// in the file.  A Chunk is simply a tagged range of the file.  There is
-// one chunk for the array of atom infos.  There is another chunk for the
-// string pool, and another for the content pool.
-//
-// It turns out there most atoms have very similar sets of attributes, only
-// the name and content attribute vary. To exploit this fact to reduce the file
-// size, the atom read-only info contains just the name and content info plus
-// a reference to which attribute set it uses.  The attribute sets are stored
-// in another chunk.
-//
-
-
-//
-// An entry in the NativeFileHeader that describes one chunk of the file.
-//
-struct NativeChunk {
-  uint32_t    signature;
-  uint32_t    fileOffset;
-  uint32_t    fileSize;
-  uint32_t    elementCount;
-};
-
-
-//
-// The header in a native object file
-//
-struct NativeFileHeader {
-  uint8_t     magic[16];
-  uint32_t    endian;
-  uint32_t    architecture;
-  uint32_t    fileSize;
-  uint32_t    chunkCount;
-  // NativeChunk chunks[]
-};
-
-//
-// Possible values for NativeChunk.signature field
-//
-enum NativeChunkSignatures {
-  NCS_DefinedAtomsV1 = 1,
-  NCS_AttributesArrayV1 = 2,
-  NCS_UndefinedAtomsV1 = 3,
-  NCS_SharedLibraryAtomsV1 = 4,
-  NCS_AbsoluteAtomsV1 = 5,
-  NCS_Strings = 6,
-  NCS_ReferencesArrayV1 = 7,
-  NCS_ReferencesArrayV2 = 8,
-  NCS_TargetsTable = 9,
-  NCS_AddendsTable = 10,
-  NCS_Content = 11,
-};
-
-//
-// The 16-bytes at the start of a native object file
-//
-#define NATIVE_FILE_HEADER_MAGIC "llvm nat obj v1 "
-
-//
-// Possible values for the NativeFileHeader.endian field
-//
-enum {
-  NFH_BigEndian     = 0x42696745,
-  NFH_LittleEndian  = 0x4574696c
-};
-
-
-//
-// Possible values for the NativeFileHeader.architecture field
-//
-enum {
-  NFA_x86     = 1,
-  NFA_x86_64  = 2,
-  NFA_armv6   = 3,
-  NFA_armv7   = 4,
-};
-
-
-//
-// The NCS_DefinedAtomsV1 chunk contains an array of these structs
-//
-struct NativeDefinedAtomIvarsV1 {
-  uint32_t  nameOffset;
-  uint32_t  attributesOffset;
-  uint32_t  referencesStartIndex;
-  uint32_t  referencesCount;
-  uint32_t  contentOffset;
-  uint32_t  contentSize;
-};
-
-
-//
-// The NCS_AttributesArrayV1 chunk contains an array of these structs
-//
-struct NativeAtomAttributesV1 {
-  uint32_t  sectionNameOffset;
-  uint16_t  align2;
-  uint16_t  alignModulus;
-  uint8_t   scope;
-  uint8_t   interposable;
-  uint8_t   merge;
-  uint8_t   contentType;
-  uint8_t   sectionChoice;
-  uint8_t   deadStrip;
-  uint8_t   permissions;
-  uint8_t   alias;
-};
-
-
-
-//
-// The NCS_UndefinedAtomsV1 chunk contains an array of these structs
-//
-struct NativeUndefinedAtomIvarsV1 {
-  uint32_t  nameOffset;
-  uint32_t  flags;
-};
-
-
-
-//
-// The NCS_SharedLibraryAtomsV1 chunk contains an array of these structs
-//
-struct NativeSharedLibraryAtomIvarsV1 {
-  uint32_t  nameOffset;
-  uint32_t  loadNameOffset;
-  uint32_t  flags;
-};
-
-
-
-//
-// The NCS_AbsoluteAtomsV1 chunk contains an array of these structs
-//
-struct NativeAbsoluteAtomIvarsV1 {
-  uint32_t  nameOffset;
-  uint32_t  reserved;
-  uint64_t  value;
-};
-
-
-
-//
-// The NCS_ReferencesArrayV1 chunk contains an array of these structs
-//
-struct NativeReferenceIvarsV1 {
-  enum {
-    noTarget = 0xFFFF
-  };
-  uint16_t  offsetInAtom;
-   int16_t  kind;
-  uint16_t  targetIndex;
-  uint16_t  addendIndex;
-};
-
-
-//
-// The NCS_ReferencesArrayV2 chunk contains an array of these structs
-//
-struct NativeReferenceIvarsV2 {
-  uint64_t  offsetInAtom;
-  int64_t   addend;
-  int32_t   kind;
-  uint32_t  targetIndex;
-};
-
-
-//
-// The NCS_TargetsTable chunk contains an array of uint32_t entries.
-// The C++ class Reference has a target() method that returns a
-// pointer to another Atom.  We can't have pointers in object files,
-// so instead  NativeReferenceIvarsV1 contains an index to the target.
-// The index is into this NCS_TargetsTable of uint32_t entries.
-// The values in this table are the index of the (target) atom in this file.
-// For DefinedAtoms the value is from 0 to NCS_DefinedAtomsV1.elementCount.
-// For UndefinedAtoms the value is from NCS_DefinedAtomsV1.elementCount to
-// NCS_DefinedAtomsV1.elementCount+NCS_UndefinedAtomsV1.elementCount.
-//
-
-
-//
-// The NCS_AddendsTable chunk contains an array of int64_t entries.
-// If we allocated space for addends directly in NativeReferenceIvarsV1
-// it would double the size of that struct.  But since addends are rare,
-// we instead just keep a pool of addends and have NativeReferenceIvarsV1
-// (if it needs an addend) just store the index (into the pool) of the
-// addend it needs.
-//
-
-
-
-} // namespace lld
-
-#endif // LLD_CORE_NATIVE_FILE_FORMAT_H_

Removed: lld/trunk/lib/Core/NativeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeReader.cpp?rev=157773&view=auto
==============================================================================
--- lld/trunk/lib/Core/NativeReader.cpp (original)
+++ lld/trunk/lib/Core/NativeReader.cpp (removed)
@@ -1,839 +0,0 @@
-//===- Core/NativeReader.cpp - reads native object file  ------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "NativeFileFormat.h"
-
-#include "lld/Core/Atom.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/File.h"
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
-
-#include <vector>
-#include <memory>
-
-namespace lld {
-
-// forward reference
-class NativeFile;
-
-//
-// An object of this class is instantied for each NativeDefinedAtomIvarsV1
-// struct in the NCS_DefinedAtomsV1 chunk.
-//
-class NativeDefinedAtomV1 : public DefinedAtom {
-public:
-      NativeDefinedAtomV1(const NativeFile& f,
-                          const NativeDefinedAtomIvarsV1* ivarData)
-        : _file(&f), _ivarData(ivarData) { }
-
-  virtual const class File& file() const;
-
-  virtual uint64_t ordinal() const;
-
-  virtual StringRef name() const;
-
-  virtual uint64_t size() const {
-    return _ivarData->contentSize;
-  }
-
-  virtual DefinedAtom::Scope scope() const {
-    return (DefinedAtom::Scope)(attributes().scope);
-  }
-
-  virtual DefinedAtom::Interposable interposable() const {
-    return (DefinedAtom::Interposable)(attributes().interposable);
-  }
-
-  virtual DefinedAtom::Merge merge() const {
-    return (DefinedAtom::Merge)(attributes().merge);
-  }
-
-  virtual DefinedAtom::ContentType contentType() const {
-    const NativeAtomAttributesV1& attr = attributes();
-    return (DefinedAtom::ContentType)(attr.contentType);
-  }
-
-  virtual DefinedAtom::Alignment alignment() const {
-    return DefinedAtom::Alignment(attributes().align2, attributes().alignModulus);
-  }
-
-  virtual DefinedAtom::SectionChoice sectionChoice() const {
-    return (DefinedAtom::SectionChoice)(attributes().sectionChoice);
-  }
-
-  virtual StringRef customSectionName() const;
-
-  virtual DefinedAtom::DeadStripKind deadStrip() const {
-     return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
-  }
-
-  virtual DefinedAtom::ContentPermissions permissions() const {
-     return (DefinedAtom::ContentPermissions)(attributes().permissions);
-  }
-
-  virtual bool isThumb() const {
-     return false; //(attributes().thumb != 0);
-  }
-
-  virtual bool isAlias() const {
-     return (attributes().alias != 0);
-  }
-
-  virtual ArrayRef<uint8_t> rawContent() const;
-
-  virtual reference_iterator begin() const;
-
-  virtual reference_iterator end() const;
-
-  virtual const Reference* derefIterator(const void*) const;
-
-  virtual void incrementIterator(const void*& it) const;
-
-private:
-  const NativeAtomAttributesV1& attributes() const;
-
-  const NativeFile*               _file;
-  const NativeDefinedAtomIvarsV1* _ivarData;
-};
-
-
-
-//
-// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
-// struct in the NCS_UndefinedAtomsV1 chunk.
-//
-class NativeUndefinedAtomV1 : public UndefinedAtom {
-public:
-       NativeUndefinedAtomV1(const NativeFile& f,
-                             const NativeUndefinedAtomIvarsV1* ivarData)
-        : _file(&f), _ivarData(ivarData) { }
-
-  virtual const File& file() const;
-  virtual StringRef name() const;
-
-  virtual CanBeNull canBeNull() const {
-    return (CanBeNull)(_ivarData->flags & 0x3);
-  }
-
-
-private:
-  const NativeFile*                 _file;
-  const NativeUndefinedAtomIvarsV1* _ivarData;
-};
-
-
-//
-// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
-// struct in the NCS_SharedLibraryAtomsV1 chunk.
-//
-class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
-public:
-       NativeSharedLibraryAtomV1(const NativeFile& f,
-                             const NativeSharedLibraryAtomIvarsV1* ivarData)
-        : _file(&f), _ivarData(ivarData) { }
-
-  virtual const File& file() const;
-  virtual StringRef name() const;
-  virtual StringRef loadName() const;
-
-  virtual bool canBeNullAtRuntime() const {
-    return (_ivarData->flags & 0x1);
-  }
-
-private:
-  const NativeFile*                     _file;
-  const NativeSharedLibraryAtomIvarsV1* _ivarData;
-};
-
-
-//
-// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
-// struct in the NCS_AbsoluteAtomsV1 chunk.
-//
-class NativeAbsoluteAtomV1 : public AbsoluteAtom {
-public:
-       NativeAbsoluteAtomV1(const NativeFile& f,
-                             const NativeAbsoluteAtomIvarsV1* ivarData)
-        : _file(&f), _ivarData(ivarData) { }
-
-  virtual const File& file() const;
-  virtual StringRef name() const;
-
-  virtual uint64_t value() const {
-    return _ivarData->value;
-  }
-
-private:
-  const NativeFile*                 _file;
-  const NativeAbsoluteAtomIvarsV1*  _ivarData;
-};
-
-
-
-//
-// An object of this class is instantied for each NativeReferenceIvarsV1
-// struct in the NCS_ReferencesArrayV1 chunk.
-//
-class NativeReferenceV1 : public Reference {
-public:
-       NativeReferenceV1(const NativeFile& f,
-                             const NativeReferenceIvarsV1* ivarData)
-        : _file(&f), _ivarData(ivarData) { }
-
-  virtual uint64_t offsetInAtom() const {
-    return _ivarData->offsetInAtom;
-  }
-
-  virtual Kind kind() const {
-    return _ivarData->kind;
-  }
-
-  virtual void setKind(Kind);
-  virtual const Atom* target() const;
-  virtual Addend addend() const;
-  virtual void setTarget(const Atom* newAtom);
-  virtual void setAddend(Addend a);
-
-private:
-  // Used in rare cases when Reference is modified,
-  // since ivar data is mapped read-only.
-  void cloneIvarData() {
-    // TODO: do nothing on second call
-   NativeReferenceIvarsV1* niv = reinterpret_cast<NativeReferenceIvarsV1*>
-                                (operator new(sizeof(NativeReferenceIvarsV1),
-                                                                std::nothrow));
-    memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
-  }
-
-  const NativeFile*                 _file;
-  const NativeReferenceIvarsV1*     _ivarData;
-};
-
-
-
-//
-// lld::File object for native llvm object file
-//
-class NativeFile : public File {
-public:
-
-  /// Instantiates a File object from a native object file.  Ownership
-  /// of the MemoryBuffer is transfered to the resulting File object.
-  static error_code make(std::unique_ptr<llvm::MemoryBuffer> mb,
-                         StringRef path,
-                         std::unique_ptr<File> &result) {
-    const uint8_t* const base =
-                       reinterpret_cast<const uint8_t*>(mb->getBufferStart());
-    const NativeFileHeader* const header =
-                       reinterpret_cast<const NativeFileHeader*>(base);
-    const NativeChunk *const chunks =
-      reinterpret_cast<const NativeChunk*>(base + sizeof(NativeFileHeader));
-    // make sure magic matches
-    if ( memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 16) != 0 )
-      return make_error_code(native_reader_error::unknown_file_format);
-
-    // make sure mapped file contains all needed data
-    const size_t fileSize = mb->getBufferSize();
-    if ( header->fileSize > fileSize )
-      return make_error_code(native_reader_error::file_too_short);
-
-    // instantiate NativeFile object and add values to it as found
-    std::unique_ptr<NativeFile> file(new NativeFile(std::move(mb), path));
-
-    // process each chunk
-    for(uint32_t i=0; i < header->chunkCount; ++i) {
-      error_code ec;
-      const NativeChunk* chunk = &chunks[i];
-      // sanity check chunk is within file
-      if ( chunk->fileOffset > fileSize )
-        return make_error_code(native_reader_error::file_malformed);
-      if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
-        return make_error_code(native_reader_error::file_malformed);
-      // process chunk, based on signature
-      switch ( chunk->signature ) {
-        case NCS_DefinedAtomsV1:
-          ec = file->processDefinedAtomsV1(base, chunk);
-          break;
-        case NCS_AttributesArrayV1:
-          ec = file->processAttributesV1(base, chunk);
-          break;
-        case NCS_UndefinedAtomsV1:
-          ec = file->processUndefinedAtomsV1(base, chunk);
-          break;
-        case NCS_SharedLibraryAtomsV1:
-          ec = file->processSharedLibraryAtomsV1(base, chunk);
-          break;
-        case NCS_AbsoluteAtomsV1:
-          ec = file->processAbsoluteAtomsV1(base, chunk);
-          break;
-        case NCS_ReferencesArrayV1:
-          ec = file->processReferencesV1(base, chunk);
-          break;
-        case NCS_TargetsTable:
-          ec = file->processTargetsTable(base, chunk);
-          break;
-        case NCS_AddendsTable:
-          ec = file->processAddendsTable(base, chunk);
-          break;
-        case NCS_Content:
-          ec = file->processContent(base, chunk);
-          break;
-        case NCS_Strings:
-          ec = file->processStrings(base, chunk);
-          break;
-        default:
-          return make_error_code(native_reader_error::unknown_chunk_type);
-      }
-      if ( ec ) {
-        return ec;
-      }
-      // TO DO: validate enough chunks were used
-    }
-
-    result.reset(file.release());
-    return make_error_code(native_reader_error::success);
-  }
-
-  virtual ~NativeFile() {
-    // _buffer is automatically deleted because of OwningPtr<>
-
-    // All other ivar pointers are pointers into the MemoryBuffer, except
-    // the _definedAtoms array which was allocated to contain an array
-    // of Atom objects.  The atoms have empty destructors, so it is ok
-    // to just delete the memory.
-    delete _definedAtoms._arrayStart;
-    delete _undefinedAtoms._arrayStart;
-    delete _sharedLibraryAtoms._arrayStart;
-    delete _absoluteAtoms._arrayStart;
-    delete _references.arrayStart;
-    delete _targetsTable;
-  }
-
-  virtual const atom_collection<DefinedAtom>&  defined() const {
-    return _definedAtoms;
-  }
-  virtual const atom_collection<UndefinedAtom>& undefined() const {
-      return _undefinedAtoms;
-  }
-  virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
-      return _sharedLibraryAtoms;
-  }
-  virtual const atom_collection<AbsoluteAtom>& absolute() const {
-      return _absoluteAtoms;
-  }
-
-  virtual void addAtom(const Atom&) {
-    assert(0 && "cannot add atoms to native .o files");
-  }
-
-private:
-  friend class NativeDefinedAtomV1;
-  friend class NativeUndefinedAtomV1;
-  friend class NativeSharedLibraryAtomV1;
-  friend class NativeAbsoluteAtomV1;
-  friend class NativeReferenceV1;
-
-  // instantiate array of DefinedAtoms from v1 ivar data in file
-  error_code processDefinedAtomsV1(const uint8_t *base,
-                                   const NativeChunk *chunk) {
-    const size_t atomSize = sizeof(NativeDefinedAtomV1);
-    size_t atomsArraySize = chunk->elementCount * atomSize;
-    uint8_t* atomsStart = reinterpret_cast<uint8_t*>
-                                (operator new(atomsArraySize, std::nothrow));
-    if (atomsStart == nullptr)
-      return make_error_code(native_reader_error::memory_error);
-    const size_t ivarElementSize = chunk->fileSize
-                                          / chunk->elementCount;
-    if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
-      return make_error_code(native_reader_error::file_malformed);
-    uint8_t* atomsEnd = atomsStart + atomsArraySize;
-    const NativeDefinedAtomIvarsV1* ivarData =
-                             reinterpret_cast<const NativeDefinedAtomIvarsV1*>
-                                                  (base + chunk->fileOffset);
-    for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
-      NativeDefinedAtomV1* atomAllocSpace =
-                  reinterpret_cast<NativeDefinedAtomV1*>(s);
-      new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
-      ++ivarData;
-    }
-    this->_definedAtoms._arrayStart = atomsStart;
-    this->_definedAtoms._arrayEnd = atomsEnd;
-    this->_definedAtoms._elementSize = atomSize;
-    this->_definedAtoms._elementCount = chunk->elementCount;
-    return make_error_code(native_reader_error::success);
-  }
-
-  // set up pointers to attributes array
-  error_code processAttributesV1(const uint8_t *base,
-                                 const NativeChunk *chunk) {
-    this->_attributes = base + chunk->fileOffset;
-    this->_attributesMaxOffset = chunk->fileSize;
-    return make_error_code(native_reader_error::success);
-  }
-
-  // instantiate array of UndefinedAtoms from v1 ivar data in file
-  error_code processUndefinedAtomsV1(const uint8_t *base,
-                                     const NativeChunk *chunk) {
-    const size_t atomSize = sizeof(NativeUndefinedAtomV1);
-    size_t atomsArraySize = chunk->elementCount * atomSize;
-    uint8_t* atomsStart = reinterpret_cast<uint8_t*>
-                                (operator new(atomsArraySize, std::nothrow));
-    if (atomsStart == nullptr)
-      return make_error_code(native_reader_error::memory_error);
-    const size_t ivarElementSize = chunk->fileSize
-                                          / chunk->elementCount;
-    if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
-      return make_error_code(native_reader_error::file_malformed);
-    uint8_t* atomsEnd = atomsStart + atomsArraySize;
-    const NativeUndefinedAtomIvarsV1* ivarData =
-                            reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
-                                                  (base + chunk->fileOffset);
-    for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
-      NativeUndefinedAtomV1* atomAllocSpace =
-                  reinterpret_cast<NativeUndefinedAtomV1*>(s);
-      new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
-      ++ivarData;
-    }
-    this->_undefinedAtoms._arrayStart = atomsStart;
-    this->_undefinedAtoms._arrayEnd = atomsEnd;
-    this->_undefinedAtoms._elementSize = atomSize;
-    this->_undefinedAtoms._elementCount = chunk->elementCount;
-    return make_error_code(native_reader_error::success);
-  }
-
-
-  // instantiate array of ShareLibraryAtoms from v1 ivar data in file
-  error_code processSharedLibraryAtomsV1(const uint8_t *base,
-                                         const NativeChunk *chunk) {
-    const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
-    size_t atomsArraySize = chunk->elementCount * atomSize;
-    uint8_t* atomsStart = reinterpret_cast<uint8_t*>
-                                (operator new(atomsArraySize, std::nothrow));
-    if (atomsStart == nullptr)
-      return make_error_code(native_reader_error::memory_error);
-    const size_t ivarElementSize = chunk->fileSize
-                                          / chunk->elementCount;
-    if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
-      return make_error_code(native_reader_error::file_malformed);
-    uint8_t* atomsEnd = atomsStart + atomsArraySize;
-    const NativeSharedLibraryAtomIvarsV1* ivarData =
-                      reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
-                                                  (base + chunk->fileOffset);
-    for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
-      NativeSharedLibraryAtomV1* atomAllocSpace =
-                  reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
-      new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
-      ++ivarData;
-    }
-    this->_sharedLibraryAtoms._arrayStart = atomsStart;
-    this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
-    this->_sharedLibraryAtoms._elementSize = atomSize;
-    this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
-    return make_error_code(native_reader_error::success);
-  }
-
-
-   // instantiate array of AbsoluteAtoms from v1 ivar data in file
-  error_code processAbsoluteAtomsV1(const uint8_t *base,
-                                    const NativeChunk *chunk) {
-    const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
-    size_t atomsArraySize = chunk->elementCount * atomSize;
-    uint8_t* atomsStart = reinterpret_cast<uint8_t*>
-                                (operator new(atomsArraySize, std::nothrow));
-    if (atomsStart == nullptr)
-      return make_error_code(native_reader_error::memory_error);
-    const size_t ivarElementSize = chunk->fileSize
-                                          / chunk->elementCount;
-    if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
-      return make_error_code(native_reader_error::file_malformed);
-    uint8_t* atomsEnd = atomsStart + atomsArraySize;
-    const NativeAbsoluteAtomIvarsV1* ivarData =
-                      reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
-                                                  (base + chunk->fileOffset);
-    for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
-      NativeAbsoluteAtomV1* atomAllocSpace =
-                  reinterpret_cast<NativeAbsoluteAtomV1*>(s);
-      new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
-      ++ivarData;
-    }
-    this->_absoluteAtoms._arrayStart = atomsStart;
-    this->_absoluteAtoms._arrayEnd = atomsEnd;
-    this->_absoluteAtoms._elementSize = atomSize;
-    this->_absoluteAtoms._elementCount = chunk->elementCount;
-    return make_error_code(native_reader_error::success);
-  }
-
-
-
-
-  // instantiate array of Referemces from v1 ivar data in file
-  error_code processReferencesV1(const uint8_t *base,
-                                 const NativeChunk *chunk) {
-    if ( chunk->elementCount == 0 )
-      return make_error_code(native_reader_error::success);
-    const size_t refSize = sizeof(NativeReferenceV1);
-    size_t refsArraySize = chunk->elementCount * refSize;
-    uint8_t* refsStart = reinterpret_cast<uint8_t*>
-                                (operator new(refsArraySize, std::nothrow));
-    if (refsStart == nullptr)
-      return make_error_code(native_reader_error::memory_error);
-    const size_t ivarElementSize = chunk->fileSize
-                                          / chunk->elementCount;
-    if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
-      return make_error_code(native_reader_error::file_malformed);
-    uint8_t* refsEnd = refsStart + refsArraySize;
-    const NativeReferenceIvarsV1* ivarData =
-                             reinterpret_cast<const NativeReferenceIvarsV1*>
-                                                  (base + chunk->fileOffset);
-    for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
-      NativeReferenceV1* atomAllocSpace =
-                  reinterpret_cast<NativeReferenceV1*>(s);
-      new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
-      ++ivarData;
-    }
-    this->_references.arrayStart = refsStart;
-    this->_references.arrayEnd = refsEnd;
-    this->_references.elementSize = refSize;
-    this->_references.elementCount = chunk->elementCount;
-    return make_error_code(native_reader_error::success);
-  }
-
-  // set up pointers to target table
-  error_code processTargetsTable(const uint8_t *base,
-                                 const NativeChunk *chunk) {
-    const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
-                                                  (base + chunk->fileOffset);
-    this->_targetsTableCount = chunk->elementCount;
-    this->_targetsTable = new const Atom*[chunk->elementCount];
-    for (uint32_t i=0; i < chunk->elementCount; ++i) {
-      const uint32_t index = targetIndexes[i];
-      if ( index < _definedAtoms._elementCount ) {
-        const uint8_t* p = _definedAtoms._arrayStart
-                                    + index * _definedAtoms._elementSize;
-        this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
-        continue;
-      }
-      const uint32_t undefIndex = index - _definedAtoms._elementCount;
-      if ( undefIndex < _undefinedAtoms._elementCount ) {
-        const uint8_t* p = _undefinedAtoms._arrayStart
-                                    + undefIndex * _undefinedAtoms._elementSize;
-        this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
-        continue;
-      }
-      const uint32_t slIndex = index - _definedAtoms._elementCount
-                                     - _undefinedAtoms._elementCount;
-      if ( slIndex < _sharedLibraryAtoms._elementCount ) {
-        const uint8_t* p = _sharedLibraryAtoms._arrayStart
-                                  + slIndex * _sharedLibraryAtoms._elementSize;
-        this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
-        continue;
-      }
-      const uint32_t abIndex = index - _definedAtoms._elementCount
-                                     - _undefinedAtoms._elementCount
-                                     - _sharedLibraryAtoms._elementCount;
-      if ( abIndex < _absoluteAtoms._elementCount ) {
-        const uint8_t* p = _absoluteAtoms._arrayStart
-                                  + slIndex * _absoluteAtoms._elementSize;
-        this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
-        continue;
-      }
-     return make_error_code(native_reader_error::file_malformed);
-    }
-    return make_error_code(native_reader_error::success);
-  }
-
-
-  // set up pointers to addend pool in file
-  error_code processAddendsTable(const uint8_t *base,
-                                 const NativeChunk *chunk) {
-    this->_addends = reinterpret_cast<const Reference::Addend*>
-                                                  (base + chunk->fileOffset);
-    this->_addendsMaxIndex = chunk->elementCount;
-    return make_error_code(native_reader_error::success);
-  }
-
-  // set up pointers to string pool in file
-  error_code processStrings(const uint8_t *base,
-                            const NativeChunk *chunk) {
-    this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
-    this->_stringsMaxOffset = chunk->fileSize;
-    return make_error_code(native_reader_error::success);
-  }
-
-  // set up pointers to content area in file
-  error_code processContent(const uint8_t *base,
-                            const NativeChunk *chunk) {
-    this->_contentStart = base + chunk->fileOffset;
-    this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
-    return make_error_code(native_reader_error::success);
-  }
-
-  StringRef string(uint32_t offset) const {
-    assert(offset < _stringsMaxOffset);
-    return StringRef(&_strings[offset]);
-  }
-
-  Reference::Addend addend(uint32_t index) const {
-    if ( index == 0 )
-      return 0; // addend index zero is used to mean "no addend"
-    assert(index <= _addendsMaxIndex);
-    return _addends[index-1]; // one-based indexing
-  }
-
-  const NativeAtomAttributesV1& attribute(uint32_t off) const {
-    assert(off < _attributesMaxOffset);
-    return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
-  }
-
-  const uint8_t* content(uint32_t offset, uint32_t size) const {
-    const uint8_t* result = _contentStart + offset;
-    assert((result+size) <= _contentEnd);
-    return result;
-  }
-
-  const Reference* referenceByIndex(uintptr_t index) const {
-    assert(index < _references.elementCount);
-    const uint8_t* p = _references.arrayStart + index * _references.elementSize;
-    return reinterpret_cast<const NativeReferenceV1*>(p);
-  }
-
-  const Atom* target(uint16_t index) const {
-    if ( index == NativeReferenceIvarsV1::noTarget )
-      return nullptr;
-    assert(index < _targetsTableCount);
-    return _targetsTable[index];
-  }
-
-  void setTarget(uint16_t index, const Atom* newAtom) const {
-    assert(index != NativeReferenceIvarsV1::noTarget);
-    assert(index > _targetsTableCount);
-    _targetsTable[index] = newAtom;
-  }
-  
-
-
-  // private constructor, only called by make()
-  NativeFile(std::unique_ptr<llvm::MemoryBuffer> mb, StringRef path) :
-    File(path),
-    _buffer(std::move(mb)),  // NativeFile now takes ownership of buffer
-    _header(nullptr),
-    _targetsTable(nullptr),
-    _targetsTableCount(0),
-    _strings(nullptr),
-    _stringsMaxOffset(0),
-    _addends(nullptr),
-    _addendsMaxIndex(0),
-    _contentStart(nullptr),
-    _contentEnd(nullptr)
-  {
-    _header = reinterpret_cast<const NativeFileHeader*>
-                                                  (_buffer->getBufferStart());
-  }
-
-  template <typename T>
-  class AtomArray : public File::atom_collection<T> {
-  public:
-     AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
-                   _elementSize(0), _elementCount(0) { }
-
-    virtual atom_iterator<T> begin() const {
-      return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
-    }
-    virtual atom_iterator<T> end() const{
-      return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
-    }
-    virtual const T* deref(const void* it) const {
-      return reinterpret_cast<const T*>(it);
-    }
-    virtual void next(const void*& it) const {
-      const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
-      p += _elementSize;
-      it = reinterpret_cast<const void*>(p);
-    }
-    const uint8_t*     _arrayStart;
-    const uint8_t*     _arrayEnd;
-    uint32_t           _elementSize;
-    uint32_t           _elementCount;
-  };
-
-  struct IvarArray {
-                      IvarArray() :
-                        arrayStart(nullptr),
-                        arrayEnd(nullptr),
-                        elementSize(0),
-                        elementCount(0) { }
-
-    const uint8_t*     arrayStart;
-    const uint8_t*     arrayEnd;
-    uint32_t           elementSize;
-    uint32_t           elementCount;
-  };
-
-
-  std::unique_ptr<llvm::MemoryBuffer> _buffer;
-  const NativeFileHeader*         _header;
-  AtomArray<DefinedAtom>          _definedAtoms;
-  AtomArray<UndefinedAtom>        _undefinedAtoms;
-  AtomArray<SharedLibraryAtom>    _sharedLibraryAtoms;
-  AtomArray<AbsoluteAtom>         _absoluteAtoms;
-  const uint8_t*                  _attributes;
-  uint32_t                        _attributesMaxOffset;
-  IvarArray                       _references;
-  const Atom**                    _targetsTable;
-  uint32_t                        _targetsTableCount;
-  const char*                     _strings;
-  uint32_t                        _stringsMaxOffset;
-  const Reference::Addend*        _addends;
-  uint32_t                        _addendsMaxIndex;
-  const uint8_t*                  _contentStart;
-  const uint8_t*                  _contentEnd;
-};
-
-
-inline const class File& NativeDefinedAtomV1::file() const {
-  return *_file;
-}
-
-inline uint64_t NativeDefinedAtomV1:: ordinal() const {
-  const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
-  return p - _file->_definedAtoms._arrayStart;
-}
-
-inline StringRef NativeDefinedAtomV1::name() const {
-  return _file->string(_ivarData->nameOffset);
-}
-
-inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
-  return _file->attribute(_ivarData->attributesOffset);
-}
-
-inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
-  if ( this->contentType() == DefinedAtom::typeZeroFill )
-    return ArrayRef<uint8_t>();
-  const uint8_t* p = _file->content(_ivarData->contentOffset,
-                                    _ivarData->contentSize);
-   return ArrayRef<uint8_t>(p, _ivarData->contentSize);
-}
-
-inline StringRef NativeDefinedAtomV1::customSectionName() const {
-  uint32_t offset = attributes().sectionNameOffset;
-  return _file->string(offset);
-}
-
-DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
-  uintptr_t index = _ivarData->referencesStartIndex;
-  const void* it = reinterpret_cast<const void*>(index);
-  return reference_iterator(*this, it);
-}
-
-DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
-  uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
-  const void* it = reinterpret_cast<const void*>(index);
-  return reference_iterator(*this, it);
-}
-
-const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
-  uintptr_t index = reinterpret_cast<uintptr_t>(it);
-  return _file->referenceByIndex(index);
-}
-
-void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
-  uintptr_t index = reinterpret_cast<uintptr_t>(it);
-  ++index;
-  it = reinterpret_cast<const void*>(index);
-}
-
-inline const class File& NativeUndefinedAtomV1::file() const {
-  return *_file;
-}
-
-inline StringRef NativeUndefinedAtomV1::name() const {
-  return _file->string(_ivarData->nameOffset);
-}
-
-
-
-
-inline const class File& NativeSharedLibraryAtomV1::file() const {
-  return *_file;
-}
-
-inline StringRef NativeSharedLibraryAtomV1::name() const {
-  return _file->string(_ivarData->nameOffset);
-}
-
-inline StringRef NativeSharedLibraryAtomV1::loadName() const {
-  return _file->string(_ivarData->loadNameOffset);
-}
-
-
-
-inline const class File& NativeAbsoluteAtomV1::file() const {
-  return *_file;
-}
-
-inline StringRef NativeAbsoluteAtomV1::name() const {
-  return _file->string(_ivarData->nameOffset);
-}
-
-
-inline const Atom* NativeReferenceV1::target() const {
-  return _file->target(_ivarData->targetIndex);
-}
-
-inline Reference::Addend NativeReferenceV1::addend() const {
-  return _file->addend(_ivarData->addendIndex);
-}
-
-inline void NativeReferenceV1::setKind(Kind k) {
-  this->cloneIvarData();
-  const_cast<NativeReferenceIvarsV1*>(_ivarData)->kind = k;
-}
-
-inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
-  return _file->setTarget(_ivarData->targetIndex, newAtom);
-}
-
-inline void NativeReferenceV1::setAddend(Addend a) {
-  assert(0 && "setAddend() not supported");
-}
-
-
-//
-// Instantiate an lld::File from the given native object file buffer
-//
-error_code parseNativeObjectFile(std::unique_ptr<llvm::MemoryBuffer> mb,
-                                 StringRef path,
-                                 std::unique_ptr<File> &result) {
-  return NativeFile::make(std::move(mb), path, result);
-}
-
-
-
-//
-// Instantiate an lld::File from the given native object file path
-//
-error_code parseNativeObjectFileOrSTDIN(StringRef path,
-                                        std::unique_ptr<File>& result) {
-  OwningPtr<llvm::MemoryBuffer> mb;
-  error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb);
-  if ( ec )
-      return ec;
-
-  return parseNativeObjectFile( std::unique_ptr<llvm::MemoryBuffer>(mb.take())
-                              , path
-                              , result);
-}
-
-} // namespace lld

Removed: lld/trunk/lib/Core/NativeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeWriter.cpp?rev=157773&view=auto
==============================================================================
--- lld/trunk/lib/Core/NativeWriter.cpp (original)
+++ lld/trunk/lib/Core/NativeWriter.cpp (removed)
@@ -1,555 +0,0 @@
-//===- Core/NativeWriter.cpp - Creates a native object file ---------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/NativeWriter.h"
-#include "NativeFileFormat.h"
-#include "lld/Core/File.h"
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringRef.h"
-
-#include <vector>
-
-namespace lld {
-
-
-///
-/// Class for writing native object files.
-///
-class NativeWriter {
-public:
-  /// construct writer for an lld::File object
-  NativeWriter(const lld::File& file) : _file(file) {
-    // reserve first byte for unnamed atoms
-    _stringPool.push_back('\0');
-    // visit all atoms
-    for ( const DefinedAtom *defAtom : file.defined() ) {
-      this->addIVarsForDefinedAtom(*defAtom);
-    }
-    for ( const UndefinedAtom *undefAtom : file.undefined() ) {
-      this->addIVarsForUndefinedAtom(*undefAtom);
-    }
-    for ( const SharedLibraryAtom *shlibAtom : file.sharedLibrary() ) {
-      this->addIVarsForSharedLibraryAtom(*shlibAtom);
-    }
-    for ( const AbsoluteAtom *absAtom : file.absolute() ) {
-      this->addIVarsForAbsoluteAtom(*absAtom);
-    }
-
-
-
-    // construct file header based on atom information accumulated
-    makeHeader();
-  }
-
-  // write the lld::File in native format to the specified stream
-  void write(raw_ostream &out) {
-    assert( out.tell() == 0 );
-    out.write((char*)_headerBuffer, _headerBufferSize);
-
-    if (!_definedAtomIvars.empty()) {
-      assert( out.tell() == findChunk(NCS_DefinedAtomsV1).fileOffset );
-      out.write((char*)&_definedAtomIvars[0],
-                _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1));
-    }
-
-    if (!_attributes.empty()) {
-      assert( out.tell() == findChunk(NCS_AttributesArrayV1).fileOffset );
-      out.write((char*)&_attributes[0],
-                _attributes.size()*sizeof(NativeAtomAttributesV1));
-    }
-
-    if ( !_undefinedAtomIvars.empty() ) {
-      assert( out.tell() == findChunk(NCS_UndefinedAtomsV1).fileOffset );
-      out.write((char*)&_undefinedAtomIvars[0],
-              _undefinedAtomIvars.size()*sizeof(NativeUndefinedAtomIvarsV1));
-    }
-
-     if ( !_sharedLibraryAtomIvars.empty() ) {
-      assert( out.tell() == findChunk(NCS_SharedLibraryAtomsV1).fileOffset );
-      out.write((char*)&_sharedLibraryAtomIvars[0],
-              _sharedLibraryAtomIvars.size()
-              * sizeof(NativeSharedLibraryAtomIvarsV1));
-    }
-
-    if ( !_absoluteAtomIvars.empty() ) {
-      assert( out.tell() == findChunk(NCS_AbsoluteAtomsV1).fileOffset );
-      out.write((char*)&_absoluteAtomIvars[0],
-              _absoluteAtomIvars.size()
-              * sizeof(NativeAbsoluteAtomIvarsV1));
-    }
-
-    if (!_stringPool.empty()) {
-      assert( out.tell() == findChunk(NCS_Strings).fileOffset );
-      out.write(&_stringPool[0], _stringPool.size());
-    }
-
-    if ( !_references.empty() ) {
-      assert( out.tell() == findChunk(NCS_ReferencesArrayV1).fileOffset );
-      out.write((char*)&_references[0],
-              _references.size()*sizeof(NativeReferenceIvarsV1));
-    }
-
-    if ( !_targetsTableIndex.empty() ) {
-      assert( out.tell() == findChunk(NCS_TargetsTable).fileOffset );
-      writeTargetTable(out);
-    }
-
-    if ( !_addendsTableIndex.empty() ) {
-      assert( out.tell() == findChunk(NCS_AddendsTable).fileOffset );
-      writeAddendTable(out);
-    }
-
-    if (!_contentPool.empty()) {
-      assert( out.tell() == findChunk(NCS_Content).fileOffset );
-      out.write((char*)&_contentPool[0], _contentPool.size());
-    }
-  }
-
-private:
-
-  void addIVarsForDefinedAtom(const DefinedAtom& atom) {
-    _definedAtomIndex[&atom] = _definedAtomIvars.size();
-    NativeDefinedAtomIvarsV1 ivar;
-    unsigned refsCount;
-    ivar.nameOffset = getNameOffset(atom);
-    ivar.attributesOffset = getAttributeOffset(atom);
-    ivar.referencesStartIndex = getReferencesIndex(atom, refsCount);
-    ivar.referencesCount = refsCount;
-    ivar.contentOffset = getContentOffset(atom);
-    ivar.contentSize = atom.size();
-    _definedAtomIvars.push_back(ivar);
-  }
-
-  void addIVarsForUndefinedAtom(const UndefinedAtom& atom) {
-    _undefinedAtomIndex[&atom] = _undefinedAtomIvars.size();
-    NativeUndefinedAtomIvarsV1 ivar;
-    ivar.nameOffset = getNameOffset(atom);
-    ivar.flags = (atom.canBeNull() & 0x03);
-    _undefinedAtomIvars.push_back(ivar);
-  }
-
-  void addIVarsForSharedLibraryAtom(const SharedLibraryAtom& atom) {
-    _sharedLibraryAtomIndex[&atom] = _sharedLibraryAtomIvars.size();
-    NativeSharedLibraryAtomIvarsV1 ivar;
-    ivar.nameOffset = getNameOffset(atom);
-    ivar.loadNameOffset = getSharedLibraryNameOffset(atom.loadName());
-    ivar.flags = atom.canBeNullAtRuntime();
-    _sharedLibraryAtomIvars.push_back(ivar);
-  }
-
-  void addIVarsForAbsoluteAtom(const AbsoluteAtom& atom) {
-    _absoluteAtomIndex[&atom] = _absoluteAtomIvars.size();
-    NativeAbsoluteAtomIvarsV1 ivar;
-    ivar.nameOffset = getNameOffset(atom);
-    ivar.reserved = 0;
-    ivar.value = atom.value();
-    _absoluteAtomIvars.push_back(ivar);
-  }
-
-  // fill out native file header and chunk directory
-  void makeHeader() {
-    const bool hasDefines = !_definedAtomIvars.empty();
-    const bool hasUndefines = !_undefinedAtomIvars.empty();
-    const bool hasSharedLibraries = !_sharedLibraryAtomIvars.empty();
-    const bool hasAbsolutes = !_absoluteAtomIvars.empty();
-    const bool hasReferences = !_references.empty();
-    const bool hasTargetsTable = !_targetsTableIndex.empty();
-    const bool hasAddendTable = !_addendsTableIndex.empty();
-    const bool hasContent = !_contentPool.empty();
-
-    int chunkCount = 1; // always have string pool chunk
-    if ( hasDefines ) chunkCount += 2;
-    if ( hasUndefines ) ++chunkCount;
-    if ( hasSharedLibraries ) ++chunkCount;
-    if ( hasAbsolutes ) ++chunkCount;
-    if ( hasReferences ) ++chunkCount;
-    if ( hasTargetsTable ) ++chunkCount;
-    if ( hasAddendTable ) ++chunkCount;
-    if ( hasContent ) ++chunkCount;
-
-    _headerBufferSize = sizeof(NativeFileHeader)
-                         + chunkCount*sizeof(NativeChunk);
-    _headerBuffer = reinterpret_cast<NativeFileHeader*>
-                               (operator new(_headerBufferSize, std::nothrow));
-    NativeChunk *chunks =
-      reinterpret_cast<NativeChunk*>(reinterpret_cast<char*>(_headerBuffer)
-                                     + sizeof(NativeFileHeader));
-    memcpy(_headerBuffer->magic, NATIVE_FILE_HEADER_MAGIC, 16);
-    _headerBuffer->endian = NFH_LittleEndian;
-    _headerBuffer->architecture = 0;
-    _headerBuffer->fileSize = 0;
-    _headerBuffer->chunkCount = chunkCount;
-
-    // create chunk for defined atom ivar array
-    int nextIndex = 0;
-    uint32_t nextFileOffset = _headerBufferSize;
-    if ( hasDefines ) {
-      NativeChunk& chd = chunks[nextIndex++];
-      chd.signature = NCS_DefinedAtomsV1;
-      chd.fileOffset = nextFileOffset;
-      chd.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1);
-      chd.elementCount = _definedAtomIvars.size();
-      nextFileOffset = chd.fileOffset + chd.fileSize;
-
-      // create chunk for attributes
-      NativeChunk& cha = chunks[nextIndex++];
-      cha.signature = NCS_AttributesArrayV1;
-      cha.fileOffset = nextFileOffset;
-      cha.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1);
-      cha.elementCount = _attributes.size();
-      nextFileOffset = cha.fileOffset + cha.fileSize;
-    }
-
-    // create chunk for undefined atom array
-    if ( hasUndefines ) {
-      NativeChunk& chu = chunks[nextIndex++];
-      chu.signature = NCS_UndefinedAtomsV1;
-      chu.fileOffset = nextFileOffset;
-      chu.fileSize = _undefinedAtomIvars.size() *
-                                            sizeof(NativeUndefinedAtomIvarsV1);
-      chu.elementCount = _undefinedAtomIvars.size();
-      nextFileOffset = chu.fileOffset + chu.fileSize;
-    }
-
-    // create chunk for shared library atom array
-    if ( hasSharedLibraries ) {
-      NativeChunk& chsl = chunks[nextIndex++];
-      chsl.signature = NCS_SharedLibraryAtomsV1;
-      chsl.fileOffset = nextFileOffset;
-      chsl.fileSize = _sharedLibraryAtomIvars.size() *
-                                        sizeof(NativeSharedLibraryAtomIvarsV1);
-      chsl.elementCount = _sharedLibraryAtomIvars.size();
-      nextFileOffset = chsl.fileOffset + chsl.fileSize;
-    }
-
-     // create chunk for shared library atom array
-    if ( hasAbsolutes ) {
-      NativeChunk& chsl = chunks[nextIndex++];
-      chsl.signature = NCS_AbsoluteAtomsV1;
-      chsl.fileOffset = nextFileOffset;
-      chsl.fileSize = _absoluteAtomIvars.size() *
-                                        sizeof(NativeAbsoluteAtomIvarsV1);
-      chsl.elementCount = _absoluteAtomIvars.size();
-      nextFileOffset = chsl.fileOffset + chsl.fileSize;
-    }
-
-    // create chunk for symbol strings
-    // pad end of string pool to 4-bytes
-    while ( (_stringPool.size() % 4) != 0 )
-      _stringPool.push_back('\0');
-    NativeChunk& chs = chunks[nextIndex++];
-    chs.signature = NCS_Strings;
-    chs.fileOffset = nextFileOffset;
-    chs.fileSize = _stringPool.size();
-    chs.elementCount = _stringPool.size();
-    nextFileOffset = chs.fileOffset + chs.fileSize;
-
-    // create chunk for references
-    if ( hasReferences ) {
-      NativeChunk& chr = chunks[nextIndex++];
-      chr.signature = NCS_ReferencesArrayV1;
-      chr.fileOffset = nextFileOffset;
-      chr.fileSize = _references.size() * sizeof(NativeReferenceIvarsV1);
-      chr.elementCount = _references.size();
-      nextFileOffset = chr.fileOffset + chr.fileSize;
-    }
-
-    // create chunk for target table
-    if ( hasTargetsTable ) {
-      NativeChunk& cht = chunks[nextIndex++];
-      cht.signature = NCS_TargetsTable;
-      cht.fileOffset = nextFileOffset;
-      cht.fileSize = _targetsTableIndex.size() * sizeof(uint32_t);
-      cht.elementCount = _targetsTableIndex.size();
-      nextFileOffset = cht.fileOffset + cht.fileSize;
-    }
-
-    // create chunk for addend table
-    if ( hasAddendTable ) {
-      NativeChunk& chad = chunks[nextIndex++];
-      chad.signature = NCS_AddendsTable;
-      chad.fileOffset = nextFileOffset;
-      chad.fileSize = _addendsTableIndex.size() * sizeof(Reference::Addend);
-      chad.elementCount = _addendsTableIndex.size();
-      nextFileOffset = chad.fileOffset + chad.fileSize;
-    }
-
-    // create chunk for content
-    if ( hasContent ) {
-      NativeChunk& chc = chunks[nextIndex++];
-      chc.signature = NCS_Content;
-      chc.fileOffset = nextFileOffset;
-      chc.fileSize = _contentPool.size();
-      chc.elementCount = _contentPool.size();
-      nextFileOffset = chc.fileOffset + chc.fileSize;
-    }
-
-    _headerBuffer->fileSize = nextFileOffset;
-  }
-
-  // scan header to find particular chunk
-  NativeChunk& findChunk(uint32_t signature) {
-    const uint32_t chunkCount = _headerBuffer->chunkCount;
-    NativeChunk* chunks =
-      reinterpret_cast<NativeChunk*>(reinterpret_cast<char*>(_headerBuffer)
-                                     + sizeof(NativeFileHeader));
-    for (uint32_t i=0; i < chunkCount; ++i) {
-      if ( chunks[i].signature == signature )
-        return chunks[i];
-    }
-    assert(0 && "findChunk() signature not found");
-    static NativeChunk x; return x; // suppress warning
-  }
-
-  // append atom name to string pool and return offset
-  uint32_t getNameOffset(const Atom& atom) {
-    return this->getNameOffset(atom.name());
-  }
-
-  // check if name is already in pool or append and return offset
-  uint32_t getSharedLibraryNameOffset(StringRef name) {
-    assert( ! name.empty() );
-    // look to see if this library name was used by another atom
-    for(NameToOffsetVector::iterator it = _sharedLibraryNames.begin();
-                                    it != _sharedLibraryNames.end(); ++it) {
-      if ( name.equals(it->first) )
-        return it->second;
-    }
-    // first use of this library name
-    uint32_t result = this->getNameOffset(name);
-    _sharedLibraryNames.push_back(std::make_pair(name, result));
-    return result;
-  }
-
-  // append atom name to string pool and return offset
-  uint32_t getNameOffset(StringRef name) {
-    if ( name.empty() )
-      return 0;
-    uint32_t result = _stringPool.size();
-    _stringPool.insert(_stringPool.end(), name.begin(), name.end());
-    _stringPool.push_back(0);
-    return result;
-  }
-
-  // append atom cotent to content pool and return offset
-  uint32_t getContentOffset(const class DefinedAtom& atom) {
-    if ( atom.contentType() == DefinedAtom::typeZeroFill )
-      return 0;
-    uint32_t result = _contentPool.size();
-    ArrayRef<uint8_t> cont = atom.rawContent();
-    _contentPool.insert(_contentPool.end(), cont.begin(), cont.end());
-    return result;
-  }
-
-  // reuse existing attributes entry or create a new one and return offet
-  uint32_t getAttributeOffset(const class DefinedAtom& atom) {
-    NativeAtomAttributesV1 attrs;
-    computeAttributesV1(atom, attrs);
-    for(unsigned int i=0; i < _attributes.size(); ++i) {
-      if ( !memcmp(&_attributes[i], &attrs, sizeof(NativeAtomAttributesV1)) ) {
-        // found that this set of attributes already used, so re-use
-        return i * sizeof(NativeAtomAttributesV1);
-      }
-    }
-    // append new attribute set to end
-    uint32_t result = _attributes.size() * sizeof(NativeAtomAttributesV1);
-    _attributes.push_back(attrs);
-    return result;
-  }
-
-  uint32_t sectionNameOffset(const class DefinedAtom& atom) {
-    // if section based on content, then no custom section name available
-    if ( atom.sectionChoice() == DefinedAtom::sectionBasedOnContent )
-      return 0;
-    StringRef name = atom.customSectionName();
-    assert( ! name.empty() );
-    // look to see if this section name was used by another atom
-    for(NameToOffsetVector::iterator it=_sectionNames.begin();
-                                            it != _sectionNames.end(); ++it) {
-      if ( name.equals(it->first) )
-        return it->second;
-    }
-    // first use of this section name
-    uint32_t result = this->getNameOffset(name);
-    _sectionNames.push_back(std::make_pair(name, result));
-    return result;
-  }
-
-  void computeAttributesV1(const class DefinedAtom& atom,
-                                                NativeAtomAttributesV1& attrs) {
-    attrs.sectionNameOffset = sectionNameOffset(atom);
-    attrs.align2            = atom.alignment().powerOf2;
-    attrs.alignModulus      = atom.alignment().modulus;
-    attrs.scope             = atom.scope();
-    attrs.interposable      = atom.interposable();
-    attrs.merge             = atom.merge();
-    attrs.contentType       = atom.contentType();
-    attrs.sectionChoice     = atom.sectionChoice();
-    attrs.deadStrip         = atom.deadStrip();
-    attrs.permissions       = atom.permissions();
-    //attrs.thumb             = atom.isThumb();
-    attrs.alias             = atom.isAlias();
-  }
-
-  // add references for this atom in a contiguous block in NCS_ReferencesArrayV1
-  uint32_t getReferencesIndex(const DefinedAtom& atom, unsigned& count) {
-    count = 0;
-    size_t startRefSize = _references.size();
-    uint32_t result = startRefSize;
-    for (const Reference *ref : atom) {
-      NativeReferenceIvarsV1 nref;
-      nref.offsetInAtom = ref->offsetInAtom();
-      nref.kind = ref->kind();
-      nref.targetIndex = this->getTargetIndex(ref->target());
-      nref.addendIndex = this->getAddendIndex(ref->addend());
-      _references.push_back(nref);
-    }
-    count = _references.size() - startRefSize;
-    if ( count == 0 )
-      return 0;
-    else
-      return result;
-  }
-
-  uint32_t getTargetIndex(const Atom* target) {
-    if ( target == nullptr )
-      return NativeReferenceIvarsV1::noTarget;
-    TargetToIndex::const_iterator pos = _targetsTableIndex.find(target);
-    if ( pos != _targetsTableIndex.end() ) {
-      return pos->second;
-    }
-    uint32_t result = _targetsTableIndex.size(); 
-    _targetsTableIndex[target] = result;
-    return result;
-  }
-
-  void writeTargetTable(raw_ostream &out) {
-    // Build table of target indexes
-    uint32_t maxTargetIndex = _targetsTableIndex.size();
-    assert(maxTargetIndex > 0);
-    std::vector<uint32_t> targetIndexes(maxTargetIndex);
-    for (TargetToIndex::iterator it = _targetsTableIndex.begin();
-                                 it != _targetsTableIndex.end(); ++it) {
-      const Atom* atom = it->first;
-      uint32_t targetIndex = it->second;
-      assert(targetIndex < maxTargetIndex);
-      uint32_t atomIndex = 0;
-      TargetToIndex::iterator pos = _definedAtomIndex.find(atom);
-      if ( pos != _definedAtomIndex.end() ) {
-        atomIndex = pos->second;
-      }
-      else {
-        pos = _undefinedAtomIndex.find(atom);
-        if ( pos != _undefinedAtomIndex.end() ) {
-          atomIndex = pos->second + _definedAtomIvars.size();
-        }
-        else {
-          pos = _sharedLibraryAtomIndex.find(atom);
-          if ( pos != _sharedLibraryAtomIndex.end() ) {
-            assert(pos != _sharedLibraryAtomIndex.end());
-            atomIndex = pos->second
-                      + _definedAtomIvars.size()
-                      + _undefinedAtomIndex.size();
-          }
-          else {
-            pos = _absoluteAtomIndex.find(atom);
-            assert(pos != _absoluteAtomIndex.end());
-            atomIndex = pos->second
-                      + _definedAtomIvars.size()
-                      + _undefinedAtomIndex.size()
-                      + _sharedLibraryAtomIndex.size();
-         }
-        }
-      }
-      targetIndexes[targetIndex] = atomIndex;
-    }
-    // write table
-    out.write((char*)&targetIndexes[0], maxTargetIndex*sizeof(uint32_t));
-  }
-
-  uint32_t getAddendIndex(Reference::Addend addend) {
-    if ( addend == 0 )
-      return 0; // addend index zero is used to mean "no addend"
-    AddendToIndex::const_iterator pos = _addendsTableIndex.find(addend);
-    if ( pos != _addendsTableIndex.end() ) {
-      return pos->second;
-    }
-    uint32_t result = _addendsTableIndex.size() + 1; // one-based index
-    _addendsTableIndex[addend] = result;
-    return result;
-  }
-
-  void writeAddendTable(raw_ostream &out) {
-    // Build table of addends
-    uint32_t maxAddendIndex = _addendsTableIndex.size();
-    std::vector<Reference::Addend> addends(maxAddendIndex);
-    for (AddendToIndex::iterator it = _addendsTableIndex.begin();
-                                 it != _addendsTableIndex.end(); ++it) {
-      Reference::Addend addend = it->first;
-      uint32_t index = it->second;
-      assert(index <= maxAddendIndex);
-      addends[index-1] = addend;
-    }
-    // write table
-    out.write((char*)&addends[0], maxAddendIndex*sizeof(Reference::Addend));
-  }
-
-  typedef std::vector<std::pair<StringRef, uint32_t> > NameToOffsetVector;
-
-  typedef llvm::DenseMap<const Atom*, uint32_t> TargetToIndex;
-  typedef llvm::DenseMap<Reference::Addend, uint32_t> AddendToIndex;
-
-  const lld::File&                        _file;
-  NativeFileHeader*                       _headerBuffer;
-  size_t                                  _headerBufferSize;
-  std::vector<char>                       _stringPool;
-  std::vector<uint8_t>                    _contentPool;
-  std::vector<NativeDefinedAtomIvarsV1>   _definedAtomIvars;
-  std::vector<NativeAtomAttributesV1>     _attributes;
-  std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
-  std::vector<NativeSharedLibraryAtomIvarsV1> _sharedLibraryAtomIvars;
-  std::vector<NativeAbsoluteAtomIvarsV1>  _absoluteAtomIvars;
-  std::vector<NativeReferenceIvarsV1>     _references;
-  TargetToIndex                           _targetsTableIndex;
-  TargetToIndex                           _definedAtomIndex;
-  TargetToIndex                           _undefinedAtomIndex;
-  TargetToIndex                           _sharedLibraryAtomIndex;
-  TargetToIndex                           _absoluteAtomIndex;
-  AddendToIndex                           _addendsTableIndex;
-  NameToOffsetVector                      _sectionNames;
-  NameToOffsetVector                      _sharedLibraryNames;
-};
-
-
-
-
-
-/// writeNativeObjectFile - writes the lld::File object in native object
-/// file format to the specified stream.
-int writeNativeObjectFile(const File &file, raw_ostream &out) {
-  NativeWriter writer(file);
-  writer.write(out);
-  return 0;
-}
-
-/// writeNativeObjectFile - writes the lld::File object in native object
-/// file format to the specified file path.
-int writeNativeObjectFile(const File &file, StringRef path) {
-  std::string errorInfo;
-  llvm::raw_fd_ostream out( path.data()
-                          , errorInfo
-                          , llvm::raw_fd_ostream::F_Binary);
-  if (!errorInfo.empty())
-    return -1;
-  return writeNativeObjectFile(file, out);
-}
-
-} // namespace lld

Removed: lld/trunk/lib/Core/Platform.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Platform.cpp?rev=157773&view=auto
==============================================================================
--- lld/trunk/lib/Core/Platform.cpp (original)
+++ lld/trunk/lib/Core/Platform.cpp (removed)
@@ -1,19 +0,0 @@
-//===- Core/Platform.cpp - Base class ------------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Platform.h"
-
-namespace lld {
-
-Platform::Platform() {}
-
-Platform::~Platform() {}
-
-
-}

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Thu May 31 17:34:00 2012
@@ -7,15 +7,17 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Resolver.h"
 #include "lld/Core/Atom.h"
 #include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
 #include "lld/Core/InputFiles.h"
 #include "lld/Core/LLVM.h"
+#include "lld/Core/Resolver.h"
 #include "lld/Core/SymbolTable.h"
 #include "lld/Core/UndefinedAtom.h"
 
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/ErrorHandling.h"
 
@@ -65,6 +67,8 @@
 
 // add all atoms from all initial .o files
 void Resolver::buildInitialAtomList() {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver initial atom list:\n");
+
   // each input files contributes initial atoms
   _atoms.reserve(1024);
   _inputFiles.forEachInitialAtom(*this);
@@ -79,7 +83,14 @@
 
 
 void Resolver::doUndefinedAtom(const class UndefinedAtom& atom) {
-  // add to list of known atoms
+  DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+                    << "       UndefinedAtom: "
+                    << llvm::format("0x%09lX", &atom)
+                    << ", name="
+                    << atom.name()
+                    << "\n");
+
+ // add to list of known atoms
   _atoms.push_back(&atom);
 
   // tell symbol table
@@ -89,6 +100,13 @@
 
 // called on each atom when a file is added
 void Resolver::doDefinedAtom(const DefinedAtom &atom) {
+  DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+                    << "         DefinedAtom: "
+                    << llvm::format("0x%09lX", &atom)
+                    << ", name="
+                    << atom.name()
+                    << "\n");
+
   // add to list of known atoms
   _atoms.push_back(&atom);
 
@@ -97,7 +115,7 @@
     // tell symbol table about non-static atoms
     _symbolTable.add(atom);
   }
-  
+
   if (_options.deadCodeStripping()) {
     // add to set of dead-strip-roots, all symbols that
     // the compiler marks as don't strip
@@ -107,6 +125,13 @@
 }
 
 void Resolver::doSharedLibraryAtom(const SharedLibraryAtom& atom) {
+   DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+                    << "   SharedLibraryAtom: "
+                    << llvm::format("0x%09lX", &atom)
+                    << ", name="
+                    << atom.name()
+                    << "\n");
+
   // add to list of known atoms
   _atoms.push_back(&atom);
 
@@ -115,6 +140,13 @@
 }
 
 void Resolver::doAbsoluteAtom(const AbsoluteAtom& atom) {
+   DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+                    << "       AbsoluteAtom: "
+                    << llvm::format("0x%09lX", &atom)
+                    << ", name="
+                     << atom.name()
+                    << "\n");
+
   // add to list of known atoms
   _atoms.push_back(&atom);
 
@@ -159,7 +191,7 @@
       _symbolTable.tentativeDefinitions(tentDefNames);
       for ( StringRef tentDefName : tentDefNames ) {
         // Load for previous tentative may also have loaded
-        // something that overrode this tentative, so always check. 
+        // something that overrode this tentative, so always check.
         const Atom *curAtom = _symbolTable.findByName(tentDefName);
         assert(curAtom != nullptr);
         if (const DefinedAtom* curDefAtom = dyn_cast<DefinedAtom>(curAtom)) {
@@ -228,7 +260,7 @@
         _deadStripRoots.insert(defAtom);
     }
   }
-  
+
   // Or, use list of names that are dead stip roots.
   const std::vector<StringRef> &names = _options.deadStripRootNames();
   for ( const StringRef &name : names ) {
@@ -332,7 +364,13 @@
 }
 
 void Resolver::MergedFile::addAtoms(std::vector<const Atom*>& all) {
+  DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
   for ( const Atom *atom : all ) {
+    DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+                    << llvm::format("    0x%09lX", atom)
+                    << ", name="
+                    << atom->name()
+                    << "\n");
     this->addAtom(*atom);
   }
 }

Modified: lld/trunk/lib/Core/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/lib/Core/SymbolTable.cpp (original)
+++ lld/trunk/lib/Core/SymbolTable.cpp Thu May 31 17:34:00 2012
@@ -173,7 +173,7 @@
           else {
             if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
               // FIXME: need diagonstics interface for writing warning messages
-              llvm::errs() << "lld warning: undefined symbol " 
+              llvm::errs() << "lld warning: undefined symbol "
                            << existingUndef->name()
                            << " has different weakness in "
                            << existingUndef->file().path()
@@ -198,7 +198,7 @@
             useNew = false;
             if ( _options.warnIfCoalesableAtomsHaveDifferentLoadName() ) {
               // FIXME: need diagonstics interface for writing warning messages
-              llvm::errs() << "lld warning: shared library symbol " 
+              llvm::errs() << "lld warning: shared library symbol "
                            << curShLib->name()
                            << " has different load path in "
                            << curShLib->file().path()
@@ -210,7 +210,7 @@
             useNew = false;
             if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
               // FIXME: need diagonstics interface for writing warning messages
-              llvm::errs() << "lld warning: shared library symbol " 
+              llvm::errs() << "lld warning: shared library symbol "
                            << curShLib->name()
                            << " has different weakness in "
                            << curShLib->file().path()

Removed: lld/trunk/lib/Core/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=157773&view=auto
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)
+++ lld/trunk/lib/Core/YamlKeyValues.cpp (removed)
@@ -1,432 +0,0 @@
-//===- Core/YamlKeyValues.cpp - Reads YAML --------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "YamlKeyValues.h"
-
-#include "llvm/Support/ErrorHandling.h"
-#include "lld/Core/File.h"
-
-#include <cstring>
-
-namespace lld {
-namespace yaml {
-
-
-const DefinedAtom::Definition         KeyValues::definitionDefault = Atom::definitionRegular;
-const DefinedAtom::Scope              KeyValues::scopeDefault = DefinedAtom::scopeTranslationUnit;
-const DefinedAtom::ContentType        KeyValues::contentTypeDefault = DefinedAtom::typeData;
-const DefinedAtom::DeadStripKind      KeyValues::deadStripKindDefault = DefinedAtom::deadStripNormal;
-const DefinedAtom::SectionChoice      KeyValues::sectionChoiceDefault = DefinedAtom::sectionBasedOnContent;
-const DefinedAtom::Interposable       KeyValues::interposableDefault = DefinedAtom::interposeNo;
-const DefinedAtom::Merge              KeyValues::mergeDefault = DefinedAtom::mergeNo;
-const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAtom::permR__;
-const bool                            KeyValues::isThumbDefault = false;
-const bool                            KeyValues::isAliasDefault = false;
-const UndefinedAtom::CanBeNull        KeyValues::canBeNullDefault = UndefinedAtom::canBeNullNever;
-
-
-
-
-struct DefinitionMapping {
-  const char*       string;
-  Atom::Definition  value;
-};
-
-static const DefinitionMapping defMappings[] = {
-  { "regular",        Atom::definitionRegular },
-  { "absolute",       Atom::definitionAbsolute },
-  { "undefined",      Atom::definitionUndefined },
-  { "shared-library", Atom::definitionSharedLibrary },
-  { nullptr,          Atom::definitionRegular }
-};
-
-bool KeyValues::definition(StringRef s, Atom::Definition &out)
-{
-  for (const DefinitionMapping* p = defMappings; p->string != nullptr; ++p) {
-    if (s == p->string) {
-      out = p->value;
-      return false;
-    }
-  }
-  return true;
-}
-
-const char* KeyValues::definition(Atom::Definition s) {
-  for (const DefinitionMapping* p = defMappings; p->string != nullptr; ++p) {
-    if ( p->value == s )
-      return p->string;
-  }
-  llvm::report_fatal_error("bad definition value");
-}
-
-
-
-
-
-struct ScopeMapping {
-  const char* string;
-  DefinedAtom::Scope value;
-};
-
-static const ScopeMapping scopeMappings[] = {
-  { "global", DefinedAtom::scopeGlobal },
-  { "hidden", DefinedAtom::scopeLinkageUnit },
-  { "static", DefinedAtom::scopeTranslationUnit },
-  { nullptr,  DefinedAtom::scopeGlobal }
-};
-
-bool KeyValues::scope(StringRef s, DefinedAtom::Scope &out)
-{
-  for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) {
-    if (s == p->string) {
-      out = p->value;
-      return false;
-    }
-  }
-  return true;
-}
-
-const char* KeyValues::scope(DefinedAtom::Scope s) {
-  for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) {
-    if ( p->value == s )
-      return p->string;
-  }
-  llvm::report_fatal_error("bad scope value");
-}
-
-
-
-
-
-
-
-
-struct ContentTypeMapping {
-  const char*       string;
-  DefinedAtom::ContentType  value;
-};
-
-static const ContentTypeMapping typeMappings[] = {
-  { "unknown",        DefinedAtom::typeUnknown },
-  { "code",           DefinedAtom::typeCode },
-  { "stub",           DefinedAtom::typeStub },
-  { "stub-helper",    DefinedAtom::typeStubHelper },
-  { "resolver",       DefinedAtom::typeResolver },
-  { "constant",       DefinedAtom::typeConstant },
-  { "c-string",       DefinedAtom::typeCString },
-  { "utf16-string",   DefinedAtom::typeUTF16String },
-  { "CFI",            DefinedAtom::typeCFI },
-  { "LSDA",           DefinedAtom::typeLSDA },
-  { "literal-4",      DefinedAtom::typeLiteral4 },
-  { "literal-8",      DefinedAtom::typeLiteral8 },
-  { "literal-16",     DefinedAtom::typeLiteral16 },
-  { "data",           DefinedAtom::typeData },
-  { "zero-fill",      DefinedAtom::typeZeroFill },
-  { "cf-string",      DefinedAtom::typeCFString },
-  { "got",            DefinedAtom::typeGOT },
-  { "lazy-pointer",   DefinedAtom::typeLazyPointer },
-  { "initializer-ptr",DefinedAtom::typeInitializerPtr },
-  { "terminator-ptr", DefinedAtom::typeTerminatorPtr },
-  { "c-string-ptr",   DefinedAtom::typeCStringPtr },
-  { "objc1-class",    DefinedAtom::typeObjC1Class },
-  { "objc1-class-ptr",DefinedAtom::typeObjCClassPtr },
-  { "objc2-cat-ptr",  DefinedAtom::typeObjC2CategoryList },
-  { "tlv-thunk",      DefinedAtom::typeThunkTLV },
-  { "tlv-data",       DefinedAtom::typeTLVInitialData },
-  { "tlv-zero-fill",  DefinedAtom::typeTLVInitialZeroFill },
-  { "tlv-init-ptr",   DefinedAtom::typeTLVInitializerPtr },
-  { nullptr,          DefinedAtom::typeUnknown }
-};
-
-bool KeyValues::contentType(StringRef s, DefinedAtom::ContentType &out)
-{
-  for (const ContentTypeMapping* p = typeMappings; p->string != nullptr; ++p) {
-    if (s == p->string) {
-      out = p->value;
-      return false;
-    }
-  }
-  return true;
-}
-
-const char* KeyValues::contentType(DefinedAtom::ContentType s) {
-  for (const ContentTypeMapping* p = typeMappings; p->string != nullptr; ++p) {
-    if ( p->value == s )
-      return p->string;
-  }
-  llvm::report_fatal_error("bad content type value");
-}
-
-
-
-
-
-
-
-struct DeadStripMapping {
-  const char*           string;
-  DefinedAtom::DeadStripKind   value;
-};
-
-static const DeadStripMapping dsMappings[] = {
-  { "normal",         DefinedAtom::deadStripNormal },
-  { "never",          DefinedAtom::deadStripNever },
-  { "always",         DefinedAtom::deadStripAlways },
-  { nullptr,          DefinedAtom::deadStripNormal }
-};
-
-bool KeyValues::deadStripKind(StringRef s, DefinedAtom::DeadStripKind &out)
-{
-  for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) {
-    if (s == p->string) {
-      out = p->value;
-      return false;
-    }
-  }
-  return true;
-}
-
-const char* KeyValues::deadStripKind(DefinedAtom::DeadStripKind dsk) {
-  for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) {
-    if ( p->value == dsk )
-      return p->string;
-  }
-  llvm::report_fatal_error("bad dead strip value");
-}
-
-
-
-
-
-struct InterposableMapping {
-  const char*           string;
-  DefinedAtom::Interposable   value;
-};
-
-static const InterposableMapping interMappings[] = {
-  { "no",           DefinedAtom::interposeNo },
-  { "yes",          DefinedAtom::interposeYes },
-  { "yesAndWeak",   DefinedAtom::interposeYesAndRuntimeWeak },
-  { nullptr,        DefinedAtom::interposeNo }
-};
-
-bool KeyValues::interposable(StringRef s, DefinedAtom::Interposable &out)
-{
-  for (const InterposableMapping* p = interMappings; p->string != nullptr; ++p){
-    if (s == p->string) {
-      out = p->value;
-      return false;
-    }
-  }
-  return true;
-}
-
-const char* KeyValues::interposable(DefinedAtom::Interposable in) {
-  for (const InterposableMapping* p = interMappings; p->string != nullptr; ++p){
-    if ( p->value == in )
-      return p->string;
-  }
-  llvm::report_fatal_error("bad interposable value");
-}
-
-
-
-
-
-
-struct MergeMapping {
-  const char*          string;
-  DefinedAtom::Merge   value;
-};
-
-static const MergeMapping mergeMappings[] = {
-  { "no",             DefinedAtom::mergeNo },
-  { "asTentative",    DefinedAtom::mergeAsTentative },
-  { "asWeak",         DefinedAtom::mergeAsWeak },
-  { "asAddressedWeak",DefinedAtom::mergeAsWeakAndAddressUsed },
-  { nullptr,          DefinedAtom::mergeNo }
-};
-
-bool KeyValues::merge(StringRef s, DefinedAtom::Merge& out)
-{
-  for (const MergeMapping* p = mergeMappings; p->string != nullptr; ++p) {
-    if (s == p->string) {
-      out = p->value;
-      return false;
-    }
-  }
-  return true;
-}
-
-const char* KeyValues::merge(DefinedAtom::Merge in) {
-  for (const MergeMapping* p = mergeMappings; p->string != nullptr; ++p) {
-    if ( p->value == in )
-      return p->string;
-  }
-  llvm::report_fatal_error("bad merge value");
-}
-
-
-
-
-
-
-struct SectionChoiceMapping {
-  const char*                 string;
-  DefinedAtom::SectionChoice  value;
-};
-
-static const SectionChoiceMapping sectMappings[] = {
-  { "content",         DefinedAtom::sectionBasedOnContent },
-  { "custom",          DefinedAtom::sectionCustomPreferred },
-  { "custom-required", DefinedAtom::sectionCustomRequired },
-  { nullptr,           DefinedAtom::sectionBasedOnContent }
-};
-
-bool KeyValues::sectionChoice(StringRef s, DefinedAtom::SectionChoice &out)
-{
-  for (const SectionChoiceMapping* p = sectMappings; p->string != nullptr; ++p){
-    if (s == p->string) {
-      out = p->value;
-      return false;
-    }
-  }
-  return true;
-}
-
-const char* KeyValues::sectionChoice(DefinedAtom::SectionChoice s) {
-  for (const SectionChoiceMapping* p = sectMappings; p->string != nullptr; ++p){
-    if ( p->value == s )
-      return p->string;
-  }
-  llvm::report_fatal_error("bad dead strip value");
-}
-
-
-
-
-
-
-
-struct PermissionsMapping {
-  const char*                      string;
-  DefinedAtom::ContentPermissions  value;
-};
-
-static const PermissionsMapping permMappings[] = {
-  { "---",    DefinedAtom::perm___  },
-  { "r--",    DefinedAtom::permR__  },
-  { "r-x",    DefinedAtom::permR_X  },
-  { "rw-",    DefinedAtom::permRW_  },
-  { "rw-l",   DefinedAtom::permRW_L },
-  { nullptr,  DefinedAtom::perm___  }
-};
-
-bool KeyValues::permissions(StringRef s, DefinedAtom::ContentPermissions &out)
-{
-  for (const PermissionsMapping* p = permMappings; p->string != nullptr; ++p) {
-    if (s == p->string) {
-      out = p->value;
-      return false;
-    }
-  }
-  return true;
-}
-
-const char* KeyValues::permissions(DefinedAtom::ContentPermissions s) {
-  for (const PermissionsMapping* p = permMappings; p->string != nullptr; ++p) {
-    if ( p->value == s )
-      return p->string;
-  }
-  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";
-}
-
-
-
-
-struct CanBeNullMapping {
-  const char*               string;
-  UndefinedAtom::CanBeNull  value;
-};
-
-static const CanBeNullMapping cbnMappings[] = {
-  { "never",         UndefinedAtom::canBeNullNever },
-  { "at-runtime",    UndefinedAtom::canBeNullAtRuntime },
-  { "at-buildtime",  UndefinedAtom::canBeNullAtBuildtime },
-  { nullptr,         UndefinedAtom::canBeNullNever }
-};
-
-
-bool KeyValues::canBeNull(StringRef s, UndefinedAtom::CanBeNull &out)
-{
-  for (const CanBeNullMapping* p = cbnMappings; p->string != nullptr; ++p) {
-    if (s == p->string) {
-      out = p->value;
-      return false;
-    }
-  }
-  return true;
-}
-
-const char* KeyValues::canBeNull(UndefinedAtom::CanBeNull c) {
-  for (const CanBeNullMapping* p = cbnMappings; p->string != nullptr; ++p) {
-    if ( p->value == c )
-      return p->string;
-  }
-  llvm::report_fatal_error("bad can-be-null value");
-}
-
-
-
-
-
-
-
-} // namespace yaml
-} // namespace lld

Removed: lld/trunk/lib/Core/YamlKeyValues.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.h?rev=157773&view=auto
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.h (original)
+++ lld/trunk/lib/Core/YamlKeyValues.h (removed)
@@ -1,84 +0,0 @@
-//===- Core/YamlKeyValues.h - Reads YAML ----------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_YAML_KEY_VALUES_H_
-#define LLD_CORE_YAML_KEY_VALUES_H_
-
-#include "lld/Core/Atom.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "lld/Core/File.h"
-
-namespace lld {
-namespace yaml {
-
-class KeyValues {
-public:
-
-  static const char* const                definitionKeyword;
-  static const Atom::Definition           definitionDefault;
-  static bool                             definition(StringRef, Atom::Definition&);
-  static const char*                      definition(Atom::Definition);
-
-  static const char* const                scopeKeyword;
-  static const DefinedAtom::Scope         scopeDefault;
-  static bool                             scope(StringRef, DefinedAtom::Scope&);
-  static const char*                      scope(DefinedAtom::Scope);
-
-  static const char* const                contentTypeKeyword;
-  static const DefinedAtom::ContentType   contentTypeDefault;
-  static bool                             contentType(StringRef, DefinedAtom::ContentType&);
-  static const char*                      contentType(DefinedAtom::ContentType);
-
-  static const char* const                deadStripKindKeyword;
-  static const DefinedAtom::DeadStripKind deadStripKindDefault;
-  static bool                             deadStripKind(StringRef, DefinedAtom::DeadStripKind&);
-  static const char*                      deadStripKind(DefinedAtom::DeadStripKind);
-
-  static const char* const                sectionChoiceKeyword;
-  static const DefinedAtom::SectionChoice sectionChoiceDefault;
-  static bool                             sectionChoice(StringRef,  DefinedAtom::SectionChoice&);
-  static const char*                      sectionChoice(DefinedAtom::SectionChoice);
-
-  static const char* const                interposableKeyword;
-  static const DefinedAtom::Interposable  interposableDefault;
-  static bool                             interposable(StringRef, DefinedAtom::Interposable&);
-  static const char*                      interposable(DefinedAtom::Interposable);
-
-  static const char* const                mergeKeyword;
-  static const DefinedAtom::Merge         mergeDefault;
-  static bool                             merge(StringRef, DefinedAtom::Merge&);
-  static const char*                      merge(DefinedAtom::Merge);
-
-  static const char* const                      permissionsKeyword;
-  static const DefinedAtom::ContentPermissions  permissionsDefault;
-  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 bool                             canBeNull(StringRef, UndefinedAtom::CanBeNull&);
-  static const char*                      canBeNull(UndefinedAtom::CanBeNull);
-
-};
-
-} // namespace yaml
-} // namespace lld
-
-#endif // LLD_CORE_YAML_KEY_VALUES_H_

Removed: lld/trunk/lib/Core/YamlReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=157773&view=auto
==============================================================================
--- lld/trunk/lib/Core/YamlReader.cpp (original)
+++ lld/trunk/lib/Core/YamlReader.cpp (removed)
@@ -1,1243 +0,0 @@
-//===- Core/YamlReader.cpp - Reads YAML encode object files ---------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/YamlReader.h"
-#include "YamlKeyValues.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/AbsoluteAtom.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/File.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Platform.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/SharedLibraryAtom.h"
-#include "lld/Core/UndefinedAtom.h"
-
-#include "llvm/ADT/APInt.h"
-#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 "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Debug.h"
-
-#include <cstring>
-#include <vector>
-
-
-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)
-  {}
-
-  virtual uint64_t offsetInAtom() const {
-    return _offsetInAtom;
-  }
-
-  virtual Kind kind() const {
-    return _kind;
-  }
-
-  virtual void setKind(Kind k) {
-    _kind = k;
-  }
-
-  virtual const Atom *target() const {
-    return _target;
-  }
-
-  virtual Addend addend() const {
-    return _addend;
-  }
-
-  virtual void setAddend(Addend a) {
-    _addend = a;
-  }
-
-  virtual void setTarget(const Atom *newAtom) {
-    _target = newAtom;
-  }
-
-  typedef llvm::yaml::ScalarNode ScalarNode;
-  
-  const Atom *_target;
-  ScalarNode * _targetNameNode;
-  uint64_t    _offsetInAtom;
-  Addend      _addend;
-  Kind        _kind;
-};
-
-
-///
-/// Concrete instance of lld::File created parsing YAML object files.
-///
-class YAMLFile : public ArchiveLibraryFile {
-public:
-  YAMLFile()
-    : ArchiveLibraryFile("<anonymous>")
-    , _lastRefIndex(0)
-    , _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;
-  }
-
-  virtual const atom_collection<DefinedAtom> &defined() const {
-    return _definedAtoms;
-  }
-  virtual const atom_collection<UndefinedAtom> &undefined() const {
-    return _undefinedAtoms;
-  }
-  virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
-    return _sharedLibraryAtoms;
-  }
-  virtual const atom_collection<AbsoluteAtom> &absolute() const {
-    return _absoluteAtoms;
-  }
-
-  virtual void addAtom(const Atom&) {
-    assert(0 && "cannot add atoms to YAML files");
-  }
-
-  // Standard way that archives are searched.
-  virtual const File *find(StringRef name, bool dataSymbolOnly) const;
-
-  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);
-  Atom *findAtom(StringRef name);
-  void addMember(StringRef);
-  void setName(StringRef);
-
-  StringRef copyString(StringRef);
-  
-  struct NameAtomPair {
-                 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<std::unique_ptr<YAMLFile>>    _memberFiles;
-  std::vector<char*>                        _stringCopies;
-  unsigned int                              _lastRefIndex;
-  File::Kind                                _kind;
-};
-
-
-
-///
-/// Concrete instance of lld::DefinedAtom created parsing YAML object files.
-///
-class YAMLDefinedAtom : public DefinedAtom {
-public:
-  YAMLDefinedAtom( uint32_t ord
-          , YAMLFile &file
-          , DefinedAtom::Scope scope
-          , DefinedAtom::ContentType type
-          , DefinedAtom::SectionChoice sectionChoice
-          , DefinedAtom::Interposable interpose
-          , DefinedAtom::Merge merge
-          , DefinedAtom::DeadStripKind deadStrip
-          , DefinedAtom::ContentPermissions perms
-          , bool isThumb
-          , bool isAlias
-          , DefinedAtom::Alignment alignment
-          , StringRef name
-          , StringRef sectionName
-          , uint64_t size
-          , std::vector<uint8_t>& content)
-    : _file(file)
-    , _name(name)
-    , _sectionName(sectionName)
-    , _size(size)
-    , _ord(ord)
-    , _content(content)
-    , _alignment(alignment)
-    , _scope(scope)
-    , _type(type)
-    , _sectionChoice(sectionChoice)
-    , _interpose(interpose)
-    , _merge(merge)
-    , _deadStrip(deadStrip)
-    , _permissions(perms)
-    , _isThumb(isThumb)
-    , _isAlias(isAlias)
-    , _refStartIndex(file._lastRefIndex)
-    , _refEndIndex(file._references.size()) {
-    file._lastRefIndex = _refEndIndex;
-  }
-
-  virtual const class File &file() const {
-    return _file;
-  }
-
-  virtual StringRef name() const {
-    return _name;
-  }
-
-  virtual uint64_t size() const {
-    return _content.empty() ? _size : _content.size();
-  }
-
-  virtual DefinedAtom::Scope scope() const {
-    return _scope;
-  }
-
-  virtual DefinedAtom::Interposable interposable() const {
-    return _interpose;
-  }
-
-  virtual DefinedAtom::Merge merge() const {
-    return _merge;
-  }
-
-  virtual DefinedAtom::ContentType contentType() const {
-    return _type;
-  }
-
-  virtual DefinedAtom::Alignment alignment() const {
-    return _alignment;
-  }
-
-  virtual DefinedAtom::SectionChoice sectionChoice() const {
-    return _sectionChoice;
-  }
-
-  virtual StringRef customSectionName() const {
-    return _sectionName;
-  }
-
-  virtual DefinedAtom::DeadStripKind deadStrip() const {
-    return _deadStrip;
-  }
-
-  virtual DefinedAtom::ContentPermissions permissions() const {
-    return _permissions;
-  }
-
-  virtual bool isThumb() const {
-    return _isThumb;
-  }
-
-  virtual bool isAlias() const {
-    return _isAlias;
-  }
-
-  ArrayRef<uint8_t> rawContent() const {
-    return ArrayRef<uint8_t>(_content);
-  }
-
-  virtual uint64_t ordinal() const {
-    return _ord;
-  }
-
-  DefinedAtom::reference_iterator begin() const {
-    uintptr_t index = _refStartIndex;
-    const void* it = reinterpret_cast<const void*>(index);
-    return reference_iterator(*this, it);
-  }
-
-  DefinedAtom::reference_iterator end() const {
-    uintptr_t index = _refEndIndex;
-    const void* it = reinterpret_cast<const void*>(index);
-    return reference_iterator(*this, it);
-  }
-
-  const Reference* derefIterator(const void* it) const {
-    uintptr_t index = reinterpret_cast<uintptr_t>(it);
-    assert(index >= _refStartIndex);
-    assert(index < _refEndIndex);
-    assert(index < _file._references.size());
-    return &_file._references[index];
-  }
-
-  void incrementIterator(const void*& it) const {
-    uintptr_t index = reinterpret_cast<uintptr_t>(it);
-    ++index;
-    it = reinterpret_cast<const void*>(index);
-  }
-
-  // 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) {
-      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:
-  YAMLFile                   &_file;
-  StringRef                   _name;
-  StringRef                   _sectionName;
-  unsigned long               _size;
-  uint32_t                    _ord;
-  std::vector<uint8_t>        _content;
-  DefinedAtom::Alignment      _alignment;
-  DefinedAtom::Scope          _scope;
-  DefinedAtom::ContentType    _type;
-  DefinedAtom::SectionChoice  _sectionChoice;
-  DefinedAtom::Interposable   _interpose;
-  DefinedAtom::Merge          _merge;
-  DefinedAtom::DeadStripKind  _deadStrip;
-  DefinedAtom::ContentPermissions _permissions;
-  bool                        _isThumb;
-  bool                        _isAlias;
-  unsigned int                _refStartIndex;
-  unsigned int                _refEndIndex;
-};
-
-
-
-///
-/// Concrete instance of lld::UndefinedAtom created parsing YAML object files.
-///
-class YAMLUndefinedAtom : public UndefinedAtom {
-public:
-  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 {
-    return _file;
-  }
-
-  virtual StringRef name() const {
-    return _name;
-  }
-
-  virtual CanBeNull canBeNull() const {
-    return _canBeNull;
-  }
-
-private:
-  YAMLFile                &_file;
-  StringRef                _name;
-  uint32_t                 _ordinal;
-  UndefinedAtom::CanBeNull _canBeNull;
-};
-
-
-
-///
-/// Concrete instance of lld::SharedLibraryAtom created parsing YAML files.
-///
-class YAMLSharedLibraryAtom : public SharedLibraryAtom {
-public:
-  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 {
-    return _file;
-  }
-
-  virtual StringRef name() const {
-    return _name;
-  }
-
-  virtual StringRef loadName() const {
-    return _loadName;
-  }
-
-  virtual bool canBeNullAtRuntime() const {
-    return _canBeNull;
-  }
-
-private:
-  YAMLFile &_file;
-  StringRef _name;
-  uint32_t  _ordinal;
-  StringRef _loadName;
-  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)
-    : _file(f)
-    , _name(name)
-    , _ordinal(ord)
-    , _value(v) {
-  }
-
-  virtual const class File &file() const {
-    return _file;
-  }
-
-  virtual StringRef name() const {
-    return _name;
-  }
-
-  virtual uint64_t value() const {
-    return _value;
-  }
-
-private:
-  YAMLFile &_file;
-  StringRef _name;
-  uint32_t  _ordinal;
-  uint64_t  _value;
-};
-
-
-
-
-//===----------------------------------------------------------------------===//
-//  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);
-    ec = atom->bindTargetReferences(stream);
-    if ( ec )
-      return ec;
-  }
-  return ec;
-}
-
-Atom *YAMLFile::findAtom(StringRef name) {
-  for (auto &ci : _nameToAtomMapping) {
-    if (ci.name == name)
-      return ci.atom;
-  }
-  return nullptr;
-}
-
-void YAMLFile::addDefinedAtom(YAMLDefinedAtom *atom, StringRef refName) {
-  _definedAtoms._atoms.push_back(atom);
-  _nameToAtomMapping.push_back(NameAtomPair(refName, atom));
-}
-
-void YAMLFile::addUndefinedAtom(UndefinedAtom *atom) {
-  _undefinedAtoms._atoms.push_back(atom);
-  _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom));
-}
-
-void YAMLFile::addSharedLibraryAtom(SharedLibraryAtom *atom) {
-  _sharedLibraryAtoms._atoms.push_back(atom);
-  _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom));
-}
-
-void YAMLFile::addAbsoluteAtom(AbsoluteAtom *atom) {
-  _absoluteAtoms._atoms.push_back(atom);
-  _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom));
-}
-
-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() ) {
-      if (name == atom->name())
-        return file.get();
-    }
-  }
-  return nullptr;
-}
-
-
-
-///
-/// 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:
-  YAMLState(Platform &platform, llvm::yaml::Stream *s, YAMLFile *f);
-
-  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 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 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;
-  std::vector<uint8_t>        _content;
-  DefinedAtom::Alignment      _alignment;
-  Atom::Definition            _definition;
-  DefinedAtom::Scope          _scope;
-  DefinedAtom::ContentType    _type;
-  DefinedAtom::SectionChoice  _sectionChoice;
-  DefinedAtom::Interposable   _interpose;
-  DefinedAtom::Merge          _merge;
-  DefinedAtom::DeadStripKind  _deadStrip;
-  DefinedAtom::ContentPermissions _permissions;
-  bool                        _isThumb;
-  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                            },
-};
-
-
-
-YAMLState::YAMLState(Platform &platform, Stream *stream, YAMLFile *file)
-  : _platform(platform)
-  , _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;
-  _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._targetNameNode= nullptr;
-  _ref._addend        = 0;
-  _ref._offsetInAtom  = 0;
-  _ref._kind          = 0;
-  
-  _hasDefinedAtomAttributes = false;
-  _hasUndefinedAtomAttributes = false;
-  _hasSharedLibraryAtomAttributes = false;
-  _hasAbsoluteAtomAttributes = false;
-}
-
-
-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 YAMLState::setAlign2(StringRef s) {
-  if (StringRef(s).getAsInteger(10, _alignment.powerOf2))
-    _alignment.powerOf2 = 1;
-}
-
-
-// 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 YAMLState::parseMemberName(ScalarNode *node) {
-   _memberName = extractString(node);
-}
-
-void YAMLState::parseAtomName(ScalarNode *node) {
-   _name = extractString(node);
-}
-
-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;
-}
-
-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);
-  }
-}
-
-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;
-}
-
-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);
-  }
-  _hasDefinedAtomAttributes = true;
-}
-
-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;
-}
-
-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);
-  }
-  _hasDefinedAtomAttributes = true;
-}
-
-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;
-}
-
-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);
-      }
-    }
-    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);
-      }
-      else {
-        for (Node &seqEntry : *seq ) {
-          this->parse(&seqEntry, StringRef("<any-seq-item>"));
-          if ( _error )
-            break;
-        }
-      }
-    }
-    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;
-        }
-      }
-    }
-    else {
-      _stream->printError(node, "unexpected node type");
-      _error = make_error_code(yaml_reader_error::illegal_value);
-    }
-    this->returnToState(savedState, node);
-    return;
-  }
-  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) {
-  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.
-    YAMLState yamlState(platform, &stream, curFile.get());
-    yamlState.parse(d.getRoot(), StringRef("<root>"));
-
-    if ( stream.failed() ) 
-      return make_error_code(yaml_reader_error::illegal_value);
-    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) {
-  OwningPtr<llvm::MemoryBuffer> mb;
-  if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb))
-    return ec;
-
-  return parseObjectText(mb.take(), platform, result);
-}
-
-} // namespace yaml
-} // namespace lld

Removed: lld/trunk/lib/Core/YamlWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlWriter.cpp?rev=157773&view=auto
==============================================================================
--- lld/trunk/lib/Core/YamlWriter.cpp (original)
+++ lld/trunk/lib/Core/YamlWriter.cpp (removed)
@@ -1,463 +0,0 @@
-//===- Core/YamlWriter.cpp - Writes YAML ----------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/YamlWriter.h"
-#include "YamlKeyValues.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Platform.h"
-#include "lld/Core/Reference.h"
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/system_error.h"
-
-#include <vector>
-
-namespace lld {
-namespace yaml {
-
-namespace {
-///
-/// In most cases, atoms names are unambiguous, so references can just
-/// use the atom name as the target (e.g. target: foo).  But in a few
-/// cases that does not work, so ref-names are added.  These are labels
-/// used only in yaml.  The labels do not exist in the Atom model.
-///
-/// One need for ref-names are when atoms have no user supplied name
-/// (e.g. c-string literal).  Another case is when two object files with
-/// identically named static functions are merged (ld -r) into one object file.
-/// In that case referencing the function by name is ambiguous, so a unique
-/// ref-name is added.
-///
-class RefNameBuilder {
-public:
-  RefNameBuilder(const File& file)
-                : _collisionCount(0), _unnamedCounter(0) {
-    // visit all atoms
-    for( const DefinedAtom *atom : file.defined() ) {
-      // Build map of atoms names to detect duplicates
-      if ( ! atom->name().empty() )
-        buildDuplicateNameMap(*atom);
-
-      // Find references to unnamed atoms and create ref-names for them.
-      for (const Reference *ref : *atom) {
-        // create refname for any unnamed reference target
-        const Atom *target = ref->target();
-        if ( (target != nullptr) && target->name().empty() ) {
-          std::string Storage;
-          llvm::raw_string_ostream Buffer(Storage);
-          Buffer << llvm::format("L%03d", _unnamedCounter++);
-          _refNames[target] = Buffer.str();
-        }
-      }
-    }
-    for( const UndefinedAtom *undefAtom : file.undefined() ) {
-      buildDuplicateNameMap(*undefAtom);
-    }
-    for( const SharedLibraryAtom *shlibAtom : file.sharedLibrary() ) {
-      buildDuplicateNameMap(*shlibAtom);
-    }
-    for( const AbsoluteAtom *absAtom : file.absolute() ) {
-      buildDuplicateNameMap(*absAtom);
-    }
-
-
-  }
-
-  void buildDuplicateNameMap(const Atom& atom) {
-    assert(!atom.name().empty());
-    NameToAtom::iterator pos = _nameMap.find(atom.name());
-    if ( pos != _nameMap.end() ) {
-      // Found name collision, give each a unique ref-name.
-      std::string Storage;
-      llvm::raw_string_ostream Buffer(Storage);
-      Buffer << atom.name() << llvm::format(".%03d", ++_collisionCount);
-      _refNames[&atom] = Buffer.str();
-      const Atom* prevAtom = pos->second;
-      AtomToRefName::iterator pos2 = _refNames.find(prevAtom);
-      if ( pos2 == _refNames.end() ) {
-        // only create ref-name for previous if none already created
-        Buffer << prevAtom->name() << llvm::format(".%03d", ++_collisionCount);
-        _refNames[prevAtom] = Buffer.str();
-      }
-    }
-    else {
-      // First time we've seen this name, just add it to map.
-      _nameMap[atom.name()] = &atom;
-    }
-  }
-
-  bool hasRefName(const Atom* atom) {
-     return _refNames.count(atom);
-  }
-
-  StringRef refName(const Atom *atom) {
-     return _refNames.find(atom)->second;
-  }
-
-private:
-  typedef llvm::StringMap<const Atom*> NameToAtom;
-  typedef llvm::DenseMap<const Atom*, std::string> AtomToRefName;
-
-  unsigned int      _collisionCount;
-  unsigned int      _unnamedCounter;
-  NameToAtom        _nameMap;
-  AtomToRefName     _refNames;
-};
-
-
-///
-/// Helper class for writeObjectText() to write out atoms in yaml format.
-///
-class AtomWriter {
-public:
-  AtomWriter(const File& file, Platform& platform, RefNameBuilder& rnb)
-    : _file(file), _platform(platform), _rnb(rnb), _firstAtom(true) { }
-
-
-  void write(raw_ostream &out) {
-    // write header
-    out << "---\n";
-
-    // visit all atoms
-    for( const DefinedAtom *atom : _file.defined() ) {
-      writeDefinedAtom(*atom, out);
-    }
-    for( const UndefinedAtom *undefAtom : _file.undefined() ) {
-      writeUndefinedAtom(*undefAtom, out);
-    }
-    for( const SharedLibraryAtom *shlibAtom : _file.sharedLibrary() ) {
-      writeSharedLibraryAtom(*shlibAtom, out);
-    }
-    for( const AbsoluteAtom *absAtom : _file.absolute() ) {
-      writeAbsoluteAtom(*absAtom, out);
-    }
-
-    out << "...\n";
-  }
-
-
-  void writeDefinedAtom(const DefinedAtom &atom, raw_ostream &out) {
-    if ( _firstAtom ) {
-      out << "atoms:\n";
-      _firstAtom = false;
-    }
-    else {
-      // add blank line between atoms for readability
-      out << "\n";
-    }
-
-    bool hasDash = false;
-    if ( !atom.name().empty() ) {
-      out   << "    - "
-            << "name:"
-            << spacePadding(strlen("name"))
-            << atom.name()
-            << "\n";
-      hasDash = true;
-    }
-
-    if ( _rnb.hasRefName(&atom) ) {
-      out   << (hasDash ? "      " : "    - ")
-            << "ref-name:"
-            << spacePadding(strlen("ref-name"))
-            << _rnb.refName(&atom)
-            << "\n";
-      hasDash = true;
-    }
-
-    if ( atom.definition() != KeyValues::definitionDefault ) {
-      out   << (hasDash ? "      " : "    - ")
-            << "definition:"
-            << spacePadding(strlen("definition"))
-            << KeyValues::definition(atom.definition())
-            << "\n";
-      hasDash = true;
-    }
-
-    if ( atom.scope() != KeyValues::scopeDefault ) {
-      out   << (hasDash ? "      " : "    - ")
-            << "scope:"
-            << spacePadding(strlen("scope"))
-            << KeyValues::scope(atom.scope())
-            << "\n";
-      hasDash = true;
-    }
-
-     if ( atom.interposable() != KeyValues::interposableDefault ) {
-      out   << "      "
-            << "interposable:"
-            << spacePadding(strlen("interposable"))
-            << KeyValues::interposable(atom.interposable())
-            << "\n";
-    }
-
-    if ( atom.merge() != KeyValues::mergeDefault ) {
-      out   << "      "
-            << "merge:"
-            << spacePadding(strlen("merge"))
-            << KeyValues::merge(atom.merge())
-            << "\n";
-    }
-
-    if ( atom.contentType() != KeyValues::contentTypeDefault ) {
-      out   << "      "
-            << "type:"
-            << spacePadding(strlen("type"))
-            << KeyValues::contentType(atom.contentType())
-            << "\n";
-    }
-
-    if ( atom.deadStrip() != KeyValues::deadStripKindDefault ) {
-      out   << "      "
-            << "dead-strip:"
-            << spacePadding(strlen("dead-strip"))
-            << KeyValues::deadStripKind(atom.deadStrip())
-            << "\n";
-    }
-
-    if ( atom.sectionChoice() != KeyValues::sectionChoiceDefault ) {
-      out   << "      "
-            << "section-choice:"
-            << spacePadding(strlen("section-choice"))
-            << KeyValues::sectionChoice(atom.sectionChoice())
-            << "\n";
-      assert( ! atom.customSectionName().empty() );
-      out   << "      "
-            << "section-name:"
-            << spacePadding(strlen("section-name"))
-            << atom.customSectionName()
-            << "\n";
-    }
-
-    if ( atom.isThumb() != KeyValues::isThumbDefault ) {
-      out   << "      "
-            << "is-thumb:"
-            << spacePadding(strlen("is-thumb"))
-            << KeyValues::isThumb(atom.isThumb())
-            << "\n";
-    }
-
-    if ( atom.isAlias() != KeyValues::isAliasDefault ) {
-      out   << "      "
-            << "is-alias:"
-            << spacePadding(strlen("is-alias"))
-            << KeyValues::isAlias(atom.isAlias())
-            << "\n";
-    }
-
-    if ( (atom.contentType() != DefinedAtom::typeZeroFill)
-                                   && (atom.size() != 0) ) {
-      out   << "      "
-            << "content:"
-            << spacePadding(strlen("content"))
-            << "[ ";
-      ArrayRef<uint8_t> arr = atom.rawContent();
-      bool needComma = false;
-      for (unsigned int i=0; i < arr.size(); ++i) {
-        if ( needComma )
-          out  << ", ";
-        if ( ((i % 12) == 0) && (i != 0) ) {
-          out << "\n                           ";
-        }
-        out  << hexdigit(arr[i] >> 4);
-        out  << hexdigit(arr[i] & 0x0F);
-        needComma = true;
-      }
-      out  << " ]\n";
-    }
-
-    bool wroteFirstFixup = false;
-    for (const Reference *ref : atom) {
-      if ( !wroteFirstFixup ) {
-        out  << "      fixups:\n";
-        wroteFirstFixup = true;
-      }
-      out   << "      - "
-            << "offset:"
-            << spacePadding(strlen("offset"))
-            << ref->offsetInAtom()
-            << "\n";
-      out   << "        "
-            << "kind:"
-            << spacePadding(strlen("kind"))
-            << _platform.kindToString(ref->kind())
-            << "\n";
-      const Atom* target = ref->target();
-      if (target != nullptr) {
-        StringRef refName = target->name();
-        if ( _rnb.hasRefName(target) )
-          refName = _rnb.refName(target);
-        assert(!refName.empty());
-        out   << "        "
-              << "target:"
-              << spacePadding(strlen("target"))
-              << refName
-              << "\n";
-      }
-      if ( ref->addend() != 0 ) {
-        out   << "        "
-              << "addend:"
-              << spacePadding(strlen("addend"))
-              << ref->addend()
-              << "\n";
-      }
-    }
-  }
-
-
-  void writeUndefinedAtom(const UndefinedAtom &atom, raw_ostream &out) {
-    if ( _firstAtom ) {
-      out  << "atoms:\n";
-      _firstAtom = false;
-    }
-    else {
-      // add blank line between atoms for readability
-      out  << "\n";
-    }
-
-    out   << "    - "
-          << "name:"
-          << spacePadding(strlen("name"))
-          << atom.name()
-          << "\n";
-
-    out   << "      "
-          << "definition:"
-          << spacePadding(strlen("definition"))
-          << KeyValues::definition(atom.definition())
-          << "\n";
-
-    if ( atom.canBeNull() != KeyValues::canBeNullDefault ) {
-      out   << "      "
-            << "can-be-null:"
-            << spacePadding(strlen("can-be-null"))
-            << KeyValues::canBeNull(atom.canBeNull())
-            << "\n";
-    }
-  }
-
-  void writeSharedLibraryAtom(const SharedLibraryAtom &atom, raw_ostream &out) {
-    if ( _firstAtom ) {
-      out  << "atoms:\n";
-      _firstAtom = false;
-    }
-    else {
-      // add blank line between atoms for readability
-      out  << "\n";
-    }
-
-    out   << "    - "
-          << "name:"
-          << spacePadding(strlen("name"))
-          << atom.name()
-          << "\n";
-
-    out   << "      "
-          << "definition:"
-          << spacePadding(strlen("definition"))
-          << KeyValues::definition(atom.definition())
-          << "\n";
-
-    if ( !atom.loadName().empty() ) {
-      out   << "      "
-            << "load-name:"
-            << spacePadding(strlen("load-name"))
-            << atom.loadName()
-            << "\n";
-    }
-
-    if ( atom.canBeNullAtRuntime() ) {
-      out   << "      "
-            << "can-be-null:"
-            << spacePadding(strlen("can-be-null"))
-            << KeyValues::canBeNull(UndefinedAtom::canBeNullAtRuntime)
-            << "\n";
-    }
-   }
-
-  void writeAbsoluteAtom(const AbsoluteAtom &atom, raw_ostream &out) {
-     if ( _firstAtom ) {
-      out << "atoms:\n";
-      _firstAtom = false;
-    }
-    else {
-      // add blank line between atoms for readability
-      out << "\n";
-    }
-
-    out   << "    - "
-          << "name:"
-          << spacePadding(strlen("name"))
-          << atom.name()
-          << "\n";
-
-    out   << "      "
-          << "definition:"
-          << spacePadding(strlen("definition"))
-          << KeyValues::definition(atom.definition())
-          << "\n";
-
-    out   << "      "
-          << "value:"
-          << spacePadding(strlen("value"))
-          << "0x";
-     out.write_hex(atom.value());
-     out << "\n";
-   }
-
-
-private:
-  // return a string of the correct number of spaces to align value
-  const char* spacePadding(size_t keyLen) {
-    const char* spaces = "                  ";
-    assert(strlen(spaces) > keyLen);
-    return &spaces[keyLen];
-  }
-
-  char hexdigit(uint8_t nibble) {
-    if ( nibble < 0x0A )
-      return '0' + nibble;
-    else
-      return 'A' + nibble - 0x0A;
-  }
-
-  const File&         _file;
-  Platform&           _platform;
-  RefNameBuilder&     _rnb;
-  bool                _firstAtom;
-};
-
-} // anonymous namespace
-
-
-
-///
-/// writeObjectText - writes the lld::File object as in YAML
-/// format to the specified stream.
-///
-void writeObjectText(const File &file, Platform &platform, raw_ostream &out) {
-  // Figure what ref-name labels are needed
-  RefNameBuilder rnb(file);
-
-  // Write out all atoms
-  AtomWriter writer(file, platform, rnb);
-  writer.write(out);
-}
-
-} // namespace yaml
-} // namespace lld

Modified: lld/trunk/lib/Passes/GOTPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/GOTPass.cpp?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/lib/Passes/GOTPass.cpp (original)
+++ lld/trunk/lib/Passes/GOTPass.cpp Thu May 31 17:34:00 2012
@@ -24,9 +24,9 @@
 // is in the same linkage unit and does not need to be interposable, and 
 // the GOT use is just a load (not some other operation), this pass can 
 // transform that load into an LEA (add).  This optimizes away one memory load
-// at runtime that could stall the pipeline.  This optimization only works
+// which at runtime that could stall the pipeline.  This optimization only works
 // for architectures in which a (GOT) load instruction can be change to an 
-// LEA instruction that is the same size.  The platform method isGOTAccess()
+// LEA instruction that is the same size.  The method isGOTAccess()
 // should only return true for "canBypassGOT" if this optimization is supported.
 //
 //===----------------------------------------------------------------------===//
@@ -35,23 +35,21 @@
 #include "lld/Core/File.h"
 #include "lld/Core/LLVM.h"
 #include "lld/Core/Pass.h"
-#include "lld/Core/Platform.h"
 #include "lld/Core/Reference.h"
-
 #include "llvm/ADT/DenseMap.h"
 
 namespace lld {
 
-void GOTPass::perform() {
+void GOTPass::perform(File& mergedFile) {
   // Use map so all pointers to same symbol use same GOT entry.
   llvm::DenseMap<const Atom*, const DefinedAtom*> targetToGOT;
   
   // Scan all references in all atoms.
-  for(const DefinedAtom *atom : _file.defined()) {
+  for(const DefinedAtom *atom : mergedFile.defined()) {
     for (const Reference *ref : *atom) {
       // Look at instructions accessing the GOT.
       bool canBypassGOT;
-      if ( _platform.isGOTAccess(ref->kind(), canBypassGOT) ) {
+      if ( this->isGOTAccess(ref->kind(), canBypassGOT) ) {
         const Atom* target = ref->target();
         assert(target != nullptr);
         const DefinedAtom* defTarget = dyn_cast<DefinedAtom>(target);
@@ -72,14 +70,14 @@
           // GOT to be by-passed, do that optimization and don't create
           // GOT entry.
           replaceTargetWithGOTAtom = !canBypassGOT;
-        } 
+        }
         if ( replaceTargetWithGOTAtom ) {
           // Replace the target with a reference to a GOT entry.
           const DefinedAtom* gotEntry = nullptr;
           auto pos = targetToGOT.find(target);
           if ( pos == targetToGOT.end() ) {
             // This is no existing GOT entry.  Create a new one.
-            gotEntry = _platform.makeGOTEntry(*target, _file);
+            gotEntry = this->makeGOTEntry(*target);
             assert(gotEntry != nullptr);
             assert(gotEntry->contentType() == DefinedAtom::typeGOT);
             targetToGOT[target] = gotEntry;
@@ -92,16 +90,16 @@
           // Switch reference to GOT atom.
           (const_cast<Reference*>(ref))->setTarget(gotEntry);
         }
-        // Platform needs to update reference kind to reflect
-        // that target is a GOT entry or a direct accesss.
-        _platform.updateReferenceToGOT(ref, replaceTargetWithGOTAtom);
+        // Update reference kind to reflect
+        // that target is now a GOT entry or a direct accesss.
+       this->updateReferenceToGOT(ref, replaceTargetWithGOTAtom);
       }
     }
   }
   
   // add all created GOT Atoms to master file
   for (auto it=targetToGOT.begin(), end=targetToGOT.end(); it != end; ++it) {
-    _file.addAtom(*it->second);
+    mergedFile.addAtom(*it->second);
   }
   
 

Modified: lld/trunk/lib/Passes/StubsPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/StubsPass.cpp?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/lib/Passes/StubsPass.cpp (original)
+++ lld/trunk/lib/Passes/StubsPass.cpp Thu May 31 17:34:00 2012
@@ -7,10 +7,10 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This linker pass updates call sites which have references to shared library
+// This linker pass updates call-sites which have references to shared library
 // atoms to instead have a reference to a stub (PLT entry) for the specified
-// symbol.  The platform object does the work of creating the platform-specific
-// StubAtom.
+// symbol.  Each file format defines a subclass of StubsPass which implements
+// the abstract methods for creating the file format specific StubAtoms.
 //
 //===----------------------------------------------------------------------===//
 
@@ -18,30 +18,28 @@
 #include "lld/Core/File.h"
 #include "lld/Core/LLVM.h"
 #include "lld/Core/Pass.h"
-#include "lld/Core/Platform.h"
 #include "lld/Core/Reference.h"
-
 #include "llvm/ADT/DenseMap.h"
 
 namespace lld {
 
-void StubsPass::perform() {
+void StubsPass::perform(File& mergedFile) {
   // Skip this pass if output format uses text relocations instead of stubs.
-  if ( !_platform.noTextRelocs() )
+  if ( ! this->noTextRelocs() )
     return;
 
   // Scan all references in all atoms.
-  for(const DefinedAtom *atom : _file.defined()) {
+  for(const DefinedAtom *atom : mergedFile.defined()) {
     for (const Reference *ref : *atom) {
       // Look at call-sites.
-      if ( _platform.isCallSite(ref->kind()) ) {
+      if (this->isCallSite(ref->kind()) ) {
         const Atom* target = ref->target();
         assert(target != nullptr);
         bool replaceCalleeWithStub = false;
         if ( target->definition() == Atom::definitionSharedLibrary ) {
           // Calls to shared libraries go through stubs.
           replaceCalleeWithStub = true;
-        } 
+        }
         else if (const DefinedAtom* defTarget =
                      dyn_cast<DefinedAtom>(target)) {
           if ( defTarget->interposable() != DefinedAtom::interposeNo ) {
@@ -52,8 +50,8 @@
           }
         }
         if ( replaceCalleeWithStub ) {
-          // Ask platform to make stub and other support atoms.
-          const DefinedAtom* stub = _platform.getStub(*target, _file);
+          // Make file-format specific stub and other support atoms.
+          const DefinedAtom* stub = this->getStub(*target);
           assert(stub != nullptr);
           // Switch call site to reference stub atom instead.
           (const_cast<Reference*>(ref))->setTarget(stub);
@@ -62,8 +60,8 @@
     }
   }
 
-  // Tell platform to add all created stubs and support Atoms to file.
-  _platform.addStubAtoms(_file);
+  // Add all created stubs and support Atoms.
+ this->addStubAtoms(mergedFile);
 }
 
 

Added: lld/trunk/lib/ReaderWriter/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/CMakeLists.txt?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/CMakeLists.txt (added)
+++ lld/trunk/lib/ReaderWriter/CMakeLists.txt Thu May 31 17:34:00 2012
@@ -0,0 +1,9 @@
+add_subdirectory(ELF)
+add_subdirectory(MachO)
+add_subdirectory(Native)
+add_subdirectory(PECOFF)
+add_subdirectory(YAML)
+add_lld_library(lldReaderWriter
+  Reader.cpp
+  Writer.cpp
+  )

Added: lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt (added)
+++ lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt Thu May 31 17:34:00 2012
@@ -0,0 +1,4 @@
+add_lld_library(lldELF
+  ReaderELF.cpp
+  WriterELF.cpp
+  )

Added: lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/ReaderELF.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,41 @@
+//===- lib/ReaderWriter/ELF/ReaderELF.cpp --------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/ReaderELF.h"
+#include "lld/Core/File.h"
+
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+#include <map>
+#include <vector>
+
+
+namespace lld {
+
+ReaderOptionsELF::ReaderOptionsELF() {
+}
+
+ReaderOptionsELF::~ReaderOptionsELF() {
+}
+
+
+
+Reader* createReaderELF(const ReaderOptionsELF &options) {
+  assert(0 && "ELF Reader not yet implemented");
+  return nullptr;
+}
+
+
+} // namespace
+

Added: lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,35 @@
+//===- lib/ReaderWriter/ELF/WriterELF.cpp ---------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/WriterELF.h"
+
+#include "llvm/Support/Debug.h"
+
+
+namespace lld {
+namespace elf {
+
+// define ELF writer class here
+
+
+} // namespace elf
+
+Writer* createWriterELF(const WriterOptionsELF &options) {
+  assert(0 && "ELF support not implemented yet");
+  return nullptr;
+}
+
+WriterOptionsELF::WriterOptionsELF() {
+}
+
+WriterOptionsELF::~WriterOptionsELF() {
+}
+
+} // namespace lld
+

Added: lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt (added)
+++ lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt Thu May 31 17:34:00 2012
@@ -0,0 +1,4 @@
+add_lld_library(lldMachO
+  WriterMachO.cpp
+  ReferenceKinds.cpp
+  )

Added: lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp (added)
+++ lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.hpp Thu May 31 17:34:00 2012
@@ -0,0 +1,50 @@
+//===- lib/ReaderWriter/MachO/ExecutableAtoms.hpp -------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_EXECUTABLE_ATOM_H_
+#define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOM_H_
+
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+
+#include "lld/ReaderWriter/WriterMachO.h"
+
+#include "SimpleAtoms.hpp"
+
+namespace lld {
+namespace mach_o {
+
+
+//
+// CRuntimeFile adds an UndefinedAtom for "_main" so that the Resolving
+// phase will fail if "_main" is undefined.
+//
+class CRuntimeFile : public SimpleFile {
+public:
+    CRuntimeFile(const WriterOptionsMachO &options) 
+      : SimpleFile("C runtime"), _undefMain(*this, "_main") {
+      // only main executables need _main
+      if ( options.outputKind() == WriterOptionsMachO::outputDynamicExecutable)
+        this->addAtom(_undefMain);
+   }
+        
+private:
+  SimpleUndefinedAtom   _undefMain;
+};
+
+
+
+} // namespace mach_o 
+} // namespace lld 
+
+
+#endif // LLD_READER_WRITER_MACHO_EXECUTABLE_ATOM_H_

Added: lld/trunk/lib/ReaderWriter/MachO/GOTPass.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/GOTPass.hpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/GOTPass.hpp (added)
+++ lld/trunk/lib/ReaderWriter/MachO/GOTPass.hpp Thu May 31 17:34:00 2012
@@ -0,0 +1,51 @@
+//===- lib/ReaderWriter/MachO/GOTPass.hpp ---------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_GOT_PASS_H_
+#define LLD_READER_WRITER_MACHO_GOT_PASS_H_
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/SharedLibraryAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/Pass.h"
+
+#include "ReferenceKinds.h"
+#include "StubAtoms.hpp"
+
+namespace lld {
+namespace mach_o {
+
+
+class GOTPass : public lld::GOTPass {
+public:
+  virtual bool noTextRelocs() {
+    return true;
+  }
+
+  virtual bool isGOTAccess(Reference::Kind, bool& canBypassGOT) {
+    return false;
+  }
+
+  virtual void updateReferenceToGOT(const Reference*, bool targetIsNowGOT) {
+  
+  }
+
+  virtual const DefinedAtom* makeGOTEntry(const Atom&) {
+    return nullptr;
+  }
+  
+};
+
+
+} // namespace mach_o 
+} // namespace lld 
+
+
+#endif // LLD_READER_WRITER_MACHO_GOT_PASS_H_

Added: lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp (added)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOFormat.hpp Thu May 31 17:34:00 2012
@@ -0,0 +1,354 @@
+//===- lib/ReaderWriter/MachO/MachOFormat.hpp -----------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//
+// This file contains all the structs and constants needed to write a 
+// mach-o final linked image.  The names of the structs and constants
+// are the same as in the darwin native header <mach-o/loader.h> so
+// they will be familiar to anyone who has used that header.
+//
+
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Memory.h"
+
+#ifndef LLD_READER_WRITER_MACHO_FORMAT_H_
+#define LLD_READER_WRITER_MACHO_FORMAT_H_
+
+namespace lld {
+namespace mach_o {
+
+class load_command {
+public:
+  uint32_t  cmd;  
+  uint32_t  cmdsize;
+  
+  void copyTo(uint8_t* to, bool swap=false) {
+    ::memcpy(to, (uint8_t*)&cmd, cmdsize);
+  }
+};
+
+enum { 
+  MH_MAGIC = 0xfeedface,
+  MAGIC_64 = 0xfeedfacf 
+};
+
+enum {
+  CPU_TYPE_I386 =   0x00000007,
+  CPU_TYPE_X86_64 = 0x01000007
+};
+
+enum {
+  CPU_SUBTYPE_X86_ALL = 0x00000003,
+  CPU_SUBTYPE_X86_64_ALL = 0x00000003
+};
+
+enum {
+  MH_OBJECT     = 0x1,
+  MH_EXECUTE    = 0x2,
+  MH_DYLIB      = 0x6,
+  MH_DYLINKER   = 0x7,
+  MH_BUNDLE     = 0x8,
+  MH_DYLIB_STUB = 0x9,
+  MH_KEXT_BUNDLE= 0xB
+};
+
+
+class mach_header {
+public:
+  uint32_t    magic;  
+  uint32_t    cputype;
+  uint32_t    cpusubtype;  
+  uint32_t    filetype;  
+  uint32_t    ncmds;    
+  uint32_t    sizeofcmds;  
+  uint32_t    flags;  
+  uint32_t    reserved;  
+ 
+  uint64_t size() {
+    return (magic == 0xfeedfacf) ? 32 : 28;
+  }
+  
+  void copyTo(uint8_t* to, bool swap=false) {
+    ::memcpy(to, (char*)&magic, this->size());
+  }
+ 
+  void recordLoadCommand(const class load_command* lc) {
+    ++ncmds;
+    sizeofcmds += lc->cmdsize;
+  }
+    
+
+};
+
+enum {
+  SECTION_TYPE              = 0x000000FF,
+  S_REGULAR                 = 0x00000000,
+  S_ZEROFILL                = 0x00000001,
+  S_CSTRING_LITERALS        = 0x00000002,
+  S_NON_LAZY_SYMBOL_POINTERS= 0x00000006,
+  S_LAZY_SYMBOL_POINTERS    = 0x00000007,
+  S_SYMBOL_STUBS            = 0x00000008,
+  
+  S_ATTR_PURE_INSTRUCTIONS  = 0x80000000,
+  S_ATTR_SOME_INSTRUCTIONS  = 0x00000400
+};
+
+struct section_64 {
+  char      sectname[16];  
+  char      segname[16];  
+  uint64_t  addr;  
+  uint64_t  size;    
+  uint32_t  offset;  
+  uint32_t  align;    
+  uint32_t  reloff;  
+  uint32_t  nreloc;    
+  uint32_t  flags;    
+  uint32_t  reserved1;
+  uint32_t  reserved2;  
+  uint32_t  reserved3;
+};
+
+enum {
+  LC_SEGMENT_64 = 0x19
+};
+
+enum {
+  VM_PROT_NONE    = 0x0,
+  VM_PROT_READ    = 0x1,
+  VM_PROT_WRITE   = 0x2,
+  VM_PROT_EXECUTE = 0x4,
+};
+
+
+
+class segment_command_64 : public load_command {
+public:
+  char      segname[16];  
+  uint64_t  vmaddr;    
+  uint64_t  vmsize;    
+  uint64_t  fileoff;  
+  uint64_t  filesize;  
+  uint32_t  maxprot;  
+  uint32_t  initprot;  
+  uint32_t  nsects;    
+  uint32_t  flags;  
+  section_64 sections[1];
+  
+  // The segment_command_64 load commands has a nsect trailing
+  // section_64 records appended to the end.
+  static segment_command_64* make(unsigned sectCount) {
+    // Compute size in portable way.  Can't use offsetof() in non-POD class.
+    // Can't use zero size sections[] array above.
+    // So, since sizeof() already includes one section_64, subtract it off.
+    unsigned size = sizeof(segment_command_64) 
+                    + ((int)sectCount -1) * sizeof(section_64);
+    segment_command_64* result = reinterpret_cast<segment_command_64*>
+                                                          (::calloc(1, size));
+    result->cmd = LC_SEGMENT_64;
+    result->cmdsize = size;
+    result->nsects = sectCount;
+    return result;
+  }
+  
+};
+
+
+enum {
+  LC_LOAD_DYLINKER = 0xe
+};
+
+
+class dylinker_command : public load_command {
+public:
+  uint32_t  name_offset;
+  char      name[1];
+  
+  static dylinker_command* make(const char* path) {
+    unsigned size = (sizeof(dylinker_command) + strlen(path) + 7) & (-8);
+    dylinker_command* result = reinterpret_cast<dylinker_command*>
+                                                          (::calloc(1, size));
+    result->cmd = LC_LOAD_DYLINKER;
+    result->cmdsize = size;
+    result->name_offset = 12;
+    strcpy(result->name, path);
+    return result;
+  }
+};
+
+
+
+
+
+
+enum {
+  N_UNDF = 0x00,
+  N_EXT  = 0x01,
+  N_PEXT = 0x10,
+  N_SECT = 0x0e
+};
+
+class nlist_64 {
+public:
+  uint32_t  n_strx; 
+  uint8_t   n_type; 
+  uint8_t   n_sect;   
+  uint16_t  n_desc;   
+  uint64_t  n_value;    
+
+   void copyTo(uint8_t* to, bool swap=false) {
+     ::memcpy(to, (uint8_t*)&n_strx, 16);
+  }
+
+
+};
+
+
+enum {
+  LC_SYMTAB  =  0x2
+};
+
+class symtab_command : public load_command {
+public:
+  uint32_t  symoff;  
+  uint32_t  nsyms;  
+  uint32_t  stroff;  
+  uint32_t  strsize;  
+
+  static symtab_command* make() {
+    unsigned size = sizeof(symtab_command);
+    symtab_command* result = reinterpret_cast<symtab_command*>
+                                                          (::calloc(1, size));
+    result->cmd = LC_SYMTAB;
+    result->cmdsize = size;
+    return result;
+  }
+};
+
+
+enum {
+  LC_MAIN = 0x80000028
+};
+
+class entry_point_command : public load_command {
+public:
+  uint64_t  entryoff;  /* file (__TEXT) offset of main() */
+  uint64_t  stacksize;/* if not zero, initial stack size */
+
+  static entry_point_command* make() {
+    unsigned size = sizeof(entry_point_command);
+    entry_point_command* result = reinterpret_cast<entry_point_command*>
+                                                          (::calloc(1, size));
+    result->cmd = LC_MAIN;
+    result->cmdsize = size;
+    return result;
+  }
+};
+
+enum {
+  LC_DYLD_INFO_ONLY = 0x80000022
+};
+
+struct dyld_info_command : public load_command {
+  uint32_t   rebase_off;  
+  uint32_t   rebase_size;  
+  uint32_t   bind_off;  
+  uint32_t   bind_size;  
+  uint32_t   weak_bind_off;  
+  uint32_t   weak_bind_size; 
+  uint32_t   lazy_bind_off;
+  uint32_t   lazy_bind_size; 
+  uint32_t   export_off;  
+  uint32_t   export_size;  
+
+  static dyld_info_command* make() {
+    unsigned size = sizeof(dyld_info_command);
+    dyld_info_command* result = reinterpret_cast<dyld_info_command*>
+    (::calloc(1, size));
+    result->cmd = LC_DYLD_INFO_ONLY;
+    result->cmdsize = size;
+    return result;
+  }
+};
+
+
+enum {
+  LC_LOAD_DYLIB = 0xC
+};
+  
+
+struct dylib_command : public load_command {
+  uint32_t  name_offset;
+  uint32_t  timestamp;
+  uint32_t  current_version;    
+  uint32_t  compatibility_version;
+  char      name[1];
+  
+  static dylib_command* make(const char* path) {
+    unsigned size = (sizeof(dylib_command) + strlen(path) + 7) & (-8);
+    dylib_command* result = reinterpret_cast<dylib_command*>
+    (::calloc(1, size));
+    result->cmd = LC_LOAD_DYLIB;
+    result->cmdsize = size;
+    result->name_offset = 24;
+    result->name_offset = 24;
+    result->timestamp = 0;
+    result->current_version = 0x10000;
+    result->compatibility_version = 0x10000;
+    strcpy(result->name, path);
+    return result;
+  }
+  
+};
+
+enum {
+  BIND_TYPE_POINTER               = 1,
+  BIND_TYPE_TEXT_ABSOLUTE32        = 2,
+  BIND_TYPE_TEXT_PCREL32          = 3
+};
+
+enum {
+  BIND_SPECIAL_DYLIB_SELF             = 0,
+  BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE  = -1,
+  BIND_SPECIAL_DYLIB_FLAT_LOOKUP      =  -2
+};
+
+enum {
+  BIND_SYMBOL_FLAGS_WEAK_IMPORT           = 0x1,
+  BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION    =  0x8
+};
+
+enum {
+  BIND_OPCODE_MASK                              = 0xF0,
+  BIND_IMMEDIATE_MASK                           = 0x0F,
+  BIND_OPCODE_DONE                              = 0x00,
+  BIND_OPCODE_SET_DYLIB_ORDINAL_IMM             = 0x10,
+  BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB            = 0x20,
+  BIND_OPCODE_SET_DYLIB_SPECIAL_IMM             = 0x30,
+  BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM     = 0x40,
+  BIND_OPCODE_SET_TYPE_IMM                      = 0x50,
+  BIND_OPCODE_SET_ADDEND_SLEB                   = 0x60,
+  BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB       = 0x70,
+  BIND_OPCODE_ADD_ADDR_ULEB                     = 0x80,
+  BIND_OPCODE_DO_BIND                           = 0x90,
+  BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB             = 0xA0,
+  BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED       = 0xB0,
+  BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB  = 0xC0
+};
+
+
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+
+#endif // LLD_READER_WRITER_MACHO_FORMAT_H_
+

Added: lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp (added)
+++ lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,103 @@
+//===- lib/FileFormat/MachO/ReferenceKinds.cpp ----------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "ReferenceKinds.h"
+
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+namespace mach_o {
+
+  
+struct Mapping {
+  const char*           string;
+  Reference::Kind       value;
+  uint32_t              flags;
+};
+
+enum {
+  flagsNone       = 0x0000,
+  flagsIsCallSite = 0x0001,
+  flagsUsesGOT    = 0x0002,
+  flagsisGOTLoad  = 0x0006,
+  flags32RipRel   = 0x1000,
+};
+
+
+static const Mapping sKindMappingsx86_64[] = {
+  { "none",           ReferenceKind::x86_64_none,        flagsNone },
+  { "call32",         ReferenceKind::x86_64_call32,      flagsIsCallSite | flags32RipRel },
+  { "pcrel32",        ReferenceKind::x86_64_pcRel32,     flags32RipRel },
+  { "gotLoad32",      ReferenceKind::x86_64_gotLoad32,   flagsisGOTLoad | flags32RipRel },
+  { "gotUse32",       ReferenceKind::x86_64_gotUse32,    flagsUsesGOT | flags32RipRel },
+  { "lea32wasGot",    ReferenceKind::x86_64_lea32WasGot, flags32RipRel },
+  { "lazyTarget",     ReferenceKind::x86_64_lazyTarget,  flagsNone },
+  { "lazyImm",        ReferenceKind::x86_64_lazyImm,     flagsNone },
+  { "gotTarget",      ReferenceKind::x86_64_gotTarget,   flagsNone },
+  { "pointer64",      ReferenceKind::x86_64_pointer64,   flagsNone },
+  { NULL,             ReferenceKind::x86_64_none,        flagsNone }
+};
+
+
+Reference::Kind ReferenceKind::fromString(StringRef kindName) {
+  for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
+    if ( kindName.equals(p->string) )
+      return p->value;
+  }
+  assert(0 && "unknown darwin reference kind");
+  return 0;
+}
+
+StringRef ReferenceKind::toString(Reference::Kind kindValue) {
+  for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
+    if ( kindValue == p->value)
+      return p->string;
+  }
+  return StringRef("???");
+}
+
+static const Mapping* mappingsForArch(WriterOptionsMachO::Architecture arch) {
+ switch ( arch ) {
+    case WriterOptionsMachO::arch_x86_64:
+      return sKindMappingsx86_64;
+    case WriterOptionsMachO::arch_x86:
+    case WriterOptionsMachO::arch_arm:
+      assert(0 && "references table not yet implemented for arch");
+      return nullptr;
+  }
+}
+
+bool ReferenceKind::isCallSite(WriterOptionsMachO::Architecture arch, 
+                                                    Reference::Kind kindValue) {
+   for (const Mapping* p = mappingsForArch(arch); p->string != NULL; ++p) {
+    if ( kindValue == p->value )
+      return (p->flags & flagsIsCallSite);
+  }
+  return false;
+}
+
+bool ReferenceKind::isRipRel32(Reference::Kind kindValue) {
+  for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
+    if ( kindValue == p->value )
+      return (p->flags & flags32RipRel);
+  }
+  return false;
+}
+
+
+
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+

Added: lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h (added)
+++ lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h Thu May 31 17:34:00 2012
@@ -0,0 +1,77 @@
+//===- lib/FileFormat/MachO/ReferenceKinds.h ------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Reference.h"
+#include "lld/ReaderWriter/WriterMachO.h"
+
+#ifndef LLD_READER_WRITER_MACHO_REFERENCE_KINDS_H_
+#define LLD_READER_WRITER_MACHO_REFERENCE_KINDS_H_
+
+namespace lld {
+namespace mach_o {
+
+
+class ReferenceKind {
+public:
+  // x86_64 Reference Kinds
+  enum {
+    x86_64_none        = 0,
+    x86_64_call32      = 1,
+    x86_64_pcRel32     = 2,
+    x86_64_gotLoad32   = 3,
+    x86_64_gotUse32    = 4,
+    x86_64_lea32WasGot = 5,
+    x86_64_lazyTarget  = 6,
+    x86_64_lazyImm     = 7,
+    x86_64_gotTarget   = 8,
+    x86_64_pointer64   = 9,
+  };
+
+  // x86 Reference Kinds
+ enum {
+    x86_none        = 0,
+    x86_call32      = 1,
+    x86_pointer32   = 2,
+    x86_lazyTarget  = 3,
+    x86_lazyImm     = 4,
+    // FIXME
+  };
+
+  // ARM Reference Kinds
+ enum {
+    arm_none        = 0,
+    arm_br22        = 1,
+    arm_pointer32   = 2,
+    arm_lazyTarget  = 3,
+    arm_lazyImm     = 4,
+    // FIXME
+  };
+
+  static bool isCallSite(WriterOptionsMachO::Architecture arch, 
+                                                    Reference::Kind kindValue);
+  
+  static bool isRipRel32(Reference::Kind kindValue);
+
+
+  static Reference::Kind fromString(StringRef kindName); 
+  static StringRef toString(Reference::Kind kindValue);
+  
+};
+
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+
+#endif // LLD_READER_WRITER_MACHO_REFERENCE_KINDS_H_
+

Added: lld/trunk/lib/ReaderWriter/MachO/SimpleAtoms.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/SimpleAtoms.hpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/SimpleAtoms.hpp (added)
+++ lld/trunk/lib/ReaderWriter/MachO/SimpleAtoms.hpp Thu May 31 17:34:00 2012
@@ -0,0 +1,247 @@
+//===- lib/ReaderWriter/MachO/SimpleAtoms.hpp -----------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_SIMPLE_ATOM_H_
+#define LLD_READER_WRITER_MACHO_SIMPLE_ATOM_H_
+
+#include <vector>
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+
+namespace lld {
+namespace mach_o {
+
+
+//
+// Simple File
+//
+class SimpleFile : public File {
+public:
+      SimpleFile(StringRef path) 
+        : File(path) {
+      }
+      
+  virtual void addAtom(const Atom &atom) {
+    if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
+      _definedAtoms._atoms.push_back(defAtom);
+    } 
+    else if (const UndefinedAtom* undefAtom = dyn_cast<UndefinedAtom>(&atom)) {
+      _undefinedAtoms._atoms.push_back(undefAtom);
+    } 
+    else if (const SharedLibraryAtom* slAtom =
+                 dyn_cast<SharedLibraryAtom>(&atom)) {
+      _sharedLibraryAtoms._atoms.push_back(slAtom);
+    } 
+    else if (const AbsoluteAtom* abAtom = dyn_cast<AbsoluteAtom>(&atom)) {
+      _absoluteAtoms._atoms.push_back(abAtom);
+    } 
+    else {
+      assert(0 && "atom has unknown definition kind");
+    }
+  }
+
+  virtual const atom_collection<DefinedAtom>& defined() const {
+    return _definedAtoms;
+  }
+  virtual const atom_collection<UndefinedAtom>& undefined() const {
+      return _undefinedAtoms;
+  }
+  virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
+      return _sharedLibraryAtoms;
+  }
+  virtual const atom_collection<AbsoluteAtom>& absolute() const {
+      return _absoluteAtoms;
+  }
+      
+private:
+  atom_collection_vector<DefinedAtom>         _definedAtoms;
+  atom_collection_vector<UndefinedAtom>       _undefinedAtoms;
+  atom_collection_vector<SharedLibraryAtom>   _sharedLibraryAtoms;
+  atom_collection_vector<AbsoluteAtom>        _absoluteAtoms;
+};
+
+
+
+//
+// Simple Reference
+//
+class SimpleReference : public Reference {
+public:
+                SimpleReference(Reference::Kind k, uint64_t off, 
+                                const Atom *t, Reference::Addend a) 
+                      : _target(t), _offsetInAtom(off), _addend(a), _kind(k) { }
+
+  virtual uint64_t offsetInAtom() const {
+    return _offsetInAtom;
+  }
+
+  virtual Kind kind() const {
+    return _kind;
+  }
+
+  virtual void setKind(Kind k) {
+    _kind = k;
+  }
+
+  virtual const Atom* target() const {
+    return _target;
+  }
+
+  virtual Addend addend() const {
+    return _addend;
+  }
+
+  virtual void setAddend(Addend a) {
+    _addend = a;
+  }
+
+  virtual void setTarget(const Atom* newAtom) {
+    _target = newAtom;
+  }
+private:
+  const Atom*  _target;
+  uint64_t     _offsetInAtom;
+  Addend       _addend;
+  Kind         _kind;
+};
+
+
+//
+// Generic Atom base class
+//
+class SimpleDefinedAtom : public DefinedAtom {
+public:
+        SimpleDefinedAtom(const File &f) : _file(f) {
+          static uint32_t lastOrdinal = 0;
+          _ordinal = lastOrdinal++; 
+        }
+
+  virtual const File& file() const {
+    return _file;
+  }
+
+  virtual StringRef name() const {
+    return StringRef();
+  }
+  
+  virtual uint64_t ordinal() const {
+    return _ordinal;
+  }
+
+  virtual Scope scope() const {
+    return DefinedAtom::scopeLinkageUnit;
+  }
+  
+  virtual Interposable interposable() const {
+    return DefinedAtom::interposeNo;
+  }
+  
+  virtual Merge merge() const {
+    return DefinedAtom::mergeNo;
+  }
+  
+  virtual Alignment alignment() const {
+    return Alignment(0,0);
+  }
+  
+  virtual SectionChoice sectionChoice() const {
+    return DefinedAtom::sectionBasedOnContent;
+  }
+    
+  virtual StringRef customSectionName() const {
+    return StringRef();
+  }
+  virtual DeadStripKind deadStrip() const {
+    return DefinedAtom::deadStripNormal;
+  }
+    
+  virtual bool isThumb() const {
+    return false;
+  }
+    
+  virtual bool isAlias() const {
+    return false;
+  }
+  
+  virtual DefinedAtom::reference_iterator begin() const {
+    uintptr_t index = 0;
+    const void* it = reinterpret_cast<const void*>(index);
+    return reference_iterator(*this, it);
+  }
+
+  virtual DefinedAtom::reference_iterator end() const {
+    uintptr_t index = _references.size();
+    const void* it = reinterpret_cast<const void*>(index);
+    return reference_iterator(*this, it);
+  }
+
+  virtual const Reference* derefIterator(const void* it) const {
+    uintptr_t index = reinterpret_cast<uintptr_t>(it);
+    assert(index < _references.size());
+    return &_references[index];
+  }
+
+  virtual void incrementIterator(const void*& it) const {
+    uintptr_t index = reinterpret_cast<uintptr_t>(it);
+    ++index;
+    it = reinterpret_cast<const void*>(index);
+  }
+  
+  void addReference(Reference::Kind kind, uint64_t offset, const Atom *target, 
+                   Reference::Addend addend) {
+    _references.push_back(SimpleReference(kind, offset, target, addend));
+  }
+  
+private:
+  const File&                   _file;
+  uint32_t                      _ordinal;
+  std::vector<SimpleReference>  _references;
+};
+
+
+
+//
+// Generic UndefinedAtom base class
+//
+class SimpleUndefinedAtom : public UndefinedAtom {
+public:
+        SimpleUndefinedAtom(const File &f, StringRef name) 
+            : _file(f), _name(name) {
+        }
+
+  /// file - returns the File that produced/owns this Atom
+  virtual const class File& file() const {
+    return _file;
+  }
+
+  /// name - The name of the atom. For a function atom, it is the (mangled)
+  /// name of the function.
+  virtual StringRef name() const {
+    return _name;
+  }
+ 
+  virtual CanBeNull canBeNull() const {
+    return UndefinedAtom::canBeNullNever;
+  }
+ 
+private:
+  const File&                   _file;
+  StringRef                     _name;
+};
+
+
+
+} // namespace mach_o 
+} // namespace lld 
+
+
+#endif // LLD_READER_WRITER_MACHO_SIMPLE_ATOM_H_

Added: lld/trunk/lib/ReaderWriter/MachO/StubAtoms.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/StubAtoms.hpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/StubAtoms.hpp (added)
+++ lld/trunk/lib/ReaderWriter/MachO/StubAtoms.hpp Thu May 31 17:34:00 2012
@@ -0,0 +1,233 @@
+//===- lib/ReaderWriter/MachO/StubAtoms.hpp -------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_STUB_ATOM_H_
+#define LLD_READER_WRITER_MACHO_STUB_ATOM_H_
+
+#include "llvm/ADT/ArrayRef.h"
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/SharedLibraryAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+
+#include "ReferenceKinds.h"
+#include "SimpleAtoms.hpp"
+
+namespace lld {
+namespace mach_o {
+
+
+//
+// X86_64 Stub Atom created by the stubs pass.
+//
+class X86_64StubAtom : public SimpleDefinedAtom {
+public:
+        X86_64StubAtom(const File &file, const Atom &lazyPointer) 
+                       : SimpleDefinedAtom(file) {
+          this->addReference(ReferenceKind::x86_64_pcRel32, 2, &lazyPointer, 0);
+        }
+
+  virtual ContentType contentType() const  {
+    return DefinedAtom::typeStub;
+  }
+
+  virtual uint64_t size() const {
+    return 6;
+  }
+
+  virtual ContentPermissions permissions() const  {
+    return DefinedAtom::permR_X;
+  }
+  
+  virtual ArrayRef<uint8_t> rawContent() const {
+    static const uint8_t instructions[] = 
+              { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 }; // jmp *lazyPointer
+    assert(sizeof(instructions) == this->size());
+    return ArrayRef<uint8_t>(instructions, sizeof(instructions));
+  }
+  
+};
+
+
+//
+// X86_64 Stub Helper Common Atom created by the stubs pass.
+//
+class X86_64StubHelperCommonAtom : public SimpleDefinedAtom {
+public:
+  X86_64StubHelperCommonAtom(const File &file, const Atom &cache,
+                                               const Atom &binder)
+  : SimpleDefinedAtom(file) {
+    this->addReference(ReferenceKind::x86_64_pcRel32, 3,  &cache, 0);
+    this->addReference(ReferenceKind::x86_64_pcRel32, 11, &binder, 0);
+  }
+  
+  virtual ContentType contentType() const  {
+    return DefinedAtom::typeStubHelper;
+  }
+  
+  virtual uint64_t size() const {
+    return 16;
+  }
+  
+  virtual ContentPermissions permissions() const  {
+    return DefinedAtom::permR_X;
+  }
+  
+  virtual ArrayRef<uint8_t> rawContent() const {
+    static const uint8_t instructions[] = 
+    { 0x4C, 0x8D, 0x1D, 0x00, 0x00, 0x00, 0x00,   // leaq cache(%rip),%r11
+      0x41, 0x53,                                 // push %r11
+      0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,         // jmp *binder(%rip)
+      0x90 };                                     // nop
+    assert(sizeof(instructions) == this->size());
+    return ArrayRef<uint8_t>(instructions, sizeof(instructions));
+  }
+  
+};
+  
+  
+
+//
+// X86_64 Stub Helper Atom created by the stubs pass.
+//
+class X86_64StubHelperAtom : public SimpleDefinedAtom {
+public:
+  X86_64StubHelperAtom(const File &file, const Atom &helperCommon) 
+  : SimpleDefinedAtom(file) {
+    this->addReference(ReferenceKind::x86_64_lazyImm, 1, nullptr, 0);
+    this->addReference(ReferenceKind::x86_64_pcRel32, 6, &helperCommon, 0);
+  }
+  
+  virtual ContentType contentType() const  {
+    return DefinedAtom::typeStubHelper;
+  }
+  
+  virtual uint64_t size() const {
+    return 10;
+  }
+  
+  virtual ContentPermissions permissions() const  {
+    return DefinedAtom::permR_X;
+  }
+  
+  virtual ArrayRef<uint8_t> rawContent() const {
+    static const uint8_t instructions[] = 
+              { 0x68, 0x00, 0x00, 0x00, 0x00,   // pushq $lazy-info-offset
+                0xE9, 0x00, 0x00, 0x00, 0x00 }; // jmp helperhelper
+    assert(sizeof(instructions) == this->size());
+    return ArrayRef<uint8_t>(instructions, sizeof(instructions));
+  }
+ 
+};
+  
+
+//
+// X86_64 Lazy Pointer Atom created by the stubs pass.
+//
+class X86_64LazyPointerAtom : public SimpleDefinedAtom {
+public:
+        X86_64LazyPointerAtom(const File &file, const Atom &helper,
+                                                const Atom &shlib)
+              : SimpleDefinedAtom(file) {
+                this->addReference(ReferenceKind::x86_64_pointer64, 0, &helper, 0);
+                this->addReference(ReferenceKind::x86_64_lazyTarget, 0, &shlib, 0);
+        }
+
+  virtual ContentType contentType() const  {
+    return DefinedAtom::typeLazyPointer;
+  }
+
+  virtual uint64_t size() const {
+    return 8;
+  }
+
+  virtual ContentPermissions permissions() const  {
+    return DefinedAtom::permRW_;
+  }
+  
+  virtual ArrayRef<uint8_t> rawContent() const {
+    static const uint8_t bytes[] = 
+                            { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    return ArrayRef<uint8_t>(bytes, 8);
+  }
+  
+};
+
+
+//
+// X86_64 NonLazy (GOT) Pointer Atom created by the stubs pass.
+//
+class X86_64NonLazyPointerAtom : public SimpleDefinedAtom {
+public:
+  X86_64NonLazyPointerAtom(const File &file)
+  : SimpleDefinedAtom(file) {
+  }
+  
+  X86_64NonLazyPointerAtom(const File &file, const Atom &shlib)
+  : SimpleDefinedAtom(file) {
+    this->addReference(ReferenceKind::x86_64_pointer64, 0, &shlib, 0);
+  }
+  
+  virtual ContentType contentType() const  {
+    return DefinedAtom::typeGOT;
+  }
+  
+  virtual uint64_t size() const {
+    return 8;
+  }
+  
+  virtual ContentPermissions permissions() const  {
+    return DefinedAtom::permRW_;
+  }
+  
+  virtual ArrayRef<uint8_t> rawContent() const {
+    static const uint8_t bytes[] = 
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    return ArrayRef<uint8_t>(bytes, 8);
+  }
+  
+};
+  
+  
+//
+// StubBinderAtom created by the stubs pass.
+//
+class StubBinderAtom : public SharedLibraryAtom {
+public:
+  StubBinderAtom(const File &f) : _file(f) { 
+  }
+          
+  virtual const File& file() const {
+    return _file;
+  }
+
+  virtual StringRef name() const {
+    return StringRef("dyld_stub_binder");
+  }
+
+  virtual StringRef loadName() const {
+    return StringRef("/usr/lib/libSystem.B.dylib");
+  }
+  
+  virtual bool canBeNullAtRuntime() const {
+    return false;
+  }
+  
+private:
+  const File  &_file;
+};
+
+
+
+} // namespace mach_o 
+} // namespace lld 
+
+
+#endif // LLD_READER_WRITER_MACHO_STUB_ATOM_H_

Added: lld/trunk/lib/ReaderWriter/MachO/StubsPass.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/StubsPass.hpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/StubsPass.hpp (added)
+++ lld/trunk/lib/ReaderWriter/MachO/StubsPass.hpp Thu May 31 17:34:00 2012
@@ -0,0 +1,145 @@
+//===- lib/ReaderWriter/MachO/StubsPass.hpp -------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_STUBS_PASS_H_
+#define LLD_READER_WRITER_MACHO_STUBS_PASS_H_
+
+#include "llvm/ADT/DenseMap.h"
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/SharedLibraryAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/Pass.h"
+
+#include "ReferenceKinds.h"
+#include "SimpleAtoms.hpp"
+#include "StubAtoms.hpp"
+
+namespace lld {
+namespace mach_o {
+
+
+class StubsPass : public lld::StubsPass {
+public:
+  StubsPass(const WriterOptionsMachO &options) : _options(options) {
+  }
+
+  virtual bool noTextRelocs() {
+    return _options.noTextRelocations();
+  }
+
+  virtual bool isCallSite(Reference::Kind kind) {
+    return ReferenceKind::isCallSite(_options.architecture(), kind);
+  }
+
+  virtual const DefinedAtom* getStub(const Atom& target) {
+    auto pos = _targetToStub.find(&target);
+    if ( pos != _targetToStub.end() ) {
+      // Reuse an existing stub.
+      assert(pos->second != nullptr);
+      return pos->second;
+    }
+    else {
+      // There is no existing stub, so create a new one.
+      return this->makeStub(target);
+    }
+  }
+
+  const DefinedAtom* makeStub(const Atom& target) {
+    switch ( _options.architecture() ) {
+      case WriterOptionsMachO::arch_x86_64:
+        return makeStub_x86_64(target);
+
+      case WriterOptionsMachO::arch_x86:
+        return makeStub_x86(target);
+
+      case WriterOptionsMachO::arch_arm:
+        return makeStub_arm(target);
+    }
+  }
+
+  const DefinedAtom* makeStub_x86_64(const Atom& target) {
+    if ( _helperCommonAtom == nullptr ) {
+      // Lazily create common helper code and data.
+      _helperCacheAtom = new X86_64NonLazyPointerAtom(_file);
+      _binderAtom = new StubBinderAtom(_file);
+      _helperBinderAtom = new X86_64NonLazyPointerAtom(_file, *_binderAtom);
+      _helperCommonAtom = new X86_64StubHelperCommonAtom(_file,
+                                       *_helperCacheAtom, *_helperBinderAtom);
+    }
+    const DefinedAtom* helper = new X86_64StubHelperAtom(_file,
+                                                          *_helperCommonAtom);
+    _stubHelperAtoms.push_back(helper);
+    const DefinedAtom* lp = new X86_64LazyPointerAtom(_file, *helper, target);
+    assert(lp->contentType() == DefinedAtom::typeLazyPointer);
+    _lazyPointers.push_back(lp);
+    const DefinedAtom* stub = new X86_64StubAtom(_file, *lp);
+     assert(stub->contentType() == DefinedAtom::typeStub);
+    _targetToStub[&target] = stub;
+    return stub;
+  }
+
+  const DefinedAtom* makeStub_x86(const Atom& target) {
+    assert(0 && "stubs not yet implemented for x86");
+    return nullptr;
+  }
+
+  const DefinedAtom* makeStub_arm(const Atom& target) {
+    assert(0 && "stubs not yet implemented for arm");
+    return nullptr;
+  }
+
+
+  virtual void addStubAtoms(File &mergedFile) {
+    // Add all stubs to master file.
+    for (auto it : _targetToStub) {
+      mergedFile.addAtom(*it.second);
+    }
+    // Add helper code atoms.
+    mergedFile.addAtom(*_helperCommonAtom);
+    for (const DefinedAtom *lp : _stubHelperAtoms) {
+      mergedFile.addAtom(*lp);
+    }
+    // Add GOT slots used for lazy binding.
+    mergedFile.addAtom(*_helperBinderAtom);
+    mergedFile.addAtom(*_helperCacheAtom);
+    // Add all lazy pointers to master file.
+    for (const DefinedAtom *lp : _lazyPointers) {
+      mergedFile.addAtom(*lp);
+    }
+    // Add sharedlibrary atom
+    mergedFile.addAtom(*_binderAtom);
+  }
+
+private:
+
+  class File : public SimpleFile {
+  public:
+      File() : SimpleFile("MachO Stubs pass") {
+      }
+  };
+
+  const WriterOptionsMachO                       &_options;
+  File                                            _file;
+  llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub;
+  std::vector<const DefinedAtom*>                 _lazyPointers;
+  std::vector<const DefinedAtom*>                 _stubHelperAtoms;
+  const SharedLibraryAtom                        *_binderAtom;
+  const DefinedAtom*                              _helperCommonAtom;
+  const DefinedAtom*                              _helperCacheAtom;
+  const DefinedAtom*                              _helperBinderAtom;
+};
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+#endif // LLD_READER_WRITER_MACHO_STUBS_PASS_H_

Added: lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp (added)
+++ lld/trunk/lib/ReaderWriter/MachO/WriterMachO.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,1533 @@
+//===- lib/ReaderWriter/MachO/WriterMachO.cpp -----------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/WriterMachO.h"
+
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+//#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/InputFiles.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/SharedLibraryAtom.h"
+
+#include <vector>
+#include <map>
+#include <string.h>
+
+#include "MachOFormat.hpp"
+#include "ReferenceKinds.h"
+#include "ExecutableAtoms.hpp"
+#include "GOTPass.hpp"
+#include "StubsPass.hpp"
+
+
+namespace lld {
+namespace mach_o {
+
+//
+// A mach-o file consists of some meta data (header and load commands),
+// then atom content (e.g. function instructions), then more meta data
+// (symbol table, etc).  Before you can write a mach-o file, you need to
+// compute what will be the file offsets and "addresses" of various things
+// in the file.
+//
+// The design here is to break up what will be the mach-o file into chunks.
+// Each Chunk has an object to manage its size and content.  There is a
+// chunk for the mach_header, one for the load commands, and one for each
+// part of the LINKEDIT segment.  There is also one chunk for each traditional
+// mach-o section.  The MachOWriter manages the list of chunks.  And
+// asks each to determine its size in the correct order.  Many chunks
+// cannot be sized until other chunks are sized (e.g. the dyld info
+// in the LINKEDIT cannot be sized until all atoms have been assigned
+// addresses).
+//
+// Once all chunks have a size, the MachOWriter iterates through them and
+// asks each to write out their content.
+//
+
+
+
+//
+// A Chunk is an abstrace contiguous range of a generated
+// mach-o executable file.
+//
+class Chunk {
+public:
+  virtual StringRef   segmentName() const = 0;
+  virtual bool        occupiesNoDiskSpace();
+  virtual void        write(uint8_t *fileBuffer) = 0;
+  void                assignFileOffset(uint64_t &curOff, uint64_t &curAddr);
+  virtual const char* info() = 0;
+  uint64_t            size() const;
+  uint64_t            address() const;
+  uint64_t            fileOffset() const;
+  uint64_t            align2() const;
+  static uint64_t     alignTo(uint64_t value, uint8_t align2);
+
+protected:
+                      Chunk();
+
+  uint64_t            _size;
+  uint64_t            _address;
+  uint64_t            _fileOffset;
+  uint32_t            _align2;
+};
+
+
+
+//
+// A SectionChunk represents a set of Atoms assigned to a specific
+// mach-o section (which is a subrange of a mach-o segment).
+// For example, there is one SectionChunk for the __TEXT,__text section.
+//
+class SectionChunk : public Chunk {
+public:
+  static SectionChunk*  make(DefinedAtom::ContentType,
+                             const WriterOptionsMachO &options,
+                             class MachOWriter &writer);
+  virtual StringRef     segmentName() const;
+  virtual bool          occupiesNoDiskSpace();
+  virtual void          write(uint8_t *fileBuffer);
+  virtual const char*   info();
+  StringRef             sectionName();
+  uint32_t              flags() const;
+  uint32_t              permissions();
+  void                  appendAtom(const DefinedAtom*);
+
+  struct AtomInfo {
+    const DefinedAtom  *atom;
+    uint64_t            offsetInSection;
+  };
+
+  const std::vector<AtomInfo>& atoms() const;
+
+private:
+                SectionChunk(StringRef seg,
+                             StringRef sect,
+                             uint32_t flags,
+                             const WriterOptionsMachO &options,
+                             class MachOWriter &writer);
+
+  void          applyFixup(Reference::Kind kind, uint64_t addend,  
+                           uint8_t* location, uint64_t fixupAddress,
+                                                     uint64_t targetAddress);
+                                                     
+  StringRef                 _segmentName;
+  StringRef                 _sectionName;
+  const WriterOptionsMachO &_options;
+  class MachOWriter        &_writer;
+  uint32_t                  _flags;
+  uint32_t                  _permissions;
+  std::vector<AtomInfo>     _atoms;
+};
+
+
+
+//
+// A MachHeaderChunk represents the mach_header struct at the start
+// of a mach-o executable file.
+//
+class MachHeaderChunk : public Chunk {
+public:
+                MachHeaderChunk(const WriterOptionsMachO &options,
+                                const File &file);
+  virtual StringRef     segmentName() const;
+  virtual void          write(uint8_t *fileBuffer);
+  virtual const char*   info();
+  void                  recordLoadCommand(load_command*);
+  uint64_t              loadCommandsSize();
+
+private:
+  uint32_t filetype(WriterOptionsMachO::OutputKind kind);
+  
+  mach_header               _mh;
+};
+
+
+
+//
+// A LoadCommandsChunk represents the variable length list of
+// of load commands in a mach-o executable file right after the
+// mach_header.
+//
+class LoadCommandsChunk : public Chunk {
+public:
+                      LoadCommandsChunk(MachHeaderChunk&,
+                                        const WriterOptionsMachO &options,
+                                        class MachOWriter&);
+  virtual StringRef   segmentName() const;
+  virtual void        write(uint8_t *fileBuffer);
+  virtual const char* info();
+  void                computeSize(const lld::File &file);
+  void                addSection(SectionChunk*);
+  void                updateLoadCommandContent(const lld::File &file);
+
+private:
+  friend class LoadCommandPaddingChunk;
+
+  void                addLoadCommand(load_command* lc);
+  void                setMachOSection(SectionChunk *chunk,
+                                      segment_command_64 *seg, uint32_t index);
+  uint32_t            permissionsFromSections(
+                                  const SmallVector<SectionChunk*,16> &);
+
+  struct ChunkSegInfo {
+    SectionChunk*         chunk;
+    segment_command_64*   segment;
+    section_64*           section;
+  };
+
+  MachHeaderChunk             &_mh;
+  const WriterOptionsMachO    &_options;
+  class MachOWriter           &_writer;
+  segment_command_64          *_linkEditSegment;
+  symtab_command              *_symbolTableLoadCommand;
+  entry_point_command         *_entryPointLoadCommand;
+  dyld_info_command           *_dyldInfoLoadCommand;
+  std::vector<load_command*>   _loadCmds;
+  std::vector<ChunkSegInfo>    _sectionInfo;
+};
+
+
+
+//
+// A LoadCommandPaddingChunk represents the padding space between the last
+// load commmand and the first section (usually __text) in the __TEXT
+// segment.
+//
+class LoadCommandPaddingChunk : public Chunk {
+public:
+                      LoadCommandPaddingChunk(LoadCommandsChunk&);
+  virtual StringRef   segmentName() const;
+  virtual void        write(uint8_t *fileBuffer);
+  virtual const char* info();
+  void                computeSize();
+private:
+  LoadCommandsChunk&  _loadCommandsChunk;
+};
+
+
+
+//
+// LinkEditChunk is the base class for all chunks in the
+// __LINKEDIT segment at the end of a mach-o executable.
+//
+class LinkEditChunk : public Chunk {
+public:
+                      LinkEditChunk();
+  virtual StringRef   segmentName() const;
+  virtual void        computeSize(const lld::File &file,
+                                      const std::vector<SectionChunk*>&) = 0;
+};
+
+
+
+//
+// A DyldInfoChunk represents the bytes for any of the dyld info areas
+// in the __LINKEDIT segment at the end of a mach-o executable.
+//
+class DyldInfoChunk : public LinkEditChunk {
+public:
+                      DyldInfoChunk(class MachOWriter &);
+  virtual void        write(uint8_t *fileBuffer);
+
+protected:
+  void                append_byte(uint8_t);
+  void                append_uleb128(uint64_t);
+  void                append_string(StringRef);
+
+  class MachOWriter      &_writer;
+  std::vector<uint8_t>    _bytes;
+};
+
+
+
+//
+// A BindingInfoChunk represents the bytes containing binding info
+// in the __LINKEDIT segment at the end of a mach-o executable.
+//
+class BindingInfoChunk : public DyldInfoChunk {
+public:
+                      BindingInfoChunk(class MachOWriter &);
+  virtual void        computeSize(const lld::File &file,
+                                      const std::vector<SectionChunk*>&);
+  virtual const char* info();
+};
+
+
+
+//
+// A LazyBindingInfoChunk represents the bytes containing lazy binding info
+// in the __LINKEDIT segment at the end of a mach-o executable.
+//
+class LazyBindingInfoChunk : public DyldInfoChunk {
+public:
+                      LazyBindingInfoChunk(class MachOWriter &);
+  virtual void        computeSize(const lld::File &file,
+                                      const std::vector<SectionChunk*>&);
+  virtual const char* info();
+private:
+  void                 updateHelper(const DefinedAtom *, uint32_t );
+};
+
+
+//
+// A SymbolTableChunk represents the array of nlist structs in the
+// __LINKEDIT segment at the end of a mach-o executable.
+//
+class SymbolTableChunk : public LinkEditChunk {
+public:
+                      SymbolTableChunk(class SymbolStringsChunk&);
+  virtual void        write(uint8_t *fileBuffer);
+  virtual void        computeSize(const lld::File &file,
+                                      const std::vector<SectionChunk*>&);
+  virtual const char* info();
+  uint32_t            count();
+
+private:
+  uint8_t             nType(const DefinedAtom*);
+
+  SymbolStringsChunk       &_stringsChunk;
+  std::vector<nlist_64>     _globalDefinedsymbols;
+  std::vector<nlist_64>     _localDefinedsymbols;
+  std::vector<nlist_64>     _undefinedsymbols;
+};
+
+
+//
+// A SymbolStringsChunk represents the strings pointed to
+// by nlist structs in the __LINKEDIT segment at the end
+// of a mach-o executable.
+//
+class SymbolStringsChunk : public LinkEditChunk {
+public:
+                      SymbolStringsChunk();
+  virtual void        write(uint8_t *fileBuffer);
+  virtual void        computeSize(const lld::File &file,
+                                      const std::vector<SectionChunk*>&);
+  virtual const char* info();
+  uint32_t            stringIndex(StringRef);
+
+private:
+  std::vector<char>         _strings;
+};
+
+
+//
+// A MachOWriter manages all the Chunks that comprise a mach-o executable.
+//
+class MachOWriter : public Writer {
+public:
+              MachOWriter(const WriterOptionsMachO &options);
+
+  virtual error_code  writeFile(const lld::File &file, StringRef path);
+  virtual StubsPass  *stubPass();  
+  virtual GOTPass    *gotPass();  
+  virtual void        addFiles(InputFiles&);
+
+  uint64_t    addressOfAtom(const Atom *atom);
+  void        findSegment(StringRef segmentName, uint32_t *segIndex,
+                                uint64_t *segStartAddr, uint64_t *segEndAddr);
+
+  const std::vector<Chunk*> chunks() { return _chunks; }
+
+private:
+  friend class LoadCommandsChunk;
+  friend class LazyBindingInfoChunk;
+
+  void        build(const lld::File &file);
+  void        createChunks(const lld::File &file);
+  void        buildAtomToAddressMap();
+  void        assignFileOffsets();
+  void        addLinkEditChunk(LinkEditChunk *chunk);
+  void        buildLinkEdit(const lld::File &file);
+  void        assignLinkEditFileOffsets();
+  void        dump();
+
+
+  typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
+
+  const WriterOptionsMachO   &_options;
+  StubsPass                   _stubsPass;
+  GOTPass                     _gotPass;
+  CRuntimeFile                _cRuntimeFile;
+  LoadCommandsChunk          *_loadCommandsChunk;
+  LoadCommandPaddingChunk    *_paddingChunk;
+  AtomToAddress               _atomToAddress;
+  std::vector<Chunk*>         _chunks;
+  std::vector<SectionChunk*>  _sectionChunks;
+  std::vector<LinkEditChunk*> _linkEditChunks;
+  BindingInfoChunk           *_bindingInfo;
+  LazyBindingInfoChunk       *_lazyBindingInfo;
+  SymbolTableChunk           *_symbolTableChunk;
+  SymbolStringsChunk         *_stringsChunk;
+  const DefinedAtom          *_mainAtom;
+  uint64_t                    _linkEditStartOffset;
+  uint64_t                    _linkEditStartAddress;
+};
+
+
+
+//===----------------------------------------------------------------------===//
+//  Chunk
+//===----------------------------------------------------------------------===//
+
+Chunk::Chunk()
+ : _size(0), _address(0), _fileOffset(0), _align2(0) {
+}
+
+bool Chunk::occupiesNoDiskSpace() {
+  return false;
+}
+
+uint64_t Chunk::size() const {
+  return _size;
+}
+
+uint64_t Chunk::align2() const {
+  return _align2;
+}
+
+uint64_t Chunk::address() const {
+  return _address;
+}
+
+uint64_t Chunk::fileOffset() const {
+  return _fileOffset;
+}
+
+uint64_t Chunk::alignTo(uint64_t value, uint8_t align2) {
+  uint64_t align = 1 << align2;
+  return ( (value + (align-1)) & (-align) );
+}
+
+void Chunk::assignFileOffset(uint64_t &curOffset, uint64_t &curAddress) {
+  if ( this->occupiesNoDiskSpace() ) {
+    // FileOffset does not change, but address space does change.
+    uint64_t alignedAddress = alignTo(curAddress, _align2);
+   _address = alignedAddress;
+   curAddress = alignedAddress + _size;
+  }
+  else {
+    // FileOffset and address both move by _size amount after alignment.
+    uint64_t alignPadding = alignTo(curAddress, _align2) - curAddress;
+    _fileOffset = curOffset + alignPadding;
+    _address = curAddress + alignPadding;
+    curOffset = _fileOffset + _size;
+    curAddress = _address + _size;
+  }
+
+  DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()  
+                      << "   fileOffset="
+                      << llvm::format("0x%08X", _fileOffset)
+                      << " address="
+                      << llvm::format("0x%016X", _address)
+                      << " info=" << this->info() << "\n");
+}
+
+
+
+//===----------------------------------------------------------------------===//
+//  SectionChunk
+//===----------------------------------------------------------------------===//
+
+SectionChunk::SectionChunk(StringRef seg, StringRef sect,
+                           uint32_t flags, const WriterOptionsMachO &options,
+                                                MachOWriter &writer)
+ : _segmentName(seg), _sectionName(sect), _options(options),
+   _writer(writer), _flags(flags), _permissions(0) {
+
+}
+
+SectionChunk* SectionChunk::make(DefinedAtom::ContentType type,
+                                 const WriterOptionsMachO &options,
+                                 MachOWriter &writer) {
+  switch ( type ) {
+    case DefinedAtom::typeCode:
+      return new SectionChunk("__TEXT", "__text",
+                              S_REGULAR | S_ATTR_PURE_INSTRUCTIONS,
+                              options, writer);
+      break;
+    case DefinedAtom::typeCString:
+       return new SectionChunk("__TEXT", "__cstring",
+                               S_CSTRING_LITERALS,
+                              options, writer);
+       break;
+    case DefinedAtom::typeStub:
+      return new SectionChunk("__TEXT", "__stubs",
+                              S_SYMBOL_STUBS | S_ATTR_PURE_INSTRUCTIONS,
+                              options, writer);
+      break;
+    case DefinedAtom::typeStubHelper:
+      return new SectionChunk("__TEXT", "__stub_helper",
+                              S_REGULAR | S_ATTR_PURE_INSTRUCTIONS,
+                              options, writer);
+      break;
+    case DefinedAtom::typeLazyPointer:
+      return new SectionChunk("__DATA", "__la_symbol_ptr",
+                              S_LAZY_SYMBOL_POINTERS,
+                              options, writer);
+      break;
+    case DefinedAtom::typeGOT:
+      return new SectionChunk("__DATA", "__got",
+                              S_NON_LAZY_SYMBOL_POINTERS,
+                              options, writer);
+      break;
+    default:
+      assert(0 && "TO DO: add support for more sections");
+      break;
+  }
+  return nullptr;
+}
+
+bool SectionChunk::occupiesNoDiskSpace() {
+  return ( (_flags & SECTION_TYPE) == S_ZEROFILL );
+}
+
+StringRef SectionChunk::segmentName() const {
+  return _segmentName;
+}
+
+StringRef SectionChunk::sectionName() {
+  return _sectionName;
+}
+
+uint32_t SectionChunk::flags() const {
+  return _flags;
+}
+
+uint32_t SectionChunk::permissions() {
+  return _permissions;
+}
+
+const char* SectionChunk::info() {
+  return _sectionName.data();
+}
+
+const std::vector<SectionChunk::AtomInfo>& SectionChunk::atoms() const {
+  return _atoms;
+}
+
+void SectionChunk::appendAtom(const DefinedAtom *atom) {
+  // Figure out offset for atom in this section given alignment constraints.
+  uint64_t offset = _size;
+  DefinedAtom::Alignment atomAlign = atom->alignment();
+  uint64_t align2 = 1 << atomAlign.powerOf2;
+  uint64_t requiredModulus = atomAlign.modulus;
+  uint64_t currentModulus = (offset % align2);
+  if ( currentModulus != requiredModulus ) {
+    if ( requiredModulus > currentModulus )
+      offset += requiredModulus-currentModulus;
+    else
+      offset += align2+requiredModulus-currentModulus;
+  }
+  // Record max alignment of any atom in this section.
+  if ( align2 > _align2 )
+    _align2 = align2;
+  // Assign atom to this section with this offset.
+  SectionChunk::AtomInfo ai = {atom, offset};
+  _atoms.push_back(ai);
+  // Update section size to include this atom.
+  _size = offset + atom->size();
+  // Update permissions
+  DefinedAtom::ContentPermissions perms = atom->permissions();
+  if ( (perms & DefinedAtom::permR__) == DefinedAtom::permR__ )
+    _permissions |= VM_PROT_READ;
+  if ( (perms & DefinedAtom::permRW_) == DefinedAtom::permRW_ )
+    _permissions |= VM_PROT_WRITE;
+  if ( (perms & DefinedAtom::permR_X) == DefinedAtom::permR_X )
+    _permissions |= VM_PROT_EXECUTE;
+}
+
+
+void SectionChunk::write(uint8_t *chunkBuffer) {
+  // Each section's content is just its atoms' content.
+  for (const AtomInfo &atomInfo : _atoms ) {
+    // Copy raw content of atom to file buffer.
+    ArrayRef<uint8_t> content = atomInfo.atom->rawContent();
+    uint64_t contentSize = content.size();
+    if ( contentSize == 0 )
+      continue;
+    uint8_t* atomContent = chunkBuffer + atomInfo.offsetInSection;
+    ::memcpy(atomContent, content.data(), contentSize);
+    // Apply fixups to file buffer
+    for (const Reference *ref : *atomInfo.atom) {
+      uint32_t offset = ref->offsetInAtom();
+      uint64_t targetAddress = 0;
+      if ( ref->target() != nullptr )
+        targetAddress = _writer.addressOfAtom(ref->target());
+      uint64_t fixupAddress = _writer.addressOfAtom(atomInfo.atom) + offset;
+      this->applyFixup(ref->kind(), ref->addend(), &atomContent[offset],
+                                              fixupAddress, targetAddress);
+    }
+  }
+}
+
+
+
+void SectionChunk::applyFixup(Reference::Kind kind, uint64_t addend,  
+                                  uint8_t* location, uint64_t fixupAddress, 
+                                                     uint64_t targetAddress) {
+  //fprintf(stderr, "applyFixup(kind=%s, addend=0x%0llX, "
+  //                "fixupAddress=0x%0llX, targetAddress=0x%0llX\n", 
+  //                kindToString(kind).data(), addend, 
+  //                fixupAddress, targetAddress);
+  if ( ReferenceKind::isRipRel32(kind) ) {
+    // compute rip relative value and update.
+    int32_t* loc32 = reinterpret_cast<int32_t*>(location);
+    *loc32 = (targetAddress - (fixupAddress+4)) + addend;
+  }
+  else if ( kind == ReferenceKind::x86_64_pointer64 ) {
+    uint64_t* loc64 = reinterpret_cast<uint64_t*>(location);
+    *loc64 = targetAddress + addend;
+  }
+}
+
+
+
+//===----------------------------------------------------------------------===//
+//  MachHeaderChunk
+//===----------------------------------------------------------------------===//
+
+MachHeaderChunk::MachHeaderChunk(const WriterOptionsMachO &options,
+                                                            const File &file) {
+  // Set up mach_header based on options
+  _mh.magic      = MAGIC_64;
+  _mh.cputype    = options.cpuType();
+  _mh.cpusubtype = options.cpuSubtype();
+  _mh.filetype   = this->filetype(options.outputKind());
+  _mh.ncmds      = 0;
+  _mh.sizeofcmds = 0;
+  _mh.flags      = 0;
+  _mh.reserved   = 0;
+  
+  _size = _mh.size();
+}
+
+
+StringRef MachHeaderChunk::segmentName() const {
+  return StringRef("__TEXT");
+}
+
+void MachHeaderChunk::write(uint8_t *chunkBuffer) {
+  _mh.copyTo(chunkBuffer);
+}
+
+const char* MachHeaderChunk::info() {
+  return "mach_header";
+}
+
+void MachHeaderChunk::recordLoadCommand(load_command* lc) {
+  _mh.recordLoadCommand(lc);
+}
+
+uint64_t MachHeaderChunk::loadCommandsSize() {
+  return _mh.sizeofcmds;
+}
+
+uint32_t MachHeaderChunk::filetype(WriterOptionsMachO::OutputKind kind) {
+  switch ( kind ) {
+    case WriterOptionsMachO::outputDynamicExecutable:
+      return MH_EXECUTE;
+    case WriterOptionsMachO::outputDylib:
+      return MH_DYLIB;
+    case WriterOptionsMachO::outputBundle:
+      return MH_BUNDLE;
+    case WriterOptionsMachO::outputObjectFile:
+      return MH_OBJECT;
+  }
+  assert(0 && "file outputkind not supported");
+}
+
+
+
+//===----------------------------------------------------------------------===//
+//  LoadCommandsChunk
+//===----------------------------------------------------------------------===//
+
+LoadCommandsChunk::LoadCommandsChunk(MachHeaderChunk &mh,
+                                     const WriterOptionsMachO &options,
+                                     MachOWriter& writer)
+ : _mh(mh), _options(options), _writer(writer),
+   _linkEditSegment(nullptr), _symbolTableLoadCommand(nullptr),
+   _entryPointLoadCommand(nullptr), _dyldInfoLoadCommand(nullptr) {
+}
+
+
+StringRef LoadCommandsChunk::segmentName() const {
+  return StringRef("__TEXT");
+}
+
+void LoadCommandsChunk::write(uint8_t *chunkBuffer) {
+  uint8_t* p = chunkBuffer;
+  for ( load_command* lc : _loadCmds ) {
+    assert( ((uintptr_t)p & 0x3) == 0);
+    lc->copyTo(p);
+    p += lc->cmdsize;    
+  }
+}
+
+const char* LoadCommandsChunk::info() {
+  return "load commands";
+}
+
+void LoadCommandsChunk::setMachOSection(SectionChunk *chunk,
+                                    segment_command_64 *seg, uint32_t index) {
+  for (ChunkSegInfo &entry : _sectionInfo) {
+    if ( entry.chunk == chunk ) {
+      entry.section = &(seg->sections[index]);
+      entry.segment = seg;
+      return;
+    }
+  }
+  assert(0 && "setMachOSection() chunk not found");
+}
+
+uint32_t LoadCommandsChunk::permissionsFromSections(
+                        const SmallVector<SectionChunk*,16> &sections) {
+  uint32_t result = 0;
+  for (SectionChunk *chunk : sections) {
+    result |= chunk->permissions();
+  }
+  return result;
+}
+
+void LoadCommandsChunk::computeSize(const lld::File &file) {
+  // Main executables have a __PAGEZERO segment.
+  uint64_t pageZeroSize = _options.pageZeroSize();
+  if ( pageZeroSize != 0 ) {
+    segment_command_64* pzSegCmd = segment_command_64::make(0);
+    strcpy(pzSegCmd->segname, "__PAGEZERO");
+    pzSegCmd->vmaddr   = 0;
+    pzSegCmd->vmsize   = pageZeroSize;
+    pzSegCmd->fileoff  = 0;
+    pzSegCmd->filesize = 0;
+    pzSegCmd->maxprot  = 0;
+    pzSegCmd->initprot = 0;
+    pzSegCmd->nsects   = 0;
+    pzSegCmd->flags    = 0;
+    this->addLoadCommand(pzSegCmd);
+  }
+  // Add other segment load commands
+  StringRef lastSegName = StringRef("__TEXT");
+  SmallVector<SectionChunk*,16> sections;
+  for (ChunkSegInfo &entry : _sectionInfo) {
+    StringRef entryName = entry.chunk->segmentName();
+    if ( !lastSegName.equals(entryName) ) {
+      // Start of new segment, so create load command for all previous sections.
+      segment_command_64* segCmd = segment_command_64::make(sections.size());
+      strncpy(segCmd->segname, lastSegName.data(), 16);
+      segCmd->initprot = this->permissionsFromSections(sections);
+      segCmd->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
+      this->addLoadCommand(segCmd);
+      unsigned int index = 0;
+      for (SectionChunk *chunk : sections) {
+        this->setMachOSection(chunk, segCmd, index);
+        ++index;
+      }
+      // Reset to begin new segment.
+      sections.clear();
+      lastSegName = entryName;
+    }
+    sections.push_back(entry.chunk);
+  }
+  // Add last segment load command.
+  segment_command_64* segCmd = segment_command_64::make(sections.size());
+  strncpy(segCmd->segname, lastSegName.data(), 16);
+  segCmd->initprot = this->permissionsFromSections(sections);;
+  segCmd->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
+  this->addLoadCommand(segCmd);
+  unsigned int index = 0;
+  for (SectionChunk *chunk : sections) {
+    this->setMachOSection(chunk, segCmd, index);
+    ++index;
+  }
+
+  // Add LINKEDIT segment load command
+  _linkEditSegment = segment_command_64::make(0);
+  strcpy(_linkEditSegment->segname, "__LINKEDIT");
+  _linkEditSegment->initprot = VM_PROT_READ;
+  _linkEditSegment->maxprot = VM_PROT_READ;
+  this->addLoadCommand(_linkEditSegment);
+
+  // Add dyld load command.
+  this->addLoadCommand(dylinker_command::make("/usr/lib/dyld"));
+
+  // Add dylib load commands.
+  llvm::StringMap<uint32_t> dylibNamesToOrdinal;
+  for (const SharedLibraryAtom* shlibAtom : file.sharedLibrary() ) {
+    StringRef installName = shlibAtom->loadName();
+    if ( dylibNamesToOrdinal.count(installName) == 0 ) {
+      uint32_t ord = dylibNamesToOrdinal.size();
+      dylibNamesToOrdinal[installName] = ord;
+    }
+  }
+  for (llvm::StringMap<uint32_t>::iterator it=dylibNamesToOrdinal.begin(),
+                            end=dylibNamesToOrdinal.end(); it != end; ++it) {
+    this->addLoadCommand(dylib_command::make(it->first().data()));
+  }
+
+  // Add symbol table load command
+  _symbolTableLoadCommand = symtab_command::make();
+  this->addLoadCommand(_symbolTableLoadCommand);
+
+  // Add dyld info load command
+  _dyldInfoLoadCommand = dyld_info_command::make();
+  this->addLoadCommand(_dyldInfoLoadCommand);
+
+  // Add entry point load command to main executables
+  if (_options.outputKind() == WriterOptionsMachO::outputDynamicExecutable) {
+    _entryPointLoadCommand = entry_point_command::make();
+    this->addLoadCommand(_entryPointLoadCommand);
+  }
+  
+  // Compute total size.
+  _size = _mh.loadCommandsSize();
+}
+
+
+void LoadCommandsChunk::updateLoadCommandContent(const lld::File &file) {
+  // Update segment/section information in segment load commands
+  segment_command_64 *lastSegment = nullptr;
+  for (ChunkSegInfo &entry : _sectionInfo) {
+    // Set section info.
+    ::strncpy(entry.section->sectname, entry.chunk->sectionName().data(), 16);
+    ::strncpy(entry.section->segname, entry.chunk->segmentName().data(), 16);
+    entry.section->addr   = entry.chunk->address();
+    entry.section->size   = entry.chunk->size();
+    entry.section->offset = entry.chunk->fileOffset();
+    entry.section->align  = entry.chunk->align2();
+    entry.section->reloff = 0;
+    entry.section->nreloc = 0;
+    entry.section->flags  = entry.chunk->flags();
+    // Adjust segment info if needed.
+    if ( entry.segment != lastSegment ) {
+      // This is first section in segment.
+      if ( strcmp(entry.segment->segname, "__TEXT") == 0 ) {
+        // __TEXT segment is special need mach_header section.
+        entry.segment->vmaddr = _writer._chunks.front()->address();
+        entry.segment->fileoff = _writer._chunks.front()->fileOffset();
+      }
+      else {
+        entry.segment->vmaddr  = entry.chunk->address();
+        entry.segment->fileoff = entry.chunk->fileOffset();
+      }
+
+      lastSegment = entry.segment;
+    }
+    uint64_t sectionEndAddr = entry.section->addr + entry.section->size;
+    if ( entry.segment->vmaddr + entry.segment->vmsize < sectionEndAddr) {
+      uint64_t sizeToEndOfSection = sectionEndAddr - entry.segment->vmaddr;
+      entry.segment->vmsize = alignTo(sizeToEndOfSection, 12);
+      // zero-fill sections do not increase the segment's filesize
+      if ( ! entry.chunk->occupiesNoDiskSpace() ) {
+        entry.segment->filesize = alignTo(sizeToEndOfSection, 12);
+      }
+    }
+  }
+  uint64_t linkEditSize = _writer._stringsChunk->fileOffset()
+                        + _writer._stringsChunk->size()
+                        - _writer._linkEditStartOffset;
+  _linkEditSegment->vmaddr   = _writer._linkEditStartAddress;
+  _linkEditSegment->vmsize   = alignTo(linkEditSize,12);
+  _linkEditSegment->fileoff  = _writer._linkEditStartOffset;
+  _linkEditSegment->filesize = linkEditSize;
+
+  // Update dyld_info load command.
+  _dyldInfoLoadCommand->bind_off       = _writer._bindingInfo->fileOffset();
+  _dyldInfoLoadCommand->bind_size      = _writer._bindingInfo->size();
+  _dyldInfoLoadCommand->lazy_bind_off  = _writer._lazyBindingInfo->fileOffset();
+  _dyldInfoLoadCommand->lazy_bind_size = _writer._lazyBindingInfo->size();
+
+
+  // Update symbol table load command.
+  _symbolTableLoadCommand->symoff  = _writer._symbolTableChunk->fileOffset();
+  _symbolTableLoadCommand->nsyms   = _writer._symbolTableChunk->count();
+  _symbolTableLoadCommand->stroff  = _writer._stringsChunk->fileOffset();
+  _symbolTableLoadCommand->strsize = _writer._stringsChunk->size();
+
+  // Update entry point
+  if ( _entryPointLoadCommand != nullptr ) {
+    const Atom *mainAtom = _writer._mainAtom;
+    assert(mainAtom != nullptr);
+    uint32_t entryOffset = _writer.addressOfAtom(mainAtom) - _mh.address();
+    _entryPointLoadCommand->entryoff = entryOffset;
+  }
+}
+
+
+void LoadCommandsChunk::addSection(SectionChunk* chunk) {
+  LoadCommandsChunk::ChunkSegInfo csi = {chunk, nullptr, nullptr};
+  _sectionInfo.push_back(csi);
+}
+
+void LoadCommandsChunk::addLoadCommand(load_command* lc) {
+  _mh.recordLoadCommand(lc);
+  _loadCmds.push_back(lc);
+}
+
+
+
+//===----------------------------------------------------------------------===//
+//  LoadCommandPaddingChunk
+//===----------------------------------------------------------------------===//
+
+LoadCommandPaddingChunk::LoadCommandPaddingChunk(LoadCommandsChunk& lcc)
+  : _loadCommandsChunk(lcc) {
+}
+
+StringRef LoadCommandPaddingChunk::segmentName() const {
+  return StringRef("__TEXT");
+}
+
+void LoadCommandPaddingChunk::write(uint8_t *chunkBuffer) {
+  // Zero fill padding.
+}
+
+const char* LoadCommandPaddingChunk::info() {
+  return "padding";
+}
+
+// Segments are page sized.  Normally, any extra space not used by atoms
+// is put at the end of the last page.  But the __TEXT segment is special.
+// Any extra space is put between the load commands and the first section.
+// The padding is put there to allow the load commands to be
+// post-processed which might potentially grow them.
+void LoadCommandPaddingChunk::computeSize() {
+ // Layout __TEXT sections backwards from end of page to get padding up front.
+  uint64_t addr = 0;
+  std::vector<LoadCommandsChunk::ChunkSegInfo>& sects
+                                        = _loadCommandsChunk._sectionInfo;
+  for (auto it=sects.rbegin(), end=sects.rend(); it != end; ++it) {
+    LoadCommandsChunk::ChunkSegInfo &entry = *it;
+    if ( !entry.chunk->segmentName().equals("__TEXT") )
+      continue;
+    addr -= entry.chunk->size();
+    addr = addr & (0 - (1 << entry.chunk->align2()));
+  }
+  // Subtract out size of mach_header and all load commands.
+  addr -= _loadCommandsChunk._mh.size();
+  addr -= _loadCommandsChunk.size();
+  // Modulo page size to get padding needed between load commands
+  // and first section.
+  _size = (addr % 4096);
+}
+
+//===----------------------------------------------------------------------===//
+//  LinkEditChunk
+//===----------------------------------------------------------------------===//
+
+LinkEditChunk::LinkEditChunk() {
+  _align2 = 3;
+}
+
+StringRef LinkEditChunk::segmentName() const {
+  return StringRef("__LINKEDIT");
+}
+
+
+//===----------------------------------------------------------------------===//
+//  DyldInfoChunk
+//===----------------------------------------------------------------------===//
+DyldInfoChunk::DyldInfoChunk(MachOWriter &writer)
+ : _writer(writer) {
+}
+
+void DyldInfoChunk::write(uint8_t *chunkBuffer) {
+  ::memcpy(chunkBuffer, &_bytes[0], _bytes.size());
+}
+
+void DyldInfoChunk::append_byte(uint8_t b) {
+  _bytes.push_back(b);
+}
+
+void DyldInfoChunk::append_string(StringRef str) {
+  _bytes.insert(_bytes.end(), str.begin(), str.end());
+  _bytes.push_back('\0');
+}
+
+void DyldInfoChunk::append_uleb128(uint64_t value) {
+  uint8_t byte;
+  do {
+    byte = value & 0x7F;
+    value &= ~0x7F;
+    if ( value != 0 )
+      byte |= 0x80;
+    _bytes.push_back(byte);
+    value = value >> 7;
+  } while( byte >= 0x80 );
+}
+
+
+
+//===----------------------------------------------------------------------===//
+//  BindingInfoChunk
+//===----------------------------------------------------------------------===//
+
+BindingInfoChunk::BindingInfoChunk(MachOWriter &writer)
+ : DyldInfoChunk(writer) {
+}
+
+const char* BindingInfoChunk::info() {
+  return "binding info";
+}
+
+void BindingInfoChunk::computeSize(const lld::File &file,
+                                    const std::vector<SectionChunk*> &chunks) {
+  for (const SectionChunk *chunk : chunks ) {
+    // skip lazy pointer section
+    if ( chunk->flags() == S_LAZY_SYMBOL_POINTERS )
+      continue;
+    // skip code sections
+    if ( chunk->flags() == (S_REGULAR | S_ATTR_PURE_INSTRUCTIONS) )
+      continue;
+    uint64_t segStartAddr = 0;
+    uint64_t segEndAddr = 0;
+    uint32_t segIndex = 0;
+    _writer.findSegment(chunk->segmentName(),
+                                    &segIndex, &segStartAddr, &segEndAddr);
+    for (const SectionChunk::AtomInfo &info : chunk->atoms() ) {
+      const DefinedAtom* atom = info.atom;
+      StringRef targetName;
+      int ordinal;
+
+      // look for fixups pointing to shlib atoms
+      for (const Reference *ref : *atom ) {
+        const Atom *target = ref->target();
+        if ( target != nullptr ) {
+          const SharedLibraryAtom *shlTarget
+                                        = dyn_cast<SharedLibraryAtom>(target);
+          if ( shlTarget != nullptr ) {
+            assert(ref->kind() == ReferenceKind::x86_64_pointer64);
+            targetName = shlTarget->name();
+            ordinal = 1;
+          }
+        }
+      }
+
+      if ( targetName.empty() )
+        continue;
+
+      // write location of fixup
+      this->append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segIndex);
+      uint64_t address = _writer.addressOfAtom(atom);
+      this->append_uleb128(address - segStartAddr);
+
+      // write ordinal
+      if ( ordinal <= 0 ) {
+        // special lookups are encoded as negative numbers in BindingInfo
+        this->append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
+                                          | (ordinal & BIND_IMMEDIATE_MASK) );
+      }
+      else if ( ordinal <= 15 ) {
+        // small ordinals are encoded in opcode
+        this->append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | ordinal);
+      }
+      else {
+        this->append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
+        this->append_uleb128(ordinal);
+      }
+
+      // write binding type
+      this->append_byte(BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER);
+
+      // write symbol name and flags
+      int flags = 0;
+      this->append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | flags);
+      this->append_string(targetName);
+
+      // write do bind
+      this->append_byte(BIND_OPCODE_DO_BIND);
+      this->append_byte(BIND_OPCODE_DONE);
+    }
+  }
+  _size = _bytes.size();
+}
+
+
+//===----------------------------------------------------------------------===//
+//  LazyBindingInfoChunk
+//===----------------------------------------------------------------------===//
+
+LazyBindingInfoChunk::LazyBindingInfoChunk(MachOWriter &writer)
+ : DyldInfoChunk(writer) {
+}
+
+const char* LazyBindingInfoChunk::info() {
+  return "lazy binding info";
+}
+
+void LazyBindingInfoChunk::updateHelper(const DefinedAtom *lazyPointerAtom,
+                                        uint32_t offset) {
+  for (const Reference *ref : *lazyPointerAtom ) {
+    if ( ref->kind() != ReferenceKind::x86_64_pointer64 )
+      continue;
+    const DefinedAtom *helperAtom = dyn_cast<DefinedAtom>(ref->target());
+    assert(helperAtom != nullptr);
+    for (const Reference *href : *helperAtom ) {
+      if ( href->kind() == ReferenceKind::x86_64_lazyImm ) {
+        (const_cast<Reference*>(href))->setAddend(offset);
+        return;
+      }
+    }
+  }
+  assert(0 && "could not update helper lazy immediate value");
+}
+
+void LazyBindingInfoChunk::computeSize(const lld::File &file,
+                                    const std::vector<SectionChunk*> &chunks) {
+  for (const SectionChunk *chunk : chunks ) {
+    if ( chunk->flags() != S_LAZY_SYMBOL_POINTERS )
+      continue;
+    uint64_t segStartAddr = 0;
+    uint64_t segEndAddr = 0;
+    uint32_t segIndex = 0;
+    _writer.findSegment(chunk->segmentName(),
+                                    &segIndex, &segStartAddr, &segEndAddr);
+    for (const SectionChunk::AtomInfo &info : chunk->atoms() ) {
+      const DefinedAtom *lazyPointerAtom = info.atom;
+      assert(lazyPointerAtom->contentType() == DefinedAtom::typeLazyPointer);
+      // Update help to have offset of the lazy binding info.
+      this->updateHelper(lazyPointerAtom, _bytes.size());
+
+      // Write location of fixup.
+      this->append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segIndex);
+      uint64_t address = _writer.addressOfAtom(lazyPointerAtom);
+      this->append_uleb128(address - segStartAddr);
+
+      // write ordinal
+      int ordinal = 1;
+      if ( ordinal <= 0 ) {
+        // special lookups are encoded as negative numbers in BindingInfo
+        this->append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
+                                          | (ordinal & BIND_IMMEDIATE_MASK) );
+      }
+      else if ( ordinal <= 15 ) {
+        // small ordinals are encoded in opcode
+        this->append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | ordinal);
+      }
+      else {
+        this->append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
+        this->append_uleb128(ordinal);
+      }
+
+      // write symbol name and flags
+      int flags = 0;
+      StringRef name;
+      for (const Reference *ref : *lazyPointerAtom ) {
+        if ( ref->kind() == ReferenceKind::x86_64_lazyTarget ) {
+          const Atom *shlib = ref->target();
+          assert(shlib != nullptr);
+          name = shlib->name();
+        }
+      }
+      assert(!name.empty());
+      this->append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | flags);
+      this->append_string(name);
+
+      // write do bind
+      this->append_byte(BIND_OPCODE_DO_BIND);
+      this->append_byte(BIND_OPCODE_DONE);
+    }
+  }
+  _size = _bytes.size();
+}
+
+
+//===----------------------------------------------------------------------===//
+//  SymbolTableChunk
+//===----------------------------------------------------------------------===//
+
+SymbolTableChunk::SymbolTableChunk(SymbolStringsChunk& str)
+  : _stringsChunk(str) {
+}
+
+void SymbolTableChunk::write(uint8_t *chunkBuffer) {
+  uint8_t *p = chunkBuffer;
+  for ( nlist_64 &sym : _globalDefinedsymbols ) {
+    sym.copyTo(p);
+    p += sizeof(nlist_64);
+  }
+  for ( nlist_64 &sym : _localDefinedsymbols ) {
+    sym.copyTo(p);
+    p += sizeof(nlist_64);
+  }
+  for ( nlist_64 &sym : _undefinedsymbols ) {
+    sym.copyTo(p);
+    p += sizeof(nlist_64);
+  }
+}
+
+const char* SymbolTableChunk::info() {
+  return "symbol tables ";
+}
+
+uint32_t SymbolTableChunk::count() {
+  return _globalDefinedsymbols.size()
+       + _localDefinedsymbols.size()
+       + _undefinedsymbols.size();
+}
+
+uint8_t SymbolTableChunk::nType(const DefinedAtom *atom) {
+  uint8_t result = N_SECT;
+  switch ( atom->scope() ) {
+    case DefinedAtom::scopeTranslationUnit:
+      break;
+    case DefinedAtom::scopeLinkageUnit:
+      result |= N_EXT | N_PEXT;
+      break;
+    case DefinedAtom::scopeGlobal:
+      result |= N_EXT;
+      break;
+  }
+  return result;
+}
+
+void SymbolTableChunk::computeSize(const lld::File &file,
+                                   const std::vector<SectionChunk*> &chunks) {
+  // Add symbols for definitions
+  unsigned int sectionIndex = 1;
+  for (const SectionChunk *chunk : chunks ) {
+    for (const SectionChunk::AtomInfo &info : chunk->atoms() ) {
+      if ( info.atom->name().empty() )
+        continue;
+      uint64_t atomAddress = chunk->address() + info.offsetInSection;
+      nlist_64 sym;
+      sym.n_strx = _stringsChunk.stringIndex(info.atom->name());
+      sym.n_type = this->nType(info.atom);
+      sym.n_sect = sectionIndex;
+      sym.n_value = atomAddress;
+      if ( info.atom->scope() == DefinedAtom::scopeGlobal )
+        _globalDefinedsymbols.push_back(sym);
+      else
+        _localDefinedsymbols.push_back(sym);
+    }
+    ++sectionIndex;
+  }
+
+  // Add symbols for undefined/sharedLibrary symbols
+  for (const SharedLibraryAtom* atom : file.sharedLibrary() ) {
+    nlist_64 sym;
+    sym.n_strx = _stringsChunk.stringIndex(atom->name());
+    sym.n_type = N_UNDF;
+    sym.n_sect = 0;
+    sym.n_value = 0;
+    _undefinedsymbols.push_back(sym);
+  }
+
+  _size = sizeof(nlist_64) * this->count();
+}
+
+
+//===----------------------------------------------------------------------===//
+//  SymbolStringsChunk
+//===----------------------------------------------------------------------===//
+
+SymbolStringsChunk::SymbolStringsChunk() {
+  // mach-o reserves the first byte in the string pool so that
+  // zero is never a valid string index.
+  _strings.push_back('\0');
+}
+
+
+void SymbolStringsChunk::write(uint8_t *chunkBuffer) {
+  ::memcpy(chunkBuffer, &_strings[0], _strings.size());
+}
+
+const char* SymbolStringsChunk::info() {
+  return "symbol strings ";
+}
+
+void SymbolStringsChunk::computeSize(const lld::File &file,
+                                     const std::vector<SectionChunk*>&) {
+  _size = _strings.size();
+}
+
+
+uint32_t SymbolStringsChunk::stringIndex(StringRef str) {
+  uint32_t result = _strings.size();
+  _strings.insert(_strings.end(), str.begin(), str.end());
+  _strings.push_back('\0');
+  return result;
+}
+
+
+//===----------------------------------------------------------------------===//
+//  MachOWriter
+//===----------------------------------------------------------------------===//
+
+MachOWriter::MachOWriter(const WriterOptionsMachO &options)
+  : _options(options), _stubsPass(options), _cRuntimeFile(options), 
+    _bindingInfo(nullptr), _lazyBindingInfo(nullptr),
+    _symbolTableChunk(nullptr), _stringsChunk(nullptr), _mainAtom(nullptr),
+    _linkEditStartOffset(0), _linkEditStartAddress(0) {
+}
+
+void MachOWriter::build(const lld::File &file) {
+  // Create objects for each chunk.
+  this->createChunks(file);
+
+  // Now that SectionChunks have sizes, load commands can be laid out
+  _loadCommandsChunk->computeSize(file);
+
+  // Now that load commands are sized, padding can be computed
+  _paddingChunk->computeSize();
+
+  // Now that all chunks (except linkedit) have sizes, assign file offsets
+  this->assignFileOffsets();
+
+  // Now chunks have file offsets each atom can be assigned an address
+  this->buildAtomToAddressMap();
+
+  // Now that atoms have address, symbol table can be build
+  this->buildLinkEdit(file);
+
+  // Assign file offsets to linkedit chunks
+  this->assignLinkEditFileOffsets();
+
+  // Finally, update load commands to reflect linkEdit layout
+  _loadCommandsChunk->updateLoadCommandContent(file);
+}
+
+
+void MachOWriter::createChunks(const lld::File &file) {
+  // Assign atoms to chunks, creating new chunks as needed
+  std::map<DefinedAtom::ContentType, SectionChunk*> map;
+  for (const DefinedAtom* atom : file.defined() ) {
+    assert( atom->sectionChoice() == DefinedAtom::sectionBasedOnContent );
+    DefinedAtom::ContentType type = atom->contentType();
+    auto pos = map.find(type);
+    if ( pos == map.end() ) {
+      SectionChunk *chunk = SectionChunk::make(type, _options, *this);
+      map[type] = chunk;
+      chunk->appendAtom(atom);
+    }
+    else {
+      pos->second->appendAtom(atom);
+    }
+  }
+
+  // Sort Chunks so ones in same segment are contiguous.
+
+
+  // Make chunks in __TEXT for mach_header and load commands at start.
+  MachHeaderChunk *mhc = new MachHeaderChunk(_options, file);
+  _chunks.push_back(mhc);
+
+  _loadCommandsChunk = new LoadCommandsChunk(*mhc, _options, *this);
+  _chunks.push_back(_loadCommandsChunk);
+
+  _paddingChunk = new LoadCommandPaddingChunk(*_loadCommandsChunk);
+  _chunks.push_back(_paddingChunk);
+
+  for (auto it=map.begin(); it != map.end(); ++it) {
+     _chunks.push_back(it->second);
+     _sectionChunks.push_back(it->second);
+     _loadCommandsChunk->addSection(it->second);
+  }
+
+  // Make LINKEDIT chunks.
+  _bindingInfo = new BindingInfoChunk(*this);
+  _lazyBindingInfo = new LazyBindingInfoChunk(*this);
+  _stringsChunk = new SymbolStringsChunk();
+  _symbolTableChunk = new SymbolTableChunk(*_stringsChunk);
+  this->addLinkEditChunk(_bindingInfo);
+  this->addLinkEditChunk(_lazyBindingInfo);
+  this->addLinkEditChunk(_symbolTableChunk);
+  this->addLinkEditChunk(_stringsChunk);
+}
+
+
+void MachOWriter::addLinkEditChunk(LinkEditChunk *chunk) {
+  _linkEditChunks.push_back(chunk);
+  _chunks.push_back(chunk);
+}
+
+
+void MachOWriter::buildAtomToAddressMap() {
+  DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs() 
+                   << "assign atom addresses:\n");
+  const bool lookForMain = 
+      (_options.outputKind() == WriterOptionsMachO::outputDynamicExecutable);
+  for (SectionChunk *chunk : _sectionChunks ) {
+    for (const SectionChunk::AtomInfo &info : chunk->atoms() ) {
+      _atomToAddress[info.atom] = chunk->address() + info.offsetInSection;
+      if (       lookForMain
+              && (info.atom->contentType() == DefinedAtom::typeCode)
+              && (info.atom->size() != 0)
+              &&  info.atom->name().equals("_main") ) {
+        _mainAtom = info.atom;
+      }
+      DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()  
+              << "   address="
+              << llvm::format("0x%016X", _atomToAddress[info.atom])
+              << " atom=" << info.atom
+              << " name=" << info.atom->name() << "\n");
+    }
+  }
+}
+
+//void MachOWriter::dump() {
+//  for ( Chunk *chunk : _chunks ) {
+//    fprintf(stderr, "size=0x%08llX, fileOffset=0x%08llX, address=0x%08llX %s\n",
+//          chunk->size(), chunk->fileOffset(),chunk->address(), chunk->info());
+//  }
+//}
+
+void MachOWriter::assignFileOffsets() {
+  DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs() 
+                    << "assign file offsets:\n");
+  uint64_t offset = 0;
+  uint64_t address = _options.pageZeroSize();
+  for ( Chunk *chunk : _chunks ) {
+    if ( chunk->segmentName().equals("__LINKEDIT") ) {
+      _linkEditStartOffset  = Chunk::alignTo(offset, 12);
+      _linkEditStartAddress = Chunk::alignTo(address, 12);
+      break;
+    }
+    chunk->assignFileOffset(offset, address);
+  }
+}
+
+void MachOWriter::assignLinkEditFileOffsets() {
+  DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs() 
+                   << "assign LINKEDIT file offsets:\n");
+  uint64_t offset = _linkEditStartOffset;
+  uint64_t address = _linkEditStartAddress;
+  for ( Chunk *chunk : _linkEditChunks ) {
+    chunk->assignFileOffset(offset, address);
+  }
+}
+
+void MachOWriter::buildLinkEdit(const lld::File &file) {
+  for (LinkEditChunk *chunk : _linkEditChunks) {
+    chunk->computeSize(file, _sectionChunks);
+  }
+}
+
+
+uint64_t MachOWriter::addressOfAtom(const Atom *atom) {
+  return _atomToAddress[atom];
+}
+
+
+void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex,
+                                uint64_t *segStartAddr, uint64_t *segEndAddr) {
+  const uint64_t kInvalidAddress = (uint64_t)(-1);
+  StringRef lastSegName("__TEXT");
+  *segIndex = 0;
+  if ( _options.pageZeroSize() != 0 ) {
+      *segIndex = 1;
+  }
+  *segStartAddr = kInvalidAddress;
+  *segEndAddr = kInvalidAddress;
+  for (SectionChunk *chunk : _sectionChunks ) {
+    if ( ! lastSegName.equals(chunk->segmentName()) ) {
+      *segIndex += 1;
+      lastSegName = chunk->segmentName();
+    }
+    if ( chunk->segmentName().equals(segmentName) ) {
+      uint64_t  chunkEndAddr = chunk->address() + chunk->size();
+      if ( *segStartAddr == kInvalidAddress ) {
+        *segStartAddr = chunk->address();
+        *segEndAddr = chunkEndAddr;
+      }
+      else if ( *segEndAddr < chunkEndAddr ) {
+        *segEndAddr = chunkEndAddr;
+      }
+    }
+  }
+}
+
+
+//
+// Creates a mach-o final linked image from the given atom graph and writes
+// it to the supplied output stream.
+//
+error_code MachOWriter::writeFile(const lld::File &file, StringRef path) {
+  this->build(file);
+
+// FIXME: re-enable when FileOutputBuffer is in LLVMSupport.a 
+#if 0 
+  uint64_t totalSize = _chunks.back()->fileOffset() + _chunks.back()->size();
+
+  OwningPtr<llvm::FileOutputBuffer> buffer;
+  error_code ec = llvm::FileOutputBuffer::create(path, 
+                                          totalSize, buffer,
+                                          llvm::FileOutputBuffer::F_executable); 
+  if ( ec )
+    return ec;
+   
+  DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs() << "writeFile:\n");
+  for ( Chunk *chunk : _chunks ) {
+    DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()  
+                      << "   fileOffset="
+                      << llvm::format("0x%08X", chunk->fileOffset())
+                      << " chunk="
+                      << chunk->info()
+                      << "\n");
+    chunk->write(buffer->getBufferStart()+chunk->fileOffset());
+  }
+  
+  return buffer->commit();
+#else
+  return error_code::success();
+#endif
+}
+
+
+StubsPass *MachOWriter::stubPass() {
+  return &_stubsPass;
+}
+ 
+GOTPass *MachOWriter::gotPass() {
+  return &_gotPass;
+}
+
+void MachOWriter::addFiles(InputFiles &inputFiles) {
+  inputFiles.prependFile(_cRuntimeFile);
+}
+
+
+} // namespace mach_o
+
+Writer* createWriterMachO(const WriterOptionsMachO &options) {
+  return new lld::mach_o::MachOWriter(options);
+}
+
+WriterOptionsMachO::WriterOptionsMachO() 
+ : _outputkind(outputDynamicExecutable),
+   _archName("x86_64"),
+   _architecture(arch_x86_64),
+   _pageZeroSize(0x10000000),
+   _cpuType(mach_o::CPU_TYPE_X86_64),
+   _cpuSubtype(mach_o::CPU_SUBTYPE_X86_64_ALL),
+   _noTextRelocations(true) {
+}
+
+WriterOptionsMachO::~WriterOptionsMachO() {
+}
+
+
+} // namespace lld
+

Added: lld/trunk/lib/ReaderWriter/Native/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Native/CMakeLists.txt?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/Native/CMakeLists.txt (added)
+++ lld/trunk/lib/ReaderWriter/Native/CMakeLists.txt Thu May 31 17:34:00 2012
@@ -0,0 +1,4 @@
+add_lld_library(lldNative
+  ReaderNative.cpp
+  WriterNative.cpp
+  )

Added: lld/trunk/lib/ReaderWriter/Native/NativeFileFormat.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Native/NativeFileFormat.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/Native/NativeFileFormat.h (added)
+++ lld/trunk/lib/ReaderWriter/Native/NativeFileFormat.h Thu May 31 17:34:00 2012
@@ -0,0 +1,243 @@
+//===- lib/ReaderWriter/Native/NativeFileFormat.h -------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_
+#define LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_
+
+#include "llvm/Support/DataTypes.h"
+
+namespace lld {
+
+
+//
+// Overview:
+//
+// The number one design goal of this file format is enable the linker to
+// read object files into in-memory Atom objects extremely quickly.
+// The second design goal is to enable future modifications to the
+// Atom attribute model.
+//
+// The llvm native object file format is not like traditional object file
+// formats (e.g. ELF, COFF, mach-o).  There is no symbol table and no
+// sections.  Instead the file is essentially an array of archived Atoms.
+// It is *not* serialized Atoms which would require deserialization into
+// in memory objects.  Instead it is an array of read-only info about each
+// Atom.  The NativeReader bulk creates in-memory Atoms which just have
+// an ivar which points to the read-only info for that Atom. No additional
+// processing is done to construct the in-memory Atoms. All Atom attribute
+// getter methods are virtual calls which dig up the info they need from the
+// ivar data.
+//
+// To support the gradual evolution of Atom attributes, the Atom read-only
+// data is versioned. The NativeReader chooses which in-memory Atom class
+// to use based on the version. What this means is that if new attributes
+// are added (or changed) in the Atom model, a new native atom class and
+// read-only atom info struct needs to be defined.  Then, all the existing
+// native reader atom classes need to be modified to do their best effort
+// to map their old style read-only data to the new Atom model.  At some point
+// some classes to support old versions may be dropped.
+//
+//
+// Details:
+//
+// The native object file format consists of a header that specifies the
+// endianness of the file and the architecture along with a list of "chunks"
+// in the file.  A Chunk is simply a tagged range of the file.  There is
+// one chunk for the array of atom infos.  There is another chunk for the
+// string pool, and another for the content pool.
+//
+// It turns out there most atoms have very similar sets of attributes, only
+// the name and content attribute vary. To exploit this fact to reduce the file
+// size, the atom read-only info contains just the name and content info plus
+// a reference to which attribute set it uses.  The attribute sets are stored
+// in another chunk.
+//
+
+
+//
+// An entry in the NativeFileHeader that describes one chunk of the file.
+//
+struct NativeChunk {
+  uint32_t    signature;
+  uint32_t    fileOffset;
+  uint32_t    fileSize;
+  uint32_t    elementCount;
+};
+
+
+//
+// The header in a native object file
+//
+struct NativeFileHeader {
+  uint8_t     magic[16];
+  uint32_t    endian;
+  uint32_t    architecture;
+  uint32_t    fileSize;
+  uint32_t    chunkCount;
+  // NativeChunk chunks[]
+};
+
+//
+// Possible values for NativeChunk.signature field
+//
+enum NativeChunkSignatures {
+  NCS_DefinedAtomsV1 = 1,
+  NCS_AttributesArrayV1 = 2,
+  NCS_UndefinedAtomsV1 = 3,
+  NCS_SharedLibraryAtomsV1 = 4,
+  NCS_AbsoluteAtomsV1 = 5,
+  NCS_Strings = 6,
+  NCS_ReferencesArrayV1 = 7,
+  NCS_ReferencesArrayV2 = 8,
+  NCS_TargetsTable = 9,
+  NCS_AddendsTable = 10,
+  NCS_Content = 11,
+};
+
+//
+// The 16-bytes at the start of a native object file
+//
+#define NATIVE_FILE_HEADER_MAGIC "llvm nat obj v1 "
+
+//
+// Possible values for the NativeFileHeader.endian field
+//
+enum {
+  NFH_BigEndian     = 0x42696745,
+  NFH_LittleEndian  = 0x4574696c
+};
+
+
+//
+// Possible values for the NativeFileHeader.architecture field
+//
+enum {
+  NFA_x86     = 1,
+  NFA_x86_64  = 2,
+  NFA_armv6   = 3,
+  NFA_armv7   = 4,
+};
+
+
+//
+// The NCS_DefinedAtomsV1 chunk contains an array of these structs
+//
+struct NativeDefinedAtomIvarsV1 {
+  uint32_t  nameOffset;
+  uint32_t  attributesOffset;
+  uint32_t  referencesStartIndex;
+  uint32_t  referencesCount;
+  uint32_t  contentOffset;
+  uint32_t  contentSize;
+};
+
+
+//
+// The NCS_AttributesArrayV1 chunk contains an array of these structs
+//
+struct NativeAtomAttributesV1 {
+  uint32_t  sectionNameOffset;
+  uint16_t  align2;
+  uint16_t  alignModulus;
+  uint8_t   scope;
+  uint8_t   interposable;
+  uint8_t   merge;
+  uint8_t   contentType;
+  uint8_t   sectionChoice;
+  uint8_t   deadStrip;
+  uint8_t   permissions;
+  uint8_t   alias;
+};
+
+
+
+//
+// The NCS_UndefinedAtomsV1 chunk contains an array of these structs
+//
+struct NativeUndefinedAtomIvarsV1 {
+  uint32_t  nameOffset;
+  uint32_t  flags;
+};
+
+
+
+//
+// The NCS_SharedLibraryAtomsV1 chunk contains an array of these structs
+//
+struct NativeSharedLibraryAtomIvarsV1 {
+  uint32_t  nameOffset;
+  uint32_t  loadNameOffset;
+  uint32_t  flags;
+};
+
+
+
+//
+// The NCS_AbsoluteAtomsV1 chunk contains an array of these structs
+//
+struct NativeAbsoluteAtomIvarsV1 {
+  uint32_t  nameOffset;
+  uint32_t  reserved;
+  uint64_t  value;
+};
+
+
+
+//
+// The NCS_ReferencesArrayV1 chunk contains an array of these structs
+//
+struct NativeReferenceIvarsV1 {
+  enum {
+    noTarget = 0xFFFF
+  };
+  uint16_t  offsetInAtom;
+   int16_t  kind;
+  uint16_t  targetIndex;
+  uint16_t  addendIndex;
+};
+
+
+//
+// The NCS_ReferencesArrayV2 chunk contains an array of these structs
+//
+struct NativeReferenceIvarsV2 {
+  uint64_t  offsetInAtom;
+  int64_t   addend;
+  int32_t   kind;
+  uint32_t  targetIndex;
+};
+
+
+//
+// The NCS_TargetsTable chunk contains an array of uint32_t entries.
+// The C++ class Reference has a target() method that returns a
+// pointer to another Atom.  We can't have pointers in object files,
+// so instead  NativeReferenceIvarsV1 contains an index to the target.
+// The index is into this NCS_TargetsTable of uint32_t entries.
+// The values in this table are the index of the (target) atom in this file.
+// For DefinedAtoms the value is from 0 to NCS_DefinedAtomsV1.elementCount.
+// For UndefinedAtoms the value is from NCS_DefinedAtomsV1.elementCount to
+// NCS_DefinedAtomsV1.elementCount+NCS_UndefinedAtomsV1.elementCount.
+//
+
+
+//
+// The NCS_AddendsTable chunk contains an array of int64_t entries.
+// If we allocated space for addends directly in NativeReferenceIvarsV1
+// it would double the size of that struct.  But since addends are rare,
+// we instead just keep a pool of addends and have NativeReferenceIvarsV1
+// (if it needs an addend) just store the index (into the pool) of the
+// addend it needs.
+//
+
+
+
+} // namespace lld
+
+#endif // LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_

Added: lld/trunk/lib/ReaderWriter/Native/ReaderNative.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Native/ReaderNative.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/Native/ReaderNative.cpp (added)
+++ lld/trunk/lib/ReaderWriter/Native/ReaderNative.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,929 @@
+//===- lib/ReaderWriter/Native/ReaderNative.cpp ---------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/ReaderNative.h"
+
+#include "lld/Core/Atom.h"
+#include "lld/Core/Error.h"
+#include "lld/Core/File.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "NativeFileFormat.h"
+
+#include <vector>
+#include <memory>
+
+namespace lld {
+namespace native {
+
+// forward reference
+class File;
+
+//
+// An object of this class is instantied for each NativeDefinedAtomIvarsV1
+// struct in the NCS_DefinedAtomsV1 chunk.
+//
+class NativeDefinedAtomV1 : public DefinedAtom {
+public:
+      NativeDefinedAtomV1(const File& f,
+                          const NativeDefinedAtomIvarsV1* ivarData)
+        : _file(&f), _ivarData(ivarData) { }
+
+  virtual const class lld::File& file() const;
+
+  virtual uint64_t ordinal() const;
+
+  virtual StringRef name() const;
+
+  virtual uint64_t size() const {
+    return _ivarData->contentSize;
+  }
+
+  virtual DefinedAtom::Scope scope() const {
+    return (DefinedAtom::Scope)(attributes().scope);
+  }
+
+  virtual DefinedAtom::Interposable interposable() const {
+    return (DefinedAtom::Interposable)(attributes().interposable);
+  }
+
+  virtual DefinedAtom::Merge merge() const {
+    return (DefinedAtom::Merge)(attributes().merge);
+  }
+
+  virtual DefinedAtom::ContentType contentType() const {
+    const NativeAtomAttributesV1& attr = attributes();
+    return (DefinedAtom::ContentType)(attr.contentType);
+  }
+
+  virtual DefinedAtom::Alignment alignment() const {
+    return DefinedAtom::Alignment(attributes().align2, attributes().alignModulus);
+  }
+
+  virtual DefinedAtom::SectionChoice sectionChoice() const {
+    return (DefinedAtom::SectionChoice)(attributes().sectionChoice);
+  }
+
+  virtual StringRef customSectionName() const;
+
+  virtual DefinedAtom::DeadStripKind deadStrip() const {
+     return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
+  }
+
+  virtual DefinedAtom::ContentPermissions permissions() const {
+     return (DefinedAtom::ContentPermissions)(attributes().permissions);
+  }
+
+  virtual bool isThumb() const {
+     return false; //(attributes().thumb != 0);
+  }
+
+  virtual bool isAlias() const {
+     return (attributes().alias != 0);
+  }
+
+  virtual ArrayRef<uint8_t> rawContent() const;
+
+  virtual reference_iterator begin() const;
+
+  virtual reference_iterator end() const;
+
+  virtual const Reference* derefIterator(const void*) const;
+
+  virtual void incrementIterator(const void*& it) const;
+
+private:
+  const NativeAtomAttributesV1& attributes() const;
+
+  const File                     *_file;
+  const NativeDefinedAtomIvarsV1 *_ivarData;
+};
+
+
+
+//
+// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
+// struct in the NCS_UndefinedAtomsV1 chunk.
+//
+class NativeUndefinedAtomV1 : public UndefinedAtom {
+public:
+       NativeUndefinedAtomV1(const File& f,
+                             const NativeUndefinedAtomIvarsV1* ivarData)
+        : _file(&f), _ivarData(ivarData) { }
+
+  virtual const lld::File& file() const;
+  virtual StringRef name() const;
+
+  virtual CanBeNull canBeNull() const {
+    return (CanBeNull)(_ivarData->flags & 0x3);
+  }
+
+
+private:
+  const File                        *_file;
+  const NativeUndefinedAtomIvarsV1  *_ivarData;
+};
+
+
+//
+// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
+// struct in the NCS_SharedLibraryAtomsV1 chunk.
+//
+class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
+public:
+       NativeSharedLibraryAtomV1(const File& f,
+                             const NativeSharedLibraryAtomIvarsV1* ivarData)
+        : _file(&f), _ivarData(ivarData) { }
+
+  virtual const lld::File& file() const;
+  virtual StringRef name() const;
+  virtual StringRef loadName() const;
+
+  virtual bool canBeNullAtRuntime() const {
+    return (_ivarData->flags & 0x1);
+  }
+
+private:
+  const File                           *_file;
+  const NativeSharedLibraryAtomIvarsV1 *_ivarData;
+};
+
+
+//
+// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
+// struct in the NCS_AbsoluteAtomsV1 chunk.
+//
+class NativeAbsoluteAtomV1 : public AbsoluteAtom {
+public:
+       NativeAbsoluteAtomV1(const File& f,
+                             const NativeAbsoluteAtomIvarsV1* ivarData)
+        : _file(&f), _ivarData(ivarData) { }
+
+  virtual const lld::File& file() const;
+  virtual StringRef name() const;
+
+  virtual uint64_t value() const {
+    return _ivarData->value;
+  }
+
+private:
+  const File                      *_file;
+  const NativeAbsoluteAtomIvarsV1 *_ivarData;
+};
+
+
+
+//
+// An object of this class is instantied for each NativeReferenceIvarsV1
+// struct in the NCS_ReferencesArrayV1 chunk.
+//
+class NativeReferenceV1 : public Reference {
+public:
+       NativeReferenceV1(const File& f,
+                             const NativeReferenceIvarsV1* ivarData)
+        : _file(&f), _ivarData(ivarData) { }
+
+  virtual uint64_t offsetInAtom() const {
+    return _ivarData->offsetInAtom;
+  }
+
+  virtual Kind kind() const {
+    return _ivarData->kind;
+  }
+
+  virtual void setKind(Kind);
+  virtual const Atom* target() const;
+  virtual Addend addend() const;
+  virtual void setTarget(const Atom* newAtom);
+  virtual void setAddend(Addend a);
+
+private:
+  // Used in rare cases when Reference is modified,
+  // since ivar data is mapped read-only.
+  void cloneIvarData() {
+    // TODO: do nothing on second call
+   NativeReferenceIvarsV1* niv = reinterpret_cast<NativeReferenceIvarsV1*>
+                                (operator new(sizeof(NativeReferenceIvarsV1),
+                                                                std::nothrow));
+    memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
+  }
+
+  const File                    *_file;
+  const NativeReferenceIvarsV1  *_ivarData;
+};
+
+
+
+//
+// lld::File object for native llvm object file
+//
+class File : public lld::File {
+public:
+
+  /// Instantiates a File object from a native object file.  Ownership
+  /// of the MemoryBuffer is transfered to the resulting File object.
+  static error_code make(std::unique_ptr<llvm::MemoryBuffer> &mb,
+                         StringRef path,
+                         std::vector<std::unique_ptr<lld::File>> &result) {
+    const uint8_t* const base =
+                       reinterpret_cast<const uint8_t*>(mb->getBufferStart());
+    const NativeFileHeader* const header =
+                       reinterpret_cast<const NativeFileHeader*>(base);
+    const NativeChunk *const chunks =
+      reinterpret_cast<const NativeChunk*>(base + sizeof(NativeFileHeader));
+    // make sure magic matches
+    if ( memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 16) != 0 )
+      return make_error_code(native_reader_error::unknown_file_format);
+
+    // make sure mapped file contains all needed data
+    const size_t fileSize = mb->getBufferSize();
+    if ( header->fileSize > fileSize )
+      return make_error_code(native_reader_error::file_too_short);
+
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " Native File Header:"
+                    << " fileSize=" << header->fileSize
+                    << " chunkCount=" << header->chunkCount
+                    << "\n");
+
+    // instantiate NativeFile object and add values to it as found
+    std::unique_ptr<File> file(new File(std::move(mb), path));
+
+    // process each chunk
+    for(uint32_t i=0; i < header->chunkCount; ++i) {
+      error_code ec;
+      const NativeChunk* chunk = &chunks[i];
+      // sanity check chunk is within file
+      if ( chunk->fileOffset > fileSize )
+        return make_error_code(native_reader_error::file_malformed);
+      if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
+        return make_error_code(native_reader_error::file_malformed);
+      // process chunk, based on signature
+      switch ( chunk->signature ) {
+        case NCS_DefinedAtomsV1:
+          ec = file->processDefinedAtomsV1(base, chunk);
+          break;
+        case NCS_AttributesArrayV1:
+          ec = file->processAttributesV1(base, chunk);
+          break;
+        case NCS_UndefinedAtomsV1:
+          ec = file->processUndefinedAtomsV1(base, chunk);
+          break;
+        case NCS_SharedLibraryAtomsV1:
+          ec = file->processSharedLibraryAtomsV1(base, chunk);
+          break;
+        case NCS_AbsoluteAtomsV1:
+          ec = file->processAbsoluteAtomsV1(base, chunk);
+          break;
+        case NCS_ReferencesArrayV1:
+          ec = file->processReferencesV1(base, chunk);
+          break;
+        case NCS_TargetsTable:
+          ec = file->processTargetsTable(base, chunk);
+          break;
+        case NCS_AddendsTable:
+          ec = file->processAddendsTable(base, chunk);
+          break;
+        case NCS_Content:
+          ec = file->processContent(base, chunk);
+          break;
+        case NCS_Strings:
+          ec = file->processStrings(base, chunk);
+          break;
+        default:
+          return make_error_code(native_reader_error::unknown_chunk_type);
+      }
+      if ( ec ) {
+        return ec;
+      }
+    }
+    // TO DO: validate enough chunks were used
+    
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                  << " ReaderNative DefinedAtoms:\n");
+    for (const DefinedAtom *a : file->defined() ) {
+      DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << llvm::format("    0x%09lX", a)
+                    << ", name=" << a->name()
+                    << ", size=" << a->size()
+                    << "\n");
+      for (const Reference *r : *a ) {
+       DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << "        offset=" 
+                    << llvm::format("0x%03X", r->offsetInAtom())
+                    << ", kind=" << r->kind()
+                    << ", target=" << r->target()
+                    << "\n");
+      }
+    }
+
+    result.push_back(std::move(file));
+    return make_error_code(native_reader_error::success);
+  }
+
+  virtual ~File() {
+    // _buffer is automatically deleted because of OwningPtr<>
+
+    // All other ivar pointers are pointers into the MemoryBuffer, except
+    // the _definedAtoms array which was allocated to contain an array
+    // of Atom objects.  The atoms have empty destructors, so it is ok
+    // to just delete the memory.
+    delete _definedAtoms._arrayStart;
+    delete _undefinedAtoms._arrayStart;
+    delete _sharedLibraryAtoms._arrayStart;
+    delete _absoluteAtoms._arrayStart;
+    delete _references.arrayStart;
+    delete _targetsTable;
+  }
+
+  virtual const atom_collection<DefinedAtom>&  defined() const {
+    return _definedAtoms;
+  }
+  virtual const atom_collection<UndefinedAtom>& undefined() const {
+      return _undefinedAtoms;
+  }
+  virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
+      return _sharedLibraryAtoms;
+  }
+  virtual const atom_collection<AbsoluteAtom>& absolute() const {
+      return _absoluteAtoms;
+  }
+
+  virtual void addAtom(const Atom&) {
+    assert(0 && "cannot add atoms to native .o files");
+  }
+
+private:
+  friend class NativeDefinedAtomV1;
+  friend class NativeUndefinedAtomV1;
+  friend class NativeSharedLibraryAtomV1;
+  friend class NativeAbsoluteAtomV1;
+  friend class NativeReferenceV1;
+
+  // instantiate array of DefinedAtoms from v1 ivar data in file
+  error_code processDefinedAtomsV1(const uint8_t *base,
+                                   const NativeChunk *chunk) {
+    const size_t atomSize = sizeof(NativeDefinedAtomV1);
+    size_t atomsArraySize = chunk->elementCount * atomSize;
+    uint8_t* atomsStart = reinterpret_cast<uint8_t*>
+                                (operator new(atomsArraySize, std::nothrow));
+    if (atomsStart == nullptr)
+      return make_error_code(native_reader_error::memory_error);
+    const size_t ivarElementSize = chunk->fileSize
+                                          / chunk->elementCount;
+    if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
+      return make_error_code(native_reader_error::file_malformed);
+    uint8_t* atomsEnd = atomsStart + atomsArraySize;
+    const NativeDefinedAtomIvarsV1* ivarData =
+                             reinterpret_cast<const NativeDefinedAtomIvarsV1*>
+                                                  (base + chunk->fileOffset);
+    for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
+      NativeDefinedAtomV1* atomAllocSpace =
+                  reinterpret_cast<NativeDefinedAtomV1*>(s);
+      new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
+      ++ivarData;
+    }
+    this->_definedAtoms._arrayStart = atomsStart;
+    this->_definedAtoms._arrayEnd = atomsEnd;
+    this->_definedAtoms._elementSize = atomSize;
+    this->_definedAtoms._elementCount = chunk->elementCount;
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " chunk DefinedAtomsV1:      "
+                    << " count=" << chunk->elementCount
+                    << " chunkSize=" << chunk->fileSize
+                    << "\n");
+    return make_error_code(native_reader_error::success);
+  }
+
+
+
+  // set up pointers to attributes array
+  error_code processAttributesV1(const uint8_t *base,
+                                 const NativeChunk *chunk) {
+    this->_attributes = base + chunk->fileOffset;
+    this->_attributesMaxOffset = chunk->fileSize;
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " chunk AttributesV1:        "
+                    << " count=" << chunk->elementCount
+                    << " chunkSize=" << chunk->fileSize
+                    << "\n");
+    return make_error_code(native_reader_error::success);
+  }
+
+  // instantiate array of UndefinedAtoms from v1 ivar data in file
+  error_code processUndefinedAtomsV1(const uint8_t *base,
+                                     const NativeChunk *chunk) {
+    const size_t atomSize = sizeof(NativeUndefinedAtomV1);
+    size_t atomsArraySize = chunk->elementCount * atomSize;
+    uint8_t* atomsStart = reinterpret_cast<uint8_t*>
+                                (operator new(atomsArraySize, std::nothrow));
+    if (atomsStart == nullptr)
+      return make_error_code(native_reader_error::memory_error);
+    const size_t ivarElementSize = chunk->fileSize
+                                          / chunk->elementCount;
+    if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
+      return make_error_code(native_reader_error::file_malformed);
+    uint8_t* atomsEnd = atomsStart + atomsArraySize;
+    const NativeUndefinedAtomIvarsV1* ivarData =
+                            reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
+                                                  (base + chunk->fileOffset);
+    for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
+      NativeUndefinedAtomV1* atomAllocSpace =
+                  reinterpret_cast<NativeUndefinedAtomV1*>(s);
+      new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
+      ++ivarData;
+    }
+    this->_undefinedAtoms._arrayStart = atomsStart;
+    this->_undefinedAtoms._arrayEnd = atomsEnd;
+    this->_undefinedAtoms._elementSize = atomSize;
+    this->_undefinedAtoms._elementCount = chunk->elementCount;
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " chunk UndefinedAtomsV1:"
+                    << " count=" << chunk->elementCount
+                    << " chunkSize=" << chunk->fileSize
+                    << "\n");
+    return make_error_code(native_reader_error::success);
+  }
+
+
+  // instantiate array of ShareLibraryAtoms from v1 ivar data in file
+  error_code processSharedLibraryAtomsV1(const uint8_t *base,
+                                         const NativeChunk *chunk) {
+    const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
+    size_t atomsArraySize = chunk->elementCount * atomSize;
+    uint8_t* atomsStart = reinterpret_cast<uint8_t*>
+                                (operator new(atomsArraySize, std::nothrow));
+    if (atomsStart == nullptr)
+      return make_error_code(native_reader_error::memory_error);
+    const size_t ivarElementSize = chunk->fileSize
+                                          / chunk->elementCount;
+    if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
+      return make_error_code(native_reader_error::file_malformed);
+    uint8_t* atomsEnd = atomsStart + atomsArraySize;
+    const NativeSharedLibraryAtomIvarsV1* ivarData =
+                      reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
+                                                  (base + chunk->fileOffset);
+    for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
+      NativeSharedLibraryAtomV1* atomAllocSpace =
+                  reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
+      new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
+      ++ivarData;
+    }
+    this->_sharedLibraryAtoms._arrayStart = atomsStart;
+    this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
+    this->_sharedLibraryAtoms._elementSize = atomSize;
+    this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " chunk SharedLibraryAtomsV1:"
+                    << " count=" << chunk->elementCount
+                    << " chunkSize=" << chunk->fileSize
+                    << "\n");
+    return make_error_code(native_reader_error::success);
+  }
+
+
+   // instantiate array of AbsoluteAtoms from v1 ivar data in file
+  error_code processAbsoluteAtomsV1(const uint8_t *base,
+                                    const NativeChunk *chunk) {
+    const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
+    size_t atomsArraySize = chunk->elementCount * atomSize;
+    uint8_t* atomsStart = reinterpret_cast<uint8_t*>
+                                (operator new(atomsArraySize, std::nothrow));
+    if (atomsStart == nullptr)
+      return make_error_code(native_reader_error::memory_error);
+    const size_t ivarElementSize = chunk->fileSize
+                                          / chunk->elementCount;
+    if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
+      return make_error_code(native_reader_error::file_malformed);
+    uint8_t* atomsEnd = atomsStart + atomsArraySize;
+    const NativeAbsoluteAtomIvarsV1* ivarData =
+                      reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
+                                                  (base + chunk->fileOffset);
+    for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
+      NativeAbsoluteAtomV1* atomAllocSpace =
+                  reinterpret_cast<NativeAbsoluteAtomV1*>(s);
+      new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
+      ++ivarData;
+    }
+    this->_absoluteAtoms._arrayStart = atomsStart;
+    this->_absoluteAtoms._arrayEnd = atomsEnd;
+    this->_absoluteAtoms._elementSize = atomSize;
+    this->_absoluteAtoms._elementCount = chunk->elementCount;
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " chunk AbsoluteAtomsV1:     "
+                    << " count=" << chunk->elementCount
+                    << " chunkSize=" << chunk->fileSize
+                    << "\n");
+    return make_error_code(native_reader_error::success);
+  }
+
+
+
+
+  // instantiate array of Referemces from v1 ivar data in file
+  error_code processReferencesV1(const uint8_t *base,
+                                 const NativeChunk *chunk) {
+    if ( chunk->elementCount == 0 )
+      return make_error_code(native_reader_error::success);
+    const size_t refSize = sizeof(NativeReferenceV1);
+    size_t refsArraySize = chunk->elementCount * refSize;
+    uint8_t* refsStart = reinterpret_cast<uint8_t*>
+                                (operator new(refsArraySize, std::nothrow));
+    if (refsStart == nullptr)
+      return make_error_code(native_reader_error::memory_error);
+    const size_t ivarElementSize = chunk->fileSize
+                                          / chunk->elementCount;
+    if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
+      return make_error_code(native_reader_error::file_malformed);
+    uint8_t* refsEnd = refsStart + refsArraySize;
+    const NativeReferenceIvarsV1* ivarData =
+                             reinterpret_cast<const NativeReferenceIvarsV1*>
+                                                  (base + chunk->fileOffset);
+    for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
+      NativeReferenceV1* atomAllocSpace =
+                  reinterpret_cast<NativeReferenceV1*>(s);
+      new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
+      ++ivarData;
+    }
+    this->_references.arrayStart = refsStart;
+    this->_references.arrayEnd = refsEnd;
+    this->_references.elementSize = refSize;
+    this->_references.elementCount = chunk->elementCount;
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " chunk ReferencesV1:        "
+                    << " count=" << chunk->elementCount
+                    << " chunkSize=" << chunk->fileSize
+                    << "\n");
+    return make_error_code(native_reader_error::success);
+  }
+
+  // set up pointers to target table
+  error_code processTargetsTable(const uint8_t *base,
+                                 const NativeChunk *chunk) {
+    const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
+                                                  (base + chunk->fileOffset);
+    this->_targetsTableCount = chunk->elementCount;
+    this->_targetsTable = new const Atom*[chunk->elementCount];
+    for (uint32_t i=0; i < chunk->elementCount; ++i) {
+      const uint32_t index = targetIndexes[i];
+      if ( index < _definedAtoms._elementCount ) {
+        const uint8_t* p = _definedAtoms._arrayStart
+                                    + index * _definedAtoms._elementSize;
+        this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
+        continue;
+      }
+      const uint32_t undefIndex = index - _definedAtoms._elementCount;
+      if ( undefIndex < _undefinedAtoms._elementCount ) {
+        const uint8_t* p = _undefinedAtoms._arrayStart
+                                    + undefIndex * _undefinedAtoms._elementSize;
+        this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
+        continue;
+      }
+      const uint32_t slIndex = index - _definedAtoms._elementCount
+                                     - _undefinedAtoms._elementCount;
+      if ( slIndex < _sharedLibraryAtoms._elementCount ) {
+        const uint8_t* p = _sharedLibraryAtoms._arrayStart
+                                  + slIndex * _sharedLibraryAtoms._elementSize;
+        this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
+        continue;
+      }
+      const uint32_t abIndex = index - _definedAtoms._elementCount
+                                     - _undefinedAtoms._elementCount
+                                     - _sharedLibraryAtoms._elementCount;
+      if ( abIndex < _absoluteAtoms._elementCount ) {
+        const uint8_t* p = _absoluteAtoms._arrayStart
+                                  + slIndex * _absoluteAtoms._elementSize;
+        this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
+        continue;
+      }
+     return make_error_code(native_reader_error::file_malformed);
+    }
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " chunk Targets Table:       "
+                    << " count=" << chunk->elementCount
+                    << " chunkSize=" << chunk->fileSize
+                    << "\n");
+    return make_error_code(native_reader_error::success);
+  }
+
+
+  // set up pointers to addend pool in file
+  error_code processAddendsTable(const uint8_t *base,
+                                 const NativeChunk *chunk) {
+    this->_addends = reinterpret_cast<const Reference::Addend*>
+                                                  (base + chunk->fileOffset);
+    this->_addendsMaxIndex = chunk->elementCount;
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " chunk Addends:             "
+                    << " count=" << chunk->elementCount
+                    << " chunkSize=" << chunk->fileSize
+                    << "\n");
+    return make_error_code(native_reader_error::success);
+  }
+
+  // set up pointers to string pool in file
+  error_code processStrings(const uint8_t *base,
+                            const NativeChunk *chunk) {
+    this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
+    this->_stringsMaxOffset = chunk->fileSize;
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " chunk Strings:             "
+                    << " chunkSize=" << chunk->fileSize
+                    << "\n");
+    return make_error_code(native_reader_error::success);
+  }
+
+  // set up pointers to content area in file
+  error_code processContent(const uint8_t *base,
+                            const NativeChunk *chunk) {
+    this->_contentStart = base + chunk->fileOffset;
+    this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " chunk content:             "
+                    << " chunkSize=" << chunk->fileSize
+                    << "\n");
+    return make_error_code(native_reader_error::success);
+  }
+
+  StringRef string(uint32_t offset) const {
+    assert(offset < _stringsMaxOffset);
+    return StringRef(&_strings[offset]);
+  }
+
+  Reference::Addend addend(uint32_t index) const {
+    if ( index == 0 )
+      return 0; // addend index zero is used to mean "no addend"
+    assert(index <= _addendsMaxIndex);
+    return _addends[index-1]; // one-based indexing
+  }
+
+  const NativeAtomAttributesV1& attribute(uint32_t off) const {
+    assert(off < _attributesMaxOffset);
+    return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
+  }
+
+  const uint8_t* content(uint32_t offset, uint32_t size) const {
+    const uint8_t* result = _contentStart + offset;
+    assert((result+size) <= _contentEnd);
+    return result;
+  }
+
+  const Reference* referenceByIndex(uintptr_t index) const {
+    assert(index < _references.elementCount);
+    const uint8_t* p = _references.arrayStart + index * _references.elementSize;
+    return reinterpret_cast<const NativeReferenceV1*>(p);
+  }
+
+  const Atom* target(uint16_t index) const {
+    if ( index == NativeReferenceIvarsV1::noTarget )
+      return nullptr;
+    assert(index < _targetsTableCount);
+    return _targetsTable[index];
+  }
+
+  void setTarget(uint16_t index, const Atom* newAtom) const {
+    assert(index != NativeReferenceIvarsV1::noTarget);
+    assert(index > _targetsTableCount);
+    _targetsTable[index] = newAtom;
+  }
+  
+
+
+  // private constructor, only called by make()
+  File(std::unique_ptr<llvm::MemoryBuffer> mb, StringRef path) :
+    lld::File(path),
+    _buffer(std::move(mb)),  // Reader now takes ownership of buffer
+    _header(nullptr),
+    _targetsTable(nullptr),
+    _targetsTableCount(0),
+    _strings(nullptr),
+    _stringsMaxOffset(0),
+    _addends(nullptr),
+    _addendsMaxIndex(0),
+    _contentStart(nullptr),
+    _contentEnd(nullptr)
+  {
+    _header = reinterpret_cast<const NativeFileHeader*>
+                                                  (_buffer->getBufferStart());
+  }
+
+  template <typename T>
+  class AtomArray : public File::atom_collection<T> {
+  public:
+     AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
+                   _elementSize(0), _elementCount(0) { }
+
+    virtual atom_iterator<T> begin() const {
+      return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
+    }
+    virtual atom_iterator<T> end() const{
+      return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
+    }
+    virtual const T* deref(const void* it) const {
+      return reinterpret_cast<const T*>(it);
+    }
+    virtual void next(const void*& it) const {
+      const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
+      p += _elementSize;
+      it = reinterpret_cast<const void*>(p);
+    }
+    const uint8_t*     _arrayStart;
+    const uint8_t*     _arrayEnd;
+    uint32_t           _elementSize;
+    uint32_t           _elementCount;
+  };
+
+  struct IvarArray {
+                      IvarArray() :
+                        arrayStart(nullptr),
+                        arrayEnd(nullptr),
+                        elementSize(0),
+                        elementCount(0) { }
+
+    const uint8_t*     arrayStart;
+    const uint8_t*     arrayEnd;
+    uint32_t           elementSize;
+    uint32_t           elementCount;
+  };
+
+
+  std::unique_ptr<llvm::MemoryBuffer> _buffer;
+  const NativeFileHeader*         _header;
+  AtomArray<DefinedAtom>          _definedAtoms;
+  AtomArray<UndefinedAtom>        _undefinedAtoms;
+  AtomArray<SharedLibraryAtom>    _sharedLibraryAtoms;
+  AtomArray<AbsoluteAtom>         _absoluteAtoms;
+  const uint8_t*                  _attributes;
+  uint32_t                        _attributesMaxOffset;
+  IvarArray                       _references;
+  const Atom**                    _targetsTable;
+  uint32_t                        _targetsTableCount;
+  const char*                     _strings;
+  uint32_t                        _stringsMaxOffset;
+  const Reference::Addend*        _addends;
+  uint32_t                        _addendsMaxIndex;
+  const uint8_t*                  _contentStart;
+  const uint8_t*                  _contentEnd;
+};
+
+
+inline const class lld::File& NativeDefinedAtomV1::file() const {
+  return *_file;
+}
+
+inline uint64_t NativeDefinedAtomV1:: ordinal() const {
+  const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
+  return p - _file->_definedAtoms._arrayStart;
+}
+
+inline StringRef NativeDefinedAtomV1::name() const {
+  return _file->string(_ivarData->nameOffset);
+}
+
+inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
+  return _file->attribute(_ivarData->attributesOffset);
+}
+
+inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
+  if ( this->contentType() == DefinedAtom::typeZeroFill )
+    return ArrayRef<uint8_t>();
+  const uint8_t* p = _file->content(_ivarData->contentOffset,
+                                    _ivarData->contentSize);
+   return ArrayRef<uint8_t>(p, _ivarData->contentSize);
+}
+
+inline StringRef NativeDefinedAtomV1::customSectionName() const {
+  uint32_t offset = attributes().sectionNameOffset;
+  return _file->string(offset);
+}
+
+DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
+  uintptr_t index = _ivarData->referencesStartIndex;
+  const void* it = reinterpret_cast<const void*>(index);
+  return reference_iterator(*this, it);
+}
+
+DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
+  uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
+  const void* it = reinterpret_cast<const void*>(index);
+  return reference_iterator(*this, it);
+}
+
+const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
+  uintptr_t index = reinterpret_cast<uintptr_t>(it);
+  return _file->referenceByIndex(index);
+}
+
+void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
+  uintptr_t index = reinterpret_cast<uintptr_t>(it);
+  ++index;
+  it = reinterpret_cast<const void*>(index);
+}
+
+inline const class lld::File& NativeUndefinedAtomV1::file() const {
+  return *_file;
+}
+
+inline StringRef NativeUndefinedAtomV1::name() const {
+  return _file->string(_ivarData->nameOffset);
+}
+
+
+
+
+inline const class lld::File& NativeSharedLibraryAtomV1::file() const {
+  return *_file;
+}
+
+inline StringRef NativeSharedLibraryAtomV1::name() const {
+  return _file->string(_ivarData->nameOffset);
+}
+
+inline StringRef NativeSharedLibraryAtomV1::loadName() const {
+  return _file->string(_ivarData->loadNameOffset);
+}
+
+
+
+inline const class lld::File& NativeAbsoluteAtomV1::file() const {
+  return *_file;
+}
+
+inline StringRef NativeAbsoluteAtomV1::name() const {
+  return _file->string(_ivarData->nameOffset);
+}
+
+
+inline const Atom* NativeReferenceV1::target() const {
+  return _file->target(_ivarData->targetIndex);
+}
+
+inline Reference::Addend NativeReferenceV1::addend() const {
+  return _file->addend(_ivarData->addendIndex);
+}
+
+inline void NativeReferenceV1::setKind(Kind k) {
+  this->cloneIvarData();
+  const_cast<NativeReferenceIvarsV1*>(_ivarData)->kind = k;
+}
+
+inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
+  return _file->setTarget(_ivarData->targetIndex, newAtom);
+}
+
+inline void NativeReferenceV1::setAddend(Addend a) {
+  // Do nothing if addend value is not being changed.
+  if ( this->addend() == a )
+    return;
+  assert(0 && "setAddend() not supported");
+}
+
+
+class Reader : public lld::Reader {
+public:
+  Reader(const ReaderOptionsNative &options) : _options(options) {
+  }
+  
+  virtual error_code parseFile(std::unique_ptr<MemoryBuffer> mb, 
+                               std::vector<std::unique_ptr<lld::File>> &result) {
+    return File::make(mb, mb->getBufferIdentifier(), result);
+  }
+
+private:
+  const ReaderOptionsNative &_options;
+};
+
+
+
+} // namespace native
+
+Reader* createReaderNative(const ReaderOptionsNative &options) {
+  return new lld::native::Reader(options);
+}
+
+ReaderOptionsNative::ReaderOptionsNative() {
+}
+
+ReaderOptionsNative::~ReaderOptionsNative() {
+}
+
+
+} // namespace lld
+
+
+
+

Added: lld/trunk/lib/ReaderWriter/Native/WriterNative.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Native/WriterNative.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/Native/WriterNative.cpp (added)
+++ lld/trunk/lib/ReaderWriter/Native/WriterNative.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,563 @@
+//===- lib/ReaderWriter/Native/WriterNative.cpp ---------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/WriterNative.h"
+#include "lld/Core/File.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+#include "NativeFileFormat.h"
+
+#include <vector>
+
+namespace lld {
+namespace native {
+
+///
+/// Class for writing native object files.
+///
+class Writer : public lld::Writer {
+public:
+  Writer(const WriterOptionsNative &options) : _options(options) {
+  }
+  
+  virtual error_code writeFile(const lld::File &file, StringRef outPath) {
+    // reserve first byte for unnamed atoms
+    _stringPool.push_back('\0');
+    // visit all atoms
+    for ( const DefinedAtom *defAtom : file.defined() ) {
+      this->addIVarsForDefinedAtom(*defAtom);
+    }
+    for ( const UndefinedAtom *undefAtom : file.undefined() ) {
+      this->addIVarsForUndefinedAtom(*undefAtom);
+    }
+    for ( const SharedLibraryAtom *shlibAtom : file.sharedLibrary() ) {
+      this->addIVarsForSharedLibraryAtom(*shlibAtom);
+    }
+    for ( const AbsoluteAtom *absAtom : file.absolute() ) {
+      this->addIVarsForAbsoluteAtom(*absAtom);
+    }
+
+    // construct file header based on atom information accumulated
+    this->makeHeader();
+    
+    std::string errorInfo;
+    llvm::raw_fd_ostream out(outPath.data(), errorInfo,
+                              llvm::raw_fd_ostream::F_Binary);
+    if (!errorInfo.empty())
+      return error_code::success(); // FIXME
+
+    this->write(out);
+    
+    return error_code::success();
+  }
+
+  virtual ~Writer() {
+  }
+
+private:
+
+  // write the lld::File in native format to the specified stream
+  void write(raw_ostream &out) {
+    assert( out.tell() == 0 );
+    out.write((char*)_headerBuffer, _headerBufferSize);
+
+    if (!_definedAtomIvars.empty()) {
+      assert( out.tell() == findChunk(NCS_DefinedAtomsV1).fileOffset );
+      out.write((char*)&_definedAtomIvars[0],
+                _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1));
+    }
+
+    if (!_attributes.empty()) {
+      assert( out.tell() == findChunk(NCS_AttributesArrayV1).fileOffset );
+      out.write((char*)&_attributes[0],
+                _attributes.size()*sizeof(NativeAtomAttributesV1));
+    }
+
+    if ( !_undefinedAtomIvars.empty() ) {
+      assert( out.tell() == findChunk(NCS_UndefinedAtomsV1).fileOffset );
+      out.write((char*)&_undefinedAtomIvars[0],
+              _undefinedAtomIvars.size()*sizeof(NativeUndefinedAtomIvarsV1));
+    }
+
+     if ( !_sharedLibraryAtomIvars.empty() ) {
+      assert( out.tell() == findChunk(NCS_SharedLibraryAtomsV1).fileOffset );
+      out.write((char*)&_sharedLibraryAtomIvars[0],
+              _sharedLibraryAtomIvars.size()
+              * sizeof(NativeSharedLibraryAtomIvarsV1));
+    }
+
+    if ( !_absoluteAtomIvars.empty() ) {
+      assert( out.tell() == findChunk(NCS_AbsoluteAtomsV1).fileOffset );
+      out.write((char*)&_absoluteAtomIvars[0],
+              _absoluteAtomIvars.size()
+              * sizeof(NativeAbsoluteAtomIvarsV1));
+    }
+
+    if (!_stringPool.empty()) {
+      assert( out.tell() == findChunk(NCS_Strings).fileOffset );
+      out.write(&_stringPool[0], _stringPool.size());
+    }
+
+    if ( !_references.empty() ) {
+      assert( out.tell() == findChunk(NCS_ReferencesArrayV1).fileOffset );
+      out.write((char*)&_references[0],
+              _references.size()*sizeof(NativeReferenceIvarsV1));
+    }
+
+    if ( !_targetsTableIndex.empty() ) {
+      assert( out.tell() == findChunk(NCS_TargetsTable).fileOffset );
+      writeTargetTable(out);
+    }
+
+    if ( !_addendsTableIndex.empty() ) {
+      assert( out.tell() == findChunk(NCS_AddendsTable).fileOffset );
+      writeAddendTable(out);
+    }
+
+    if (!_contentPool.empty()) {
+      assert( out.tell() == findChunk(NCS_Content).fileOffset );
+      out.write((char*)&_contentPool[0], _contentPool.size());
+    }
+  }
+
+  void addIVarsForDefinedAtom(const DefinedAtom& atom) {
+    _definedAtomIndex[&atom] = _definedAtomIvars.size();
+    NativeDefinedAtomIvarsV1 ivar;
+    unsigned refsCount;
+    ivar.nameOffset = getNameOffset(atom);
+    ivar.attributesOffset = getAttributeOffset(atom);
+    ivar.referencesStartIndex = getReferencesIndex(atom, refsCount);
+    ivar.referencesCount = refsCount;
+    ivar.contentOffset = getContentOffset(atom);
+    ivar.contentSize = atom.size();
+    _definedAtomIvars.push_back(ivar);
+  }
+
+  void addIVarsForUndefinedAtom(const UndefinedAtom& atom) {
+    _undefinedAtomIndex[&atom] = _undefinedAtomIvars.size();
+    NativeUndefinedAtomIvarsV1 ivar;
+    ivar.nameOffset = getNameOffset(atom);
+    ivar.flags = (atom.canBeNull() & 0x03);
+    _undefinedAtomIvars.push_back(ivar);
+  }
+
+  void addIVarsForSharedLibraryAtom(const SharedLibraryAtom& atom) {
+    _sharedLibraryAtomIndex[&atom] = _sharedLibraryAtomIvars.size();
+    NativeSharedLibraryAtomIvarsV1 ivar;
+    ivar.nameOffset = getNameOffset(atom);
+    ivar.loadNameOffset = getSharedLibraryNameOffset(atom.loadName());
+    ivar.flags = atom.canBeNullAtRuntime();
+    _sharedLibraryAtomIvars.push_back(ivar);
+  }
+
+  void addIVarsForAbsoluteAtom(const AbsoluteAtom& atom) {
+    _absoluteAtomIndex[&atom] = _absoluteAtomIvars.size();
+    NativeAbsoluteAtomIvarsV1 ivar;
+    ivar.nameOffset = getNameOffset(atom);
+    ivar.reserved = 0;
+    ivar.value = atom.value();
+    _absoluteAtomIvars.push_back(ivar);
+  }
+
+  // fill out native file header and chunk directory
+  void makeHeader() {
+    const bool hasDefines = !_definedAtomIvars.empty();
+    const bool hasUndefines = !_undefinedAtomIvars.empty();
+    const bool hasSharedLibraries = !_sharedLibraryAtomIvars.empty();
+    const bool hasAbsolutes = !_absoluteAtomIvars.empty();
+    const bool hasReferences = !_references.empty();
+    const bool hasTargetsTable = !_targetsTableIndex.empty();
+    const bool hasAddendTable = !_addendsTableIndex.empty();
+    const bool hasContent = !_contentPool.empty();
+
+    int chunkCount = 1; // always have string pool chunk
+    if ( hasDefines ) chunkCount += 2;
+    if ( hasUndefines ) ++chunkCount;
+    if ( hasSharedLibraries ) ++chunkCount;
+    if ( hasAbsolutes ) ++chunkCount;
+    if ( hasReferences ) ++chunkCount;
+    if ( hasTargetsTable ) ++chunkCount;
+    if ( hasAddendTable ) ++chunkCount;
+    if ( hasContent ) ++chunkCount;
+
+    _headerBufferSize = sizeof(NativeFileHeader)
+                         + chunkCount*sizeof(NativeChunk);
+    _headerBuffer = reinterpret_cast<NativeFileHeader*>
+                               (operator new(_headerBufferSize, std::nothrow));
+    NativeChunk *chunks =
+      reinterpret_cast<NativeChunk*>(reinterpret_cast<char*>(_headerBuffer)
+                                     + sizeof(NativeFileHeader));
+    memcpy(_headerBuffer->magic, NATIVE_FILE_HEADER_MAGIC, 16);
+    _headerBuffer->endian = NFH_LittleEndian;
+    _headerBuffer->architecture = 0;
+    _headerBuffer->fileSize = 0;
+    _headerBuffer->chunkCount = chunkCount;
+
+    // create chunk for defined atom ivar array
+    int nextIndex = 0;
+    uint32_t nextFileOffset = _headerBufferSize;
+    if ( hasDefines ) {
+      NativeChunk& chd = chunks[nextIndex++];
+      chd.signature = NCS_DefinedAtomsV1;
+      chd.fileOffset = nextFileOffset;
+      chd.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1);
+      chd.elementCount = _definedAtomIvars.size();
+      nextFileOffset = chd.fileOffset + chd.fileSize;
+
+      // create chunk for attributes
+      NativeChunk& cha = chunks[nextIndex++];
+      cha.signature = NCS_AttributesArrayV1;
+      cha.fileOffset = nextFileOffset;
+      cha.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1);
+      cha.elementCount = _attributes.size();
+      nextFileOffset = cha.fileOffset + cha.fileSize;
+    }
+
+    // create chunk for undefined atom array
+    if ( hasUndefines ) {
+      NativeChunk& chu = chunks[nextIndex++];
+      chu.signature = NCS_UndefinedAtomsV1;
+      chu.fileOffset = nextFileOffset;
+      chu.fileSize = _undefinedAtomIvars.size() *
+                                            sizeof(NativeUndefinedAtomIvarsV1);
+      chu.elementCount = _undefinedAtomIvars.size();
+      nextFileOffset = chu.fileOffset + chu.fileSize;
+    }
+
+    // create chunk for shared library atom array
+    if ( hasSharedLibraries ) {
+      NativeChunk& chsl = chunks[nextIndex++];
+      chsl.signature = NCS_SharedLibraryAtomsV1;
+      chsl.fileOffset = nextFileOffset;
+      chsl.fileSize = _sharedLibraryAtomIvars.size() *
+                                        sizeof(NativeSharedLibraryAtomIvarsV1);
+      chsl.elementCount = _sharedLibraryAtomIvars.size();
+      nextFileOffset = chsl.fileOffset + chsl.fileSize;
+    }
+
+     // create chunk for shared library atom array
+    if ( hasAbsolutes ) {
+      NativeChunk& chsl = chunks[nextIndex++];
+      chsl.signature = NCS_AbsoluteAtomsV1;
+      chsl.fileOffset = nextFileOffset;
+      chsl.fileSize = _absoluteAtomIvars.size() *
+                                        sizeof(NativeAbsoluteAtomIvarsV1);
+      chsl.elementCount = _absoluteAtomIvars.size();
+      nextFileOffset = chsl.fileOffset + chsl.fileSize;
+    }
+
+    // create chunk for symbol strings
+    // pad end of string pool to 4-bytes
+    while ( (_stringPool.size() % 4) != 0 )
+      _stringPool.push_back('\0');
+    NativeChunk& chs = chunks[nextIndex++];
+    chs.signature = NCS_Strings;
+    chs.fileOffset = nextFileOffset;
+    chs.fileSize = _stringPool.size();
+    chs.elementCount = _stringPool.size();
+    nextFileOffset = chs.fileOffset + chs.fileSize;
+
+    // create chunk for references
+    if ( hasReferences ) {
+      NativeChunk& chr = chunks[nextIndex++];
+      chr.signature = NCS_ReferencesArrayV1;
+      chr.fileOffset = nextFileOffset;
+      chr.fileSize = _references.size() * sizeof(NativeReferenceIvarsV1);
+      chr.elementCount = _references.size();
+      nextFileOffset = chr.fileOffset + chr.fileSize;
+    }
+
+    // create chunk for target table
+    if ( hasTargetsTable ) {
+      NativeChunk& cht = chunks[nextIndex++];
+      cht.signature = NCS_TargetsTable;
+      cht.fileOffset = nextFileOffset;
+      cht.fileSize = _targetsTableIndex.size() * sizeof(uint32_t);
+      cht.elementCount = _targetsTableIndex.size();
+      nextFileOffset = cht.fileOffset + cht.fileSize;
+    }
+
+    // create chunk for addend table
+    if ( hasAddendTable ) {
+      NativeChunk& chad = chunks[nextIndex++];
+      chad.signature = NCS_AddendsTable;
+      chad.fileOffset = nextFileOffset;
+      chad.fileSize = _addendsTableIndex.size() * sizeof(Reference::Addend);
+      chad.elementCount = _addendsTableIndex.size();
+      nextFileOffset = chad.fileOffset + chad.fileSize;
+    }
+
+    // create chunk for content
+    if ( hasContent ) {
+      NativeChunk& chc = chunks[nextIndex++];
+      chc.signature = NCS_Content;
+      chc.fileOffset = nextFileOffset;
+      chc.fileSize = _contentPool.size();
+      chc.elementCount = _contentPool.size();
+      nextFileOffset = chc.fileOffset + chc.fileSize;
+    }
+
+    _headerBuffer->fileSize = nextFileOffset;
+  }
+
+  // scan header to find particular chunk
+  NativeChunk& findChunk(uint32_t signature) {
+    const uint32_t chunkCount = _headerBuffer->chunkCount;
+    NativeChunk* chunks =
+      reinterpret_cast<NativeChunk*>(reinterpret_cast<char*>(_headerBuffer)
+                                     + sizeof(NativeFileHeader));
+    for (uint32_t i=0; i < chunkCount; ++i) {
+      if ( chunks[i].signature == signature )
+        return chunks[i];
+    }
+    assert(0 && "findChunk() signature not found");
+    static NativeChunk x; return x; // suppress warning
+  }
+
+  // append atom name to string pool and return offset
+  uint32_t getNameOffset(const Atom& atom) {
+    return this->getNameOffset(atom.name());
+  }
+
+  // check if name is already in pool or append and return offset
+  uint32_t getSharedLibraryNameOffset(StringRef name) {
+    assert( ! name.empty() );
+    // look to see if this library name was used by another atom
+    for(NameToOffsetVector::iterator it = _sharedLibraryNames.begin();
+                                    it != _sharedLibraryNames.end(); ++it) {
+      if ( name.equals(it->first) )
+        return it->second;
+    }
+    // first use of this library name
+    uint32_t result = this->getNameOffset(name);
+    _sharedLibraryNames.push_back(std::make_pair(name, result));
+    return result;
+  }
+
+  // append atom name to string pool and return offset
+  uint32_t getNameOffset(StringRef name) {
+    if ( name.empty() )
+      return 0;
+    uint32_t result = _stringPool.size();
+    _stringPool.insert(_stringPool.end(), name.begin(), name.end());
+    _stringPool.push_back(0);
+    return result;
+  }
+
+  // append atom cotent to content pool and return offset
+  uint32_t getContentOffset(const class DefinedAtom& atom) {
+    if ( atom.contentType() == DefinedAtom::typeZeroFill )
+      return 0;
+    uint32_t result = _contentPool.size();
+    ArrayRef<uint8_t> cont = atom.rawContent();
+    _contentPool.insert(_contentPool.end(), cont.begin(), cont.end());
+    return result;
+  }
+
+  // reuse existing attributes entry or create a new one and return offet
+  uint32_t getAttributeOffset(const class DefinedAtom& atom) {
+    NativeAtomAttributesV1 attrs;
+    computeAttributesV1(atom, attrs);
+    for(unsigned int i=0; i < _attributes.size(); ++i) {
+      if ( !memcmp(&_attributes[i], &attrs, sizeof(NativeAtomAttributesV1)) ) {
+        // found that this set of attributes already used, so re-use
+        return i * sizeof(NativeAtomAttributesV1);
+      }
+    }
+    // append new attribute set to end
+    uint32_t result = _attributes.size() * sizeof(NativeAtomAttributesV1);
+    _attributes.push_back(attrs);
+    return result;
+  }
+
+  uint32_t sectionNameOffset(const class DefinedAtom& atom) {
+    // if section based on content, then no custom section name available
+    if ( atom.sectionChoice() == DefinedAtom::sectionBasedOnContent )
+      return 0;
+    StringRef name = atom.customSectionName();
+    assert( ! name.empty() );
+    // look to see if this section name was used by another atom
+    for(NameToOffsetVector::iterator it=_sectionNames.begin();
+                                            it != _sectionNames.end(); ++it) {
+      if ( name.equals(it->first) )
+        return it->second;
+    }
+    // first use of this section name
+    uint32_t result = this->getNameOffset(name);
+    _sectionNames.push_back(std::make_pair(name, result));
+    return result;
+  }
+
+  void computeAttributesV1(const class DefinedAtom& atom,
+                                                NativeAtomAttributesV1& attrs) {
+    attrs.sectionNameOffset = sectionNameOffset(atom);
+    attrs.align2            = atom.alignment().powerOf2;
+    attrs.alignModulus      = atom.alignment().modulus;
+    attrs.scope             = atom.scope();
+    attrs.interposable      = atom.interposable();
+    attrs.merge             = atom.merge();
+    attrs.contentType       = atom.contentType();
+    attrs.sectionChoice     = atom.sectionChoice();
+    attrs.deadStrip         = atom.deadStrip();
+    attrs.permissions       = atom.permissions();
+    //attrs.thumb             = atom.isThumb();
+    attrs.alias             = atom.isAlias();
+  }
+
+  // add references for this atom in a contiguous block in NCS_ReferencesArrayV1
+  uint32_t getReferencesIndex(const DefinedAtom& atom, unsigned& count) {
+    count = 0;
+    size_t startRefSize = _references.size();
+    uint32_t result = startRefSize;
+    for (const Reference *ref : atom) {
+      NativeReferenceIvarsV1 nref;
+      nref.offsetInAtom = ref->offsetInAtom();
+      nref.kind = ref->kind();
+      nref.targetIndex = this->getTargetIndex(ref->target());
+      nref.addendIndex = this->getAddendIndex(ref->addend());
+      _references.push_back(nref);
+    }
+    count = _references.size() - startRefSize;
+    if ( count == 0 )
+      return 0;
+    else
+      return result;
+  }
+
+  uint32_t getTargetIndex(const Atom* target) {
+    if ( target == nullptr )
+      return NativeReferenceIvarsV1::noTarget;
+    TargetToIndex::const_iterator pos = _targetsTableIndex.find(target);
+    if ( pos != _targetsTableIndex.end() ) {
+      return pos->second;
+    }
+    uint32_t result = _targetsTableIndex.size();
+    _targetsTableIndex[target] = result;
+    return result;
+  }
+
+  void writeTargetTable(raw_ostream &out) {
+    // Build table of target indexes
+    uint32_t maxTargetIndex = _targetsTableIndex.size();
+    assert(maxTargetIndex > 0);
+    std::vector<uint32_t> targetIndexes(maxTargetIndex);
+    for (TargetToIndex::iterator it = _targetsTableIndex.begin();
+                                 it != _targetsTableIndex.end(); ++it) {
+      const Atom* atom = it->first;
+      uint32_t targetIndex = it->second;
+      assert(targetIndex < maxTargetIndex);
+      uint32_t atomIndex = 0;
+      TargetToIndex::iterator pos = _definedAtomIndex.find(atom);
+      if ( pos != _definedAtomIndex.end() ) {
+        atomIndex = pos->second;
+      }
+      else {
+        pos = _undefinedAtomIndex.find(atom);
+        if ( pos != _undefinedAtomIndex.end() ) {
+          atomIndex = pos->second + _definedAtomIvars.size();
+        }
+        else {
+          pos = _sharedLibraryAtomIndex.find(atom);
+          if ( pos != _sharedLibraryAtomIndex.end() ) {
+            assert(pos != _sharedLibraryAtomIndex.end());
+            atomIndex = pos->second
+                      + _definedAtomIvars.size()
+                      + _undefinedAtomIndex.size();
+          }
+          else {
+            pos = _absoluteAtomIndex.find(atom);
+            assert(pos != _absoluteAtomIndex.end());
+            atomIndex = pos->second
+                      + _definedAtomIvars.size()
+                      + _undefinedAtomIndex.size()
+                      + _sharedLibraryAtomIndex.size();
+         }
+        }
+      }
+      targetIndexes[targetIndex] = atomIndex;
+    }
+    // write table
+    out.write((char*)&targetIndexes[0], maxTargetIndex*sizeof(uint32_t));
+  }
+
+  uint32_t getAddendIndex(Reference::Addend addend) {
+    if ( addend == 0 )
+      return 0; // addend index zero is used to mean "no addend"
+    AddendToIndex::const_iterator pos = _addendsTableIndex.find(addend);
+    if ( pos != _addendsTableIndex.end() ) {
+      return pos->second;
+    }
+    uint32_t result = _addendsTableIndex.size() + 1; // one-based index
+    _addendsTableIndex[addend] = result;
+    return result;
+  }
+
+  void writeAddendTable(raw_ostream &out) {
+    // Build table of addends
+    uint32_t maxAddendIndex = _addendsTableIndex.size();
+    std::vector<Reference::Addend> addends(maxAddendIndex);
+    for (AddendToIndex::iterator it = _addendsTableIndex.begin();
+                                 it != _addendsTableIndex.end(); ++it) {
+      Reference::Addend addend = it->first;
+      uint32_t index = it->second;
+      assert(index <= maxAddendIndex);
+      addends[index-1] = addend;
+    }
+    // write table
+    out.write((char*)&addends[0], maxAddendIndex*sizeof(Reference::Addend));
+  }
+
+  typedef std::vector<std::pair<StringRef, uint32_t> > NameToOffsetVector;
+
+  typedef llvm::DenseMap<const Atom*, uint32_t> TargetToIndex;
+  typedef llvm::DenseMap<Reference::Addend, uint32_t> AddendToIndex;
+
+  const WriterOptionsNative              &_options;
+  NativeFileHeader*                       _headerBuffer;
+  size_t                                  _headerBufferSize;
+  std::vector<char>                       _stringPool;
+  std::vector<uint8_t>                    _contentPool;
+  std::vector<NativeDefinedAtomIvarsV1>   _definedAtomIvars;
+  std::vector<NativeAtomAttributesV1>     _attributes;
+  std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
+  std::vector<NativeSharedLibraryAtomIvarsV1> _sharedLibraryAtomIvars;
+  std::vector<NativeAbsoluteAtomIvarsV1>  _absoluteAtomIvars;
+  std::vector<NativeReferenceIvarsV1>     _references;
+  TargetToIndex                           _targetsTableIndex;
+  TargetToIndex                           _definedAtomIndex;
+  TargetToIndex                           _undefinedAtomIndex;
+  TargetToIndex                           _sharedLibraryAtomIndex;
+  TargetToIndex                           _absoluteAtomIndex;
+  AddendToIndex                           _addendsTableIndex;
+  NameToOffsetVector                      _sectionNames;
+  NameToOffsetVector                      _sharedLibraryNames;
+};
+
+
+} // namespace native
+
+Writer* createWriterNative(const WriterOptionsNative &options) {
+  return new lld::native::Writer(options);
+}
+
+WriterOptionsNative::WriterOptionsNative() {
+}
+
+WriterOptionsNative::~WriterOptionsNative() {
+}
+
+
+} // namespace lld
+
+

Added: lld/trunk/lib/ReaderWriter/PECOFF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/CMakeLists.txt?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/CMakeLists.txt (added)
+++ lld/trunk/lib/ReaderWriter/PECOFF/CMakeLists.txt Thu May 31 17:34:00 2012
@@ -0,0 +1,4 @@
+add_lld_library(lldPECOFF
+  ReaderCOFF.cpp
+  WriterPECOFF.cpp
+  )

Added: lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp (added)
+++ lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,384 @@
+//===- lib/ReaderWriter/PECOFF/ReaderCOFF.cpp -----------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/ReaderPECOFF.h"
+#include "lld/Core/File.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+#include <map>
+#include <vector>
+
+using namespace lld;
+using llvm::object::coff_symbol;
+
+class COFFAbsoluteAtom : public AbsoluteAtom {
+public:
+  COFFAbsoluteAtom(const File &F, llvm::StringRef N, uint64_t V)
+    : OwningFile(F)
+    , Name(N)
+    , Value(V)
+  {}
+
+  virtual const class File& file() const {
+    return OwningFile;
+  }
+
+  virtual llvm::StringRef name() const {
+    return Name;
+  }
+
+  virtual uint64_t value() const {
+    return Value;
+  }
+
+private:
+  const File &OwningFile;
+  llvm::StringRef Name;
+  uint64_t Value;
+};
+
+class COFFUndefinedAtom : public UndefinedAtom {
+public:
+  COFFUndefinedAtom(const File &F, llvm::StringRef N)
+    : OwningFile(F)
+    , Name(N)
+  {}
+
+  virtual const class File& file() const {
+    return OwningFile;
+  }
+
+  virtual llvm::StringRef name() const {
+    return Name;
+  }
+
+  virtual CanBeNull canBeNull() const {
+    return CanBeNull::canBeNullNever;
+  }
+
+private:
+  const File &OwningFile;
+  llvm::StringRef Name;
+};
+
+class COFFDefinedAtom : public DefinedAtom {
+public:
+  COFFDefinedAtom( const File &F
+                 , llvm::StringRef N
+                 , const llvm::object::coff_symbol *Symb
+                 , const llvm::object::coff_section *Sec
+                 , llvm::ArrayRef<uint8_t> D)
+    : OwningFile(F)
+    , Name(N)
+    , Symbol(Symb)
+    , Section(Sec)
+    , Data(D)
+  {}
+
+  virtual const class File& file() const {
+    return OwningFile;
+  }
+
+  virtual llvm::StringRef name() const {
+    return Name;
+  }
+
+  virtual uint64_t ordinal() const {
+    return reinterpret_cast<intptr_t>(Symbol);
+  }
+
+  virtual uint64_t size() const {
+    return Data.size();
+  }
+
+  virtual Scope scope() const {
+    if (!Symbol)
+      return scopeTranslationUnit;
+    switch (Symbol->StorageClass) {
+    case llvm::COFF::IMAGE_SYM_CLASS_EXTERNAL:
+      return scopeGlobal;
+    case llvm::COFF::IMAGE_SYM_CLASS_STATIC:
+      return scopeTranslationUnit;
+    }
+    llvm_unreachable("Unknown scope!");
+  }
+
+  virtual Interposable interposable() const {
+    return interposeNo;
+  }
+
+  virtual Merge merge() const {
+    return mergeNo;
+  }
+
+  virtual ContentType contentType() const {
+    if (Section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_CODE)
+      return typeCode;
+    if (Section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
+      return typeData;
+    if (Section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+      return typeZeroFill;
+    return typeUnknown;
+  }
+
+  virtual Alignment alignment() const {
+    return Alignment(1);
+  }
+
+  virtual SectionChoice sectionChoice() const {
+    return sectionBasedOnContent;
+  }
+
+  virtual llvm::StringRef customSectionName() const {
+    return "";
+  }
+
+  virtual DeadStripKind deadStrip() const {
+    return deadStripNormal;
+  }
+
+  virtual ContentPermissions permissions() const {
+    if (   Section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ
+        && Section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_WRITE)
+      return permRW_;
+    if (   Section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ
+        && Section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
+      return permR_X;
+    if (Section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ)
+      return permR__;
+    return perm___;
+  }
+
+  virtual bool isThumb() const {
+    return false;
+  }
+
+  virtual bool isAlias() const {
+    return false;
+  }
+
+  virtual llvm::ArrayRef<uint8_t> rawContent() const {
+    return Data;
+  }
+
+  virtual reference_iterator begin() const {
+    return reference_iterator(*this, nullptr);
+  }
+
+  virtual reference_iterator end() const {
+    return reference_iterator(*this, nullptr);
+  }
+
+private:
+  virtual const Reference* derefIterator(const void* iter) const {
+    return nullptr;
+  }
+
+  virtual void incrementIterator(const void*& iter) const {
+
+  }
+
+  const File &OwningFile;
+  llvm::StringRef Name;
+  const llvm::object::coff_symbol *Symbol;
+  const llvm::object::coff_section *Section;
+  llvm::ArrayRef<uint8_t> Data;
+};
+
+class FileCOFF : public File {
+public:
+  FileCOFF(std::unique_ptr<llvm::MemoryBuffer> MB, llvm::error_code &EC)
+    : File(MB->getBufferIdentifier()) {
+    llvm::OwningPtr<llvm::object::Binary> Bin;
+    EC = llvm::object::createBinary(MB.release(), Bin);
+    if (EC)
+      return;
+
+    Obj.reset(llvm::dyn_cast<const llvm::object::COFFObjectFile>(Bin.get()));
+    if (!Obj) {
+      EC = make_error_code(llvm::object::object_error::invalid_file_type);
+      return;
+    }
+    Bin.take();
+
+    const llvm::object::coff_file_header *Header = nullptr;
+    if ((EC = Obj->getHeader(Header)))
+      return;
+
+    // Assign each symbol to the section it's in. If it does not belong to a
+    // section, create an atom for it now.
+    std::map< const llvm::object::coff_section*
+            , std::vector<const llvm::object::coff_symbol*>> SectionSymbols;
+
+    for (uint32_t i = 0, e = Header->NumberOfSymbols; i != e; ++i) {
+      const llvm::object::coff_symbol *Symb;
+      if ((EC = Obj->getSymbol(i, Symb)))
+        return;
+      llvm::StringRef Name;
+      if ((EC = Obj->getSymbolName(Symb, Name)))
+        return;
+      int16_t SectionIndex = Symb->SectionNumber;
+      assert(SectionIndex != llvm::COFF::IMAGE_SYM_DEBUG &&
+        "Cannot atomize IMAGE_SYM_DEBUG!");
+      if (SectionIndex == llvm::COFF::IMAGE_SYM_ABSOLUTE) {
+        // Create an absolute atom.
+        AbsoluteAtoms._atoms.push_back(
+          new (AtomStorage.Allocate<COFFAbsoluteAtom>())
+            COFFAbsoluteAtom(*this, Name, Symb->Value));
+      } else if (SectionIndex == llvm::COFF::IMAGE_SYM_UNDEFINED) {
+        // Create an undefined atom.
+        UndefinedAtoms._atoms.push_back(
+          new (AtomStorage.Allocate<COFFUndefinedAtom>())
+            COFFUndefinedAtom(*this, Name));
+      } else {
+        // This is actually a defined symbol. Add it to its section's list of
+        // symbols.
+        uint8_t SC = Symb->StorageClass;
+        // If Symb->Value actually means section offset.
+        if (   SC == llvm::COFF::IMAGE_SYM_CLASS_EXTERNAL
+            || SC == llvm::COFF::IMAGE_SYM_CLASS_STATIC
+            || SC == llvm::COFF::IMAGE_SYM_CLASS_FUNCTION) {
+          const llvm::object::coff_section *Sec;
+          if ((EC = Obj->getSection(SectionIndex, Sec)))
+            return;
+          assert(Sec && "SectionIndex > 0, Sec must be non-null!");
+          SectionSymbols[Sec].push_back(Symb);
+        } else {
+          llvm::errs() << "Unable to create atom for: " << Name << "\n";
+          EC = llvm::object::object_error::parse_failed;
+          return;
+        }
+      }
+      // Skip aux symbols.
+      i += Symb->NumberOfAuxSymbols;
+    }
+
+    // For each section, sort its symbols by address, then create a defined atom
+    // for each range.
+    for (auto &i : SectionSymbols) {
+      auto &Symbs = i.second;
+      // Sort symbols by position.
+      std::stable_sort(Symbs.begin(), Symbs.end(),
+        // For some reason MSVC fails to allow the lambda in this context with a
+        // "illegal use of local type in type instantiation". MSVC is clearly
+        // wrong here. Force a conversion to function pointer to work around.
+        static_cast<bool(*)(const coff_symbol*, const coff_symbol*)>(
+          [](const coff_symbol *A, const coff_symbol *B) -> bool {
+        return A->Value < B->Value;
+      }));
+
+      if (Symbs.empty()) {
+        // Create an atom for the entire section.
+        llvm::ArrayRef<uint8_t> Data;
+        DefinedAtoms._atoms.push_back(
+          new (AtomStorage.Allocate<COFFDefinedAtom>())
+            COFFDefinedAtom(*this, "", nullptr, i.first, Data));
+        continue;
+      }
+
+      llvm::ArrayRef<uint8_t> SecData;
+      if ((EC = Obj->getSectionContents(i.first, SecData)))
+        return;
+
+      // Create an unnamed atom if the first atom isn't at the start of the
+      // section.
+      if (Symbs[0]->Value != 0) {
+        uint64_t Size = Symbs[0]->Value;
+        llvm::ArrayRef<uint8_t> Data(SecData.data(), Size);
+        DefinedAtoms._atoms.push_back(
+          new (AtomStorage.Allocate<COFFDefinedAtom>())
+            COFFDefinedAtom(*this, "", nullptr, i.first, Data));
+      }
+
+      for (auto si = Symbs.begin(), se = Symbs.end(); si != se; ++si) {
+        // if this is the last symbol, take up the remaining data.
+        llvm::ArrayRef<uint8_t> Data;
+        if (si + 1 == se) {
+          Data = llvm::ArrayRef<uint8_t>( SecData.data() + (*si)->Value
+                                        , SecData.end());
+        } else {
+          Data = llvm::ArrayRef<uint8_t>( SecData.data() + (*si)->Value
+                                        , (*(si + 1))->Value - (*si)->Value);
+        }
+        llvm::StringRef Name;
+        if ((EC = Obj->getSymbolName(*si, Name)))
+          return;
+        DefinedAtoms._atoms.push_back(
+          new (AtomStorage.Allocate<COFFDefinedAtom>())
+            COFFDefinedAtom(*this, Name, *si, i.first, Data));
+      }
+    }
+  }
+
+  virtual void addAtom(const Atom&) {
+    llvm_unreachable("cannot add atoms to native .obj files");
+  }
+
+  virtual const atom_collection<DefinedAtom> &defined() const {
+    return DefinedAtoms;
+  }
+
+  virtual const atom_collection<UndefinedAtom> &undefined() const {
+    return UndefinedAtoms;
+  }
+
+  virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
+    return SharedLibraryAtoms;
+  }
+
+  virtual const atom_collection<AbsoluteAtom> &absolute() const {
+    return AbsoluteAtoms;
+  }
+
+private:
+  std::unique_ptr<const llvm::object::COFFObjectFile> Obj;
+  atom_collection_vector<DefinedAtom>       DefinedAtoms;
+  atom_collection_vector<UndefinedAtom>     UndefinedAtoms;
+  atom_collection_vector<SharedLibraryAtom> SharedLibraryAtoms;
+  atom_collection_vector<AbsoluteAtom>      AbsoluteAtoms;
+  llvm::BumpPtrAllocator AtomStorage;
+};
+
+
+
+class ReaderCOFF : public Reader {
+public:
+  ReaderCOFF(const ReaderOptionsPECOFF &options) : _options(options) {
+  }
+
+  error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
+                       std::vector<std::unique_ptr<File>> &result) {
+    llvm::error_code ec;
+    std::unique_ptr<File> f(new FileCOFF(std::move(mb), ec));
+    if (ec) {
+      return ec;
+    }
+
+    result.push_back(std::move(f));
+    return error_code::success();
+  }
+private:
+  const ReaderOptionsPECOFF &_options;
+};
+
+
+
+Reader* createReaderPECOFF(const ReaderOptionsPECOFF &options) {
+  return new ReaderCOFF(options);
+}
+
+

Added: lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp (added)
+++ lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,35 @@
+//===- lib/ReaderWriter/PECOFF/WriterPECOFF.cpp ---------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/WriterPECOFF.h"
+
+#include "llvm/Support/Debug.h"
+
+
+namespace lld {
+namespace pe_coff {
+
+// define PE/COFF writer class here
+
+
+} // namespace pe_coff
+
+Writer* createWriterPECOFF(const WriterOptionsPECOFF &options) {
+  assert(0 && "PE/COFF support not implemented yet");
+  return nullptr;
+}
+
+WriterOptionsPECOFF::WriterOptionsPECOFF() {
+}
+
+WriterOptionsPECOFF::~WriterOptionsPECOFF() {
+}
+
+} // namespace lld
+

Added: lld/trunk/lib/ReaderWriter/Reader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Reader.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/Reader.cpp (added)
+++ lld/trunk/lib/ReaderWriter/Reader.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,42 @@
+//===- lib/ReaderWriter/Reader.cpp ----------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/Reader.h"
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/system_error.h"
+
+
+namespace lld {
+
+Reader::Reader() {
+}
+
+Reader::~Reader() {
+}
+
+error_code Reader::readFile(StringRef path,
+                                  std::vector<std::unique_ptr<File>> &result) {
+  OwningPtr<llvm::MemoryBuffer> opmb;
+  if ( error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, opmb) )
+    return ec;
+ 
+  std::unique_ptr<MemoryBuffer> mb(opmb.take());
+  return this->parseFile(std::move(mb), result);
+}
+
+
+
+ReaderOptions::ReaderOptions() {
+}
+
+} // namespace lld 
+

Added: lld/trunk/lib/ReaderWriter/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Writer.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/Writer.cpp (added)
+++ lld/trunk/lib/ReaderWriter/Writer.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,25 @@
+//===- lib/ReaderWriter/Writer.cpp ----------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/Writer.h"
+
+
+namespace lld {
+
+Writer::Writer() {
+}
+
+Writer::~Writer() {
+}
+
+WriterOptions::WriterOptions() {
+}
+
+} // namespace lld
+

Added: lld/trunk/lib/ReaderWriter/YAML/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/CMakeLists.txt?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/CMakeLists.txt (added)
+++ lld/trunk/lib/ReaderWriter/YAML/CMakeLists.txt Thu May 31 17:34:00 2012
@@ -0,0 +1,5 @@
+add_lld_library(lldYAML
+  YamlKeyValues.cpp
+  ReaderYAML.cpp
+  WriterYAML.cpp
+  )

Added: lld/trunk/lib/ReaderWriter/YAML/ReaderYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/ReaderYAML.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/ReaderYAML.cpp (added)
+++ lld/trunk/lib/ReaderWriter/YAML/ReaderYAML.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,1264 @@
+//===- lib/ReaderWriter/YAML/ReaderYAML.cpp - Reads YAML object files -----===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/ReaderYAML.h"
+
+#include "lld/Core/AbsoluteAtom.h"
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/Atom.h"
+#include "lld/Core/Error.h"
+#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/SharedLibraryAtom.h"
+#include "lld/Core/UndefinedAtom.h"
+
+#include "llvm/ADT/APInt.h"
+#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/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/system_error.h"
+#include "llvm/Support/YAMLParser.h"
+
+#include <cstring>
+#include <vector>
+
+#include "YamlKeyValues.h"
+
+
+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)
+  {}
+
+  virtual uint64_t offsetInAtom() const {
+    return _offsetInAtom;
+  }
+
+  virtual Kind kind() const {
+    return _kind;
+  }
+
+  virtual void setKind(Kind k) {
+    _kind = k;
+  }
+
+  virtual const Atom *target() const {
+    return _target;
+  }
+
+  virtual Addend addend() const {
+    return _addend;
+  }
+
+  virtual void setAddend(Addend a) {
+    _addend = a;
+  }
+
+  virtual void setTarget(const Atom *newAtom) {
+    _target = newAtom;
+  }
+
+  typedef llvm::yaml::ScalarNode ScalarNode;
+  
+  const Atom *_target;
+  ScalarNode * _targetNameNode;
+  uint64_t    _offsetInAtom;
+  Addend      _addend;
+  Kind        _kind;
+};
+
+
+///
+/// Concrete instance of lld::File created parsing YAML object files.
+///
+class YAMLFile : public ArchiveLibraryFile {
+public:
+  YAMLFile()
+    : ArchiveLibraryFile("<anonymous>")
+    , _lastRefIndex(0)
+    , _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;
+  }
+
+  virtual const atom_collection<DefinedAtom> &defined() const {
+    return _definedAtoms;
+  }
+  virtual const atom_collection<UndefinedAtom> &undefined() const {
+    return _undefinedAtoms;
+  }
+  virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
+    return _sharedLibraryAtoms;
+  }
+  virtual const atom_collection<AbsoluteAtom> &absolute() const {
+    return _absoluteAtoms;
+  }
+
+  virtual void addAtom(const Atom&) {
+    assert(0 && "cannot add atoms to YAML files");
+  }
+
+  // Standard way that archives are searched.
+  virtual const File *find(StringRef name, bool dataSymbolOnly) const;
+
+  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);
+  Atom *findAtom(StringRef name);
+  void addMember(StringRef);
+  void setName(StringRef);
+
+  StringRef copyString(StringRef);
+  
+  struct NameAtomPair {
+                 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<std::unique_ptr<YAMLFile>>    _memberFiles;
+  std::vector<char*>                        _stringCopies;
+  unsigned int                              _lastRefIndex;
+  File::Kind                                _kind;
+};
+
+
+
+///
+/// Concrete instance of lld::DefinedAtom created parsing YAML object files.
+///
+class YAMLDefinedAtom : public DefinedAtom {
+public:
+  YAMLDefinedAtom( uint32_t ord
+          , YAMLFile &file
+          , DefinedAtom::Scope scope
+          , DefinedAtom::ContentType type
+          , DefinedAtom::SectionChoice sectionChoice
+          , DefinedAtom::Interposable interpose
+          , DefinedAtom::Merge merge
+          , DefinedAtom::DeadStripKind deadStrip
+          , DefinedAtom::ContentPermissions perms
+          , bool isThumb
+          , bool isAlias
+          , DefinedAtom::Alignment alignment
+          , StringRef name
+          , StringRef sectionName
+          , uint64_t size
+          , std::vector<uint8_t>& content)
+    : _file(file)
+    , _name(name)
+    , _sectionName(sectionName)
+    , _size(size)
+    , _ord(ord)
+    , _content(content)
+    , _alignment(alignment)
+    , _scope(scope)
+    , _type(type)
+    , _sectionChoice(sectionChoice)
+    , _interpose(interpose)
+    , _merge(merge)
+    , _deadStrip(deadStrip)
+    , _permissions(perms)
+    , _isThumb(isThumb)
+    , _isAlias(isAlias)
+    , _refStartIndex(file._lastRefIndex)
+    , _refEndIndex(file._references.size()) {
+    file._lastRefIndex = _refEndIndex;
+  }
+
+  virtual const class File &file() const {
+    return _file;
+  }
+
+  virtual StringRef name() const {
+    return _name;
+  }
+
+  virtual uint64_t size() const {
+    return _content.empty() ? _size : _content.size();
+  }
+
+  virtual DefinedAtom::Scope scope() const {
+    return _scope;
+  }
+
+  virtual DefinedAtom::Interposable interposable() const {
+    return _interpose;
+  }
+
+  virtual DefinedAtom::Merge merge() const {
+    return _merge;
+  }
+
+  virtual DefinedAtom::ContentType contentType() const {
+    return _type;
+  }
+
+  virtual DefinedAtom::Alignment alignment() const {
+    return _alignment;
+  }
+
+  virtual DefinedAtom::SectionChoice sectionChoice() const {
+    return _sectionChoice;
+  }
+
+  virtual StringRef customSectionName() const {
+    return _sectionName;
+  }
+
+  virtual DefinedAtom::DeadStripKind deadStrip() const {
+    return _deadStrip;
+  }
+
+  virtual DefinedAtom::ContentPermissions permissions() const {
+    return _permissions;
+  }
+
+  virtual bool isThumb() const {
+    return _isThumb;
+  }
+
+  virtual bool isAlias() const {
+    return _isAlias;
+  }
+
+  ArrayRef<uint8_t> rawContent() const {
+    return ArrayRef<uint8_t>(_content);
+  }
+
+  virtual uint64_t ordinal() const {
+    return _ord;
+  }
+
+  DefinedAtom::reference_iterator begin() const {
+    uintptr_t index = _refStartIndex;
+    const void* it = reinterpret_cast<const void*>(index);
+    return reference_iterator(*this, it);
+  }
+
+  DefinedAtom::reference_iterator end() const {
+    uintptr_t index = _refEndIndex;
+    const void* it = reinterpret_cast<const void*>(index);
+    return reference_iterator(*this, it);
+  }
+
+  const Reference* derefIterator(const void* it) const {
+    uintptr_t index = reinterpret_cast<uintptr_t>(it);
+    assert(index >= _refStartIndex);
+    assert(index < _refEndIndex);
+    assert(index < _file._references.size());
+    return &_file._references[index];
+  }
+
+  void incrementIterator(const void*& it) const {
+    uintptr_t index = reinterpret_cast<uintptr_t>(it);
+    ++index;
+    it = reinterpret_cast<const void*>(index);
+  }
+
+  // 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) {
+      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:
+  YAMLFile                   &_file;
+  StringRef                   _name;
+  StringRef                   _sectionName;
+  unsigned long               _size;
+  uint32_t                    _ord;
+  std::vector<uint8_t>        _content;
+  DefinedAtom::Alignment      _alignment;
+  DefinedAtom::Scope          _scope;
+  DefinedAtom::ContentType    _type;
+  DefinedAtom::SectionChoice  _sectionChoice;
+  DefinedAtom::Interposable   _interpose;
+  DefinedAtom::Merge          _merge;
+  DefinedAtom::DeadStripKind  _deadStrip;
+  DefinedAtom::ContentPermissions _permissions;
+  bool                        _isThumb;
+  bool                        _isAlias;
+  unsigned int                _refStartIndex;
+  unsigned int                _refEndIndex;
+};
+
+
+
+///
+/// Concrete instance of lld::UndefinedAtom created parsing YAML object files.
+///
+class YAMLUndefinedAtom : public UndefinedAtom {
+public:
+  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 {
+    return _file;
+  }
+
+  virtual StringRef name() const {
+    return _name;
+  }
+
+  virtual CanBeNull canBeNull() const {
+    return _canBeNull;
+  }
+
+private:
+  YAMLFile                &_file;
+  StringRef                _name;
+  uint32_t                 _ordinal;
+  UndefinedAtom::CanBeNull _canBeNull;
+};
+
+
+
+///
+/// Concrete instance of lld::SharedLibraryAtom created parsing YAML files.
+///
+class YAMLSharedLibraryAtom : public SharedLibraryAtom {
+public:
+  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 {
+    return _file;
+  }
+
+  virtual StringRef name() const {
+    return _name;
+  }
+
+  virtual StringRef loadName() const {
+    return _loadName;
+  }
+
+  virtual bool canBeNullAtRuntime() const {
+    return _canBeNull;
+  }
+
+private:
+  YAMLFile &_file;
+  StringRef _name;
+  uint32_t  _ordinal;
+  StringRef _loadName;
+  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)
+    : _file(f)
+    , _name(name)
+    , _ordinal(ord)
+    , _value(v) {
+  }
+
+  virtual const class File &file() const {
+    return _file;
+  }
+
+  virtual StringRef name() const {
+    return _name;
+  }
+
+  virtual uint64_t value() const {
+    return _value;
+  }
+
+private:
+  YAMLFile &_file;
+  StringRef _name;
+  uint32_t  _ordinal;
+  uint64_t  _value;
+};
+
+
+
+
+//===----------------------------------------------------------------------===//
+//  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);
+    ec = atom->bindTargetReferences(stream);
+    if ( ec )
+      return ec;
+  }
+  return ec;
+}
+
+Atom *YAMLFile::findAtom(StringRef name) {
+  for (auto &ci : _nameToAtomMapping) {
+    if (ci.name == name)
+      return ci.atom;
+  }
+  return nullptr;
+}
+
+void YAMLFile::addDefinedAtom(YAMLDefinedAtom *atom, StringRef refName) {
+  _definedAtoms._atoms.push_back(atom);
+  _nameToAtomMapping.push_back(NameAtomPair(refName, atom));
+}
+
+void YAMLFile::addUndefinedAtom(UndefinedAtom *atom) {
+  _undefinedAtoms._atoms.push_back(atom);
+  _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom));
+}
+
+void YAMLFile::addSharedLibraryAtom(SharedLibraryAtom *atom) {
+  _sharedLibraryAtoms._atoms.push_back(atom);
+  _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom));
+}
+
+void YAMLFile::addAbsoluteAtom(AbsoluteAtom *atom) {
+  _absoluteAtoms._atoms.push_back(atom);
+  _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom));
+}
+
+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() ) {
+      if (name == atom->name())
+        return file.get();
+    }
+  }
+  return nullptr;
+}
+
+
+
+///
+/// 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:
+  YAMLState(const ReaderOptionsYAML &opts, llvm::yaml::Stream *s, YAMLFile *f);
+
+  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 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 moveToState(State s);
+  void returnToState(State s, Node *node);
+  
+  static const Transistion _s_transistions[];
+
+  const ReaderOptionsYAML    &_options;
+  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;
+  std::vector<uint8_t>        _content;
+  DefinedAtom::Alignment      _alignment;
+  Atom::Definition            _definition;
+  DefinedAtom::Scope          _scope;
+  DefinedAtom::ContentType    _type;
+  DefinedAtom::SectionChoice  _sectionChoice;
+  DefinedAtom::Interposable   _interpose;
+  DefinedAtom::Merge          _merge;
+  DefinedAtom::DeadStripKind  _deadStrip;
+  DefinedAtom::ContentPermissions _permissions;
+  bool                        _isThumb;
+  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                            },
+};
+
+
+
+YAMLState::YAMLState(const ReaderOptionsYAML &opts, Stream *stream, 
+                                                                YAMLFile *file)
+  : _options(opts)
+  , _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;
+  _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._targetNameNode= nullptr;
+  _ref._addend        = 0;
+  _ref._offsetInAtom  = 0;
+  _ref._kind          = 0;
+  
+  _hasDefinedAtomAttributes = false;
+  _hasUndefinedAtomAttributes = false;
+  _hasSharedLibraryAtomAttributes = false;
+  _hasAbsoluteAtomAttributes = false;
+}
+
+
+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 YAMLState::setAlign2(StringRef s) {
+  if (StringRef(s).getAsInteger(10, _alignment.powerOf2))
+    _alignment.powerOf2 = 1;
+}
+
+
+// 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_WITH_TYPE("objtxt", 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_WITH_TYPE("objtxt", 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 YAMLState::parseMemberName(ScalarNode *node) {
+   _memberName = extractString(node);
+}
+
+void YAMLState::parseAtomName(ScalarNode *node) {
+   _name = extractString(node);
+}
+
+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;
+}
+
+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);
+  }
+}
+
+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;
+}
+
+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);
+  }
+  _hasDefinedAtomAttributes = true;
+}
+
+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;
+}
+
+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);
+  }
+  _hasDefinedAtomAttributes = true;
+}
+
+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;
+}
+
+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 = _options.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_WITH_TYPE("objtxt", 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);
+      }
+    }
+    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);
+      }
+      else {
+        for (Node &seqEntry : *seq ) {
+          this->parse(&seqEntry, StringRef("<any-seq-item>"));
+          if ( _error )
+            break;
+        }
+      }
+    }
+    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;
+        }
+      }
+    }
+    else {
+      _stream->printError(node, "unexpected node type");
+      _error = make_error_code(yaml_reader_error::illegal_value);
+    }
+    this->returnToState(savedState, node);
+    return;
+  }
+  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 parseFile(std::unique_ptr<MemoryBuffer> &mb,
+                      const ReaderOptionsYAML &options,
+                      std::vector<std::unique_ptr<File>> &result) {
+  llvm::SourceMgr       srcMgr;
+  llvm::yaml::Stream    stream(mb->getBuffer(), srcMgr);
+
+  for (llvm::yaml::Document &d : stream) {
+    std::unique_ptr<yaml::YAMLFile> curFile(new yaml::YAMLFile);
+    if (llvm::isa<llvm::yaml::NullNode>(d.getRoot()))
+      continue; // Empty files are allowed.
+    yaml::YAMLState yamlState(options, &stream, curFile.get());
+    yamlState.parse(d.getRoot(), StringRef("<root>"));
+
+    if ( stream.failed() ) 
+      return make_error_code(yaml_reader_error::illegal_value);
+    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);
+}
+
+
+
+} // namespace yaml
+
+
+
+class ReaderYAML: public Reader {
+public:
+  ReaderYAML(const ReaderOptionsYAML &options) : _options(options) {
+  }
+
+  error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
+                       std::vector<std::unique_ptr<File>> &result) {
+    return lld::yaml::parseFile(mb, _options, result);
+  }
+
+private:
+  const ReaderOptionsYAML &_options;
+};
+
+
+
+Reader* createReaderYAML(const ReaderOptionsYAML &options) {
+  return new ReaderYAML(options);
+}
+
+ReaderOptionsYAML::ReaderOptionsYAML() {
+}
+
+ReaderOptionsYAML::~ReaderOptionsYAML() {
+}
+
+
+
+
+} // namespace lld

Added: lld/trunk/lib/ReaderWriter/YAML/WriterYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/WriterYAML.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/WriterYAML.cpp (added)
+++ lld/trunk/lib/ReaderWriter/YAML/WriterYAML.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,498 @@
+//===- lib/ReaderWriter/YAML/WriterYAML.cpp - Writes YAML object files ----===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/WriterYAML.h"
+
+#include "lld/Core/Atom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+#include "YamlKeyValues.h"
+
+#include <vector>
+
+namespace lld {
+namespace yaml {
+
+///
+/// In most cases, atoms names are unambiguous, so references can just
+/// use the atom name as the target (e.g. target: foo).  But in a few
+/// cases that does not work, so ref-names are added.  These are labels
+/// used only in yaml.  The labels do not exist in the Atom model.
+///
+/// One need for ref-names are when atoms have no user supplied name
+/// (e.g. c-string literal).  Another case is when two object files with
+/// identically named static functions are merged (ld -r) into one object file.
+/// In that case referencing the function by name is ambiguous, so a unique
+/// ref-name is added.
+///
+class RefNameBuilder {
+public:
+  RefNameBuilder(const File& file)
+                : _collisionCount(0), _unnamedCounter(0) {
+    // visit all atoms
+    for( const DefinedAtom *atom : file.defined() ) {
+      // Build map of atoms names to detect duplicates
+      if ( ! atom->name().empty() )
+        buildDuplicateNameMap(*atom);
+
+      // Find references to unnamed atoms and create ref-names for them.
+      for (const Reference *ref : *atom) {
+        // create refname for any unnamed reference target
+        const Atom *target = ref->target();
+        if ( (target != nullptr) && target->name().empty() ) {
+          std::string Storage;
+          llvm::raw_string_ostream Buffer(Storage);
+          Buffer << llvm::format("L%03d", _unnamedCounter++);
+          _refNames[target] = Buffer.str();
+        }
+      }
+    }
+    for( const UndefinedAtom *undefAtom : file.undefined() ) {
+      buildDuplicateNameMap(*undefAtom);
+    }
+    for( const SharedLibraryAtom *shlibAtom : file.sharedLibrary() ) {
+      buildDuplicateNameMap(*shlibAtom);
+    }
+    for( const AbsoluteAtom *absAtom : file.absolute() ) {
+      buildDuplicateNameMap(*absAtom);
+    }
+
+
+  }
+
+  void buildDuplicateNameMap(const Atom& atom) {
+    assert(!atom.name().empty());
+    NameToAtom::iterator pos = _nameMap.find(atom.name());
+    if ( pos != _nameMap.end() ) {
+      // Found name collision, give each a unique ref-name.
+      std::string Storage;
+      llvm::raw_string_ostream Buffer(Storage);
+      Buffer << atom.name() << llvm::format(".%03d", ++_collisionCount);
+      _refNames[&atom] = Buffer.str();
+      const Atom* prevAtom = pos->second;
+      AtomToRefName::iterator pos2 = _refNames.find(prevAtom);
+      if ( pos2 == _refNames.end() ) {
+        // only create ref-name for previous if none already created
+        Buffer << prevAtom->name() << llvm::format(".%03d", ++_collisionCount);
+        _refNames[prevAtom] = Buffer.str();
+      }
+    }
+    else {
+      // First time we've seen this name, just add it to map.
+      _nameMap[atom.name()] = &atom;
+    }
+  }
+
+  bool hasRefName(const Atom* atom) {
+     return _refNames.count(atom);
+  }
+
+  StringRef refName(const Atom *atom) {
+     return _refNames.find(atom)->second;
+  }
+
+private:
+  typedef llvm::StringMap<const Atom*> NameToAtom;
+  typedef llvm::DenseMap<const Atom*, std::string> AtomToRefName;
+
+  unsigned int      _collisionCount;
+  unsigned int      _unnamedCounter;
+  NameToAtom        _nameMap;
+  AtomToRefName     _refNames;
+};
+
+
+///
+/// Helper class for writeObjectText() to write out atoms in yaml format.
+///
+class AtomWriter {
+public:
+  AtomWriter(const File& file, const WriterOptionsYAML &options, 
+                                                            RefNameBuilder& rnb)
+    : _file(file), _options(options), _rnb(rnb), _firstAtom(true) { }
+
+
+  void write(raw_ostream &out) {
+    // write header
+    out << "---\n";
+
+    // visit all atoms
+    for( const DefinedAtom *atom : _file.defined() ) {
+      writeDefinedAtom(*atom, out);
+    }
+    for( const UndefinedAtom *undefAtom : _file.undefined() ) {
+      writeUndefinedAtom(*undefAtom, out);
+    }
+    for( const SharedLibraryAtom *shlibAtom : _file.sharedLibrary() ) {
+      writeSharedLibraryAtom(*shlibAtom, out);
+    }
+    for( const AbsoluteAtom *absAtom : _file.absolute() ) {
+      writeAbsoluteAtom(*absAtom, out);
+    }
+
+    out << "...\n";
+  }
+
+
+  void writeDefinedAtom(const DefinedAtom &atom, raw_ostream &out) {
+    if ( _firstAtom ) {
+      out << "atoms:\n";
+      _firstAtom = false;
+    }
+    else {
+      // add blank line between atoms for readability
+      out << "\n";
+    }
+
+    bool hasDash = false;
+    if ( !atom.name().empty() ) {
+      out   << "    - "
+            << "name:"
+            << spacePadding(strlen("name"))
+            << atom.name()
+            << "\n";
+      hasDash = true;
+    }
+
+    if ( _rnb.hasRefName(&atom) ) {
+      out   << (hasDash ? "      " : "    - ")
+            << "ref-name:"
+            << spacePadding(strlen("ref-name"))
+            << _rnb.refName(&atom)
+            << "\n";
+      hasDash = true;
+    }
+
+    if ( atom.definition() != KeyValues::definitionDefault ) {
+      out   << (hasDash ? "      " : "    - ")
+            << "definition:"
+            << spacePadding(strlen("definition"))
+            << KeyValues::definition(atom.definition())
+            << "\n";
+      hasDash = true;
+    }
+
+    if ( atom.scope() != KeyValues::scopeDefault ) {
+      out   << (hasDash ? "      " : "    - ")
+            << "scope:"
+            << spacePadding(strlen("scope"))
+            << KeyValues::scope(atom.scope())
+            << "\n";
+      hasDash = true;
+    }
+
+     if ( atom.interposable() != KeyValues::interposableDefault ) {
+      out   << "      "
+            << "interposable:"
+            << spacePadding(strlen("interposable"))
+            << KeyValues::interposable(atom.interposable())
+            << "\n";
+    }
+
+    if ( atom.merge() != KeyValues::mergeDefault ) {
+      out   << "      "
+            << "merge:"
+            << spacePadding(strlen("merge"))
+            << KeyValues::merge(atom.merge())
+            << "\n";
+    }
+
+    if ( atom.contentType() != KeyValues::contentTypeDefault ) {
+      out   << "      "
+            << "type:"
+            << spacePadding(strlen("type"))
+            << KeyValues::contentType(atom.contentType())
+            << "\n";
+    }
+
+    if ( atom.deadStrip() != KeyValues::deadStripKindDefault ) {
+      out   << "      "
+            << "dead-strip:"
+            << spacePadding(strlen("dead-strip"))
+            << KeyValues::deadStripKind(atom.deadStrip())
+            << "\n";
+    }
+
+    if ( atom.sectionChoice() != KeyValues::sectionChoiceDefault ) {
+      out   << "      "
+            << "section-choice:"
+            << spacePadding(strlen("section-choice"))
+            << KeyValues::sectionChoice(atom.sectionChoice())
+            << "\n";
+      assert( ! atom.customSectionName().empty() );
+      out   << "      "
+            << "section-name:"
+            << spacePadding(strlen("section-name"))
+            << atom.customSectionName()
+            << "\n";
+    }
+
+    if ( atom.isThumb() != KeyValues::isThumbDefault ) {
+      out   << "      "
+            << "is-thumb:"
+            << spacePadding(strlen("is-thumb"))
+            << KeyValues::isThumb(atom.isThumb())
+            << "\n";
+    }
+
+    if ( atom.isAlias() != KeyValues::isAliasDefault ) {
+      out   << "      "
+            << "is-alias:"
+            << spacePadding(strlen("is-alias"))
+            << KeyValues::isAlias(atom.isAlias())
+            << "\n";
+    }
+
+    if ( (atom.contentType() != DefinedAtom::typeZeroFill)
+                                   && (atom.size() != 0) ) {
+      out   << "      "
+            << "content:"
+            << spacePadding(strlen("content"))
+            << "[ ";
+      ArrayRef<uint8_t> arr = atom.rawContent();
+      bool needComma = false;
+      for (unsigned int i=0; i < arr.size(); ++i) {
+        if ( needComma )
+          out  << ", ";
+        if ( ((i % 12) == 0) && (i != 0) ) {
+          out << "\n                           ";
+        }
+        out  << hexdigit(arr[i] >> 4);
+        out  << hexdigit(arr[i] & 0x0F);
+        needComma = true;
+      }
+      out  << " ]\n";
+    }
+
+    bool wroteFirstFixup = false;
+    for (const Reference *ref : atom) {
+      if ( !wroteFirstFixup ) {
+        out  << "      fixups:\n";
+        wroteFirstFixup = true;
+      }
+      out   << "      - "
+            << "offset:"
+            << spacePadding(strlen("offset"))
+            << ref->offsetInAtom()
+            << "\n";
+      out   << "        "
+            << "kind:"
+            << spacePadding(strlen("kind"))
+            << _options.kindToString(ref->kind())
+            << "\n";
+      const Atom* target = ref->target();
+      if (target != nullptr) {
+        StringRef refName = target->name();
+        if ( _rnb.hasRefName(target) )
+          refName = _rnb.refName(target);
+        assert(!refName.empty());
+        out   << "        "
+              << "target:"
+              << spacePadding(strlen("target"))
+              << refName
+              << "\n";
+      }
+      if ( ref->addend() != 0 ) {
+        out   << "        "
+              << "addend:"
+              << spacePadding(strlen("addend"))
+              << ref->addend()
+              << "\n";
+      }
+    }
+  }
+
+
+  void writeUndefinedAtom(const UndefinedAtom &atom, raw_ostream &out) {
+    if ( _firstAtom ) {
+      out  << "atoms:\n";
+      _firstAtom = false;
+    }
+    else {
+      // add blank line between atoms for readability
+      out  << "\n";
+    }
+
+    out   << "    - "
+          << "name:"
+          << spacePadding(strlen("name"))
+          << atom.name()
+          << "\n";
+
+    out   << "      "
+          << "definition:"
+          << spacePadding(strlen("definition"))
+          << KeyValues::definition(atom.definition())
+          << "\n";
+
+    if ( atom.canBeNull() != KeyValues::canBeNullDefault ) {
+      out   << "      "
+            << "can-be-null:"
+            << spacePadding(strlen("can-be-null"))
+            << KeyValues::canBeNull(atom.canBeNull())
+            << "\n";
+    }
+  }
+
+  void writeSharedLibraryAtom(const SharedLibraryAtom &atom, raw_ostream &out) {
+    if ( _firstAtom ) {
+      out  << "atoms:\n";
+      _firstAtom = false;
+    }
+    else {
+      // add blank line between atoms for readability
+      out  << "\n";
+    }
+
+    out   << "    - "
+          << "name:"
+          << spacePadding(strlen("name"))
+          << atom.name()
+          << "\n";
+
+    out   << "      "
+          << "definition:"
+          << spacePadding(strlen("definition"))
+          << KeyValues::definition(atom.definition())
+          << "\n";
+
+    if ( !atom.loadName().empty() ) {
+      out   << "      "
+            << "load-name:"
+            << spacePadding(strlen("load-name"))
+            << atom.loadName()
+            << "\n";
+    }
+
+    if ( atom.canBeNullAtRuntime() ) {
+      out   << "      "
+            << "can-be-null:"
+            << spacePadding(strlen("can-be-null"))
+            << KeyValues::canBeNull(UndefinedAtom::canBeNullAtRuntime)
+            << "\n";
+    }
+   }
+
+  void writeAbsoluteAtom(const AbsoluteAtom &atom, raw_ostream &out) {
+     if ( _firstAtom ) {
+      out << "atoms:\n";
+      _firstAtom = false;
+    }
+    else {
+      // add blank line between atoms for readability
+      out << "\n";
+    }
+
+    out   << "    - "
+          << "name:"
+          << spacePadding(strlen("name"))
+          << atom.name()
+          << "\n";
+
+    out   << "      "
+          << "definition:"
+          << spacePadding(strlen("definition"))
+          << KeyValues::definition(atom.definition())
+          << "\n";
+
+    out   << "      "
+          << "value:"
+          << spacePadding(strlen("value"))
+          << "0x";
+     out.write_hex(atom.value());
+     out << "\n";
+   }
+
+
+private:
+  // return a string of the correct number of spaces to align value
+  const char* spacePadding(size_t keyLen) {
+    const char* spaces = "                  ";
+    assert(strlen(spaces) > keyLen);
+    return &spaces[keyLen];
+  }
+
+  char hexdigit(uint8_t nibble) {
+    if ( nibble < 0x0A )
+      return '0' + nibble;
+    else
+      return 'A' + nibble - 0x0A;
+  }
+
+  const File                      &_file;
+  const WriterOptionsYAML         &_options;
+  RefNameBuilder                  &_rnb;
+  bool                             _firstAtom;
+};
+
+
+
+
+class Writer : public lld::Writer {
+public:
+  Writer(const WriterOptionsYAML &options) : _options(options) {
+  }
+  
+  virtual error_code writeFile(const lld::File &file, StringRef path) {
+    // Create stream to path.
+    std::string errorInfo;
+    llvm::raw_fd_ostream out(path.data(), errorInfo);
+    if (!errorInfo.empty())
+      return llvm::make_error_code(llvm::errc::no_such_file_or_directory);
+
+    // Figure what ref-name labels are needed.
+    RefNameBuilder rnb(file);
+
+    // Write out all atoms.
+    AtomWriter writer(file, _options, rnb);
+    writer.write(out);
+    return error_code::success();
+  }
+  
+  virtual StubsPass *stubPass() {
+    return _options.stubPass();
+  }
+  
+  virtual GOTPass *gotPass() {
+    return _options.gotPass();
+  }
+  
+  
+private:
+  const WriterOptionsYAML &_options;
+};
+
+
+} // namespace yaml
+
+
+Writer* createWriterYAML(const WriterOptionsYAML &options) {
+  return new lld::yaml::Writer(options);
+}
+
+WriterOptionsYAML::WriterOptionsYAML() {
+}
+
+WriterOptionsYAML::~WriterOptionsYAML() {
+}
+
+
+} // namespace lld

Added: lld/trunk/lib/ReaderWriter/YAML/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/YamlKeyValues.cpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/YamlKeyValues.cpp (added)
+++ lld/trunk/lib/ReaderWriter/YAML/YamlKeyValues.cpp Thu May 31 17:34:00 2012
@@ -0,0 +1,432 @@
+//===- lib/ReaderWriter/YAML/YamlKeyValues.cpp ----------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "YamlKeyValues.h"
+
+#include "llvm/Support/ErrorHandling.h"
+#include "lld/Core/File.h"
+
+#include <cstring>
+
+namespace lld {
+namespace yaml {
+
+
+const DefinedAtom::Definition         KeyValues::definitionDefault = Atom::definitionRegular;
+const DefinedAtom::Scope              KeyValues::scopeDefault = DefinedAtom::scopeTranslationUnit;
+const DefinedAtom::ContentType        KeyValues::contentTypeDefault = DefinedAtom::typeData;
+const DefinedAtom::DeadStripKind      KeyValues::deadStripKindDefault = DefinedAtom::deadStripNormal;
+const DefinedAtom::SectionChoice      KeyValues::sectionChoiceDefault = DefinedAtom::sectionBasedOnContent;
+const DefinedAtom::Interposable       KeyValues::interposableDefault = DefinedAtom::interposeNo;
+const DefinedAtom::Merge              KeyValues::mergeDefault = DefinedAtom::mergeNo;
+const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAtom::permR__;
+const bool                            KeyValues::isThumbDefault = false;
+const bool                            KeyValues::isAliasDefault = false;
+const UndefinedAtom::CanBeNull        KeyValues::canBeNullDefault = UndefinedAtom::canBeNullNever;
+
+
+
+
+struct DefinitionMapping {
+  const char*       string;
+  Atom::Definition  value;
+};
+
+static const DefinitionMapping defMappings[] = {
+  { "regular",        Atom::definitionRegular },
+  { "absolute",       Atom::definitionAbsolute },
+  { "undefined",      Atom::definitionUndefined },
+  { "shared-library", Atom::definitionSharedLibrary },
+  { nullptr,          Atom::definitionRegular }
+};
+
+bool KeyValues::definition(StringRef s, Atom::Definition &out)
+{
+  for (const DefinitionMapping* p = defMappings; p->string != nullptr; ++p) {
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
+  }
+  return true;
+}
+
+const char* KeyValues::definition(Atom::Definition s) {
+  for (const DefinitionMapping* p = defMappings; p->string != nullptr; ++p) {
+    if ( p->value == s )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad definition value");
+}
+
+
+
+
+
+struct ScopeMapping {
+  const char* string;
+  DefinedAtom::Scope value;
+};
+
+static const ScopeMapping scopeMappings[] = {
+  { "global", DefinedAtom::scopeGlobal },
+  { "hidden", DefinedAtom::scopeLinkageUnit },
+  { "static", DefinedAtom::scopeTranslationUnit },
+  { nullptr,  DefinedAtom::scopeGlobal }
+};
+
+bool KeyValues::scope(StringRef s, DefinedAtom::Scope &out)
+{
+  for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) {
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
+  }
+  return true;
+}
+
+const char* KeyValues::scope(DefinedAtom::Scope s) {
+  for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) {
+    if ( p->value == s )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad scope value");
+}
+
+
+
+
+
+
+
+
+struct ContentTypeMapping {
+  const char*       string;
+  DefinedAtom::ContentType  value;
+};
+
+static const ContentTypeMapping typeMappings[] = {
+  { "unknown",        DefinedAtom::typeUnknown },
+  { "code",           DefinedAtom::typeCode },
+  { "stub",           DefinedAtom::typeStub },
+  { "stub-helper",    DefinedAtom::typeStubHelper },
+  { "resolver",       DefinedAtom::typeResolver },
+  { "constant",       DefinedAtom::typeConstant },
+  { "c-string",       DefinedAtom::typeCString },
+  { "utf16-string",   DefinedAtom::typeUTF16String },
+  { "CFI",            DefinedAtom::typeCFI },
+  { "LSDA",           DefinedAtom::typeLSDA },
+  { "literal-4",      DefinedAtom::typeLiteral4 },
+  { "literal-8",      DefinedAtom::typeLiteral8 },
+  { "literal-16",     DefinedAtom::typeLiteral16 },
+  { "data",           DefinedAtom::typeData },
+  { "zero-fill",      DefinedAtom::typeZeroFill },
+  { "cf-string",      DefinedAtom::typeCFString },
+  { "got",            DefinedAtom::typeGOT },
+  { "lazy-pointer",   DefinedAtom::typeLazyPointer },
+  { "initializer-ptr",DefinedAtom::typeInitializerPtr },
+  { "terminator-ptr", DefinedAtom::typeTerminatorPtr },
+  { "c-string-ptr",   DefinedAtom::typeCStringPtr },
+  { "objc1-class",    DefinedAtom::typeObjC1Class },
+  { "objc1-class-ptr",DefinedAtom::typeObjCClassPtr },
+  { "objc2-cat-ptr",  DefinedAtom::typeObjC2CategoryList },
+  { "tlv-thunk",      DefinedAtom::typeThunkTLV },
+  { "tlv-data",       DefinedAtom::typeTLVInitialData },
+  { "tlv-zero-fill",  DefinedAtom::typeTLVInitialZeroFill },
+  { "tlv-init-ptr",   DefinedAtom::typeTLVInitializerPtr },
+  { nullptr,          DefinedAtom::typeUnknown }
+};
+
+bool KeyValues::contentType(StringRef s, DefinedAtom::ContentType &out)
+{
+  for (const ContentTypeMapping* p = typeMappings; p->string != nullptr; ++p) {
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
+  }
+  return true;
+}
+
+const char* KeyValues::contentType(DefinedAtom::ContentType s) {
+  for (const ContentTypeMapping* p = typeMappings; p->string != nullptr; ++p) {
+    if ( p->value == s )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad content type value");
+}
+
+
+
+
+
+
+
+struct DeadStripMapping {
+  const char*           string;
+  DefinedAtom::DeadStripKind   value;
+};
+
+static const DeadStripMapping dsMappings[] = {
+  { "normal",         DefinedAtom::deadStripNormal },
+  { "never",          DefinedAtom::deadStripNever },
+  { "always",         DefinedAtom::deadStripAlways },
+  { nullptr,          DefinedAtom::deadStripNormal }
+};
+
+bool KeyValues::deadStripKind(StringRef s, DefinedAtom::DeadStripKind &out)
+{
+  for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) {
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
+  }
+  return true;
+}
+
+const char* KeyValues::deadStripKind(DefinedAtom::DeadStripKind dsk) {
+  for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) {
+    if ( p->value == dsk )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad dead strip value");
+}
+
+
+
+
+
+struct InterposableMapping {
+  const char*           string;
+  DefinedAtom::Interposable   value;
+};
+
+static const InterposableMapping interMappings[] = {
+  { "no",           DefinedAtom::interposeNo },
+  { "yes",          DefinedAtom::interposeYes },
+  { "yesAndWeak",   DefinedAtom::interposeYesAndRuntimeWeak },
+  { nullptr,        DefinedAtom::interposeNo }
+};
+
+bool KeyValues::interposable(StringRef s, DefinedAtom::Interposable &out)
+{
+  for (const InterposableMapping* p = interMappings; p->string != nullptr; ++p){
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
+  }
+  return true;
+}
+
+const char* KeyValues::interposable(DefinedAtom::Interposable in) {
+  for (const InterposableMapping* p = interMappings; p->string != nullptr; ++p){
+    if ( p->value == in )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad interposable value");
+}
+
+
+
+
+
+
+struct MergeMapping {
+  const char*          string;
+  DefinedAtom::Merge   value;
+};
+
+static const MergeMapping mergeMappings[] = {
+  { "no",             DefinedAtom::mergeNo },
+  { "asTentative",    DefinedAtom::mergeAsTentative },
+  { "asWeak",         DefinedAtom::mergeAsWeak },
+  { "asAddressedWeak",DefinedAtom::mergeAsWeakAndAddressUsed },
+  { nullptr,          DefinedAtom::mergeNo }
+};
+
+bool KeyValues::merge(StringRef s, DefinedAtom::Merge& out)
+{
+  for (const MergeMapping* p = mergeMappings; p->string != nullptr; ++p) {
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
+  }
+  return true;
+}
+
+const char* KeyValues::merge(DefinedAtom::Merge in) {
+  for (const MergeMapping* p = mergeMappings; p->string != nullptr; ++p) {
+    if ( p->value == in )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad merge value");
+}
+
+
+
+
+
+
+struct SectionChoiceMapping {
+  const char*                 string;
+  DefinedAtom::SectionChoice  value;
+};
+
+static const SectionChoiceMapping sectMappings[] = {
+  { "content",         DefinedAtom::sectionBasedOnContent },
+  { "custom",          DefinedAtom::sectionCustomPreferred },
+  { "custom-required", DefinedAtom::sectionCustomRequired },
+  { nullptr,           DefinedAtom::sectionBasedOnContent }
+};
+
+bool KeyValues::sectionChoice(StringRef s, DefinedAtom::SectionChoice &out)
+{
+  for (const SectionChoiceMapping* p = sectMappings; p->string != nullptr; ++p){
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
+  }
+  return true;
+}
+
+const char* KeyValues::sectionChoice(DefinedAtom::SectionChoice s) {
+  for (const SectionChoiceMapping* p = sectMappings; p->string != nullptr; ++p){
+    if ( p->value == s )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad dead strip value");
+}
+
+
+
+
+
+
+
+struct PermissionsMapping {
+  const char*                      string;
+  DefinedAtom::ContentPermissions  value;
+};
+
+static const PermissionsMapping permMappings[] = {
+  { "---",    DefinedAtom::perm___  },
+  { "r--",    DefinedAtom::permR__  },
+  { "r-x",    DefinedAtom::permR_X  },
+  { "rw-",    DefinedAtom::permRW_  },
+  { "rw-l",   DefinedAtom::permRW_L },
+  { nullptr,  DefinedAtom::perm___  }
+};
+
+bool KeyValues::permissions(StringRef s, DefinedAtom::ContentPermissions &out)
+{
+  for (const PermissionsMapping* p = permMappings; p->string != nullptr; ++p) {
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
+  }
+  return true;
+}
+
+const char* KeyValues::permissions(DefinedAtom::ContentPermissions s) {
+  for (const PermissionsMapping* p = permMappings; p->string != nullptr; ++p) {
+    if ( p->value == s )
+      return p->string;
+  }
+  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";
+}
+
+
+
+
+struct CanBeNullMapping {
+  const char*               string;
+  UndefinedAtom::CanBeNull  value;
+};
+
+static const CanBeNullMapping cbnMappings[] = {
+  { "never",         UndefinedAtom::canBeNullNever },
+  { "at-runtime",    UndefinedAtom::canBeNullAtRuntime },
+  { "at-buildtime",  UndefinedAtom::canBeNullAtBuildtime },
+  { nullptr,         UndefinedAtom::canBeNullNever }
+};
+
+
+bool KeyValues::canBeNull(StringRef s, UndefinedAtom::CanBeNull &out)
+{
+  for (const CanBeNullMapping* p = cbnMappings; p->string != nullptr; ++p) {
+    if (s == p->string) {
+      out = p->value;
+      return false;
+    }
+  }
+  return true;
+}
+
+const char* KeyValues::canBeNull(UndefinedAtom::CanBeNull c) {
+  for (const CanBeNullMapping* p = cbnMappings; p->string != nullptr; ++p) {
+    if ( p->value == c )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad can-be-null value");
+}
+
+
+
+
+
+
+
+} // namespace yaml
+} // namespace lld

Added: lld/trunk/lib/ReaderWriter/YAML/YamlKeyValues.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/YamlKeyValues.h?rev=157774&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/YamlKeyValues.h (added)
+++ lld/trunk/lib/ReaderWriter/YAML/YamlKeyValues.h Thu May 31 17:34:00 2012
@@ -0,0 +1,84 @@
+//===- lib/ReaderWriter/YAML/YamlKeyValues.h ------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_YAML_KEY_VALUES_H_
+#define LLD_CORE_YAML_KEY_VALUES_H_
+
+#include "lld/Core/Atom.h"
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/File.h"
+
+namespace lld {
+namespace yaml {
+
+class KeyValues {
+public:
+
+  static const char* const                definitionKeyword;
+  static const Atom::Definition           definitionDefault;
+  static bool                             definition(StringRef, Atom::Definition&);
+  static const char*                      definition(Atom::Definition);
+
+  static const char* const                scopeKeyword;
+  static const DefinedAtom::Scope         scopeDefault;
+  static bool                             scope(StringRef, DefinedAtom::Scope&);
+  static const char*                      scope(DefinedAtom::Scope);
+
+  static const char* const                contentTypeKeyword;
+  static const DefinedAtom::ContentType   contentTypeDefault;
+  static bool                             contentType(StringRef, DefinedAtom::ContentType&);
+  static const char*                      contentType(DefinedAtom::ContentType);
+
+  static const char* const                deadStripKindKeyword;
+  static const DefinedAtom::DeadStripKind deadStripKindDefault;
+  static bool                             deadStripKind(StringRef, DefinedAtom::DeadStripKind&);
+  static const char*                      deadStripKind(DefinedAtom::DeadStripKind);
+
+  static const char* const                sectionChoiceKeyword;
+  static const DefinedAtom::SectionChoice sectionChoiceDefault;
+  static bool                             sectionChoice(StringRef,  DefinedAtom::SectionChoice&);
+  static const char*                      sectionChoice(DefinedAtom::SectionChoice);
+
+  static const char* const                interposableKeyword;
+  static const DefinedAtom::Interposable  interposableDefault;
+  static bool                             interposable(StringRef, DefinedAtom::Interposable&);
+  static const char*                      interposable(DefinedAtom::Interposable);
+
+  static const char* const                mergeKeyword;
+  static const DefinedAtom::Merge         mergeDefault;
+  static bool                             merge(StringRef, DefinedAtom::Merge&);
+  static const char*                      merge(DefinedAtom::Merge);
+
+  static const char* const                      permissionsKeyword;
+  static const DefinedAtom::ContentPermissions  permissionsDefault;
+  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 bool                             canBeNull(StringRef, UndefinedAtom::CanBeNull&);
+  static const char*                      canBeNull(UndefinedAtom::CanBeNull);
+
+};
+
+} // namespace yaml
+} // namespace lld
+
+#endif // LLD_CORE_YAML_KEY_VALUES_H_

Modified: lld/trunk/tools/lld-core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/CMakeLists.txt?rev=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/CMakeLists.txt (original)
+++ lld/trunk/tools/lld-core/CMakeLists.txt Thu May 31 17:34:00 2012
@@ -1,9 +1,13 @@
 set(LLVM_USED_LIBS
   lldCore
-  lldReader
   lldPasses
-  lldDarwinPlatform
-  )
+  lldMachO
+  lldPECOFF
+  lldELF
+  lldNative
+  lldYAML
+  lldReaderWriter
+ )
 
 set(LLVM_LINK_COMPONENTS
   support

Added: lld/trunk/tools/lld-core/TestingHelpers.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/TestingHelpers.hpp?rev=157774&view=auto
==============================================================================
--- lld/trunk/tools/lld-core/TestingHelpers.hpp (added)
+++ lld/trunk/tools/lld-core/TestingHelpers.hpp Thu May 31 17:34:00 2012
@@ -0,0 +1,403 @@
+//===- tools/lld/TestingWriter.hpp - Linker Core Test Support -------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_TOOLS_TESTING_HELPERS_H_
+#define LLD_TOOLS_TESTING_HELPERS_H_
+
+#include "lld/Core/Atom.h"
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Pass.h"
+#include "lld/Core/Resolver.h"
+#include "lld/ReaderWriter/WriterYAML.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
+
+#include <vector>
+
+using namespace lld;
+
+//
+// Simple atom created by the stubs pass.
+//
+class TestingStubAtom : public DefinedAtom {
+public:
+        TestingStubAtom(const File& f, const Atom& shlib) :
+                        _file(f), _shlib(shlib) {
+          static uint32_t lastOrdinal = 0;
+          _ordinal = lastOrdinal++; 
+        }
+
+  virtual const File& file() const {
+    return _file;
+  }
+
+  virtual StringRef name() const {
+    return StringRef();
+  }
+  
+  virtual uint64_t ordinal() const {
+    return _ordinal;
+  }
+
+  virtual uint64_t size() const {
+    return 0;
+  }
+
+  virtual Scope scope() const {
+    return DefinedAtom::scopeLinkageUnit;
+  }
+  
+  virtual Interposable interposable() const {
+    return DefinedAtom::interposeNo;
+  }
+  
+  virtual Merge merge() const {
+    return DefinedAtom::mergeNo;
+  }
+  
+  virtual ContentType contentType() const  {
+    return DefinedAtom::typeStub;
+  }
+
+  virtual Alignment alignment() const {
+    return Alignment(0,0);
+  }
+  
+  virtual SectionChoice sectionChoice() const {
+    return DefinedAtom::sectionBasedOnContent;
+  }
+    
+  virtual StringRef customSectionName() const {
+    return StringRef();
+  }
+  virtual DeadStripKind deadStrip() const {
+    return DefinedAtom::deadStripNormal;
+  }
+    
+  virtual ContentPermissions permissions() const  {
+    return DefinedAtom::permR_X;
+  }
+  
+  virtual bool isThumb() const {
+    return false;
+  }
+    
+  virtual bool isAlias() const {
+    return false;
+  }
+  
+  virtual ArrayRef<uint8_t> rawContent() const {
+    return ArrayRef<uint8_t>();
+  }
+  
+  virtual reference_iterator begin() const {
+    return reference_iterator(*this, nullptr);
+  }
+  
+  virtual reference_iterator end() const {
+    return reference_iterator(*this, nullptr);
+  }
+  
+  virtual const Reference* derefIterator(const void* iter) const {
+    return nullptr;
+  }
+  
+  virtual void incrementIterator(const void*& iter) const {
+  
+  }
+  
+private:
+  const File&               _file;
+  const Atom&               _shlib;
+  uint32_t                  _ordinal;
+};
+
+
+
+
+//
+// Simple atom created by the GOT pass.
+//
+class TestingGOTAtom : public DefinedAtom {
+public:
+        TestingGOTAtom(const File& f, const Atom& shlib) :
+                        _file(f), _shlib(shlib) {
+          static uint32_t lastOrdinal = 0;
+          _ordinal = lastOrdinal++; 
+        }
+
+  virtual const File& file() const {
+    return _file;
+  }
+
+  virtual StringRef name() const {
+    return StringRef();
+  }
+  
+  virtual uint64_t ordinal() const {
+    return _ordinal;
+  }
+
+  virtual uint64_t size() const {
+    return 0;
+  }
+
+  virtual Scope scope() const {
+    return DefinedAtom::scopeLinkageUnit;
+  }
+  
+  virtual Interposable interposable() const {
+    return DefinedAtom::interposeNo;
+  }
+  
+  virtual Merge merge() const {
+    return DefinedAtom::mergeNo;
+  }
+  
+  virtual ContentType contentType() const  {
+    return DefinedAtom::typeGOT;
+  }
+
+  virtual Alignment alignment() const {
+    return Alignment(3,0);
+  }
+  
+  virtual SectionChoice sectionChoice() const {
+    return DefinedAtom::sectionBasedOnContent;
+  }
+    
+  virtual StringRef customSectionName() const {
+    return StringRef();
+  }
+  virtual DeadStripKind deadStrip() const {
+    return DefinedAtom::deadStripNormal;
+  }
+    
+  virtual ContentPermissions permissions() const  {
+    return DefinedAtom::permRW_;
+  }
+  
+  virtual bool isThumb() const {
+    return false;
+  }
+    
+  virtual bool isAlias() const {
+    return false;
+  }
+  
+  virtual ArrayRef<uint8_t> rawContent() const {
+    return ArrayRef<uint8_t>();
+  }
+  
+  virtual reference_iterator begin() const {
+    return reference_iterator(*this, nullptr);
+  }
+  
+  virtual reference_iterator end() const {
+    return reference_iterator(*this, nullptr);
+  }
+  
+  virtual const Reference* derefIterator(const void* iter) const {
+    return nullptr;
+  }
+  
+  virtual void incrementIterator(const void*& iter) const {
+  
+  }
+  
+private:
+  const File&               _file;
+  const Atom&               _shlib;
+  uint32_t                  _ordinal;
+};
+
+
+
+class TestingPassFile : public File {
+public:
+  TestingPassFile() : File("Testing pass") {
+  }
+  
+  virtual void addAtom(const Atom &atom) {
+    if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
+      _definedAtoms._atoms.push_back(defAtom);
+    } 
+    else {
+      assert(0 && "atom has unknown definition kind");
+    }
+  }
+  
+  virtual const atom_collection<DefinedAtom>& defined() const {
+    return _definedAtoms;
+  }
+  virtual const atom_collection<UndefinedAtom>& undefined() const {
+    return _undefinedAtoms;
+  }
+  virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
+    return _sharedLibraryAtoms;
+  }
+  virtual const atom_collection<AbsoluteAtom>& absolute() const {
+    return _absoluteAtoms;
+  }
+    
+private:
+  atom_collection_vector<DefinedAtom>         _definedAtoms;
+  atom_collection_vector<UndefinedAtom>       _undefinedAtoms;
+  atom_collection_vector<SharedLibraryAtom>   _sharedLibraryAtoms;
+  atom_collection_vector<AbsoluteAtom>        _absoluteAtoms;
+};
+
+
+
+struct TestingKindMapping {
+  const char*           string;
+  Reference::Kind       value;
+  bool                  isBranch;
+  bool                  isGotLoad;
+  bool                  isGotUse;
+};
+
+//
+// Table of fixup kinds in YAML documents used for testing
+//
+const TestingKindMapping sKinds[] = {
+    { "call32",         1,    true,  false, false},
+    { "pcrel32",        2,    false, false, false },
+    { "gotLoad32",      3,    false, true,  true },
+    { "gotUse32",       4,    false, false, true },
+    { "lea32wasGot",    5,    false, false, false },
+    { nullptr,          0,    false, false, false }
+  };
+
+
+
+class TestingStubsPass : public StubsPass {
+public:
+  virtual bool noTextRelocs() {
+    return true;
+  }
+
+  virtual bool isCallSite(Reference::Kind kind) {
+    for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) {
+      if ( kind == p->value )
+        return p->isBranch;
+    }
+    return false;
+  }
+
+  virtual const DefinedAtom* getStub(const Atom& target) {
+    const DefinedAtom *result = new TestingStubAtom(_file, target);
+    _file.addAtom(*result);
+    return result;
+  }
+
+
+  virtual void addStubAtoms(File &mergedFile) {
+    for (const DefinedAtom *stub : _file.defined() ) {
+      mergedFile.addAtom(*stub);
+    }
+  }
+  
+private:
+  TestingPassFile    _file;
+};
+
+
+
+class TestingGOTPass : public GOTPass {
+public:
+  virtual bool noTextRelocs() {
+    return true;
+  }
+
+  virtual bool isGOTAccess(Reference::Kind kind, bool &canBypassGOT) {
+    for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) {
+      if ( kind == p->value ) {
+        canBypassGOT = p->isGotLoad;
+        return (p->isGotUse || p->isGotLoad);
+      }
+    }
+    return false;
+  }
+
+  virtual void updateReferenceToGOT(const Reference *ref, bool targetIsNowGOT) {
+    if ( targetIsNowGOT )
+      (const_cast<Reference*>(ref))->setKind(2); // pcrel32
+    else
+      (const_cast<Reference*>(ref))->setKind(5); // lea32wasGot
+  }
+
+  virtual const DefinedAtom* makeGOTEntry(const Atom &target) {
+    return new TestingGOTAtom(_file, target);
+  }
+  
+private:
+  TestingPassFile    _file;
+};
+
+
+class TestingWriterOptionsYAML : public lld::WriterOptionsYAML {
+public:
+  TestingWriterOptionsYAML(bool stubs, bool got)
+    : _doStubs(stubs), _doGOT(got) {
+  }
+
+  virtual StubsPass *stubPass() const {
+    if ( _doStubs )
+      return const_cast<TestingStubsPass*>(&_stubsPass);
+    else
+      return nullptr;
+  }
+  
+  virtual GOTPass *gotPass() const {
+     if ( _doGOT )
+      return const_cast<TestingGOTPass*>(&_gotPass);
+    else
+      return nullptr;
+  }
+  
+  virtual StringRef kindToString(Reference::Kind value) const {
+    for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) {
+      if ( value == p->value)
+        return p->string;
+    }
+    return StringRef("???");
+  }
+private:
+  bool              _doStubs;
+  bool              _doGOT;
+  TestingStubsPass  _stubsPass;
+  TestingGOTPass    _gotPass;
+};
+
+
+class TestingReaderOptionsYAML : public lld::ReaderOptionsYAML {
+  virtual Reference::Kind kindFromString(StringRef kindName) const {
+    for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) {
+      if ( kindName.equals(p->string) )
+        return p->value;
+    }
+    int k;
+    if (kindName.getAsInteger(0, k))
+      k = 0;
+    return k;
+  }
+};
+
+
+
+#endif // LLD_TOOLS_TESTING_HELPERS_H_

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=157774&r1=157773&r2=157774&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Thu May 31 17:34:00 2012
@@ -9,13 +9,17 @@
 
 #include "lld/Core/Atom.h"
 #include "lld/Core/LLVM.h"
-#include "lld/Core/NativeReader.h"
-#include "lld/Core/NativeWriter.h"
 #include "lld/Core/Pass.h"
 #include "lld/Core/Resolver.h"
-#include "lld/Core/YamlReader.h"
-#include "lld/Core/YamlWriter.h"
-#include "lld/Reader/Reader.h"
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/ReaderNative.h"
+#include "lld/ReaderWriter/ReaderYAML.h"
+#include "lld/ReaderWriter/Writer.h"
+#include "lld/ReaderWriter/WriterELF.h"
+#include "lld/ReaderWriter/WriterMachO.h"
+#include "lld/ReaderWriter/WriterNative.h"
+#include "lld/ReaderWriter/WriterPECOFF.h"
+#include "lld/ReaderWriter/WriterYAML.h"
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Support/CommandLine.h"
@@ -29,6 +33,8 @@
 
 #include <vector>
 
+#include "TestingHelpers.hpp"
+
 using namespace lld;
 
 static void error(Twine message) {
@@ -43,311 +49,6 @@
   return false;
 }
 
-namespace {
-
-
-//
-// Simple atom created by the stubs pass.
-//
-class TestingStubAtom : public DefinedAtom {
-public:
-        TestingStubAtom(const File& f, const Atom& shlib) :
-                        _file(f), _shlib(shlib) {
-          static uint32_t lastOrdinal = 0;
-          _ordinal = lastOrdinal++; 
-        }
-
-  virtual const File& file() const {
-    return _file;
-  }
-
-  virtual StringRef name() const {
-    return StringRef();
-  }
-  
-  virtual uint64_t ordinal() const {
-    return _ordinal;
-  }
-
-  virtual uint64_t size() const {
-    return 0;
-  }
-
-  virtual Scope scope() const {
-    return DefinedAtom::scopeLinkageUnit;
-  }
-  
-  virtual Interposable interposable() const {
-    return DefinedAtom::interposeNo;
-  }
-  
-  virtual Merge merge() const {
-    return DefinedAtom::mergeNo;
-  }
-  
-  virtual ContentType contentType() const  {
-    return DefinedAtom::typeStub;
-  }
-
-  virtual Alignment alignment() const {
-    return Alignment(0,0);
-  }
-  
-  virtual SectionChoice sectionChoice() const {
-    return DefinedAtom::sectionBasedOnContent;
-  }
-    
-  virtual StringRef customSectionName() const {
-    return StringRef();
-  }
-  virtual DeadStripKind deadStrip() const {
-    return DefinedAtom::deadStripNormal;
-  }
-    
-  virtual ContentPermissions permissions() const  {
-    return DefinedAtom::permR_X;
-  }
-  
-  virtual bool isThumb() const {
-    return false;
-  }
-    
-  virtual bool isAlias() const {
-    return false;
-  }
-  
-  virtual ArrayRef<uint8_t> rawContent() const {
-    return ArrayRef<uint8_t>();
-  }
-  
-  virtual reference_iterator begin() const {
-    return reference_iterator(*this, nullptr);
-  }
-  
-  virtual reference_iterator end() const {
-    return reference_iterator(*this, nullptr);
-  }
-  
-  virtual const Reference* derefIterator(const void* iter) const {
-    return nullptr;
-  }
-  
-  virtual void incrementIterator(const void*& iter) const {
-  
-  }
-  
-private:
-  const File&               _file;
-  const Atom&               _shlib;
-  uint32_t                  _ordinal;
-};
-
-
-
-
-//
-// Simple atom created by the GOT pass.
-//
-class TestingGOTAtom : public DefinedAtom {
-public:
-        TestingGOTAtom(const File& f, const Atom& shlib) :
-                        _file(f), _shlib(shlib) {
-          static uint32_t lastOrdinal = 0;
-          _ordinal = lastOrdinal++; 
-        }
-
-  virtual const File& file() const {
-    return _file;
-  }
-
-  virtual StringRef name() const {
-    return StringRef();
-  }
-  
-  virtual uint64_t ordinal() const {
-    return _ordinal;
-  }
-
-  virtual uint64_t size() const {
-    return 0;
-  }
-
-  virtual Scope scope() const {
-    return DefinedAtom::scopeLinkageUnit;
-  }
-  
-  virtual Interposable interposable() const {
-    return DefinedAtom::interposeNo;
-  }
-  
-  virtual Merge merge() const {
-    return DefinedAtom::mergeNo;
-  }
-  
-  virtual ContentType contentType() const  {
-    return DefinedAtom::typeGOT;
-  }
-
-  virtual Alignment alignment() const {
-    return Alignment(3,0);
-  }
-  
-  virtual SectionChoice sectionChoice() const {
-    return DefinedAtom::sectionBasedOnContent;
-  }
-    
-  virtual StringRef customSectionName() const {
-    return StringRef();
-  }
-  virtual DeadStripKind deadStrip() const {
-    return DefinedAtom::deadStripNormal;
-  }
-    
-  virtual ContentPermissions permissions() const  {
-    return DefinedAtom::permRW_;
-  }
-  
-  virtual bool isThumb() const {
-    return false;
-  }
-    
-  virtual bool isAlias() const {
-    return false;
-  }
-  
-  virtual ArrayRef<uint8_t> rawContent() const {
-    return ArrayRef<uint8_t>();
-  }
-  
-  virtual reference_iterator begin() const {
-    return reference_iterator(*this, nullptr);
-  }
-  
-  virtual reference_iterator end() const {
-    return reference_iterator(*this, nullptr);
-  }
-  
-  virtual const Reference* derefIterator(const void* iter) const {
-    return nullptr;
-  }
-  
-  virtual void incrementIterator(const void*& iter) const {
-  
-  }
-  
-private:
-  const File&               _file;
-  const Atom&               _shlib;
-  uint32_t                  _ordinal;
-};
-
-//
-// A simple platform for testing.
-//
-class TestingPlatform : public Platform {
-public:
-
-  virtual void addFiles(InputFiles&) {
-  }
-
-  struct KindMapping {
-    const char*           string;
-    Reference::Kind       value;
-    bool                  isBranch;
-    bool                  isGotLoad;
-    bool                  isGotUse;
-  };
-
-  static const KindMapping _s_kindMappings[]; 
-  
-  virtual Reference::Kind kindFromString(StringRef kindName) {
-    for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) {
-      if ( kindName.equals(p->string) )
-        return p->value;
-    }
-    int k;
-    if (kindName.getAsInteger(0, k))
-      k = 0;
-    return k;
-  }
-  
-  virtual StringRef kindToString(Reference::Kind value) {
-    for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) {
-      if ( value == p->value)
-        return p->string;
-    }
-    return StringRef("???");
-  }
-
-  virtual bool noTextRelocs() {
-    return true;
-  }
-  
-  virtual bool isCallSite(Reference::Kind kind) {
-    for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) {
-      if ( kind == p->value )
-        return p->isBranch;
-    }
-    return false;
-  }
-
-  virtual bool isGOTAccess(Reference::Kind kind, bool& canBypassGOT) {
-    for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) {
-      if ( kind == p->value ) {
-        canBypassGOT = p->isGotLoad;
-        return p->isGotUse;
-      }
-    }
-    return false;
-  }
-  
-  virtual void updateReferenceToGOT(const Reference* ref, bool targetIsNowGOT) {
-    if ( targetIsNowGOT )
-      (const_cast<Reference*>(ref))->setKind(kindFromString("pcrel32"));
-    else
-      (const_cast<Reference*>(ref))->setKind(kindFromString("lea32wasGot"));
-  }
-
-
-
-  virtual const DefinedAtom *getStub(const Atom& shlibAtom, File& file) {
-    const DefinedAtom *result = new TestingStubAtom(file, shlibAtom);
-    _stubs.push_back(result);
-    return result;
-  }
-  
-  virtual const DefinedAtom* makeGOTEntry(const Atom& shlibAtom, File& file) {
-    return new TestingGOTAtom(file, shlibAtom);
-  }
-  
-  virtual void addStubAtoms(File &file) {
-    for (const DefinedAtom *stub : _stubs) {
-      file.addAtom(*stub);
-    }
-  }
-  
-  virtual void writeExecutable(const lld::File &, raw_ostream &out) {
-  }
-private:
-  std::vector<const DefinedAtom*> _stubs;
-};
-
-
-//
-// Table of fixup kinds in YAML documents used for testing
-//
-const TestingPlatform::KindMapping TestingPlatform::_s_kindMappings[] = {
-    { "call32",         1,    true,  false, false},
-    { "pcrel32",        2,    false, false, false },
-    { "gotLoad32",      3,    false, true,  true },
-    { "gotUse32",       4,    false, false, true },
-    { "lea32wasGot",    5,    false, false, false },
-    { nullptr,          0,    false, false, false }
-  };
-
-
-} // anon namespace
-
 
 llvm::cl::list<std::string>
 cmdLineInputFilePaths(llvm::cl::Positional,
@@ -383,16 +84,18 @@
           llvm::cl::desc("All global symbols are roots for dead-strip"));
 
 
-enum PlatformChoice {
-  platformTesting, platformDarwin
+enum WriteChoice {
+  writeYAML, writeMachO, writePECOFF, writeELF
 };
 
-llvm::cl::opt<PlatformChoice> 
-platformSelected("platform",
-  llvm::cl::desc("Select platform"),
+llvm::cl::opt<WriteChoice> 
+writeSelected("writer",
+  llvm::cl::desc("Select writer"),
   llvm::cl::values(
-    clEnumValN(platformTesting, "none", "link for testing"),
-    clEnumValN(platformDarwin, "darwin", "link as darwin would"),
+    clEnumValN(writeYAML,   "YAML",   "link assuming YAML format"),
+    clEnumValN(writeMachO,  "mach-o", "link as darwin would"),
+    clEnumValN(writePECOFF, "PECOFF", "link as windows would"),
+    clEnumValN(writeELF,    "ELF",    "link as linux would"),
     clEnumValEnd));
     
 
@@ -410,8 +113,6 @@
 
 
 
-
-    
 int main(int argc, char *argv[]) {
   // Print a stack trace if we signal out.
   llvm::sys::PrintStackTraceOnErrorSignal();
@@ -421,108 +122,97 @@
   // parse options
   llvm::cl::ParseCommandLineOptions(argc, argv);
 
+  // if no input file specified, read from stdin
   if (cmdLineInputFilePaths.empty())
     cmdLineInputFilePaths.emplace_back("-");
 
-  // create platform for testing
-  Platform* platform = nullptr;
-  switch ( platformSelected ) {
-    case platformTesting:
-      platform = new TestingPlatform();
+  // if no output path specified, write to stdout
+  if (cmdLineOutputFilePath.empty())
+    cmdLineOutputFilePath.assign("-");
+
+  // create writer for final output
+  TestingWriterOptionsYAML  writerOptionsYAML(cmdLineDoStubsPass, 
+                                              cmdLineDoGotPass);
+  WriterOptionsMachO        writerOptionsMachO;
+  WriterOptionsPECOFF       writerOptionsPECOFF;
+  WriterOptionsELF          writerOptionsELF;
+  Writer* writer = nullptr;
+  switch ( writeSelected ) {
+    case writeYAML:
+      writer = createWriterYAML(writerOptionsYAML);
+      break;
+    case writeMachO:
+      writer = createWriterMachO(writerOptionsMachO);
       break;
-    case platformDarwin:
-      platform = createDarwinPlatform();
+    case writePECOFF:
+      writer = createWriterPECOFF(writerOptionsPECOFF);
+      break;
+    case writeELF:
+      writer = createWriterELF(writerOptionsELF);
       break;
   }
   
-  // read input YAML doc into object file(s)
-  std::vector<std::unique_ptr<const File>> files;
+  // create object to mange input files
+  InputFiles inputFiles;
+
+  // read input files into in-memory File objects
+  TestingReaderOptionsYAML  readerOptionsYAML;
+  Reader *reader = createReaderYAML(readerOptionsYAML);
   for (auto path : cmdLineInputFilePaths) {
-    OwningPtr<llvm::MemoryBuffer> ofile;
-    if (error(llvm::MemoryBuffer::getFileOrSTDIN(path, ofile)))
+    std::vector<std::unique_ptr<File>> files;
+    if ( error(reader->readFile(path, files)) )
       return 1;
-    std::unique_ptr<llvm::MemoryBuffer> file(ofile.take());
-    if (llvm::sys::fs::identify_magic(file->getBuffer())
-        == llvm::sys::fs::file_magic::coff_object) {
-      std::unique_ptr<File> f;
-      if (error(parseCOFFObjectFile(std::move(file), f)))
-        return 1;
-      files.push_back(std::move(f));
-    } else {
-      if (error(yaml::parseObjectText( file.release()
-                                     , *platform
-                                     , files)))
-        return 1;
-    }
+    inputFiles.appendFiles(files);
   }
+    
+  // given writer a chance to add files
+  writer->addFiles(inputFiles);
 
   // create options for resolving
   TestingResolverOptions options;
 
-  // create object to mange input files
-  InputFiles inputFiles;
-  for (const auto &file : files) {
-    inputFiles.appendFile(*file);
-  }
-  
-  platform->addFiles(inputFiles);
-
   // merge all atom graphs
   Resolver resolver(options, inputFiles);
   resolver.resolve();
+  File &mergedMasterFile = resolver.resultFile();
 
   // run passes
-  if ( cmdLineDoGotPass ) {
-    GOTPass  addGot(resolver.resultFile(), *platform);
-    addGot.perform();
+  if ( GOTPass *pass = writer->gotPass() ) {
+    pass->perform(mergedMasterFile);
   }
-  if ( cmdLineDoStubsPass ) {
-    StubsPass  addStubs(resolver.resultFile(), *platform);
-    addStubs.perform();
+  if ( StubsPass *pass = writer->stubPass() ) {
+    pass->perform(mergedMasterFile);
   }
 
+  // showing yaml at this stage can help when debugging
+  const bool dumpIntermediateYAML = false;
+  if ( dumpIntermediateYAML )
+    writer->writeFile(mergedMasterFile, "-");
+
+  // make unique temp file to put generated native object file
+  llvm::sys::Path tmpNativePath = llvm::sys::Path::GetTemporaryDirectory();
+  if (tmpNativePath.createTemporaryFileOnDisk()) {
+    error("createTemporaryFileOnDisk() failed");
+    return 1;
+  }
   
-//  yaml::writeObjectText(resolver.resultFile(), *platform, llvm::errs());
-
-  // make unique temp .o file to put generated object file
-  int fd;
-  SmallString<128> tempPath;
-  llvm::sys::fs::unique_file("temp%%%%%.o", fd, tempPath);
-  llvm::raw_fd_ostream  binaryOut(fd, /*shouldClose=*/true);
-  
-  // write native file
-  writeNativeObjectFile(resolver.resultFile(), binaryOut);
-  binaryOut.close();  // manually close so that file can be read next
-
-//  out << "native file: " << tempPath.str() << "\n";
+  // write as native file
+  WriterOptionsNative  optionsNativeWriter;
+  Writer *natWriter = createWriterNative(optionsNativeWriter);
+  if (error(natWriter->writeFile(mergedMasterFile, tmpNativePath.c_str())))
+    return 1;
   
-  // read native file
-  std::unique_ptr<lld::File> natFile;
-  if ( error(parseNativeObjectFileOrSTDIN(tempPath, natFile)) ) 
+  // read as native file
+  ReaderOptionsNative  optionsNativeReader;
+  Reader *natReader = createReaderNative(optionsNativeReader);
+  std::vector<std::unique_ptr<File>> readNativeFiles;
+  if (error(natReader->readFile(tmpNativePath.c_str(), readNativeFiles)))
     return 1;
-
-  // write new atom graph
-  std::string errorInfo;
-  const char* outPath = (cmdLineOutputFilePath.empty() ? "-" 
-                                              : cmdLineOutputFilePath.c_str());
-  llvm::raw_fd_ostream out(outPath, errorInfo);
-  if ( platformSelected == platformTesting) {
-    // write atom graph out as YAML doc
-    yaml::writeObjectText(resolver.resultFile() /* *natFile */, *platform, out);
-  }
-  else {
-    // write atom graph as an executable
-    platform->writeExecutable(resolver.resultFile() /* *natFile */, out);
-    // HACK.  I don't see any way to set the 'executable' bit on files 
-    // in raw_fd_ostream or in llvm/Support.
-#if HAVE_SYS_STAT_H
-    ::chmod(outPath, 0777);
-#endif
-  }
-
-  // delete temp .o file
-  bool existed;
-  llvm::sys::fs::remove(tempPath.str(), existed);
   
+  // write new atom graph
+  const File *parsedNativeFile = readNativeFiles[0].get();
+  if (error(writer->writeFile(*parsedNativeFile, cmdLineOutputFilePath)))
+    return 1;
+   
   return 0;
 }





More information about the llvm-commits mailing list