[llvm-commits] [lld] r155060 - in /lld/trunk: ./ docs/ include/lld/Core/ lib/Core/ lib/Platforms/Darwin/ test/ tools/lld-core/

Nick Kledzik kledzik at apple.com
Wed Apr 18 14:55:06 PDT 2012


Author: kledzik
Date: Wed Apr 18 16:55:06 2012
New Revision: 155060

URL: http://llvm.org/viewvc/llvm-project?rev=155060&view=rev
Log:
Factor out core linking options from Platform in a new ResolverOptions
class.  Change Resolver to no longer use Platform.  Core linking
now issues errors directly.  We need to factor that out later.

Rework how Darwin executable writer finds "main" atom.  It now
adds to core linking an Atom  which has a Reference to "main".  

Added:
    lld/trunk/lib/Platforms/Darwin/ExecutableAtoms.hpp
    lld/trunk/lib/Platforms/Darwin/SimpleAtoms.hpp
    lld/trunk/test/undef-coalesce-error.objtxt
Modified:
    lld/trunk/CMakeLists.txt
    lld/trunk/docs/design.rst
    lld/trunk/include/lld/Core/File.h
    lld/trunk/include/lld/Core/InputFiles.h
    lld/trunk/include/lld/Core/Platform.h
    lld/trunk/include/lld/Core/Resolver.h
    lld/trunk/include/lld/Core/SymbolTable.h
    lld/trunk/lib/Core/File.cpp
    lld/trunk/lib/Core/Resolver.cpp
    lld/trunk/lib/Core/SymbolTable.cpp
    lld/trunk/lib/Core/YamlKeyValues.cpp
    lld/trunk/lib/Core/YamlWriter.cpp
    lld/trunk/lib/Platforms/Darwin/DarwinPlatform.cpp
    lld/trunk/lib/Platforms/Darwin/DarwinPlatform.h
    lld/trunk/lib/Platforms/Darwin/DarwinReferenceKinds.cpp
    lld/trunk/lib/Platforms/Darwin/ExecutableWriter.cpp
    lld/trunk/lib/Platforms/Darwin/StubAtoms.hpp
    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=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/CMakeLists.txt (original)
+++ lld/trunk/CMakeLists.txt Wed Apr 18 16:55:06 2012
@@ -73,6 +73,13 @@
   else( SUPPORTS_CXX11_FLAG )
     message(WARNING "-std=c++0x not supported.")
   endif()
+  check_cxx_compiler_flag("-stdlib=libc++" SUPPORTS_LIBCXX_FLAG)
+  if( SUPPORTS_LIBCXX_FLAG )
+    message(STATUS "Building with -stdlib=libc++")
+    set(CMAKE_CXX_FLAGS "-stdlib=libc++ ${CMAKE_CXX_FLAGS}")
+  else( SUPPORTS_LIBCXX_FLAG )
+    message(WARNING "-stdlib=libc++ not supported.")
+  endif()
 endif()
 
 

Modified: lld/trunk/docs/design.rst
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/design.rst?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/docs/design.rst (original)
+++ lld/trunk/docs/design.rst Wed Apr 18 16:55:06 2012
@@ -144,7 +144,7 @@
 "live".  When done, all atoms not marked "live" are removed.
 
 The result of the Resolving phase is the creation of an lld::File object.  The
-goal is that the lld::File model is <b>the</b> internal representation
+goal is that the lld::File model is **the** internal representation
 throughout the linker. The file readers parse (mach-o, ELF, COFF) into an
 lld::File.  The file writers (mach-o, ELF, COFF) taken an lld::File and produce
 their file kind, and every Pass only operates on an lld::File.  This is not only
@@ -196,6 +196,19 @@
 object.  The writer's job is to create the executable content file wrapper and
 place the content of the atoms into it.
 
+Sometimes the output generator needs access to particular atoms (for instance,
+it may need to know which atom is "main" in order to specifiy the entry 
+point in the executable.  The way to do this is to have the platform create
+an Atom with a Reference to the required atom(s) and provide this atom
+in the initialize set of atoms for the resolver.  If a particular symbol name
+is required, this arrangment will also cause core linking to fail if the
+symbol is not defined (e.g. "main" is undefined).
+
+Sometimes a platform supports lazily created symbols.  To support this, the
+platform can create a File object which vends no initial atoms, but does
+lazily supply atoms by name as needed.  
+
+
 lld::File representations
 -------------------------
 

Modified: lld/trunk/include/lld/Core/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/File.h?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/File.h (original)
+++ lld/trunk/include/lld/Core/File.h Wed Apr 18 16:55:06 2012
@@ -49,12 +49,6 @@
   /// be ascertained, this method returns the empty string.
   virtual StringRef translationUnitSource() const;
 
-  /// Returns pointer to "main" atom, or nullptr. All object files can
-  /// use the default implementation which just returns nullptr.  
-  /// But the master merged File operated on by Passes, needs override
-  /// this and return the atom for "main". 
-  virtual const Atom *entryPoint() const; 
-
 protected:
   template <typename T> class atom_iterator; // forward reference
 public:

Modified: lld/trunk/include/lld/Core/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputFiles.h?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/InputFiles.h (original)
+++ lld/trunk/include/lld/Core/InputFiles.h Wed Apr 18 16:55:06 2012
@@ -35,6 +35,13 @@
   };
 
 
+  /// Used by platforms to insert platform specific files.
+  virtual void prependFile(const File&) = 0;
+  
+  /// Used by platforms to insert platform specific files.
+  virtual void appendFile(const File&) = 0;
+ 
+
   /// @brief iterates all atoms in initial files
   virtual void forEachInitialAtom(Handler &) const = 0;
 

Modified: lld/trunk/include/lld/Core/Platform.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Platform.h?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Platform.h (original)
+++ lld/trunk/include/lld/Core/Platform.h Wed Apr 18 16:55:06 2012
@@ -20,6 +20,7 @@
 class UndefinedAtom;
 class SharedLibraryAtom;
 class File;
+class InputFiles;
 
 
 /// The Platform class encapsulated plaform specific linking knowledge.
