[llvm-commits] [lld] r155183 - in /lld/trunk: include/lld/Core/ lib/Core/ test/ test/darwin/ tools/lld-core/

Nick Kledzik kledzik at apple.com
Thu Apr 19 18:24:37 PDT 2012


Author: kledzik
Date: Thu Apr 19 20:24:37 2012
New Revision: 155183

URL: http://llvm.org/viewvc/llvm-project?rev=155183&view=rev
Log:
Add way to represent static archives in yaml test cases.

Add SharedLibraryFile and ArchiveLibraryFile subclasses of File.

Add command line options to lld-core to set various ResolverOptions settings
and added lots of test cases to verify the options work.


Added:
    lld/trunk/include/lld/Core/ArchiveLibraryFile.h
    lld/trunk/include/lld/Core/SharedLibraryFile.h
    lld/trunk/lib/Core/InputFiles.cpp
    lld/trunk/test/archive-basic.objtxt
    lld/trunk/test/archive-chain.objtxt
    lld/trunk/test/archive-tentdef-search.objtxt
    lld/trunk/test/dead-strip-basic.objtxt
    lld/trunk/test/dead-strip-globals.objtxt
Modified:
    lld/trunk/include/lld/Core/File.h
    lld/trunk/include/lld/Core/InputFiles.h
    lld/trunk/include/lld/Core/SymbolTable.h
    lld/trunk/lib/Core/CMakeLists.txt
    lld/trunk/lib/Core/Resolver.cpp
    lld/trunk/lib/Core/SymbolTable.cpp
    lld/trunk/lib/Core/YamlKeyValues.cpp
    lld/trunk/lib/Core/YamlKeyValues.h
    lld/trunk/lib/Core/YamlReader.cpp
    lld/trunk/test/darwin/hello-world.objtxt
    lld/trunk/test/pass-got-basic.objtxt
    lld/trunk/test/pass-stubs-basic.objtxt
    lld/trunk/test/undef-coalesce-error.objtxt
    lld/trunk/tools/lld-core/lld-core.cpp

Added: lld/trunk/include/lld/Core/ArchiveLibraryFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/ArchiveLibraryFile.h?rev=155183&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/ArchiveLibraryFile.h (added)
+++ lld/trunk/include/lld/Core/ArchiveLibraryFile.h Thu Apr 19 20:24:37 2012
@@ -0,0 +1,54 @@
+//===- Core/ArchiveLibraryFile.h - Models static library ------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_ARCHIVE_LIBRARY_FILE_H_
+#define LLD_CORE_ARCHIVE_LIBRARY_FILE_H_
+
+#include "lld/Core/File.h"
+
+namespace lld {
+
+
+///
+/// The ArchiveLibraryFile subclass of File is used to represent unix
+/// static library archives.  These libraries provide no atoms to the 
+/// initial set of atoms linked.  Instead, when the Resolver will query
+/// ArchiveLibraryFile instances for specific symbols names using the
+/// find() method.  If the archive contains an object file which has a
+/// DefinedAtom whose scope is not translationUnit, then that entire
+/// object file File is returned.
+/// 
+class ArchiveLibraryFile : public File {
+public:
+          ArchiveLibraryFile(StringRef path) : File(path) {
+  }
+
+  virtual ~ArchiveLibraryFile() {
+  }
+
+  virtual Kind kind() const {
+    return kindArchiveLibrary;
+  }
+
+  static inline bool classof(const File *f) {
+    return f->kind() == kindArchiveLibrary;
+  }
+  static inline bool classof(const ArchiveLibraryFile *) { 
+    return true; 
+  }
+
+  /// Check if any member of the archive contains an Atom with the
+  /// specified name and return the File object for that member, or nullptr.
+  virtual const File *find(StringRef name, bool dataSymbolOnly) const = 0;
+
+};
+
+} // namespace lld
+
+#endif // LLD_CORE_ARCHIVE_LIBRARY_FILE_H_

Modified: lld/trunk/include/lld/Core/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/File.h?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/File.h (original)
+++ lld/trunk/include/lld/Core/File.h Thu Apr 19 20:24:37 2012
@@ -27,8 +27,11 @@
 /// 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.  
+/// To iterate through the Atoms in a File there are four methods that
+/// return collections.  For instance to iterate through all the DefinedAtoms
+/// in a File object use:  
+///      for (const DefinedAtoms *atom : file->defined()) {
+///      }
 ///
 /// The Atom objects in a File are owned by the File object.  The Atom objects  
 /// are destroyed when the File object is destroyed.
@@ -37,6 +40,18 @@
 public:
   virtual ~File();
 
+  /// Kinds of files that are supported.
+  enum Kind {
+    kindObject,            ///< object file (.o)
+    kindSharedLibrary,     ///< shared library (.so)
+    kindArchiveLibrary,    ///< archive (.a)
+  };
+
+  /// Returns file kind.  Need for dyn_cast<> on File objects.
+  virtual Kind kind() const {
+    return kindObject;
+  }
+
   /// For error messages and debugging, this returns the path to the file
   /// which was used to create this object (e.g. "/tmp/foo.o").
   StringRef path() const  {
@@ -49,6 +64,11 @@
   /// be ascertained, this method returns the empty string.
   virtual StringRef translationUnitSource() const;
 
+
+  static inline bool classof(const File *) { 
+    return true; 
+  }
+
 protected:
   template <typename T> class atom_iterator; // forward reference
 public:
@@ -144,7 +164,7 @@
   /// Must be implemented to return the atom_collection object for 
   /// all AbsoluteAtoms in this File.
   virtual const atom_collection<AbsoluteAtom>& absolute() const = 0;
-  
+
 protected:
   /// This is a convenience class for File subclasses which manage their
   /// atoms as a simple std::vector<>.  
@@ -152,11 +172,12 @@
   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.data()));
