Adding a basic ELF dynamic loader and MC-JIT for ELF. Functionality is currently...
authorEli Bendersky <eli.bendersky@intel.com>
Mon, 16 Jan 2012 08:56:09 +0000 (08:56 +0000)
committerEli Bendersky <eli.bendersky@intel.com>
Mon, 16 Jan 2012 08:56:09 +0000 (08:56 +0000)
Patch developed by Andy Kaylor and Daniel Malea. Reviewed on llvm-commits.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148231 91177308-0d34-0410-b5e6-96231b3b80d8

46 files changed:
lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp [new file with mode: 0644]
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
test/ExecutionEngine/2002-12-16-ArgTest.ll
test/ExecutionEngine/2003-01-04-ArgumentBug.ll
test/ExecutionEngine/2003-01-04-LoopTest.ll
test/ExecutionEngine/2003-01-04-PhiTest.ll
test/ExecutionEngine/2003-01-09-SARTest.ll
test/ExecutionEngine/2003-01-10-FUCOM.ll
test/ExecutionEngine/2003-01-15-AlignmentTest.ll
test/ExecutionEngine/2003-05-06-LivenessClobber.ll
test/ExecutionEngine/2003-05-07-ArgumentTest.ll
test/ExecutionEngine/2003-05-11-PHIRegAllocBug.ll
test/ExecutionEngine/2003-06-04-bzip2-bug.ll
test/ExecutionEngine/2003-06-05-PHIBug.ll
test/ExecutionEngine/2003-08-15-AllocaAssertion.ll
test/ExecutionEngine/2003-08-21-EnvironmentTest.ll
test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll
test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll
test/ExecutionEngine/2005-12-02-TailCallBug.ll
test/ExecutionEngine/2007-12-10-APIntLoadStore.ll
test/ExecutionEngine/2008-06-05-APInt-OverAShr.ll
test/ExecutionEngine/2010-01-15-UndefValue.ll
test/ExecutionEngine/fpbitcast.ll
test/ExecutionEngine/hello.ll
test/ExecutionEngine/hello2.ll
test/ExecutionEngine/simplesttest.ll
test/ExecutionEngine/simpletest.ll
test/ExecutionEngine/stubs.ll
test/ExecutionEngine/test-arith.ll
test/ExecutionEngine/test-branch.ll
test/ExecutionEngine/test-call.ll
test/ExecutionEngine/test-cast.ll
test/ExecutionEngine/test-constantexpr.ll
test/ExecutionEngine/test-fp.ll
test/ExecutionEngine/test-loadstore.ll
test/ExecutionEngine/test-logical.ll
test/ExecutionEngine/test-loop.ll
test/ExecutionEngine/test-phi.ll
test/ExecutionEngine/test-ret.ll
test/ExecutionEngine/test-setcond-fp.ll
test/ExecutionEngine/test-setcond-int.ll
test/ExecutionEngine/test-shift.ll
test/lit.cfg
tools/lli/lli.cpp

index 59bdfee3db435c94c4645a287aa26141399cda94..002e63cd3b6b7eec0ba4ec9635f4ce15ba44a940 100644 (file)
@@ -1,4 +1,5 @@
 add_llvm_library(LLVMRuntimeDyld
   RuntimeDyld.cpp
   RuntimeDyldMachO.cpp
+  RuntimeDyldELF.cpp
   )
index 33dd70502798f840efb8bb93ae83b3ea6cb97af2..b017ebb2dcbe8bc843802b274840c2fbb6fb8a01 100644 (file)
@@ -13,6 +13,7 @@
 
 #define DEBUG_TYPE "dyld"
 #include "RuntimeDyldImpl.h"
+#include "llvm/Support/Path.h"
 using namespace llvm;
 using namespace llvm::object;
 
