Add support for archives and object file caching under MCJIT.

Patch by Andy Kaylor, with minor edits to resolve merge conflicts.

llvm-svn: 196639
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h b/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h
index 9cbde5d..477ebcc 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h
@@ -20,6 +20,10 @@
 
 namespace llvm {
 
+namespace object {
+  class ObjectFile;
+}
+
 class ObjectImageCommon : public ObjectImage {
   ObjectImageCommon(); // = delete
   ObjectImageCommon(const ObjectImageCommon &other); // = delete
@@ -42,6 +46,8 @@
   {
     ObjFile = object::ObjectFile::createObjectFile(Buffer->getMemBuffer());
   }
+  ObjectImageCommon(object::ObjectFile* Input)
+  : ObjectImage(NULL), ObjFile(Input)  {}
   virtual ~ObjectImageCommon() { delete ObjFile; }
 
   virtual object::symbol_iterator begin_symbols() const
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index 161135a4..800a75e 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -82,12 +82,24 @@
   return new ObjectImageCommon(InputBuffer);
 }
 
+ObjectImage *RuntimeDyldImpl::createObjectImageFromFile(ObjectFile *InputObject) {
+  return new ObjectImageCommon(InputObject);
+}
+
+ObjectImage *RuntimeDyldImpl::loadObject(ObjectFile *InputObject) {
+  return loadObject(createObjectImageFromFile(InputObject));
+}
+
 ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) {
+  return loadObject(createObjectImage(InputBuffer));
+} 
+
+ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) {
   MutexGuard locked(lock);
 
-  OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer));
+  OwningPtr<ObjectImage> obj(InputObject);
   if (!obj)
-    report_fatal_error("Unable to create object image from memory buffer!");
+    return NULL;
 
   // Save information about our target
   Arch = (Triple::ArchType)obj->getArch();
@@ -139,7 +151,7 @@
         if (si == obj->end_sections()) continue;
         Check(si->getContents(SectionData));
         Check(si->isText(IsCode));
-        const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() +
+        const uint8_t* SymPtr = (const uint8_t*)InputObject->getData().data() +
                                 (uintptr_t)FileOffset;
         uintptr_t SectOffset = (uintptr_t)(SymPtr -
                                            (const uint8_t*)SectionData.begin());
@@ -563,6 +575,22 @@
   delete Dyld;
 }
 
