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

Nick Kledzik kledzik at apple.com
Tue Feb 14 16:38:09 PST 2012


Author: kledzik
Date: Tue Feb 14 18:38:09 2012
New Revision: 150539

URL: http://llvm.org/viewvc/llvm-project?rev=150539&view=rev
Log:


Added:
    lld/trunk/test/fixups-addend.objtxt
    lld/trunk/test/fixups-dup-named.objtxt
    lld/trunk/test/fixups-named.objtxt
    lld/trunk/test/fixups-unnamed.objtxt
Removed:
    lld/trunk/test/internal-name-attributes.objtxt
Modified:
    lld/trunk/include/lld/Core/DefinedAtom.h
    lld/trunk/include/lld/Core/Reference.h
    lld/trunk/include/lld/Core/Resolver.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/test/cstring-coalesce.objtxt
    lld/trunk/tools/lld-core/lld-core.cpp

Modified: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Tue Feb 14 18:38:09 2012
@@ -34,7 +34,7 @@
 /// Here are some example attribute sets for common atoms. If a particular
 /// attribute is not listed, the default values are:  definition=regular,
 /// sectionChoice=basedOnContent, scope=translationUnit, merge=no, 
-/// internalName=false, deadStrip=normal, interposable=no
+/// deadStrip=normal, interposable=no
 ///
 ///  C function:  void foo() {} <br>
 ///    name=foo, type=code, perm=r_x, scope=global
@@ -71,16 +71,16 @@
 ///    mergeDupes=asAddressedWeak
 ///
 ///  literal c-string:  "hello" <br>
-///    name=L0, internalName=true, type=cstring, perm=r__, scope=linkageUnit
+///    name="" type=cstring, perm=r__, scope=linkageUnit
 ///
 ///  literal double:  1.234 <br>
-///    name=L0, internalName=true, type=literal8, perm=r__, scope=linkageUnit
+///    name="" type=literal8, perm=r__, scope=linkageUnit
 ///
 ///  constant:  { 1,2,3 } <br>
-///    name=L0, internalName=true, type=constant, perm=r__, scope=linkageUnit
+///    name="" type=constant, perm=r__, scope=linkageUnit
 ///
 ///  Pointer to initializer function:  <br>
-///    name=_init, internalName=true, type=initializer, perm=rw_l,
+///    name="" type=initializer, perm=rw_l,
 ///    sectionChoice=customRequired
 ///
 ///  C function place in custom section:  __attribute__((section("__foo"))) 
@@ -195,15 +195,18 @@
     uint16_t modulus;
   };
 
+  /// for use iterating over this Atom's References
+  class ReferenceHandler {
+  public:
+    virtual ~ReferenceHandler() {}
+    virtual void doReference(const Reference &) = 0;
+  };
+
   /// ordinal - returns a value for the order of this Atom within its file.
   /// This is used by the linker to order the layout of Atoms so that
   /// the resulting image is stable and reproducible.
   virtual uint64_t ordinal() const = 0;
-    
-  /// internalName - If the name is just a temporary label that should
-  /// not show up in the final linked image.
-  virtual bool internalName() const = 0;
-  
+
   /// size - the number of bytes of space this atom's content will occupy
   /// in the final linked image.  For a function atom, it is the number
   /// of bytes of code in the function.
@@ -264,12 +267,9 @@
   /// this Atom's content.
   virtual llvm::ArrayRef<uint8_t> rawContent() const = 0;
 
-  /// referencesBegin - used to start iterating this Atom's References
-  virtual Reference::iterator referencesBegin() const = 0;
-
-  /// referencesEnd - used to end iterating this Atom's References
-  virtual Reference::iterator referencesEnd() const = 0;
-
+  /// iterator over this Atom's References
+  virtual void forEachReference(ReferenceHandler&) const = 0;
+  
 protected:
   /// DefinedAtom is an abstract base class.  
   /// Only subclasses can access constructor.

Modified: lld/trunk/include/lld/Core/Reference.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Reference.h?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Reference.h (original)
+++ lld/trunk/include/lld/Core/Reference.h Tue Feb 14 18:38:09 2012
@@ -12,22 +12,60 @@
 
 #include <stdint.h>
 
-
 namespace lld {
 
-class Atom;
-
+///
+/// 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. 
+///
+/// For example if a function contains a call site to "malloc" 40 bytes into 
+/// the Atom, then the function Atom will have a Reference of: offsetInAtom=40,
+/// kind=callsite, target=malloc, addend=0.
+///
+/// Besides supporting traditional "relocations", References are also used
+/// grouping atoms (group comdat), forcing layout (one atom must follow 
+/// another), marking data-in-code (jump tables or ARM constants), etc.
+///
 class Reference {
 public:
-  typedef Reference *iterator;
-
-  const Atom *target;
-  uint64_t    addend;
-  uint32_t    offsetInAtom;
-  uint16_t    kind;
-  uint16_t    flags;
+  /// The meaning of positive kind values is architecture specific.  
+  /// Negative kind values are architecture independent.
+  typedef int32_t Kind;
+
+  // A value to be added to the value of a target
+  typedef int64_t Addend;
+
+  /// What sort of reference this is. 
+  virtual Kind kind() const = 0;
+  
+  /// If the reference is a fixup in the Atom, then this returns the 
+  /// byte offset into the Atom's content to do the fix up.
+  virtual uint64_t offsetInAtom() const = 0;
+  
+  /// If the reference is an edge to another Atom, then this returns the
+  /// other Atom.  Otherwise, it returns NULL.
+  virtual const class Atom * target() const = 0;
+  
+  /// During linking, the linker may merge graphs which coalesces some nodes
+  /// (i.e. Atoms).  To switch the target of a reference, this method is called.
+  virtual void setTarget(const class Atom *) = 0;
+  
+  /// Some relocations require a symbol and a value (e.g. foo + 4).
+  virtual Addend addend() const = 0;
+  
+protected:
+  /// Atom is an abstract base class.  Only subclasses can access constructor.
+  Reference() {}
+  
+  /// The memory for Reference objects is always managed by the owning File
+  /// object.  Therefore, no one but the owning File object should call
+  /// delete on an Reference.  In fact, some File objects may bulk allocate
+  /// an array of References, so they cannot be individually deleted by anyone.
+  virtual ~Reference() {}
 };
 
+
 } // namespace lld
 
 #endif // LLD_CORE_REFERENCES_H_

Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Tue Feb 14 18:38:09 2012
@@ -70,6 +70,22 @@
   void markLive(const Atom &atom, WhyLiveBackChain *previous);
   void addAtoms(const std::vector<const DefinedAtom *>&);
 
+
+  // helper to update targets for use with forEachReference()
+  class MarkLiveReferences : public DefinedAtom::ReferenceHandler {
+  public:
+             MarkLiveReferences(Resolver& resolver, WhyLiveBackChain* chain) 
+                  : _resolver(resolver), _chain(chain) { }
+    
+    virtual void doReference(const Reference& ref) {
+    _resolver.markLive(*ref.target(), _chain);
+    }
+
+  private:
+    Resolver&          _resolver;
+    WhyLiveBackChain*  _chain;
+  };
+
   Platform &_platform;
   const InputFiles &_inputFiles;
   SymbolTable _symbolTable;

Modified: lld/trunk/lib/Core/NativeFileFormat.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeFileFormat.h?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeFileFormat.h (original)
+++ lld/trunk/lib/Core/NativeFileFormat.h Tue Feb 14 18:38:09 2012
@@ -80,6 +80,7 @@
   uint32_t    architecture;
   uint32_t    fileSize;
   uint32_t    chunkCount;
+  // NativeChunk chunks[]
 };
 
 //
@@ -90,8 +91,11 @@
   NCS_AttributesArrayV1 = 2,
   NCS_UndefinedAtomsV1 = 3,
   NCS_Strings = 4,
-  NCS_Content = 5,
-  NCS_ReferencesArray = 6,
+  NCS_ReferencesArrayV1 = 5,
+  NCS_ReferencesArrayV2 = 6,
+  NCS_TargetsTable = 7,
+  NCS_AddendsTable = 8,
+  NCS_Content = 9,
 }; 
 
 //
@@ -125,6 +129,8 @@
 struct NativeDefinedAtomIvarsV1 {
   uint32_t  nameOffset;
   uint32_t  attributesOffset;
+  uint32_t  referencesStartIndex;
+  uint32_t  referencesCount;
   uint32_t  contentOffset;
   uint32_t  contentSize;
 };
@@ -137,7 +143,6 @@
   uint32_t  sectionNameOffset;
   uint16_t  align2;
   uint16_t  alignModulus;
-  uint8_t   internalName;
   uint8_t   scope;
   uint8_t   interposable;
   uint8_t   merge;
@@ -145,10 +150,7 @@
   uint8_t   sectionChoice;
   uint8_t   deadStrip;
   uint8_t   permissions;
-  uint8_t   thumb;
   uint8_t   alias;
-  uint8_t   pad1;
-  uint8_t   pad2;
 };
 
 
@@ -164,6 +166,51 @@
 
 
 