@@ -64,12 +65,36 @@ RuntimeDyld::~RuntimeDyld() {
 
 bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) {
   if (!Dyld) {
-    if (RuntimeDyldMachO::isKnownFormat(InputBuffer))
-      Dyld = new RuntimeDyldMachO(MM);
-    else
-      report_fatal_error("Unknown object format!");
+    sys::LLVMFileType type = sys::IdentifyFileType(
+            InputBuffer->getBufferStart(),
+            static_cast<unsigned>(InputBuffer->getBufferSize()));
+    switch (type) {
+      case sys::ELF_Relocatable_FileType:
+      case sys::ELF_Executable_FileType:
+      case sys::ELF_SharedObject_FileType:
+      case sys::ELF_Core_FileType:
+        Dyld = new RuntimeDyldELF(MM);
+        break;
+      case sys::Mach_O_Object_FileType:
+      case sys::Mach_O_Executable_FileType:
+      case sys::Mach_O_FixedVirtualMemorySharedLib_FileType:
+      case sys::Mach_O_Core_FileType:
+      case sys::Mach_O_PreloadExecutable_FileType:
+      case sys::Mach_O_DynamicallyLinkedSharedLib_FileType:
+      case sys::Mach_O_DynamicLinker_FileType:
+      case sys::Mach_O_Bundle_FileType:
+      case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType:
+      case sys::Mach_O_DSYMCompanion_FileType:
+        Dyld = new RuntimeDyldMachO(MM);
+        break;
+      case sys::Unknown_FileType:
+      case sys::Bitcode_FileType:
+      case sys::Archive_FileType:
+      case sys::COFF_FileType:
+        report_fatal_error("Incompatible object format!");
+    }
   } else {
-    if(!Dyld->isCompatibleFormat(InputBuffer))
+    if (!Dyld->isCompatibleFormat(InputBuffer))
       report_fatal_error("Incompatible object format!");
   }
 
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
new file mode 100644 (file)
index 0000000..9ff95ff
--- /dev/null
@@ -0,0 +1,282 @@
+//===-- RuntimeDyldELF.cpp - Run-time dynamic linker for MC-JIT ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of ELF support for the MC-JIT runtime dynamic linker.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "dyld"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "RuntimeDyldImpl.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/ADT/Triple.h"
+using namespace llvm;
+using namespace llvm::object;
+
+namespace llvm {
+
+namespace {
+
+// FIXME: this function should probably not live here...
+//
+// Returns the name and address of an unrelocated symbol in an ELF section
+void getSymbolInfo(symbol_iterator Sym, uint64_t &Addr, StringRef &Name) {
+  //FIXME: error checking here required to catch corrupt ELF objects...
+  error_code Err = Sym->getName(Name);
+
+  uint64_t AddrInSection;
+  Err = Sym->getAddress(AddrInSection);
+
+  SectionRef empty_section;
+  section_iterator Section(empty_section);
+  Err = Sym->getSection(Section);
+
+  StringRef SectionContents;
+  Section->getContents(SectionContents);
+
+  Addr = reinterpret_cast<uint64_t>(SectionContents.data()) + AddrInSection;
+}
+
+}
+
+bool RuntimeDyldELF::loadObject(MemoryBuffer *InputBuffer) {
+  if (!isCompatibleFormat(InputBuffer))
+    return true;
+
+  OwningPtr<ObjectFile> Obj(ObjectFile::createELFObjectFile(InputBuffer));
+
+  Arch = Obj->getArch();
+
+  // Map address in the Object file image to function names
+  IntervalMap<uint64_t, StringRef>::Allocator A;
+  IntervalMap<uint64_t, StringRef> FuncMap(A);
+
+  // This is a bit of a hack.  The ObjectFile we've just loaded reports
+  // section addresses as 0 and doesn't provide access to the section
+  // offset (from which we could calculate the address.  Instead,
+  // we're storing the address when it comes up in the ST_Debug case
+  // below.
+  //
+  StringMap<uint64_t> DebugSymbolMap;
+
+  symbol_iterator SymEnd = Obj->end_symbols();
+  error_code Err;
+  for (symbol_iterator Sym = Obj->begin_symbols();
+       Sym != SymEnd; Sym.increment(Err)) {
+    SymbolRef::Type Type;
+    Sym->getType(Type);
+    if (Type == SymbolRef::ST_Function) {
+      StringRef Name;
+      uint64_t Addr;
+      getSymbolInfo(Sym, Addr, Name);
+
+      uint64_t Size;
+      Err = Sym->getSize(Size);
+
+      uint8_t *Start;
+      uint8_t *End;
+      Start = reinterpret_cast<uint8_t*>(Addr);
+      End   = reinterpret_cast<uint8_t*>(Addr + Size - 1);
+
+      extractFunction(Name, Start, End);
+      FuncMap.insert(Addr, Addr + Size - 1, Name);
+    } else if (Type == SymbolRef::ST_Debug) {
+      // This case helps us find section addresses
+      StringRef Name;
+      uint64_t Addr;
+      getSymbolInfo(Sym, Addr, Name);
+      DebugSymbolMap[Name] = Addr;
+    }
+  }
+
+  // Iterate through the relocations for this object
+  section_iterator SecEnd = Obj->end_sections();
+  for (section_iterator Sec = Obj->begin_sections();
+       Sec != SecEnd; Sec.increment(Err)) {
+    StringRef SecName;
+    uint64_t  SecAddr;
+    Sec->getName(SecName);
+    // Ignore sections that aren't in our map
+    if (DebugSymbolMap.find(SecName) == DebugSymbolMap.end()) {
+      continue;
+    }
+    SecAddr = DebugSymbolMap[SecName];
+    relocation_iterator RelEnd = Sec->end_relocations();
+    for (relocation_iterator Rel = Sec->begin_relocations();
+         Rel != RelEnd; Rel.increment(Err)) {
+      uint64_t RelOffset;
+      uint64_t RelType;
+      int64_t RelAddend;
+      SymbolRef RelSym;
+      StringRef SymName;
+      uint64_t SymAddr;
+      uint64_t SymOffset;
+
+      Rel->getAddress(RelOffset);
+      Rel->getType(RelType);
+      Rel->getAdditionalInfo(RelAddend);
+      Rel->getSymbol(RelSym);
+      RelSym.getName(SymName);
+      RelSym.getAddress(SymAddr);
+      RelSym.getFileOffset(SymOffset);
+
+      // If this relocation is inside a function, we want to store the
+      // function name and a function-relative offset
+      IntervalMap<uint64_t, StringRef>::iterator ContainingFunc
+        = FuncMap.find(SecAddr + RelOffset);
+      if (ContainingFunc.valid()) {
+        // Re-base the relocation to make it relative to the target function
+        RelOffset = (SecAddr + RelOffset) - ContainingFunc.start();
+        Relocations[SymName].push_back(RelocationEntry(ContainingFunc.value(),
+                                                       RelOffset,
+                                                       RelType,
+                                                       RelAddend,
+                                                       true));
+      } else {
+        Relocations[SymName].push_back(RelocationEntry(SecName,
+                                                       RelOffset,
+                                                       RelType,
+                                                       RelAddend,
+                                                       false));
+      }
+    }
+  }
+  return false;
+}
+
+void RuntimeDyldELF::resolveX86_64Relocation(StringRef Name,
+                                             uint8_t *Addr,
+                                             const RelocationEntry &RE) {
+  uint8_t *TargetAddr;
+  if (RE.IsFunctionRelative) {
+    StringMap<sys::MemoryBlock>::iterator ContainingFunc
+      = Functions.find(RE.Target);
+    assert(ContainingFunc != Functions.end()
+           && "Function for relocation not found");
+    TargetAddr = reinterpret_cast<uint8_t*>(ContainingFunc->getValue().base()) +
+                 RE.Offset;
+  } else {
+    // FIXME: Get the address of the target section and add that to RE.Offset
+    assert(0 && ("Non-function relocation not implemented yet!"));
+  }
+
+  switch (RE.Type) {
+  default:
+    assert(0 && ("Relocation type not implemented yet!"));
+  break;
+  case ELF::R_X86_64_64: {
+    uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
+    *Target = Addr + RE.Addend;
+    break;
+  }
+  case ELF::R_X86_64_32:
+  case ELF::R_X86_64_32S: {
+    uint64_t Value = reinterpret_cast<uint64_t>(Addr) + RE.Addend;
+    // FIXME: Handle the possibility of this assertion failing
+    assert((RE.Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000)) ||
+           (RE.Type == ELF::R_X86_64_32S &&
+            (Value & 0xFFFFFFFF00000000) == 0xFFFFFFFF00000000));
+    uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
+    uint32_t *Target = reinterpret_cast<uint32_t*>(TargetAddr);
+    *Target = TruncatedAddr;
+    break;
+  }
+  case ELF::R_X86_64_PC32: {
+    uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
+    uint64_t RealOffset = *Placeholder +
+                           reinterpret_cast<uint64_t>(Addr) +
+                           RE.Addend - reinterpret_cast<uint64_t>(TargetAddr);
+    assert((RealOffset & 0xFFFFFFFF) == RealOffset);
+    uint32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
+    *Placeholder = TruncOffset;
+    break;
+  }
+  }
+}
+
+void RuntimeDyldELF::resolveX86Relocation(StringRef Name,
+                                          uint8_t *Addr,
+                                          const RelocationEntry &RE) {
+  uint8_t *TargetAddr;
+  if (RE.IsFunctionRelative) {
+    StringMap<sys::MemoryBlock>::iterator ContainingFunc
+      = Functions.find(RE.Target);
+    assert(ContainingFunc != Functions.end()
+           && "Function for relocation not found");
+    TargetAddr = reinterpret_cast<uint8_t*>(
+      ContainingFunc->getValue().base()) + RE.Offset;
+  } else {
+    // FIXME: Get the address of the target section and add that to RE.Offset
+    assert(0 && ("Non-function relocation not implemented yet!"));
+  }
+
+  switch (RE.Type) {
+  case ELF::R_386_32: {
+    uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
+    *Target = Addr + RE.Addend;
+    break;
+  }
+  case ELF::R_386_PC32: {
+    uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
+    uint32_t RealOffset = *Placeholder + reinterpret_cast<uintptr_t>(Addr) +
+                           RE.Addend - reinterpret_cast<uintptr_t>(TargetAddr);
+    *Placeholder = RealOffset;
+    break;
+    }
+    default:
+      // There are other relocation types, but it appears these are the
+      //  only ones currently used by the LLVM ELF object writer
+      assert(0 && ("Relocation type not implemented yet!"));
+      break;
+  }
+}
+
+void RuntimeDyldELF::resolveArmRelocation(StringRef Name,
+                                          uint8_t *Addr,
+                                          const RelocationEntry &RE) {
+}
+
+void RuntimeDyldELF::resolveRelocation(StringRef Name,
+                                       uint8_t *Addr,
+                                       const RelocationEntry &RE) {
+  switch (Arch) {
+  case Triple::x86_64:
+    resolveX86_64Relocation(Name, Addr, RE);
+    break;
+  case Triple::x86:
+    resolveX86Relocation(Name, Addr, RE);
+    break;
+  case Triple::arm:
+    resolveArmRelocation(Name, Addr, RE);
+    break;
+  default:
+    assert(0 && "Unsupported CPU type!");
+    break;
+  }
+}
+
+void RuntimeDyldELF::reassignSymbolAddress(StringRef Name, uint8_t *Addr) {
+  SymbolTable[Name] = Addr;
+
+  RelocationList &Relocs = Relocations[Name];
+  for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
+    RelocationEntry &RE = Relocs[i];
+    resolveRelocation(Name, Addr, RE);
+  }
+}
+
+bool RuntimeDyldELF::isCompatibleFormat(const MemoryBuffer *InputBuffer) const {
+  StringRef Magic = InputBuffer->getBuffer().slice(0, ELF::EI_NIDENT);
+  return (memcmp(Magic.data(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
+}
+} // namespace llvm
index 7190a3c36fe9e35df106f6730ecd8a6f0bab3616..cff7cbdf28ad996fc77e3035f2705535d024a1c4 100644 (file)
@@ -94,6 +94,66 @@ public:
   virtual bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const = 0;
 };
 
+class RuntimeDyldELF : public RuntimeDyldImpl {
+    // For each symbol, keep a list of relocations based on it. Anytime
+    // its address is reassigned (the JIT re-compiled the function, e.g.),
+    // the relocations get re-resolved.
+    struct RelocationEntry {
+      // Function or section this relocation is contained in.
+      std::string Target;
+      // Offset into the target function or section for the relocation.
+      uint32_t    Offset;
+      // Relocation type
+      uint32_t    Type;
+      // Addend encoded in the instruction itself, if any.
+      int32_t     Addend;
+      // Has the relocation been recalcuated as an offset within a function?
+      bool        IsFunctionRelative;
+      // Has this relocation been resolved previously?
+      bool        isResolved;
+
+      RelocationEntry(StringRef t,
+                      uint32_t offset,
+                      uint32_t type,
+                      int32_t addend,
+                      bool isFunctionRelative)
+        : Target(t)
+        , Offset(offset)
+        , Type(type)
+        , Addend(addend)
+        , IsFunctionRelative(isFunctionRelative)
+        , isResolved(false) { }
+    };
+    typedef SmallVector<RelocationEntry, 4> RelocationList;
+    StringMap<RelocationList> Relocations;
+    unsigned Arch;
+
+    void resolveX86_64Relocation(StringRef Name,
+                                 uint8_t *Addr,
+                                 const RelocationEntry &RE);
+
+    void resolveX86Relocation(StringRef Name,
+                              uint8_t *Addr,
+                              const RelocationEntry &RE);
+
+    void resolveArmRelocation(StringRef Name,
+                              uint8_t *Addr,
+                              const RelocationEntry &RE);
+
+    void resolveRelocation(StringRef Name,
+                           uint8_t *Addr,
+                           const RelocationEntry &RE);
+
+public:
+  RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
+
+  bool loadObject(MemoryBuffer *InputBuffer);
+
+  void reassignSymbolAddress(StringRef Name, uint8_t *Addr);
+
+  bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const;
+};
+
 
 class RuntimeDyldMachO : public RuntimeDyldImpl {
 
index eba58ccca423599966aa5c69d548f3f750d70dbc..b36feee516abf6d1a7665344d5db4541e0f5dfe2 100644 (file)
@@ -1,4 +1,5 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
+; XFAIL: mcjit
 
 @.LC0 = internal global [10 x i8] c"argc: %d\0A\00"            ; <[10 x i8]*> [#uses=1]
 
index 577226b5318b4347ae8f6f7d9a6699ca00b37b11..0cc0efd7eaf78eba51dac50723f7ad3710e44629 100644 (file)
@@ -1,5 +1,6 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
+; XFAIL: mcjit
 
 define i32 @foo(i32 %X, i32 %Y, double %A) {
        %cond212 = fcmp une double %A, 1.000000e+00             ; <i1> [#uses=1]
index 61b0a1bd58ee17930e71a324384c4f98422e5753..e4049a76e0693852c479b45f9c68be7f63633b02 100644 (file)
@@ -1,5 +1,6 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
+; XFAIL: mcjit
 
 define i32 @main() {
        call i32 @mylog( i32 4 )                ; <i32>:1 [#uses=0]
index 2bc70d749f504f723284cddb304234606c2f25c6..48576e7c83e68d52b175ed171209c8c4bde3238d 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 define i32 @main() {
 ; <label>:0
index 560cd3eae9a2604a4adecfc84012304b81454ec5..ed58e118437769e014f56fb18189c26171336ee7 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 ; We were accidentally inverting the signedness of right shifts.  Whoops.
 
index 8512f634323f5bf0c161edd883895990e9bae455..4960e5969005aef36078d902e5a4e270f0cb2fce 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 define i32 @main() {
        %X = fadd double 0.000000e+00, 1.000000e+00             ; <double> [#uses=1]
index df150373b7273d93fe28bedce93ac72ffe5f2dc0..80e19ba19320e1115d5941bd9155b25f5cfb6c81 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
 
 define i32 @bar(i8* %X) {
index 26429a05090fda18f12199e47628d3b088c18ae4..1e155ee20d54f2770f2bd11b195d892f80c66bc2 100644 (file)
@@ -1,7 +1,8 @@
 ; This testcase should return with an exit code of 1.
 ;
-; RUN: not lli %s
+; RUN: not %lli %s
 ; XFAIL: arm
+; XFAIL: mcjit
 
 @test = global i64 0           ; <i64*> [#uses=1]
 
index 566f3ae3693b185df455c8fefe6f0bd33a2d1d96..1a1ae5f56b9b683bb8e3bf685d44102464d100b8 100644 (file)
@@ -1,5 +1,6 @@
-; RUN: lli %s test
+; RUN: %lli %s test
 ; XFAIL: arm
+; XFAIL: mcjit
 
 declare i32 @puts(i8*)
 
index bcdb11468dcaaa520a56ef45d381bf4bf3765aa0..45279adbe57b33a3ea9dc4a7f463ec19386834bf 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 target datalayout = "e-p:32:32"
 
index 37dae861c983ba5223da0692dd574d8b2571dbc4..4342aa4409757e401d9a80bdf48fc21b4f052c07 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 ; Testcase distilled from 256.bzip2.
 
index f7bd8b77244f644c91a9b2014fb5283f12be40bb..03b66c43a1ced7b835366751ea23ae10720572b4 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 ; Testcase distilled from 256.bzip2.
 
index 6c2f34095f6096e9f904484515e57c352b695790..22dd4ccb44cf575d0b83f7965fe7a43f4fbb62bb 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
 
 ; This testcase failed to work because two variable sized allocas confused the
index 29cbaac4deb657ef060821e33e2bbe59d9e0058d..b56025a27964cc5db1ddb56dbee0395505a9a0bc 100644 (file)
@@ -1,5 +1,6 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
+; XFAIL: mcjit
 
 ;
 ; Regression Test: EnvironmentTest.ll
index 6711d4db245a2055f6bf438c8d86fc07de91a467..04a5e1741bb0f768152046b5cabdc23afad96ceb 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
 
 ; This testcase exposes a bug in the local register allocator where it runs out
index fe182116ec9ea9fea06357b2ae5e27166762738c..6e48c60db26270b632973005cd4a8e69e6202e0e 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
 
 @A = global i32 0              ; <i32*> [#uses=1]
index 874ce39e662f79368a8e08a40be6620bec736c41..4d7bd895d24e1c8c90adb1cfc1ec0103d88763d5 100644 (file)
@@ -1,6 +1,7 @@
 ; PR672
-; RUN: lli %s
+; RUN: %lli %s
 ; XFAIL: arm
+; XFAIL: mcjit-ia32
 
 define i32 @main() {
        %f = bitcast i32 (i32, i32*, i32)* @check_tail to i32*          ; <i32*> [#uses=1]
index c0dc4cf61abb0a3306433c9d59d6d290febf808a..418361163fcf3b0a5dd9bed0915d30cabb7f1cf2 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli -force-interpreter %s
+; RUN: %lli -force-interpreter %s
 ; PR1836
 
 define i32 @main() {
index 07cc659cd0409b1e637f118f0b6d27eae8814fc4..0ab02747ba1dbec0d63438a9763da0a4da2350c0 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli -force-interpreter=true %s | grep 1
+; RUN: %lli -force-interpreter=true %s | grep 1
 
 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
 target triple = "i686-pc-linux-gnu"
index 6e7a392125e18802be93a9dd55297201e008478a..01cb21f4206dd35030fc3f604408967b6b09c336 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli -force-interpreter=true %s
+; RUN: %lli -force-interpreter=true %s
 
 define i32 @main() {
        %a = add i32 0, undef
index 47cbb02db180647f05ac936951f16606e77eaaa9..fa84be44101032217d7ce41d5e0263bbf0abc0d2 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli -force-interpreter=true %s | grep 40091eb8
+; RUN: %lli -force-interpreter=true %s | grep 40091eb8
 ;
 define i32 @test(double %x) {
 entry:
index 92c26a6c365cc664b523577c2bc1f295c37a4ce4..4d1d9874bbfa11478061583689a9dd32aef21119 100644 (file)
@@ -1,5 +1,6 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
+; XFAIL: mcjit
 
 @.LC0 = internal global [12 x i8] c"Hello World\00"            ; <[12 x i8]*> [#uses=1]
 
index 10557ab5336f0e97ddd6b1404f16213e53b91efd..05b4409302f1b85a59a87cbfdc4cc91b1fbac296 100644 (file)
@@ -1,5 +1,6 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
+; XFAIL: mcjit
 
 @X = global i32 7              ; <i32*> [#uses=0]
 @msg = internal global [13 x i8] c"Hello World\0A\00"          ; <[13 x i8]*> [#uses=1]
index ad38485d6e02ecdf1e4bab8c82a971d5f2eb69ff..85c171532752f24a2fd30f1f0178ccab47385184 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 define i32 @main() {
        ret i32 0
index 797b359c29aa582387ab1ed8e7f34084e57c9b65..83f9b8405902b23edb8ebb256acfe554811723f9 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
 
 define i32 @bar() {
index 2039ab5a6a3c18f7e034c81aeb1c838bcda8abd1..c1134e9ee0635ff6325fbcefe29eefbaf4190bdb 100644 (file)
@@ -1,5 +1,6 @@
-; RUN: lli -disable-lazy-compilation=false %s
+; RUN: %lli -disable-lazy-compilation=false %s
 ; XFAIL: arm
+; XFAIL: mcjit
 
 define i32 @main() nounwind {
 entry:
index 354ecd24bc83bffcde2484a7d898423592dbab0c..79f989f7265b71a595ab9373569b7f5c79d72ea3 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 define i32 @main() {
        %A = add i8 0, 12               ; <i8> [#uses=1]
index 7d4fd5605922dd30403b3c54fbdf35e171aa782e..3ae55d069b3de066b99788f958f496a347ff1c01 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 ; test unconditional branch
 define i32 @main() {
index c4131a20f7951d72e0e810be718593cebd4a29d4..eaadbbae0a7c909db37f34abb8540eb8ce25cad2 100644 (file)
@@ -1,5 +1,6 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
+; XFAIL: mcjit
 
 declare void @exit(i32)
 
index f41448cc60aa62b5ed9a50704b271b924a53a59f..667fa80a48971ead9fccf3a0ccfdeea64104c047 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 define i32 @foo() {
        ret i32 0
index d6d90e3e1982c1438763f4b44ce5e5467eb5f997..d01479a86cdc877a95aa73dcc66ea73de83af0a7 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 ; This tests to make sure that we can evaluate weird constant expressions
 
index f653660fb83257b3eafa5171bfd0194dce84619c..3411ca1c766ca5a60505c1c88224362885a9d0eb 100644 (file)
@@ -1,4 +1,5 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
+; XFAIL: mcjit
 
 define double @test(double* %DP, double %Arg) {
        %D = load double* %DP           ; <double> [#uses=1]
index 7eb57cbf0102e312d8b53a70d10889c29adc2075..b9b779802cceb8d72cbc32c3ba3111355eb5f89b 100644 (file)
@@ -1,5 +1,6 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 ; XFAIL: arm
+; XFAIL: mcjit-ia32
 
 define void @test(i8* %P, i16* %P.upgrd.1, i32* %P.upgrd.2, i64* %P.upgrd.3) {
        %V = load i8* %P                ; <i8> [#uses=1]
index 710763a30bd87dc2d99c79c82f68283305521f5b..05b381bb53c22872b97a4d5335a72655814d8365 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 define i32 @main() {
        %A = and i8 4, 8                ; <i8> [#uses=2]
index f0e6f7a6f9c115b7733d35a416c9ed78e50aef4f..e951a14ed2e94dbd4555c439bd5c853d448a929c 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 define i32 @main() {
 ; <label>:0
index c5848a8b5cce9368ffc431b4a269e0e8732935f4..c5bdfd513edca46cd33bc4a65c7fd449e4f62440 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 ; test phi node
 @Y = global i32 6              ; <i32*> [#uses=1]
index beec3996075133eb2ce2ca6ff333f628c395749e..025f53e5cb9e44d4a2bbba881b33f64d85c0c352 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 ; test return instructions
 define void @test1() {
index d1d6d05b33521aff202e6446ece73e8de5693b96..68276e617a4a1bf5188b6e725566f3593d39b9c7 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 
 define i32 @main() {
index f59d325a5b5912c7ac0f76f7f25d26e246e89f70..48dc02198ec0e18419e6a00bf8787d33c60e47de 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 define i32 @main() {
        %int1 = add i32 0, 0            ; <i32> [#uses=6]
index d0fb90a4275058d08287e65dfc0f0cc354252588..590e2620689f1369f38d71e079a1f25e49b7699c 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: lli %s > /dev/null
+; RUN: %lli %s > /dev/null
 
 define i32 @main() {
        %shamt = add i8 0, 1            ; <i8> [#uses=8]
index 6bc170cdf944afd7cff1dc49e7989a2f18eabdca..f3302a2d6c078eab3d9fc026641d62ea33099783 100644 (file)
@@ -141,6 +141,29 @@ for line in open(os.path.join(config.llvm_obj_root, 'test', 'site.exp')):
     if m:
         site_exp[m.group(1)] = m.group(2)
 
+# Provide target_triple for use in XFAIL and XTARGET.
+config.target_triple = site_exp['target_triplet']
+
+# When running under valgrind, we mangle '-vg' or '-vg_leak' onto the end of the
+# triple so we can check it with XFAIL and XTARGET.
+config.target_triple += lit.valgrindTriple
+
+# Process jit implementation option
+jit_impl_cfg = lit.params.get('jit_impl', None)
+if jit_impl_cfg == 'mcjit':
+  # When running with mcjit, mangle -mcjit into target triple
+  # and add -use-mcjit flag to lli invocation
+  if 'i686' in config.target_triple:
+    config.target_triple += jit_impl_cfg + '-ia32'
+  elif 'x86_64' in config.target_triple:
+    config.target_triple += jit_impl_cfg + '-ia64'
+  else:
+    config.target_triple += jit_impl_cfg
+
+  config.substitutions.append( ('%lli', 'lli -use-mcjit') )
+else:
+  config.substitutions.append( ('%lli', 'lli') )
+
 # Add substitutions.
 for sub in ['link', 'shlibext', 'ocamlopt', 'llvmshlibdir']:
     config.substitutions.append(('%' + sub, site_exp[sub]))
@@ -197,13 +220,6 @@ for pattern in [r"\bbugpoint\b(?!-)",   r"(?<!/|-)\bclang\b(?!-)",
 
 excludes = []
 
-# Provide target_triple for use in XFAIL and XTARGET.
-config.target_triple = site_exp['target_triplet']
-
-# When running under valgrind, we mangle '-vg' or '-vg_leak' onto the end of the
-# triple so we can check it with XFAIL and XTARGET.
-config.target_triple += lit.valgrindTriple
-
 # Provide llvm_supports_target for use in local configs.
 targets = set(site_exp["TARGETS_TO_BUILD"].split())
 def llvm_supports_target(name):
index 23025b4931245ac890459c52d78143022f03664d..0e8d1d8953c183c1081186c70ee61f1898525651 100644 (file)
@@ -95,12 +95,12 @@ namespace {
                      "of the executable"),
             cl::value_desc("function"),
             cl::init("main"));
-  
+
   cl::opt<std::string>
   FakeArgv0("fake-argv0",
             cl::desc("Override the 'argv[0]' value passed into the executing"
                      " program"), cl::value_desc("executable"));
-  
+
   cl::opt<bool>
   DisableCoreFiles("disable-core-files", cl::Hidden,
                    cl::desc("Disable emission of core files if possible"));
@@ -159,7 +159,7 @@ static void do_shutdown() {
 int main(int argc, char **argv, char * const *envp) {
   sys::PrintStackTraceOnErrorSignal();
   PrettyStackTraceProgram X(argc, argv);
-  
+
   LLVMContext &Context = getGlobalContext();
   atexit(do_shutdown);  // Call llvm_shutdown() on exit.
 
@@ -174,7 +174,7 @@ int main(int argc, char **argv, char * const *envp) {
   // If the user doesn't want core files, disable them.
   if (DisableCoreFiles)
     sys::Process::PreventCoreFiles();
-  
+
   // Load the bitcode...
   SMDiagnostic Err;
   Module *Mod = ParseIRFile(InputFile, Err, Context);
@@ -210,9 +210,11 @@ int main(int argc, char **argv, char * const *envp) {
   if (!TargetTriple.empty())
     Mod->setTargetTriple(Triple::normalize(TargetTriple));
 
-  // Enable MCJIT, if desired.
-  if (UseMCJIT)
+  // Enable MCJIT if desired.
+  if (UseMCJIT && !ForceInterpreter) {
     builder.setUseMCJIT(true);
+    builder.setJITMemoryManager(JITMemoryManager::CreateDefaultMemManager());
+  }
 
   CodeGenOpt::Level OLvl = CodeGenOpt::Default;
   switch (OptLevel) {
@@ -265,15 +267,15 @@ int main(int argc, char **argv, char * const *envp) {
     return -1;
   }
 
-  // If the program doesn't explicitly call exit, we will need the Exit 
-  // function later on to make an explicit call, so get the function now. 
+  // If the program doesn't explicitly call exit, we will need the Exit
+  // function later on to make an explicit call, so get the function now.
   Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context),
                                                     Type::getInt32Ty(Context),
                                                     NULL);
-  
+
   // Reset errno to zero on entry to main.
   errno = 0;
+
   // Run static constructors.
   EE->runStaticConstructorsDestructors(false);
 
@@ -290,8 +292,8 @@ int main(int argc, char **argv, char * const *envp) {
 
   // Run static destructors.
   EE->runStaticConstructorsDestructors(true);
-  
-  // If the program didn't call exit explicitly, we should call it now. 
+
+  // If the program didn't call exit explicitly, we should call it now.
   // This ensures that any atexit handlers get called correctly.
   if (Function *ExitF = dyn_cast<Function>(Exit)) {
     std::vector<GenericValue> Args;