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

Nick Kledzik kledzik at apple.com
Wed Feb 22 13:57:00 PST 2012


Author: kledzik
Date: Wed Feb 22 15:56:59 2012
New Revision: 151204

URL: http://llvm.org/viewvc/llvm-project?rev=151204&view=rev
Log:
Add support for SharedLibraryAtoms (proxy atoms for exported symbols from a 
shared library) and AbsoluteAtoms (proxy atoms for absolute address (e.g. ROM)).
Redesign weak importing as can-be-null-at-runtime and can-be-null-at-build-time.
Add lots of test cases for all the above.

Added:
    lld/trunk/include/lld/Core/AbsoluteAtom.h
    lld/trunk/include/lld/Core/SharedLibraryAtom.h
    lld/trunk/test/absolute-basic.objtxt
    lld/trunk/test/empty.objtxt
    lld/trunk/test/shared-library-basic.objtxt
    lld/trunk/test/shared-library-coalesce.objtxt
    lld/trunk/test/undef-weak-coalesce.objtxt
Modified:
    lld/trunk/include/lld/Core/Atom.h
    lld/trunk/include/lld/Core/File.h
    lld/trunk/include/lld/Core/Resolver.h
    lld/trunk/include/lld/Core/SymbolTable.h
    lld/trunk/include/lld/Core/UndefinedAtom.h
    lld/trunk/include/lld/Platform/Platform.h
    lld/trunk/lib/Core/NativeFileFormat.h
    lld/trunk/lib/Core/NativeReader.cpp
    lld/trunk/lib/Core/NativeWriter.cpp
    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/lib/Core/YamlWriter.cpp
    lld/trunk/tools/lld-core/lld-core.cpp

Added: lld/trunk/include/lld/Core/AbsoluteAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/AbsoluteAtom.h?rev=151204&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/AbsoluteAtom.h (added)
+++ lld/trunk/include/lld/Core/AbsoluteAtom.h Wed Feb 22 15:56:59 2012
@@ -0,0 +1,41 @@
+//===- Core/AbsoluteAtom.h - An absolute Atom -----------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_ABSOLUTE_ATOM_H_
+#define LLD_CORE_ABSOLUTE_ATOM_H_
+
+#include "lld/Core/Atom.h"
+
+namespace lld {
+
+/// An AbsoluteAtom has no content.
+/// It exists to represent content at fixed addresses in memory.
+class AbsoluteAtom : public Atom {
+public:
+  virtual Definition definition() const {
+    return Atom::definitionAbsolute;
+  }
+
+  /// like dynamic_cast, if atom is definitionAbsolute
+  /// returns atom cast to AbsoluteAtom*, else returns NULL
+  virtual const AbsoluteAtom* absoluteAtom() const { 
+    return this;
+  }
+  
+  virtual uint64_t value() const = 0;
+  
+  
+protected:
+           AbsoluteAtom() {}
+  virtual ~AbsoluteAtom() {}
+};
+
+} // namespace lld
+
+#endif // LLD_CORE_ABSOLUTE_ATOM_H_

Modified: lld/trunk/include/lld/Core/Atom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Atom.h?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Atom.h (original)
+++ lld/trunk/include/lld/Core/Atom.h Wed Feb 22 15:56:59 2012
@@ -21,8 +21,10 @@
 class File;
 class DefinedAtom;
 class UndefinedAtom;
+class SharedLibraryAtom;
+class AbsoluteAtom;
 
-///
+  ///
 /// The linker has a Graph Theory model of linking. An object file is seen
 /// as a set of Atoms with References to other Atoms.  Each Atom is a node
 /// and each Reference is an edge. An Atom can be a DefinedAtom which has
@@ -52,12 +54,20 @@
   
   /// definedAtom - like dynamic_cast, if atom is definitionRegular
   /// returns atom cast to DefinedAtom*, else returns nullptr;
-  virtual const DefinedAtom* definedAtom() const { return 0; }
+  virtual const DefinedAtom* definedAtom() const { return NULL; }
 
   /// undefinedAtom - like dynamic_cast, if atom is definitionUndefined
   /// returns atom cast to UndefinedAtom*, else returns NULL;
   virtual const UndefinedAtom* undefinedAtom() const { return NULL; }
   
+  /// sharedLibraryAtom - like dynamic_cast, if atom is definitionSharedLibrary
+  /// returns atom cast to SharedLibraryAtom*, else returns nullptr;
+  virtual const SharedLibraryAtom* sharedLibraryAtom() const { return NULL; }
+  
+  /// absoluteAtom - like dynamic_cast, if atom is definitionAbsolute
+  /// returns atom cast to AbsoluteAtom*, else returns nullptr;
+  virtual const AbsoluteAtom* absoluteAtom() const { return NULL; }
+  
 protected:
   /// Atom is an abstract base class.  Only subclasses can access constructor.
   Atom() {}

Modified: lld/trunk/include/lld/Core/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/File.h?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/File.h (original)
+++ lld/trunk/include/lld/Core/File.h Wed Feb 22 15:56:59 2012
@@ -14,6 +14,8 @@
 
 #include "lld/Core/DefinedAtom.h"
 #include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/SharedLibraryAtom.h"
+#include "lld/Core/AbsoluteAtom.h"
 
 namespace lld {
 
@@ -27,6 +29,8 @@
     virtual ~AtomHandler() {}
     virtual void doDefinedAtom(const class DefinedAtom &) = 0;
     virtual void doUndefinedAtom(const class UndefinedAtom &) = 0;
+    virtual void doSharedLibraryAtom(const class SharedLibraryAtom &) = 0;
+    virtual void doAbsoluteAtom(const class AbsoluteAtom &) = 0;
     virtual void doFile(const class File &) = 0;
   };
 

Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Wed Feb 22 15:56:59 2012
@@ -43,6 +43,8 @@
   // AtomHandler methods
   virtual void doDefinedAtom(const class DefinedAtom&);
   virtual void doUndefinedAtom(const class UndefinedAtom&);
+  virtual void doSharedLibraryAtom(const class SharedLibraryAtom &);
+  virtual void doAbsoluteAtom(const class AbsoluteAtom &);
   virtual void doFile(const File&);
 
   /// @brief do work of merging and resolving and return list

Added: lld/trunk/include/lld/Core/SharedLibraryAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/SharedLibraryAtom.h?rev=151204&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/SharedLibraryAtom.h (added)
+++ lld/trunk/include/lld/Core/SharedLibraryAtom.h Wed Feb 22 15:56:59 2012
@@ -0,0 +1,51 @@
+//===- Core/SharedLibraryAtom.h - A Shared Library Atom -------------------===//
+//
+//                             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_ATOM_H_
+#define LLD_CORE_SHARED_LIBRARY_ATOM_H_
+
+#include "lld/Core/Atom.h"
+
+namespace llvm {
+  class StringRef;
+}
+
+namespace lld {
+
+/// A SharedLibraryAtom has no content.
+/// It exists to represent a symbol which will be bound at runtime.
+class SharedLibraryAtom : public Atom {
+public:
+  virtual Definition definition() const {
+    return Atom::definitionSharedLibrary;
+  }
+
+  /// like dynamic_cast, if atom is definitionSharedLibrary
+  /// returns atom cast to SharedLibraryAtom*, else returns NULL
+  virtual const SharedLibraryAtom* sharedLibraryAtom() const { 
+    return this;
+  }
+
+  /// Returns shared library name used to load it at runtime.
+  /// On linux that is the DT_NEEDED name.
+  /// On Darwin it is the LC_DYLIB_LOAD dylib name.
+  virtual llvm::StringRef loadName() const = 0;
+
+  /// Returns if shared library symbol can be missing at runtime and if
+  /// so the loader should silently resolve address of symbol to be NULL.
+  virtual bool canBeNullAtRuntime() const = 0;
+  
+protected:
+           SharedLibraryAtom() {}
+  virtual ~SharedLibraryAtom() {}
+};
+
+} // namespace lld
+
+#endif // LLD_CORE_SHARED_LIBRARY_ATOM_H_

Modified: lld/trunk/include/lld/Core/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/SymbolTable.h?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/SymbolTable.h (original)
+++ lld/trunk/include/lld/Core/SymbolTable.h Wed Feb 22 15:56:59 2012
@@ -24,6 +24,8 @@
 class Atom;
 class DefinedAtom;
 class UndefinedAtom;
+class SharedLibraryAtom;
+class AbsoluteAtom;
 class Platform;
 
 /// The SymbolTable class is responsible for coalescing atoms.
@@ -41,6 +43,12 @@
   /// @brief add atom to symbol table
   void add(const UndefinedAtom &);
 
+  /// @brief add atom to symbol table
+  void add(const SharedLibraryAtom &);
+  
+  /// @brief add atom to symbol table
+  void add(const AbsoluteAtom &);
+  
   /// @brief checks if name is in symbol table and if so atom is not
   ///        UndefinedAtom
   bool isDefined(llvm::StringRef sym);

Modified: lld/trunk/include/lld/Core/UndefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/UndefinedAtom.h?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/UndefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/UndefinedAtom.h Wed Feb 22 15:56:59 2012
@@ -12,8 +12,6 @@
 
 #include "lld/Core/Atom.h"
 
-#include "llvm/ADT/StringRef.h"
-
 namespace lld {
 
 /// An UndefinedAtom has no content.
@@ -30,9 +28,40 @@
     return this;
   }
 