+      return atom_iterator<T>(*this, reinterpret_cast<const void*>
+                                                              (_atoms.data()));
     }
     virtual atom_iterator<T> end() const{ 
       return atom_iterator<T>(*this, reinterpret_cast<const void*>
-        (_atoms.data() + _atoms.size()));
+                                              (_atoms.data() + _atoms.size()));
     }
     virtual const T* deref(const void* it) const {
       return *reinterpret_cast<const T* const*>(it);
@@ -169,8 +190,6 @@
     std::vector<const T*>   _atoms;
   };
   
-
-private:
   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=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/InputFiles.h (original)
+++ lld/trunk/include/lld/Core/InputFiles.h Thu Apr 19 20:24:37 2012
@@ -34,23 +34,30 @@
     virtual void doAbsoluteAtom(const class AbsoluteAtom &) = 0;
   };
 
+  InputFiles();
+  virtual ~InputFiles();
 
   /// Used by platforms to insert platform specific files.
-  virtual void prependFile(const File&) = 0;
+  virtual void prependFile(const File&);
   
   /// Used by platforms to insert platform specific files.
-  virtual void appendFile(const File&) = 0;
+  virtual void appendFile(const File&);
  
 
   /// @brief iterates all atoms in initial files
-  virtual void forEachInitialAtom(Handler &) const = 0;
+  virtual void forEachInitialAtom(Handler &) const;
 
   /// @brief searches libraries for name
   virtual bool searchLibraries(  StringRef name
-                               , bool searchDylibs
+                               , bool searchSharedLibs
                                , bool searchArchives
                                , bool dataSymbolOnly
-                               , Handler &) const = 0;
+                               , Handler &) const;
+
+protected:
+  void handleFile(const File *file, InputFiles::Handler &handler) const;
+  
+  std::vector<const File*>        _files;
 };
 
 } // namespace lld

Added: lld/trunk/include/lld/Core/SharedLibraryFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/SharedLibraryFile.h?rev=155183&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/SharedLibraryFile.h (added)
+++ lld/trunk/include/lld/Core/SharedLibraryFile.h Thu Apr 19 20:24:37 2012
@@ -0,0 +1,52 @@
+//===- Core/SharedLibraryFile.h - Models shared libraries as Atoms --------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_SHARED_LIBRARY_FILE_H_
+#define LLD_CORE_SHARED_LIBRARY_FILE_H_
+
+#include "lld/Core/File.h"
+#include "lld/Core/SharedLibraryAtom.h"
+
+namespace lld {
+
+
+///
+/// The SharedLibraryFile subclass of File is used to represent dynamic
+/// shared libraries being linked against.  
+///
+class SharedLibraryFile : public File {
+public:
+           SharedLibraryFile(StringRef path) : File(path) {
+  }
+  virtual ~SharedLibraryFile() {
+  }
+
+  virtual Kind kind() const {
+    return kindSharedLibrary;
+  }
+
+  static inline bool classof(const File *f) {
+    return f->kind() == kindSharedLibrary;
+  }
+  static inline bool classof(const SharedLibraryFile *) { 
+    return true; 
+  }
+
+
+  /// Check if the shared library exports a symbol with the specified name.
+  /// If so, return a SharedLibraryAtom which represents that exported
+  /// symbol.  Otherwise return nullptr.
+  virtual const SharedLibraryAtom *exports(StringRef name, 
+                                          bool dataSymbolOnly) const;
+  
+};
+
+} // namespace lld
+
+#endif // LLD_CORE_SHARED_LIBRARY_FILE_H_

Modified: lld/trunk/include/lld/Core/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/SymbolTable.h?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/SymbolTable.h (original)
+++ lld/trunk/include/lld/Core/SymbolTable.h Thu Apr 19 20:24:37 2012
@@ -59,6 +59,9 @@
 
   /// @brief returns vector of remaining UndefinedAtoms
   void undefines(std::vector<const Atom *>&);
+  
+  /// returns vector of tentative definitions
+  void tentativeDefinitions(std::vector<StringRef> &);
 
   /// @brief count of by-name entries in symbol table
   unsigned int size();

