This update does the following:
  * Moves enum Scope from DefinedAtom.h to Atom.h
  * Adds scope method to AbsoluteAtom class
  * Updates YAML to print scope of AbsoluteAtoms
  * Update Native Reader/Writer to handle this new, "attribute"
  * Adds testcase 
Reviewed and approved by Nick Kledzik

llvm-svn: 166189
diff --git a/lld/lib/ReaderWriter/Native/NativeFileFormat.h b/lld/lib/ReaderWriter/Native/NativeFileFormat.h
index 43731f1..d43236f 100644
--- a/lld/lib/ReaderWriter/Native/NativeFileFormat.h
+++ b/lld/lib/ReaderWriter/Native/NativeFileFormat.h
@@ -89,6 +89,7 @@
 enum NativeChunkSignatures {
   NCS_DefinedAtomsV1 = 1,
   NCS_AttributesArrayV1 = 2,
+  NCS_AbsoluteAttributesV1 = 12,
   NCS_UndefinedAtomsV1 = 3,
   NCS_SharedLibraryAtomsV1 = 4,
   NCS_AbsoluteAtomsV1 = 5,
@@ -183,6 +184,7 @@
 //
 struct NativeAbsoluteAtomIvarsV1 {
   uint32_t  nameOffset;
+  uint32_t  attributesOffset;
   uint32_t  reserved;
   uint64_t  value;
 };
diff --git a/lld/lib/ReaderWriter/Native/ReaderNative.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
index bd0c17a..1ad37c7 100644
--- a/lld/lib/ReaderWriter/Native/ReaderNative.cpp
+++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
@@ -175,12 +175,16 @@
 
   virtual const lld::File& file() const;
   virtual StringRef name() const;
-
+  virtual Scope scope() const {
+    const NativeAtomAttributesV1& attr = absAttributes();
+    return (Scope)(attr.scope);
+  }
   virtual uint64_t value() const {
     return _ivarData->value;
   }
 
 private:
+  const NativeAtomAttributesV1& absAttributes() const;
   const File                      *_file;
   const NativeAbsoluteAtomIvarsV1 *_ivarData;
 };
@@ -289,6 +293,9 @@
         case NCS_AbsoluteAtomsV1:
           ec = file->processAbsoluteAtomsV1(base, chunk);
           break;
+        case NCS_AbsoluteAttributesV1:
+          ec = file->processAbsoluteAttributesV1(base, chunk);
+          break;
         case NCS_ReferencesArrayV1:
           ec = file->processReferencesV1(base, chunk);
           break;
@@ -425,6 +432,19 @@
     return make_error_code(native_reader_error::success);
   }
 
+  // set up pointers to attributes array
+  error_code processAbsoluteAttributesV1(const uint8_t *base,
+                                 const NativeChunk *chunk) {
+    this->_absAttributes = base + chunk->fileOffset;
+    this->_absAbsoluteMaxOffset = chunk->fileSize;
+    DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() 
+                    << " chunk AbsoluteAttributesV1:        "
+                    << " count=" << chunk->elementCount
+                    << " chunkSize=" << chunk->fileSize
+                    << "\n");
+    return make_error_code(native_reader_error::success);
+  }
+
   // instantiate array of UndefinedAtoms from v1 ivar data in file
   error_code processUndefinedAtomsV1(const uint8_t *base,
                                      const NativeChunk *chunk) {
@@ -677,6 +697,11 @@
     return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
   }
 
+  const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
+    assert(off < _absAbsoluteMaxOffset);
+    return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
+  }
+
   const uint8_t* content(uint32_t offset, uint32_t size) const {
     const uint8_t* result = _contentStart + offset;
     assert((result+size) <= _contentEnd);
@@ -768,6 +793,8 @@
   AtomArray<UndefinedAtom>        _undefinedAtoms;
   AtomArray<SharedLibraryAtom>    _sharedLibraryAtoms;
   AtomArray<AbsoluteAtom>         _absoluteAtoms;
+  const uint8_t*                  _absAttributes;
+  uint32_t                        _absAbsoluteMaxOffset;
   const uint8_t*                  _attributes;
   uint32_t                        _attributesMaxOffset;
   IvarArray                       _references;
@@ -868,6 +895,9 @@
   return _file->string(_ivarData->nameOffset);
 }
 
+inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
+  return _file->absAttribute(_ivarData->attributesOffset);
+}
 
 inline const Atom* NativeReferenceV1::target() const {
   return _file->target(_ivarData->targetIndex);
diff --git a/lld/lib/ReaderWriter/Native/WriterNative.cpp b/lld/lib/ReaderWriter/Native/WriterNative.cpp
index 50969a6..615dfac 100644
--- a/lld/lib/ReaderWriter/Native/WriterNative.cpp
+++ b/lld/lib/ReaderWriter/Native/WriterNative.cpp
@@ -102,6 +102,11 @@
               _absoluteAtomIvars.size()
               * sizeof(NativeAbsoluteAtomIvarsV1));
     }
