[llvm-commits] [lld] r152269 - in /lld/trunk: ./ include/lld/Core/ include/lld/Platform/ lib/ lib/Core/ lib/Passes/ test/ tools/lld-core/

Nick Kledzik kledzik at apple.com
Wed Mar 7 16:18:31 PST 2012


Author: kledzik
Date: Wed Mar  7 18:18:30 2012
New Revision: 152269

URL: http://llvm.org/viewvc/llvm-project?rev=152269&view=rev
Log:
Sources now require C++11 to build.

Add first linker pass (StubsPass) which looks for calls to shared library
symbols and replaces them with calls to a StubAtom.  On ELF system, a "stub"
is a PLT entry.  Added a simple test case.

Pass a Platform object to YAML reader and writer for converting fixup kinds 
between names and values.

Change output of Resolver to be a File object instead of a vector of Atoms.
Thus, passes operate on a File instead of just Atoms.

Rework how to walk through a File's Atoms. Now iterator based instead of 
a method that visits each atom.  


Added:
    lld/trunk/include/lld/Core/Pass.h
    lld/trunk/lib/Passes/CMakeLists.txt
    lld/trunk/lib/Passes/StubsPass.cpp
    lld/trunk/test/pass-stubs-basic.objtxt
Modified:
    lld/trunk/CMakeLists.txt
    lld/trunk/include/lld/Core/Atom.h
    lld/trunk/include/lld/Core/DefinedAtom.h
    lld/trunk/include/lld/Core/File.h
    lld/trunk/include/lld/Core/InputFiles.h
    lld/trunk/include/lld/Core/Resolver.h
    lld/trunk/include/lld/Core/YamlReader.h
    lld/trunk/include/lld/Core/YamlWriter.h
    lld/trunk/include/lld/Platform/Platform.h
    lld/trunk/lib/CMakeLists.txt
    lld/trunk/lib/Core/File.cpp
    lld/trunk/lib/Core/NativeReader.cpp
    lld/trunk/lib/Core/NativeWriter.cpp
    lld/trunk/lib/Core/Resolver.cpp
    lld/trunk/lib/Core/YamlKeyValues.cpp
    lld/trunk/lib/Core/YamlReader.cpp
    lld/trunk/lib/Core/YamlWriter.cpp
    lld/trunk/tools/lld-core/CMakeLists.txt
    lld/trunk/tools/lld-core/lld-core.cpp

Modified: lld/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/CMakeLists.txt?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/CMakeLists.txt (original)
+++ lld/trunk/CMakeLists.txt Wed Mar  7 18:18:30 2012
@@ -1,6 +1,8 @@
 # If we are not building as a part of LLVM, build lld as a standalone project,
 # using LLVM as an external library.
 
+
+
 if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
   project(lld)
   cmake_minimum_required(VERSION 2.8)
@@ -58,6 +60,20 @@
 "`CMakeFiles'. Please delete them.")
 endif()
 
+#
+# lld now requires C++11 to build
+#
+# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+include(CheckCXXCompilerFlag)
+check_cxx_compiler_flag("-std=c++11" SUPPORTS_CXX11_FLAG)
+if( SUPPORTS_CXX11_FLAG )
+  message(STATUS "Building with -std=c++11")
+  set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
+else( SUPPORTS_CXX11_FLAG )
+  message(WARNING "-std=c++11 not supported.")
+endif()
+
+
 macro(add_lld_library name)
   llvm_process_sources(srcs ${ARGN})
   if (MSVC_IDE OR XCODE)

Modified: lld/trunk/include/lld/Core/Atom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Atom.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Atom.h (original)
+++ lld/trunk/include/lld/Core/Atom.h Wed Mar  7 18:18:30 2012
@@ -24,7 +24,7 @@
 class SharedLibraryAtom;
 class AbsoluteAtom;
 
-  ///
+///
 /// The linker has a Graph Theory model of linking. An object file is seen
 /// as a set of Atoms with References to other Atoms.  Each Atom is a node
 /// and each Reference is an edge. An Atom can be a DefinedAtom which has

Modified: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Wed Mar  7 18:18:30 2012
@@ -195,13 +195,6 @@
     uint16_t modulus;
   };
 
-  /// for use iterating over this Atom's References
-  class ReferenceHandler {
-  public:
-    virtual ~ReferenceHandler() {}
-    virtual void doReference(const Reference &) = 0;
-  };
-
   /// ordinal - returns a value for the order of this Atom within its file.
   /// This is used by the linker to order the layout of Atoms so that
   /// the resulting image is stable and reproducible.
@@ -266,10 +259,43 @@
   /// rawContent - returns a reference to the raw (unrelocated) bytes of 
   /// this Atom's content.
   virtual llvm::ArrayRef<uint8_t> rawContent() const = 0;
+  
+  /// This class abstracts iterating over the sequence of References
+  /// in an Atom.  Concrete instances of DefinedAtom must implement
+  /// the derefIterator() and incrementIterator methods.
+  class reference_iterator {
+  public:
+    reference_iterator(const DefinedAtom& a, const void* it) 
+              : _atom(a), _it(it) { }
 
-  /// iterator over this Atom's References
-  virtual void forEachReference(ReferenceHandler&) const = 0;
+    const Reference* operator*() const {
+      return _atom.derefIterator(_it);
+    }
+    
+    const Reference* operator->() const {
+      return _atom.derefIterator(_it);
+    }
+
+    bool operator!=(const reference_iterator& other) const {
+      return (this->_it != other._it);
+    }
+
+    reference_iterator& operator++() {
+      _atom.incrementIterator(_it);
+      return *this;
+    }
+  private:
+    const DefinedAtom&   _atom;
+    const void*          _it;
+  };
+
+  /// Returns an iterator to the beginning of this Atom's References
+  virtual reference_iterator referencesBegin() const = 0;
   
+  /// Returns an iterator to the end of this Atom's References
+  virtual reference_iterator referencesEnd() const = 0;
+ 
+ 
 protected:
   /// DefinedAtom is an abstract base class.  
   /// Only subclasses can access constructor.
@@ -280,6 +306,15 @@
   /// delete on an Atom.  In fact, some File objects may bulk allocate
   /// an array of Atoms, so they cannot be individually deleted by anyone.
   virtual ~DefinedAtom() {}
+  
+  /// Returns a pointer to the Reference object that the abstract
+  /// iterator "points" to.
+  virtual const Reference* derefIterator(const void* iter) const = 0;
+  
+  /// Adjusts the abstract iterator to "point" to the next Reference object
+  /// for this Atom.
+  virtual void incrementIterator(const void*& iter) const = 0;
+
 };
 
 } // namespace lld

Modified: lld/trunk/include/lld/Core/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/File.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/File.h (original)
+++ lld/trunk/include/lld/Core/File.h Wed Mar  7 18:18:30 2012
@@ -1,4 +1,4 @@
-//===- Core/File.h - A Contaier of Atoms ----------------------------------===//
+//===- Core/File.h - A Container of Atoms ---------------------------------===//
 //
 //                             The LLVM Linker
 //
@@ -10,6 +10,8 @@
 #ifndef LLD_CORE_FILE_H_
 #define LLD_CORE_FILE_H_
 
+#include <vector>
+
 #include "llvm/ADT/StringRef.h"
 
 #include "lld/Core/DefinedAtom.h"