+//
+// The NCS_ReferencesArrayV1 chunk contains an array of these structs
+//
+struct NativeReferenceIvarsV1 {
+  uint16_t  offsetInAtom;
+   int16_t  kind;
+  uint16_t  targetIndex;
+  uint16_t  addendIndex;
+};
+
+
+
+//
+// The NCS_ReferencesArrayV2 chunk contains an array of these structs
+//
+struct NativeReferenceIvarsV2 {
+  uint64_t  offsetInAtom;
+  int64_t   addend;
+  int32_t   kind;
+  uint32_t  targetIndex;
+};
+
+
+//
+// The NCS_TargetsTable chunk contains an array of uint32_t entries.
+// The C++ class Reference has a target() method that returns a 
+// pointer to another Atom.  We can't have pointers in object files,
+// so instead  NativeReferenceIvarsV1 contains an index to the target.
+// The index is into this NCS_TargetsTable of uint32_t entries.  
+// The values in this table are the index of the (target) atom in this file.
+// For DefinedAtoms the value is from 0 to NCS_DefinedAtomsV1.elementCount.
+// For UndefinedAtoms the value is from NCS_DefinedAtomsV1.elementCount to
+// NCS_DefinedAtomsV1.elementCount+NCS_UndefinedAtomsV1.elementCount.
+//
+
+
+//
+// The NCS_AddendsTable chunk contains an array of int64_t entries.
+// If we allocated space for addends directly in NativeReferenceIvarsV1
+// it would double the size of that struct.  But since addends are rare,
+// we instead just keep a pool of addends and have NativeReferenceIvarsV1
+// (if it needs an addend) just store the index (into the pool) of the 
+// addend it needs.
+//
+
 
 
 } // namespace lld

Modified: lld/trunk/lib/Core/NativeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeReader.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeReader.cpp (original)
+++ lld/trunk/lib/Core/NativeReader.cpp Tue Feb 14 18:38:09 2012
@@ -44,10 +44,6 @@
   
   virtual llvm::StringRef name() const;
   
-  virtual bool internalName() const {
-    return attributes().internalName;
-  }
-  
   virtual uint64_t size() const {
     return _ivarData->contentSize;
   }
@@ -88,23 +84,17 @@
   }
   
   virtual bool isThumb() const {
-     return (attributes().thumb != 0);
+     return false; //(attributes().thumb != 0);
   }
     
   virtual bool isAlias() const {
      return (attributes().alias != 0);
   }
   
-  llvm::ArrayRef<uint8_t> rawContent() const;
+  virtual llvm::ArrayRef<uint8_t> rawContent() const;
     
-  virtual Reference::iterator referencesBegin() const {
-     return 0;
-  }
-  
-  virtual Reference::iterator referencesEnd() const {
-    return 0;
-  }
-
+  virtual void forEachReference(ReferenceHandler&) const;
+   
 private:
   const NativeAtomAttributesV1& attributes() const;
   
@@ -139,6 +129,35 @@
 
 
 //
+// An object of this class is instantied for each NativeReferenceIvarsV1
+// struct in the NCS_ReferencesArrayV1 chunk.
+//
+class NativeReferenceV1 : public Reference {
+public:
+       NativeReferenceV1(const NativeFile& f, 
+                             const NativeReferenceIvarsV1* ivarData)
+        : _file(&f), _ivarData(ivarData) { } 
+
+  virtual uint64_t offsetInAtom() const {
+    return _ivarData->offsetInAtom;
+  }
+  
+  virtual Kind kind() const {
+    return _ivarData->kind;
+  }
+  
+  virtual const Atom* target() const;
+  virtual Addend addend() const;
+  virtual void setTarget(const Atom* newAtom);
+   
+private:
+  const NativeFile*                 _file;
+  const NativeReferenceIvarsV1*     _ivarData;
+};
+
+
+
+//
 // lld::File object for native llvm object file
 //
 class NativeFile : public File {
@@ -187,6 +206,15 @@
         case NCS_UndefinedAtomsV1:
           ec = file->processUndefinedAtomsV1(base, chunk);
           break;
+        case NCS_ReferencesArrayV1:
+          ec = file->processReferencesV1(base, chunk);
+          break;
+        case NCS_TargetsTable:
+          ec = file->processTargetsTable(base, chunk);
+          break;
+        case NCS_AddendsTable:
+          ec = file->processAddendsTable(base, chunk);
+          break;
         case NCS_Content:
           ec = file->processContent(base, chunk);
           break;
@@ -219,6 +247,8 @@
     // to just delete the memory.
     delete _definedAtoms.arrayStart;
     delete _undefinedAtoms.arrayStart;
+    delete _references.arrayStart;
+    delete _targetsTable;
   }
   
   // visits each atom in the file
@@ -245,6 +275,7 @@
 private:
   friend class NativeDefinedAtomV1;
   friend class NativeUndefinedAtomV1;
+  friend class NativeReferenceV1;
   
   // instantiate array of DefinedAtoms from v1 ivar data in file
   llvm::error_code processDefinedAtomsV1(const uint8_t* base, 
@@ -272,6 +303,7 @@
     this->_definedAtoms.arrayStart = atomsStart;
     this->_definedAtoms.arrayEnd = atomsEnd;
     this->_definedAtoms.elementSize = atomSize;
+    this->_definedAtoms.elementCount = chunk->elementCount;
     return make_error_code(native_reader_error::success);
   }
   
@@ -307,6 +339,77 @@
     this->_undefinedAtoms.arrayStart = atomsStart;
     this->_undefinedAtoms.arrayEnd = atomsEnd;
     this->_undefinedAtoms.elementSize = atomSize;
+    this->_undefinedAtoms.elementCount = chunk->elementCount;
+    return make_error_code(native_reader_error::success);
+  }
+  
+  
+  // instantiate array of Referemces from v1 ivar data in file
+  llvm::error_code processReferencesV1(const uint8_t* base, 
+                                                const NativeChunk* chunk) {
+    if ( chunk->elementCount == 0 )
+      return make_error_code(native_reader_error::success);
+    const size_t refSize = sizeof(NativeReferenceV1);
+    size_t refsArraySize = chunk->elementCount * refSize;
+    uint8_t* refsStart = reinterpret_cast<uint8_t*>
+                                (operator new(refsArraySize, std::nothrow));
+    if (refsStart == NULL )
+      return make_error_code(native_reader_error::memory_error);
+    const size_t ivarElementSize = chunk->fileSize
+                                          / chunk->elementCount;
+    if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
+      return make_error_code(native_reader_error::file_malformed);
+    uint8_t* refsEnd = refsStart + refsArraySize;
+    const NativeReferenceIvarsV1* ivarData = 
+                             reinterpret_cast<const NativeReferenceIvarsV1*>
+                                                  (base + chunk->fileOffset);
+    for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
+      NativeReferenceV1* atomAllocSpace = 
+                  reinterpret_cast<NativeReferenceV1*>(s);
+      new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
+      ++ivarData;
+    }
+    this->_references.arrayStart = refsStart;
+    this->_references.arrayEnd = refsEnd;
+    this->_references.elementSize = refSize;
+    this->_references.elementCount = chunk->elementCount;
+    return make_error_code(native_reader_error::success);
+  }
+  
+  // set up pointers to target table
+  llvm::error_code processTargetsTable(const uint8_t* base, 
+                                                const NativeChunk* chunk) {
+    const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
+                                                  (base + chunk->fileOffset);
+    this->_targetsTableCount = chunk->elementCount;
+    this->_targetsTable = new const Atom*[chunk->elementCount];
+    for (uint32_t i=0; i < chunk->elementCount; ++i) {
+      const uint32_t index = targetIndexes[i];
+      if ( index < _definedAtoms.elementCount ) {
+        const uint8_t* p = _definedAtoms.arrayStart 
+                                    + index * _definedAtoms.elementSize;
+        this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
+        continue;
+      }
+      const uint32_t undefIndex = index - _definedAtoms.elementCount;
+      if ( undefIndex < _undefinedAtoms.elementCount ) {
+        const uint8_t* p = _undefinedAtoms.arrayStart 
+                                    + undefIndex * _undefinedAtoms.elementSize;
+        this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
+        continue;
+      }
+      return make_error_code(native_reader_error::file_malformed);
+    }
+    return make_error_code(native_reader_error::success);
+  }
+  
+  
+  // set up pointers to addend pool in file
+  llvm::error_code processAddendsTable(const uint8_t* base, 
+                                                const NativeChunk* chunk) {
+    this->_addends = reinterpret_cast<const Reference::Addend*>
+                                                  (base + chunk->fileOffset);
+    this->_addendsMaxIndex = chunk->elementCount;
     return make_error_code(native_reader_error::success);
   }
   
@@ -331,9 +434,16 @@
     return llvm::StringRef(&_strings[offset]);
   }
   
-  const NativeAtomAttributesV1& attribute(uint32_t offset) const {
-    assert(offset < _attributesMaxOffset);
-    return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + offset);
+  Reference::Addend addend(uint32_t index) const {
+    if ( index == 0 )
+      return 0; // addend index zero is used to mean "no addend"
+    assert(index <= _addendsMaxIndex);
+    return _addends[index-1]; // one-based indexing
+  }
+
+  const NativeAtomAttributesV1& attribute(uint32_t off) const {
+    assert(off < _attributesMaxOffset);
+    return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
   }
 
   const uint8_t* content(uint32_t offset, uint32_t size) const {
@@ -342,44 +452,75 @@
     return result;
   }
 