@@ -28,85 +29,9 @@
 class Platform {
 public:
   virtual ~Platform();
-
-  virtual void initialize() = 0;
-
-  /// @brief tell platform object another file has been added
-  virtual void fileAdded(const File &file) = 0;
-
-  /// @brief tell platform object another atom has been added
-  virtual void atomAdded(const Atom &file) = 0;
-
-  /// @brief give platform a chance to change each atom's scope
-  virtual void adjustScope(const DefinedAtom &atom) = 0;
-
-  /// @brief if specified atom needs alternate names, return AliasAtom(s)
-  virtual bool getAliasAtoms(const Atom &atom,
-                             std::vector<const DefinedAtom *>&) = 0;
-
-  /// @brief give platform a chance to resolve platform-specific undefs
-  virtual bool getPlatformAtoms(StringRef undefined,
-                                std::vector<const DefinedAtom *>&) = 0;
-
-  /// @brief resolver should remove unreferenced atoms
-  virtual bool deadCodeStripping() = 0;
-
-  /// @brief atom must be kept so should be root of dead-strip graph
-  virtual bool isDeadStripRoot(const Atom &atom) = 0;
-
-  /// @brief if target must have some atoms, denote here
-  virtual bool getImplicitDeadStripRoots(std::vector<const DefinedAtom *>&) = 0;
-
-  /// @brief return entry point for output file (e.g. "main") or nullptr
-  virtual StringRef entryPointName() = 0;
-
-  /// @brief for iterating must-be-defined symbols ("main" or -u command line
-  ///        option)
-  typedef StringRef const *UndefinesIterator;
-  virtual UndefinesIterator  initialUndefinesBegin() const = 0;
-  virtual UndefinesIterator  initialUndefinesEnd() const = 0;
-
-  /// @brief if platform wants resolvers to search libraries for overrides
-  virtual bool searchArchivesToOverrideTentativeDefinitions() = 0;
-  virtual bool searchSharedLibrariesToOverrideTentativeDefinitions() = 0;
-
-  /// @brief if platform allows symbol to remain undefined (e.g. -r)
-  virtual bool allowUndefinedSymbol(StringRef name) = 0;
-
-  /// @brief for debugging dead code stripping, -why_live
-  virtual bool printWhyLive(StringRef name) = 0;
-
-  /// When core linking finds a duplicate definition, the platform
-  /// can either print an error message and terminate or return with
-  /// which atom the linker should use.
-  virtual const Atom& handleMultipleDefinitions(const Atom& def1,
-                                                const Atom& def2) = 0;
-
-  /// @brief print out undefined symbol error messages in platform specific way
-  virtual void errorWithUndefines(const std::vector<const Atom *>& undefs,
-                                  const std::vector<const Atom *>& all) = 0;
-
-  /// When core linking finds undefined atoms from different object
-  /// files that have different canBeNull values, this method is called.
-  /// The useUndef2 parameter is set to which canBeNull setting the
-  /// linker should use, and can be changed by this method.  Or this
-  /// method can emit a warning/error about the mismatch.
-  virtual void undefineCanBeNullMismatch(const UndefinedAtom& undef1,
-                                         const UndefinedAtom& undef2,
-                                         bool& useUndef2) = 0;
-
-  /// When core linking finds shared library atoms from different object
-  /// files that have different attribute values, this method is called.
-  /// The useShlib2 parameter is set to which atom attributes the
-  /// linker should use, and can be changed by this method.  Or this
-  /// method can emit a warning/error about the mismatch.
-  virtual void sharedLibrarylMismatch(const SharedLibraryAtom& shLib1,
-                                      const SharedLibraryAtom& shLib2,
-                                      bool& useShlib2) = 0;
-
-  /// @brief last chance for platform to tweak atoms
-  virtual void postResolveTweaks(std::vector<const Atom *>& all) = 0;
-
+  
+  virtual void addFiles(InputFiles&) = 0;
+  
   /// Converts a reference kind string to a in-memory numeric value.
   /// For use with parsing YAML encoded object files.
   virtual Reference::Kind kindFromString(StringRef) = 0;

Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Wed Apr 18 16:55:06 2012
@@ -23,20 +23,104 @@
 
 class Atom;
 class InputFiles;
-class Platform;
 class SymbolTable;
 
+/// 
+/// The ResolverOptions class encapsulates options needed during core linking.
+/// To use, create a subclass whose constructor sets up the ivars.
+///
+class ResolverOptions {
+public:
+  ResolverOptions()
+    : _deadCodeStrip(false)
+    , _globalsAreDeadStripRoots(false)
+    , _searchArchivesToOverrideTentativeDefinitions(false)
+    , _searchSharedLibrariesToOverrideTentativeDefinitions(false)
+    , _warnSharedLibrariesOverridesTentativeDefinitions(false)
+    , _undefinesAreErrors(false)
+    , _warnIfCoalesableAtomsHaveDifferentCanBeNull(false)
+    , _warnIfCoalesableAtomsHaveDifferentLoadName(false) {
+  }
+  
+  /// Whether the resolver should removed unreferenced atoms.
+  bool deadCodeStripping() const {
+    return _deadCodeStrip;
+  }
+  
+  /// If dead stripping, whether all global symbols are kept. 
+  bool allGlobalsAreDeadStripRoots() const {
+    return _globalsAreDeadStripRoots;
+  }
+  
+  /// If dead stripping, names of atoms that must be kept. 
+  const std::vector<StringRef>& deadStripRootNames() const {
+    return _deadStripRootNames;
+  }
+  
+  /// Whether resolver should look in archives for a definition to 
+  /// replace a tentative defintion.
+  bool searchArchivesToOverrideTentativeDefinitions() const {
+    return _searchArchivesToOverrideTentativeDefinitions;
+  }
+  
+  /// Whether resolver should look in shared libraries for a definition to 
+  /// replace a tentative defintion.
+  bool searchSharedLibrariesToOverrideTentativeDefinitions() const {
+    return _searchSharedLibrariesToOverrideTentativeDefinitions;
+  }
+  
+  /// Whether resolver should look warn if shared library definition replaced
+  /// a tentative defintion.
+  bool warnSharedLibrariesOverridesTentativeDefinitions() const {
+    return _warnSharedLibrariesOverridesTentativeDefinitions;
+  }
+
+  /// Whether resolver should error if there are any UndefinedAtoms 
+  /// left when resolving is done.
+  bool undefinesAreErrors() const {
+    return _undefinesAreErrors;
+  }
+  
+  /// Whether resolver should warn if it discovers two UndefinedAtoms 
+  /// or two SharedLibraryAtoms with the same name, but different 
+  /// canBeNull attributes.
+  bool warnIfCoalesableAtomsHaveDifferentCanBeNull() const {
+    return _warnIfCoalesableAtomsHaveDifferentCanBeNull;
+  }
+ 
+  /// Whether resolver should warn if it discovers two SharedLibraryAtoms
+  /// with the same name, but different loadNames.
+   bool warnIfCoalesableAtomsHaveDifferentLoadName() const {
+    return _warnIfCoalesableAtomsHaveDifferentLoadName;
+  }
+ 
+protected:
+  bool  _deadCodeStrip;
+  bool  _globalsAreDeadStripRoots;
+  bool  _searchArchivesToOverrideTentativeDefinitions;
+  bool  _searchSharedLibrariesToOverrideTentativeDefinitions;
+  bool  _warnSharedLibrariesOverridesTentativeDefinitions;
+  bool  _undefinesAreErrors;
+  bool  _warnIfCoalesableAtomsHaveDifferentCanBeNull;
+  bool  _warnIfCoalesableAtomsHaveDifferentLoadName;
+  std::vector<StringRef> _deadStripRootNames;
+};
+
+
+
+///
 /// The Resolver is responsible for merging all input object files
 /// and producing a merged graph.
 ///
-/// All platform specific resolving is done by delegating to the
-/// Platform object specified.
+/// All variations in resolving are controlled by the 
+/// ResolverOptions object specified.
+///
 class Resolver : public InputFiles::Handler {
 public:
-  Resolver(Platform &plat, const InputFiles &inputs)
-    : _platform(plat)
+  Resolver(ResolverOptions &opts, const InputFiles &inputs)
+    : _options(opts)
     , _inputFiles(inputs)
-    , _symbolTable(plat)
+    , _symbolTable(opts)
     , _haveLLVMObjs(false)
     , _addToFinalSection(false)
     , _completedInitialObjectFiles(false) {}
@@ -56,13 +140,7 @@
   }
 
 private:
-  struct WhyLiveBackChain {
-    WhyLiveBackChain *previous;
-    const Atom *referer;
-  };
 
-  void initializeState();
-  void addInitialUndefines();
   void buildInitialAtomList();
   void resolveUndefines();
   void updateReferences();
@@ -73,18 +151,14 @@
   void linkTimeOptimize();
   void tweakAtoms();
 
-  const Atom *entryPoint();
-  void markLive(const Atom &atom, WhyLiveBackChain *previous);
+  void markLive(const Atom &atom);
   void addAtoms(const std::vector<const DefinedAtom *>&);
 
 
   class MergedFile : public File {
   public:
-    MergedFile() : File("<linker-internal>"), _mainAtom(nullptr) { }
+    MergedFile() : File("<linker-internal>") { }
 
-  virtual const Atom *entryPoint() const {
-    return _mainAtom;
-  }
   virtual const atom_collection<DefinedAtom>& defined() const {
     return _definedAtoms;
   }
@@ -104,7 +178,6 @@
 
   private:
     friend class Resolver;
-    const Atom*                                 _mainAtom;
     atom_collection_vector<DefinedAtom>         _definedAtoms;
     atom_collection_vector<UndefinedAtom>       _undefinedAtoms;
     atom_collection_vector<SharedLibraryAtom>   _sharedLibraryAtoms;
@@ -112,9 +185,8 @@
   };
 
 
-
-  Platform&                     _platform;
-  const InputFiles&             _inputFiles;
+  ResolverOptions              &_options;
+  const InputFiles             &_inputFiles;
   SymbolTable                   _symbolTable;
   std::vector<const Atom *>     _atoms;
   std::set<const Atom *>        _deadStripRoots;

Modified: lld/trunk/include/lld/Core/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/SymbolTable.h?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/SymbolTable.h (original)
+++ lld/trunk/include/lld/Core/SymbolTable.h Wed Apr 18 16:55:06 2012
@@ -27,7 +27,7 @@
 class UndefinedAtom;
 class SharedLibraryAtom;
 class AbsoluteAtom;
-class Platform;
+class ResolverOptions;
 
 /// The SymbolTable class is responsible for coalescing atoms.
 ///
@@ -36,7 +36,7 @@
 /// if an atom has been coalesced away.
 class SymbolTable {
 public:
-      SymbolTable(Platform& plat);
+      SymbolTable(ResolverOptions&);
 
   /// @brief add atom to symbol table
   void add(const DefinedAtom &);
@@ -92,10 +92,10 @@
   void addByName(const Atom &);
   void addByContent(const DefinedAtom &);
 
-  Platform&  _platform;
-  AtomToAtom _replacedAtoms;
-  NameToAtom _nameTable;
-  AtomContentSet _contentTable;
+  ResolverOptions &_options;
+  AtomToAtom       _replacedAtoms;
+  NameToAtom       _nameTable;
+  AtomContentSet   _contentTable;
 };
 
 } // namespace lld