@@ -19,31 +21,190 @@
 
 namespace lld {
 
+
+///
+/// Every Atom is owned by some File. A common scenario is for a single 
+/// object file (.o) to be parsed by some reader and produce a single
+/// File object that represents the content of that object file.  
+///
+/// The File class has *begin() and *end() methods for use iterating through
+/// the Atoms in a File object.  
+///
+/// The Atom objects in a File are owned by the File object.  The Atom objects  
+/// are destroyed when the File object is destroyed.
+///
 class File {
 public:
-  File(llvm::StringRef p) : _path(p) {}
   virtual ~File();
 
-  class AtomHandler {
-  public:
-    virtual ~AtomHandler() {}
-    virtual void doDefinedAtom(const class DefinedAtom &) = 0;
-    virtual void doUndefinedAtom(const class UndefinedAtom &) = 0;
-    virtual void doSharedLibraryAtom(const class SharedLibraryAtom &) = 0;
-    virtual void doAbsoluteAtom(const class AbsoluteAtom &) = 0;
-    virtual void doFile(const class File &) = 0;
-  };
-
+  /// For error messages and debugging, this returns the path to the file
+  /// which was used to create this object (e.g. "/tmp/foo.o").
   llvm::StringRef path() const  {
     return _path;
   }
 
-  virtual bool forEachAtom(AtomHandler &) const = 0;
-  virtual bool justInTimeforEachAtom( llvm::StringRef name
-                                    , AtomHandler &) const = 0;
+  /// Returns the path of the source file used to create the object
+  /// file which this (File) object represents.  This information is usually 
+  /// parsed out of the DWARF debug information. If the source file cannot 
+  /// be ascertained, this method returns the empty string.
+  virtual llvm::StringRef translationUnitSource() const;
 
-  virtual bool translationUnitSource(llvm::StringRef &path) const;
+protected:
+  template <typename T> class atom_iterator; // forward reference
+public:
+  
+  /// For use interating over DefinedAtoms in this File.
+  typedef atom_iterator<DefinedAtom>  defined_iterator;
+
+  /// For use interating over UndefinedAtoms in this File.
+  typedef atom_iterator<UndefinedAtom> undefined_iterator;
+
+  /// For use interating over SharedLibraryAtoms in this File.
+  typedef atom_iterator<SharedLibraryAtom> shared_library_iterator;
+
+  /// For use interating over AbsoluteAtoms in this File.
+  typedef atom_iterator<AbsoluteAtom> absolute_iterator;
+
+  /// Returns an iterator to the beginning of this File's DefinedAtoms
+  defined_iterator definedAtomsBegin() const {
+    return defined().begin();
+  }
+  
+  /// Returns an iterator to the end of this File's DefinedAtoms
+  defined_iterator definedAtomsEnd() const {
+    return defined().end();
+  }
+   
+  /// Returns an iterator to the beginning of this File's DefinedAtoms
+  undefined_iterator undefinedAtomsBegin() const {
+    return undefined().begin();
+  }
+  
+  /// Returns an iterator to the end of this File's UndefinedAtoms
+  undefined_iterator undefinedAtomsEnd() const {
+    return undefined().end();
+  }
+  
+  /// Returns an iterator to the beginning of this File's SharedLibraryAtoms
+  shared_library_iterator sharedLibraryAtomsBegin() const {
+    return sharedLibrary().begin();
+  }
+
+  /// Returns an iterator to the end of this File's SharedLibraryAtoms
+  shared_library_iterator sharedLibraryAtomsEnd() const {
+    return sharedLibrary().end();
+  }
+
+  /// Returns an iterator to the beginning of this File's AbsoluteAtoms
+  absolute_iterator absoluteAtomsBegin() const {
+    return absolute().begin();
+  }
 
+  /// Returns an iterator to the end of this File's AbsoluteAtoms
+  absolute_iterator absoluteAtomsEnd() const {
+    return absolute().end();
+  }
+  
+  /// Note: this method is not const.  All File objects instantiated by reading
+  /// an object file from disk are "const File*" objects and cannot be 
+  /// modified.  This method can only be used with temporay File objects
+  /// such as is seen by each Pass object when it runs.
+  /// This method is *not* safe to call while iterating through this File's 
+  /// Atoms.  A Pass should queue up any Atoms it want to add and then 
+  /// call this method when no longer iterating over the File's Atoms.
+  virtual void addAtom(const Atom&) = 0;
+
+
+
+protected:
+  /// only subclasses of File can be instantiated 
+  File(llvm::StringRef p) : _path(p) {}
+
+
+  /// Different object file readers may instantiate and manage atoms with
+  /// different data structures.  This class is a collection abstraction.
+  /// Each concrete File instance must implement these atom_collection
+  /// methods to enable clients to interate the File's atoms.
+  template <typename T>
+  class atom_collection {
+  public:
+    virtual atom_iterator<T> begin() const = 0;
+    virtual atom_iterator<T> end() const = 0;
+    virtual const T* deref(const void* it) const = 0;
+    virtual void next(const void*& it) const = 0;
+  };
+
+
+  /// The class is the iterator type used to iterate through a File's Atoms.
+  /// This iterator delegates the work to the associated atom_collection object.
+  /// There are four kinds of Atoms, so this iterator is templated on
+  /// the four base Atom kinds.
+  template <typename T>
+  class atom_iterator {
+  public:
+    atom_iterator(const atom_collection<T>& c, const void* it) 
+              : _collection(c), _it(it) { }
+
+    const T* operator*() const {
+      return _collection.deref(_it);
+    }
+    
+    const T* operator->() const {
+      return _collection.deref(_it);
+    }
+
+    bool operator!=(const atom_iterator<T>& other) const {
+      return (this->_it != other._it);
+    }
+
+    atom_iterator<T>& operator++() {
+      _collection.next(_it);
+      return *this;
+    }
+  private:
+    const atom_collection<T>&   _collection;
+    const void*                 _it;
+  };
+
+  /// Must be implemented to return the atom_collection object for 
+  /// all DefinedAtoms in this File.
+  virtual const atom_collection<DefinedAtom>& defined() const = 0;
+
+  /// Must be implemented to return the atom_collection object for 
+  /// all UndefinedAtomw in this File.
+  virtual const atom_collection<UndefinedAtom>& undefined() const = 0;
+
+  /// Must be implemented to return the atom_collection object for 
+  /// all SharedLibraryAtoms in this File.
+  virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const = 0;
+
+  /// Must be implemented to return the atom_collection object for 
+  /// all AbsoluteAtoms in this File.
+  virtual const atom_collection<AbsoluteAtom>& absolute() const = 0;
+
+  /// This is a convenience class for File subclasses which manage their
+  /// atoms as a simple std::vector<>.  
+  template <typename T>
+  class atom_collection_vector : public atom_collection<T> {
+  public:
+    virtual atom_iterator<T> begin() const { 
+      return atom_iterator<T>(*this, reinterpret_cast<const void*>(&_atoms[0]));
+    }
+    virtual atom_iterator<T> end() const{ 
+      return atom_iterator<T>(*this, reinterpret_cast<const void*>
+                              (&_atoms[_atoms.size()]));
+    }
+    virtual const T* deref(const void* it) const {
+      return *reinterpret_cast<const T* const*>(it);
+    }
+    virtual void next(const void*& it) const {
+      const T * const * p = reinterpret_cast<const T * const *>(it);
+      ++p;
+      it = reinterpret_cast<const void*>(p);
+    }
+    std::vector<const T*>   _atoms;
+  };
+  
 
 private:
   llvm::StringRef _path;

Modified: lld/trunk/include/lld/Core/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputFiles.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/InputFiles.h (original)
+++ lld/trunk/include/lld/Core/InputFiles.h Wed Mar  7 18:18:30 2012
@@ -24,15 +24,26 @@
 /// The searchLibraries() method is used to lazily search libraries.
 class InputFiles {
 public:
+  class Handler {
+  public:
+    virtual ~Handler() {}
+    virtual void doFile(const class File &) = 0;
+    virtual void doDefinedAtom(const class DefinedAtom &) = 0;
+    virtual void doUndefinedAtom(const class UndefinedAtom &) = 0;
+    virtual void doSharedLibraryAtom(const class SharedLibraryAtom &) = 0;
+    virtual void doAbsoluteAtom(const class AbsoluteAtom &) = 0;
+  };
+
+
   /// @brief iterates all atoms in initial files
-  virtual void forEachInitialAtom(File::AtomHandler &) const = 0;
+  virtual void forEachInitialAtom(Handler &) const = 0;
 
   /// @brief searches libraries for name
   virtual bool searchLibraries(  llvm::StringRef name
                                , bool searchDylibs
                                , bool searchArchives
                                , bool dataSymbolOnly
-                               , File::AtomHandler &) const = 0;
+                               , Handler &) const = 0;
 };
 
 } // namespace lld

Added: lld/trunk/include/lld/Core/Pass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Pass.h?rev=152269&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/Pass.h (added)
+++ lld/trunk/include/lld/Core/Pass.h Wed Mar  7 18:18:30 2012
@@ -0,0 +1,65 @@
+//===------ Core/Pass.h - Base class for linker passes --------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_PASS_H_
+#define LLD_CORE_PASS_H_
+
+#include <vector>
+
+#include "lld/Core/Atom.h"
+#include "lld/Platform/Platform.h"
+
+namespace lld {
+
+
+///
+/// Once the core linking is done (which resolves references, coalesces atoms
+/// and produces a complete Atom graph), the linker runs a series of passes
+/// on the Atom graph. The graph is modeled as a File, which means the pass
+/// has access to all the atoms and to File level attributes. Each pass does 
+/// a particular transformation to the Atom graph or to the File attributes.  
+///
+/// This is the abstract base class for all passes.  A Pass does its
+/// actual work in it perform() method.  It can iterator over Atoms in the 
+/// graph using the *begin()/*end() atom iterator of the File.  It can add
+/// new Atoms to the graph using the File's addAtom() method.
+///
+///
+class Pass {
+public:
+    /// Do the actual work of the Pass.
+    virtual void perform() = 0;
+
+protected:
+  // Only subclassess can be instantiated.
+  Pass(File& f, Platform& p) : _file(f), _platform(p) {}
+  
+    
+  File&       _file;
+  Platform&   _platform;
+};
+
+
+///
+/// Pass for adding stubs (PLT entries) for calls to functions
+/// outside the linkage unit.
+///
+class StubsPass : public Pass {
+public:
+  StubsPass(File& f, Platform& p) : Pass(f, p) {}
+
+  /// Scans all Atoms looking for call-site uses of SharedLibraryAtoms
+  /// and transfroms the call-site to call a stub instead.
+  virtual void perform();
+};
+
+
+} // namespace lld
+
+#endif // LLD_CORE_PASS_H_

Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Wed Mar  7 18:18:30 2012
@@ -11,6 +11,7 @@
 #define LLD_CORE_RESOLVER_H_
 
 #include "lld/Core/File.h"
+#include "lld/Core/InputFiles.h"
 #include "lld/Core/SymbolTable.h"
 
 #include "llvm/ADT/DenseSet.h"
@@ -30,7 +31,7 @@
 ///
 /// All platform specific resolving is done by delegating to the
 /// Platform object specified.
-class Resolver : public File::AtomHandler {
+class Resolver : public InputFiles::Handler {
 public:
   Resolver(Platform &plat, const InputFiles &inputs)
     : _platform(plat)
@@ -40,7 +41,7 @@
     , _addToFinalSection(false)
     , _completedInitialObjectFiles(false) {}
 
-  // AtomHandler methods
+  // InputFiles::Handler methods
   virtual void doDefinedAtom(const class DefinedAtom&);
   virtual void doUndefinedAtom(const class UndefinedAtom&);
   virtual void doSharedLibraryAtom(const class SharedLibraryAtom &);
@@ -48,7 +49,11 @@
   virtual void doFile(const File&);
 
   /// @brief do work of merging and resolving and return list
-  std::vector<const Atom *> &resolve();
+  void resolve();
+
+  File& resultFile() {
+    return _result;
+  }
 
 private:
   struct WhyLiveBackChain {
@@ -73,31 +78,49 @@
   void addAtoms(const std::vector<const DefinedAtom *>&);
 
 
-  // helper to update targets for use with forEachReference()
-  class MarkLiveReferences : public DefinedAtom::ReferenceHandler {
+  class MergedFile : public File {
   public:
-             MarkLiveReferences(Resolver& resolver, WhyLiveBackChain* chain) 
-                  : _resolver(resolver), _chain(chain) { }
+    MergedFile() : File("<linker-internal>") { }
     
-    virtual void doReference(const Reference& ref) {
-    _resolver.markLive(*ref.target(), _chain);
-    }
+
+
+  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;
+  }
+ 
+  void addAtoms(std::vector<const Atom*>& atoms);
+
+  virtual void addAtom(const Atom& atom);  
 
   private:
-    Resolver&          _resolver;
-    WhyLiveBackChain*  _chain;
+    atom_collection_vector<DefinedAtom>         _definedAtoms;
+    atom_collection_vector<UndefinedAtom>       _undefinedAtoms;
+    atom_collection_vector<SharedLibraryAtom>   _sharedLibraryAtoms;
+    atom_collection_vector<AbsoluteAtom>        _absoluteAtoms;
   };
-
-  Platform &_platform;
-  const InputFiles &_inputFiles;
-  SymbolTable _symbolTable;
-  std::vector<const Atom *> _atoms;
-  std::set<const Atom *> _deadStripRoots;
-  std::vector<const Atom *> _atomsWithUnresolvedReferences;
-  llvm::DenseSet<const Atom *> _liveAtoms;
-  bool _haveLLVMObjs;
-  bool _addToFinalSection;
-  bool _completedInitialObjectFiles;
+  
+  
+  
+  Platform&                     _platform;
+  const InputFiles&             _inputFiles;
+  SymbolTable                   _symbolTable;
+  std::vector<const Atom *>     _atoms;
+  std::set<const Atom *>        _deadStripRoots;
+  std::vector<const Atom *>     _atomsWithUnresolvedReferences;
+  llvm::DenseSet<const Atom *>  _liveAtoms;
+  MergedFile                    _result;
+  bool                          _haveLLVMObjs;
+  bool                          _addToFinalSection;
+  bool                          _completedInitialObjectFiles;
 };
 
 } // namespace lld

Modified: lld/trunk/include/lld/Core/YamlReader.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/YamlReader.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/YamlReader.h (original)
+++ lld/trunk/include/lld/Core/YamlReader.h Wed Mar  7 18:18:30 2012
@@ -10,8 +10,6 @@
 #ifndef LLD_CORE_YAML_READER_H_
 #define LLD_CORE_YAML_READER_H_
 
-#include "lld/Core/File.h"
-
 #include "llvm/Support/system_error.h"
 
 #include <vector>
@@ -19,19 +17,25 @@
 namespace llvm { class MemoryBuffer; }
 
 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*>.
   llvm::error_code parseObjectTextFileOrSTDIN(llvm::StringRef path
-                                 , std::vector<File *>&);
+                                              , Platform& 
+                                              , std::vector<const File *>&);
 
 
   /// parseObjectText - Parse the specified YAML formatted MemoryBuffer
   /// into lld::File object(s) and append each to the specified vector<File*>.
   llvm::error_code parseObjectText(llvm::MemoryBuffer *mb
-                                 , std::vector<File *>&);
+                                , Platform& 
+                                , std::vector<const File *>&);
 
 } // namespace yaml
 } // namespace lld