-
+  void forEachReference(DefinedAtom::ReferenceHandler& handler, 
+                                        uint32_t start, uint32_t count) const {
+    assert(start < _references.elementCount);
+    assert(start+count <= _references.elementCount);
+    const uint8_t* arrStart = _references.arrayStart 
+                                   + start * _references.elementSize;
+    const uint8_t* arrEnd = arrStart + count * _references.elementSize;
+    for(const uint8_t* p=arrStart; p != arrEnd; p += _references.elementSize) {
+      const NativeReferenceV1* ref 
+                              = reinterpret_cast<const NativeReferenceV1*>(p);
+      handler.doReference(*ref);
+    }
+  }
+  
+  const Atom* target(uint32_t index) const {
+    assert(index < _targetsTableCount);
+    return _targetsTable[index];
+  }
+  
+  void setTarget(uint32_t index, const Atom* newAtom) const {
+    assert(index > _targetsTableCount);
+    _targetsTable[index] = newAtom;
+  }
+ 
+  
   // private constructor, only called by make()
   NativeFile(llvm::OwningPtr<llvm::MemoryBuffer>& mb, llvm::StringRef path) :
     lld::File(path), 
     _buffer(mb.take()),  // NativeFile now takes ownership of buffer
     _header(NULL), 
+    _targetsTable(NULL), 
+    _targetsTableCount(0),
     _strings(NULL), 
     _stringsMaxOffset(0),
+    _addends(NULL), 
+    _addendsMaxIndex(0),
     _contentStart(NULL), 
     _contentEnd(NULL)
   {
     _header = reinterpret_cast<const NativeFileHeader*>(_buffer->getBufferStart());
-    _definedAtoms.arrayStart = NULL;
-    _undefinedAtoms.arrayStart = NULL;
   }
 
-  struct AtomArray {
-                      AtomArray() : arrayStart(NULL), arrayEnd(NULL), 
-                                    elementSize(0) { }
+  struct IvarArray {
+                      IvarArray() : arrayStart(NULL), arrayEnd(NULL), 
+                                    elementSize(0), elementCount(0) { }
     const uint8_t*     arrayStart;
     const uint8_t*     arrayEnd;
     uint32_t           elementSize;
-  };
+    uint32_t           elementCount;
+ };
 
   llvm::OwningPtr<llvm::MemoryBuffer>  _buffer;
   const NativeFileHeader*         _header;
-  AtomArray                       _definedAtoms;
-  AtomArray                       _undefinedAtoms;
+  IvarArray                       _definedAtoms;
+  IvarArray                       _undefinedAtoms;
   const uint8_t*                  _attributes;
   uint32_t                        _attributesMaxOffset;
+  IvarArray                       _references;
+  const Atom**                    _targetsTable;
+  uint32_t                        _targetsTableCount;
   const char*                     _strings;
   uint32_t                        _stringsMaxOffset;
+  const Reference::Addend*        _addends;
+  uint32_t                        _addendsMaxIndex;
   const uint8_t*                  _contentStart;
   const uint8_t*                  _contentEnd;
 };
 
-
-
+ 
 inline const class File& NativeDefinedAtomV1::file() const {
   return *_file;
 }
@@ -410,8 +551,12 @@
   return _file->string(offset);
 }
 
-
-
+inline void NativeDefinedAtomV1::forEachReference(ReferenceHandler& hnd) const {
+  if ( _ivarData->referencesCount == 0 )
+    return;
+  _file->forEachReference(hnd, _ivarData->referencesStartIndex, 
+                               _ivarData->referencesCount);
+}
 
 inline const class File& NativeUndefinedAtomV1::file() const {
   return *_file;
@@ -422,6 +567,17 @@
 }
 
 
+inline const Atom* NativeReferenceV1::target() const {
+  return _file->target(_ivarData->targetIndex);
+}
+
+inline Reference::Addend NativeReferenceV1::addend() const {
+  return _file->addend(_ivarData->addendIndex);
+}
+
+inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
+  return _file->setTarget(_ivarData->targetIndex, newAtom);
+}
 
 
 //

Modified: lld/trunk/lib/Core/NativeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeWriter.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeWriter.cpp (original)
+++ lld/trunk/lib/Core/NativeWriter.cpp Tue Feb 14 18:38:09 2012
@@ -12,6 +12,7 @@
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
 
 #include "lld/Core/File.h"
 #include "lld/Core/NativeWriter.h"
@@ -25,10 +26,13 @@
 ///
 /// Class for writing native object files.
 ///
