Add support for UndefinedAtom in yaml and native format.  Add test cases with undefined atoms

llvm-svn: 149962
diff --git a/lld/lib/Core/NativeWriter.cpp b/lld/lib/Core/NativeWriter.cpp
index e9533be..09fdd9c 100644
--- a/lld/lib/Core/NativeWriter.cpp
+++ b/lld/lib/Core/NativeWriter.cpp
@@ -44,10 +44,13 @@
     if (!_attributes.empty())
       out.write((char*)&_attributes[0],
                 _attributes.size()*sizeof(NativeAtomAttributesV1));
-    if (!_contentPool.empty())
-      out.write((char*)&_contentPool[0], _contentPool.size());
+    if ( !_undefinedAtomIvars.empty() ) 
+      out.write((char*)&_undefinedAtomIvars[0], 
+              _undefinedAtomIvars.size()*sizeof(NativeUndefinedAtomIvarsV1));
     if (!_stringPool.empty())
       out.write(&_stringPool[0], _stringPool.size());
+    if (!_contentPool.empty())
+      out.write((char*)&_contentPool[0], _contentPool.size());
   }
 
 private:
@@ -64,15 +67,22 @@
   
   // visitor routine called by forEachAtom() 
   virtual void doUndefinedAtom(const class UndefinedAtom& atom) {
+    NativeUndefinedAtomIvarsV1 ivar;
+    ivar.nameOffset = getNameOffset(atom);
+    ivar.flags = (atom.weakImport() ? 1 : 0);
+    _undefinedAtomIvars.push_back(ivar);
   }
   
   // visitor routine called by forEachAtom() 
   virtual void doFile(const class File &) {
   }
-  
+
   // fill out native file header and chunk directory
   void makeHeader() {
-    _headerBufferSize = sizeof(NativeFileHeader) + 4*sizeof(NativeChunk);
+    const bool hasUndefines = !_undefinedAtomIvars.empty();
+    const int chunkCount = hasUndefines ? 5 : 4;
+    _headerBufferSize = sizeof(NativeFileHeader) 
+                         + chunkCount*sizeof(NativeChunk);
     _headerBuffer = reinterpret_cast<NativeFileHeader*>
                                (operator new(_headerBufferSize, std::nothrow));
     NativeChunk *chunks =
@@ -82,39 +92,59 @@
     _headerBuffer->endian = NFH_LittleEndian;
     _headerBuffer->architecture = 0;
     _headerBuffer->fileSize = 0;
-    _headerBuffer->chunkCount = 4;
+    _headerBuffer->chunkCount = chunkCount;
+    
     
     // create chunk for atom ivar array
-    NativeChunk& ch0 = chunks[0];
-    ch0.signature = NCS_DefinedAtomsV1;
-    ch0.fileOffset = _headerBufferSize;
-    ch0.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1);
-    ch0.elementCount = _definedAtomIvars.size();
-    // create chunk for attributes
-    NativeChunk& ch1 = chunks[1];
-    ch1.signature = NCS_AttributesArrayV1;
-    ch1.fileOffset = ch0.fileOffset + ch0.fileSize;
-    ch1.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1);
-    ch1.elementCount = _attributes.size();
-    // create chunk for content
-    NativeChunk& ch2 = chunks[2];
-    ch2.signature = NCS_Content;
-    ch2.fileOffset = ch1.fileOffset + ch1.fileSize;
-    ch2.fileSize = _contentPool.size();
-    ch2.elementCount = _contentPool.size();
-    // create chunk for symbol strings
-    NativeChunk& ch3 = chunks[3];
-    ch3.signature = NCS_Strings;
-    ch3.fileOffset = ch2.fileOffset + ch2.fileSize;
-    ch3.fileSize = _stringPool.size();
-    ch3.elementCount = _stringPool.size();
+    int nextIndex = 0;
+    NativeChunk& chd = chunks[nextIndex++];
+    chd.signature = NCS_DefinedAtomsV1;
+    chd.fileOffset = _headerBufferSize;
+    chd.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1);
+    chd.elementCount = _definedAtomIvars.size();
+    uint32_t nextFileOffset = chd.fileOffset + chd.fileSize;
+
+    // create chunk for attributes 
+    NativeChunk& cha = chunks[nextIndex++];
+    cha.signature = NCS_AttributesArrayV1;
+    cha.fileOffset = nextFileOffset;
+    cha.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1);
+    cha.elementCount = _attributes.size();
+    nextFileOffset = cha.fileOffset + cha.fileSize;
     
-    _headerBuffer->fileSize = ch3.fileOffset + ch3.fileSize;
+    // create chunk for undefined atom array
+    if ( hasUndefines ) {
+      NativeChunk& chu = chunks[nextIndex++];
+      chu.signature = NCS_UndefinedAtomsV1;
+      chu.fileOffset = nextFileOffset;
+      chu.fileSize = _undefinedAtomIvars.size() * 
+                                            sizeof(NativeUndefinedAtomIvarsV1);
+      chu.elementCount = _undefinedAtomIvars.size();
+      nextFileOffset = chu.fileOffset + chu.fileSize;
+    }
+    
+    // create chunk for symbol strings
+    NativeChunk& chs = chunks[nextIndex++];
+    chs.signature = NCS_Strings;
+    chs.fileOffset = nextFileOffset;
+    chs.fileSize = _stringPool.size();
+    chs.elementCount = _stringPool.size();
+    nextFileOffset = chs.fileOffset + chs.fileSize;
+    
+    // create chunk for content 
+    NativeChunk& chc = chunks[nextIndex++];
+    chc.signature = NCS_Content;
+    chc.fileOffset = nextFileOffset;
+    chc.fileSize = _contentPool.size();
+    chc.elementCount = _contentPool.size();
+    nextFileOffset = chc.fileOffset + chc.fileSize;
+
+    _headerBuffer->fileSize = nextFileOffset;
   }
 
 
   // append atom name to string pool and return offset
-  uint32_t getNameOffset(const class DefinedAtom& atom) {
+  uint32_t getNameOffset(const Atom& atom) {
     return this->getNameOffset(atom.name());
   }
   
@@ -190,14 +220,15 @@
 
   typedef std::vector<std::pair<llvm::StringRef, uint32_t> > NameToOffsetVector;
 
-  const lld::File&                      _file;
-  NativeFileHeader*                     _headerBuffer;
-  size_t                                _headerBufferSize;
-  std::vector<char>                     _stringPool;
-  std::vector<uint8_t>                  _contentPool;
-  std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars;
-  std::vector<NativeAtomAttributesV1>   _attributes;
-  NameToOffsetVector                    _sectionNames;
+  const lld::File&                        _file;
+  NativeFileHeader*                       _headerBuffer;
+  size_t                                  _headerBufferSize;
+  std::vector<char>                       _stringPool;
+  std::vector<uint8_t>                    _contentPool;
+  std::vector<NativeDefinedAtomIvarsV1>   _definedAtomIvars;
+  std::vector<NativeAtomAttributesV1>     _attributes;
+  std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
+  NameToOffsetVector                      _sectionNames;
 };