-  /// returns if undefined symbol can be missing at runtime
-  virtual bool weakImport() const = 0;
+  /// Whether this undefined symbol needs to be resolved,
+  /// or whether it can just evaluate to NULL.
+  /// This concept is often called "weak", but that term
+  /// is overloaded to mean other things too.
+  enum CanBeNull {
+    /// Normal symbols must be resolved at build time
+    canBeNullNever,
+    
+    /// This symbol can be missing at runtime and will evalute to NULL.
+    /// That is, the static linker still must find a definition (usually
+    /// is some shared library), but at runtime, the dynamic loader
+    /// will allow the symbol to be missing and resolved to NULL.
+    ///
+    /// On Darwin this is generated using a function prototype with
+    /// __attribute__((weak_import)).  
+    /// On linux this is generated using a function prototype with
+    ///  __attribute__((weak)).
+    canBeNullAtRuntime,
+    
+    
+    /// This symbol can be missing at build time.
+    /// That is, the static linker will not error if a definition for
+    /// this symbol is not found at build time. Instead, the linker 
+    /// will build an executable that lets the dynamic loader find the
+    /// symbol at runtime.  
+    /// This feature is not supported on Darwin.
+    /// On linux this is generated using a function prototype with
+    ///  __attribute__((weak)).
+    canBeNullAtBuildtime
+  };
+  
+  virtual CanBeNull canBeNull() const = 0;
   
+   
 protected:
            UndefinedAtom() {}
   virtual ~UndefinedAtom() {}

Modified: lld/trunk/include/lld/Platform/Platform.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Platform/Platform.h?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/include/lld/Platform/Platform.h (original)
+++ lld/trunk/include/lld/Platform/Platform.h Wed Feb 22 15:56:59 2012
@@ -78,6 +78,24 @@
   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;
 };

Modified: lld/trunk/lib/Core/NativeFileFormat.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeFileFormat.h?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeFileFormat.h (original)
+++ lld/trunk/lib/Core/NativeFileFormat.h Wed Feb 22 15:56:59 2012
@@ -90,12 +90,14 @@
   NCS_DefinedAtomsV1 = 1,
   NCS_AttributesArrayV1 = 2,
   NCS_UndefinedAtomsV1 = 3,
-  NCS_Strings = 4,
-  NCS_ReferencesArrayV1 = 5,
-  NCS_ReferencesArrayV2 = 6,
-  NCS_TargetsTable = 7,
-  NCS_AddendsTable = 8,
-  NCS_Content = 9,
+  NCS_SharedLibraryAtomsV1 = 4,
+  NCS_AbsoluteAtomsV1 = 5,
+  NCS_Strings = 6,
+  NCS_ReferencesArrayV1 = 7,
+  NCS_ReferencesArrayV2 = 8,
+  NCS_TargetsTable = 9,
+  NCS_AddendsTable = 10,
+  NCS_Content = 11,
 }; 
 
 //
@@ -165,6 +167,27 @@
 
 
 
+//
+// The NCS_SharedLibraryAtomsV1 chunk contains an array of these structs
+//
+struct NativeSharedLibraryAtomIvarsV1 {
+  uint32_t  nameOffset;
+  uint32_t  loadNameOffset;
+  uint32_t  flags;
+};
+
+
+
+//
+// The NCS_AbsoluteAtomsV1 chunk contains an array of these structs
+//
+struct NativeAbsoluteAtomIvarsV1 {
+  uint32_t  nameOffset;
+  uint32_t  reserved;
+  uint64_t  value;
+};
+
+
 
 //
 // The NCS_ReferencesArrayV1 chunk contains an array of these structs

Modified: lld/trunk/lib/Core/NativeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeReader.cpp?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeReader.cpp (original)
+++ lld/trunk/lib/Core/NativeReader.cpp Wed Feb 22 15:56:59 2012
@@ -77,7 +77,7 @@
       
   virtual DefinedAtom::DeadStripKind deadStrip() const {
      return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
- }
+  }
     
   virtual DefinedAtom::ContentPermissions permissions() const {
      return (DefinedAtom::ContentPermissions)(attributes().permissions);
@@ -117,16 +117,64 @@
   virtual const File& file() const;
   virtual llvm::StringRef name() const;
   
-  virtual bool weakImport() const {
-    return (_ivarData->flags & 0x1);
+  virtual CanBeNull canBeNull() const {
+    return (CanBeNull)(_ivarData->flags & 0x3);
   }
   
+
 private:
   const NativeFile*                 _file;
   const NativeUndefinedAtomIvarsV1* _ivarData;
 };
 
 
+//
+// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
+// struct in the NCS_SharedLibraryAtomsV1 chunk.
+//
+class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
+public:
+       NativeSharedLibraryAtomV1(const NativeFile& f, 
+                             const NativeSharedLibraryAtomIvarsV1* ivarData)
+        : _file(&f), _ivarData(ivarData) { } 
+
+  virtual const File& file() const;
+  virtual llvm::StringRef name() const;
+  virtual llvm::StringRef loadName() const;
+  
+  virtual bool canBeNullAtRuntime() const {
+    return (_ivarData->flags & 0x1);
+  }
+
+private:
+  const NativeFile*                     _file;
+  const NativeSharedLibraryAtomIvarsV1* _ivarData;
+};
+
+
+//
+// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
+// struct in the NCS_AbsoluteAtomsV1 chunk.
+//
+class NativeAbsoluteAtomV1 : public AbsoluteAtom {
+public:
+       NativeAbsoluteAtomV1(const NativeFile& f, 
+                             const NativeAbsoluteAtomIvarsV1* ivarData)
+        : _file(&f), _ivarData(ivarData) { } 
+
+  virtual const File& file() const;
+  virtual llvm::StringRef name() const;
+  
+  virtual uint64_t value() const {
+    return _ivarData->value;
+  }
+
+private:
+  const NativeFile*                 _file;
+  const NativeAbsoluteAtomIvarsV1*  _ivarData;
+};
+
+
 
 //
 // An object of this class is instantied for each NativeReferenceIvarsV1
@@ -206,6 +254,12 @@
         case NCS_UndefinedAtomsV1:
           ec = file->processUndefinedAtomsV1(base, chunk);
           break;
+        case NCS_SharedLibraryAtomsV1:
+          ec = file->processSharedLibraryAtomsV1(base, chunk);
+          break;
+        case NCS_AbsoluteAtomsV1:
+          ec = file->processAbsoluteAtomsV1(base, chunk);
+          break;
         case NCS_ReferencesArrayV1:
           ec = file->processReferencesV1(base, chunk);
           break;
@@ -247,23 +301,45 @@
     // to just delete the memory.
     delete _definedAtoms.arrayStart;
     delete _undefinedAtoms.arrayStart;
+    delete _sharedLibraryAtoms.arrayStart;
+    delete _absoluteAtoms.arrayStart;
     delete _references.arrayStart;
     delete _targetsTable;
   }
   
   // visits each atom in the file
   virtual bool forEachAtom(AtomHandler& handler) const {
+    bool didSomething = false;
     for(const uint8_t* p=_definedAtoms.arrayStart; p != _definedAtoms.arrayEnd; 
           p += _definedAtoms.elementSize) {
       const DefinedAtom* atom = reinterpret_cast<const DefinedAtom*>(p);
       handler.doDefinedAtom(*atom);
+      didSomething = true;
     }
-    for(const uint8_t* p=_undefinedAtoms.arrayStart; p != _undefinedAtoms.arrayEnd; 
-          p += _undefinedAtoms.elementSize) {
+    for(const uint8_t* p=_undefinedAtoms.arrayStart; 
+                      p != _undefinedAtoms.arrayEnd; 
+                      p += _undefinedAtoms.elementSize) {
       const UndefinedAtom* atom = reinterpret_cast<const UndefinedAtom*>(p);
       handler.doUndefinedAtom(*atom);
+      didSomething = true;
+    }
+    for(const uint8_t* p=_sharedLibraryAtoms.arrayStart; 
+                  p != _sharedLibraryAtoms.arrayEnd; 
+                  p += _sharedLibraryAtoms.elementSize) {
+      const SharedLibraryAtom* atom 
+                          = reinterpret_cast<const SharedLibraryAtom*>(p);
+      handler.doSharedLibraryAtom(*atom);
+      didSomething = true;
+    }
+    for(const uint8_t* p=_absoluteAtoms.arrayStart; 
+                  p != _absoluteAtoms.arrayEnd; 
+                  p += _absoluteAtoms.elementSize) {
+      const AbsoluteAtom* atom 
+                          = reinterpret_cast<const AbsoluteAtom*>(p);
+      handler.doAbsoluteAtom(*atom);
+      didSomething = true;
     }
-    return (_definedAtoms.arrayStart != _definedAtoms.arrayEnd);
+    return didSomething;
   }
   
   // not used
@@ -275,6 +351,8 @@
 private:
   friend class NativeDefinedAtomV1;
   friend class NativeUndefinedAtomV1;
+  friend class NativeSharedLibraryAtomV1;
+  friend class NativeAbsoluteAtomV1;
   friend class NativeReferenceV1;
   
   // instantiate array of DefinedAtoms from v1 ivar data in file
@@ -308,12 +386,14 @@
   }
   
   // set up pointers to attributes array