Modified: lld/trunk/lib/Core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/CMakeLists.txt?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/lib/Core/CMakeLists.txt (original)
+++ lld/trunk/lib/Core/CMakeLists.txt Thu Apr 19 20:24:37 2012
@@ -1,6 +1,7 @@
 add_lld_library(lldCore
   Error.cpp
   File.cpp
+  InputFiles.cpp
   NativeFileFormat.h
   NativeReader.cpp
   NativeWriter.cpp

Added: lld/trunk/lib/Core/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputFiles.cpp?rev=155183&view=auto
==============================================================================
--- lld/trunk/lib/Core/InputFiles.cpp (added)
+++ lld/trunk/lib/Core/InputFiles.cpp Thu Apr 19 20:24:37 2012
@@ -0,0 +1,84 @@
+//===- Core/InputFiles.cpp - Manages list of Files -----------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Core/InputFiles.h"
+#include "lld/Core/SharedLibraryFile.h"
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/LLVM.h"
+
+namespace lld {
+
+InputFiles::InputFiles() {
+}
+
+
+InputFiles::~InputFiles() {
+}
+
+void InputFiles::forEachInitialAtom(InputFiles::Handler &handler) const {
+  for ( const File *file : _files ) {
+    this->handleFile(file, handler);
+  }
+}
+
+void InputFiles::prependFile(const File &file) {
+  _files.insert(_files.begin(), &file);
+}
+  
+void InputFiles::appendFile(const File &file) {
+  _files.push_back(&file);
+}
+
+
+bool InputFiles::searchLibraries(StringRef name, bool searchSharedLibs,
+                               bool searchArchives, bool dataSymbolOnly,
+                               InputFiles::Handler &handler) const {
+                               
+  for ( const File *file : _files ) {
+    if ( searchSharedLibs ) {
+      if (const SharedLibraryFile *shlib = dyn_cast<SharedLibraryFile>(file)) {
+        if ( const SharedLibraryAtom* shAtom = shlib->exports(name, 
+                                                            dataSymbolOnly) ) {
+          handler.doSharedLibraryAtom(*shAtom);
+          return true;
+        }
+      }
+    }
+    if ( searchArchives ) {
+      if (const ArchiveLibraryFile *lib = dyn_cast<ArchiveLibraryFile>(file)) {
+        if ( const File *member = lib->find(name, dataSymbolOnly) ) {
+          this->handleFile(member, handler);
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+
+
+void InputFiles::handleFile(const File *file, 
+                            InputFiles::Handler &handler) const {
+  handler.doFile(*file);
+  for( const DefinedAtom *atom : file->defined() ) {
+    handler.doDefinedAtom(*atom);
+  }
+  for( const UndefinedAtom *undefAtom : file->undefined() ) {
+    handler.doUndefinedAtom(*undefAtom);
+  }
+  for( const SharedLibraryAtom *shlibAtom : file->sharedLibrary() ) {
+    handler.doSharedLibraryAtom(*shlibAtom);
+  }
+  for( const AbsoluteAtom *absAtom : file->absolute() ) {
+    handler.doAbsoluteAtom(*absAtom);
+  }
+}
+
+
+} // namespace lld

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Thu Apr 19 20:24:37 2012
@@ -137,7 +137,7 @@
 void Resolver::resolveUndefines() {
   const bool searchArchives =
     _options.searchArchivesToOverrideTentativeDefinitions();
-  const bool searchDylibs =
+  const bool searchSharedLibs =
     _options.searchSharedLibrariesToOverrideTentativeDefinitions();
 
   // keep looping until no more undefines were added in last loop
@@ -154,24 +154,20 @@
       }
     }
     // search libraries for overrides of common symbols
-    if (searchArchives || searchDylibs) {
-      std::vector<const Atom *> tents;
-      for ( const Atom *tent : tents ) {
-        if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(tent)) {
-          if ( defAtom->merge() == DefinedAtom::mergeAsTentative )
-            tents.push_back(defAtom);
-        }
-      }
-      for ( const Atom *tent : tents ) {
-        // load for previous tentative may also have loaded
-        // this tentative, so check again
-        StringRef tentName = tent->name();
-        const Atom *curAtom = _symbolTable.findByName(tentName);
+    if (searchArchives || searchSharedLibs) {
+      std::vector<StringRef> tentDefNames;
+      _symbolTable.tentativeDefinitions(tentDefNames);
+      for ( StringRef tentDefName : tentDefNames ) {
+        // Load for previous tentative may also have loaded
+        // something that overrode this tentative, so always check. 
+        const Atom *curAtom = _symbolTable.findByName(tentDefName);
         assert(curAtom != nullptr);
         if (const DefinedAtom* curDefAtom = dyn_cast<DefinedAtom>(curAtom)) {
-          if (curDefAtom->merge() == DefinedAtom::mergeAsTentative )
-            _inputFiles.searchLibraries(tentName, searchDylibs,
-                                        true, true, *this);
+          if (curDefAtom->merge() == DefinedAtom::mergeAsTentative ) {
+            // Still tentative definition, so look for override.
+            _inputFiles.searchLibraries(tentDefName, searchSharedLibs,
+                                        searchArchives, true, *this);
+          }
         }
       }
     }

Modified: lld/trunk/lib/Core/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/lib/Core/SymbolTable.cpp (original)
+++ lld/trunk/lib/Core/SymbolTable.cpp Thu Apr 19 20:24:37 2012
@@ -330,4 +330,16 @@
   }
 }
 
+void SymbolTable::tentativeDefinitions(std::vector<StringRef> &names) {
+  for (auto entry : _nameTable) {
+    const Atom *atom = entry.second;
+    StringRef name   = entry.first;
+    assert(atom != nullptr);
+    if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom) ) {
+      if ( defAtom->merge() == DefinedAtom::mergeAsTentative )
+        names.push_back(name);
+    }
+  }
+}
+
 } // namespace lld

Modified: lld/trunk/lib/Core/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)
+++ lld/trunk/lib/Core/YamlKeyValues.cpp Thu Apr 19 20:24:37 2012
@@ -10,6 +10,7 @@
 #include "YamlKeyValues.h"
 
 #include "llvm/Support/ErrorHandling.h"
