diff options
author | Eli Bendersky <eli.bendersky@intel.com> | 2012-01-16 08:56:09 +0000 |
---|---|---|
committer | Eli Bendersky <eli.bendersky@intel.com> | 2012-01-16 08:56:09 +0000 |
commit | a66a18505e07a4e72d6fa7e85663937a257577f3 (patch) | |
tree | 1c14e0bc22014ae756f795ee8c9a3108bbcb8df1 | |
parent | 810d6d3354a31f24125abef831e4afccbbbe973d (diff) | |
download | llvm-a66a18505e07a4e72d6fa7e85663937a257577f3.tar.gz llvm-a66a18505e07a4e72d6fa7e85663937a257577f3.tar.bz2 llvm-a66a18505e07a4e72d6fa7e85663937a257577f3.tar.xz |
Adding a basic ELF dynamic loader and MC-JIT for ELF. Functionality is currently basic and will be enhanced with future patches.
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, 463 insertions, 64 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt index 59bdfee3db..002e63cd3b 100644 --- a/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt +++ b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMRuntimeDyld RuntimeDyld.cpp RuntimeDyldMachO.cpp + RuntimeDyldELF.cpp ) diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 33dd705027..b017ebb2dc 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -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 index 0000000000..9ff95ff8b6 --- /dev/null +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -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 diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 7190a3c36f..cff7cbdf28 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -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 { diff --git a/test/ExecutionEngine/2002-12-16-ArgTest.ll b/test/ExecutionEngine/2002-12-16-ArgTest.ll index eba58ccca4..b36feee516 100644 --- a/test/ExecutionEngine/2002-12-16-ArgTest.ll +++ b/test/ExecutionEngine/2002-12-16-ArgTest.ll @@ -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] diff --git a/test/ExecutionEngine/2003-01-04-ArgumentBug.ll b/test/ExecutionEngine/2003-01-04-ArgumentBug.ll index 577226b531..0cc0efd7ea 100644 --- a/test/ExecutionEngine/2003-01-04-ArgumentBug.ll +++ b/test/ExecutionEngine/2003-01-04-ArgumentBug.ll @@ -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] diff --git a/test/ExecutionEngine/2003-01-04-LoopTest.ll b/test/ExecutionEngine/2003-01-04-LoopTest.ll index 61b0a1bd58..e4049a76e0 100644 --- a/test/ExecutionEngine/2003-01-04-LoopTest.ll +++ b/test/ExecutionEngine/2003-01-04-LoopTest.ll @@ -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] diff --git a/test/ExecutionEngine/2003-01-04-PhiTest.ll b/test/ExecutionEngine/2003-01-04-PhiTest.ll index 2bc70d749f..48576e7c83 100644 --- a/test/ExecutionEngine/2003-01-04-PhiTest.ll +++ b/test/ExecutionEngine/2003-01-04-PhiTest.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null define i32 @main() { ; <label>:0 diff --git a/test/ExecutionEngine/2003-01-09-SARTest.ll b/test/ExecutionEngine/2003-01-09-SARTest.ll index 560cd3eae9..ed58e11843 100644 --- a/test/ExecutionEngine/2003-01-09-SARTest.ll +++ b/test/ExecutionEngine/2003-01-09-SARTest.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null ; We were accidentally inverting the signedness of right shifts. Whoops. diff --git a/test/ExecutionEngine/2003-01-10-FUCOM.ll b/test/ExecutionEngine/2003-01-10-FUCOM.ll index 8512f63432..4960e59690 100644 --- a/test/ExecutionEngine/2003-01-10-FUCOM.ll +++ b/test/ExecutionEngine/2003-01-10-FUCOM.ll @@ -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] diff --git a/test/ExecutionEngine/2003-01-15-AlignmentTest.ll b/test/ExecutionEngine/2003-01-15-AlignmentTest.ll index df150373b7..80e19ba193 100644 --- a/test/ExecutionEngine/2003-01-15-AlignmentTest.ll +++ b/test/ExecutionEngine/2003-01-15-AlignmentTest.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null ; XFAIL: arm define i32 @bar(i8* %X) { diff --git a/test/ExecutionEngine/2003-05-06-LivenessClobber.ll b/test/ExecutionEngine/2003-05-06-LivenessClobber.ll index 26429a0509..1e155ee20d 100644 --- a/test/ExecutionEngine/2003-05-06-LivenessClobber.ll +++ b/test/ExecutionEngine/2003-05-06-LivenessClobber.ll @@ -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] diff --git a/test/ExecutionEngine/2003-05-07-ArgumentTest.ll b/test/ExecutionEngine/2003-05-07-ArgumentTest.ll index 566f3ae369..1a1ae5f56b 100644 --- a/test/ExecutionEngine/2003-05-07-ArgumentTest.ll +++ b/test/ExecutionEngine/2003-05-07-ArgumentTest.ll @@ -1,5 +1,6 @@ -; RUN: lli %s test +; RUN: %lli %s test ; XFAIL: arm +; XFAIL: mcjit declare i32 @puts(i8*) diff --git a/test/ExecutionEngine/2003-05-11-PHIRegAllocBug.ll b/test/ExecutionEngine/2003-05-11-PHIRegAllocBug.ll index bcdb11468d..45279adbe5 100644 --- a/test/ExecutionEngine/2003-05-11-PHIRegAllocBug.ll +++ b/test/ExecutionEngine/2003-05-11-PHIRegAllocBug.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null target datalayout = "e-p:32:32" diff --git a/test/ExecutionEngine/2003-06-04-bzip2-bug.ll b/test/ExecutionEngine/2003-06-04-bzip2-bug.ll index 37dae861c9..4342aa4409 100644 --- a/test/ExecutionEngine/2003-06-04-bzip2-bug.ll +++ b/test/ExecutionEngine/2003-06-04-bzip2-bug.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null ; Testcase distilled from 256.bzip2. diff --git a/test/ExecutionEngine/2003-06-05-PHIBug.ll b/test/ExecutionEngine/2003-06-05-PHIBug.ll index f7bd8b7724..03b66c43a1 100644 --- a/test/ExecutionEngine/2003-06-05-PHIBug.ll +++ b/test/ExecutionEngine/2003-06-05-PHIBug.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null ; Testcase distilled from 256.bzip2. diff --git a/test/ExecutionEngine/2003-08-15-AllocaAssertion.ll b/test/ExecutionEngine/2003-08-15-AllocaAssertion.ll index 6c2f34095f..22dd4ccb44 100644 --- a/test/ExecutionEngine/2003-08-15-AllocaAssertion.ll +++ b/test/ExecutionEngine/2003-08-15-AllocaAssertion.ll @@ -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 diff --git a/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll b/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll index 29cbaac4de..b56025a279 100644 --- a/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll +++ b/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll @@ -1,5 +1,6 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null ; XFAIL: arm +; XFAIL: mcjit ; ; Regression Test: EnvironmentTest.ll diff --git a/test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll b/test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll index 6711d4db24..04a5e1741b 100644 --- a/test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll +++ b/test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll @@ -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 diff --git a/test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll b/test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll index fe182116ec..6e48c60db2 100644 --- a/test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll +++ b/test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null ; XFAIL: arm @A = global i32 0 ; <i32*> [#uses=1] diff --git a/test/ExecutionEngine/2005-12-02-TailCallBug.ll b/test/ExecutionEngine/2005-12-02-TailCallBug.ll index 874ce39e66..4d7bd895d2 100644 --- a/test/ExecutionEngine/2005-12-02-TailCallBug.ll +++ b/test/ExecutionEngine/2005-12-02-TailCallBug.ll @@ -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] diff --git a/test/ExecutionEngine/2007-12-10-APIntLoadStore.ll b/test/ExecutionEngine/2007-12-10-APIntLoadStore.ll index c0dc4cf61a..418361163f 100644 --- a/test/ExecutionEngine/2007-12-10-APIntLoadStore.ll +++ b/test/ExecutionEngine/2007-12-10-APIntLoadStore.ll @@ -1,4 +1,4 @@ -; RUN: lli -force-interpreter %s +; RUN: %lli -force-interpreter %s ; PR1836 define i32 @main() { diff --git a/test/ExecutionEngine/2008-06-05-APInt-OverAShr.ll b/test/ExecutionEngine/2008-06-05-APInt-OverAShr.ll index 07cc659cd0..0ab02747ba 100644 --- a/test/ExecutionEngine/2008-06-05-APInt-OverAShr.ll +++ b/test/ExecutionEngine/2008-06-05-APInt-OverAShr.ll @@ -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" diff --git a/test/ExecutionEngine/2010-01-15-UndefValue.ll b/test/ExecutionEngine/2010-01-15-UndefValue.ll index 6e7a392125..01cb21f420 100644 --- a/test/ExecutionEngine/2010-01-15-UndefValue.ll +++ b/test/ExecutionEngine/2010-01-15-UndefValue.ll @@ -1,4 +1,4 @@ -; RUN: lli -force-interpreter=true %s +; RUN: %lli -force-interpreter=true %s define i32 @main() { %a = add i32 0, undef diff --git a/test/ExecutionEngine/fpbitcast.ll b/test/ExecutionEngine/fpbitcast.ll index 47cbb02db1..fa84be4410 100644 --- a/test/ExecutionEngine/fpbitcast.ll +++ b/test/ExecutionEngine/fpbitcast.ll @@ -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: diff --git a/test/ExecutionEngine/hello.ll b/test/ExecutionEngine/hello.ll index 92c26a6c36..4d1d9874bb 100644 --- a/test/ExecutionEngine/hello.ll +++ b/test/ExecutionEngine/hello.ll @@ -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] diff --git a/test/ExecutionEngine/hello2.ll b/test/ExecutionEngine/hello2.ll index 10557ab533..05b4409302 100644 --- a/test/ExecutionEngine/hello2.ll +++ b/test/ExecutionEngine/hello2.ll @@ -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] diff --git a/test/ExecutionEngine/simplesttest.ll b/test/ExecutionEngine/simplesttest.ll index ad38485d6e..85c1715327 100644 --- a/test/ExecutionEngine/simplesttest.ll +++ b/test/ExecutionEngine/simplesttest.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null define i32 @main() { ret i32 0 diff --git a/test/ExecutionEngine/simpletest.ll b/test/ExecutionEngine/simpletest.ll index 797b359c29..83f9b84059 100644 --- a/test/ExecutionEngine/simpletest.ll +++ b/test/ExecutionEngine/simpletest.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null ; XFAIL: arm define i32 @bar() { diff --git a/test/ExecutionEngine/stubs.ll b/test/ExecutionEngine/stubs.ll index 2039ab5a6a..c1134e9ee0 100644 --- a/test/ExecutionEngine/stubs.ll +++ b/test/ExecutionEngine/stubs.ll @@ -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: diff --git a/test/ExecutionEngine/test-arith.ll b/test/ExecutionEngine/test-arith.ll index 354ecd24bc..79f989f726 100644 --- a/test/ExecutionEngine/test-arith.ll +++ b/test/ExecutionEngine/test-arith.ll @@ -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] diff --git a/test/ExecutionEngine/test-branch.ll b/test/ExecutionEngine/test-branch.ll index 7d4fd56059..3ae55d069b 100644 --- a/test/ExecutionEngine/test-branch.ll +++ b/test/ExecutionEngine/test-branch.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null ; test unconditional branch define i32 @main() { diff --git a/test/ExecutionEngine/test-call.ll b/test/ExecutionEngine/test-call.ll index c4131a20f7..eaadbbae0a 100644 --- a/test/ExecutionEngine/test-call.ll +++ b/test/ExecutionEngine/test-call.ll @@ -1,5 +1,6 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null ; XFAIL: arm +; XFAIL: mcjit declare void @exit(i32) diff --git a/test/ExecutionEngine/test-cast.ll b/test/ExecutionEngine/test-cast.ll index f41448cc60..667fa80a48 100644 --- a/test/ExecutionEngine/test-cast.ll +++ b/test/ExecutionEngine/test-cast.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null define i32 @foo() { ret i32 0 diff --git a/test/ExecutionEngine/test-constantexpr.ll b/test/ExecutionEngine/test-constantexpr.ll index d6d90e3e19..d01479a86c 100644 --- a/test/ExecutionEngine/test-constantexpr.ll +++ b/test/ExecutionEngine/test-constantexpr.ll @@ -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 diff --git a/test/ExecutionEngine/test-fp.ll b/test/ExecutionEngine/test-fp.ll index f653660fb8..3411ca1c76 100644 --- a/test/ExecutionEngine/test-fp.ll +++ b/test/ExecutionEngine/test-fp.ll @@ -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] diff --git a/test/ExecutionEngine/test-loadstore.ll b/test/ExecutionEngine/test-loadstore.ll index 7eb57cbf01..b9b779802c 100644 --- a/test/ExecutionEngine/test-loadstore.ll +++ b/test/ExecutionEngine/test-loadstore.ll @@ -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] diff --git a/test/ExecutionEngine/test-logical.ll b/test/ExecutionEngine/test-logical.ll index 710763a30b..05b381bb53 100644 --- a/test/ExecutionEngine/test-logical.ll +++ b/test/ExecutionEngine/test-logical.ll @@ -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] diff --git a/test/ExecutionEngine/test-loop.ll b/test/ExecutionEngine/test-loop.ll index f0e6f7a6f9..e951a14ed2 100644 --- a/test/ExecutionEngine/test-loop.ll +++ b/test/ExecutionEngine/test-loop.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null define i32 @main() { ; <label>:0 diff --git a/test/ExecutionEngine/test-phi.ll b/test/ExecutionEngine/test-phi.ll index c5848a8b5c..c5bdfd513e 100644 --- a/test/ExecutionEngine/test-phi.ll +++ b/test/ExecutionEngine/test-phi.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null ; test phi node @Y = global i32 6 ; <i32*> [#uses=1] diff --git a/test/ExecutionEngine/test-ret.ll b/test/ExecutionEngine/test-ret.ll index beec399607..025f53e5cb 100644 --- a/test/ExecutionEngine/test-ret.ll +++ b/test/ExecutionEngine/test-ret.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null ; test return instructions define void @test1() { diff --git a/test/ExecutionEngine/test-setcond-fp.ll b/test/ExecutionEngine/test-setcond-fp.ll index d1d6d05b33..68276e617a 100644 --- a/test/ExecutionEngine/test-setcond-fp.ll +++ b/test/ExecutionEngine/test-setcond-fp.ll @@ -1,4 +1,4 @@ -; RUN: lli %s > /dev/null +; RUN: %lli %s > /dev/null define i32 @main() { diff --git a/test/ExecutionEngine/test-setcond-int.ll b/test/ExecutionEngine/test-setcond-int.ll index f59d325a5b..48dc02198e 100644 --- a/test/ExecutionEngine/test-setcond-int.ll +++ b/test/ExecutionEngine/test-setcond-int.ll @@ -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] diff --git a/test/ExecutionEngine/test-shift.ll b/test/ExecutionEngine/test-shift.ll index d0fb90a427..590e262068 100644 --- a/test/ExecutionEngine/test-shift.ll +++ b/test/ExecutionEngine/test-shift.ll @@ -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] diff --git a/test/lit.cfg b/test/lit.cfg index 6bc170cdf9..f3302a2d6c 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -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): diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index 23025b4931..0e8d1d8953 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -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; |