Modified: lld/trunk/include/lld/Core/YamlWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/YamlWriter.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/YamlWriter.h (original)
+++ lld/trunk/include/lld/Core/YamlWriter.h Wed Mar  7 18:18:30 2012
@@ -10,15 +10,18 @@
 #ifndef LLD_CORE_YAML_WRITER_H_
 #define LLD_CORE_YAML_WRITER_H_
 
-#include "lld/Core/File.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 &, llvm::raw_ostream &);
+  void writeObjectText(const lld::File &, Platform &, llvm::raw_ostream &);
 
 } // namespace yaml
 } // namespace lld

Modified: lld/trunk/include/lld/Platform/Platform.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Platform/Platform.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Platform/Platform.h (original)
+++ lld/trunk/include/lld/Platform/Platform.h Wed Mar  7 18:18:30 2012
@@ -12,10 +12,13 @@
 
 #include <vector>
 
+#include "lld/Core/Reference.h"
+ 
 namespace lld {
 class Atom;
 class DefinedAtom;
 
+
 /// The Platform class encapsulated plaform specific linking knowledge.
 ///
 /// Much of what it does is driving by platform specific linker options.
@@ -98,6 +101,26 @@
 
   /// @brief last chance for platform to tweak atoms
   virtual void postResolveTweaks(std::vector<const Atom *>& all) = 0;
+  
+  /// If the output being generated uses needs stubs for external calls
+  virtual bool outputUsesStubs() = 0;
+  
+  /// Converts a reference kind string to a in-memory numeric value. 
+  /// For use with parsing YAML encoded object files.
+  virtual Reference::Kind kindFromString(llvm::StringRef) = 0;
+  
+  /// Converts an in-memory reference kind value to a string.
+  /// For use with writing YAML encoded object files.
+  virtual llvm::StringRef kindToString(Reference::Kind) = 0;
+  
+  /// If Reference is a branch instruction that might need to be changed
+  /// to target a stub (PLT entry). 
+  virtual bool isBranch(const Reference*) = 0;
+  
+  /// Create a platform specific atom which contains a stub/PLT entry 
+  /// targeting the specified shared library atom.
+  virtual const Atom* makeStub(const SharedLibraryAtom&, File&) = 0;
+
 };
 
 } // namespace lld

Modified: lld/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/CMakeLists.txt?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/CMakeLists.txt (original)
+++ lld/trunk/lib/CMakeLists.txt Wed Mar  7 18:18:30 2012
@@ -1 +1,2 @@
 add_subdirectory(Core)
+add_subdirectory(Passes)

Modified: lld/trunk/lib/Core/File.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/File.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/File.cpp (original)
+++ lld/trunk/lib/Core/File.cpp Wed Mar  7 18:18:30 2012
@@ -13,8 +13,8 @@
 
 File::~File() {}
 
-bool File::translationUnitSource(llvm::StringRef &path) const {
-  return false;
+llvm::StringRef File::translationUnitSource() const {
+  return llvm::StringRef();
 }
 
 

Modified: lld/trunk/lib/Core/NativeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeReader.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeReader.cpp (original)
+++ lld/trunk/lib/Core/NativeReader.cpp Wed Mar  7 18:18:30 2012
@@ -92,9 +92,15 @@
   }
   
   virtual llvm::ArrayRef<uint8_t> rawContent() const;
-    
-  virtual void forEachReference(ReferenceHandler&) const;
-   
+  
+  virtual reference_iterator referencesBegin() const;
+  
+  virtual reference_iterator referencesEnd() const;
+
+  virtual const Reference* derefIterator(const void*) const;
+  
+  virtual void incrementIterator(const void*& it) const;
+
 private:
   const NativeAtomAttributesV1& attributes() const;
   
@@ -299,53 +305,29 @@
     // 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 _definedAtoms._arrayStart;
+    delete _undefinedAtoms._arrayStart;
+    delete _sharedLibraryAtoms._arrayStart;
+    delete _absoluteAtoms._arrayStart;
     delete _references.arrayStart;
     delete _targetsTable;
   }
   
-  // visits each atom in the file
-  virtual bool forEachAtom(AtomHandler& handler) const {
-    bool didSomething = false;
-    for(const uint8_t* p=_definedAtoms.arrayStart; p != _definedAtoms.arrayEnd; 
-          p += _definedAtoms.elementSize) {
-      const DefinedAtom* atom = reinterpret_cast<const DefinedAtom*>(p);
-      handler.doDefinedAtom(*atom);
-      didSomething = true;
-    }
-    for(const uint8_t* p=_undefinedAtoms.arrayStart; 
-                      p != _undefinedAtoms.arrayEnd; 
-                      p += _undefinedAtoms.elementSize) {
-      const UndefinedAtom* atom = reinterpret_cast<const UndefinedAtom*>(p);
-      handler.doUndefinedAtom(*atom);
-      didSomething = true;
-    }
-    for(const uint8_t* p=_sharedLibraryAtoms.arrayStart; 
-                  p != _sharedLibraryAtoms.arrayEnd; 
-                  p += _sharedLibraryAtoms.elementSize) {
-      const SharedLibraryAtom* atom 
-                          = reinterpret_cast<const SharedLibraryAtom*>(p);
-      handler.doSharedLibraryAtom(*atom);
-      didSomething = true;
-    }
-    for(const uint8_t* p=_absoluteAtoms.arrayStart; 
-                  p != _absoluteAtoms.arrayEnd; 
-                  p += _absoluteAtoms.elementSize) {
-      const AbsoluteAtom* atom 
-                          = reinterpret_cast<const AbsoluteAtom*>(p);
-      handler.doAbsoluteAtom(*atom);
-      didSomething = true;
-    }
-    return didSomething;
-  }
-  
-  // not used
-  virtual bool justInTimeforEachAtom(llvm::StringRef name,
-                                              AtomHandler &) const {
-    return false;
+  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:
@@ -378,10 +360,10 @@
       new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
       ++ivarData;
     }
-    this->_definedAtoms.arrayStart = atomsStart;
-    this->_definedAtoms.arrayEnd = atomsEnd;
-    this->_definedAtoms.elementSize = atomSize;
-    this->_definedAtoms.elementCount = chunk->elementCount;
+    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);
   }
   
@@ -416,10 +398,10 @@
       new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
       ++ivarData;
     }
-    this->_undefinedAtoms.arrayStart = atomsStart;
-    this->_undefinedAtoms.arrayEnd = atomsEnd;
-    this->_undefinedAtoms.elementSize = atomSize;
-    this->_undefinedAtoms.elementCount = chunk->elementCount;
+    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);
   }
   
@@ -447,10 +429,10 @@
       new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
       ++ivarData;
     }
-    this->_sharedLibraryAtoms.arrayStart = atomsStart;
-    this->_sharedLibraryAtoms.arrayEnd = atomsEnd;
-    this->_sharedLibraryAtoms.elementSize = atomSize;
-    this->_sharedLibraryAtoms.elementCount = chunk->elementCount;
+    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);
   }
   
@@ -478,10 +460,10 @@
       new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
       ++ivarData;
     }
-    this->_absoluteAtoms.arrayStart = atomsStart;
-    this->_absoluteAtoms.arrayEnd = atomsEnd;
-    this->_absoluteAtoms.elementSize = atomSize;
-    this->_absoluteAtoms.elementCount = chunk->elementCount;
+    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);
   }
   
@@ -529,33 +511,33 @@
     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;
+      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;
+      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;
+      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;
+      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;
       }
@@ -612,21 +594,13 @@
     assert((result+size) <= _contentEnd);
     return result;
   }
-
-  void forEachReference(DefinedAtom::ReferenceHandler& handler, 
-                                        uint32_t start, uint32_t count) const {
-    assert(start < _references.elementCount);
-    assert(start+count <= _references.elementCount);
-    const uint8_t* arrStart = _references.arrayStart 
-                                   + start * _references.elementSize;
-    const uint8_t* arrEnd = arrStart + count * _references.elementSize;
-    for(const uint8_t* p=arrStart; p != arrEnd; p += _references.elementSize) {
-      const NativeReferenceV1* ref 
-                              = reinterpret_cast<const NativeReferenceV1*>(p);
-      handler.doReference(*ref);
-    }
-  }
   
