[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:55:55 PST 2012


Sorry.  Pilot error.  The commit message was supposed to be:

Implement References. lld::Reference is an abstract base class (like lld::Atom)
with virtual methods for all methods.  To iterate over an Atom's References use
the Atom's forEachReference() method.  Add a bunch of test cases.  Remove
Atom::internalName() method.  Atoms without a user supplied name will have
the Atom::name() method return an empty string. 

-Nick

On Feb 14, 2012, at 4:51 PM, Chandler Carruth wrote:
> I know this is early stage stuff, but others are interested, so commit log messages would be good. ;)
> 
> On Feb 14, 2012 2:45 PM, "Nick Kledzik" <kledzik at apple.com> wrote:
> 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);
> 
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20120214/86755399/attachment.html>


More information about the llvm-commits mailing list