+#include "lld/Core/File.h"
 
 #include <cstring>
 
@@ -40,6 +41,9 @@
 const char* const KeyValues::fixupsOffsetKeyword    = "offset";
 const char* const KeyValues::fixupsTargetKeyword    = "target";
 const char* const KeyValues::fixupsAddendKeyword    = "addend";
+const char* const KeyValues::fileAtomsKeyword       = "atoms";
+const char* const KeyValues::fileKindKeyword        = "kind";
+const char* const KeyValues::fileMembersKeyword     = "members";
 
 
 
@@ -54,9 +58,36 @@
 const bool                            KeyValues::isThumbDefault = false;
 const bool                            KeyValues::isAliasDefault = false;
 const UndefinedAtom::CanBeNull        KeyValues::canBeNullDefault = UndefinedAtom::canBeNullNever;
+const File::Kind                      KeyValues::fileKindDefault = File::kindObject;
 
 
+struct FileKindMapping {
+  const char*       string;
+  File::Kind        value;
+};
+
+static const FileKindMapping fileKindMappings[] = {
+  { "object",         File::kindObject },
+  { "archive",        File::kindArchiveLibrary },
+  { "shared-library", File::kindSharedLibrary },
+  { nullptr,          File::kindObject }
+};
 
+ File::Kind KeyValues::fileKind(const char* str) {
+  for (const FileKindMapping* p = fileKindMappings; p->string != nullptr; ++p) {
+    if ( strcmp(p->string, str) == 0 )
+      return p->value;
+  }
+  llvm::report_fatal_error("bad file kind value");
+}
+
+const char* KeyValues::fileKind(File::Kind k) {
+  for (const FileKindMapping* p = fileKindMappings; p->string != nullptr; ++p) {
+    if ( p->value == k )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad file kind value");
+}
 
 
 struct DefinitionMapping {

Modified: lld/trunk/lib/Core/YamlKeyValues.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.h?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.h (original)
+++ lld/trunk/lib/Core/YamlKeyValues.h Thu Apr 19 20:24:37 2012
@@ -13,6 +13,7 @@
 #include "lld/Core/Atom.h"
 #include "lld/Core/DefinedAtom.h"
 #include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/File.h"
 
 
 namespace lld {
@@ -28,6 +29,13 @@
   static const char* const                loadNameKeyword;
   static const char* const                valueKeyword;
   static const char* const                fixupsKeyword;
+  static const char* const                fileAtomsKeyword;
+  static const char* const                fileMembersKeyword;
+
+  static const char* const                fileKindKeyword;
+  static const File::Kind                 fileKindDefault;
+  static File::Kind                       fileKind(const char*);
+  static const char*                      fileKind(File::Kind);
 
   static const char* const                definitionKeyword;
   static const Atom::Definition           definitionDefault;

Modified: lld/trunk/lib/Core/YamlReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlReader.cpp (original)
+++ lld/trunk/lib/Core/YamlReader.cpp Thu Apr 19 20:24:37 2012
@@ -13,6 +13,7 @@
 #include "lld/Core/AbsoluteAtom.h"
 #include "lld/Core/Error.h"
 #include "lld/Core/File.h"
+#include "lld/Core/ArchiveLibraryFile.h"
 #include "lld/Core/LLVM.h"
 #include "lld/Core/Platform.h"
 #include "lld/Core/Reference.h"
@@ -30,6 +31,7 @@
 
 #include <cstring>
 #include <vector>
+#include <set>
 
 
 
@@ -300,36 +302,47 @@
 
 class YAMLDefinedAtom;
 
-class YAMLFile : public File {
+class YAMLFile : public ArchiveLibraryFile {
 public:
   YAMLFile()
-    : File("path")
-    , _lastRefIndex(0) {}
+    : ArchiveLibraryFile("<anonymous>")
+    , _lastRefIndex(0) 
+    , _kind(File::kindObject)
+    , _inArchive(false) {
+  }
+
+  virtual File::Kind kind() const {
+    return _kind;
+  }
 
   virtual const atom_collection<DefinedAtom>& defined() const {
     return _definedAtoms;
   }
   virtual const atom_collection<UndefinedAtom>& undefined() const {
-      return _undefinedAtoms;
+    return _undefinedAtoms;
   }
   virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
-      return _sharedLibraryAtoms;
+    return _sharedLibraryAtoms;
   }
   virtual const atom_collection<AbsoluteAtom>& absolute() const {
-      return _absoluteAtoms;
+    return _absoluteAtoms;
   }
 
   virtual void addAtom(const Atom&) {
     assert(0 && "cannot add atoms to YAML files");
   }
 
+  virtual const File *find(StringRef name, bool dataSymbolOnly) const;
+
   void bindTargetReferences();
   void addDefinedAtom(YAMLDefinedAtom* atom, const char* refName);
   void addUndefinedAtom(UndefinedAtom* atom);
   void addSharedLibraryAtom(SharedLibraryAtom* atom);
   void addAbsoluteAtom(AbsoluteAtom* atom);
   Atom* findAtom(const char* name);
-
+  void addMember(const char*);
+  void setName(const char*);
+ 
   struct NameAtomPair {
                  NameAtomPair(const char* n, Atom* a) : name(n), atom(a) {}
     const char*  name;
@@ -342,7 +355,11 @@
   atom_collection_vector<AbsoluteAtom>        _absoluteAtoms;
   std::vector<YAMLReference>                  _references;
   std::vector<NameAtomPair>                   _nameToAtomMapping;
+  std::vector<const char*>                    _memberNames;
+  std::vector<YAMLFile*>                      _memberFiles;
   unsigned int                                _lastRefIndex;
+  File::Kind                                  _kind;
+  bool                                        _inArchive;
 };
 
 
@@ -643,6 +660,25 @@
   _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
 }
 
+void YAMLFile::addMember(const char* name) {
+  _memberNames.push_back(name);
+}
+
+void YAMLFile::setName(const char* name) {
+  _path = StringRef(name);
+}
+
+const File *YAMLFile::find(StringRef name, bool dataSymbolOnly) const {
+  for (YAMLFile *file : _memberFiles) {
+    for (const DefinedAtom *atom : file->defined() ) {
+      if ( name.equals(atom->name()) )
+        return file;
+    }
+  }
+  return NULL;
+}
+
+
 
 class YAMLAtomState {
 public:
@@ -810,17 +846,21 @@
                           , Platform& platform
                           , std::vector<const File *> &result) {
   std::vector<const YAML::Entry *> entries;
+  std::vector<YAMLFile*> allFiles;
   YAML::parse(mb, entries);
 
   YAMLFile *file = nullptr;
   YAMLAtomState atomState(platform);
   bool inAtoms       = false;
   bool inFixups      = false;
+  bool inMembers     = false;
   int depthForAtoms  = -1;
   int depthForFixups = -1;
+  int depthForMembers= -1;
   int lastDepth      = -1;
   bool haveAtom      = false;
   bool haveFixup     = false;
+  bool hasArchives = false;
 
   for (std::vector<const YAML::Entry *>::iterator it = entries.begin();
        it != entries.end(); ++it) {
@@ -833,7 +873,7 @@
           haveAtom = false;
         }
         file->bindTargetReferences();
-        result.push_back(file);
+        allFiles.push_back(file);
       }
       file = new YAMLFile();
       inAtoms = false;
@@ -853,9 +893,24 @@
     if (inFixups && (depthForFixups == -1)) {
       depthForFixups = entry->depth;
     }
-    if (strcmp(entry->key, "atoms") == 0) {
+    if (inMembers && (depthForMembers == -1)) {
+      depthForMembers = entry->depth;
+    }
+    if ( !inFixups && (strcmp(entry->key, KeyValues::fileKindKeyword) == 0) ) {
+      file->_kind = KeyValues::fileKind(entry->value);
+      if ( file->_kind == File::kindArchiveLibrary ) 
+        hasArchives = true;
+    }
+    else if (strcmp(entry->key, KeyValues::fileMembersKeyword) == 0) {
+      inMembers = true;
+    }
+    else if (strcmp(entry->key, KeyValues::fileAtomsKeyword) == 0) {
       inAtoms = true;
     }
+    else if ( !inAtoms && !inMembers 
+                       && (strcmp(entry->key, KeyValues::nameKeyword) == 0) ) {
+      file->setName(entry->value);
+    }
     if (inAtoms) {
       if (depthForAtoms == entry->depth) {
         if (entry->beginSequence) {
@@ -980,6 +1035,15 @@
         }
       }
     }
+    else if (inMembers) {
+      if (depthForMembers == entry->depth) {
+        if (entry->beginSequence) {
+          if (strcmp(entry->key, KeyValues::nameKeyword) == 0) {
+            file->addMember(entry->value);
+          }
+        }
+      }
+    }
     lastDepth = entry->depth;
   }
   if (haveAtom) {
@@ -987,8 +1051,31 @@
   }
   if (file != nullptr) {
     file->bindTargetReferences();
-    result.push_back(file);
+    allFiles.push_back(file);
+  }
+  
+  // If yaml contained archive files, push members down into archives
+  if ( hasArchives ) {
+    for (YAMLFile *f : allFiles) {
+      if ( f->kind() == File::kindArchiveLibrary ) {
+        for (const char *memberName : f->_memberNames ) {
+          for (YAMLFile *f2 : allFiles) {
+            if ( f2->path().equals(memberName) ) {
+              f2->_inArchive = true;
+              f->_memberFiles.push_back(f2);
+            }
+          }
+        }
+      }
+    }
+  }
+  // Copy files that have not been pushed into archives to result.
+  for (YAMLFile *f : allFiles) {
+    if ( ! f->_inArchive ) {
+      result.push_back(f);
+    }
   }
+  
   return make_error_code(yaml_reader_error::success);
 }
 

Added: lld/trunk/test/archive-basic.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/archive-basic.objtxt?rev=155183&view=auto
==============================================================================
--- lld/trunk/test/archive-basic.objtxt (added)
+++ lld/trunk/test/archive-basic.objtxt Thu Apr 19 20:24:37 2012
@@ -0,0 +1,47 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Tests archives in YAML. Tests that an undefined in a regular file will load
+# all atoms in select archive members.
+#
+
+---
+atoms:
+    - name:              foo
+      type:              code
+      
+    - name:              bar
+      definition:        undefined
+
+---
+name: bar.o
+atoms:
+    - name:              bar
+      scope:             global
+      type:              code
+      
+    - name:              bar2
+      type:              code
+  
+---
+name: baz.o
+atoms:
+    - name:              baz
+      scope:             global
+      type:              code
+      
+    - name:              baz2
+      type:              code
+---
+kind: archive
+members:  
+    - name:    bar.o
+    - name:    baz.o
+...
+
+# CHECK:       name:       foo
+# CHECK:       name:       bar
+# CHECK-NOT:   definition: undefined
+# CHECK:       name:       bar2
+# CHECK-NOT:   name:       baz
+# CHECK:       ...

Added: lld/trunk/test/archive-chain.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/archive-chain.objtxt?rev=155183&view=auto
==============================================================================
--- lld/trunk/test/archive-chain.objtxt (added)
+++ lld/trunk/test/archive-chain.objtxt Thu Apr 19 20:24:37 2012
@@ -0,0 +1,74 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Tests that an undefine in one archive can force a load from another archive.
+#
+
+---
+atoms:
+    - name:              foo
+      type:              code
+      
+    - name:              bar1
+      definition:        undefined
+
+---
+name: bar1.o
+atoms:
+    - name:              bar1
+      scope:             global
+      type:              code
+      
+    - name:              bar1b
+      type:              code
+  
+    - name:              baz1
+      definition:        undefined
+---
+name: bar2.o
+atoms:
+    - name:              bar2
+      scope:             global
+      type:              code
+      
+    - name:              bar2b
+      type:              code
+  
+---
+name: baz1.o
+atoms:
+    - name:              baz1
+      scope:             global
+      type:              code
+      
+    - name:              baz1b
+      type:              code
+---
+name: baz2.o
+atoms:
+    - name:              baz2
+      scope:             global
+      type:              code
+      
+    - name:              baz2b
+      type:              code
+---
+kind: archive
+members:  
+    - name:    bar1.o
+    - name:    bar2.o
+---
+kind: archive
+members:  
+    - name:    baz1.o
+    - name:    baz2.o
+...
+
+# CHECK:       name:       foo
+# CHECK:       name:       bar1
+# CHECK:       name:       bar1b
+# CHECK-NOT:   name:       bar2
+# CHECK:       name:       baz1
+# CHECK:       name:       baz1b
+# CHECK-NOT:   name:       baz2
+# CHECK:       ...

Added: lld/trunk/test/archive-tentdef-search.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/archive-tentdef-search.objtxt?rev=155183&view=auto
==============================================================================
--- lld/trunk/test/archive-tentdef-search.objtxt (added)
+++ lld/trunk/test/archive-tentdef-search.objtxt Thu Apr 19 20:24:37 2012
@@ -0,0 +1,45 @@
+# RUN: lld-core -commons-search-archives=false  %s | FileCheck -check-prefix=CHK1 %s
+# RUN: lld-core -commons-search-archives=true   %s | FileCheck -check-prefix=CHK2 %s
+
+#
+# Tests that -commons_search_archives cause core linker to look for overrides
+# of tentative definition in archives, and that not using that option
+# does not search.
+#
+
+---
+atoms:
+    - name:              foo
+      type:              code
+      
+    - name:              bar
+      scope:             global
+      content:           zero-fill
+      merge:             asTentative
+
+---
+name: bar.o
+atoms:
+    - name:              bar
+      scope:             global
+      type:              data
+      
+    - name:              bar2
+      type:              data
+  
+---
+kind: archive
+members:  
+    - name:    bar.o
+...
+
+# CHK1:       name:       foo
+# CHK1:       name:       bar
+# CHK1:       merge:      asTentative
+# CHK1:       ...
+
+# CHK2:       name:       foo
+# CHK2:       name:       bar
+# CHK2-NOT:  merge:      asTentative
+# CHK2:       name:       bar2
+# CHK2:       ...

Modified: lld/trunk/test/darwin/hello-world.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/darwin/hello-world.objtxt?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/test/darwin/hello-world.objtxt (original)
+++ lld/trunk/test/darwin/hello-world.objtxt Thu Apr 19 20:24:37 2012
@@ -1,4 +1,4 @@
-# RUN: lld-core -platform darwin -stubs_pass %s -o %t && llvm-nm %t | FileCheck %s
+# RUN: lld-core -platform darwin -stubs-pass %s -o %t && llvm-nm %t | FileCheck %s
 
 #
 # Test that hello-world can be linked into a mach-o executable

Added: lld/trunk/test/dead-strip-basic.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/dead-strip-basic.objtxt?rev=155183&view=auto
==============================================================================
--- lld/trunk/test/dead-strip-basic.objtxt (added)
+++ lld/trunk/test/dead-strip-basic.objtxt Thu Apr 19 20:24:37 2012
@@ -0,0 +1,63 @@
+# RUN: lld-core -dead-strip=true  %s | FileCheck -check-prefix=CHK1 %s
+# RUN: lld-core -dead-strip=false %s | FileCheck -check-prefix=CHK2 %s
+
+#
+# Test that -dead-strip removes unreachable code and data
+# and that not using that option leaves them.
+#
+
+---
+atoms:
+    - name:         entry
+      dead-strip:   never
+      fixups:
+      - offset:          1
+        kind:            pcrel32
+        target:          bar
+      - offset:          6
+        kind:            pcrel32
+        target:          baz
+  
+    - name:         mydead1
+      scope:        global
+
+    - name:         bar
+      definition:   undefined
+
+    - name:         baz
+      definition:   undefined
+---
+atoms:
+    - name:         mydead2
+      scope:        global
+      type:         data
+
+    - name:         bar
+      scope:        global
+      type:         data
+---
+atoms:
+    - name:         baz
+      scope:        global
+      type:         code
+
+    - name:         mydead3
+      type:         code
+...
+
+
+# CHK1:       name: entry
+# CHK1-NOT:   name: mydead1
+# CHK1:       name: bar
+# CHK1-NOT:   name: mydead2
+# CHK1:       name: baz
+# CHK1-NOT:   name: mydead3
+# CHK1:       ...
+
+# CHK2:       name: entry
+# CHK2:       name: mydead1
+# CHK2:       name: mydead2
+# CHK2:       name: bar
+# CHK2:       name: baz
+# CHK2:       name: mydead3
+# CHK2:       ...

Added: lld/trunk/test/dead-strip-globals.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/dead-strip-globals.objtxt?rev=155183&view=auto
==============================================================================
--- lld/trunk/test/dead-strip-globals.objtxt (added)
+++ lld/trunk/test/dead-strip-globals.objtxt Thu Apr 19 20:24:37 2012
@@ -0,0 +1,62 @@
+# RUN: lld-core -dead-strip -keep-globals=true  %s | FileCheck -check-prefix=CHK1 %s
+# RUN: lld-core -dead-strip -keep-globals=false %s | FileCheck -check-prefix=CHK2 %s
+
+#
+# Test that -keep-globals prevents -dead-strip from removing globals.
+#
+
+---
+atoms:
+    - name:         entry
+      dead-strip:   never
+      fixups:
+      - offset:          1
+        kind:            pcrel32
+        target:          bar
+      - offset:          6
+        kind:            pcrel32
+        target:          baz
+  
+    - name:         myglobal1
+      scope:        global
+
+    - name:         bar
+      definition:   undefined
+
+    - name:         baz
+      definition:   undefined
+---
+atoms:
+    - name:         myglobal2
+      scope:        global
+      type:         data
+
+    - name:         bar
+      scope:        hidden
+      type:         data
+---
+atoms:
+    - name:         baz
+      scope:        hidden
+      type:         code
+
+    - name:         mydead
+      type:         code
+...
+
+
+# CHK1:       name: entry
+# CHK1:       name: myglobal1
+# CHK1:       name: myglobal2
+# CHK1:       name: bar
+# CHK1:       name: baz
+# CHK1-NOT:   name: mydead
+# CHK1:       ...
+
+# CHK2:       name: entry
+# CHK2-NOT:   name: myglobal1
+# CHK2-NOT:   name: myglobal2
+# CHK2:       name: bar
+# CHK2:       name: baz
+# CHK2-NOT:   name: mydead
+# CHK2:       ...

Modified: lld/trunk/test/pass-got-basic.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pass-got-basic.objtxt?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/test/pass-got-basic.objtxt (original)
+++ lld/trunk/test/pass-got-basic.objtxt Thu Apr 19 20:24:37 2012
@@ -1,4 +1,4 @@
-# RUN: lld-core %s -got_pass  | FileCheck %s
+# RUN: lld-core %s -got-pass  | FileCheck %s
 
 #
 # Test that GOT pass instantiates GOT entires and alters references

Modified: lld/trunk/test/pass-stubs-basic.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pass-stubs-basic.objtxt?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/test/pass-stubs-basic.objtxt (original)
+++ lld/trunk/test/pass-stubs-basic.objtxt Thu Apr 19 20:24:37 2012
@@ -1,4 +1,4 @@
-# RUN: lld-core %s -stubs_pass  | FileCheck %s
+# RUN: lld-core %s -stubs-pass  | FileCheck %s
 
 #
 # Test that stubs pass adds stubs and rebinds call sites to the stub

Modified: lld/trunk/test/undef-coalesce-error.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/undef-coalesce-error.objtxt?rev=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/test/undef-coalesce-error.objtxt (original)
+++ lld/trunk/test/undef-coalesce-error.objtxt Thu Apr 19 20:24:37 2012
@@ -1,8 +1,10 @@
-# RUN: not lld-core -undefines_are_errors %s 2> %t.err
-# RUN: FileCheck < %t.err %s
+# RUN: not lld-core -undefines-are-errors %s 2> %t.err
+# RUN:   FileCheck -check-prefix=CHECKERR < %t.err %s
+# RUN: lld-core -undefines-are-errors=false %s | FileCheck %s
 
 #
-# Test that any remaining undefined symbols cause an error
+# Test that -undefines-are-errors triggers and error 
+# and that not using that option results in undefined atoms.
 #
 
 ---
@@ -35,6 +37,15 @@
       definition:        undefined
 ...
 
-# CHECK:       free
-# CHECK:       malloc
-# CHECK:       symbol(s) not found
+# CHECKERR:       free
+# CHECKERR:       malloc
+# CHECKERR:       symbol(s) not found
+
+# CHECK:   name:  foo
+# CHECK:   name:  bar
+# CHECK:   name:  myfunc
+# CHECK:   name:  malloc
+# CHECK:   definition:  undefined
+# CHECK:   name:  free
+# CHECK:   definition:  undefined
+# CHECK:   ...

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=155183&r1=155182&r2=155183&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Thu Apr 19 20:24:37 2012
@@ -345,78 +345,43 @@
   };
 
 
-
-//
-// A simple input files wrapper for testing.
-//
-class TestingInputFiles : public InputFiles {
-public:
-  TestingInputFiles(std::vector<const File*>& f) : _files(f) { }
-
-  // InputFiles interface
-  virtual void forEachInitialAtom(InputFiles::Handler& handler) const {
-    for ( const File *file : _files ) {
-      handler.doFile(*file);
-      for( const DefinedAtom *atom : file->defined() ) {
-        handler.doDefinedAtom(*atom);
-      }
-      for( const UndefinedAtom *undefAtom : file->undefined() ) {
-        handler.doUndefinedAtom(*undefAtom);
-      }
-      for( const SharedLibraryAtom *shlibAtom : file->sharedLibrary() ) {
-        handler.doSharedLibraryAtom(*shlibAtom);
-      }
-      for( const AbsoluteAtom *absAtom : file->absolute() ) {
-        handler.doAbsoluteAtom(*absAtom);
-      }
-    }
-  }
-
-  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 {
-    return false;
-  }
-
-
-private:
-  std::vector<const File*>&        _files;
-};
-}
-
-
+} // anon namespace
 
 
 llvm::cl::opt<std::string> 