+  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(uint32_t index) const {
     assert(index < _targetsTableCount);
     return _targetsTable[index];
@@ -656,21 +630,52 @@
                                                   (_buffer->getBufferStart());
   }
 
+  template <typename T>
+  class AtomArray : public File::atom_collection<T> {
+  public:
+     AtomArray() : _arrayStart(NULL), _arrayEnd(NULL), 
+                   _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(NULL), arrayEnd(NULL), 
-                                    elementSize(0), elementCount(0) { }
+                      IvarArray() : 
+                        arrayStart(NULL), 
+                        arrayEnd(NULL), 
+                        elementSize(0), 
+                        elementCount(0) { } 
+    
     const uint8_t*     arrayStart;
     const uint8_t*     arrayEnd;
     uint32_t           elementSize;
     uint32_t           elementCount;
- };
+  };
+
 
   llvm::OwningPtr<llvm::MemoryBuffer>  _buffer;
   const NativeFileHeader*         _header;
-  IvarArray                       _definedAtoms;
-  IvarArray                       _undefinedAtoms;
-  IvarArray                       _sharedLibraryAtoms;
-  IvarArray                       _absoluteAtoms;
+  AtomArray<DefinedAtom>          _definedAtoms;
+  AtomArray<UndefinedAtom>        _undefinedAtoms;
+  AtomArray<SharedLibraryAtom>    _sharedLibraryAtoms;
+  AtomArray<AbsoluteAtom>         _absoluteAtoms;
   const uint8_t*                  _attributes;
   uint32_t                        _attributesMaxOffset;
   IvarArray                       _references;
@@ -684,14 +689,14 @@
   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;
+  return p - _file->_definedAtoms._arrayStart;
 }
 
 inline llvm::StringRef NativeDefinedAtomV1::name() const {
@@ -715,11 +720,27 @@
   return _file->string(offset);
 }
 
-inline void NativeDefinedAtomV1::forEachReference(ReferenceHandler& hnd) const {
-  if ( _ivarData->referencesCount == 0 )
-    return;
-  _file->forEachReference(hnd, _ivarData->referencesStartIndex, 
-                               _ivarData->referencesCount);
+DefinedAtom::reference_iterator NativeDefinedAtomV1::referencesBegin() const {
+  uintptr_t index = _ivarData->referencesStartIndex;
+  const void* it = reinterpret_cast<const void*>(index);
+  return reference_iterator(*this, it);
+}
+  
+DefinedAtom::reference_iterator NativeDefinedAtomV1::referencesEnd() 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 {

Modified: lld/trunk/lib/Core/NativeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeWriter.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeWriter.cpp (original)
+++ lld/trunk/lib/Core/NativeWriter.cpp Wed Mar  7 18:18:30 2012
@@ -8,7 +8,6 @@
 //===----------------------------------------------------------------------===//
 
 #include <vector>
-#include <map>
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -26,15 +25,36 @@
 ///
 /// Class for writing native object files.
 ///
-class NativeWriter : public File::AtomHandler, 
-                     public DefinedAtom::ReferenceHandler {
+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
-    _file.forEachAtom(*this);
+    for(File::defined_iterator it=file.definedAtomsBegin(), 
+                              end=file.definedAtomsEnd(); 
+                               it != end; ++it) {
+      this->addIVarsForDefinedAtom(**it);
+    }
+    for(File::undefined_iterator it=file.undefinedAtomsBegin(), 
+                              end=file.undefinedAtomsEnd(); 
+                               it != end; ++it) {
+      this->addIVarsForUndefinedAtom(**it);
+    }
+    for(File::shared_library_iterator it=file.sharedLibraryAtomsBegin(), 
+                              end=file.sharedLibraryAtomsEnd(); 
+                               it != end; ++it) {
+      this->addIVarsForSharedLibraryAtom(**it);
+    }
+    for(File::absolute_iterator it=file.absoluteAtomsBegin(), 
+                              end=file.absoluteAtomsEnd(); 
+                               it != end; ++it) {
+      this->addIVarsForAbsoluteAtom(**it);
+    }
+
+    
+    
     // construct file header based on atom information accumulated
     makeHeader();
   }
@@ -105,8 +125,7 @@
 
 private:
 
-  // visitor routine called by forEachAtom() 
-  virtual void doDefinedAtom(const DefinedAtom& atom) {
+  void addIVarsForDefinedAtom(const DefinedAtom& atom) {
     _definedAtomIndex[&atom] = _definedAtomIvars.size();
     NativeDefinedAtomIvarsV1 ivar;
     unsigned refsCount;
@@ -119,8 +138,7 @@
     _definedAtomIvars.push_back(ivar);
   }
   
-  // visitor routine called by forEachAtom() 
-  virtual void doUndefinedAtom(const UndefinedAtom& atom) {
+  void addIVarsForUndefinedAtom(const UndefinedAtom& atom) {
     _undefinedAtomIndex[&atom] = _undefinedAtomIvars.size();
     NativeUndefinedAtomIvarsV1 ivar;
     ivar.nameOffset = getNameOffset(atom);
@@ -128,8 +146,7 @@
     _undefinedAtomIvars.push_back(ivar);
   }
   
-  // visitor routine called by forEachAtom() 
-  virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
+  void addIVarsForSharedLibraryAtom(const SharedLibraryAtom& atom) {
     _sharedLibraryAtomIndex[&atom] = _sharedLibraryAtomIvars.size();
     NativeSharedLibraryAtomIvarsV1 ivar;
     ivar.nameOffset = getNameOffset(atom);
@@ -138,8 +155,7 @@
     _sharedLibraryAtomIvars.push_back(ivar);
   }
    
-  // visitor routine called by forEachAtom() 
-  virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
+  void addIVarsForAbsoluteAtom(const AbsoluteAtom& atom) {
     _absoluteAtomIndex[&atom] = _absoluteAtomIvars.size();
     NativeAbsoluteAtomIvarsV1 ivar;
     ivar.nameOffset = getNameOffset(atom);
@@ -148,10 +164,6 @@
     _absoluteAtomIvars.push_back(ivar);
   }
 
-  // visitor routine called by forEachAtom() 
-  virtual void doFile(const File &) {
-  }
-
   // fill out native file header and chunk directory
   void makeHeader() {
     const bool hasDefines = !_definedAtomIvars.empty();
@@ -304,6 +316,7 @@
         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
@@ -403,23 +416,23 @@
     count = 0;
     size_t startRefSize = _references.size();
     uint32_t result = startRefSize;
-    atom.forEachReference(*this);
+    for (auto it=atom.referencesBegin(), end=atom.referencesEnd();
+                                                    it != end; ++it) {
+      const Reference* ref = *it;
+      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;
   }
-  
-  void doReference(const Reference& ref) {
-    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);
-  }
-  
+    
   uint32_t getTargetIndex(const Atom* target) {
     TargetToIndex::const_iterator pos = _targetsTableIndex.find(target);
     if ( pos != _targetsTableIndex.end() ) {

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Wed Mar  7 18:18:30 2012
@@ -217,29 +217,18 @@
   }
 }
 
-// helper to update targets for use with forEachReference()
-class ReferenceUpdater : public DefinedAtom::ReferenceHandler {
-public:
-		           ReferenceUpdater(SymbolTable& sym) : _symbolTable(sym) { }
-	
-	virtual void doReference(const Reference& ref) {
-    const Atom* newTarget = _symbolTable.replacement(ref.target());
-    (const_cast<Reference*>(&ref))->setTarget(newTarget);
-  }
-
-private:
-	SymbolTable&  _symbolTable;
-};
-
 
 // switch all references to undefined or coalesced away atoms
 // to the new defined atom
 void Resolver::updateReferences() {
-  ReferenceUpdater updater(_symbolTable);
-  for (std::vector<const Atom *>::iterator it = _atoms.begin();
-       it != _atoms.end(); ++it) {
-    if ( const DefinedAtom* defAtom = (*it)->definedAtom() ) {
-      defAtom->forEachReference(updater);
+  for (auto ait = _atoms.begin(); ait != _atoms.end(); ++ait) {
+    if ( const DefinedAtom* defAtom = (*ait)->definedAtom() ) {
+      for (auto rit=defAtom->referencesBegin(), end=defAtom->referencesEnd();
+                                                        rit != end; ++rit) {
+        const Reference* ref = *rit;
+        const Atom* newTarget = _symbolTable.replacement(ref->target());
+        (const_cast<Reference*>(ref))->setTarget(newTarget);
+      }
     }
   }
 }
@@ -272,8 +261,11 @@
   thisChain.previous = previous;
   thisChain.referer = &atom;
   if ( const DefinedAtom* defAtom = atom.definedAtom() ) {
-    MarkLiveReferences markRefs(*this, &thisChain);
-    defAtom->forEachReference(markRefs);
+    for (auto rit=defAtom->referencesBegin(), end=defAtom->referencesEnd();
+                                                        rit != end; ++rit) {
+      const Reference* ref = *rit;
+      this->markLive(*ref->target(), &thisChain);
+    }
   }
 }
 
@@ -382,7 +374,7 @@
   // FIX ME
 }
 
-std::vector<const Atom *> &Resolver::resolve() {
+void Resolver::resolve() {
   this->initializeState();
   this->addInitialUndefines();
   this->buildInitialAtomList();
@@ -394,7 +386,32 @@
   this->checkDylibSymbolCollisions();
   this->linkTimeOptimize();
   this->tweakAtoms();
-  return _atoms;
+  this->_result.addAtoms(_atoms);
 }
 
+void Resolver::MergedFile::addAtom(const Atom& atom) {
+  if ( const DefinedAtom* defAtom = atom.definedAtom() ) {
+    _definedAtoms._atoms.push_back(defAtom);
+  }
+  else if ( const UndefinedAtom* undefAtom = atom.undefinedAtom() ) {
+    _undefinedAtoms._atoms.push_back(undefAtom);
+  }
+  else if ( const SharedLibraryAtom* slAtom = atom.sharedLibraryAtom() ) {
+    _sharedLibraryAtoms._atoms.push_back(slAtom);
+  }
+  else if ( const AbsoluteAtom* abAtom = atom.absoluteAtom() ) {
+    _absoluteAtoms._atoms.push_back(abAtom);
+  }
+  else {
+    assert(0 && "atom has unknown definition kind");
+  }
+}
+
+void Resolver::MergedFile::addAtoms(std::vector<const Atom*>& all) {
+  for(std::vector<const Atom*>::iterator it=all.begin(); it != all.end(); ++it) {
+    this->addAtom(**it);
+  }
+}
+
+
 } // namespace lld

Modified: lld/trunk/lib/Core/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)
+++ lld/trunk/lib/Core/YamlKeyValues.cpp Wed Mar  7 18:18:30 2012
@@ -137,6 +137,7 @@
 static const ContentTypeMapping typeMappings[] = {
   { "unknown",        DefinedAtom::typeUnknown },
   { "code",           DefinedAtom::typeCode },
+  { "stub",           DefinedAtom::typeStub },
   { "resolver",       DefinedAtom::typeResolver },
   { "constant",       DefinedAtom::typeConstant },
   { "c-string",       DefinedAtom::typeCString },

Modified: lld/trunk/lib/Core/YamlReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlReader.cpp (original)
+++ lld/trunk/lib/Core/YamlReader.cpp Wed Mar  7 18:18:30 2012
@@ -20,6 +20,8 @@
 #include "lld/Core/File.h"
 #include "lld/Core/Reference.h"
 
+#include "lld/Platform/Platform.h"
+
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -297,10 +299,23 @@
     : File("path")
     , _lastRefIndex(0) {}
 
-  virtual bool forEachAtom(File::AtomHandler &) const;
-  virtual bool justInTimeforEachAtom(llvm::StringRef name,
-                                     File::AtomHandler &) const;
+  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");
+  }
+   
   void bindTargetReferences();
   void addDefinedAtom(YAMLDefinedAtom* atom, const char* refName);
   void addUndefinedAtom(UndefinedAtom* atom);
@@ -314,13 +329,13 @@
     Atom*        atom;
   };
 
-  std::vector<YAMLDefinedAtom*>   _definedAtoms;
-  std::vector<UndefinedAtom*>     _undefinedAtoms;
-  std::vector<SharedLibraryAtom*> _sharedLibraryAtoms;
-  std::vector<AbsoluteAtom*>      _absoluteAtoms;
-  std::vector<YAMLReference>      _references;
-  std::vector<NameAtomPair>       _nameToAtomMapping;
-  unsigned int                    _lastRefIndex;
+  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;
+  unsigned int                                _lastRefIndex;
 };
 
 
@@ -434,14 +449,35 @@
     return _ord;
   }
 