Modified: lld/trunk/lib/Core/File.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/File.cpp?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/lib/Core/File.cpp (original)
+++ lld/trunk/lib/Core/File.cpp Wed Apr 18 16:55:06 2012
@@ -18,8 +18,4 @@
   return StringRef();
 }
 
-const Atom *File::entryPoint() const {
-  return nullptr;
-}
-
 }

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Wed Apr 18 16:55:06 2012
@@ -13,11 +13,11 @@
 #include "lld/Core/File.h"
 #include "lld/Core/InputFiles.h"
 #include "lld/Core/LLVM.h"
-#include "lld/Core/Platform.h"
 #include "lld/Core/SymbolTable.h"
 #include "lld/Core/UndefinedAtom.h"
 
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ErrorHandling.h"
 
 #include <algorithm>
 #include <cassert>
@@ -63,17 +63,6 @@
 };
 
 
-
-
-void Resolver::initializeState() {
-  _platform.initialize();
-}
-
-// add initial undefines from -u option
-void Resolver::addInitialUndefines() {
-
-}
-
 // add all atoms from all initial .o files
 void Resolver::buildInitialAtomList() {
   // each input files contributes initial atoms
@@ -86,8 +75,6 @@
 
 // called before the first atom in any file is added with doAtom()
 void Resolver::doFile(const File &file) {
-  // notify platform
-  _platform.fileAdded(file);
 }
 
 
@@ -102,35 +89,19 @@
 
 // called on each atom when a file is added
 void Resolver::doDefinedAtom(const DefinedAtom &atom) {
-  // notify platform
-  _platform.atomAdded(atom);
-
   // add to list of known atoms
   _atoms.push_back(&atom);
 
-  // adjust scope (e.g. force some globals to be hidden)
-  _platform.adjustScope(atom);
-
   // non-static atoms need extra handling
   if (atom.scope() != DefinedAtom::scopeTranslationUnit) {
     // tell symbol table about non-static atoms
     _symbolTable.add(atom);
-
-    // platform can add aliases for any symbol
-    std::vector<const DefinedAtom *> aliases;
-    if (_platform.getAliasAtoms(atom, aliases))
-      this->addAtoms(aliases);
   }
-
-  if (_platform.deadCodeStripping()) {
+  
+  if (_options.deadCodeStripping()) {
     // add to set of dead-strip-roots, all symbols that
     // the compiler marks as don't strip
-    if (!atom.deadStrip())
-      _deadStripRoots.insert(&atom);
-
-    // add to set of dead-strip-roots, all symbols that
-    // the platform decided must remain
-    if (_platform.isDeadStripRoot(atom))
+    if (atom.deadStrip() == DefinedAtom::deadStripNever)
       _deadStripRoots.insert(&atom);
   }
 }
@@ -165,9 +136,9 @@
 // if so, keep searching libraries until no more atoms being added
 void Resolver::resolveUndefines() {
   const bool searchArchives =
-    _platform.searchArchivesToOverrideTentativeDefinitions();
+    _options.searchArchivesToOverrideTentativeDefinitions();
   const bool searchDylibs =
-    _platform.searchSharedLibrariesToOverrideTentativeDefinitions();
+    _options.searchSharedLibrariesToOverrideTentativeDefinitions();
 
   // keep looping until no more undefines were added in last loop
   unsigned int undefineGenCount = 0xFFFFFFFF;
@@ -180,14 +151,6 @@
       // load for previous undefine may also have loaded this undefine
       if (!_symbolTable.isDefined(undefName)) {
         _inputFiles.searchLibraries(undefName, true, true, false, *this);
-
-        // give platform a chance to instantiate platform
-        // specific atoms (e.g. section boundary)
-        if (!_symbolTable.isDefined(undefName)) {
-          std::vector<const DefinedAtom *> platAtoms;
-          if (_platform.getPlatformAtoms(undefName, platAtoms))
-            this->addAtoms(platAtoms);
-        }
       }
     }
     // search libraries for overrides of common symbols
@@ -230,21 +193,8 @@
 }
 
 
-// for dead code stripping, recursively mark atom "live"
-void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {
-  // if -why_live cares about this symbol, then dump chain
-  if ((previous->referer != nullptr) && _platform.printWhyLive(atom.name())) {
-    llvm::errs() << atom.name() << " from " << atom.file().path() << "\n";
-    int depth = 1;
-    for (WhyLiveBackChain *p = previous; p != nullptr;
-         p = p->previous, ++depth) {
-      for (int i = depth; i > 0; --i)
-        llvm::errs() << "  ";
-      llvm::errs() << p->referer->name() << " from "
-                   << p->referer->file().path() << "\n";
-    }
-  }
-
+// for dead code stripping, recursively mark atoms "live"
+void Resolver::markLive(const Atom &atom) {
   // if already marked live, then done (stop recursion)
   if ( _liveAtoms.count(&atom) )
     return;
@@ -253,50 +203,47 @@
   _liveAtoms.insert(&atom);
 
   // mark all atoms it references as live
-  WhyLiveBackChain thisChain;
-  thisChain.previous = previous;
-  thisChain.referer = &atom;
   if ( const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
     for (const Reference *ref : *defAtom) {
-      this->markLive(*ref->target(), &thisChain);
+      const Atom *target = ref->target();
+      if ( target != nullptr )
+        this->markLive(*target);
     }
   }
 }
 
+
 // remove all atoms not actually used
 void Resolver::deadStripOptimize() {
   // only do this optimization with -dead_strip
-  if (!_platform.deadCodeStripping())
+  if (!_options.deadCodeStripping())
     return;
 
   // clear liveness on all atoms
   _liveAtoms.clear();
 
-  // add entry point (main) to live roots
-  const Atom *entry = this->entryPoint();
-  if (entry != nullptr)
-    _deadStripRoots.insert(entry);
-
-  // add -exported_symbols_list, -init, and -u entries to live roots
-  for (Platform::UndefinesIterator uit = _platform.initialUndefinesBegin();
-       uit != _platform.initialUndefinesEnd(); ++uit) {
-    StringRef sym = *uit;
-    const Atom *symAtom = _symbolTable.findByName(sym);
+  // By default, shared libraries are built with all globals as dead strip roots
+  if ( _options.allGlobalsAreDeadStripRoots() ) {
+    for ( const Atom *atom : _atoms ) {
+      const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom);
+      if (defAtom == nullptr)
+        continue;
+      if ( defAtom->scope() == DefinedAtom::scopeGlobal )
+        _deadStripRoots.insert(defAtom);
+    }
+  }
+  
+  // Or, use list of names that are dead stip roots.
+  const std::vector<StringRef> &names = _options.deadStripRootNames();
+  for ( const StringRef &name : names ) {
+    const Atom *symAtom = _symbolTable.findByName(name);
     assert(symAtom->definition() != Atom::definitionUndefined);
     _deadStripRoots.insert(symAtom);
   }
 
-  // add platform specific helper atoms
-  std::vector<const DefinedAtom *> platRootAtoms;
-  if (_platform.getImplicitDeadStripRoots(platRootAtoms))
-    this->addAtoms(platRootAtoms);
-
   // mark all roots as live, and recursively all atoms they reference
   for ( const Atom *dsrAtom : _deadStripRoots) {
-    WhyLiveBackChain rootChain;
-    rootChain.previous = nullptr;
-    rootChain.referer = dsrAtom;
-    this->markLive(*dsrAtom, &rootChain);
+    this->markLive(*dsrAtom);
   }
 
   // now remove all non-live atoms from _atoms
@@ -304,6 +251,7 @@
                               NotLive(_liveAtoms)), _atoms.end());
 }
 