-gInputFilePath(llvm::cl::Positional,
+cmdLineInputFilePath(llvm::cl::Positional,
               llvm::cl::desc("<input file>"),
               llvm::cl::init("-"));
 
 llvm::cl::opt<std::string> 
-gOutputFilePath("o", 
+cmdLineOutputFilePath("o", 
               llvm::cl::desc("Specify output filename"), 
               llvm::cl::value_desc("filename"));
 
 llvm::cl::opt<bool> 
-gDoStubsPass("stubs_pass", 
+cmdLineDoStubsPass("stubs-pass", 
           llvm::cl::desc("Run pass to create stub atoms"));
 
 llvm::cl::opt<bool> 
-gDoGotPass("got_pass", 
+cmdLineDoGotPass("got-pass", 
           llvm::cl::desc("Run pass to create GOT atoms"));
 
 llvm::cl::opt<bool> 
-gUndefinesIsError("undefines_are_errors", 
+cmdLineUndefinesIsError("undefines-are-errors", 
           llvm::cl::desc("Any undefined symbols at end is an error"));
 
+llvm::cl::opt<bool> 
+cmdLineCommonsSearchArchives("commons-search-archives", 
+          llvm::cl::desc("Tentative definitions trigger archive search"));
+
+llvm::cl::opt<bool> 
+cmdLineDeadStrip("dead-strip", 
+          llvm::cl::desc("Remove unreachable code and data"));
+
+llvm::cl::opt<bool> 
+cmdLineGlobalsNotDeadStrip("keep-globals", 
+          llvm::cl::desc("All global symbols are roots for dead-strip"));
+
 
 enum PlatformChoice {
   platformTesting, platformDarwin
@@ -435,7 +400,10 @@
 class TestingResolverOptions : public ResolverOptions {
 public:
   TestingResolverOptions() {
-    _undefinesAreErrors = gUndefinesIsError;
+    _undefinesAreErrors = cmdLineUndefinesIsError;
+    _searchArchivesToOverrideTentativeDefinitions = cmdLineCommonsSearchArchives;
+    _deadCodeStrip = cmdLineDeadStrip;
+    _globalsAreDeadStripRoots = cmdLineGlobalsNotDeadStrip;
   }
 
 };
@@ -466,7 +434,7 @@
   
   // read input YAML doc into object file(s)
   std::vector<const File *> files;
-  if (error(yaml::parseObjectTextFileOrSTDIN(gInputFilePath, 
+  if (error(yaml::parseObjectTextFileOrSTDIN(cmdLineInputFilePath, 
                                             *platform, files))) {
     return 1;
   }
@@ -475,7 +443,10 @@
   TestingResolverOptions options;
 
   // create object to mange input files
-  TestingInputFiles inputFiles(files);
+  InputFiles inputFiles;
+  for (const File *file : files) {
+    inputFiles.appendFile(*file);
+  }
   
   platform->addFiles(inputFiles);
 
@@ -484,11 +455,11 @@
   resolver.resolve();
 
   // run passes
-  if ( gDoGotPass ) {
+  if ( cmdLineDoGotPass ) {
     GOTPass  addGot(resolver.resultFile(), *platform);
     addGot.perform();
   }
-  if ( gDoStubsPass ) {
+  if ( cmdLineDoStubsPass ) {
     StubsPass  addStubs(resolver.resultFile(), *platform);
     addStubs.perform();
   }
@@ -515,7 +486,8 @@
 
   // write new atom graph
   std::string errorInfo;
-  const char* outPath = gOutputFilePath.empty() ? "-" : gOutputFilePath.c_str();
+  const char* outPath = (cmdLineOutputFilePath.empty() ? "-" 
+                                              : cmdLineOutputFilePath.c_str());
   llvm::raw_fd_ostream out(outPath, errorInfo);
   if ( platformSelected == platformTesting) {
     // write atom graph out as YAML doc





More information about the llvm-commits mailing list