-  
-  virtual void forEachReference(ReferenceHandler& handler) const {
-    for (uint32_t i=_refStartIndex; i < _refEndIndex; ++i) {
-      handler.doReference(_file._references[i]);
-    }
+  DefinedAtom::reference_iterator referencesBegin() const {
+    uintptr_t index = _refStartIndex;
+    const void* it = reinterpret_cast<const void*>(index);
+    return reference_iterator(*this, it);
   }
     
-  void bindTargetReferences() {
+  DefinedAtom::reference_iterator referencesEnd() 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);
+  }
+
+  
+    
+  void bindTargetReferences() const {
     for (unsigned int i=_refStartIndex; i < _refEndIndex; ++i) {
       const char* targetName = _file._references[i]._targetName;
       Atom* targetAtom = _file.findAtom(targetName);
@@ -559,40 +595,9 @@
 
 
 
-
-bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
-  handler.doFile(*this);
-  for (std::vector<YAMLDefinedAtom *>::const_iterator it = _definedAtoms.begin();
-       it != _definedAtoms.end(); ++it) {
-    handler.doDefinedAtom(**it);
-  }
-  for (std::vector<UndefinedAtom *>::const_iterator it = _undefinedAtoms.begin();
-       it != _undefinedAtoms.end(); ++it) {
-    handler.doUndefinedAtom(**it);
-  }
-  for (std::vector<SharedLibraryAtom *>::const_iterator 
-        it = _sharedLibraryAtoms.begin();
-        it != _sharedLibraryAtoms.end(); ++it) {
-    handler.doSharedLibraryAtom(**it);
-  }
-  for (std::vector<AbsoluteAtom *>::const_iterator 
-        it = _absoluteAtoms.begin();
-        it != _absoluteAtoms.end(); ++it) {
-    handler.doAbsoluteAtom(**it);
-  }
-  
-  return true;
-}
-
-bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,
-                                     File::AtomHandler &handler) const {
-  return false;
-}
-
 void YAMLFile::bindTargetReferences() {
-    for (std::vector<YAMLDefinedAtom *>::const_iterator 
-         it = _definedAtoms.begin(); it != _definedAtoms.end(); ++it) {
-      YAMLDefinedAtom* atom = *it;   
+    for (defined_iterator it = definedAtomsBegin(); it != definedAtomsEnd(); ++it) {
+      const YAMLDefinedAtom* atom = reinterpret_cast<const YAMLDefinedAtom*>(*it);   
       atom->bindTargetReferences();
     }
 }
@@ -607,31 +612,31 @@
 }
 
 void YAMLFile::addDefinedAtom(YAMLDefinedAtom* atom, const char* refName) {
-  _definedAtoms.push_back(atom);
+  _definedAtoms._atoms.push_back(atom);
   assert(refName != NULL);
   _nameToAtomMapping.push_back(NameAtomPair(refName, atom));
 }
 
 void YAMLFile::addUndefinedAtom(UndefinedAtom* atom) {
-  _undefinedAtoms.push_back(atom);
+  _undefinedAtoms._atoms.push_back(atom);
   _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
 }
 
 void YAMLFile::addSharedLibraryAtom(SharedLibraryAtom* atom) {
-  _sharedLibraryAtoms.push_back(atom);
+  _sharedLibraryAtoms._atoms.push_back(atom);
   _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
 }
 
 void YAMLFile::addAbsoluteAtom(AbsoluteAtom* atom) {
-  _absoluteAtoms.push_back(atom);
+  _absoluteAtoms._atoms.push_back(atom);
   _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
 }
 
 
 class YAMLAtomState {
 public:
-  YAMLAtomState();
-
+  YAMLAtomState(Platform& platform);
+  
   void setName(const char *n);
   void setRefName(const char *n);
   void setAlign2(const char *n);
@@ -642,6 +647,7 @@
 
   void makeAtom(YAMLFile&);
 
+  Platform&                   _platform;
   const char *                _name;
   const char *                _refName;
   const char *                _sectionName;
@@ -666,8 +672,9 @@
 };
 
 
-YAMLAtomState::YAMLAtomState()
-  : _name(NULL)
+YAMLAtomState::YAMLAtomState(Platform& platform)
+  : _platform(platform)
+  , _name(NULL)
   , _refName(NULL)
   , _sectionName(NULL)
   , _loadName(NULL)
@@ -764,15 +771,7 @@
 
 
 void YAMLAtomState::setFixupKind(const char *s) {
-  if (strcmp(s, "pcrel32") == 0)
-    _ref._kind = 1;
-  else if (strcmp(s, "call32") == 0)
-    _ref._kind = 2;
-  else {
-    int k;
-    llvm::StringRef(s).getAsInteger(10, k);
-    _ref._kind = k;
-  }
+  _ref._kind = _platform.kindFromString(llvm::StringRef(s));
 }
 
 void YAMLAtomState::setFixupTarget(const char *s) {
@@ -800,12 +799,13 @@
 /// parseObjectText - Parse the specified YAML formatted MemoryBuffer
 /// into lld::File object(s) and append each to the specified vector<File*>.
 llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
-                                , std::vector<File *> &result) {
+                                , Platform& platform
+                                , std::vector<const File *> &result) {
   std::vector<const YAML::Entry *> entries;
   YAML::parse(mb, entries);
 
   YAMLFile *file = NULL;
-  YAMLAtomState atomState;
+  YAMLAtomState atomState(platform);
   bool inAtoms       = false;
   bool inFixups      = false;
   int depthForAtoms  = -1;
@@ -985,13 +985,14 @@
 // Fill in vector<File*> from path to input text file.
 //
 llvm::error_code parseObjectTextFileOrSTDIN(llvm::StringRef path
-                                 , std::vector<File*>& result) {
+                                          , Platform&  platform
+                                          , std::vector<const File*>& result) {
   llvm::OwningPtr<llvm::MemoryBuffer> mb;
   llvm::error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb);
   if ( ec ) 
       return ec;
       
-  return parseObjectText(mb.get(), result);
+  return parseObjectText(mb.get(), platform, result);
 }
 
 

Modified: lld/trunk/lib/Core/YamlWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlWriter.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlWriter.cpp (original)
+++ lld/trunk/lib/Core/YamlWriter.cpp Wed Mar  7 18:18:30 2012
@@ -14,6 +14,8 @@
 #include "lld/Core/File.h"
 #include "lld/Core/Reference.h"
 
+#include "lld/Platform/Platform.h"
+
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringExtras.h"
@@ -41,44 +43,50 @@
 /// In that case referencing the function by name is ambiguous, so a unique
 /// ref-name is added.
 ///