-  llvm::error_code processAttributesV1(const uint8_t* base, const NativeChunk* chunk) {
+  llvm::error_code processAttributesV1(const uint8_t* base, 
+                                       const NativeChunk* chunk) {
     this->_attributes = base + chunk->fileOffset;
     this->_attributesMaxOffset = chunk->fileSize;
     return make_error_code(native_reader_error::success);
   }
   
+  // instantiate array of UndefinedAtoms from v1 ivar data in file
   llvm::error_code processUndefinedAtomsV1(const uint8_t* base, 
                                                 const NativeChunk* chunk) {
     const size_t atomSize = sizeof(NativeUndefinedAtomV1);
@@ -344,6 +424,70 @@
   }
   
   
+  // instantiate array of ShareLibraryAtoms from v1 ivar data in file
+  llvm::error_code processSharedLibraryAtomsV1(const uint8_t* base, 
+                                                const NativeChunk* chunk) {
+    const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
+    size_t atomsArraySize = chunk->elementCount * atomSize;
+    uint8_t* atomsStart = reinterpret_cast<uint8_t*>
+                                (operator new(atomsArraySize, std::nothrow));
+    if (atomsStart == NULL )
+      return make_error_code(native_reader_error::memory_error);
+    const size_t ivarElementSize = chunk->fileSize 
+                                          / chunk->elementCount;
+    if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
+      return make_error_code(native_reader_error::file_malformed);
+    uint8_t* atomsEnd = atomsStart + atomsArraySize;
+    const NativeSharedLibraryAtomIvarsV1* ivarData = 
+                      reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
+                                                  (base + chunk->fileOffset);
+    for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
+      NativeSharedLibraryAtomV1* atomAllocSpace = 
+                  reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
+      new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
+      ++ivarData;
+    }
+    this->_sharedLibraryAtoms.arrayStart = atomsStart;
+    this->_sharedLibraryAtoms.arrayEnd = atomsEnd;
+    this->_sharedLibraryAtoms.elementSize = atomSize;
+    this->_sharedLibraryAtoms.elementCount = chunk->elementCount;
+    return make_error_code(native_reader_error::success);
+  }
+  
+ 
+   // instantiate array of AbsoluteAtoms from v1 ivar data in file
+  llvm::error_code processAbsoluteAtomsV1(const uint8_t* base, 
+                                                const NativeChunk* chunk) {
+    const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
+    size_t atomsArraySize = chunk->elementCount * atomSize;
+    uint8_t* atomsStart = reinterpret_cast<uint8_t*>
+                                (operator new(atomsArraySize, std::nothrow));
+    if (atomsStart == NULL )
+      return make_error_code(native_reader_error::memory_error);
+    const size_t ivarElementSize = chunk->fileSize 
+                                          / chunk->elementCount;
+    if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
+      return make_error_code(native_reader_error::file_malformed);
+    uint8_t* atomsEnd = atomsStart + atomsArraySize;
+    const NativeAbsoluteAtomIvarsV1* ivarData = 
+                      reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
+                                                  (base + chunk->fileOffset);
+    for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
+      NativeAbsoluteAtomV1* atomAllocSpace = 
+                  reinterpret_cast<NativeAbsoluteAtomV1*>(s);
+      new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
+      ++ivarData;
+    }
+    this->_absoluteAtoms.arrayStart = atomsStart;
+    this->_absoluteAtoms.arrayEnd = atomsEnd;
+    this->_absoluteAtoms.elementSize = atomSize;
+    this->_absoluteAtoms.elementCount = chunk->elementCount;
+    return make_error_code(native_reader_error::success);
+  }
+  
+ 
+ 
+  
   // instantiate array of Referemces from v1 ivar data in file
   llvm::error_code processReferencesV1(const uint8_t* base, 
                                                 const NativeChunk* chunk) {
@@ -398,7 +542,24 @@
         this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
         continue;
       }
-      return make_error_code(native_reader_error::file_malformed);
+      const uint32_t slIndex = index - _definedAtoms.elementCount 
+                                     - _undefinedAtoms.elementCount;
+      if ( slIndex < _sharedLibraryAtoms.elementCount ) {
+        const uint8_t* p = _sharedLibraryAtoms.arrayStart 
+                                  + slIndex * _sharedLibraryAtoms.elementSize;
+        this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
+        continue;
+      }
+      const uint32_t abIndex = index - _definedAtoms.elementCount 
+                                     - _undefinedAtoms.elementCount
+                                     - _sharedLibraryAtoms.elementCount;
+      if ( abIndex < _absoluteAtoms.elementCount ) {
+        const uint8_t* p = _absoluteAtoms.arrayStart 
+                                  + slIndex * _absoluteAtoms.elementSize;
+        this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
+        continue;
+      }
+     return make_error_code(native_reader_error::file_malformed);
     }
     return make_error_code(native_reader_error::success);
   }
@@ -491,7 +652,8 @@
     _contentStart(NULL), 
     _contentEnd(NULL)
   {
-    _header = reinterpret_cast<const NativeFileHeader*>(_buffer->getBufferStart());
+    _header = reinterpret_cast<const NativeFileHeader*>
+                                                  (_buffer->getBufferStart());
   }
 
   struct IvarArray {
@@ -507,6 +669,8 @@
   const NativeFileHeader*         _header;
   IvarArray                       _definedAtoms;
   IvarArray                       _undefinedAtoms;
+  IvarArray                       _sharedLibraryAtoms;
+  IvarArray                       _absoluteAtoms;
   const uint8_t*                  _attributes;
   uint32_t                        _attributesMaxOffset;
   IvarArray                       _references;
@@ -567,6 +731,31 @@
 }
 
 
+
+
+inline const class File& NativeSharedLibraryAtomV1::file() const {
+  return *_file;
+}
+
+inline llvm::StringRef NativeSharedLibraryAtomV1::name() const {
+  return _file->string(_ivarData->nameOffset);
+}
+
+inline llvm::StringRef NativeSharedLibraryAtomV1::loadName() const {
+  return _file->string(_ivarData->loadNameOffset);
+}
+
+
+
+inline const class File& NativeAbsoluteAtomV1::file() const {
+  return *_file;
+}
+
+inline llvm::StringRef NativeAbsoluteAtomV1::name() const {
+  return _file->string(_ivarData->nameOffset);
+}
+
+
 inline const Atom* NativeReferenceV1::target() const {
   return _file->target(_ivarData->targetIndex);
 }

Modified: lld/trunk/lib/Core/NativeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeWriter.cpp?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeWriter.cpp (original)
+++ lld/trunk/lib/Core/NativeWriter.cpp Wed Feb 22 15:56:59 2012
@@ -61,7 +61,21 @@
       out.write((char*)&_undefinedAtomIvars[0], 
               _undefinedAtomIvars.size()*sizeof(NativeUndefinedAtomIvarsV1));
     }
-              
+    
+     if ( !_sharedLibraryAtomIvars.empty() ) {
+      assert( out.tell() == findChunk(NCS_SharedLibraryAtomsV1).fileOffset );
+      out.write((char*)&_sharedLibraryAtomIvars[0], 
+              _sharedLibraryAtomIvars.size() 
+              * sizeof(NativeSharedLibraryAtomIvarsV1));
+    }
+     
+    if ( !_absoluteAtomIvars.empty() ) {
+      assert( out.tell() == findChunk(NCS_AbsoluteAtomsV1).fileOffset );
+      out.write((char*)&_absoluteAtomIvars[0], 
+              _absoluteAtomIvars.size() 
+              * sizeof(NativeAbsoluteAtomIvarsV1));
+    }
+                       
     if (!_stringPool.empty()) {
       assert( out.tell() == findChunk(NCS_Strings).fileOffset );
       out.write(&_stringPool[0], _stringPool.size());
@@ -110,23 +124,55 @@
     _undefinedAtomIndex[&atom] = _undefinedAtomIvars.size();
     NativeUndefinedAtomIvarsV1 ivar;
     ivar.nameOffset = getNameOffset(atom);
-    ivar.flags = (atom.weakImport() ? 1 : 0);
+    ivar.flags = (atom.canBeNull() & 0x03);
     _undefinedAtomIvars.push_back(ivar);
   }
   
   // visitor routine called by forEachAtom() 