-class NativeWriter : public File::AtomHandler {
+class NativeWriter : public File::AtomHandler, 
+                     public DefinedAtom::ReferenceHandler {
 public:
   /// construct writer for an lld::File object
   NativeWriter(const lld::File& file) : _file(file) { 
+    // reserve first byte for unnamed atoms
+    _stringPool.push_back('\0');
     // visit all atoms
     _file.forEachAtom(*this);
     // construct file header based on atom information accumulated
@@ -37,36 +41,73 @@
 
   // write the lld::File in native format to the specified stream
   void write(llvm::raw_ostream& out) {
+    assert( out.tell() == 0 );
     out.write((char*)_headerBuffer, _headerBufferSize);
-    if (!_definedAtomIvars.empty())
+    
+    if (!_definedAtomIvars.empty()) {
+      assert( out.tell() == findChunk(NCS_DefinedAtomsV1).fileOffset );
       out.write((char*)&_definedAtomIvars[0],
                 _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1));
-    if (!_attributes.empty())
+    }
+    
+    if (!_attributes.empty()) {
+      assert( out.tell() == findChunk(NCS_AttributesArrayV1).fileOffset );
       out.write((char*)&_attributes[0],
                 _attributes.size()*sizeof(NativeAtomAttributesV1));
-    if ( !_undefinedAtomIvars.empty() ) 
+    }
+                
+    if ( !_undefinedAtomIvars.empty() ) {
+      assert( out.tell() == findChunk(NCS_UndefinedAtomsV1).fileOffset );
       out.write((char*)&_undefinedAtomIvars[0], 
               _undefinedAtomIvars.size()*sizeof(NativeUndefinedAtomIvarsV1));
-    if (!_stringPool.empty())
+    }
+              
+    if (!_stringPool.empty()) {
+      assert( out.tell() == findChunk(NCS_Strings).fileOffset );
       out.write(&_stringPool[0], _stringPool.size());
-    if (!_contentPool.empty())
+    }
+    
+    if ( !_references.empty() ) {
+      assert( out.tell() == findChunk(NCS_ReferencesArrayV1).fileOffset );
+      out.write((char*)&_references[0], 
+              _references.size()*sizeof(NativeReferenceIvarsV1));
+    }
+    
+    if ( !_targetsTableIndex.empty() ) {
+      assert( out.tell() == findChunk(NCS_TargetsTable).fileOffset );
+      writeTargetTable(out);
+    }
+  
+    if ( !_addendsTableIndex.empty() ) {
+      assert( out.tell() == findChunk(NCS_AddendsTable).fileOffset );
+      writeAddendTable(out);
+    }
+  
+    if (!_contentPool.empty()) {
+      assert( out.tell() == findChunk(NCS_Content).fileOffset );
       out.write((char*)&_contentPool[0], _contentPool.size());
+    }
   }
 
 private:
 
   // visitor routine called by forEachAtom() 
-  virtual void doDefinedAtom(const class DefinedAtom& atom) {
+  virtual void doDefinedAtom(const DefinedAtom& atom) {
+    _definedAtomIndex[&atom] = _definedAtomIvars.size();
     NativeDefinedAtomIvarsV1 ivar;
+    unsigned refsCount;
     ivar.nameOffset = getNameOffset(atom);
     ivar.attributesOffset = getAttributeOffset(atom);
+    ivar.referencesStartIndex = getReferencesIndex(atom, refsCount);
+    ivar.referencesCount = refsCount;
     ivar.contentOffset = getContentOffset(atom);
     ivar.contentSize = atom.size();
     _definedAtomIvars.push_back(ivar);
   }
   
   // visitor routine called by forEachAtom() 
-  virtual void doUndefinedAtom(const class UndefinedAtom& atom) {
+  virtual void doUndefinedAtom(const UndefinedAtom& atom) {
+    _undefinedAtomIndex[&atom] = _undefinedAtomIvars.size();
     NativeUndefinedAtomIvarsV1 ivar;
     ivar.nameOffset = getNameOffset(atom);
     ivar.flags = (atom.weakImport() ? 1 : 0);
@@ -74,13 +115,18 @@
   }
   
   // visitor routine called by forEachAtom() 
-  virtual void doFile(const class File &) {
+  virtual void doFile(const File &) {
   }
 
   // fill out native file header and chunk directory
   void makeHeader() {
     const bool hasUndefines = !_undefinedAtomIvars.empty();
-    const int chunkCount = hasUndefines ? 5 : 4;
+    const bool hasTargetsTable = !_targetsTableIndex.empty();
+    const bool hasAddendTable = !_addendsTableIndex.empty();
+    int chunkCount = 5;
+    if ( hasUndefines ) ++chunkCount;
+    if ( hasTargetsTable ) ++chunkCount;
+    if ( hasAddendTable ) ++chunkCount;
     _headerBufferSize = sizeof(NativeFileHeader) 
                          + chunkCount*sizeof(NativeChunk);
     _headerBuffer = reinterpret_cast<NativeFileHeader*>
@@ -124,6 +170,9 @@
     }
     
     // create chunk for symbol strings
+    // pad end of string pool to 4-bytes 
+    while ( (_stringPool.size() % 4) != 0 )
+      _stringPool.push_back('\0');
     NativeChunk& chs = chunks[nextIndex++];
     chs.signature = NCS_Strings;
     chs.fileOffset = nextFileOffset;
@@ -131,6 +180,34 @@
     chs.elementCount = _stringPool.size();
     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;
+
+    // create chunk for target table 
+    if ( hasTargetsTable ) {
+      NativeChunk& cht = chunks[nextIndex++];
+      cht.signature = NCS_TargetsTable;
+      cht.fileOffset = nextFileOffset;
+      cht.fileSize = _targetsTableIndex.size() * sizeof(uint32_t);
+      cht.elementCount = _targetsTableIndex.size();
+      nextFileOffset = cht.fileOffset + cht.fileSize;
+    }
+
+    // create chunk for addend table 
+    if ( hasAddendTable ) {
+      NativeChunk& chad = chunks[nextIndex++];
+      chad.signature = NCS_AddendsTable;
+      chad.fileOffset = nextFileOffset;
+      chad.fileSize = _addendsTableIndex.size() * sizeof(Reference::Addend);
+      chad.elementCount = _addendsTableIndex.size();
+      nextFileOffset = chad.fileOffset + chad.fileSize;
+    }
+    
     // create chunk for content 
     NativeChunk& chc = chunks[nextIndex++];
     chc.signature = NCS_Content;
@@ -142,6 +219,18 @@
     _headerBuffer->fileSize = nextFileOffset;
   }
 
+  // scan header to find particular chunk
+  NativeChunk& findChunk(uint32_t signature) {
+    const uint32_t chunkCount = _headerBuffer->chunkCount;
+    NativeChunk* chunks =
+      reinterpret_cast<NativeChunk*>(reinterpret_cast<char*>(_headerBuffer)
+                                     + sizeof(NativeFileHeader));
+    for (uint32_t i=0; i < chunkCount; ++i) {
+      if ( chunks[i].signature == signature )
+        return chunks[i];
+    }
+    assert(0 && "findChunk() signature not found");
+  }
 
   // append atom name to string pool and return offset
   uint32_t getNameOffset(const Atom& atom) {
@@ -150,6 +239,8 @@
   
  // append atom name to string pool and return offset
   uint32_t getNameOffset(llvm::StringRef name) {
+    if ( name.empty() )
+      return 0;
     uint32_t result = _stringPool.size();
     _stringPool.insert(_stringPool.end(), name.size()+1, 0);
     strcpy(&_stringPool[result], name.data());
@@ -206,7 +297,6 @@
     attrs.sectionNameOffset = sectionNameOffset(atom);
     attrs.align2            = atom.alignment().powerOf2;
     attrs.alignModulus      = atom.alignment().modulus;
-    attrs.internalName      = atom.internalName(); 
     attrs.scope             = atom.scope(); 
     attrs.interposable      = atom.interposable(); 
     attrs.merge             = atom.merge(); 
@@ -214,12 +304,99 @@
     attrs.sectionChoice     = atom.sectionChoice(); 
     attrs.deadStrip         = atom.deadStrip(); 
     attrs.permissions       = atom.permissions(); 
-    attrs.thumb             = atom.isThumb(); 
+    //attrs.thumb             = atom.isThumb(); 
     attrs.alias             = atom.isAlias(); 
   }
 
+  // add references for this atom in a contiguous block in NCS_ReferencesArrayV1
+  uint32_t getReferencesIndex(const DefinedAtom& atom, unsigned& count) {
+    count = 0;
+    size_t startRefSize = _references.size();
+    uint32_t result = startRefSize;
+    atom.forEachReference(*this);
+    count = _references.size() - startRefSize;
+    if ( count == 0 )
+      return 0;
+    else
+      return result;
+  }
+  
+  void doReference(const Reference& ref) {
+    NativeReferenceIvarsV1 nref;
+    nref.offsetInAtom = ref.offsetInAtom();
+    nref.kind = ref.kind();
+    nref.targetIndex = this->getTargetIndex(ref.target());
+    nref.addendIndex = this->getAddendIndex(ref.addend());
+    _references.push_back(nref);
+  }
+  
+  uint32_t getTargetIndex(const Atom* target) {
+    TargetToIndex::const_iterator pos = _targetsTableIndex.find(target);
+    if ( pos != _targetsTableIndex.end() ) {
+      return pos->second;
+    }
+    uint32_t result = _targetsTableIndex.size();
+    _targetsTableIndex[target] = result;
+    return result;
+  }
+  
+  void writeTargetTable(llvm::raw_ostream& out) {
+    // Build table of target indexes  
+    uint32_t maxTargetIndex = _targetsTableIndex.size();
+    uint32_t targetIndexes[maxTargetIndex];
+    for (TargetToIndex::iterator it = _targetsTableIndex.begin(); 
+                                 it != _targetsTableIndex.end(); ++it) {
+      const Atom* atom = it->first;
+      uint32_t targetIndex = it->second;
+      assert(targetIndex < maxTargetIndex);
+      uint32_t atomIndex = 0;
+      TargetToIndex::iterator pos = _definedAtomIndex.find(atom);
+      if ( pos != _definedAtomIndex.end() ) {
+        atomIndex = pos->second;
+      }
+      else {
+        pos = _undefinedAtomIndex.find(atom);
+        assert(pos != _undefinedAtomIndex.end());
+        atomIndex = pos->second + _definedAtomIvars.size();
+      }
+      targetIndexes[targetIndex] = atomIndex;
+    }
+    // write table
+    out.write((char*)&targetIndexes[0], maxTargetIndex*sizeof(uint32_t));
+  }
+  
+  uint32_t getAddendIndex(Reference::Addend addend) { 
+    if ( addend == 0 )
+      return 0; // addend index zero is used to mean "no addend"
+    AddendToIndex::const_iterator pos = _addendsTableIndex.find(addend);
+    if ( pos != _addendsTableIndex.end() ) {
+      return pos->second;
+    }
+    uint32_t result = _addendsTableIndex.size() + 1; // one-based index
+    _addendsTableIndex[addend] = result;
+    return result;
+  }
+ 
+  void writeAddendTable(llvm::raw_ostream& out) {
+    // Build table of addends  
+    uint32_t maxAddendIndex = _addendsTableIndex.size();
+    Reference::Addend addends[maxAddendIndex];
+    for (AddendToIndex::iterator it = _addendsTableIndex.begin(); 
+                                 it != _addendsTableIndex.end(); ++it) {
+      Reference::Addend addend = it->first;
+      uint32_t index = it->second;
+      assert(index <= maxAddendIndex);
+      addends[index-1] = addend;
+    }
+    // write table
+    out.write((char*)&addends[0], maxAddendIndex*sizeof(Reference::Addend));
+  }
+
   typedef std::vector<std::pair<llvm::StringRef, uint32_t> > NameToOffsetVector;
 
+  typedef llvm::DenseMap<const Atom*, uint32_t> TargetToIndex;
+  typedef llvm::DenseMap<Reference::Addend, uint32_t> AddendToIndex;
+
   const lld::File&                        _file;
   NativeFileHeader*                       _headerBuffer;
   size_t                                  _headerBufferSize;
@@ -228,6 +405,11 @@
   std::vector<NativeDefinedAtomIvarsV1>   _definedAtomIvars;
   std::vector<NativeAtomAttributesV1>     _attributes;
   std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
+  std::vector<NativeReferenceIvarsV1>     _references;
+  TargetToIndex                           _targetsTableIndex;
+  TargetToIndex                           _definedAtomIndex;
+  TargetToIndex                           _undefinedAtomIndex;
+  AddendToIndex                           _addendsTableIndex;
   NameToOffsetVector                      _sectionNames;
 };
 

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Tue Feb 14 18:38:09 2012
@@ -199,20 +199,34 @@
   }
 }
 
+// helper to update targets for use with forEachReference()
+class ReferenceUpdater : public DefinedAtom::ReferenceHandler {
+public:
+		           ReferenceUpdater(SymbolTable& sym) : _symbolTable(sym) { }
+	
+	virtual void doReference(const Reference& ref) {
+    const Atom* newTarget = _symbolTable.replacement(ref.target());
+    (const_cast<Reference*>(&ref))->setTarget(newTarget);
+  }
+
+private:
+	SymbolTable&  _symbolTable;
+};
+
+
 // switch all references to undefined or coalesced away atoms
 // to the new defined atom
 void Resolver::updateReferences() {
+  ReferenceUpdater updater(_symbolTable);
   for (std::vector<const Atom *>::iterator it = _atoms.begin();
        it != _atoms.end(); ++it) {
     if ( const DefinedAtom* defAtom = (*it)->definedAtom() ) {
-      for (Reference::iterator rit = defAtom->referencesBegin(),
-         end = defAtom->referencesEnd(); rit != end; ++rit) {
-        rit->target = _symbolTable.replacement(rit->target);
-      }
+      defAtom->forEachReference(updater);
     }
   }
 }
 
+
 // for dead code stripping, recursively mark atom "live"
 void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {
   // if -why_live cares about this symbol, then dump chain
@@ -240,10 +254,8 @@
   thisChain.previous = previous;
   thisChain.referer = &atom;
   if ( const DefinedAtom* defAtom = atom.definedAtom() ) {
-    for (Reference::iterator rit = defAtom->referencesBegin(),
-        end = defAtom->referencesEnd(); rit != end; ++rit) {
-      this->markLive(*(rit->target), &thisChain);
-    }
+    MarkLiveReferences markRefs(*this, &thisChain);
+    defAtom->forEachReference(markRefs);
   }
 }
 

Modified: lld/trunk/lib/Core/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/SymbolTable.cpp (original)
+++ lld/trunk/lib/Core/SymbolTable.cpp Tue Feb 14 18:38:09 2012
@@ -38,7 +38,7 @@
 
 void SymbolTable::add(const DefinedAtom &atom) {
   assert(atom.scope() != DefinedAtom::scopeTranslationUnit);
-  if ( !atom.internalName() ) {
+  if ( !atom.name().empty() ) {
     this->addByName(atom);
   }
   else {

Modified: lld/trunk/lib/Core/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)
+++ lld/trunk/lib/Core/YamlKeyValues.cpp Tue Feb 14 18:38:09 2012
@@ -18,12 +18,12 @@
 
 
 const char* const KeyValues::nameKeyword            = "name";
+const char* const KeyValues::refNameKeyword         = "ref-name";
 const char* const KeyValues::definitionKeyword      = "definition";
 const char* const KeyValues::scopeKeyword           = "scope";
 const char* const KeyValues::contentTypeKeyword     = "type";
 const char* const KeyValues::deadStripKindKeyword   = "dead-strip";
 const char* const KeyValues::sectionChoiceKeyword   = "section-choice";
-const char* const KeyValues::internalNameKeyword    = "internal-name";
 const char* const KeyValues::interposableKeyword    = "interposable";
 const char* const KeyValues::mergeKeyword           = "merge";
 const char* const KeyValues::isThumbKeyword         = "is-thumb";
@@ -31,8 +31,14 @@
 const char* const KeyValues::sectionNameKeyword     = "section-name";
 const char* const KeyValues::contentKeyword         = "content";
 const char* const KeyValues::sizeKeyword            = "size";
+const char* const KeyValues::fixupsKeyword          = "fixups";
 const char* const KeyValues::permissionsKeyword     = "permissions";
 const char* const KeyValues::weakImportKeyword      = "weak-import";
+const char* const KeyValues::fixupsKindKeyword      = "kind";
+const char* const KeyValues::fixupsOffsetKeyword    = "offset";
+const char* const KeyValues::fixupsTargetKeyword    = "target";
+const char* const KeyValues::fixupsAddendKeyword    = "addend";
+
 
 
 const DefinedAtom::Definition         KeyValues::definitionDefault = Atom::definitionRegular;
@@ -43,7 +49,6 @@
 const DefinedAtom::Interposable       KeyValues::interposableDefault = DefinedAtom::interposeNo;
 const DefinedAtom::Merge              KeyValues::mergeDefault = DefinedAtom::mergeNo;
 const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAtom::permR__;
-const bool                            KeyValues::internalNameDefault = false;
 const bool                            KeyValues::isThumbDefault = false;
 const bool                            KeyValues::isAliasDefault = false;
 const bool                            KeyValues::weakImportDefault = false;
@@ -352,22 +357,6 @@
 
 
 
-bool KeyValues::internalName(const char* s)
-{
-  if ( strcmp(s, "true") == 0 )
-    return true;
-  else if ( strcmp(s, "false") == 0 )
-    return false;
-  llvm::report_fatal_error("bad internal-name value");
-}
-
-const char* KeyValues::internalName(bool b) {
-  return b ? "true" : "false";
-}
-
-
-
-
 bool KeyValues::isThumb(const char* s)
 {
   if ( strcmp(s, "true") == 0 )

Modified: lld/trunk/lib/Core/YamlKeyValues.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.h?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.h (original)
+++ lld/trunk/lib/Core/YamlKeyValues.h Tue Feb 14 18:38:09 2012
@@ -20,10 +20,12 @@
 class KeyValues {
 public:
   static const char* const                nameKeyword;
+  static const char* const                refNameKeyword;
   static const char* const                sectionNameKeyword;
   static const char* const                contentKeyword;
   static const char* const                sizeKeyword;
-  
+  static const char* const                fixupsKeyword;
+ 
   static const char* const                definitionKeyword;
   static const Atom::Definition           definitionDefault;
   static Atom::Definition                 definition(const char*);
@@ -64,11 +66,6 @@
   static DefinedAtom::ContentPermissions        permissions(const char*);
   static const char*                            permissions(DefinedAtom::ContentPermissions);
 
-  static const char* const                internalNameKeyword;
-  static const bool                       internalNameDefault;
-  static bool                             internalName(const char*);
-  static const char*                      internalName(bool);
-
   static const char* const                isThumbKeyword;
   static const bool                       isThumbDefault;
   static bool                             isThumb(const char*);
@@ -84,6 +81,12 @@
   static bool                             weakImport(const char*);
   static const char*                      weakImport(bool);
 
+
+  static const char* const                fixupsKindKeyword;
+  static const char* const                fixupsOffsetKeyword;
+  static const char* const                fixupsTargetKeyword;
+  static const char* const                fixupsAddendKeyword;
+
 };
 
 } // namespace yaml

Modified: lld/trunk/lib/Core/YamlReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlReader.cpp (original)
+++ lld/trunk/lib/Core/YamlReader.cpp Tue Feb 14 18:38:09 2012
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <string.h>
+
 #include "YamlKeyValues.h"
 
 #include "lld/Core/YamlReader.h"
@@ -30,6 +32,8 @@
 namespace lld {
 namespace yaml {
 
+namespace {
+
 class YAML {
 public:
   struct Entry {
@@ -214,7 +218,7 @@
         sequenceBytes->push_back(contentByte);
         state = inValueSequenceEnd;
       }
-      else if (c == ' ') {
+      else if ( (c == ' ') || (c == '\n') ) {
         // eat white space
       }
       else if (c == ',') {
@@ -245,6 +249,44 @@
   }
 }
 
+
+
+class YAMLReference : public Reference {
+public: 
+                YAMLReference() : _target(NULL), _targetName(NULL), 
+                                   _offsetInAtom(0), _addend(0), _kind(0) { }
+
+  virtual uint64_t offsetInAtom() const {
+    return _offsetInAtom;
+  }
+  
+  virtual Kind kind() const {
+    return _kind;
+  }
+  
+  virtual const Atom* target() const {
+    return _target;
+  }
+  
+  virtual Addend addend() const {
+    return _addend;
+  }
+
+  virtual void setTarget(const Atom* newAtom) {
+    _target = newAtom;
+  }
+
+  const Atom*  _target;
+  const char*  _targetName;
+  uint64_t     _offsetInAtom;
+  Addend       _addend;
+  Kind         _kind;
+};
+
+
+
+class YAMLDefinedAtom;
+
 class YAMLFile : public File {
 public:
   YAMLFile()
@@ -255,29 +297,24 @@
   virtual bool justInTimeforEachAtom(llvm::StringRef name,
                                      File::AtomHandler &) const;
 
-  std::vector<DefinedAtom*> _definedAtoms;
-  std::vector<UndefinedAtom*> _undefinedAtoms;
-  std::vector<Reference> _references;
-  unsigned int _lastRefIndex;
-};
+  void bindTargetReferences();
+  void addDefinedAtom(YAMLDefinedAtom* atom, const char* refName);
+  void addUndefinedAtom(UndefinedAtom* atom);
+  Atom* findAtom(const char* name);
+  
+  struct NameAtomPair {
+                 NameAtomPair(const char* n, Atom* a) : name(n), atom(a) {}
+    const char*  name;
+    Atom*        atom;
+  };
 
-bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
-  handler.doFile(*this);
-  for (std::vector<DefinedAtom *>::const_iterator it = _definedAtoms.begin();
-       it != _definedAtoms.end(); ++it) {
-    handler.doDefinedAtom(**it);
-  }
-  for (std::vector<UndefinedAtom *>::const_iterator it = _undefinedAtoms.begin();
-       it != _undefinedAtoms.end(); ++it) {
-    handler.doUndefinedAtom(**it);
-  }
-  return true;
-}
+  std::vector<YAMLDefinedAtom*>   _definedAtoms;
+  std::vector<UndefinedAtom*>     _undefinedAtoms;
+  std::vector<YAMLReference>      _references;
+  std::vector<NameAtomPair>       _nameToAtomMapping;
+  unsigned int                    _lastRefIndex;
+};
 
-bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,
-                                     File::AtomHandler &handler) const {
-  return false;
-}
 
 
 class YAMLDefinedAtom : public DefinedAtom {
@@ -291,7 +328,6 @@
           , DefinedAtom::Merge merge
           , DefinedAtom::DeadStripKind deadStrip
           , DefinedAtom::ContentPermissions perms
-          , bool internalName
           , bool isThumb
           , bool isAlias
           , DefinedAtom::Alignment alignment
@@ -313,7 +349,6 @@
     , _merge(merge)
     , _deadStrip(deadStrip)
     , _permissions(perms)
-    , _internalName(internalName)
     , _isThumb(isThumb)
     , _isAlias(isAlias)
     , _refStartIndex(file._lastRefIndex)
@@ -326,13 +361,12 @@
   }
 
   virtual llvm::StringRef name() const {
-    return _name;
+    if ( _name == NULL )
+      return llvm::StringRef();
+    else
+      return _name;
   }
 
-  virtual bool internalName() const {
-    return _internalName;
-  }
-  
  virtual uint64_t size() const {
     return (_content ? _content->size() : _size);
   }
@@ -393,16 +427,18 @@
   }
 
   
-  virtual Reference::iterator referencesBegin() const {
-    if (_file._references.size() < _refStartIndex)
-      return (Reference::iterator)&_file._references[_refStartIndex];
-    return 0;
+  virtual void forEachReference(ReferenceHandler& handler) const {
+    for (uint32_t i=_refStartIndex; i < _refEndIndex; ++i) {
+      handler.doReference(_file._references[i]);
+    }
   }
-  
-  virtual Reference::iterator referencesEnd() const {
-    if (_file._references.size() < _refEndIndex)
-      return (Reference::iterator)&_file._references[_refEndIndex];
-    return 0;
+    
+  void bindTargetReferences() {
+    for (unsigned int i=_refStartIndex; i < _refEndIndex; ++i) {
+      const char* targetName = _file._references[i]._targetName;
+      Atom* targetAtom = _file.findAtom(targetName);
+      _file._references[i]._target = targetAtom;
+    }
   }
   
 private:
@@ -420,7 +456,6 @@
   DefinedAtom::Merge          _merge;
   DefinedAtom::DeadStripKind  _deadStrip;
   DefinedAtom::ContentPermissions _permissions;
-  bool                        _internalName;
   bool                        _isThumb;
   bool                        _isAlias;
   unsigned int                _refStartIndex;
@@ -453,22 +488,71 @@
 };
 
 
+bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
+  handler.doFile(*this);
+  for (std::vector<YAMLDefinedAtom *>::const_iterator it = _definedAtoms.begin();
+       it != _definedAtoms.end(); ++it) {
+    handler.doDefinedAtom(**it);
+  }
+  for (std::vector<UndefinedAtom *>::const_iterator it = _undefinedAtoms.begin();
+       it != _undefinedAtoms.end(); ++it) {
+    handler.doUndefinedAtom(**it);
+  }
+  return true;
+}
+
+bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,
+                                     File::AtomHandler &handler) const {
+  return false;
+}
+
+void YAMLFile::bindTargetReferences() {
+    for (std::vector<YAMLDefinedAtom *>::const_iterator 
+         it = _definedAtoms.begin(); it != _definedAtoms.end(); ++it) {
+      YAMLDefinedAtom* atom = *it;   
+      atom->bindTargetReferences();
+    }
+}
+
+Atom* YAMLFile::findAtom(const char* name) {
+  for (std::vector<NameAtomPair>::const_iterator it = _nameToAtomMapping.begin();
+                                    it != _nameToAtomMapping.end(); ++it) {
+    if ( strcmp(name, it->name) == 0 )
+      return it->atom;
+  }
+  llvm::report_fatal_error("reference to atom that does not exist");
+}
+
+void YAMLFile::addDefinedAtom(YAMLDefinedAtom* atom, const char* refName) {
+  _definedAtoms.push_back(atom);
+  assert(refName != NULL);
+  _nameToAtomMapping.push_back(NameAtomPair(refName, atom));
+}
+
+void YAMLFile::addUndefinedAtom(UndefinedAtom* atom) {
+  _undefinedAtoms.push_back(atom);
+  _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
+}
+
 
 class YAMLAtomState {
 public:
   YAMLAtomState();
 
   void setName(const char *n);
+  void setRefName(const char *n);
   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&);
 
   const char *                _name;
+  const char *                _refName;
   const char *                _sectionName;
   unsigned long long          _size;
   uint32_t                    _ordinal;
@@ -482,16 +566,16 @@
   DefinedAtom::Merge          _merge;
   DefinedAtom::DeadStripKind  _deadStrip;
   DefinedAtom::ContentPermissions _permissions;
-  bool                        _internalName;
   bool                        _isThumb;
   bool                        _isAlias;
   bool                        _weakImport;
-  Reference                   _ref;
+  YAMLReference               _ref;
 };
 
 
 YAMLAtomState::YAMLAtomState()
   : _name(NULL)
+  , _refName(NULL)
   , _sectionName(NULL)
   , _size(0)
   , _ordinal(0)
@@ -505,38 +589,31 @@
   , _merge(KeyValues::mergeDefault)
   , _deadStrip(KeyValues::deadStripKindDefault)
   , _permissions(KeyValues::permissionsDefault)
-  , _internalName(KeyValues::internalNameDefault)
   , _isThumb(KeyValues::isThumbDefault)
   , _isAlias(KeyValues::isAliasDefault) 
   , _weakImport(false)
   {
-  _ref.target       = NULL;
-  _ref.addend       = 0;
-  _ref.offsetInAtom = 0;
-  _ref.kind         = 0;
-  _ref.flags        = 0;
-}
+  }
 
 
 void YAMLAtomState::makeAtom(YAMLFile& f) {
   if ( _definition == Atom::definitionRegular ) {
-    DefinedAtom *a = new YAMLDefinedAtom(_ordinal, f, _scope, _type,
+    YAMLDefinedAtom *a = new YAMLDefinedAtom(_ordinal, f, _scope, _type,
                           _sectionChoice, _interpose, _merge, _deadStrip,
-                          _permissions,  _internalName, _isThumb, _isAlias, 
+                          _permissions, _isThumb, _isAlias, 
                           _alignment, _name, _sectionName, _size, _content);
-
-    f._definedAtoms.push_back(a);
+    f.addDefinedAtom(a, _refName ? _refName : _name);
     ++_ordinal;
   }
   else if ( _definition == Atom::definitionUndefined ) {
     UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _weakImport);
-
-    f._undefinedAtoms.push_back(a);
+    f.addUndefinedAtom(a);
     ++_ordinal;
   }
   
   // reset state for next atom
   _name             = NULL;
+  _refName          = NULL;
   _sectionName      = NULL;
   _size             = 0;
   _ordinal          = 0;
@@ -554,17 +631,20 @@
   _isThumb          = KeyValues::isThumbDefault;
   _isAlias          = KeyValues::isAliasDefault;
   _weakImport       = KeyValues::weakImportDefault;
-  _ref.target       = NULL;
-  _ref.addend       = 0;
-  _ref.offsetInAtom = 0;
-  _ref.kind         = 0;
-  _ref.flags        = 0;
+  _ref._target       = NULL;
+  _ref._targetName   = NULL;
+  _ref._addend       = 0;
+  _ref._offsetInAtom = 0;
+  _ref._kind         = 0;
 }
 
 void YAMLAtomState::setName(const char *n) {
   _name = n;
 }
 
+void YAMLAtomState::setRefName(const char *n) {
+  _refName = n;
+}
 
 void YAMLAtomState::setAlign2(const char *s) {
   llvm::StringRef str(s);
@@ -576,33 +656,54 @@
 
 void YAMLAtomState::setFixupKind(const char *s) {
   if (strcmp(s, "pcrel32") == 0)
-    _ref.kind = 1;
+    _ref._kind = 1;
   else if (strcmp(s, "call32") == 0)
-    _ref.kind = 2;
-  else
-    llvm::report_fatal_error("bad fixup kind value");
+    _ref._kind = 2;
+  else {
+    int k;
+    llvm::StringRef(s).getAsInteger(10, k);
+    _ref._kind = k;
+  }
 }
 
 void YAMLAtomState::setFixupOffset(const char *s) {
   if ((s[0] == '0') && (s[1] == 'x'))
-    llvm::StringRef(s).getAsInteger(16, _ref.offsetInAtom);
+    llvm::StringRef(s).getAsInteger(16, _ref._offsetInAtom);
   else
-    llvm::StringRef(s).getAsInteger(10, _ref.offsetInAtom);
+    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);
   // clear for next ref
-  _ref.target       = NULL;
-  _ref.addend       = 0;
-  _ref.offsetInAtom = 0;
-  _ref.kind         = 0;
-  _ref.flags        = 0;
+  _ref._target       = NULL;
+  _ref._targetName   = NULL;
+  _ref._addend       = 0;
+  _ref._offsetInAtom = 0;
+  _ref._kind         = 0;
 }
 
+
+} // anonymous namespace
+
+
+
+
+
+/// parseObjectText - Parse the specified YAML formatted MemoryBuffer
+/// into lld::File object(s) and append each to the specified vector<File*>.
 llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
                                 , std::vector<File *> &result) {
   std::vector<const YAML::Entry *> entries;
@@ -628,6 +729,7 @@
           atomState.makeAtom(*file);
           haveAtom = false;
         }