-class RefNameBuilder : public File::AtomHandler, 
-                       public DefinedAtom::ReferenceHandler {
+class RefNameBuilder {
 public:
-  RefNameBuilder() { }
-
-  virtual void doReference(const Reference& ref) {
-    // create refname for any unnamed reference target
-    if ( ref.target()->name().empty() ) {
-      char* buffer;
-      asprintf(&buffer, "L%03d", _unnamedCounter++);
-      _refNames[ref.target()] = buffer;
+  RefNameBuilder(const File& file) 
+                : _collisionCount(0), _unnamedCounter(0) { 
+    // visit all atoms
+    for(File::defined_iterator it=file.definedAtomsBegin(), 
+                              end=file.definedAtomsEnd(); 
+                               it != end; ++it) {
+      const DefinedAtom* atom = *it;  
+      // 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 (auto rit=atom->referencesBegin(), rend=atom->referencesEnd();
+                                                        rit != rend; ++rit) {
+        const Reference* ref = *rit;
+        // create refname for any unnamed reference target
+        if ( ref->target()->name().empty() ) {
+          char* buffer;
+          asprintf(&buffer, "L%03d", _unnamedCounter++);
+          _refNames[ref->target()] = buffer;
+        }
+      }
+    }
+    for(File::undefined_iterator it=file.undefinedAtomsBegin(), 
+                              end=file.undefinedAtomsEnd(); 
+                               it != end; ++it) {
+      buildDuplicateNameMap(**it);
+    }
+    for(File::shared_library_iterator it=file.sharedLibraryAtomsBegin(), 
+                              end=file.sharedLibraryAtomsEnd(); 
+                               it != end; ++it) {
+      buildDuplicateNameMap(**it);
+    }
+    for(File::absolute_iterator it=file.absoluteAtomsBegin(), 
+                              end=file.absoluteAtomsEnd(); 
+                               it != end; ++it) {
+      buildDuplicateNameMap(**it);
     }
-  }
 
-  virtual void doFile(const File &) { }
-  
-  virtual void doDefinedAtom(const DefinedAtom& atom) {
-    // 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.
-    _unnamedCounter = 0;
-    atom.forEachReference(*this);
-  }
-  
-  virtual void doUndefinedAtom(const UndefinedAtom& atom) {
-    buildDuplicateNameMap(atom);
-  }
   
-  virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
-    buildDuplicateNameMap(atom);
-  }
-
-  virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
-    buildDuplicateNameMap(atom);
   }
-                         
+                           
   void buildDuplicateNameMap(const Atom& atom) {
     assert(!atom.name().empty());
     NameToAtom::iterator pos = _nameMap.find(atom.name());
@@ -131,27 +139,55 @@
 ///
 /// Helper class for writeObjectText() to write out atoms in yaml format.
 ///
-class AtomWriter : public File::AtomHandler,
-                   public DefinedAtom::ReferenceHandler {
+class AtomWriter {
 public:
-  AtomWriter(RefNameBuilder& rnb, llvm::raw_ostream &out) 
-    : _out(out), _rnb(rnb), _firstAtom(true) { }
+  AtomWriter(const File& file, Platform& platform, RefNameBuilder& rnb) 
+    : _file(file), _platform(platform), _rnb(rnb), _firstAtom(true) { }
+
+
+  void write(llvm::raw_ostream& out) {
+    // write header 
+    out << "---\n";
+    
+    // visit all atoms
+    for(File::defined_iterator it=_file.definedAtomsBegin(), 
+                              end=_file.definedAtomsEnd(); 
+                               it != end; ++it) {
+      writeDefinedAtom(**it, out);
+    }
+    for(File::undefined_iterator it=_file.undefinedAtomsBegin(), 
+                              end=_file.undefinedAtomsEnd(); 
+                               it != end; ++it) {
+      writeUndefinedAtom(**it, out);
+    }
+    for(File::shared_library_iterator it=_file.sharedLibraryAtomsBegin(), 
+                              end=_file.sharedLibraryAtomsEnd(); 
+                               it != end; ++it) {
+      writeSharedLibraryAtom(**it, out);
+    }
+    for(File::absolute_iterator it=_file.absoluteAtomsBegin(), 
+                              end=_file.absoluteAtomsEnd(); 
+                               it != end; ++it) {
+      writeAbsoluteAtom(**it, out);
+    }
+    
+    out << "...\n";
+  }
 
-  virtual void doFile(const class File &) { _firstAtom = true; }
   
-  virtual void doDefinedAtom(const class DefinedAtom &atom) {
+  void writeDefinedAtom(const DefinedAtom &atom, llvm::raw_ostream& out) {
     if ( _firstAtom ) {
-      _out << "atoms:\n";
+      out << "atoms:\n";
       _firstAtom = false;
     }
     else {
       // add blank line between atoms for readability
-      _out << "\n";
+      out << "\n";
     }
     
     bool hasDash = false;
     if ( !atom.name().empty() ) {
-      _out  << "    - "
+      out   << "    - "
             << KeyValues::nameKeyword
             << ":"
             << spacePadding(KeyValues::nameKeyword)
@@ -161,7 +197,7 @@
     }
      
     if ( _rnb.hasRefName(&atom) ) {
-      _out  << (hasDash ? "      " : "    - ")
+      out   << (hasDash ? "      " : "    - ")
             << KeyValues::refNameKeyword
             << ":"
             << spacePadding(KeyValues::refNameKeyword)
@@ -171,7 +207,7 @@
     }
     
     if ( atom.definition() != KeyValues::definitionDefault ) {
-      _out  << (hasDash ? "      " : "    - ")
+      out   << (hasDash ? "      " : "    - ")
             << KeyValues::definitionKeyword 
             << ":"
             << spacePadding(KeyValues::definitionKeyword)
@@ -181,7 +217,7 @@
     }
     
     if ( atom.scope() != KeyValues::scopeDefault ) {
-      _out  << (hasDash ? "      " : "    - ")
+      out   << (hasDash ? "      " : "    - ")
             << KeyValues::scopeKeyword 
             << ":"
             << spacePadding(KeyValues::scopeKeyword)
@@ -191,7 +227,7 @@
     }
     
      if ( atom.interposable() != KeyValues::interposableDefault ) {
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::interposableKeyword 
             << ":"
             << spacePadding(KeyValues::interposableKeyword)
@@ -200,7 +236,7 @@
     }
     
     if ( atom.merge() != KeyValues::mergeDefault ) {
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::mergeKeyword 
             << ":"
             << spacePadding(KeyValues::mergeKeyword)
@@ -209,7 +245,7 @@
     }
     
     if ( atom.contentType() != KeyValues::contentTypeDefault ) {
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::contentTypeKeyword 
             << ":"
             << spacePadding(KeyValues::contentTypeKeyword)
@@ -218,7 +254,7 @@
     }
 
     if ( atom.deadStrip() != KeyValues::deadStripKindDefault ) {
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::deadStripKindKeyword 
             << ":"
             << spacePadding(KeyValues::deadStripKindKeyword)
@@ -227,14 +263,14 @@
     }
 
     if ( atom.sectionChoice() != KeyValues::sectionChoiceDefault ) {
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::sectionChoiceKeyword 
             << ":"
             << spacePadding(KeyValues::sectionChoiceKeyword)
             << KeyValues::sectionChoice(atom.sectionChoice()) 
             << "\n";
       assert( ! atom.customSectionName().empty() );
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::sectionNameKeyword 
             << ":"
             << spacePadding(KeyValues::sectionNameKeyword)
@@ -243,7 +279,7 @@
     }
 
     if ( atom.isThumb() != KeyValues::isThumbDefault ) {
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::isThumbKeyword 
             << ":"
             << spacePadding(KeyValues::isThumbKeyword)
@@ -252,7 +288,7 @@
     }
 
     if ( atom.isAlias() != KeyValues::isAliasDefault ) {
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::isAliasKeyword 
             << ":"
             << spacePadding(KeyValues::isAliasKeyword)
@@ -262,7 +298,7 @@
 
     if ( (atom.contentType() != DefinedAtom::typeZeroFill) 
                                    && (atom.size() != 0) ) {
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::contentKeyword 
             << ":"
             << spacePadding(KeyValues::contentKeyword)
@@ -271,77 +307,77 @@
       bool needComma = false;
       for (unsigned int i=0; i < arr.size(); ++i) {
         if ( needComma )
-          _out << ", ";
-        _out << hexdigit(arr[i] >> 4);
-        _out << hexdigit(arr[i] & 0x0F);
+          out  << ", ";
+        out  << hexdigit(arr[i] >> 4);
+        out  << hexdigit(arr[i] & 0x0F);
         needComma = true;
       }
-      _out << " ]\n";
+      out  << " ]\n";
     }
 
-    _wroteFirstFixup = false;
-    atom.forEachReference(*this);
-  }
-    
-  virtual void doReference(const Reference& ref) {
-    if ( !_wroteFirstFixup ) {
-      _out << "      fixups:\n";
-      _wroteFirstFixup = true;
-    }
-    _out  << "      - "
-          << KeyValues::fixupsOffsetKeyword
-          << ":"
-          << spacePadding(KeyValues::fixupsOffsetKeyword)
-          << ref.offsetInAtom()
-          << "\n";
-    _out  << "        "
-          << KeyValues::fixupsKindKeyword
-          << ":"
-          << spacePadding(KeyValues::fixupsKindKeyword)
-          << ref.kind()
-          << "\n";
-    const Atom* target = ref.target();
-    if ( target != NULL ) {
-      llvm::StringRef refName = target->name();
-      if ( _rnb.hasRefName(target) )
-        refName = _rnb.refName(target);
-      assert(!refName.empty());
-      _out  << "        "
-            << KeyValues::fixupsTargetKeyword
-            << ":"
-            << spacePadding(KeyValues::fixupsTargetKeyword)
-            << refName 
-            << "\n";
-    }
-    if ( ref.addend() != 0 ) {
-      _out  << "        "
-            << KeyValues::fixupsAddendKeyword
+    bool wroteFirstFixup = false;
+    for (auto it=atom.referencesBegin(), end=atom.referencesEnd();
+                                                    it != end; ++it) {
+      const Reference* ref = *it;
+      if ( !wroteFirstFixup ) {
+        out  << "      fixups:\n";
+        wroteFirstFixup = true;
+      }
+      out   << "      - "
+            << KeyValues::fixupsOffsetKeyword
             << ":"
-            << spacePadding(KeyValues::fixupsAddendKeyword)
-            << ref.addend()
+            << spacePadding(KeyValues::fixupsOffsetKeyword)
+            << ref->offsetInAtom()
             << "\n";
+      out   << "        "
+            << KeyValues::fixupsKindKeyword
+            << ":"
+            << spacePadding(KeyValues::fixupsKindKeyword)
+            << _platform.kindToString(ref->kind())
+            << "\n";
+      const Atom* target = ref->target();
+      if ( target != NULL ) {
+        llvm::StringRef refName = target->name();
+        if ( _rnb.hasRefName(target) )
+          refName = _rnb.refName(target);
+        assert(!refName.empty());
+        out   << "        "
+              << KeyValues::fixupsTargetKeyword
+              << ":"
+              << spacePadding(KeyValues::fixupsTargetKeyword)
+              << refName 
+              << "\n";
+      }
+      if ( ref->addend() != 0 ) {
+        out   << "        "
+              << KeyValues::fixupsAddendKeyword
+              << ":"
+              << spacePadding(KeyValues::fixupsAddendKeyword)
+              << ref->addend()
+              << "\n";
+      }
     }
   }
+    
 
-
-  virtual void doUndefinedAtom(const class UndefinedAtom &atom) {
+  void writeUndefinedAtom(const UndefinedAtom &atom, llvm::raw_ostream& out) {
     if ( _firstAtom ) {
-      _out << "atoms:\n";
+      out  << "atoms:\n";
       _firstAtom = false;
     }
     else {
       // add blank line between atoms for readability
-      _out << "\n";
+      out  << "\n";
     }
         
-    _out  << "    - "
+    out   << "    - "
           << KeyValues::nameKeyword
           << ":"
           << spacePadding(KeyValues::nameKeyword)
           << atom.name() 
           << "\n";
 
-    _out  << "      " 
+    out   << "      " 
           << KeyValues::definitionKeyword 
           << ":"
           << spacePadding(KeyValues::definitionKeyword)
@@ -349,7 +385,7 @@
           << "\n";
 
     if ( atom.canBeNull() != KeyValues::canBeNullDefault ) {
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::canBeNullKeyword 
             << ":"
             << spacePadding(KeyValues::canBeNullKeyword)
@@ -358,24 +394,24 @@
     }
   }
 
-   virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
+  void writeSharedLibraryAtom(const SharedLibraryAtom& atom, llvm::raw_ostream& out) {
     if ( _firstAtom ) {
-      _out << "atoms:\n";
+      out  << "atoms:\n";
       _firstAtom = false;
     }
     else {
       // add blank line between atoms for readability
-      _out << "\n";
+      out  << "\n";
     }
         
-    _out  << "    - "
+    out   << "    - "
           << KeyValues::nameKeyword
           << ":"
           << spacePadding(KeyValues::nameKeyword)
           << atom.name() 
           << "\n";
 
-    _out  << "      " 
+    out   << "      " 
           << KeyValues::definitionKeyword 
           << ":"
           << spacePadding(KeyValues::definitionKeyword)
@@ -383,7 +419,7 @@
           << "\n";
 
     if ( !atom.loadName().empty() ) {
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::loadNameKeyword 
             << ":"
             << spacePadding(KeyValues::loadNameKeyword)
@@ -392,7 +428,7 @@
     }
 
     if ( atom.canBeNullAtRuntime() ) {
-      _out  << "      " 
+      out   << "      " 
             << KeyValues::canBeNullKeyword 
             << ":"
             << spacePadding(KeyValues::canBeNullKeyword)
@@ -401,37 +437,37 @@
     }
    }
    
-   virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
+  void writeAbsoluteAtom(const AbsoluteAtom& atom, llvm::raw_ostream& out) {
      if ( _firstAtom ) {
-      _out << "atoms:\n";
+      out << "atoms:\n";
       _firstAtom = false;
     }
     else {
       // add blank line between atoms for readability
-      _out << "\n";
+      out << "\n";
     }
         
-    _out  << "    - "
+    out   << "    - "
           << KeyValues::nameKeyword
           << ":"
           << spacePadding(KeyValues::nameKeyword)
           << atom.name() 
           << "\n";
 
-    _out  << "      " 
+    out   << "      " 
           << KeyValues::definitionKeyword 
           << ":"
           << spacePadding(KeyValues::definitionKeyword)
           << KeyValues::definition(atom.definition()) 
           << "\n";
     
-    _out  << "      " 
+    out   << "      " 
           << KeyValues::valueKeyword 
           << ":"
           << spacePadding(KeyValues::valueKeyword)
           << "0x";
-     _out.write_hex(atom.value());
-     _out << "\n";
+     out.write_hex(atom.value());
+     out << "\n";
    }
                      
 
@@ -450,10 +486,10 @@
       return 'A' + nibble - 0x0A;
   }
 
-  llvm::raw_ostream&  _out;
-  RefNameBuilder      _rnb;
+  const File&         _file;
+  Platform&           _platform;
+  RefNameBuilder&     _rnb;
   bool                _firstAtom;
-  bool                _wroteFirstFixup;
 };
 
 } // anonymous namespace
@@ -464,16 +500,14 @@
 /// writeObjectText - writes the lld::File object as in YAML
 /// format to the specified stream.
 ///
-void writeObjectText(const File &file, llvm::raw_ostream &out) {
+void writeObjectText(const File& file, Platform& platform, 
+                      llvm::raw_ostream &out) {
   // Figure what ref-name labels are needed
-  RefNameBuilder rnb;
-  file.forEachAtom(rnb);
+  RefNameBuilder rnb(file);
   
   // Write out all atoms
-  AtomWriter h(rnb, out);
-  out << "---\n";
-  file.forEachAtom(h);
-  out << "...\n";
+  AtomWriter writer(file, platform, rnb);
+  writer.write(out);
 }
 
 } // namespace yaml

Added: lld/trunk/lib/Passes/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/CMakeLists.txt?rev=152269&view=auto
==============================================================================
--- lld/trunk/lib/Passes/CMakeLists.txt (added)
+++ lld/trunk/lib/Passes/CMakeLists.txt Wed Mar  7 18:18:30 2012
@@ -0,0 +1,3 @@
+add_lld_library(lldPasses
+  StubsPass.cpp
+  )

Added: lld/trunk/lib/Passes/StubsPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/StubsPass.cpp?rev=152269&view=auto
==============================================================================
--- lld/trunk/lib/Passes/StubsPass.cpp (added)
+++ lld/trunk/lib/Passes/StubsPass.cpp Wed Mar  7 18:18:30 2012
@@ -0,0 +1,79 @@
+//===- Passes/StubsPass.cpp - Adds stubs ----------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//
+// This linker pass is 
+//
+//
+//
+//
+
+
+#include "llvm/ADT/DenseMap.h"
+
+#include "lld/Core/Pass.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+#include "lld/Platform/Platform.h"
+
+
+namespace lld {
+
+void StubsPass::perform() {
+  // Skip this pass if output format does not need stubs.
+  if ( !_platform.outputUsesStubs() )
+    return;
+  
+  // Use map so all call sites to same shlib symbol use same stub
+  llvm::DenseMap<const SharedLibraryAtom*, const Atom*> shlibToStub;
+  
+  // Scan all references in all atoms.
+  for(auto ait=_file.definedAtomsBegin(), aend=_file.definedAtomsEnd(); 
+                                                      ait != aend; ++ait) {
+    const DefinedAtom* atom = *ait;
+    for (auto rit=atom->referencesBegin(), rend=atom->referencesEnd(); 
+                                                      rit != rend; ++rit) {
+      const Reference* ref = *rit;
+      const Atom* target = ref->target();
+      assert(target != NULL);
+      // If the target of this reference is in a shared library
+      if ( const SharedLibraryAtom* shlbTarget = target->sharedLibraryAtom() ) {
+        // and this is a call to that shared library symbol.
+        if ( _platform.isBranch(ref) ) {
+          const Atom* stub;
+          // Replace the target with a reference to a stub
+          auto pos = shlibToStub.find(shlbTarget);
+          if ( pos == shlibToStub.end() ) {
+            // This is no existing stub.  Create a new one.
+            stub = _platform.makeStub(*shlbTarget, _file);
+            shlibToStub[shlbTarget] = stub;
+          }
+          else {
+            // Reuse and existing stub
+            stub = pos->second;
+          }
+          assert(stub != NULL);
+          // Switch call site in atom to refrence stub instead of shlib atom.
+          (const_cast<Reference*>(ref))->setTarget(stub);
+        }
+      }
+    }
+  }
+  
+  // add all created stubs to file
+  for (auto it=shlibToStub.begin(), end=shlibToStub.end(); it != end; ++it) {
+    _file.addAtom(*it->second);
+  }
+  
+
+}
+
+
+
+}

Added: lld/trunk/test/pass-stubs-basic.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pass-stubs-basic.objtxt?rev=152269&view=auto
==============================================================================
--- lld/trunk/test/pass-stubs-basic.objtxt (added)
+++ lld/trunk/test/pass-stubs-basic.objtxt Wed Mar  7 18:18:30 2012
@@ -0,0 +1,50 @@
+# RUN: lld-core %s -stubs_pass  | FileCheck %s
+
+#
+# Test that stubs pass adds stubs and rebinds call sites to the stub
+#
+
+---
+atoms:
+    - name:              foo
+      type:              code
+      content:           [ E8, 00, 00, 00, 00, E8, 00, 00, 00, 
+                           00, 48 ,8B, 05, 00, 00, 00, 00 ]
+      fixups:
+      - offset:          1
+        kind:            call32
+        target:          malloc
+      - offset:          6
+        kind:            call32
+        target:          free
+      - offset:          13
+        kind:            gotLoad32
+        target:          malloc
+
+    - name:              malloc
+      definition:        shared-library
+      load-name:         libc.so
+      
+    - name:              free
+      definition:        shared-library
+      load-name:         libc.so
+
+...
+
+# CHECK:       name:         foo
+# CHECK:       fixups: 
+# CHECK:       kind:         call32
+# CHECK:       target:       L
+# CHECK:       kind:         call32
+# CHECK:       target:       L
+# CHECK:       kind:         gotLoad32
+# CHECK:       target:       malloc
+# CHECK:       name:         L
+# CHECK:       type:         stub
+# CHECK:       name:         L
+# CHECK:       type:         stub
+# CHECK:       name:         malloc
+# CHECK:       definition:   shared-library
+# CHECK:       name:         free
+# CHECK:       definition:   shared-library
+# CHECK:       ...

Modified: lld/trunk/tools/lld-core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/CMakeLists.txt?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/CMakeLists.txt (original)
+++ lld/trunk/tools/lld-core/CMakeLists.txt Wed Mar  7 18:18:30 2012
@@ -1,5 +1,6 @@
 set(LLVM_USED_LIBS
   lldCore
+  lldPasses
   )
 
 set(LLVM_LINK_COMPONENTS

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=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Wed Mar  7 18:18:30 2012
@@ -11,6 +11,7 @@
 #include "lld/Core/Atom.h"
 #include "lld/Core/DefinedAtom.h"
 #include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/Pass.h"
 #include "lld/Core/Resolver.h"
 #include "lld/Core/YamlReader.h"
 #include "lld/Core/YamlWriter.h"
@@ -22,6 +23,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -49,15 +51,110 @@
 }
 
 namespace {
-class LdCore : public InputFiles, public Platform {
+
+
+//
+// Simple atoms created by the stubs pass.
+//
+class TestingStubAtom : public DefinedAtom {
 public:
-  LdCore(std::vector<File *> &f) : _files(f) { }
+        TestingStubAtom(const File& f, const SharedLibraryAtom& shlib) :
+                        _file(f), _shlib(shlib) {
+          static uint32_t lastOrdinal = 0;
+          _ordinal = lastOrdinal++; 
+        }
 
-  // InputFiles interface
-  virtual void forEachInitialAtom(File::AtomHandler &) const;
-  virtual bool searchLibraries(llvm::StringRef name, bool searchDylibs,
-                               bool searchArchives, bool dataSymbolOnly,
-                               File::AtomHandler &) const;
+  virtual const File& file() const {
+    return _file;
+  }
+
+  virtual llvm::StringRef name() const {
+    return llvm::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 llvm::StringRef customSectionName() const {
+    return llvm::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 llvm::ArrayRef<uint8_t> rawContent() const {
+    return llvm::ArrayRef<uint8_t>();
+  }
+  
+  virtual reference_iterator referencesBegin() const {
+    return reference_iterator(*this, NULL);
+  }
+  
+  virtual reference_iterator referencesEnd() const {
+    return reference_iterator(*this, NULL);
+  }
+  
+  virtual const Reference* derefIterator(const void* iter) const {
+    return NULL;
+  }
+  
+  virtual void incrementIterator(const void*& iter) const {
+  
+  }
+  
+private:
+  const File&               _file;
+  const SharedLibraryAtom&  _shlib;
+  uint32_t                  _ordinal;
+};
+
+
+//
+// A simple platform for testing.
+//
+class TestingPlatform : public Platform {
+public:
 
   virtual void initialize() { }
 
@@ -155,97 +252,163 @@
   // last chance for platform to tweak atoms
   virtual void postResolveTweaks(std::vector<const Atom *> &all) {}
 
-private:
-  std::vector<File *> &_files;
-};
-}
+  virtual bool outputUsesStubs() { return true; };
+  
+
+  struct KindMapping {
+    const char*           string;
+    Reference::Kind       value;
+    bool                  isBranch;
+  };
 
-void LdCore::forEachInitialAtom(File::AtomHandler &handler) const {
-  for (std::vector<File *>::iterator it = _files.begin();
-       it != _files.end(); ++it) {
-    const File *file = *it;
-    handler.doFile(*file);
-    file->forEachAtom(handler);
+  static const KindMapping _s_kindMappings[]; 
+  
+  virtual Reference::Kind kindFromString(llvm::StringRef kindName) {
+    for (const KindMapping* p = _s_kindMappings; p->string != NULL; ++p) {
+      if ( kindName.equals(p->string) )
+        return p->value;
+    }
+    int k;
+    kindName.getAsInteger(0, k);
+    return k;
+  }
+  
+  virtual llvm::StringRef kindToString(Reference::Kind value) {
+    for (const KindMapping* p = _s_kindMappings; p->string != NULL; ++p) {
+      if ( value == p->value)
+        return p->string;
+    }
+    return llvm::StringRef("???");
   }
-}
 
-bool LdCore::searchLibraries(llvm::StringRef name, bool searchDylibs,
-                             bool searchArchives, bool dataSymbolOnly,
-                             File::AtomHandler &) const {
-  return false;
-}
 
-namespace {
-class MergedFile : public File {
+  virtual bool isBranch(const Reference* ref) { 
+    Reference::Kind value = ref->kind();
+    for (const KindMapping* p = _s_kindMappings; p->string != NULL; ++p) {
+      if ( value == p->value )
+        return p->isBranch;
+    }
+    return false;
+  }
+  
+  virtual const Atom* makeStub(const SharedLibraryAtom& shlibAtom, File& file) {
+    return new TestingStubAtom(file, shlibAtom);
+  }
+};
+
+
+//
+// Table of fixup kinds in YAML documents used for testing
+//
+const TestingPlatform::KindMapping TestingPlatform::_s_kindMappings[] = {
+    { "call32",         1,    true },
+    { "pcrel32",        2,    false },
+    { "gotLoad32",      3,    false },
+    { NULL,             0,    false }
+  };
+
+
+//
+// A simple input files wrapper for testing.
+//
+class TestingInputFiles : public InputFiles {
 public:
-  MergedFile(std::vector<const Atom *> &a)
-    : File("path"), _atoms(a) { }
+  TestingInputFiles(std::vector<const File*>& f) : _files(f) { }
 
-  virtual bool forEachAtom(File::AtomHandler &handler) const {
-    handler.doFile(*this);
-    // visit defined atoms
-    for (std::vector<const Atom *>::iterator it = _atoms.begin();
-         it != _atoms.end(); ++it) {
-      const DefinedAtom* atom = (*it)->definedAtom();
-      if ( atom ) 
-          handler.doDefinedAtom(*atom);
-    }
-    // visit undefined atoms
-    for (std::vector<const Atom *>::iterator it = _atoms.begin();
-         it != _atoms.end(); ++it) {
-      const UndefinedAtom* atom = (*it)->undefinedAtom();
-      if ( atom ) 
-          handler.doUndefinedAtom(*atom);
-    }
-    // visit shared library atoms
-    for (std::vector<const Atom *>::iterator it = _atoms.begin();
-         it != _atoms.end(); ++it) {
-      const SharedLibraryAtom* atom = (*it)->sharedLibraryAtom();
-      if ( atom ) 
-          handler.doSharedLibraryAtom(*atom);
-    }
-    // visit absolute atoms
-    for (std::vector<const Atom *>::iterator it = _atoms.begin();
-         it != _atoms.end(); ++it) {
-      const AbsoluteAtom* atom = (*it)->absoluteAtom();
-      if ( atom ) 
-          handler.doAbsoluteAtom(*atom);
+  // InputFiles interface
+  virtual void forEachInitialAtom(InputFiles::Handler& handler) const {
+    for (std::vector<const File *>::iterator fit = _files.begin();
+                                       fit != _files.end(); ++fit) {
+      const File* file = *fit;
+      handler.doFile(*file);
+      for(auto it=file->definedAtomsBegin(),end=file->definedAtomsEnd(); 
+                                 it != end; ++it) {
+        handler.doDefinedAtom(**it);
+      }
+      for(auto it=file->undefinedAtomsBegin(), end=file->undefinedAtomsEnd(); 
+                                 it != end; ++it) {
+        handler.doUndefinedAtom(**it);
+      }
+      for(auto it=file->sharedLibraryAtomsBegin(), end=file->sharedLibraryAtomsEnd(); 
+                                 it != end; ++it) {
+        handler.doSharedLibraryAtom(**it);
+      }
+      for(auto it=file->absoluteAtomsBegin(),end=file->absoluteAtomsEnd(); 
+                                 it != end; ++it) {
+        handler.doAbsoluteAtom(**it);
+      }
     }
-    return true;
   }
 
-  virtual bool justInTimeforEachAtom(llvm::StringRef name,
-                                     File::AtomHandler &) const {
+  virtual bool searchLibraries(llvm::StringRef name, bool searchDylibs,
+                               bool searchArchives, bool dataSymbolOnly,
+                               InputFiles::Handler &) const {
     return false;
   }
 
+
 private:
-  std::vector<const Atom *> &_atoms;
+  std::vector<const File*>&        _files;
 };
-} //anonymous namespace
+}
+
+
+
 
 
-int main(int argc, const char *argv[]) {
+
+llvm::cl::opt<std::string> 
+gInputFilePath(llvm::cl::Positional,
+              llvm::cl::desc("<input file>"),
+              llvm::cl::init("-"));
+
+llvm::cl::opt<std::string> 
+gOutputFilePath("o", 
+              llvm::cl::desc("Specify output filename"), 
+              llvm::cl::value_desc("filename"));
+
+llvm::cl::opt<bool> 
+gDoStubsPass("stubs_pass", 
+          llvm::cl::desc("Run pass to create stub atoms"));
+
+
+int main(int argc, char *argv[]) {
   // Print a stack trace if we signal out.
   llvm::sys::PrintStackTraceOnErrorSignal();
   llvm::PrettyStackTraceProgram X(argc, argv);
   llvm::llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
 
+  // parse options
+  llvm::cl::ParseCommandLineOptions(argc, argv);
+
+  // create platform for testing
+  TestingPlatform testingPlatform;
+  
   // read input YAML doc into object file(s)
-  std::vector<File *> files;
-  if (error(yaml::parseObjectTextFileOrSTDIN(llvm::StringRef(argv[1]), files)))
+  std::vector<const File *> files;
+  if (error(yaml::parseObjectTextFileOrSTDIN(gInputFilePath, 
+                                            testingPlatform, files))) {
     return 1;
-
+  }
+  
+  // create object to mange input files
+  TestingInputFiles inputFiles(files);
+  
   // merge all atom graphs
-  LdCore core(files);
-  Resolver resolver(core, core);
-  std::vector<const Atom *> &mergedAtoms = resolver.resolve();
-  MergedFile outFile(mergedAtoms);
+  Resolver resolver(testingPlatform, inputFiles);
+  resolver.resolve();
 
+  // run passes
+  if ( gDoStubsPass ) {
+    StubsPass  addStubs(resolver.resultFile(), testingPlatform);
+    addStubs.perform();
+  }
+  
   // write new atom graph out as YAML doc
   std::string errorInfo;
-  llvm::raw_fd_ostream out("-", errorInfo);
-//  yaml::writeObjectText(outFile, out);
+  const char* outPath = gOutputFilePath.empty() ? "-" : gOutputFilePath.c_str();
+  llvm::raw_fd_ostream out(outPath, errorInfo);
+//  yaml::writeObjectText(resolver.resultFile(), out);
 
   // make unique temp .o file to put generated object file
   int fd;
@@ -254,7 +417,7 @@
   llvm::raw_fd_ostream  binaryOut(fd, /*shouldClose=*/true);
   
   // write native file
-  writeNativeObjectFile(outFile, binaryOut);
+  writeNativeObjectFile(resolver.resultFile(), binaryOut);
   binaryOut.close();  // manually close so that file can be read next
 
 //  out << "native file: " << tempPath.str() << "\n";
@@ -265,7 +428,7 @@
 	return 1;
 	
   // write new atom graph out as YAML doc
-  yaml::writeObjectText(*natFile, out);
+  yaml::writeObjectText(*natFile, testingPlatform, out);
 
   // delete temp .o file
   bool existed;





More information about the llvm-commits mailing list