+
 // error out if some undefines remain
 void Resolver::checkUndefines(bool final) {
   // when using LTO, undefines are checked after bitcode is optimized
@@ -313,18 +261,25 @@
   // build vector of remaining undefined symbols
   std::vector<const Atom *> undefinedAtoms;
   _symbolTable.undefines(undefinedAtoms);
-  if (_platform.deadCodeStripping()) {
-    // when dead code stripping we don't care if dead atoms are undefined
+  if (_options.deadCodeStripping()) {
+    // When dead code stripping, we don't care if dead atoms are undefined.
     undefinedAtoms.erase(std::remove_if(
                            undefinedAtoms.begin(), undefinedAtoms.end(),
                            NotLive(_liveAtoms)), undefinedAtoms.end());
   }
 
-  // let platform make error message about missing symbols
-  if (undefinedAtoms.size() != 0)
-    _platform.errorWithUndefines(undefinedAtoms, _atoms);
+  // error message about missing symbols
+  if ( (undefinedAtoms.size() != 0) && _options.undefinesAreErrors() ) {
+    // FIXME: need diagonstics interface for writing error messages
+    llvm::errs() << "Undefined symbols:\n";
+    for ( const Atom *undefAtom : undefinedAtoms ) {
+      llvm::errs() << "  " << undefAtom->name() << "\n";
+    }
+    llvm::report_fatal_error("symbol(s) not found");
+  }
 }
 
+
 // remove from _atoms all coaleseced away atoms
 void Resolver::removeCoalescedAwayAtoms() {
   _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
@@ -348,27 +303,12 @@
   }
 }
 
-// get "main" atom for linkage unit
-const Atom *Resolver::entryPoint() {
-  StringRef symbolName = _platform.entryPointName();
-  if ( !symbolName.empty() )
-    return _symbolTable.findByName(symbolName);
-
-  return nullptr;
-}
-
-// give platform a chance to tweak the set of atoms
-void Resolver::tweakAtoms() {
-  _platform.postResolveTweaks(_atoms);
-}
 
 void Resolver::linkTimeOptimize() {
   // FIX ME
 }
 
 void Resolver::resolve() {
-  this->initializeState();
-  this->addInitialUndefines();
   this->buildInitialAtomList();
   this->resolveUndefines();
   this->updateReferences();
@@ -377,9 +317,7 @@
   this->removeCoalescedAwayAtoms();
   this->checkDylibSymbolCollisions();
   this->linkTimeOptimize();
-  this->tweakAtoms();
   this->_result.addAtoms(_atoms);
-  this->_result._mainAtom = this->entryPoint();
 }
 
 void Resolver::MergedFile::addAtom(const Atom& atom) {

Modified: lld/trunk/lib/Core/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/lib/Core/SymbolTable.cpp (original)
+++ lld/trunk/lib/Core/SymbolTable.cpp Wed Apr 18 16:55:06 2012
@@ -14,7 +14,6 @@
 #include "lld/Core/File.h"
 #include "lld/Core/InputFiles.h"
 #include "lld/Core/LLVM.h"
-#include "lld/Core/Platform.h"
 #include "lld/Core/Resolver.h"
 #include "lld/Core/SharedLibraryAtom.h"
 #include "lld/Core/UndefinedAtom.h"
@@ -22,6 +21,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
 
 #include <algorithm>
 #include <cassert>
@@ -30,8 +30,8 @@
 
 namespace lld {
 
-SymbolTable::SymbolTable(Platform& plat)
-  : _platform(plat) {
+SymbolTable::SymbolTable(ResolverOptions &opts)
+  : _options(opts) {
 }
 
 void SymbolTable::add(const UndefinedAtom &atom) {
@@ -171,29 +171,56 @@
             useNew = false;
           }
           else {
+            if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
+              // FIXME: need diagonstics interface for writing warning messages
+              llvm::errs() << "lld warning: undefined symbol " 
+                           << existingUndef->name()
+                           << " has different weakness in "
+                           << existingUndef->file().path()
+                           << " and in "
+                           << newUndef->file().path();
+            }
             useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
-            // give platform a change to override which to use
-            _platform.undefineCanBeNullMismatch(*existingUndef,
-                                                 *newUndef, useNew);
           }
         }
         break;
       case NCR_DupShLib: {
-          const SharedLibraryAtom* existingShLib =
+          const SharedLibraryAtom* curShLib =
             dyn_cast<SharedLibraryAtom>(existing);
           const SharedLibraryAtom* newShLib =
             dyn_cast<SharedLibraryAtom>(&newAtom);
-          assert(existingShLib != nullptr);
+          assert(curShLib != nullptr);
           assert(newShLib != nullptr);
-          if ( (existingShLib->canBeNullAtRuntime()
-                  == newShLib->canBeNullAtRuntime()) &&
-               existingShLib->loadName().equals(newShLib->loadName()) ) {
+          bool sameNullness = (curShLib->canBeNullAtRuntime()
+                                          == newShLib->canBeNullAtRuntime());
+          bool sameName = curShLib->loadName().equals(newShLib->loadName());
+          if ( !sameName ) {
             useNew = false;
+            if ( _options.warnIfCoalesableAtomsHaveDifferentLoadName() ) {
+              // FIXME: need diagonstics interface for writing warning messages
+              llvm::errs() << "lld warning: shared library symbol " 
+                           << curShLib->name()
+                           << " has different load path in "
+                           << curShLib->file().path()
+                           << " and in "
+                           << newShLib->file().path();
+            }
+          }
+          else if ( ! sameNullness ) {
+            useNew = false;
+            if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
+              // FIXME: need diagonstics interface for writing warning messages
+              llvm::errs() << "lld warning: shared library symbol " 
+                           << curShLib->name()
+                           << " has different weakness in "
+                           << curShLib->file().path()
+                           << " and in "
+                           << newShLib->file().path();
+            }
           }
           else {
-            useNew = false; // use existing shared library by default
-            // give platform a change to override which to use
-            _platform.sharedLibrarylMismatch(*existingShLib, *newShLib, useNew);
+            // Both shlib atoms are identical and can be coalesced.
+            useNew = false;
           }
         }
         break;

Modified: lld/trunk/lib/Core/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)
+++ lld/trunk/lib/Core/YamlKeyValues.cpp Wed Apr 18 16:55:06 2012
@@ -138,6 +138,7 @@
   { "unknown",        DefinedAtom::typeUnknown },
   { "code",           DefinedAtom::typeCode },
   { "stub",           DefinedAtom::typeStub },