+  virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
+    _sharedLibraryAtomIndex[&atom] = _sharedLibraryAtomIvars.size();
+    NativeSharedLibraryAtomIvarsV1 ivar;
+    ivar.nameOffset = getNameOffset(atom);
+    ivar.loadNameOffset = getSharedLibraryNameOffset(atom.loadName());
+    ivar.flags = atom.canBeNullAtRuntime();
+    _sharedLibraryAtomIvars.push_back(ivar);
+  }
+   
+  // visitor routine called by forEachAtom() 
+  virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
+    _absoluteAtomIndex[&atom] = _absoluteAtomIvars.size();
+    NativeAbsoluteAtomIvarsV1 ivar;
+    ivar.nameOffset = getNameOffset(atom);
+    ivar.reserved = 0;
+    ivar.value = atom.value();
+    _absoluteAtomIvars.push_back(ivar);
+  }
+
+  // visitor routine called by forEachAtom() 
   virtual void doFile(const File &) {
   }
 
   // fill out native file header and chunk directory
   void makeHeader() {
+    const bool hasDefines = !_definedAtomIvars.empty();
     const bool hasUndefines = !_undefinedAtomIvars.empty();
+    const bool hasSharedLibraries = !_sharedLibraryAtomIvars.empty();
+    const bool hasAbsolutes = !_absoluteAtomIvars.empty();
+    const bool hasReferences = !_references.empty();
     const bool hasTargetsTable = !_targetsTableIndex.empty();
     const bool hasAddendTable = !_addendsTableIndex.empty();
-    int chunkCount = 5;
+    const bool hasContent = !_contentPool.empty();
+
+    int chunkCount = 1; // always have string pool chunk
+    if ( hasDefines ) chunkCount += 2;
     if ( hasUndefines ) ++chunkCount;
+    if ( hasSharedLibraries ) ++chunkCount;
+    if ( hasAbsolutes ) ++chunkCount;
+    if ( hasReferences ) ++chunkCount;
     if ( hasTargetsTable ) ++chunkCount;
     if ( hasAddendTable ) ++chunkCount;
+    if ( hasContent ) ++chunkCount;
+
     _headerBufferSize = sizeof(NativeFileHeader) 
                          + chunkCount*sizeof(NativeChunk);
     _headerBuffer = reinterpret_cast<NativeFileHeader*>
@@ -140,23 +186,25 @@
     _headerBuffer->fileSize = 0;
     _headerBuffer->chunkCount = chunkCount;
     
-    
-    // create chunk for atom ivar array
+    // create chunk for defined atom ivar array
     int nextIndex = 0;
-    NativeChunk& chd = chunks[nextIndex++];
-    chd.signature = NCS_DefinedAtomsV1;
-    chd.fileOffset = _headerBufferSize;
-    chd.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1);
-    chd.elementCount = _definedAtomIvars.size();
-    uint32_t nextFileOffset = chd.fileOffset + chd.fileSize;
-
-    // create chunk for attributes 
-    NativeChunk& cha = chunks[nextIndex++];
-    cha.signature = NCS_AttributesArrayV1;
-    cha.fileOffset = nextFileOffset;
-    cha.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1);
-    cha.elementCount = _attributes.size();
-    nextFileOffset = cha.fileOffset + cha.fileSize;
+    uint32_t nextFileOffset = _headerBufferSize;
+    if ( hasDefines ) {
+      NativeChunk& chd = chunks[nextIndex++];
+      chd.signature = NCS_DefinedAtomsV1;
+      chd.fileOffset = nextFileOffset;
+      chd.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1);
+      chd.elementCount = _definedAtomIvars.size();
+      nextFileOffset = chd.fileOffset + chd.fileSize;
+
+      // create chunk for attributes 
+      NativeChunk& cha = chunks[nextIndex++];
+      cha.signature = NCS_AttributesArrayV1;
+      cha.fileOffset = nextFileOffset;
+      cha.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1);
+      cha.elementCount = _attributes.size();
+      nextFileOffset = cha.fileOffset + cha.fileSize;
+    }
     
     // create chunk for undefined atom array
     if ( hasUndefines ) {
@@ -169,6 +217,28 @@
       nextFileOffset = chu.fileOffset + chu.fileSize;
     }
     
+    // create chunk for shared library atom array
+    if ( hasSharedLibraries ) {
+      NativeChunk& chsl = chunks[nextIndex++];
+      chsl.signature = NCS_SharedLibraryAtomsV1;
+      chsl.fileOffset = nextFileOffset;
+      chsl.fileSize = _sharedLibraryAtomIvars.size() * 
+                                        sizeof(NativeSharedLibraryAtomIvarsV1);
+      chsl.elementCount = _sharedLibraryAtomIvars.size();
+      nextFileOffset = chsl.fileOffset + chsl.fileSize;
+    }
+   
+     // create chunk for shared library atom array
+    if ( hasAbsolutes ) {
+      NativeChunk& chsl = chunks[nextIndex++];
+      chsl.signature = NCS_AbsoluteAtomsV1;
+      chsl.fileOffset = nextFileOffset;
+      chsl.fileSize = _absoluteAtomIvars.size() * 
+                                        sizeof(NativeAbsoluteAtomIvarsV1);
+      chsl.elementCount = _absoluteAtomIvars.size();
+      nextFileOffset = chsl.fileOffset + chsl.fileSize;
+    }
+   
     // create chunk for symbol strings
     // pad end of string pool to 4-bytes 
     while ( (_stringPool.size() % 4) != 0 )
@@ -181,13 +251,15 @@
     nextFileOffset = chs.fileOffset + chs.fileSize;
     
     // create chunk for references 
-    NativeChunk& chr = chunks[nextIndex++];
-    chr.signature = NCS_ReferencesArrayV1;
-    chr.fileOffset = nextFileOffset;
-    chr.fileSize = _references.size() * sizeof(NativeReferenceIvarsV1);
-    chr.elementCount = _references.size();
-    nextFileOffset = chr.fileOffset + chr.fileSize;
-
+    if ( hasReferences ) {
+      NativeChunk& chr = chunks[nextIndex++];
+      chr.signature = NCS_ReferencesArrayV1;
+      chr.fileOffset = nextFileOffset;
+      chr.fileSize = _references.size() * sizeof(NativeReferenceIvarsV1);
+      chr.elementCount = _references.size();
+      nextFileOffset = chr.fileOffset + chr.fileSize;
+    }
+    
     // create chunk for target table 
     if ( hasTargetsTable ) {
       NativeChunk& cht = chunks[nextIndex++];
@@ -209,13 +281,15 @@
     }
     
     // create chunk for content 
-    NativeChunk& chc = chunks[nextIndex++];
-    chc.signature = NCS_Content;
-    chc.fileOffset = nextFileOffset;
-    chc.fileSize = _contentPool.size();
-    chc.elementCount = _contentPool.size();
-    nextFileOffset = chc.fileOffset + chc.fileSize;
-
+    if ( hasContent ) {
+      NativeChunk& chc = chunks[nextIndex++];
+      chc.signature = NCS_Content;
+      chc.fileOffset = nextFileOffset;
+      chc.fileSize = _contentPool.size();
+      chc.elementCount = _contentPool.size();
+      nextFileOffset = chc.fileOffset + chc.fileSize;
+    }
+    
     _headerBuffer->fileSize = nextFileOffset;
   }
 
@@ -237,7 +311,23 @@
     return this->getNameOffset(atom.name());
   }
   
- // append atom name to string pool and return offset
+  // check if name is already in pool or append and return offset
+  uint32_t getSharedLibraryNameOffset(llvm::StringRef name) {
+    assert( ! name.empty() );
+    // look to see if this library name was used by another atom
+    for(NameToOffsetVector::iterator it = _sharedLibraryNames.begin(); 
+                                    it != _sharedLibraryNames.end(); ++it) {
+      if ( name.equals(it->first) )
+        return it->second;
+    }
+    // first use of this library name
+    uint32_t result = this->getNameOffset(name);
+    _sharedLibraryNames.push_back(
+                    std::make_pair<llvm::StringRef, uint32_t>(name, result));
+    return result;
+  }
+  
+  // append atom name to string pool and return offset
   uint32_t getNameOffset(llvm::StringRef name) {
     if ( name.empty() )
       return 0;
@@ -356,8 +446,26 @@
       }
       else {
         pos = _undefinedAtomIndex.find(atom);
-        assert(pos != _undefinedAtomIndex.end());
-        atomIndex = pos->second + _definedAtomIvars.size();
+        if ( pos != _undefinedAtomIndex.end() ) {
+          atomIndex = pos->second + _definedAtomIvars.size();
+        }
+        else {
+          pos = _sharedLibraryAtomIndex.find(atom);
+          if ( pos != _sharedLibraryAtomIndex.end() ) {
+            assert(pos != _sharedLibraryAtomIndex.end());
+            atomIndex = pos->second 
+                      + _definedAtomIvars.size() 
+                      + _undefinedAtomIndex.size();
+          }
+          else {
+            pos = _absoluteAtomIndex.find(atom);
+            assert(pos != _absoluteAtomIndex.end());
+            atomIndex = pos->second 
+                      + _definedAtomIvars.size() 
+                      + _undefinedAtomIndex.size()
+                      + _sharedLibraryAtomIndex.size();
+         }
+        }
       }
       targetIndexes[targetIndex] = atomIndex;
     }
@@ -405,12 +513,17 @@
   std::vector<NativeDefinedAtomIvarsV1>   _definedAtomIvars;
   std::vector<NativeAtomAttributesV1>     _attributes;
   std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
+  std::vector<NativeSharedLibraryAtomIvarsV1> _sharedLibraryAtomIvars;
+  std::vector<NativeAbsoluteAtomIvarsV1>  _absoluteAtomIvars;
   std::vector<NativeReferenceIvarsV1>     _references;
   TargetToIndex                           _targetsTableIndex;
   TargetToIndex                           _definedAtomIndex;
   TargetToIndex                           _undefinedAtomIndex;
+  TargetToIndex                           _sharedLibraryAtomIndex;
+  TargetToIndex                           _absoluteAtomIndex;
   AddendToIndex                           _addendsTableIndex;
   NameToOffsetVector                      _sectionNames;
+  NameToOffsetVector                      _sharedLibraryNames;
 };
 
 

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Wed Feb 22 15:56:59 2012
@@ -134,6 +134,24 @@
   }
 }
 