+        file->bindTargetReferences();
         result.push_back(file);
       }
       file = new YAMLFile();
@@ -663,10 +765,10 @@
           atomState.setName(entry->value);
           haveAtom = true;
         } 
-        else if (strcmp(entry->key, KeyValues::internalNameKeyword) == 0) {
-          atomState._internalName = KeyValues::internalName(entry->value);
+        else if (strcmp(entry->key, KeyValues::refNameKeyword) == 0) {
+          atomState.setRefName(entry->value);
           haveAtom = true;
-        }
+        } 
         else if (strcmp(entry->key, KeyValues::definitionKeyword) == 0) {
           atomState._definition = KeyValues::definition(entry->value);
           haveAtom = true;
@@ -725,8 +827,9 @@
           atomState.setAlign2(entry->value);
           haveAtom = true;
         } 
-        else if (strcmp(entry->key, "fixups") == 0) {
+        else if (strcmp(entry->key, KeyValues::fixupsKeyword) == 0) {
           inFixups = true;
+          
         }
         else {
           return make_error_code(yaml_reader_error::unknown_keyword);
@@ -739,16 +842,22 @@
             haveFixup = false;
           }
         }
-        if (strcmp(entry->key, "kind") == 0) {
+        if (strcmp(entry->key, KeyValues::fixupsKindKeyword) == 0) {
           atomState.setFixupKind(entry->value);
           haveFixup = true;
-        } else if (strcmp(entry->key, "offset") == 0) {
+        } 
+        else if (strcmp(entry->key, KeyValues::fixupsOffsetKeyword) == 0) {
           atomState.setFixupOffset(entry->value);
           haveFixup = true;
-        } else if (strcmp(entry->key, "target") == 0) {
+        } 
+        else if (strcmp(entry->key, KeyValues::fixupsTargetKeyword) == 0) {
           atomState.setFixupTarget(entry->value);
           haveFixup = true;
         }
+        else if (strcmp(entry->key, KeyValues::fixupsAddendKeyword) == 0) {
+          atomState.setFixupAddend(entry->value);
+          haveFixup = true;
+        }
       }
     }
     lastDepth = entry->depth;
