1//===- MultiJITTest.cpp - Unit tests for instantiating multiple JITs ------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/ExecutionEngine/JIT.h"
11#include "llvm/AsmParser/Parser.h"
12#include "llvm/ExecutionEngine/GenericValue.h"
13#include "llvm/IR/LLVMContext.h"
14#include "llvm/IR/Module.h"
15#include "llvm/Support/SourceMgr.h"
16#include "gtest/gtest.h"
17#include <vector>
18
19using namespace llvm;
20
21namespace {
22
23// ARM, PowerPC and SystemZ tests disabled pending fix for PR10783.
24#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \
25                      && !defined(__aarch64__)
26
27bool LoadAssemblyInto(Module *M, const char *assembly) {
28  SMDiagnostic Error;
29  bool success =
30    nullptr != ParseAssemblyString(assembly, M, Error, M->getContext());
31  std::string errMsg;
32  raw_string_ostream os(errMsg);
33  Error.print("", os);
34  EXPECT_TRUE(success) << os.str();
35  return success;
36}
37
38void createModule1(LLVMContext &Context1, Module *&M1, Function *&FooF1) {
39  M1 = new Module("test1", Context1);
40  LoadAssemblyInto(M1,
41                   "define i32 @add1(i32 %ArgX1) { "
42                   "entry: "
43                   "  %addresult = add i32 1, %ArgX1 "
44                   "  ret i32 %addresult "
45                   "} "
46                   " "
47                   "define i32 @foo1() { "
48                   "entry: "
49                   "  %add1 = call i32 @add1(i32 10) "
50                   "  ret i32 %add1 "
51                   "} ");
52  FooF1 = M1->getFunction("foo1");
53}
54
55void createModule2(LLVMContext &Context2, Module *&M2, Function *&FooF2) {
56  M2 = new Module("test2", Context2);
57  LoadAssemblyInto(M2,
58                   "define i32 @add2(i32 %ArgX2) { "
59                   "entry: "
60                   "  %addresult = add i32 2, %ArgX2 "
61                   "  ret i32 %addresult "
62                   "} "
63                   " "
64                   "define i32 @foo2() { "
65                   "entry: "
66                   "  %add2 = call i32 @add2(i32 10) "
67                   "  ret i32 %add2 "
68                   "} ");
69  FooF2 = M2->getFunction("foo2");
70}
71
72TEST(MultiJitTest, EagerMode) {
73  LLVMContext Context1;
74  Module *M1 = nullptr;
75  Function *FooF1 = nullptr;
76  createModule1(Context1, M1, FooF1);
77
78  LLVMContext Context2;
79  Module *M2 = nullptr;
80  Function *FooF2 = nullptr;
81  createModule2(Context2, M2, FooF2);
82
83  // Now we create the JIT in eager mode
84  std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create());
85  EE1->DisableLazyCompilation(true);
86  std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create());
87  EE2->DisableLazyCompilation(true);
88
89  // Call the `foo' function with no arguments:
90  std::vector<GenericValue> noargs;
91  GenericValue gv1 = EE1->runFunction(FooF1, noargs);
92  GenericValue gv2 = EE2->runFunction(FooF2, noargs);
93
94  // Import result of execution:
95  EXPECT_EQ(gv1.IntVal, 11);
96  EXPECT_EQ(gv2.IntVal, 12);
97
98  EE1->freeMachineCodeForFunction(FooF1);
99  EE2->freeMachineCodeForFunction(FooF2);
100}
101
102TEST(MultiJitTest, LazyMode) {
103  LLVMContext Context1;
104  Module *M1 = nullptr;
105  Function *FooF1 = nullptr;
106  createModule1(Context1, M1, FooF1);
107
108  LLVMContext Context2;
109  Module *M2 = nullptr;
110  Function *FooF2 = nullptr;
111  createModule2(Context2, M2, FooF2);
112
113  // Now we create the JIT in lazy mode
114  std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create());
115  EE1->DisableLazyCompilation(false);
116  std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create());
117  EE2->DisableLazyCompilation(false);
118
119  // Call the `foo' function with no arguments:
120  std::vector<GenericValue> noargs;
121  GenericValue gv1 = EE1->runFunction(FooF1, noargs);
122  GenericValue gv2 = EE2->runFunction(FooF2, noargs);
123
124  // Import result of execution:
125  EXPECT_EQ(gv1.IntVal, 11);
126  EXPECT_EQ(gv2.IntVal, 12);
127
128  EE1->freeMachineCodeForFunction(FooF1);
129  EE2->freeMachineCodeForFunction(FooF2);
130}
131
132extern "C" {
133  extern void *getPointerToNamedFunction(const char *Name);
134}
135
136TEST(MultiJitTest, JitPool) {
137  LLVMContext Context1;
138  Module *M1 = nullptr;
139  Function *FooF1 = nullptr;
140  createModule1(Context1, M1, FooF1);
141
142  LLVMContext Context2;
143  Module *M2 = nullptr;
144  Function *FooF2 = nullptr;
145  createModule2(Context2, M2, FooF2);
146
147  // Now we create two JITs
148  std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create());
149  std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create());
150
151  Function *F1 = EE1->FindFunctionNamed("foo1");
152  void *foo1 = EE1->getPointerToFunction(F1);
153
154  Function *F2 = EE2->FindFunctionNamed("foo2");
155  void *foo2 = EE2->getPointerToFunction(F2);
156
157  // Function in M1
158  EXPECT_EQ(getPointerToNamedFunction("foo1"), foo1);
159
160  // Function in M2
161  EXPECT_EQ(getPointerToNamedFunction("foo2"), foo2);
162
163  // Symbol search
164  intptr_t
165    sa = (intptr_t)getPointerToNamedFunction("getPointerToNamedFunction");
166  EXPECT_TRUE(sa != 0);
167  intptr_t fa = (intptr_t)&getPointerToNamedFunction;
168  EXPECT_TRUE(fa != 0);
169#ifdef __i386__
170  // getPointerToNamedFunction might be indirect jump on Win32 --enable-shared.
171  // FF 25 <disp32>: jmp *(pointer to IAT)
172  if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) {
173    fa = *(intptr_t *)(fa + 2); // Address to IAT
174    EXPECT_TRUE(fa != 0);
175    fa = *(intptr_t *)fa;       // Bound value of IAT
176  }
177#elif defined(__x86_64__)
178  // getPointerToNamedFunction might be indirect jump
179  // on Win32 x64 --enable-shared.
180  // FF 25 <pcrel32>: jmp *(RIP + pointer to IAT)
181  if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) {
182    fa += *(int32_t *)(fa + 2) + 6;     // Address to IAT(RIP)
183    fa = *(intptr_t *)fa;               // Bound value of IAT
184  }
185#endif
186  EXPECT_TRUE(sa == fa);
187}
188#endif  // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__)
189
190}  // anonymous namespace
191