+void Resolver::doSharedLibraryAtom(const SharedLibraryAtom& atom) {
+  // add to list of known atoms
+  _atoms.push_back(&atom);
+  
+  // tell symbol table
+  _symbolTable.add(atom);
+}
+  
+void Resolver::doAbsoluteAtom(const AbsoluteAtom& atom) {
+  // add to list of known atoms
+  _atoms.push_back(&atom);
+  
+  // tell symbol table
+  _symbolTable.add(atom);
+}
+
+
+  
 // utility to add a vector of atoms
 void Resolver::addAtoms(const std::vector<const DefinedAtom*>& newAtoms) {
   for (std::vector<const DefinedAtom *>::const_iterator it = newAtoms.begin();

Modified: lld/trunk/lib/Core/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/lib/Core/SymbolTable.cpp (original)
+++ lld/trunk/lib/Core/SymbolTable.cpp Wed Feb 22 15:56:59 2012
@@ -11,10 +11,11 @@
 #include "lld/Core/Atom.h"
 #include "lld/Core/DefinedAtom.h"
 #include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/SharedLibraryAtom.h"
+#include "lld/Core/AbsoluteAtom.h"
 #include "lld/Core/File.h"
 #include "lld/Core/InputFiles.h"
 #include "lld/Core/Resolver.h"
-#include "lld/Core/UndefinedAtom.h"
 #include "lld/Platform/Platform.h"
 
 #include "llvm/Support/ErrorHandling.h"
@@ -36,6 +37,14 @@
   this->addByName(atom);
 }
 
+void SymbolTable::add(const SharedLibraryAtom &atom) {
+  this->addByName(atom);
+}
+  
+void SymbolTable::add(const AbsoluteAtom &atom) {
+  this->addByName(atom);
+}
+
 void SymbolTable::add(const DefinedAtom &atom) {
   assert(atom.scope() != DefinedAtom::scopeTranslationUnit);
   if ( !atom.name().empty() ) {
@@ -49,7 +58,9 @@
 enum NameCollisionResolution {
   NCR_First,
   NCR_Second,
-  NCR_Dup,
+  NCR_DupDef,
+  NCR_DupUndef,
+  NCR_DupShLib,
   NCR_Error
 };
 
@@ -57,7 +68,7 @@
   //regular     absolute    undef      sharedLib
   {
     // first is regular
-    NCR_Dup,   NCR_Error,   NCR_First, NCR_First
+    NCR_DupDef, NCR_Error,   NCR_First, NCR_First
   },
   {
     // first is absolute
@@ -65,11 +76,11 @@
   },
   {
     // first is undef
-    NCR_Second, NCR_Second, NCR_First, NCR_Second
+    NCR_Second, NCR_Second, NCR_DupUndef, NCR_Second
   },
   {
     // first is sharedLib
-    NCR_Second, NCR_Second, NCR_First, NCR_First
+    NCR_Second, NCR_Second, NCR_First, NCR_DupShLib
   }
 };
 
@@ -129,7 +140,7 @@
       case NCR_Second:
         useNew = true;
         break;
-      case NCR_Dup:
+      case NCR_DupDef:
         assert(existing->definition() == Atom::definitionRegular);
         assert(newAtom.definition() == Atom::definitionRegular);
         switch ( mergeSelect(((DefinedAtom*)existing)->merge(), 
@@ -148,6 +159,39 @@
             break;
         }
         break;
+      case NCR_DupUndef: {
+          const UndefinedAtom* existingUndef = existing->undefinedAtom();
+          const UndefinedAtom* newUndef = newAtom.undefinedAtom();
+          assert(existingUndef != NULL);
+          assert(newUndef != NULL);
+          if ( existingUndef->canBeNull() == newUndef->canBeNull() ) {
+            useNew = false;
+          }
+          else {
+            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 = existing->sharedLibraryAtom();
+          const SharedLibraryAtom* newShLib = newAtom.sharedLibraryAtom();
+          assert(existingShLib != NULL);
+          assert(newShLib != NULL);
+          if ( (existingShLib->canBeNullAtRuntime() 
+                  == newShLib->canBeNullAtRuntime()) &&
+               existingShLib->loadName().equals(newShLib->loadName()) ) {
+            useNew = false;
+          }
+          else {
+            useNew = false; // use existing shared library by default
+            // give platform a change to override which to use
+            _platform.sharedLibrarylMismatch(*existingShLib, *newShLib, useNew);
+          }
+        }
+        break;
       default:
         llvm::report_fatal_error("SymbolTable::addByName(): unhandled switch clause");
     }

Modified: lld/trunk/lib/Core/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)
+++ lld/trunk/lib/Core/YamlKeyValues.cpp Wed Feb 22 15:56:59 2012
@@ -30,10 +30,12 @@
 const char* const KeyValues::isAliasKeyword         = "is-alias";
 const char* const KeyValues::sectionNameKeyword     = "section-name";
 const char* const KeyValues::contentKeyword         = "content";
+const char* const KeyValues::loadNameKeyword        = "load-name";
 const char* const KeyValues::sizeKeyword            = "size";
+const char* const KeyValues::valueKeyword           = "value";
 const char* const KeyValues::fixupsKeyword          = "fixups";
 const char* const KeyValues::permissionsKeyword     = "permissions";
-const char* const KeyValues::weakImportKeyword      = "weak-import";
+const char* const KeyValues::canBeNullKeyword       = "can-be-null";
 const char* const KeyValues::fixupsKindKeyword      = "kind";
 const char* const KeyValues::fixupsOffsetKeyword    = "offset";
 const char* const KeyValues::fixupsTargetKeyword    = "target";
@@ -51,7 +53,7 @@
 const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAtom::permR__;
 const bool                            KeyValues::isThumbDefault = false;
 const bool                            KeyValues::isAliasDefault = false;
-const bool                            KeyValues::weakImportDefault = false;
+const UndefinedAtom::CanBeNull        KeyValues::canBeNullDefault = UndefinedAtom::canBeNullNever;
 
 
 
@@ -389,17 +391,34 @@
 
 
 
-bool KeyValues::weakImport(const char* s)
+struct CanBeNullMapping {
+  const char*               string;
+  UndefinedAtom::CanBeNull  value;
+};
+
+static const CanBeNullMapping cbnMappings[] = {
+  { "never",         UndefinedAtom::canBeNullNever },
+  { "at-runtime",    UndefinedAtom::canBeNullAtRuntime },
+  { "at-buildtime",  UndefinedAtom::canBeNullAtBuildtime },
+  { NULL,            UndefinedAtom::canBeNullNever }
+};
+
+
+UndefinedAtom::CanBeNull KeyValues::canBeNull(const char* s)
 {
-  if ( strcmp(s, "true") == 0 )
-    return true;
-  else if ( strcmp(s, "false") == 0 )
-    return false;
-  llvm::report_fatal_error("bad weak-import value");
+  for (const CanBeNullMapping* p = cbnMappings; p->string != NULL; ++p) {
+    if ( strcmp(p->string, s) == 0 )
+      return p->value;
+  }
+  llvm::report_fatal_error("bad can-be-null value");
 }
 
-const char* KeyValues::weakImport(bool b) {
-  return b ? "true" : "false";
+const char* KeyValues::canBeNull(UndefinedAtom::CanBeNull c) {
+  for (const CanBeNullMapping* p = cbnMappings; p->string != NULL; ++p) {
+    if ( p->value == c )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad can-be-null value");
 }
 
 

Modified: lld/trunk/lib/Core/YamlKeyValues.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.h?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.h (original)
+++ lld/trunk/lib/Core/YamlKeyValues.h Wed Feb 22 15:56:59 2012
@@ -12,6 +12,7 @@
 
 #include "lld/Core/Atom.h"
 #include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
 
 
 namespace lld {
@@ -24,6 +25,8 @@
   static const char* const                sectionNameKeyword;
   static const char* const                contentKeyword;
   static const char* const                sizeKeyword;
+  static const char* const                loadNameKeyword;
+  static const char* const                valueKeyword;
   static const char* const                fixupsKeyword;
  
   static const char* const                definitionKeyword;
@@ -76,10 +79,10 @@
   static bool                             isAlias(const char*);
   static const char*                      isAlias(bool);
 
-  static const char* const                weakImportKeyword;
-  static const bool                       weakImportDefault;
-  static bool                             weakImport(const char*);
-  static const char*                      weakImport(bool);
+  static const char* const                canBeNullKeyword;
+  static const UndefinedAtom::CanBeNull   canBeNullDefault;
+  static UndefinedAtom::CanBeNull         canBeNull(const char*);
+  static const char*                      canBeNull(UndefinedAtom::CanBeNull);
 
 
   static const char* const                fixupsKindKeyword;

Modified: lld/trunk/lib/Core/YamlReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlReader.cpp (original)
+++ lld/trunk/lib/Core/YamlReader.cpp Wed Feb 22 15:56:59 2012
@@ -13,6 +13,9 @@
 
 #include "lld/Core/YamlReader.h"
 #include "lld/Core/Atom.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/SharedLibraryAtom.h"
+#include "lld/Core/AbsoluteAtom.h"
 #include "lld/Core/Error.h"
 #include "lld/Core/File.h"
 #include "lld/Core/Reference.h"
@@ -200,9 +203,7 @@
       }
       break;
     case inValue:
-      if (isalnum(c) || (c == '-') || (c == '_')) {
-        *p++ = c;
-      } else if (c == '\n') {
+      if (c == '\n') {
         *p = '\0';
         entries.push_back(new Entry(key, value, NULL, depth,
                                     nextKeyIsStartOfDocument,
@@ -212,6 +213,9 @@
         state = inDocument;
         depth = 0;
       }
+      else {
+        *p++ = c;
+      } 
       break;
     case inValueSequence:
       if (c == ']') {
@@ -300,6 +304,8 @@
   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);
   
   struct NameAtomPair {
@@ -310,6 +316,8 @@
 
   std::vector<YAMLDefinedAtom*>   _definedAtoms;
   std::vector<UndefinedAtom*>     _undefinedAtoms;
+  std::vector<SharedLibraryAtom*> _sharedLibraryAtoms;
+  std::vector<AbsoluteAtom*>      _absoluteAtoms;
   std::vector<YAMLReference>      _references;
   std::vector<NameAtomPair>       _nameToAtomMapping;
   unsigned int                    _lastRefIndex;
@@ -465,8 +473,38 @@
 
 class YAMLUndefinedAtom : public UndefinedAtom {
 public:
-        YAMLUndefinedAtom(YAMLFile& f, int32_t ord, const char* nm, bool wi)
-            : _file(f), _name(nm), _ordinal(ord), _weakImport(wi) { }
+        YAMLUndefinedAtom(YAMLFile& f, int32_t ord, const char* nm, 
+                          UndefinedAtom::CanBeNull cbn)
+            : _file(f), _name(nm), _ordinal(ord), _canBeNull(cbn) { }
+
+  virtual const class File& file() const {
+    return _file;
+  }
+
+  virtual llvm::StringRef name() const {
+    return _name;
+  }
+
+  virtual CanBeNull canBeNull() const {
+    return _canBeNull;
+  }
+  
+ 
+private:
+  YAMLFile&                   _file;
+  const char *                _name;
+  uint32_t                    _ordinal;
+  UndefinedAtom::CanBeNull     _canBeNull;
+};
+
+
+
+class YAMLSharedLibraryAtom : public SharedLibraryAtom {
+public:
+        YAMLSharedLibraryAtom(YAMLFile& f, int32_t ord, const char* nm, 
+                                const char* ldnm, bool cbn)
+            : _file(f), _name(nm), _ordinal(ord), 
+              _loadName(ldnm), _canBeNull(cbn) { }
 
   virtual const class File& file() const {
     return _file;
@@ -476,18 +514,52 @@
     return _name;
   }
 
-  virtual bool weakImport() const {
-    return _weakImport;
+  virtual llvm::StringRef loadName() const {
+    return _loadName;
+  }
+
+  virtual bool canBeNullAtRuntime() const {
+    return _canBeNull;
   }
   
+ 
 private:
   YAMLFile&                   _file;
   const char *                _name;
   uint32_t                    _ordinal;
-  bool                        _weakImport;
+  const char *                _loadName;
+  bool                        _canBeNull;
 };
 
 
+
+class YAMLAbsoluteAtom : public AbsoluteAtom {
+public:
+        YAMLAbsoluteAtom(YAMLFile& f, int32_t ord, const char* nm, uint64_t v)
+            : _file(f), _name(nm), _ordinal(ord), _value(v) { }
+
+  virtual const class File& file() const {
+    return _file;
+  }
+
+  virtual llvm::StringRef name() const {
+    return _name;
+  }
+
+  virtual uint64_t value() const {
+    return _value;
+  }
+
+private:
+  YAMLFile&        _file;
+  const char *     _name;
+  uint32_t         _ordinal;
+  uint64_t         _value;
+};
+
+
+
+
 bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
   handler.doFile(*this);
   for (std::vector<YAMLDefinedAtom *>::const_iterator it = _definedAtoms.begin();
@@ -498,6 +570,17 @@
        it != _undefinedAtoms.end(); ++it) {
     handler.doUndefinedAtom(**it);
   }
+  for (std::vector<SharedLibraryAtom *>::const_iterator 
+        it = _sharedLibraryAtoms.begin();
+        it != _sharedLibraryAtoms.end(); ++it) {
+    handler.doSharedLibraryAtom(**it);
+  }
+  for (std::vector<AbsoluteAtom *>::const_iterator 
+        it = _absoluteAtoms.begin();
+        it != _absoluteAtoms.end(); ++it) {
+    handler.doAbsoluteAtom(**it);
+  }
+  
   return true;
 }
 
@@ -534,6 +617,16 @@
   _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
 }
 
+void YAMLFile::addSharedLibraryAtom(SharedLibraryAtom* atom) {
+  _sharedLibraryAtoms.push_back(atom);
+  _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
+}
+
+void YAMLFile::addAbsoluteAtom(AbsoluteAtom* atom) {
+  _absoluteAtoms.push_back(atom);
+  _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
+}
+
 
 class YAMLAtomState {
 public:
@@ -544,9 +637,7 @@
   void setAlign2(const char *n);
 
   void setFixupKind(const char *n);
-  void setFixupOffset(const char *n);
   void setFixupTarget(const char *n);
-  void setFixupAddend(const char *n);
   void addFixup(YAMLFile *f);
 
   void makeAtom(YAMLFile&);
@@ -554,7 +645,9 @@
   const char *                _name;
   const char *                _refName;
   const char *                _sectionName;
+  const char*                 _loadName;
   unsigned long long          _size;
+  uint64_t                    _value;
   uint32_t                    _ordinal;
   std::vector<uint8_t>*       _content;
   DefinedAtom::Alignment      _alignment;
@@ -568,7 +661,7 @@
   DefinedAtom::ContentPermissions _permissions;
   bool                        _isThumb;
   bool                        _isAlias;
-  bool                        _weakImport;
+  UndefinedAtom::CanBeNull    _canBeNull;
   YAMLReference               _ref;
 };
 
@@ -577,7 +670,9 @@
   : _name(NULL)
   , _refName(NULL)
   , _sectionName(NULL)
+  , _loadName(NULL)
   , _size(0)
+  , _value(0)
   , _ordinal(0)
   , _content(NULL) 
   , _alignment(0, 0)
@@ -591,7 +686,7 @@
   , _permissions(KeyValues::permissionsDefault)
   , _isThumb(KeyValues::isThumbDefault)
   , _isAlias(KeyValues::isAliasDefault) 
-  , _weakImport(false)
+  , _canBeNull(KeyValues::canBeNullDefault)
   {
   }
 
@@ -606,16 +701,30 @@
     ++_ordinal;
   }
   else if ( _definition == Atom::definitionUndefined ) {
-    UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _weakImport);
+    UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _canBeNull);
     f.addUndefinedAtom(a);
     ++_ordinal;
   }
-  
+  else if ( _definition == Atom::definitionSharedLibrary ) {
+    bool nullable = (_canBeNull == UndefinedAtom::canBeNullAtRuntime);
+    SharedLibraryAtom *a = new YAMLSharedLibraryAtom(f, _ordinal, _name, 
+                                                      _loadName, nullable);
+    f.addSharedLibraryAtom(a);
+    ++_ordinal;
+  }
+   else if ( _definition == Atom::definitionAbsolute ) {
+    AbsoluteAtom *a = new YAMLAbsoluteAtom(f, _ordinal, _name, _value);
+    f.addAbsoluteAtom(a);
+    ++_ordinal;
+  }
+ 
   // reset state for next atom
   _name             = NULL;
   _refName          = NULL;
   _sectionName      = NULL;
+  _loadName         = NULL;
   _size             = 0;
+  _value            = 0;
   _ordinal          = 0;
   _content          = NULL;
   _alignment.powerOf2= 0;
@@ -630,7 +739,7 @@
   _permissions      = KeyValues::permissionsDefault;
   _isThumb          = KeyValues::isThumbDefault;
   _isAlias          = KeyValues::isAliasDefault;
-  _weakImport       = KeyValues::weakImportDefault;
+  _canBeNull        = KeyValues::canBeNullDefault;
   _ref._target       = NULL;
   _ref._targetName   = NULL;
   _ref._addend       = 0;
@@ -666,24 +775,10 @@
   }
 }
 
-void YAMLAtomState::setFixupOffset(const char *s) {
-  if ((s[0] == '0') && (s[1] == 'x'))
-    llvm::StringRef(s).getAsInteger(16, _ref._offsetInAtom);
-  else
-    llvm::StringRef(s).getAsInteger(10, _ref._offsetInAtom);
-}
-
 void YAMLAtomState::setFixupTarget(const char *s) {
   _ref._targetName = s;
 }
 
-void YAMLAtomState::setFixupAddend(const char *s) {
-  if ((s[0] == '0') && (s[1] == 'x'))
-    llvm::StringRef(s).getAsInteger(16, _ref._addend);
-  else
-    llvm::StringRef(s).getAsInteger(10, _ref._addend);
-}
-
 
 void YAMLAtomState::addFixup(YAMLFile *f) {
   f->_references.push_back(_ref);
@@ -805,8 +900,12 @@
           atomState._isAlias = KeyValues::isAlias(entry->value);
           haveAtom = true;
         }
-        else if (strcmp(entry->key, KeyValues::weakImportKeyword) == 0) {
-          atomState._weakImport = KeyValues::weakImport(entry->value);
+        else if (strcmp(entry->key, KeyValues::canBeNullKeyword) == 0) {
+          atomState._canBeNull = KeyValues::canBeNull(entry->value);
+          if ( atomState._definition == Atom::definitionSharedLibrary ) {
+            if ( atomState._canBeNull == UndefinedAtom::canBeNullAtBuildtime )
+              return make_error_code(yaml_reader_error::illegal_value);
+          }
           haveAtom = true;
         }
         else if (strcmp(entry->key, KeyValues::sectionNameKeyword) == 0) {
@@ -829,7 +928,14 @@
         } 
         else if (strcmp(entry->key, KeyValues::fixupsKeyword) == 0) {
           inFixups = true;
-          
+        }
+        else if (strcmp(entry->key, KeyValues::loadNameKeyword) == 0) {
+          atomState._loadName = entry->value;
+          haveAtom = true;
+        }
+        else if (strcmp(entry->key, KeyValues::valueKeyword) == 0) {
+          llvm::StringRef(entry->value).getAsInteger(0, atomState._value);
+          haveAtom = true;
         }
         else {
           return make_error_code(yaml_reader_error::unknown_keyword);
@@ -847,7 +953,8 @@
           haveFixup = true;
         } 
         else if (strcmp(entry->key, KeyValues::fixupsOffsetKeyword) == 0) {
-          atomState.setFixupOffset(entry->value);
+          llvm::StringRef(entry->value).getAsInteger(0, 
+                                              atomState._ref._offsetInAtom);
           haveFixup = true;
         } 
         else if (strcmp(entry->key, KeyValues::fixupsTargetKeyword) == 0) {
@@ -855,7 +962,8 @@
           haveFixup = true;
         }
         else if (strcmp(entry->key, KeyValues::fixupsAddendKeyword) == 0) {
-          atomState.setFixupAddend(entry->value);
+          llvm::StringRef(entry->value).getAsInteger(0, 
+                                              atomState._ref._addend);
           haveFixup = true;
         }
       }
@@ -865,9 +973,10 @@
   if (haveAtom) {
     atomState.makeAtom(*file);
   }
-
-  file->bindTargetReferences();
-  result.push_back(file);
+  if ( file != NULL ) { 
+    file->bindTargetReferences();
+    result.push_back(file);
+  }
   return make_error_code(yaml_reader_error::success);
 }
 

Modified: lld/trunk/lib/Core/YamlWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlWriter.cpp?rev=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlWriter.cpp (original)
+++ lld/trunk/lib/Core/YamlWriter.cpp Wed Feb 22 15:56:59 2012
@@ -71,6 +71,14 @@
     buildDuplicateNameMap(atom);
   }
   