+ObjectImage *RuntimeDyld::loadObject(ObjectFile *InputObject) {
+  if (!Dyld) {
+    if (InputObject->isELF())
+      Dyld = new RuntimeDyldELF(MM);
+    else if (InputObject->isMachO())
+      Dyld = new RuntimeDyldMachO(MM);
+    else
+      report_fatal_error("Incompatible object format!");
+  } else {
+    if (!Dyld->isCompatibleFile(InputObject))
+      report_fatal_error("Incompatible object format!");
+  }
+
+  return Dyld->loadObject(InputObject);
+}
+
 ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) {
   if (!Dyld) {
     sys::fs::file_magic Type =
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index f2c69fc..68e86d8 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -25,6 +25,8 @@
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/ELF.h"
+#include "llvm/Support/MemoryBuffer.h"
+
 using namespace llvm;
 using namespace llvm::object;
 
@@ -178,6 +180,39 @@
   RegisteredEHFrameSections.clear();
 }
 
+ObjectImage *RuntimeDyldELF::createObjectImageFromFile(object::ObjectFile *ObjFile) {
+  if (!ObjFile)
+    return NULL;
+
+  error_code ec;
+  MemoryBuffer* Buffer = MemoryBuffer::getMemBuffer(ObjFile->getData(), 
+                                                    "", 
+                                                    false);
+
+  if (ObjFile->getBytesInAddress() == 4 && ObjFile->isLittleEndian()) {
+    DyldELFObject<ELFType<support::little, 4, false> > *Obj =
+      new DyldELFObject<ELFType<support::little, 4, false> >(Buffer, ec);
+    return new ELFObjectImage<ELFType<support::little, 4, false> >(NULL, Obj);
+  }
+  else if (ObjFile->getBytesInAddress() == 4 && !ObjFile->isLittleEndian()) {
+    DyldELFObject<ELFType<support::big, 4, false> > *Obj =
+      new DyldELFObject<ELFType<support::big, 4, false> >(Buffer, ec);
+    return new ELFObjectImage<ELFType<support::big, 4, false> >(NULL, Obj);
+  }
+  else if (ObjFile->getBytesInAddress() == 8 && !ObjFile->isLittleEndian()) {
+    DyldELFObject<ELFType<support::big, 8, true> > *Obj =
+      new DyldELFObject<ELFType<support::big, 8, true> >(Buffer, ec);
+    return new ELFObjectImage<ELFType<support::big, 8, true> >(NULL, Obj);
+  }
+  else if (ObjFile->getBytesInAddress() == 8 && ObjFile->isLittleEndian()) {
+    DyldELFObject<ELFType<support::little, 8, true> > *Obj =
+      new DyldELFObject<ELFType<support::little, 8, true> >(Buffer, ec);
+    return new ELFObjectImage<ELFType<support::little, 8, true> >(NULL, Obj);
+  }
+  else
+    llvm_unreachable("Unexpected ELF format");
+}
+
 ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) {
   if (Buffer->getBufferSize() < ELF::EI_NIDENT)
     llvm_unreachable("Unexpected ELF object size");
@@ -1403,4 +1438,9 @@
     return false;
   return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
 }
+
+bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile *Obj) const {
+  return Obj->isELF();
+}
+
 } // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
index 3adf827..181964f 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
@@ -140,7 +140,9 @@
                                     const SymbolTableMap &Symbols,
                                     StubMap &Stubs);
   virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const;
+  virtual bool isCompatibleFile(const object::ObjectFile *Buffer) const;
   virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
+  virtual ObjectImage *createObjectImageFromFile(object::ObjectFile *Obj);
   virtual void registerEHFrames();
   virtual void deregisterEHFrames();
   virtual void finalizeLoad(ObjSectionToIDMap &SectionMap);
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
index 3014b30..183cf6c 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
@@ -311,12 +311,18 @@
   virtual void updateGOTEntries(StringRef Name, uint64_t Addr) {}
 
   virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
+  virtual ObjectImage *createObjectImageFromFile(object::ObjectFile *InputObject);
+
+  // This is the implementation for the two public overloads
+  ObjectImage *loadObject(ObjectImage *InputObject);
+
 public:
   RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}
 
   virtual ~RuntimeDyldImpl();
 
   ObjectImage *loadObject(ObjectBuffer *InputBuffer);
+  ObjectImage *loadObject(object::ObjectFile *InputObject);
 
   void *getSymbolAddress(StringRef Name) {
     // FIXME: Just look up as a function for now. Overly simple of course.
@@ -354,6 +360,7 @@
   StringRef getErrorString() { return ErrorStr; }
 
   virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0;
+  virtual bool isCompatibleFile(const ObjectFile *Obj) const = 0;
 
   virtual void registerEHFrames();
 
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
index 5b92867..780908b 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
@@ -455,4 +455,9 @@
   return false;
 }
 
+bool RuntimeDyldMachO::isCompatibleFile(
+        const object::ObjectFile *Obj) const {
+  return Obj->isMachO();
+}
+
 } // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
index bbf6aa9..0f1c0cb 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
@@ -94,6 +94,7 @@
                                     const SymbolTableMap &Symbols,
                                     StubMap &Stubs);
   virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const;
+  virtual bool isCompatibleFile(const object::ObjectFile *Obj) const;
   virtual void registerEHFrames();
   virtual void finalizeLoad(ObjSectionToIDMap &SectionMap);
 };