Make ObjectFile ownership of the MemoryBuffer optional.

This allows llvm-ar to mmap the input files only once.

llvm-svn: 200040
diff --git a/llvm/lib/Object/Binary.cpp b/llvm/lib/Object/Binary.cpp
index a0c412a..a2f4ec9 100644
--- a/llvm/lib/Object/Binary.cpp
+++ b/llvm/lib/Object/Binary.cpp
@@ -26,12 +26,12 @@
 using namespace object;
 
 Binary::~Binary() {
-  delete Data;
+  if (BufferOwned)
+    delete Data;
 }
 
-Binary::Binary(unsigned int Type, MemoryBuffer *Source)
-  : TypeID(Type)
-  , Data(Source) {}
+Binary::Binary(unsigned int Type, MemoryBuffer *Source, bool BufferOwned)
+  : TypeID(Type), BufferOwned(BufferOwned), Data(Source) {}
 
 StringRef Binary::getData() const {
   return Data->getBuffer();
diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp
index a7b0688..c28f884 100644
--- a/llvm/lib/Object/COFFObjectFile.cpp
+++ b/llvm/lib/Object/COFFObjectFile.cpp
@@ -463,11 +463,12 @@
   return object_error::success;
 }
 
-COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC)
-  : ObjectFile(Binary::ID_COFF, Object), COFFHeader(0), PE32Header(0),
-    DataDirectory(0), SectionTable(0), SymbolTable(0), StringTable(0),
-    StringTableSize(0), ImportDirectory(0), NumberOfImportDirectory(0),
-    ExportDirectory(0) {
+COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC,
+                               bool BufferOwned)
+    : ObjectFile(Binary::ID_COFF, Object, BufferOwned), COFFHeader(0),
+      PE32Header(0), DataDirectory(0), SectionTable(0), SymbolTable(0),
+      StringTable(0), StringTableSize(0), ImportDirectory(0),
+      NumberOfImportDirectory(0), ExportDirectory(0) {
   // Check that we at least have enough room for a header.
   if (!checkSize(Data, EC, sizeof(coff_file_header))) return;
 
@@ -1015,9 +1016,10 @@
   return object_error::success;
 }
 
-ErrorOr<ObjectFile *> ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
+ErrorOr<ObjectFile *> ObjectFile::createCOFFObjectFile(MemoryBuffer *Object,
+                                                       bool BufferOwned) {
   error_code EC;
-  OwningPtr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
+  OwningPtr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC, BufferOwned));
   if (EC)
     return EC;
   return Ret.take();
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp
index 2736bc4..0d90c90 100644
--- a/llvm/lib/Object/ELFObjectFile.cpp
+++ b/llvm/lib/Object/ELFObjectFile.cpp
@@ -17,7 +17,8 @@
 namespace llvm {
 using namespace object;
 
-ErrorOr<ObjectFile *> ObjectFile::createELFObjectFile(MemoryBuffer *Obj) {
+ErrorOr<ObjectFile *> ObjectFile::createELFObjectFile(MemoryBuffer *Obj,
+                                                      bool BufferOwned) {
   std::pair<unsigned char, unsigned char> Ident = getElfArchType(Obj);
   std::size_t MaxAlignment =
     1ULL << countTrailingZeros(uintptr_t(Obj->getBufferStart()));
@@ -27,41 +28,49 @@
   if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB)
 #if !LLVM_IS_UNALIGNED_ACCESS_FAST
     if (MaxAlignment >= 4)
-      R.reset(new ELFObjectFile<ELFType<support::little, 4, false> >(Obj, EC));
+      R.reset(new ELFObjectFile<ELFType<support::little, 4, false> >(
+          Obj, EC, BufferOwned));
     else
 #endif
     if (MaxAlignment >= 2)
-      R.reset(new ELFObjectFile<ELFType<support::little, 2, false> >(Obj, EC));
+      R.reset(new ELFObjectFile<ELFType<support::little, 2, false> >(
+          Obj, EC, BufferOwned));
     else
       llvm_unreachable("Invalid alignment for ELF file!");
   else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB)
 #if !LLVM_IS_UNALIGNED_ACCESS_FAST
     if (MaxAlignment >= 4)
-      R.reset(new ELFObjectFile<ELFType<support::big, 4, false> >(Obj, EC));
+      R.reset(new ELFObjectFile<ELFType<support::big, 4, false> >(Obj, EC,
+                                                                  BufferOwned));
     else
 #endif
     if (MaxAlignment >= 2)
-      R.reset(new ELFObjectFile<ELFType<support::big, 2, false> >(Obj, EC));
+      R.reset(new ELFObjectFile<ELFType<support::big, 2, false> >(Obj, EC,
+                                                                  BufferOwned));
     else
       llvm_unreachable("Invalid alignment for ELF file!");
   else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB)
 #if !LLVM_IS_UNALIGNED_ACCESS_FAST
     if (MaxAlignment >= 8)
-      R.reset(new ELFObjectFile<ELFType<support::big, 8, true> >(Obj, EC));
+      R.reset(new ELFObjectFile<ELFType<support::big, 8, true> >(Obj, EC,
+                                                                 BufferOwned));
     else
 #endif
     if (MaxAlignment >= 2)