+  virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
+    buildDuplicateNameMap(atom);
+  }
+
+  virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
+    buildDuplicateNameMap(atom);
+  }
+                         
   void buildDuplicateNameMap(const Atom& atom) {
     assert(!atom.name().empty());
     NameToAtom::iterator pos = _nameMap.find(atom.name());
@@ -132,10 +140,14 @@
   virtual void doFile(const class File &) { _firstAtom = true; }
   
   virtual void doDefinedAtom(const class DefinedAtom &atom) {
-    // add blank line between atoms for readability
-    if ( !_firstAtom )
+    if ( _firstAtom ) {
+      _out << "atoms:\n";
+      _firstAtom = false;
+    }
+    else {
+      // add blank line between atoms for readability
       _out << "\n";
-    _firstAtom = false;
+    }
     
     bool hasDash = false;
     if ( !atom.name().empty() ) {
@@ -313,35 +325,115 @@
 
 
   virtual void doUndefinedAtom(const class UndefinedAtom &atom) {
-      // add blank line between atoms for readability
-      if ( !_firstAtom )
-        _out << "\n";
+    if ( _firstAtom ) {
+      _out << "atoms:\n";
       _firstAtom = false;
+    }
+    else {
+      // add blank line between atoms for readability
+      _out << "\n";
+    }
         
-      _out  << "    - "
-            << KeyValues::nameKeyword
+    _out  << "    - "
+          << KeyValues::nameKeyword
+          << ":"
+          << spacePadding(KeyValues::nameKeyword)
+          << atom.name() 
+          << "\n";
+
+    _out  << "      " 
+          << KeyValues::definitionKeyword 
+          << ":"
+          << spacePadding(KeyValues::definitionKeyword)
+          << KeyValues::definition(atom.definition()) 
+          << "\n";
+
+    if ( atom.canBeNull() != KeyValues::canBeNullDefault ) {
+      _out  << "      " 
+            << KeyValues::canBeNullKeyword 
             << ":"
-            << spacePadding(KeyValues::nameKeyword)
-            << atom.name() 
+            << spacePadding(KeyValues::canBeNullKeyword)
+            << KeyValues::canBeNull(atom.canBeNull()) 
             << "\n";
+    }
+  }
+
+   virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
+    if ( _firstAtom ) {
+      _out << "atoms:\n";
+      _firstAtom = false;
+    }
+    else {
+      // add blank line between atoms for readability
+      _out << "\n";
+    }
+        
+    _out  << "    - "
+          << KeyValues::nameKeyword
+          << ":"
+          << spacePadding(KeyValues::nameKeyword)
+          << atom.name() 
+          << "\n";
+
+    _out  << "      " 
+          << KeyValues::definitionKeyword 
+          << ":"
+          << spacePadding(KeyValues::definitionKeyword)
+          << KeyValues::definition(atom.definition()) 
+          << "\n";
 
+    if ( !atom.loadName().empty() ) {
       _out  << "      " 
-            << KeyValues::definitionKeyword 
+            << KeyValues::loadNameKeyword 
             << ":"
-            << spacePadding(KeyValues::definitionKeyword)
-            << KeyValues::definition(atom.definition()) 
+            << spacePadding(KeyValues::loadNameKeyword)
+            << atom.loadName()
             << "\n";
+    }
 
-    if ( atom.weakImport() != KeyValues::weakImportDefault ) {
+    if ( atom.canBeNullAtRuntime() ) {
       _out  << "      " 
-            << KeyValues::weakImportKeyword 
+            << KeyValues::canBeNullKeyword 
             << ":"
-            << spacePadding(KeyValues::weakImportKeyword)
-            << KeyValues::weakImport(atom.weakImport()) 
+            << spacePadding(KeyValues::canBeNullKeyword)
+            << KeyValues::canBeNull(UndefinedAtom::canBeNullAtRuntime) 
             << "\n";
     }
-  }
+   }
+   
+   virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
+     if ( _firstAtom ) {
+      _out << "atoms:\n";
+      _firstAtom = false;
+    }
+    else {
+      // add blank line between atoms for readability
+      _out << "\n";
+    }
+        
+    _out  << "    - "
+          << KeyValues::nameKeyword
+          << ":"
+          << spacePadding(KeyValues::nameKeyword)
+          << atom.name() 
+          << "\n";
 
+    _out  << "      " 
+          << KeyValues::definitionKeyword 
+          << ":"
+          << spacePadding(KeyValues::definitionKeyword)
+          << KeyValues::definition(atom.definition()) 
+          << "\n";
+    
+    _out  << "      " 
+          << KeyValues::valueKeyword 
+          << ":"
+          << spacePadding(KeyValues::valueKeyword)
+          << "0x";
+     _out.write_hex(atom.value());
+     _out << "\n";
+   }
+                     
 
 private:
   // return a string of the correct number of spaces to align value
@@ -380,7 +472,6 @@
   // Write out all atoms
   AtomWriter h(rnb, out);
   out << "---\n";
-  out << "atoms:\n";
   file.forEachAtom(h);
   out << "...\n";
 }

