Skip to content

Commit 8740360

Browse files
committed
[ORC] Add unit tests for parts of the Orc and LLJIT C APIs.
Patch by Mats Larsen. Thanks Mats! Reviewed By: lhames Differential Revision: https://reviews.llvm.org/D100506
1 parent c8fc5e3 commit 8740360

File tree

2 files changed

+220
-0
lines changed

2 files changed

+220
-0
lines changed

llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ add_llvm_unittest(OrcJITTests
1717
IndirectionUtilsTest.cpp
1818
JITTargetMachineBuilderTest.cpp
1919
LazyCallThroughAndReexportsTest.cpp
20+
OrcCAPITest.cpp
2021
OrcTestCommon.cpp
2122
QueueChannel.cpp
2223
ResourceTrackerTest.cpp
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
//===--- OrcCAPITest.cpp - Unit tests for the OrcJIT v2 C API ---*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "OrcTestCommon.h"
10+
#include "llvm-c/Core.h"
11+
#include "llvm-c/LLJIT.h"
12+
#include "llvm-c/Orc.h"
13+
#include "gtest/gtest.h"
14+
15+
using namespace llvm;
16+
17+
// OrcCAPITestBase contains several helper methods and pointers for unit tests
18+
// written for the LLVM-C API. It provides the following helpers:
19+
//
20+
// 1. Jit: an LLVMOrcLLJIT instance which is freed upon test exit
21+
// 2. ExecutionSession: the LLVMOrcExecutionSession for the JIT
22+
// 3. MainDylib: the main JITDylib for the LLJIT instance
23+
// 4. materializationUnitFn: function pointer to an empty function, used for
24+
// materialization unit testing
25+
// 5. definitionGeneratorFn: function pointer for a basic
26+
// LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction
27+
// 6. createTestModule: helper method for creating a basic thread-safe-module
28+
class OrcCAPITestBase : public testing::Test, public OrcExecutionTest {
29+
protected:
30+
LLVMOrcLLJITRef Jit;
31+
LLVMOrcExecutionSessionRef ExecutionSession;
32+
LLVMOrcJITDylibRef MainDylib;
33+
34+
public:
35+
void SetUp() override {
36+
LLVMInitializeNativeTarget();
37+
LLVMOrcLLJITBuilderRef Builder = LLVMOrcCreateLLJITBuilder();
38+
if (LLVMErrorRef E = LLVMOrcCreateLLJIT(&Jit, Builder)) {
39+
char *Message = LLVMGetErrorMessage(E);
40+
FAIL() << "Failed to create LLJIT - This should never fail"
41+
<< " -- " << Message;
42+
}
43+
ExecutionSession = LLVMOrcLLJITGetExecutionSession(Jit);
44+
MainDylib = LLVMOrcLLJITGetMainJITDylib(Jit);
45+
}
46+
void TearDown() override { LLVMOrcDisposeLLJIT(Jit); }
47+
48+
protected:
49+
static void materializationUnitFn() {}
50+
// Stub definition generator, where all Names are materialized from the
51+
// materializationUnitFn() test function and defined into the JIT Dylib
52+
static LLVMErrorRef
53+
definitionGeneratorFn(LLVMOrcDefinitionGeneratorRef G, void *Ctx,
54+
LLVMOrcLookupStateRef *LS, LLVMOrcLookupKind K,
55+
LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags F,
56+
LLVMOrcCLookupSet Names, size_t NamesCount) {
57+
for (size_t I = 0; I < NamesCount; I++) {
58+
LLVMOrcCLookupSetElement Element = Names[I];
59+
LLVMOrcJITTargetAddress Addr =
60+
(LLVMOrcJITTargetAddress)(&materializationUnitFn);
61+
LLVMJITSymbolFlags Flags = {LLVMJITSymbolGenericFlagsWeak, 0};
62+
LLVMJITEvaluatedSymbol Sym = {Addr, Flags};
63+
LLVMOrcRetainSymbolStringPoolEntry(Element.Name);
64+
LLVMJITCSymbolMapPair Pair = {Element.Name, Sym};
65+
LLVMJITCSymbolMapPair Pairs[] = {Pair};
66+
LLVMOrcMaterializationUnitRef MU = LLVMOrcAbsoluteSymbols(Pairs, 1);
67+
LLVMErrorRef Err = LLVMOrcJITDylibDefine(JD, MU);
68+
if (Err)
69+
return Err;
70+
}
71+
return LLVMErrorSuccess;
72+
}
73+
// create a test LLVM IR module containing a function named "sum" which has
74+
// returns the sum of its two parameters
75+
static LLVMOrcThreadSafeModuleRef createTestModule() {
76+
LLVMOrcThreadSafeContextRef TSC = LLVMOrcCreateNewThreadSafeContext();
77+
LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSC);
78+
LLVMModuleRef Mod = LLVMModuleCreateWithNameInContext("test", Ctx);
79+
{
80+
LLVMTypeRef Int32Ty = LLVMInt32TypeInContext(Ctx);
81+
LLVMTypeRef ParamTys[] = {Int32Ty, Int32Ty};
82+
LLVMTypeRef TestFnTy = LLVMFunctionType(Int32Ty, ParamTys, 2, 0);
83+
LLVMValueRef TestFn = LLVMAddFunction(Mod, "sum", TestFnTy);
84+
LLVMBuilderRef IRBuilder = LLVMCreateBuilderInContext(Ctx);
85+
LLVMBasicBlockRef EntryBB = LLVMAppendBasicBlock(TestFn, "entry");
86+
LLVMPositionBuilderAtEnd(IRBuilder, EntryBB);
87+
LLVMValueRef Arg1 = LLVMGetParam(TestFn, 0);
88+
LLVMValueRef Arg2 = LLVMGetParam(TestFn, 1);
89+
LLVMValueRef Sum = LLVMBuildAdd(IRBuilder, Arg1, Arg2, "");
90+
LLVMBuildRet(IRBuilder, Sum);
91+
LLVMDisposeBuilder(IRBuilder);
92+
}
93+
LLVMOrcThreadSafeModuleRef TSM = LLVMOrcCreateNewThreadSafeModule(Mod, TSC);
94+
return TSM;
95+
}
96+
};
97+
98+
TEST_F(OrcCAPITestBase, SymbolStringPoolUniquing) {
99+
LLVMOrcSymbolStringPoolEntryRef E1 =
100+
LLVMOrcExecutionSessionIntern(ExecutionSession, "aaa");
101+
LLVMOrcSymbolStringPoolEntryRef E2 =
102+
LLVMOrcExecutionSessionIntern(ExecutionSession, "aaa");
103+
LLVMOrcSymbolStringPoolEntryRef E3 =
104+
LLVMOrcExecutionSessionIntern(ExecutionSession, "bbb");
105+
const char *SymbolName = LLVMOrcSymbolStringPoolEntryStr(E1);
106+
ASSERT_EQ(E1, E2) << "String pool entries are not unique";
107+
ASSERT_NE(E1, E3) << "Unique symbol pool entries are equal";
108+
ASSERT_STREQ("aaa", SymbolName) << "String value of symbol is not equal";
109+
LLVMOrcReleaseSymbolStringPoolEntry(E1);
110+
LLVMOrcReleaseSymbolStringPoolEntry(E2);
111+
LLVMOrcReleaseSymbolStringPoolEntry(E3);
112+
}
113+
114+
TEST_F(OrcCAPITestBase, JITDylibLookup) {
115+
LLVMOrcJITDylibRef DoesNotExist =
116+
LLVMOrcExecutionSessionGetJITDylibByName(ExecutionSession, "test");
117+
ASSERT_FALSE(!!DoesNotExist);
118+
LLVMOrcJITDylibRef L1 =
119+
LLVMOrcExecutionSessionCreateBareJITDylib(ExecutionSession, "test");
120+
LLVMOrcJITDylibRef L2 =
121+
LLVMOrcExecutionSessionGetJITDylibByName(ExecutionSession, "test");
122+
ASSERT_EQ(L1, L2) << "Located JIT Dylib is not equal to original";
123+
}
124+
125+
TEST_F(OrcCAPITestBase, MaterializationUnitCreation) {
126+
LLVMOrcSymbolStringPoolEntryRef Name =
127+
LLVMOrcLLJITMangleAndIntern(Jit, "test");
128+
LLVMJITSymbolFlags Flags = {LLVMJITSymbolGenericFlagsWeak, 0};
129+
LLVMOrcJITTargetAddress Addr =
130+
(LLVMOrcJITTargetAddress)(&materializationUnitFn);
131+
LLVMJITEvaluatedSymbol Sym = {Addr, Flags};
132+
LLVMJITCSymbolMapPair Pair = {Name, Sym};
133+
LLVMJITCSymbolMapPair Pairs[] = {Pair};
134+
LLVMOrcMaterializationUnitRef MU = LLVMOrcAbsoluteSymbols(Pairs, 1);
135+
LLVMOrcJITDylibDefine(MainDylib, MU);
136+
LLVMOrcJITTargetAddress OutAddr;
137+
if (LLVMOrcLLJITLookup(Jit, &OutAddr, "test")) {
138+
FAIL() << "Failed to look up \"test\" symbol";
139+
}
140+
ASSERT_EQ(Addr, OutAddr);
141+
}
142+
143+
TEST_F(OrcCAPITestBase, DefinitionGenerators) {
144+
LLVMOrcDefinitionGeneratorRef Gen =
145+
LLVMOrcCreateCustomCAPIDefinitionGenerator(&definitionGeneratorFn,
146+
nullptr);
147+
LLVMOrcJITDylibAddGenerator(MainDylib, Gen);
148+
LLVMOrcJITTargetAddress OutAddr;
149+
if (LLVMOrcLLJITLookup(Jit, &OutAddr, "test")) {
150+
FAIL() << "The DefinitionGenerator did not create symbol \"test\"";
151+
}
152+
LLVMOrcJITTargetAddress ExpectedAddr =
153+
(LLVMOrcJITTargetAddress)(&materializationUnitFn);
154+
ASSERT_EQ(ExpectedAddr, OutAddr);
155+
}
156+
157+
TEST_F(OrcCAPITestBase, ResourceTrackerDefinitionLifetime) {
158+
// This test case ensures that all symbols loaded into a JITDylib with a
159+
// ResourceTracker attached are cleared from the JITDylib once the RT is
160+
// removed.
161+
LLVMOrcResourceTrackerRef RT =
162+
LLVMOrcJITDylibCreateResourceTracker(MainDylib);
163+
LLVMOrcThreadSafeModuleRef TSM = createTestModule();
164+
if (LLVMErrorRef E = LLVMOrcLLJITAddLLVMIRModuleWithRT(Jit, RT, TSM)) {
165+
FAIL() << "Failed to add LLVM IR module to LLJIT";
166+
}
167+
LLVMOrcJITTargetAddress TestFnAddr;
168+
if (LLVMOrcLLJITLookup(Jit, &TestFnAddr, "sum")) {
169+
FAIL() << "Symbol \"sum\" was not added into JIT";
170+
}
171+
ASSERT_TRUE(!!TestFnAddr);
172+
LLVMOrcResourceTrackerRemove(RT);
173+
LLVMOrcJITTargetAddress OutAddr;
174+
LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &OutAddr, "sum");
175+
ASSERT_TRUE(Err);
176+
ASSERT_FALSE(OutAddr);
177+
LLVMOrcReleaseResourceTracker(RT);
178+
LLVMConsumeError(Err);
179+
}
180+
181+
TEST_F(OrcCAPITestBase, ResourceTrackerTransfer) {
182+
LLVMOrcResourceTrackerRef DefaultRT =
183+
LLVMOrcJITDylibGetDefaultResourceTracker(MainDylib);
184+
LLVMOrcResourceTrackerRef RT2 =
185+
LLVMOrcJITDylibCreateResourceTracker(MainDylib);
186+
LLVMOrcThreadSafeModuleRef TSM = createTestModule();
187+
if (LLVMErrorRef E = LLVMOrcLLJITAddLLVMIRModuleWithRT(Jit, DefaultRT, TSM)) {
188+
FAIL() << "Failed to add LLVM IR module to LLJIT";
189+
}
190+
LLVMOrcJITTargetAddress Addr;
191+
if (LLVMOrcLLJITLookup(Jit, &Addr, "sum")) {
192+
FAIL() << "Symbol \"sum\" was not added into JIT";
193+
}
194+
LLVMOrcResourceTrackerTransferTo(DefaultRT, RT2);
195+
LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "sum");
196+
ASSERT_FALSE(Err);
197+
LLVMOrcReleaseResourceTracker(RT2);
198+
}
199+
200+
TEST_F(OrcCAPITestBase, ExecutionTest) {
201+
if (!SupportsJIT)
202+
return;
203+
204+
using SumFunctionType = int32_t (*)(int32_t, int32_t);
205+
206+
// This test performs OrcJIT compilation of a simple sum module
207+
LLVMInitializeNativeAsmPrinter();
208+
LLVMOrcThreadSafeModuleRef TSM = createTestModule();
209+
if (LLVMErrorRef E = LLVMOrcLLJITAddLLVMIRModule(Jit, MainDylib, TSM)) {
210+
FAIL() << "Failed to add LLVM IR module to LLJIT";
211+
}
212+
LLVMOrcJITTargetAddress TestFnAddr;
213+
if (LLVMOrcLLJITLookup(Jit, &TestFnAddr, "sum")) {
214+
FAIL() << "Symbol \"sum\" was not added into JIT";
215+
}
216+
auto *SumFn = (SumFunctionType)(TestFnAddr);
217+
int32_t Result = SumFn(1, 1);
218+
ASSERT_EQ(2, Result);
219+
}

0 commit comments

Comments
 (0)