+  { "stub-helper",    DefinedAtom::typeStubHelper },
   { "resolver",       DefinedAtom::typeResolver },
   { "constant",       DefinedAtom::typeConstant },
   { "c-string",       DefinedAtom::typeCString },
@@ -151,6 +152,7 @@
   { "zero-fill",      DefinedAtom::typeZeroFill },
   { "cf-string",      DefinedAtom::typeCFString },
   { "got",            DefinedAtom::typeGOT },
+  { "lazy-pointer",   DefinedAtom::typeLazyPointer },
   { "initializer-ptr",DefinedAtom::typeInitializerPtr },
   { "terminator-ptr", DefinedAtom::typeTerminatorPtr },
   { "c-string-ptr",   DefinedAtom::typeCStringPtr },

Modified: lld/trunk/lib/Core/YamlWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlWriter.cpp?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlWriter.cpp (original)
+++ lld/trunk/lib/Core/YamlWriter.cpp Wed Apr 18 16:55:06 2012
@@ -56,11 +56,12 @@
       // Find references to unnamed atoms and create ref-names for them.
       for (const Reference *ref : *atom) {
         // create refname for any unnamed reference target
-        if ( ref->target()->name().empty() ) {
+        const Atom *target = ref->target();
+        if ( (target != nullptr) && target->name().empty() ) {
           std::string Storage;
           llvm::raw_string_ostream Buffer(Storage);
           Buffer << llvm::format("L%03d", _unnamedCounter++);
-          _refNames[ref->target()] = Buffer.str();
+          _refNames[target] = Buffer.str();
         }
       }
     }

Modified: lld/trunk/lib/Platforms/Darwin/DarwinPlatform.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Platforms/Darwin/DarwinPlatform.cpp?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/lib/Platforms/Darwin/DarwinPlatform.cpp (original)
+++ lld/trunk/lib/Platforms/Darwin/DarwinPlatform.cpp Wed Apr 18 16:55:06 2012
@@ -10,12 +10,14 @@
 #include "DarwinPlatform.h"
 #include "MachOFormat.hpp"
 #include "StubAtoms.hpp"
+#include "ExecutableAtoms.hpp"
 #include "DarwinReferenceKinds.h"
 #include "ExecutableWriter.h"
 
 #include "lld/Core/DefinedAtom.h"
 #include "lld/Core/File.h"
 #include "lld/Core/Reference.h"
+#include "lld/Core/InputFiles.h"
 
 #include "llvm/Support/ErrorHandling.h"
 
@@ -29,110 +31,14 @@
 namespace darwin {
 
 DarwinPlatform::DarwinPlatform()
-  : _helperCommonAtom(nullptr) {
+  : _helperCommonAtom(nullptr), _cRuntimeFile(nullptr) {
 }
 
-void DarwinPlatform::initialize() {
+void DarwinPlatform::addFiles(InputFiles &inputFiles) {
+  _cRuntimeFile = new CRuntimeFile();
+  inputFiles.prependFile(*_cRuntimeFile);
 }
 
-void DarwinPlatform::fileAdded(const File &file) {
-}
-
-
-void DarwinPlatform::atomAdded(const Atom &file) {
-}
-
-
-void DarwinPlatform::adjustScope(const DefinedAtom &atom) {
-}
-
-
-bool DarwinPlatform::getAliasAtoms(const Atom &atom,
-                           std::vector<const DefinedAtom *>&) {
-  return false;
-}
-
-
-bool DarwinPlatform::getPlatformAtoms(StringRef undefined,
-                              std::vector<const DefinedAtom *>&) {
-  return false;
-}
-
-
-bool DarwinPlatform::deadCodeStripping() {
-  return false;
-}
-
-
-bool DarwinPlatform::isDeadStripRoot(const Atom &atom) {
-  return false;
-}
-
-
-bool DarwinPlatform::getImplicitDeadStripRoots(std::vector<const DefinedAtom *>&) {
-  return false;
-}
-
-
-StringRef DarwinPlatform::entryPointName() {
-  return StringRef("_main");
-}
-
-
-Platform::UndefinesIterator DarwinPlatform::initialUndefinesBegin() const {
-  return nullptr;
-}
-
-Platform::UndefinesIterator DarwinPlatform::initialUndefinesEnd() const {
-  return nullptr;
-}
-
-
-bool DarwinPlatform::searchArchivesToOverrideTentativeDefinitions() {
-  return false;
-}
-
-bool DarwinPlatform::searchSharedLibrariesToOverrideTentativeDefinitions() {
-  return false;
-}
-
-
-bool DarwinPlatform::allowUndefinedSymbol(StringRef name) {
-  return false;
-}
-
-bool DarwinPlatform::printWhyLive(StringRef name) {
-  return false;
-}
-
-
-const Atom& DarwinPlatform::handleMultipleDefinitions(const Atom& def1, 
-                                              const Atom& def2) {
-  llvm::report_fatal_error("multiple definitions");
-}
-
-
-void DarwinPlatform::errorWithUndefines(const std::vector<const Atom *>& undefs,
-                                const std::vector<const Atom *>& all) {
-}
-
-
-void DarwinPlatform::undefineCanBeNullMismatch(const UndefinedAtom& undef1,
-                                       const UndefinedAtom& undef2,
-                                       bool& useUndef2) {
-}
-
-
-void DarwinPlatform::sharedLibrarylMismatch(const SharedLibraryAtom& shLib1,
-                                    const SharedLibraryAtom& shLib2,
-                                    bool& useShlib2) {
-}
-
-
-void DarwinPlatform::postResolveTweaks(std::vector<const Atom *>& all) {
-}
-
-
 Reference::Kind DarwinPlatform::kindFromString(StringRef kindName) {
   return ReferenceKind::fromString(kindName);
 }
@@ -259,6 +165,16 @@
   mh.reserved   = 0;
 }
 
+const Atom *DarwinPlatform::mainAtom() {
+  assert(_cRuntimeFile != nullptr);
+  const Atom *result = _cRuntimeFile->mainAtom();
+  assert(result != nullptr);
+  if ( result->definition() == Atom::definitionUndefined )
+    llvm::report_fatal_error("_main not found");
+  return _cRuntimeFile->mainAtom();
+}
+
+
 
 } // namespace darwin 
 } // namespace lld 