Added: lld/trunk/test/absolute-basic.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/absolute-basic.objtxt?rev=151204&view=auto
==============================================================================
--- lld/trunk/test/absolute-basic.objtxt (added)
+++ lld/trunk/test/absolute-basic.objtxt Wed Feb 22 15:56:59 2012
@@ -0,0 +1,25 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test that absolute symbols are parsed and preserved
+#
+
+---
+atoms:
+    - name:              putchar
+      definition:        absolute
+      value:             0xFFFF0040
+      
+    - name:              reset
+      definition:        absolute
+      value:             0xFFFF0080
+
+...
+
+# CHECK:       name:         putchar
+# CHECK:       definition:   absolute
+# CHECK:       value:        0xffff0040
+# CHECK:       name:         reset
+# CHECK:       definition:   absolute
+# CHECK:       value:        0xffff0080
+# CHECK:       ...

Added: lld/trunk/test/empty.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/empty.objtxt?rev=151204&view=auto
==============================================================================
--- lld/trunk/test/empty.objtxt (added)
+++ lld/trunk/test/empty.objtxt Wed Feb 22 15:56:59 2012
@@ -0,0 +1,11 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test that an empty file is handled properly
+#
+
+---
+...
+
+# CHECK:       ---
+# CHECK:       ...

Added: lld/trunk/test/shared-library-basic.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/shared-library-basic.objtxt?rev=151204&view=auto
==============================================================================
--- lld/trunk/test/shared-library-basic.objtxt (added)
+++ lld/trunk/test/shared-library-basic.objtxt Wed Feb 22 15:56:59 2012
@@ -0,0 +1,34 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test that shared-library symbols are parsed and preserved
+#
+
+---
+atoms:
+    - name:              malloc
+      definition:        shared-library
+      load-name:         libc.so
+      
+    - name:              free
+      definition:        shared-library
+      load-name:         libc.so
+
+    - name:              fast_malloc
+      definition:        shared-library
+      load-name:         libc.so
+      can-be-null:       at-runtime
+      
+...
+
+# CHECK:       name:         malloc
+# CHECK:       definition:   shared-library
+# CHECK:       load-name:    libc.so
+# CHECK:       name:         free
+# CHECK:       definition:   shared-library
+# CHECK:       load-name:    libc.so
+# CHECK:       name:         fast_malloc
+# CHECK:       definition:   shared-library
+# CHECK:       load-name:    libc.so
+# CHECK:       can-be-null:  at-runtime
+# CHECK:       ...