@@ -757,10 +866,12 @@
     atomState.makeAtom(*file);
   }
 
+  file->bindTargetReferences();
   result.push_back(file);
   return make_error_code(yaml_reader_error::success);
 }
 
+
 //
 // Fill in vector<File*> from path to input text file.
 //

Modified: lld/trunk/lib/Core/YamlWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlWriter.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlWriter.cpp (original)
+++ lld/trunk/lib/Core/YamlWriter.cpp Tue Feb 14 18:38:09 2012
@@ -15,6 +15,8 @@
 #include "lld/Core/Reference.h"
 
 #include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/DataTypes.h"
@@ -26,50 +28,154 @@
 namespace lld {
 namespace yaml {
 
-class Handler : public File::AtomHandler {
+namespace {
+///
+/// In most cases, atoms names are unambiguous, so references can just
+/// use the atom name as the target (e.g. target: foo).  But in a few 
+/// cases that does not work, so ref-names are added.  These are labels
+/// used only in yaml.  The labels do not exist in the Atom model.
+///
+/// One need for ref-names are when atoms have no user supplied name
+/// (e.g. c-string literal).  Another case is when two object files with
+/// identically named static functions are merged (ld -r) into one object file.
+/// In that case referencing the function by name is ambiguous, so a unique
+/// ref-name is added.
+///
+class RefNameBuilder : public File::AtomHandler, 
+                       public DefinedAtom::ReferenceHandler {
 public:
-  Handler(llvm::raw_ostream &out) : _out(out), _firstAtom(true) { }
+  RefNameBuilder() { }
+
+  virtual void doReference(const Reference& ref) {
+    // create refname for any unnamed reference target
+    if ( ref.target()->name().empty() ) {
+      char* buffer;
+      asprintf(&buffer, "L%03d", _unnamedCounter++);
+      _refNames[ref.target()] = buffer;
+    }
+  }
+
+  virtual void doFile(const File &) { }
+  
+  virtual void doDefinedAtom(const DefinedAtom& atom) {
+    // Build map of atoms names to detect duplicates
+    if ( ! atom.name().empty() )
+      buildDuplicateNameMap(atom);
+    
+    // Find references to unnamed atoms and create ref-names for them.
+    _unnamedCounter = 0;
+    atom.forEachReference(*this);
+  }
+  
+  virtual void doUndefinedAtom(const UndefinedAtom& atom) {
+    buildDuplicateNameMap(atom);
+  }
+  
+  void buildDuplicateNameMap(const Atom& atom) {
+    assert(!atom.name().empty());
+    NameToAtom::iterator pos = _nameMap.find(atom.name());
+    if ( pos != _nameMap.end() ) {
+      // Found name collision, give each a unique ref-name.
+      char* buffer;
+      asprintf(&buffer, "%s.%03d", atom.name().data(), ++_collisionCount);
+      _refNames[&atom] = buffer;
+      const Atom* prevAtom = pos->second;
+      AtomToRefName::iterator pos2 = _refNames.find(prevAtom);
+      if ( pos2 == _refNames.end() ) {
+        // only create ref-name for previous if none already created
+        asprintf(&buffer, "%s.%03d", prevAtom->name().data(), ++_collisionCount);
+        _refNames[prevAtom] = buffer;
+      }
+    }
+    else {
+      // First time we've seen this name, just add it to map.
+      _nameMap[atom.name()] = &atom;
+    }
+  }
+  
+  bool hasRefName(const Atom* atom) {
+     return _refNames.count(atom);
+  }
+  
+  const char* refName(const Atom* atom) {
+     return _refNames.find(atom)->second;
+  }
+  
+private:
+  struct MyMappingInfo {
+    static llvm::StringRef getEmptyKey() { return llvm::StringRef(); }
+    static llvm::StringRef getTombstoneKey() { return llvm::StringRef(" ", 0); }
+    static unsigned getHashValue(llvm::StringRef const val) {
+                                               return llvm::HashString(val); }
+    static bool isEqual(llvm::StringRef const lhs, 
+                        llvm::StringRef const rhs) { return lhs.equals(rhs); }
+  };
+  typedef llvm::DenseMap<llvm::StringRef, const Atom*, MyMappingInfo> NameToAtom;
+  typedef llvm::DenseMap<const Atom*, const char*> AtomToRefName;
+  
+  unsigned int      _collisionCount;
+  unsigned int      _unnamedCounter;
+  NameToAtom        _nameMap;
+  AtomToRefName     _refNames;
+};
+
+
+///
+/// Helper class for writeObjectText() to write out atoms in yaml format.
+///
+class AtomWriter : public File::AtomHandler,
+                   public DefinedAtom::ReferenceHandler {
+public:
+  AtomWriter(RefNameBuilder& rnb, llvm::raw_ostream &out) 
+    : _out(out), _rnb(rnb), _firstAtom(true) { }
 
   virtual void doFile(const class File &) { _firstAtom = true; }
   
   virtual void doDefinedAtom(const class DefinedAtom &atom) {
-      // add blank line between atoms for readability
-      if ( !_firstAtom )
-        _out << "\n";
-      _firstAtom = false;
-        
+    // add blank line between atoms for readability
+    if ( !_firstAtom )
+      _out << "\n";
+    _firstAtom = false;
+    
+    bool hasDash = false;
+    if ( !atom.name().empty() ) {
       _out  << "    - "
             << KeyValues::nameKeyword
             << ":"
             << spacePadding(KeyValues::nameKeyword)
             << atom.name() 
             << "\n";
-    
-    if ( atom.internalName() != KeyValues::internalNameDefault ) {
-      _out  << "      " 
-            << KeyValues::internalNameKeyword 
+      hasDash = true;
+    }
+     
+    if ( _rnb.hasRefName(&atom) ) {
+      _out  << (hasDash ? "      " : "    - ")
+            << KeyValues::refNameKeyword
             << ":"
-            << spacePadding(KeyValues::internalNameKeyword)
-            << KeyValues::internalName(atom.internalName()) 
+            << spacePadding(KeyValues::refNameKeyword)
+            << _rnb.refName(&atom) 
             << "\n";
+      hasDash = true;
     }
     
     if ( atom.definition() != KeyValues::definitionDefault ) {
-      _out  << "      " 
+      _out  << (hasDash ? "      " : "    - ")
             << KeyValues::definitionKeyword 
             << ":"
             << spacePadding(KeyValues::definitionKeyword)
             << KeyValues::definition(atom.definition()) 
             << "\n";
+      hasDash = true;
     }
     
     if ( atom.scope() != KeyValues::scopeDefault ) {
-      _out  << "      " 
+      _out  << (hasDash ? "      " : "    - ")
             << KeyValues::scopeKeyword 
             << ":"
             << spacePadding(KeyValues::scopeKeyword)
             << KeyValues::scope(atom.scope()) 
             << "\n";
+      hasDash = true;
     }
     
      if ( atom.interposable() != KeyValues::interposableDefault ) {
@@ -161,17 +267,51 @@
       _out << " ]\n";
     }
 
-    if (atom.referencesBegin() != atom.referencesEnd()) {
+    _wroteFirstFixup = false;
+    atom.forEachReference(*this);
+  }
+    
+  virtual void doReference(const Reference& ref) {
+    if ( !_wroteFirstFixup ) {
       _out << "      fixups:\n";
-      for (Reference::iterator it = atom.referencesBegin(),
-           end = atom.referencesEnd(); it != end; ++it) {
-        _out << "      - kind:      " << it->kind << "\n";
-        _out << "        offset:    " << it->offsetInAtom << "\n";
-      }
+      _wroteFirstFixup = true;
+    }
+    _out  << "      - "
+          << KeyValues::fixupsOffsetKeyword
+          << ":"
+          << spacePadding(KeyValues::fixupsOffsetKeyword)
+          << ref.offsetInAtom()
+          << "\n";
+    _out  << "        "
+          << KeyValues::fixupsKindKeyword
+          << ":"
+          << spacePadding(KeyValues::fixupsKindKeyword)
+          << ref.kind()
+          << "\n";
+    const Atom* target = ref.target();
+    if ( target != NULL ) {
+      llvm::StringRef refName = target->name();
+      if ( _rnb.hasRefName(target) )
+        refName = _rnb.refName(target);
+      assert(!refName.empty());
+      _out  << "        "
+            << KeyValues::fixupsTargetKeyword
+            << ":"
+            << spacePadding(KeyValues::fixupsTargetKeyword)
+            << refName 
+            << "\n";
+    }
+    if ( ref.addend() != 0 ) {
+      _out  << "        "
+            << KeyValues::fixupsAddendKeyword
+            << ":"
+            << spacePadding(KeyValues::fixupsAddendKeyword)
+            << ref.addend()
+            << "\n";
     }
-
   }
 
+
   virtual void doUndefinedAtom(const class UndefinedAtom &atom) {
       // add blank line between atoms for readability
       if ( !_firstAtom )
@@ -219,11 +359,26 @@
   }
 
   llvm::raw_ostream&  _out;
+  RefNameBuilder      _rnb;
   bool                _firstAtom;
+  bool                _wroteFirstFixup;
 };
 
+} // anonymous namespace
+
+
+
+///
+/// writeObjectText - writes the lld::File object as in YAML
+/// format to the specified stream.
+///
 void writeObjectText(const File &file, llvm::raw_ostream &out) {
-  Handler h(out);
+  // Figure what ref-name labels are needed
+  RefNameBuilder rnb;
+  file.forEachAtom(rnb);
+  
+  // Write out all atoms
+  AtomWriter h(rnb, out);
   out << "---\n";
   out << "atoms:\n";
   file.forEachAtom(h);

Modified: lld/trunk/test/cstring-coalesce.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/cstring-coalesce.objtxt?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/test/cstring-coalesce.objtxt (original)
+++ lld/trunk/test/cstring-coalesce.objtxt Tue Feb 14 18:38:09 2012
@@ -6,28 +6,24 @@
 
 ---
 atoms:
-    - name:              L0
-      internal-name:     true
+    - ref-name:          L0
       scope:             hidden
       type:              c-string
       content:           [ 68, 65, 6c, 6c, 6f, 00 ]
       
-    - name:              L1
-      internal-name:     true
+    - ref-name:          L1
       scope:             hidden
       type:              c-string
       content:           [ 74, 68, 65, 72, 65, 00 ]
 ---
 atoms:
-    - name:              L2
-      internal-name:     true
+    - ref-name:          L2
       scope:             hidden
       type:              c-string
       content:           [ 68, 65, 6c, 6c, 6f, 00 ]
 ---
 atoms:
-    - name:              L2
-      internal-name:     true
+    - ref-name:          L2
       scope:             hidden
       type:              c-string
       content:           [ 74, 68, 65, 72, 65, 00 ]

Added: lld/trunk/test/fixups-addend.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-addend.objtxt?rev=150539&view=auto
==============================================================================
--- lld/trunk/test/fixups-addend.objtxt (added)
+++ lld/trunk/test/fixups-addend.objtxt Tue Feb 14 18:38:09 2012
@@ -0,0 +1,50 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test addends in fixups
+#
+
+---
+atoms:
+    - name:              foo
+      type:              code
+      content:           [ 48, 8D, 3D, 00, 00, 00, 00, 
+                           48, 8D, 3D, 00, 00, 00, 00 ]
+      fixups:
+      - offset:          3
+        kind:            3
+        target:          bar
+        addend:          100
+      - offset:          10
+        kind:            3
+        target:          bar
+        addend:          -50
+  
+    - name:              func
+      type:              code
+      content:           [ 48, 8D, 3D, 00, 00, 00, 00, 
+                           48, 8D, 3D, 00, 00, 00, 00 ]
+      fixups:
+      - offset:          3
+        kind:            3
+        target:          bar
+        addend:          8000000000
+      - offset:          10
+        kind:            3
+        target:          bar
+        addend:          -50
+  
+    - name:              bar
+      definition:        undefined
+
+  
+...
+
+# CHECK:      name: foo
+# CHECK:      fixups:
+# CHECK:      addend: 100
+# CHECK:      addend: -50
+# CHECK:      name: func
+# CHECK:      fixups:
+# CHECK:      addend: 8000000000
+# CHECK:      addend: -50

Added: lld/trunk/test/fixups-dup-named.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-dup-named.objtxt?rev=150539&view=auto
==============================================================================
--- lld/trunk/test/fixups-dup-named.objtxt (added)
+++ lld/trunk/test/fixups-dup-named.objtxt Tue Feb 14 18:38:09 2012
@@ -0,0 +1,31 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test fixups referencing multiple atoms that have the same name
+#
+
+---
+atoms:
+    - name:              foo
+      type:              code
+      content:           [ E8, 00, 00, 00, 00, E8, 00, 00, 00, 00 ]
+      fixups:
+      - offset:          1
+        kind:            3
+        target:          bar_1
+      - offset:          6
+        kind:            3
+        target:          bar_2
+  
+    - name:              bar
+      ref-name:          bar_1
+      scope:             static
+
+    - name:              bar
+      ref-name:          bar_2
+      scope:             static
+  
+
+...
+
+# CHECK:       ...

Added: lld/trunk/test/fixups-named.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-named.objtxt?rev=150539&view=auto
==============================================================================
--- lld/trunk/test/fixups-named.objtxt (added)
+++ lld/trunk/test/fixups-named.objtxt Tue Feb 14 18:38:09 2012
@@ -0,0 +1,35 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test fixups to simple named atoms
+#
+
+---
+atoms:
+    - name:              foo
+      type:              code
+      content:           [ E8, 00, 00, 00, 00, E8, 00, 00, 00, 00 ]
+      fixups:
+      - offset:          1
+        kind:            3
+        target:          bar
+      - offset:          6
+        kind:            3
+        target:          baz
+  
+    - name:              baz
+      scope:             static
+      type:              code
+
+    - name:              bar
+      definition:        undefined
+  
+
+...
+
+# CHECK:      name: foo
+# CHECK:      fixups:
+# CHECK:      target: bar
+# CHECK:      target: baz
+# CHECK:      ...
+

Added: lld/trunk/test/fixups-unnamed.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-unnamed.objtxt?rev=150539&view=auto
==============================================================================
--- lld/trunk/test/fixups-unnamed.objtxt (added)
+++ lld/trunk/test/fixups-unnamed.objtxt Tue Feb 14 18:38:09 2012
@@ -0,0 +1,40 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test fixups to unnamed atoms
+#
+
+---
+atoms:
+    - name:              foo
+      type:              code
+      content:           [ 48, 8D, 3D, 00, 00, 00, 00, 
+                           48, 8D, 3D, 00, 00, 00, 00 ]
+      fixups:
+      - offset:          3
+        kind:            3
+        target:          LC1
+      - offset:          10
+        kind:            3
+        target:          LC2
+  
+
+    - ref-name:          LC1
+      scope:             hidden
+      type:              c-string
+      content:           [ 68, 65, 6c, 6c, 6f, 00 ]
+
+    - ref-name:          LC2
+      scope:             hidden
+      type:              c-string
+      content:           [ 74, 68, 65, 72, 65, 00 ]
+  
+
+...
+
+# CHECK:      name: foo
+# CHECK:      fixups:
+# CHECK:      offset: 3
+# CHECK:      offset: 10
+# CHECK:      ref-name:
+# CHECK:      ref-name:

Removed: lld/trunk/test/internal-name-attributes.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/internal-name-attributes.objtxt?rev=150538&view=auto
==============================================================================
--- lld/trunk/test/internal-name-attributes.objtxt (original)
+++ lld/trunk/test/internal-name-attributes.objtxt (removed)
@@ -1,27 +0,0 @@
-# RUN: lld-core %s | FileCheck %s
-
-#
-# Test that internal-name attributes are preserved
-#
-
----
-atoms:
-    - name:          foo
-      internal-name: false
-    - name:          L0 
-      internal-name: true
-    - name:          L1 
-      internal-name: true
-    - name:          bar 
-...
-
-
-# CHECK:       name: foo
-# CHECK-NOT:   internal-name: false
-# CHECK:       name: L0
-# CHECK:       internal-name: true
-# CHECK:       name: L1
-# CHECK:       internal-name: true
-# CHECK:       name: bar
-# CHECK-NOT:   internal-name: false
-# 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=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Tue Feb 14 18:38:09 2012
@@ -234,8 +234,9 @@
 
   // read native file
   llvm::OwningPtr<lld::File> natFile;
-  parseNativeObjectFileOrSTDIN(tempPath, natFile);
-
+  if ( error(parseNativeObjectFileOrSTDIN(tempPath, natFile)) ) 
+	return 1;
+	
   // write new atom graph out as YAML doc
   yaml::writeObjectText(*natFile, out);
 





More information about the llvm-commits mailing list