-      R.reset(new ELFObjectFile<ELFType<support::big, 2, true> >(Obj, EC));
+      R.reset(new ELFObjectFile<ELFType<support::big, 2, true> >(Obj, EC,
+                                                                 BufferOwned));
     else
       llvm_unreachable("Invalid alignment for ELF file!");
   else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {
 #if !LLVM_IS_UNALIGNED_ACCESS_FAST
     if (MaxAlignment >= 8)
-      R.reset(new ELFObjectFile<ELFType<support::little, 8, true> >(Obj, EC));
+      R.reset(new ELFObjectFile<ELFType<support::little, 8, true> >(
+          Obj, EC, BufferOwned));
     else
 #endif
     if (MaxAlignment >= 2)
-      R.reset(new ELFObjectFile<ELFType<support::little, 2, true> >(Obj, EC));
+      R.reset(new ELFObjectFile<ELFType<support::little, 2, true> >(
+          Obj, EC, BufferOwned));
     else
       llvm_unreachable("Invalid alignment for ELF file!");
   }
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index a930117..2409314 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -419,10 +419,10 @@
   return Sect.flags;
 }
 
-MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
-                                 bool IsLittleEndian, bool Is64bits,
-                                 error_code &ec)
-    : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
+MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian,
+                                 bool Is64bits, error_code &EC,
+                                 bool BufferOwned)
+    : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object, BufferOwned),
       SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) {
   uint32_t LoadCommandCount = this->getHeader().ncmds;
   MachO::LoadCommandType SegmentLoadType = is64Bit() ?
@@ -1582,18 +1582,19 @@
   }
 }
 
-ErrorOr<ObjectFile *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
+ErrorOr<ObjectFile *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer,
+                                                        bool BufferOwned) {
   StringRef Magic = Buffer->getBuffer().slice(0, 4);
   error_code EC;
   OwningPtr<MachOObjectFile> Ret;
   if (Magic == "\xFE\xED\xFA\xCE")
-    Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
+    Ret.reset(new MachOObjectFile(Buffer, false, false, EC, BufferOwned));
   else if (Magic == "\xCE\xFA\xED\xFE")
-    Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
+    Ret.reset(new MachOObjectFile(Buffer, true, false, EC, BufferOwned));
   else if (Magic == "\xFE\xED\xFA\xCF")
-    Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
+    Ret.reset(new MachOObjectFile(Buffer, false, true, EC, BufferOwned));
   else if (Magic == "\xCF\xFA\xED\xFE")
-    Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
+    Ret.reset(new MachOObjectFile(Buffer, true, true, EC, BufferOwned));
   else {
     delete Buffer;
     return object_error::parse_failed;
diff --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp
index 6b14e78..2e6b9e6 100644
--- a/llvm/lib/Object/ObjectFile.cpp
+++ b/llvm/lib/Object/ObjectFile.cpp
@@ -23,9 +23,9 @@
 
 void ObjectFile::anchor() { }
 
-ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source)
-  : Binary(Type, source) {
-}
+ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *Source,
+                       bool BufferOwned)
+    : Binary(Type, Source, BufferOwned) {}
 
 error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI,
                                           uint32_t &Result) const {
@@ -38,8 +38,8 @@
 }
 
 ErrorOr<ObjectFile *> ObjectFile::createObjectFile(MemoryBuffer *Object,
+                                                   bool BufferOwned,
                                                    sys::fs::file_magic Type) {
-  OwningPtr<MemoryBuffer> ScopedObj(Object);
   if (Type == sys::fs::file_magic::unknown)
     Type = sys::fs::identify_magic(Object->getBuffer());
 
@@ -49,12 +49,14 @@
   case sys::fs::file_magic::archive:
   case sys::fs::file_magic::macho_universal_binary:
   case sys::fs::file_magic::windows_resource:
+    if (BufferOwned)
+      delete Object;
     return object_error::invalid_file_type;
   case sys::fs::file_magic::elf_relocatable:
   case sys::fs::file_magic::elf_executable:
   case sys::fs::file_magic::elf_shared_object:
   case sys::fs::file_magic::elf_core:
-    return createELFObjectFile(ScopedObj.take());
+    return createELFObjectFile(Object, BufferOwned);
   case sys::fs::file_magic::macho_object:
   case sys::fs::file_magic::macho_executable:
   case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib:
@@ -65,11 +67,11 @@
   case sys::fs::file_magic::macho_bundle:
   case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub:
   case sys::fs::file_magic::macho_dsym_companion:
-    return createMachOObjectFile(ScopedObj.take());
+    return createMachOObjectFile(Object, BufferOwned);
   case sys::fs::file_magic::coff_object:
   case sys::fs::file_magic::coff_import_library:
   case sys::fs::file_magic::pecoff_executable:
-    return createCOFFObjectFile(ScopedObj.take());
+    return createCOFFObjectFile(Object, BufferOwned);
   }
   llvm_unreachable("Unexpected Object File Type");
 }