Added: lld/trunk/test/shared-library-coalesce.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/shared-library-coalesce.objtxt?rev=151204&view=auto
==============================================================================
--- lld/trunk/test/shared-library-coalesce.objtxt (added)
+++ lld/trunk/test/shared-library-coalesce.objtxt Wed Feb 22 15:56:59 2012
@@ -0,0 +1,110 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test that shared library symbols preserve their attributes and merge properly
+#
+
+---
+atoms:
+    - name:              foo1
+      definition:        shared-library
+      load-name:         libc.so
+      
+    - name:              foo2
+      definition:        shared-library
+      load-name:         libc.so
+
+    - name:              bar1
+      definition:        shared-library
+      load-name:         libc.so
+      can-be-null:       at-runtime
+      
+    - name:              bar2
+      definition:        shared-library
+      load-name:         libc.so
+      can-be-null:       at-runtime
+
+    - name:              mismatchNull1
+      definition:        shared-library
+      load-name:         libc.so
+      can-be-null:       at-runtime
+      
+    - name:              mismatchNull2
+      definition:        shared-library
+      load-name:         libc.so
+  
+    - name:              mismatchload1
+      definition:        shared-library
+      load-name:         liba.so
+      
+    - name:              mismatchload2
+      definition:        shared-library
+      load-name:         libb.so
+
+---
+atoms:
+    - name:              foo2
+      definition:        shared-library
+      load-name:         libc.so
+      
+    - name:              foo3
+      definition:        shared-library
+      load-name:         libc.so
+
+    - name:              bar2
+      definition:        shared-library
+      load-name:         libc.so
+      can-be-null:       at-runtime
+
+    - name:              bar3
+      definition:        shared-library
+      load-name:         libc.so
+      can-be-null:       at-runtime
+
+    - name:              mismatchNull1
+      definition:        shared-library
+      load-name:         libc.so
+      
+    - name:              mismatchNull2
+      definition:        shared-library
+      load-name:         libc.so
+      can-be-null:       at-runtime
+  
+    - name:              mismatchload1
+      definition:        shared-library
+      load-name:         libb.so
+      
+    - name:              mismatchload2
+      definition:        shared-library
+      load-name:         liba.so
+
+...
+
+# CHECK:       name:       foo1
+# CHECK:     definition:   shared-library
+# CHECK:       name:       foo2
+# CHECK:     definition:   shared-library
+# CHECK:       name:       bar1
+# CHECK:     definition:   shared-library
+# CHECK:     can-be-null:  at-runtime
+# CHECK:       name:       bar2
+# CHECK:     definition:   shared-library
+# CHECK:     can-be-null:  at-runtime
+# CHECK:       name:       mismatchNull1
+# CHECK:     definition:   shared-library
+# CHECK:     can-be-null:  at-runtime
+# CHECK:       name:       mismatchNull2
+# CHECK:     definition:   shared-library
+# CHECK-NOT: can-be-null:  at-runtime
+# CHECK:       name:       mismatchload1
+# CHECK:     definition:   shared-library
+# CHECK:     load-name:    liba.so
+# CHECK:       name:       mismatchload2
+# CHECK:     definition:   shared-library
+# CHECK:     load-name:    libb.so
+# CHECK:       name:       foo3
+# CHECK:     definition:   shared-library
+# CHECK:       name:       bar3
+# CHECK:     definition:   shared-library
+# CHECK:     can-be-null:  at-runtime
+# CHECK:       ...

Added: lld/trunk/test/undef-weak-coalesce.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/undef-weak-coalesce.objtxt?rev=151204&view=auto
==============================================================================
--- lld/trunk/test/undef-weak-coalesce.objtxt (added)
+++ lld/trunk/test/undef-weak-coalesce.objtxt Wed Feb 22 15:56:59 2012
@@ -0,0 +1,117 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test that undefined symbols preserve their attributes and merge properly
+#
+
+---
+atoms:
+    - name:              regular_func
+      definition:        undefined
+      can-be-null:       never
+
+    - name:              weak_import_func
+      definition:        undefined
+      can-be-null:       at-runtime
+      
+    - name:              weak_func
+      definition:        undefined
+      can-be-null:       at-buildtime
+      
+    - name:              bar1
+      definition:        undefined
+      can-be-null:       never
+      
+    - name:              bar2
+      definition:        undefined
+      can-be-null:       at-runtime
+      
+    - name:              bar3
+      definition:        undefined
+      can-be-null:       at-buildtime
+      
+    - name:              bar4
+      definition:        undefined
+      can-be-null:       never
+      
+    - name:              bar5
+      definition:        undefined
+      can-be-null:       at-runtime
+      
+    - name:              bar6
+      definition:        undefined
+      can-be-null:       at-buildtime
+      
+    - name:              bar7
+      definition:        undefined
+      can-be-null:       never
+      
+    - name:              bar8
+      definition:        undefined
+      can-be-null:       at-runtime
+      
+    - name:              bar9
+      definition:        undefined
+      can-be-null:       at-buildtime
+      
+---
+atoms:
+    - name:              bar1
+      definition:        undefined
+      can-be-null:       never
+      
+    - name:              bar2
+      definition:        undefined
+      can-be-null:       at-runtime
+      
+    - name:              bar3
+      definition:        undefined
+      can-be-null:       at-buildtime
+      
+    - name:              bar4
+      definition:        undefined
+      can-be-null:       at-runtime
+      
+    - name:              bar5
+      definition:        undefined
+      can-be-null:       at-buildtime
+      
+    - name:              bar6
+      definition:        undefined
+      can-be-null:       never
+      
+    - name:              bar7
+      definition:        undefined
+      can-be-null:       at-buildtime
+      
+    - name:              bar8
+      definition:        undefined
+      can-be-null:       never
+      
+    - name:              bar9
+      definition:        undefined
+      can-be-null:       at-runtime
+...
+
+# CHECK:       name:       regular_func
+# CHECK:     definition:   undefined
+# CHECK:       name:       weak_import_func
+# CHECK:     definition:   undefined
+# CHECK:     can-be-null:  at-runtime
+# CHECK:       name:       weak_func
+# CHECK:     definition:   undefined
+# CHECK:     can-be-null:  at-buildtime
+# CHECK:       name:       bar1
+# CHECK:       name:       bar2
+# CHECK:     can-be-null:  at-runtime
+# CHECK:       name:       bar3
+# CHECK:     can-be-null:  at-buildtime
+# CHECK:       name:       bar4
+# CHECK:       name:       bar5
+# CHECK:     can-be-null:  at-runtime
+# CHECK:       name:       bar7
+# CHECK:       name:       bar6
+# CHECK:       name:       bar8
+# CHECK:       name:       bar9
+# CHECK:     can-be-null:  at-runtime
+# 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=151204&r1=151203&r2=151204&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Wed Feb 22 15:56:59 2012
@@ -141,6 +141,17 @@
   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) {}
 
@@ -186,6 +197,20 @@
       if ( atom ) 
           handler.doUndefinedAtom(*atom);
     }
+    // visit shared library atoms
+    for (std::vector<const Atom *>::iterator it = _atoms.begin();
+         it != _atoms.end(); ++it) {
+      const SharedLibraryAtom* atom = (*it)->sharedLibraryAtom();
+      if ( atom ) 
+          handler.doSharedLibraryAtom(*atom);
+    }
+    // visit absolute atoms
+    for (std::vector<const Atom *>::iterator it = _atoms.begin();
+         it != _atoms.end(); ++it) {
+      const AbsoluteAtom* atom = (*it)->absoluteAtom();
+      if ( atom ) 
+          handler.doAbsoluteAtom(*atom);
+    }
     return true;
   }
 
@@ -220,7 +245,7 @@
   // write new atom graph out as YAML doc
   std::string errorInfo;
   llvm::raw_fd_ostream out("-", errorInfo);
-  //yaml::writeObjectText(outFile, out);
+//  yaml::writeObjectText(outFile, out);
 
   // make unique temp .o file to put generated object file
   int fd;
@@ -232,6 +257,8 @@
   writeNativeObjectFile(outFile, binaryOut);
   binaryOut.close();  // manually close so that file can be read next
 
+//  out << "native file: " << tempPath.str() << "\n";
+  
   // read native file
   llvm::OwningPtr<lld::File> natFile;
   if ( error(parseNativeObjectFileOrSTDIN(tempPath, natFile)) ) 





More information about the llvm-commits mailing list