Eric Christopher aa5b9c0f6f Temporarily Revert "Nuke the old JIT." as it's not quite ready to
be deleted. This will be reapplied as soon as possible and before
the 3.6 branch date at any rate.

Approved by Jim Grosbach, Lang Hames, Rafael Espindola.

This reverts commits r215111, 215115, 215116, 215117, 215136.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215154 91177308-0d34-0410-b5e6-96231b3b80d8
2014-08-07 22:02:54 +00:00

191 lines
5.8 KiB
C++

//===- MultiJITTest.cpp - Unit tests for instantiating multiple JITs ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
#include <vector>
using namespace llvm;
namespace {
// ARM, PowerPC and SystemZ tests disabled pending fix for PR10783.
#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \
&& !defined(__aarch64__)
bool LoadAssemblyInto(Module *M, const char *assembly) {
SMDiagnostic Error;
bool success =
nullptr != ParseAssemblyString(assembly, M, Error, M->getContext());
std::string errMsg;
raw_string_ostream os(errMsg);
Error.print("", os);
EXPECT_TRUE(success) << os.str();
return success;
}
void createModule1(LLVMContext &Context1, Module *&M1, Function *&FooF1) {
M1 = new Module("test1", Context1);
LoadAssemblyInto(M1,
"define i32 @add1(i32 %ArgX1) { "
"entry: "
" %addresult = add i32 1, %ArgX1 "
" ret i32 %addresult "
"} "
" "
"define i32 @foo1() { "
"entry: "
" %add1 = call i32 @add1(i32 10) "
" ret i32 %add1 "
"} ");
FooF1 = M1->getFunction("foo1");
}
void createModule2(LLVMContext &Context2, Module *&M2, Function *&FooF2) {
M2 = new Module("test2", Context2);
LoadAssemblyInto(M2,
"define i32 @add2(i32 %ArgX2) { "
"entry: "
" %addresult = add i32 2, %ArgX2 "
" ret i32 %addresult "
"} "
" "
"define i32 @foo2() { "
"entry: "
" %add2 = call i32 @add2(i32 10) "
" ret i32 %add2 "
"} ");
FooF2 = M2->getFunction("foo2");
}
TEST(MultiJitTest, EagerMode) {
LLVMContext Context1;
Module *M1 = nullptr;
Function *FooF1 = nullptr;
createModule1(Context1, M1, FooF1);
LLVMContext Context2;
Module *M2 = nullptr;
Function *FooF2 = nullptr;
createModule2(Context2, M2, FooF2);
// Now we create the JIT in eager mode
std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create());
EE1->DisableLazyCompilation(true);
std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create());
EE2->DisableLazyCompilation(true);
// Call the `foo' function with no arguments:
std::vector<GenericValue> noargs;
GenericValue gv1 = EE1->runFunction(FooF1, noargs);
GenericValue gv2 = EE2->runFunction(FooF2, noargs);
// Import result of execution:
EXPECT_EQ(gv1.IntVal, 11);
EXPECT_EQ(gv2.IntVal, 12);
EE1->freeMachineCodeForFunction(FooF1);
EE2->freeMachineCodeForFunction(FooF2);
}
TEST(MultiJitTest, LazyMode) {
LLVMContext Context1;
Module *M1 = nullptr;
Function *FooF1 = nullptr;
createModule1(Context1, M1, FooF1);
LLVMContext Context2;
Module *M2 = nullptr;
Function *FooF2 = nullptr;
createModule2(Context2, M2, FooF2);
// Now we create the JIT in lazy mode
std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create());
EE1->DisableLazyCompilation(false);
std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create());
EE2->DisableLazyCompilation(false);
// Call the `foo' function with no arguments:
std::vector<GenericValue> noargs;
GenericValue gv1 = EE1->runFunction(FooF1, noargs);
GenericValue gv2 = EE2->runFunction(FooF2, noargs);
// Import result of execution:
EXPECT_EQ(gv1.IntVal, 11);
EXPECT_EQ(gv2.IntVal, 12);
EE1->freeMachineCodeForFunction(FooF1);
EE2->freeMachineCodeForFunction(FooF2);
}
extern "C" {
extern void *getPointerToNamedFunction(const char *Name);
}
TEST(MultiJitTest, JitPool) {
LLVMContext Context1;
Module *M1 = nullptr;
Function *FooF1 = nullptr;
createModule1(Context1, M1, FooF1);
LLVMContext Context2;
Module *M2 = nullptr;
Function *FooF2 = nullptr;
createModule2(Context2, M2, FooF2);
// Now we create two JITs
std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create());
std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create());
Function *F1 = EE1->FindFunctionNamed("foo1");
void *foo1 = EE1->getPointerToFunction(F1);
Function *F2 = EE2->FindFunctionNamed("foo2");
void *foo2 = EE2->getPointerToFunction(F2);
// Function in M1
EXPECT_EQ(getPointerToNamedFunction("foo1"), foo1);
// Function in M2
EXPECT_EQ(getPointerToNamedFunction("foo2"), foo2);
// Symbol search
intptr_t
sa = (intptr_t)getPointerToNamedFunction("getPointerToNamedFunction");
EXPECT_TRUE(sa != 0);
intptr_t fa = (intptr_t)&getPointerToNamedFunction;
EXPECT_TRUE(fa != 0);
#ifdef __i386__
// getPointerToNamedFunction might be indirect jump on Win32 --enable-shared.
// FF 25 <disp32>: jmp *(pointer to IAT)
if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) {
fa = *(intptr_t *)(fa + 2); // Address to IAT
EXPECT_TRUE(fa != 0);
fa = *(intptr_t *)fa; // Bound value of IAT
}
#elif defined(__x86_64__)
// getPointerToNamedFunction might be indirect jump
// on Win32 x64 --enable-shared.
// FF 25 <pcrel32>: jmp *(RIP + pointer to IAT)
if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) {
fa += *(int32_t *)(fa + 2) + 6; // Address to IAT(RIP)
fa = *(intptr_t *)fa; // Bound value of IAT
}
#endif
EXPECT_TRUE(sa == fa);
}
#endif // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__)
} // anonymous namespace