+    if (!_absAttributes.empty()) {
+      assert( out.tell() == findChunk(NCS_AbsoluteAttributesV1).fileOffset );
+      out.write((char*)&_absAttributes[0],
+                _absAttributes.size()*sizeof(NativeAtomAttributesV1));
+    }
 
     if (!_stringPool.empty()) {
       assert( out.tell() == findChunk(NCS_Strings).fileOffset );
@@ -164,6 +169,7 @@
     _absoluteAtomIndex[&atom] = _absoluteAtomIvars.size();
     NativeAbsoluteAtomIvarsV1 ivar;
     ivar.nameOffset = getNameOffset(atom);
+    ivar.attributesOffset = getAttributeOffset(atom);
     ivar.reserved = 0;
     ivar.value = atom.value();
     _absoluteAtomIvars.push_back(ivar);
@@ -184,7 +190,7 @@
     if ( hasDefines ) chunkCount += 2;
     if ( hasUndefines ) ++chunkCount;
     if ( hasSharedLibraries ) ++chunkCount;
-    if ( hasAbsolutes ) ++chunkCount;
+    if ( hasAbsolutes ) chunkCount += 2;
     if ( hasReferences ) ++chunkCount;
     if ( hasTargetsTable ) ++chunkCount;
     if ( hasAddendTable ) ++chunkCount;
@@ -247,13 +253,21 @@
 
      // create chunk for shared library atom array
     if ( hasAbsolutes ) {
-      NativeChunk& chsl = chunks[nextIndex++];
-      chsl.signature = NCS_AbsoluteAtomsV1;
-      chsl.fileOffset = nextFileOffset;
-      chsl.fileSize = _absoluteAtomIvars.size() *
+      NativeChunk& chabs = chunks[nextIndex++];
+      chabs.signature = NCS_AbsoluteAtomsV1;
+      chabs.fileOffset = nextFileOffset;
+      chabs.fileSize = _absoluteAtomIvars.size() *
                                         sizeof(NativeAbsoluteAtomIvarsV1);
-      chsl.elementCount = _absoluteAtomIvars.size();
-      nextFileOffset = chsl.fileOffset + chsl.fileSize;
+      chabs.elementCount = _absoluteAtomIvars.size();
+      nextFileOffset = chabs.fileOffset + chabs.fileSize;
+
+      // create chunk for attributes
+      NativeChunk& cha = chunks[nextIndex++];
+      cha.signature = NCS_AbsoluteAttributesV1;
+      cha.fileOffset = nextFileOffset;
+      cha.fileSize = _absAttributes.size()*sizeof(NativeAtomAttributesV1);
+      cha.elementCount = _absAttributes.size();
+      nextFileOffset = cha.fileOffset + cha.fileSize;
     }
 
     // create chunk for symbol strings
@@ -380,6 +394,21 @@
     return result;
   }
 
+  uint32_t getAttributeOffset(const class AbsoluteAtom& atom) {
+    NativeAtomAttributesV1 attrs;
+    computeAbsoluteAttributes(atom, attrs);
+    for(unsigned int i=0; i < _absAttributes.size(); ++i) {
+      if ( !memcmp(&_absAttributes[i], &attrs, sizeof(NativeAtomAttributesV1)) ) {
+        // found that this set of attributes already used, so re-use
+        return i * sizeof(NativeAtomAttributesV1);
+      }
+    }
+    // append new attribute set to end
+    uint32_t result = _absAttributes.size() * sizeof(NativeAtomAttributesV1);
+    _absAttributes.push_back(attrs);
+    return result;
+  }
+
   uint32_t sectionNameOffset(const class DefinedAtom& atom) {
     // if section based on content, then no custom section name available
     if ( atom.sectionChoice() == DefinedAtom::sectionBasedOnContent )
@@ -414,6 +443,11 @@
     attrs.alias             = atom.isAlias();
   }
 
+  void computeAbsoluteAttributes(const class AbsoluteAtom& atom,
+                                                NativeAtomAttributesV1& attrs) {
+    attrs.scope       = atom.scope();
+  }
+
   // add references for this atom in a contiguous block in NCS_ReferencesArrayV1
   uint32_t getReferencesIndex(const DefinedAtom& atom, unsigned& count) {
     count = 0;
@@ -528,6 +562,7 @@
   std::vector<uint8_t>                    _contentPool;
   std::vector<NativeDefinedAtomIvarsV1>   _definedAtomIvars;
   std::vector<NativeAtomAttributesV1>     _attributes;
+  std::vector<NativeAtomAttributesV1>     _absAttributes;
   std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
   std::vector<NativeSharedLibraryAtomIvarsV1> _sharedLibraryAtomIvars;
   std::vector<NativeAbsoluteAtomIvarsV1>  _absoluteAtomIvars;