Modified: lld/trunk/lib/Platforms/Darwin/DarwinPlatform.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Platforms/Darwin/DarwinPlatform.h?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/lib/Platforms/Darwin/DarwinPlatform.h (original)
+++ lld/trunk/lib/Platforms/Darwin/DarwinPlatform.h Wed Apr 18 16:55:06 2012
@@ -23,35 +23,7 @@
                 
 /// @name Platform methods
 /// @{
-  virtual void initialize();
-  virtual void fileAdded(const File &file);
-  virtual void atomAdded(const Atom &file);
-  virtual void adjustScope(const DefinedAtom &atom);
-  virtual bool getAliasAtoms(const Atom &atom,
-                             std::vector<const DefinedAtom *>&);
-  virtual bool getPlatformAtoms(llvm::StringRef undefined,
-                                std::vector<const DefinedAtom *>&);
-  virtual bool deadCodeStripping();
-  virtual bool isDeadStripRoot(const Atom &atom);
-  virtual bool getImplicitDeadStripRoots(std::vector<const DefinedAtom *>&);
-  virtual llvm::StringRef entryPointName();
-  virtual UndefinesIterator  initialUndefinesBegin() const;
-  virtual UndefinesIterator  initialUndefinesEnd() const;
-  virtual bool searchArchivesToOverrideTentativeDefinitions();
-  virtual bool searchSharedLibrariesToOverrideTentativeDefinitions();
-  virtual bool allowUndefinedSymbol(llvm::StringRef name);
-  virtual bool printWhyLive(llvm::StringRef name);
-  virtual const Atom& handleMultipleDefinitions(const Atom& def1, 
-                                                const Atom& def2);
-  virtual void errorWithUndefines(const std::vector<const Atom *>& undefs,
-                                  const std::vector<const Atom *>& all);
-  virtual void undefineCanBeNullMismatch(const UndefinedAtom& undef1,
-                                         const UndefinedAtom& undef2,
-                                         bool& useUndef2);
-  virtual void sharedLibrarylMismatch(const SharedLibraryAtom& shLib1,
-                                      const SharedLibraryAtom& shLib2,
-                                      bool& useShlib2);
-  virtual void postResolveTweaks(std::vector<const Atom *>& all);
+  virtual void addFiles(InputFiles&);
   virtual Reference::Kind kindFromString(llvm::StringRef);
   virtual llvm::StringRef kindToString(Reference::Kind);
   virtual bool noTextRelocs();
@@ -69,6 +41,7 @@
 /// @{
   uint64_t  pageZeroSize();
   void initializeMachHeader(const lld::File& file, class mach_header& mh);
+  const Atom *mainAtom();
 /// @}
 
 private:
@@ -79,6 +52,7 @@
   const DefinedAtom*                              _helperCommonAtom;
   const DefinedAtom*                              _helperCacheAtom;
   const DefinedAtom*                              _helperBinderAtom;
+  class CRuntimeFile                             *_cRuntimeFile;
 };
 
 } // namespace darwin

Modified: lld/trunk/lib/Platforms/Darwin/DarwinReferenceKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Platforms/Darwin/DarwinReferenceKinds.cpp?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/lib/Platforms/Darwin/DarwinReferenceKinds.cpp (original)
+++ lld/trunk/lib/Platforms/Darwin/DarwinReferenceKinds.cpp Wed Apr 18 16:55:06 2012
@@ -32,6 +32,7 @@
 
 
 static const Mapping sKindMappings[] = {
+  { "none",           ReferenceKind::none,        flagsNone },
   { "call32",         ReferenceKind::call32,      flagsIsCallSite | flags32RipRel },
   { "pcrel32",        ReferenceKind::pcRel32,     flags32RipRel },
   { "gotLoad32",      ReferenceKind::gotLoad32,   flagsisGOTLoad | flags32RipRel },

Added: lld/trunk/lib/Platforms/Darwin/ExecutableAtoms.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Platforms/Darwin/ExecutableAtoms.hpp?rev=155060&view=auto
==============================================================================
--- lld/trunk/lib/Platforms/Darwin/ExecutableAtoms.hpp (added)
+++ lld/trunk/lib/Platforms/Darwin/ExecutableAtoms.hpp Wed Apr 18 16:55:06 2012
@@ -0,0 +1,84 @@
+//===- Platforms/Darwin/x86_64StubAtom.hpp --------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_
+#define LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_
+
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+
+#include "DarwinReferenceKinds.h"
+#include "SimpleAtoms.hpp"
+
+namespace lld {
+namespace darwin {
+
+
+//
+// EntryPointReferenceAtom is used to:
+//  1) Require "_main" is defined.
+//  2) Give Darwin Platform a pointer to the atom named "_main"
+//
+class EntryPointReferenceAtom : public SimpleDefinedAtom {
+public:
+        EntryPointReferenceAtom(const File &file) 
+                       : SimpleDefinedAtom(file)
+                       , _mainUndefAtom(file, "_main") {
+          this->addReference(ReferenceKind::none, 0, &_mainUndefAtom, 0);
+        }
+
+  virtual ContentType contentType() const  {
+    return DefinedAtom::typeCode;
+  }
+
+  virtual uint64_t size() const {
+    return 0;
+  }
+
+  virtual ContentPermissions permissions() const  {
+    return DefinedAtom::permR_X;
+  }
+  
+  virtual ArrayRef<uint8_t> rawContent() const {
+    return ArrayRef<uint8_t>();
+  }
+private:
+  friend class CRuntimeFile;
+  SimpleUndefinedAtom   _mainUndefAtom;
+};
+
+
+class CRuntimeFile : public SimpleFile {
+public:
+    CRuntimeFile() 
+          : SimpleFile("C runtime")
+          , _atom(*this) {
+      this->addAtom(_atom);
+      this->addAtom(_atom._mainUndefAtom);
+   }
+    
+    const Atom *mainAtom() {
+      const Reference *ref = *(_atom.begin());
+      return ref->target();
+    }
+    
+private:
+  EntryPointReferenceAtom   _atom;
+};
+
+
+
+} // namespace darwin 
+} // namespace lld 
+
+
+#endif // LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_

Modified: lld/trunk/lib/Platforms/Darwin/ExecutableWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Platforms/Darwin/ExecutableWriter.cpp?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/lib/Platforms/Darwin/ExecutableWriter.cpp (original)
+++ lld/trunk/lib/Platforms/Darwin/ExecutableWriter.cpp Wed Apr 18 16:55:06 2012
@@ -554,7 +554,10 @@
     }
     // Copy raw content of atom.
     ArrayRef<uint8_t> content = atomInfo.atom->rawContent();
-    buffer.resize(content.size());
+    uint64_t contentSize = content.size();
+    buffer.resize(contentSize);
+    if ( contentSize == 0 )
+      continue;
     ::memcpy(buffer.data(), content.data(), content.size());
     for (const Reference *ref : *atomInfo.atom) {
       uint32_t offset = ref->offsetInAtom();
@@ -808,7 +811,7 @@
 
   // Update entry point
   if ( _entryPointLoadCommand != nullptr ) {
-    const Atom *mainAtom = file.entryPoint();
+    const Atom *mainAtom = _platform.mainAtom();
     assert(mainAtom != nullptr);
     uint32_t entryOffset = _writer.addressOfAtom(mainAtom) - _mh.address();
     _entryPointLoadCommand->entryoff = entryOffset;

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

Modified: lld/trunk/lib/Platforms/Darwin/StubAtoms.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Platforms/Darwin/StubAtoms.hpp?rev=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/lib/Platforms/Darwin/StubAtoms.hpp (original)
+++ lld/trunk/lib/Platforms/Darwin/StubAtoms.hpp Wed Apr 18 16:55:06 2012
@@ -10,8 +10,6 @@
 #ifndef LLD_PLATFORM_DARWIN_X86_64_STUB_ATOM_H_
 #define LLD_PLATFORM_DARWIN_X86_64_STUB_ATOM_H_
 
-#include <vector>
-
 #include "llvm/ADT/ArrayRef.h"
 
 #include "lld/Core/DefinedAtom.h"
@@ -20,156 +18,19 @@
 #include "lld/Core/Reference.h"
 
 #include "DarwinReferenceKinds.h"
+#include "SimpleAtoms.hpp"
 
 namespace lld {
 namespace darwin {
 
 
 //
-// Generic Reference
-//
-class GenericReference : public Reference {
-public:
-                GenericReference(Reference::Kind k, uint64_t off, 
-                                const Atom *t, Reference::Addend a) 
-                      : _target(t), _offsetInAtom(off), _addend(a), _kind(k) { }
-
-  virtual uint64_t offsetInAtom() const {
-    return _offsetInAtom;
-  }
-
-  virtual Kind kind() const {
-    return _kind;
-  }
-
-  virtual void setKind(Kind k) {
-    _kind = k;
-  }
-
-  virtual const Atom* target() const {
-    return _target;
-  }
-
-  virtual Addend addend() const {
-    return _addend;
-  }
-
-  virtual void setAddend(Addend a) {
-    _addend = a;
-  }
-
-  virtual void setTarget(const Atom* newAtom) {
-    _target = newAtom;
-  }
-private:
-  const Atom*  _target;
-  uint64_t     _offsetInAtom;
-  Addend       _addend;
-  Kind         _kind;
-};
-
-
-//
-// Generic Atom base class
-//
-class BaseAtom : public DefinedAtom {
-public:
-        BaseAtom(const File &f) : _file(f) {
-          static uint32_t lastOrdinal = 0;
-          _ordinal = lastOrdinal++; 
-        }
-
-  virtual const File& file() const {
-    return _file;
-  }
-
-  virtual StringRef name() const {
-    return StringRef();
-  }
-  
-  virtual uint64_t ordinal() const {
-    return _ordinal;
-  }
-
-  virtual Scope scope() const {
-    return DefinedAtom::scopeLinkageUnit;
-  }
-  
-  virtual Interposable interposable() const {
-    return DefinedAtom::interposeNo;
-  }
-  
-  virtual Merge merge() const {
-    return DefinedAtom::mergeNo;
-  }
-  
-  virtual Alignment alignment() const {
-    return Alignment(0,0);
-  }
-  
-  virtual SectionChoice sectionChoice() const {
-    return DefinedAtom::sectionBasedOnContent;
-  }
-    
-  virtual StringRef customSectionName() const {
-    return StringRef();
-  }
-  virtual DeadStripKind deadStrip() const {
-    return DefinedAtom::deadStripNormal;
-  }
-    
-  virtual bool isThumb() const {
-    return false;
-  }
-    
-  virtual bool isAlias() const {
-    return false;
-  }
-  
-  virtual DefinedAtom::reference_iterator begin() const {
-    uintptr_t index = 0;
-    const void* it = reinterpret_cast<const void*>(index);
-    return reference_iterator(*this, it);
-  }
-
-  virtual DefinedAtom::reference_iterator end() const {
-    uintptr_t index = _references.size();
-    const void* it = reinterpret_cast<const void*>(index);
-    return reference_iterator(*this, it);
-  }
-
-  virtual const Reference* derefIterator(const void* it) const {
-    uintptr_t index = reinterpret_cast<uintptr_t>(it);
-    assert(index < _references.size());
-    return &_references[index];
-  }
-
-  virtual void incrementIterator(const void*& it) const {
-    uintptr_t index = reinterpret_cast<uintptr_t>(it);
-    ++index;
-    it = reinterpret_cast<const void*>(index);
-  }
-  
-  void addReference(Reference::Kind kind, uint64_t offset, const Atom *target, 
-                   Reference::Addend addend) {
-    _references.push_back(GenericReference(kind, offset, target, addend));
-  }
-  
-private:
-  const File&                   _file;
-  uint32_t                      _ordinal;
-  std::vector<GenericReference> _references;
-};
-
-
-
-//
 // X86_64 Stub Atom created by the stubs pass.
 //
-class X86_64StubAtom : public BaseAtom {
+class X86_64StubAtom : public SimpleDefinedAtom {
 public:
         X86_64StubAtom(const File &file, const Atom &lazyPointer) 
-                       : BaseAtom(file) {
+                       : SimpleDefinedAtom(file) {
           this->addReference(ReferenceKind::pcRel32, 2, &lazyPointer, 0);
         }
 
@@ -198,11 +59,11 @@
 //
 // X86_64 Stub Helper Common Atom created by the stubs pass.
 //
-class X86_64StubHelperCommonAtom : public BaseAtom {
+class X86_64StubHelperCommonAtom : public SimpleDefinedAtom {
 public:
   X86_64StubHelperCommonAtom(const File &file, const Atom &cache,
                                                const Atom &binder)
-  : BaseAtom(file) {
+  : SimpleDefinedAtom(file) {
     this->addReference(ReferenceKind::pcRel32, 3,  &cache, 0);
     this->addReference(ReferenceKind::pcRel32, 11, &binder, 0);
   }
@@ -236,10 +97,10 @@
 //
 // X86_64 Stub Helper Atom created by the stubs pass.
 //
-class X86_64StubHelperAtom : public BaseAtom {
+class X86_64StubHelperAtom : public SimpleDefinedAtom {
 public:
   X86_64StubHelperAtom(const File &file, const Atom &helperCommon) 
-  : BaseAtom(file) {
+  : SimpleDefinedAtom(file) {
     this->addReference(ReferenceKind::lazyImm, 1, nullptr, 0);
     this->addReference(ReferenceKind::pcRel32, 6, &helperCommon, 0);
   }
@@ -270,11 +131,11 @@
 //
 // X86_64 Lazy Pointer Atom created by the stubs pass.
 //
-class X86_64LazyPointerAtom : public BaseAtom {
+class X86_64LazyPointerAtom : public SimpleDefinedAtom {
 public:
         X86_64LazyPointerAtom(const File &file, const Atom &helper,
                                                 const Atom &shlib)
-              : BaseAtom(file) {
+              : SimpleDefinedAtom(file) {
                 this->addReference(ReferenceKind::pointer64, 0, &helper, 0);
                 this->addReference(ReferenceKind::lazyTarget, 0, &shlib, 0);
         }
@@ -303,14 +164,14 @@
 //
 // X86_64 NonLazy (GOT) Pointer Atom created by the stubs pass.
 //
-class X86_64NonLazyPointerAtom : public BaseAtom {
+class X86_64NonLazyPointerAtom : public SimpleDefinedAtom {
 public:
   X86_64NonLazyPointerAtom(const File &file)
-  : BaseAtom(file) {
+  : SimpleDefinedAtom(file) {
   }
   
   X86_64NonLazyPointerAtom(const File &file, const Atom &shlib)
-  : BaseAtom(file) {
+  : SimpleDefinedAtom(file) {
     this->addReference(ReferenceKind::pointer64, 0, &shlib, 0);
   }
   

Added: lld/trunk/test/undef-coalesce-error.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/undef-coalesce-error.objtxt?rev=155060&view=auto
==============================================================================
--- lld/trunk/test/undef-coalesce-error.objtxt (added)
+++ lld/trunk/test/undef-coalesce-error.objtxt Wed Apr 18 16:55:06 2012
@@ -0,0 +1,40 @@
+# RUN: not lld-core -undefines_are_errors %s 2> %t.err
+# RUN: FileCheck < %t.err %s
+
+#
+# Test that any remaining undefined symbols cause an error
+#
+
+---
+atoms:
+    - name:              foo
+      type:              code
+      
+    - name:              malloc
+      definition:        undefined
+
+    - name:              free
+      definition:        undefined
+---
+atoms:
+    - name:              bar
+      type:              code
+      
+    - name:              malloc
+      definition:        undefined
+  
+    - name:              myfunc
+      definition:        undefined
+---
+atoms:
+    - name:              myfunc
+      scope:             global
+      type:              code
+      
+    - name:              free
+      definition:        undefined
+...
+
+# CHECK:       free
+# CHECK:       malloc
+# CHECK:       symbol(s) not found

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=155060&r1=155059&r2=155060&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Wed Apr 18 16:55:06 2012
@@ -246,103 +246,9 @@
 class TestingPlatform : public Platform {
 public:
 
-  virtual void initialize() { }
-
-  // tell platform object another file has been added
-  virtual void fileAdded(const File &file) { }
-
-  // tell platform object another atom has been added
-  virtual void atomAdded(const Atom &file) { }
-
-  // give platform a chance to change each atom's scope
-  virtual void adjustScope(const DefinedAtom &atom) { }
-
-  // if specified atom needs alternate names, return AliasAtom(s)
-  virtual bool getAliasAtoms(const Atom &atom,
-                             std::vector<const DefinedAtom *>&) {
-    return false;
-  }
-
-  // give platform a chance to resolve platform-specific undefs
-  virtual bool getPlatformAtoms(StringRef undefined,
-                                std::vector<const DefinedAtom *>&) {
-    return false;
-  }
-
-  // resolver should remove unreferenced atoms
-  virtual bool deadCodeStripping() {
-    return false;
-  }
-
-  // atom must be kept so should be root of dead-strip graph
-  virtual bool isDeadStripRoot(const Atom &atom) {
-    return false;
-  }
-
-  // if target must have some atoms, denote here
-  virtual bool getImplicitDeadStripRoots(std::vector<const DefinedAtom *>&) {
-    return false;
-  }
-
-  // return entry point for output file (e.g. "main") or nullptr
-  virtual StringRef entryPointName() {
-    return StringRef();
-  }
-
-  // for iterating must-be-defined symbols ("main" or -u command line option)
-  typedef StringRef const *UndefinesIterator;
-  virtual UndefinesIterator initialUndefinesBegin() const {
-    return nullptr;
-  }
-  virtual UndefinesIterator initialUndefinesEnd() const {
-    return nullptr;
-  }
-
-  // if platform wants resolvers to search libraries for overrides
-  virtual bool searchArchivesToOverrideTentativeDefinitions() {
-    return false;
-  }
-
-  virtual bool searchSharedLibrariesToOverrideTentativeDefinitions() {
-    return false;
-  }
-
-  // if platform allows symbol to remain undefined (e.g. -r)
-  virtual bool allowUndefinedSymbol(StringRef name) {
-    return true;
-  }
-
-  // for debugging dead code stripping, -why_live
-  virtual bool printWhyLive(StringRef name) {
-    return false;
+  virtual void addFiles(InputFiles&) {
   }
 
-  virtual const Atom& handleMultipleDefinitions(const Atom& def1,
-                                                const Atom& def2) {
-    llvm::report_fatal_error("symbol '" 
-                            + Twine(def1.name())
-                            + "' multiply defined");
-  }
-
-  // print out undefined symbol error messages in platform specific way
-  virtual void errorWithUndefines(const std::vector<const Atom *> &undefs,
-                                  const std::vector<const Atom *> &all) {}
-
-  // print out undefined can-be-null mismatches
-  virtual void undefineCanBeNullMismatch(const UndefinedAtom& undef1,
-                                         const UndefinedAtom& undef2,
-                                         bool& useUndef2) { }
-
-  // print out shared library mismatches
-  virtual void sharedLibrarylMismatch(const SharedLibraryAtom& shLib1,
-                                      const SharedLibraryAtom& shLib2,
-                                      bool& useShlib2) { }
-
-
-  // last chance for platform to tweak atoms
-  virtual void postResolveTweaks(std::vector<const Atom *> &all) {}
-  
-
   struct KindMapping {
     const char*           string;
     Reference::Kind       value;
@@ -466,6 +372,14 @@
     }
   }
 
+  virtual void prependFile(const File &file) {
+    _files.insert(_files.begin(), &file);
+  }
+  
+  virtual void appendFile(const File &file) {
+    _files.push_back(&file);
+  }
+
   virtual bool searchLibraries(StringRef name, bool searchDylibs,
                                bool searchArchives, bool dataSymbolOnly,
                                InputFiles::Handler &) const {
@@ -481,8 +395,6 @@
 
 
 
-
-
 llvm::cl::opt<std::string> 
 gInputFilePath(llvm::cl::Positional,
               llvm::cl::desc("<input file>"),
@@ -501,6 +413,11 @@
 gDoGotPass("got_pass", 
           llvm::cl::desc("Run pass to create GOT atoms"));
 
+llvm::cl::opt<bool> 
+gUndefinesIsError("undefines_are_errors", 
+          llvm::cl::desc("Any undefined symbols at end is an error"));
+
+
 enum PlatformChoice {
   platformTesting, platformDarwin
 };
@@ -513,7 +430,19 @@
     clEnumValN(platformDarwin, "darwin", "link as darwin would"),
     clEnumValEnd));
     
-    
+
+
+class TestingResolverOptions : public ResolverOptions {
+public:
+  TestingResolverOptions() {
+    _undefinesAreErrors = gUndefinesIsError;
+  }
+
+};
+
+
+
+
     
 int main(int argc, char *argv[]) {
   // Print a stack trace if we signal out.
@@ -541,12 +470,17 @@
                                             *platform, files))) {
     return 1;
   }
-  
+
+  // create options for resolving
+  TestingResolverOptions options;
+
   // create object to mange input files
   TestingInputFiles inputFiles(files);
   
+  platform->addFiles(inputFiles);
+
   // merge all atom graphs
-  Resolver resolver(*platform, inputFiles);
+  Resolver resolver(options, inputFiles);
   resolver.resolve();
 
   // run passes
@@ -560,11 +494,7 @@
   }
 
   
-  // write new atom graph out as YAML doc
-  std::string errorInfo;
-  const char* outPath = gOutputFilePath.empty() ? "-" : gOutputFilePath.c_str();
-  llvm::raw_fd_ostream out(outPath, errorInfo);
-//  yaml::writeObjectText(resolver.resultFile(), out);
+//  yaml::writeObjectText(resolver.resultFile(), *platform, llvm::errs());
 
   // make unique temp .o file to put generated object file
   int fd;
@@ -583,11 +513,16 @@
   if ( error(parseNativeObjectFileOrSTDIN(tempPath, natFile)) ) 
     return 1;
 
+  // write new atom graph
+  std::string errorInfo;
+  const char* outPath = gOutputFilePath.empty() ? "-" : gOutputFilePath.c_str();
+  llvm::raw_fd_ostream out(outPath, errorInfo);
   if ( platformSelected == platformTesting) {
-    // write new atom graph out as YAML doc
+    // write atom graph out as YAML doc
     yaml::writeObjectText(resolver.resultFile() /* *natFile */, *platform, out);
   }
   else {
+    // write atom graph as an executable
     platform->writeExecutable(resolver.resultFile() /* *natFile */, out);
     // HACK.  I don't see any way to set the 'executable' bit on files 
     // in raw_fd_ostream or in llvm/Support.





More information about the llvm-commits mailing list