1 //===--- OrcCAPITest.cpp - Unit tests for the OrcJIT v2 C API ---*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm-c/Core.h"
10 #include "llvm-c/Error.h"
11 #include "llvm-c/LLJIT.h"
12 #include "llvm-c/LLJITUtils.h"
13 #include "llvm-c/Orc.h"
14 #include "gtest/gtest.h"
16 #include "llvm/Analysis/TargetLibraryInfo.h"
17 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
18 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
19 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/IRReader/IRReader.h"
23 #include "llvm/Support/Error.h"
24 #include "llvm/Support/FormatVariadic.h"
25 #include "llvm/Support/SourceMgr.h"
26 #include "llvm/TargetParser/Triple.h"
27 #include "llvm/Testing/Support/Error.h"
31 using namespace llvm::orc
;
33 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ObjectLayer
, LLVMOrcObjectLayerRef
)
34 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule
, LLVMOrcThreadSafeModuleRef
)
36 // A class that sets strings for extension attributes by querying
38 struct TargetI32ArgExtensions
{
41 TargetI32ArgExtensions(std::string TargetTriple
, bool Signed
= true) {
42 Triple
T(TargetTriple
);
43 if (auto AK
= TargetLibraryInfo::getExtAttrForI32Return(T
, Signed
))
44 Ret
= Attribute::getNameFromAttrKind(AK
).str() + " ";
45 if (auto AK
= TargetLibraryInfo::getExtAttrForI32Param(T
, Signed
))
46 Arg
= Attribute::getNameFromAttrKind(AK
).str() + " ";
50 // OrcCAPITestBase contains several helper methods and pointers for unit tests
51 // written for the LLVM-C API. It provides the following helpers:
53 // 1. Jit: an LLVMOrcLLJIT instance which is freed upon test exit
54 // 2. ExecutionSession: the LLVMOrcExecutionSession for the JIT
55 // 3. MainDylib: the main JITDylib for the LLJIT instance
56 // 4. materializationUnitFn: function pointer to an empty function, used for
57 // materialization unit testing
58 // 5. definitionGeneratorFn: function pointer for a basic
59 // LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction
60 // 6. createTestModule: helper method for creating a basic thread-safe-module
61 class OrcCAPITestBase
: public testing::Test
{
63 LLVMOrcLLJITRef Jit
= nullptr;
64 LLVMOrcExecutionSessionRef ExecutionSession
= nullptr;
65 LLVMOrcJITDylibRef MainDylib
= nullptr;
68 static void SetUpTestCase() {
69 LLVMInitializeNativeTarget();
70 LLVMInitializeNativeAsmParser();
71 LLVMInitializeNativeAsmPrinter();
73 // Attempt to set up a JIT instance once to verify that we can.
74 LLVMOrcJITTargetMachineBuilderRef JTMB
= nullptr;
75 if (LLVMErrorRef E
= LLVMOrcJITTargetMachineBuilderDetectHost(&JTMB
)) {
76 // If setup fails then disable these tests.
78 TargetSupported
= false;
82 // Capture the target triple. We'll use it for both verification that
83 // this target is *supposed* to be supported, and error messages in
84 // the case that it fails anyway.
85 char *TT
= LLVMOrcJITTargetMachineBuilderGetTargetTriple(JTMB
);
87 LLVMDisposeMessage(TT
);
89 if (!isSupported(TargetTriple
)) {
90 // If this triple isn't supported then bail out.
91 TargetSupported
= false;
92 LLVMOrcDisposeJITTargetMachineBuilder(JTMB
);
96 LLVMOrcLLJITBuilderRef Builder
= LLVMOrcCreateLLJITBuilder();
97 LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(Builder
, JTMB
);
99 if (LLVMErrorRef E
= LLVMOrcCreateLLJIT(&J
, Builder
)) {
100 // If setup fails then disable these tests.
101 TargetSupported
= false;
106 LLVMOrcDisposeLLJIT(J
);
107 TargetSupported
= true;
109 // Create test functions in text format, with the proper extension
111 if (SumExample
.empty()) {
112 TargetI32ArgExtensions
ArgExt(TargetTriple
);
113 std::ostringstream OS
;
114 OS
<< "define " << ArgExt
.Ret
<< "i32 "
115 << "@sum(i32 " << ArgExt
.Arg
<< "%x, i32 " << ArgExt
.Arg
<< "%y)"
118 %r = add nsw i32 %x, %y
122 SumExample
= OS
.str();
125 !llvm.module.flags = !{!0}
127 !0 = !{i32 2, !"Debug Info Version
", i32 3}
128 !1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, emissionKind: FullDebug)
129 !2 = !DIFile(filename: "sum
.c
", directory: "/tmp
")
131 SumDebugExample
= OS
.str();
135 void SetUp() override
{
136 if (!TargetSupported
)
139 LLVMOrcJITTargetMachineBuilderRef JTMB
= nullptr;
140 LLVMErrorRef E1
= LLVMOrcJITTargetMachineBuilderDetectHost(&JTMB
);
141 assert(E1
== LLVMErrorSuccess
&& "Expected call to detect host to succeed");
144 LLVMOrcLLJITBuilderRef Builder
= LLVMOrcCreateLLJITBuilder();
145 LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(Builder
, JTMB
);
146 LLVMErrorRef E2
= LLVMOrcCreateLLJIT(&Jit
, Builder
);
147 assert(E2
== LLVMErrorSuccess
&&
148 "Expected call to create LLJIT to succeed");
150 ExecutionSession
= LLVMOrcLLJITGetExecutionSession(Jit
);
151 MainDylib
= LLVMOrcLLJITGetMainJITDylib(Jit
);
153 void TearDown() override
{
154 // Check whether Jit has already been torn down -- we allow clients to do
155 // this manually to check teardown behavior.
157 LLVMOrcDisposeLLJIT(Jit
);
163 static bool isSupported(StringRef Triple
) {
164 // TODO: Print error messages in failure logs, use them to audit this list.
165 // Some architectures may be unsupportable or missing key components, but
166 // some may just be failing due to bugs in this testcase.
167 if (Triple
.starts_with("armv7") || Triple
.starts_with("armv8l"))
172 static void materializationUnitFn() {}
174 // Stub definition generator, where all Names are materialized from the
175 // materializationUnitFn() test function and defined into the JIT Dylib
177 definitionGeneratorFn(LLVMOrcDefinitionGeneratorRef G
, void *Ctx
,
178 LLVMOrcLookupStateRef
*LS
, LLVMOrcLookupKind K
,
179 LLVMOrcJITDylibRef JD
, LLVMOrcJITDylibLookupFlags F
,
180 LLVMOrcCLookupSet Names
, size_t NamesCount
) {
181 for (size_t I
= 0; I
< NamesCount
; I
++) {
182 LLVMOrcCLookupSetElement Element
= Names
[I
];
183 LLVMOrcJITTargetAddress Addr
=
184 (LLVMOrcJITTargetAddress
)(&materializationUnitFn
);
185 LLVMJITSymbolFlags Flags
= {LLVMJITSymbolGenericFlagsWeak
, 0};
186 LLVMJITEvaluatedSymbol Sym
= {Addr
, Flags
};
187 LLVMOrcRetainSymbolStringPoolEntry(Element
.Name
);
188 LLVMOrcCSymbolMapPair Pair
= {Element
.Name
, Sym
};
189 LLVMOrcCSymbolMapPair Pairs
[] = {Pair
};
190 LLVMOrcMaterializationUnitRef MU
= LLVMOrcAbsoluteSymbols(Pairs
, 1);
191 LLVMErrorRef Err
= LLVMOrcJITDylibDefine(JD
, MU
);
195 return LLVMErrorSuccess
;
198 static Error
createSMDiagnosticError(llvm::SMDiagnostic
&Diag
) {
201 raw_string_ostream
OS(Msg
);
204 return make_error
<StringError
>(std::move(Msg
), inconvertibleErrorCode());
207 // Create an LLVM IR module from the given StringRef.
208 static Expected
<std::unique_ptr
<Module
>>
209 parseTestModule(LLVMContext
&Ctx
, StringRef Source
, StringRef Name
) {
210 assert(TargetSupported
&&
211 "Attempted to create module for unsupported target");
213 if (auto M
= parseIR(MemoryBufferRef(Source
, Name
), Err
, Ctx
))
215 return createSMDiagnosticError(Err
);
218 // returns the sum of its two parameters
219 static LLVMOrcThreadSafeModuleRef
createTestModule(StringRef Source
,
221 auto Ctx
= std::make_unique
<LLVMContext
>();
222 auto M
= cantFail(parseTestModule(*Ctx
, Source
, Name
));
223 return wrap(new ThreadSafeModule(std::move(M
), std::move(Ctx
)));
226 static LLVMMemoryBufferRef
createTestObject(StringRef Source
,
228 auto Ctx
= std::make_unique
<LLVMContext
>();
229 auto M
= cantFail(parseTestModule(*Ctx
, Source
, Name
));
231 auto JTMB
= cantFail(JITTargetMachineBuilder::detectHost());
232 M
->setDataLayout(cantFail(JTMB
.getDefaultDataLayoutForTarget()));
233 auto TM
= cantFail(JTMB
.createTargetMachine());
235 SimpleCompiler
SC(*TM
);
236 auto ObjBuffer
= cantFail(SC(*M
));
237 return wrap(ObjBuffer
.release());
240 static std::string TargetTriple
;
241 static bool TargetSupported
;
243 static std::string SumExample
;
244 static std::string SumDebugExample
;
247 std::string
OrcCAPITestBase::TargetTriple
;
248 bool OrcCAPITestBase::TargetSupported
= false;
250 std::string
OrcCAPITestBase::SumExample
;
251 std::string
OrcCAPITestBase::SumDebugExample
;
253 // Consumes the given error ref and returns the string error message.
254 static std::string
toString(LLVMErrorRef E
) {
255 char *ErrMsg
= LLVMGetErrorMessage(E
);
256 std::string
Result(ErrMsg
);
257 LLVMDisposeErrorMessage(ErrMsg
);
261 TEST_F(OrcCAPITestBase
, SymbolStringPoolUniquing
) {
262 LLVMOrcSymbolStringPoolEntryRef E1
=
263 LLVMOrcExecutionSessionIntern(ExecutionSession
, "aaa");
264 LLVMOrcSymbolStringPoolEntryRef E2
=
265 LLVMOrcExecutionSessionIntern(ExecutionSession
, "aaa");
266 LLVMOrcSymbolStringPoolEntryRef E3
=
267 LLVMOrcExecutionSessionIntern(ExecutionSession
, "bbb");
268 const char *SymbolName
= LLVMOrcSymbolStringPoolEntryStr(E1
);
269 ASSERT_EQ(E1
, E2
) << "String pool entries are not unique";
270 ASSERT_NE(E1
, E3
) << "Unique symbol pool entries are equal";
271 ASSERT_STREQ("aaa", SymbolName
) << "String value of symbol is not equal";
272 LLVMOrcReleaseSymbolStringPoolEntry(E1
);
273 LLVMOrcReleaseSymbolStringPoolEntry(E2
);
274 LLVMOrcReleaseSymbolStringPoolEntry(E3
);
277 TEST_F(OrcCAPITestBase
, JITDylibLookup
) {
278 LLVMOrcJITDylibRef DoesNotExist
=
279 LLVMOrcExecutionSessionGetJITDylibByName(ExecutionSession
, "test");
280 ASSERT_FALSE(!!DoesNotExist
);
281 LLVMOrcJITDylibRef L1
=
282 LLVMOrcExecutionSessionCreateBareJITDylib(ExecutionSession
, "test");
283 LLVMOrcJITDylibRef L2
=
284 LLVMOrcExecutionSessionGetJITDylibByName(ExecutionSession
, "test");
285 ASSERT_EQ(L1
, L2
) << "Located JIT Dylib is not equal to original";
288 TEST_F(OrcCAPITestBase
, MaterializationUnitCreation
) {
289 LLVMOrcSymbolStringPoolEntryRef Name
=
290 LLVMOrcLLJITMangleAndIntern(Jit
, "test");
291 LLVMJITSymbolFlags Flags
= {LLVMJITSymbolGenericFlagsWeak
, 0};
292 LLVMOrcJITTargetAddress Addr
=
293 (LLVMOrcJITTargetAddress
)(&materializationUnitFn
);
294 LLVMJITEvaluatedSymbol Sym
= {Addr
, Flags
};
295 LLVMOrcCSymbolMapPair Pair
= {Name
, Sym
};
296 LLVMOrcCSymbolMapPair Pairs
[] = {Pair
};
297 LLVMOrcMaterializationUnitRef MU
= LLVMOrcAbsoluteSymbols(Pairs
, 1);
298 if (LLVMErrorRef E
= LLVMOrcJITDylibDefine(MainDylib
, MU
))
299 FAIL() << "Unexpected error while adding \"test\" symbol (triple = "
300 << TargetTriple
<< "): " << toString(E
);
301 LLVMOrcJITTargetAddress OutAddr
;
302 if (LLVMErrorRef E
= LLVMOrcLLJITLookup(Jit
, &OutAddr
, "test"))
303 FAIL() << "Failed to look up \"test\" symbol (triple = " << TargetTriple
304 << "): " << toString(E
);
305 ASSERT_EQ(Addr
, OutAddr
);
308 struct ExecutionSessionLookupHelper
{
309 bool ExpectSuccess
= true;
310 bool CallbackReceived
= false;
311 size_t NumExpectedPairs
;
312 LLVMOrcCSymbolMapPair
*ExpectedMapping
;
315 static void executionSessionLookupHandlerCallback(LLVMErrorRef Err
,
316 LLVMOrcCSymbolMapPairs Result
,
319 auto *Ctx
= static_cast<ExecutionSessionLookupHelper
*>(RawCtx
);
320 Ctx
->CallbackReceived
= true;
321 if (Ctx
->ExpectSuccess
) {
322 EXPECT_THAT_ERROR(unwrap(Err
), Succeeded());
323 EXPECT_EQ(NumPairs
, Ctx
->NumExpectedPairs
)
324 << "Expected " << Ctx
->NumExpectedPairs
<< " entries in result, got "
326 auto ExpectedMappingEnd
= Ctx
->ExpectedMapping
+ Ctx
->NumExpectedPairs
;
327 for (unsigned I
= 0; I
!= NumPairs
; ++I
) {
329 std::find_if(Ctx
->ExpectedMapping
, ExpectedMappingEnd
,
330 [N
= Result
[I
].Name
](const LLVMOrcCSymbolMapPair
&Val
) {
331 return Val
.Name
== N
;
333 EXPECT_NE(J
, ExpectedMappingEnd
)
334 << "Missing symbol \""
335 << LLVMOrcSymbolStringPoolEntryStr(Result
[I
].Name
) << "\"";
336 if (J
!= ExpectedMappingEnd
) {
337 EXPECT_EQ(Result
[I
].Sym
.Address
, J
->Sym
.Address
)
338 << "Result map for \"" << Result
[I
].Name
339 << "\" differs from expected value: "
340 << formatv("{0:x} vs {1:x}", Result
[I
].Sym
.Address
, J
->Sym
.Address
);
344 EXPECT_THAT_ERROR(unwrap(Err
), Failed());
347 TEST_F(OrcCAPITestBase
, ExecutionSessionLookup_Success
) {
348 // Test a successful generic lookup. We will look up three symbols over two
349 // JITDylibs: { "Foo" (Required), "Bar" (Weakly-ref), "Baz" (Required) } over
350 // { MainJITDylib (Exported-only), ExtraJD (All symbols) }.
352 // Foo will be defined as exported in MainJD.
353 // Bar will be defined as non-exported in MainJD.
354 // Baz will be defined as non-exported in ExtraJD.
356 // This will require (1) that we find the regular exported symbol Foo in
357 // MainJD, (2) that we *don't* find the non-exported symbol Bar in MainJD
358 // but also don't error (since it's weakly referenced), and (3) that we
359 // find the non-exported symbol Baz in ExtraJD (since we're searching all
360 // symbols in ExtraJD).
362 ExecutionSessionLookupHelper H
;
363 LLVMOrcSymbolStringPoolEntryRef Foo
= LLVMOrcLLJITMangleAndIntern(Jit
, "Foo");
364 LLVMOrcSymbolStringPoolEntryRef Bar
= LLVMOrcLLJITMangleAndIntern(Jit
, "Bar");
365 LLVMOrcSymbolStringPoolEntryRef Baz
= LLVMOrcLLJITMangleAndIntern(Jit
, "Baz");
368 LLVMOrcJITDylibRef ExtraJD
= nullptr;
369 if (auto E
= LLVMOrcExecutionSessionCreateJITDylib(ExecutionSession
, &ExtraJD
,
371 FAIL() << "Unexpected error while creating JITDylib \"ExtraJD\" (triple = "
372 << TargetTriple
<< "): " << toString(E
);
376 // Add exported symbols "Foo" and "Bar" to Main JITDylib.
377 LLVMOrcRetainSymbolStringPoolEntry(Foo
);
378 LLVMOrcRetainSymbolStringPoolEntry(Bar
);
379 LLVMOrcCSymbolMapPair MainJDPairs
[] = {
380 {Foo
, {0x1, {LLVMJITSymbolGenericFlagsExported
, 0}}},
381 {Bar
, {0x2, {LLVMJITSymbolGenericFlagsNone
, 0}}}};
382 LLVMOrcMaterializationUnitRef MainJDMU
=
383 LLVMOrcAbsoluteSymbols(MainJDPairs
, 2);
384 if (LLVMErrorRef E
= LLVMOrcJITDylibDefine(MainDylib
, MainJDMU
))
385 FAIL() << "Unexpected error while adding MainDylib symbols (triple = "
386 << TargetTriple
<< "): " << toString(E
);
388 // Add non-exported symbol "Baz" to ExtraJD.
389 LLVMOrcRetainSymbolStringPoolEntry(Baz
);
390 LLVMOrcCSymbolMapPair ExtraJDPairs
[] = {
391 {Baz
, {0x3, {LLVMJITSymbolGenericFlagsNone
, 0}}}};
392 LLVMOrcMaterializationUnitRef ExtraJDMU
=
393 LLVMOrcAbsoluteSymbols(ExtraJDPairs
, 1);
394 if (LLVMErrorRef E
= LLVMOrcJITDylibDefine(ExtraJD
, ExtraJDMU
))
395 FAIL() << "Unexpected error while adding ExtraJD symbols (triple = "
396 << TargetTriple
<< "): " << toString(E
);
398 // Create expected mapping for result:
399 LLVMOrcCSymbolMapPair ExpectedMapping
[] = {
400 {Foo
, {0x1, {LLVMJITSymbolGenericFlagsExported
, 0}}},
401 {Baz
, {0x3, {LLVMJITSymbolGenericFlagsNone
, 0}}}};
402 H
.ExpectedMapping
= ExpectedMapping
;
403 H
.NumExpectedPairs
= 2;
405 // Issue the lookup. We're using the default same-thread dispatch, so the
406 // handler should have run by the time we return from this call.
407 LLVMOrcCJITDylibSearchOrderElement SO
[] = {
408 {MainDylib
, LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly
},
409 {ExtraJD
, LLVMOrcJITDylibLookupFlagsMatchAllSymbols
}};
411 LLVMOrcRetainSymbolStringPoolEntry(Foo
);
412 LLVMOrcRetainSymbolStringPoolEntry(Bar
);
413 LLVMOrcRetainSymbolStringPoolEntry(Baz
);
414 LLVMOrcCLookupSetElement LS
[] = {
415 {Foo
, LLVMOrcSymbolLookupFlagsRequiredSymbol
},
416 {Bar
, LLVMOrcSymbolLookupFlagsWeaklyReferencedSymbol
},
417 {Baz
, LLVMOrcSymbolLookupFlagsRequiredSymbol
}};
418 LLVMOrcExecutionSessionLookup(ExecutionSession
, LLVMOrcLookupKindStatic
, SO
,
419 2, LS
, 3, executionSessionLookupHandlerCallback
,
422 EXPECT_TRUE(H
.CallbackReceived
) << "Lookup callback never received";
424 // Release our local string ptrs.
425 LLVMOrcReleaseSymbolStringPoolEntry(Baz
);
426 LLVMOrcReleaseSymbolStringPoolEntry(Bar
);
427 LLVMOrcReleaseSymbolStringPoolEntry(Foo
);
430 TEST_F(OrcCAPITestBase
, ExecutionSessionLookup_Failure
) {
431 // Test generic lookup failure case. We will look up a symbol in MainDylib
432 // without defining it. We expect this to result in a symbol-not-found error.
434 ExecutionSessionLookupHelper H
;
435 H
.ExpectSuccess
= false;
437 LLVMOrcCJITDylibSearchOrderElement SO
[] = {
438 {MainDylib
, LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly
}};
439 LLVMOrcCLookupSetElement LS
[] = {{LLVMOrcLLJITMangleAndIntern(Jit
, "Foo"),
440 LLVMOrcSymbolLookupFlagsRequiredSymbol
}};
441 LLVMOrcExecutionSessionLookup(ExecutionSession
, LLVMOrcLookupKindStatic
, SO
,
442 1, LS
, 1, executionSessionLookupHandlerCallback
,
445 EXPECT_TRUE(H
.CallbackReceived
) << "Lookup callback never received";
448 TEST_F(OrcCAPITestBase
, DefinitionGenerators
) {
449 LLVMOrcDefinitionGeneratorRef Gen
=
450 LLVMOrcCreateCustomCAPIDefinitionGenerator(&definitionGeneratorFn
,
452 LLVMOrcJITDylibAddGenerator(MainDylib
, Gen
);
453 LLVMOrcJITTargetAddress OutAddr
;
454 if (LLVMErrorRef E
= LLVMOrcLLJITLookup(Jit
, &OutAddr
, "test"))
455 FAIL() << "The DefinitionGenerator did not create symbol \"test\" "
456 << "(triple = " << TargetTriple
<< "): " << toString(E
);
457 LLVMOrcJITTargetAddress ExpectedAddr
=
458 (LLVMOrcJITTargetAddress
)(&materializationUnitFn
);
459 ASSERT_EQ(ExpectedAddr
, OutAddr
);
463 TEST_F(OrcCAPITestBase
, DISABLED_ResourceTrackerDefinitionLifetime
) {
465 TEST_F(OrcCAPITestBase
, ResourceTrackerDefinitionLifetime
) {
467 // This test case ensures that all symbols loaded into a JITDylib with a
468 // ResourceTracker attached are cleared from the JITDylib once the RT is
470 LLVMOrcResourceTrackerRef RT
=
471 LLVMOrcJITDylibCreateResourceTracker(MainDylib
);
472 LLVMOrcThreadSafeModuleRef TSM
= createTestModule(SumExample
, "sum.ll");
473 if (LLVMErrorRef E
= LLVMOrcLLJITAddLLVMIRModuleWithRT(Jit
, RT
, TSM
))
474 FAIL() << "Failed to add LLVM IR module to LLJIT (triple = " << TargetTriple
475 << "): " << toString(E
);
476 LLVMOrcJITTargetAddress TestFnAddr
;
477 if (LLVMErrorRef E
= LLVMOrcLLJITLookup(Jit
, &TestFnAddr
, "sum"))
478 FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple
479 << "): " << toString(E
);
480 ASSERT_TRUE(!!TestFnAddr
);
481 LLVMOrcResourceTrackerRemove(RT
);
482 LLVMOrcJITTargetAddress OutAddr
;
483 LLVMErrorRef Err
= LLVMOrcLLJITLookup(Jit
, &OutAddr
, "sum");
485 LLVMConsumeError(Err
);
487 ASSERT_FALSE(OutAddr
);
488 LLVMOrcReleaseResourceTracker(RT
);
492 TEST_F(OrcCAPITestBase
, DISABLED_ResourceTrackerTransfer
) {
494 TEST_F(OrcCAPITestBase
, ResourceTrackerTransfer
) {
496 LLVMOrcResourceTrackerRef DefaultRT
=
497 LLVMOrcJITDylibGetDefaultResourceTracker(MainDylib
);
498 LLVMOrcResourceTrackerRef RT2
=
499 LLVMOrcJITDylibCreateResourceTracker(MainDylib
);
500 LLVMOrcThreadSafeModuleRef TSM
= createTestModule(SumExample
, "sum.ll");
501 if (LLVMErrorRef E
= LLVMOrcLLJITAddLLVMIRModuleWithRT(Jit
, DefaultRT
, TSM
))
502 FAIL() << "Failed to add LLVM IR module to LLJIT (triple = " << TargetTriple
503 << "): " << toString(E
);
504 LLVMOrcJITTargetAddress Addr
;
505 if (LLVMErrorRef E
= LLVMOrcLLJITLookup(Jit
, &Addr
, "sum"))
506 FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple
507 << "): " << toString(E
);
508 LLVMOrcResourceTrackerTransferTo(DefaultRT
, RT2
);
509 LLVMErrorRef Err
= LLVMOrcLLJITLookup(Jit
, &Addr
, "sum");
511 LLVMOrcReleaseResourceTracker(RT2
);
515 TEST_F(OrcCAPITestBase
, DISABLED_AddObjectBuffer
) {
517 TEST_F(OrcCAPITestBase
, AddObjectBuffer
) {
519 LLVMOrcObjectLayerRef ObjLinkingLayer
= LLVMOrcLLJITGetObjLinkingLayer(Jit
);
520 LLVMMemoryBufferRef ObjBuffer
= createTestObject(SumExample
, "sum.ll");
522 if (LLVMErrorRef E
= LLVMOrcObjectLayerAddObjectFile(ObjLinkingLayer
,
523 MainDylib
, ObjBuffer
))
524 FAIL() << "Failed to add object file to ObjLinkingLayer (triple = "
525 << TargetTriple
<< "): " << toString(E
);
527 LLVMOrcJITTargetAddress SumAddr
;
528 if (LLVMErrorRef E
= LLVMOrcLLJITLookup(Jit
, &SumAddr
, "sum"))
529 FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple
530 << "): " << toString(E
);
531 ASSERT_TRUE(!!SumAddr
);
534 // JITLink debug support plugins put information about JITed code in this GDB
535 // JIT Interface global from OrcTargetProcess.
536 extern "C" struct jit_descriptor __jit_debug_descriptor
;
538 static void *findLastDebugDescriptorEntryPtr() {
539 struct jit_code_entry
*Last
= __jit_debug_descriptor
.first_entry
;
540 while (Last
&& Last
->next_entry
)
541 Last
= Last
->next_entry
;
545 #if defined(_AIX) or not(defined(__ELF__) or defined(__MACH__))
546 TEST_F(OrcCAPITestBase
, DISABLED_EnableDebugSupport
) {
548 static LLVM_ATTRIBUTE_USED
void linkComponents() {
549 errs() << "Linking in runtime functions\n"
550 << (void *)&llvm_orc_registerJITLoaderGDBWrapper
<< '\n'
551 << (void *)&llvm_orc_registerJITLoaderGDBAllocAction
<< '\n';
553 TEST_F(OrcCAPITestBase
, EnableDebugSupport
) {
555 void *Before
= findLastDebugDescriptorEntryPtr();
556 LLVMMemoryBufferRef ObjBuffer
= createTestObject(SumDebugExample
, "sum.ll");
557 LLVMOrcObjectLayerRef ObjLayer
= LLVMOrcLLJITGetObjLinkingLayer(Jit
);
559 if (LLVMErrorRef E
= LLVMOrcLLJITEnableDebugSupport(Jit
)) {
560 EXPECT_FALSE(isa
<ObjectLinkingLayer
>(unwrap(ObjLayer
)))
561 << "Error testing LLJIT debug support "
562 << "(triple = " << TargetTriple
<< "): " << toString(E
);
563 GTEST_SKIP() << "LLJIT C bindings provide debug support only for JITLink";
567 LLVMOrcObjectLayerAddObjectFile(ObjLayer
, MainDylib
, ObjBuffer
))
568 FAIL() << "Failed to add object file to ObjLinkingLayer (triple = "
569 << TargetTriple
<< "): " << toString(E
);
571 LLVMOrcJITTargetAddress SumAddr
;
572 if (LLVMErrorRef E
= LLVMOrcLLJITLookup(Jit
, &SumAddr
, "sum"))
573 FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple
574 << "): " << toString(E
);
576 void *After
= findLastDebugDescriptorEntryPtr();
577 ASSERT_NE(Before
, After
);
581 TEST_F(OrcCAPITestBase
, DISABLED_ExecutionTest
) {
583 TEST_F(OrcCAPITestBase
, ExecutionTest
) {
585 using SumFunctionType
= int32_t (*)(int32_t, int32_t);
587 // This test performs OrcJIT compilation of a simple sum module
588 LLVMInitializeNativeAsmPrinter();
589 LLVMOrcThreadSafeModuleRef TSM
= createTestModule(SumExample
, "sum.ll");
590 if (LLVMErrorRef E
= LLVMOrcLLJITAddLLVMIRModule(Jit
, MainDylib
, TSM
))
591 FAIL() << "Failed to add LLVM IR module to LLJIT (triple = " << TargetTriple
592 << ")" << toString(E
);
593 LLVMOrcJITTargetAddress TestFnAddr
;
594 if (LLVMErrorRef E
= LLVMOrcLLJITLookup(Jit
, &TestFnAddr
, "sum"))
595 FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple
596 << "): " << toString(E
);
597 auto *SumFn
= (SumFunctionType
)(TestFnAddr
);
598 int32_t Result
= SumFn(1, 1);
599 ASSERT_EQ(2, Result
);
602 void Destroy(void *Ctx
) {}
606 void Materialize(void *Ctx
, LLVMOrcMaterializationResponsibilityRef MR
) {
607 LLVMOrcJITDylibRef JD
=
608 LLVMOrcMaterializationResponsibilityGetTargetDylib(MR
);
611 LLVMOrcExecutionSessionRef ES
=
612 LLVMOrcMaterializationResponsibilityGetExecutionSession(MR
);
615 LLVMOrcSymbolStringPoolEntryRef InitSym
=
616 LLVMOrcMaterializationResponsibilityGetInitializerSymbol(MR
);
617 ASSERT_TRUE(!InitSym
);
620 LLVMOrcCSymbolFlagsMapPairs Symbols
=
621 LLVMOrcMaterializationResponsibilityGetSymbols(MR
, &NumSymbols
);
623 ASSERT_TRUE(!!Symbols
);
624 ASSERT_EQ(NumSymbols
, (size_t)1);
626 LLVMOrcSymbolStringPoolEntryRef
*RequestedSymbols
=
627 LLVMOrcMaterializationResponsibilityGetRequestedSymbols(MR
, &NumSymbols
);
629 ASSERT_TRUE(!!RequestedSymbols
);
630 ASSERT_EQ(NumSymbols
, (size_t)1);
632 LLVMOrcCSymbolFlagsMapPair TargetSym
= Symbols
[0];
634 ASSERT_EQ(RequestedSymbols
[0], TargetSym
.Name
);
635 LLVMOrcRetainSymbolStringPoolEntry(TargetSym
.Name
);
637 LLVMOrcDisposeCSymbolFlagsMap(Symbols
);
638 LLVMOrcDisposeSymbols(RequestedSymbols
);
640 LLVMOrcJITTargetAddress Addr
= (LLVMOrcJITTargetAddress
)(&TargetFn
);
642 LLVMJITSymbolFlags Flags
= {
643 LLVMJITSymbolGenericFlagsExported
| LLVMJITSymbolGenericFlagsCallable
, 0};
644 ASSERT_EQ(TargetSym
.Flags
.GenericFlags
, Flags
.GenericFlags
);
645 ASSERT_EQ(TargetSym
.Flags
.TargetFlags
, Flags
.TargetFlags
);
647 LLVMJITEvaluatedSymbol Sym
= {Addr
, Flags
};
649 LLVMOrcLLJITRef J
= (LLVMOrcLLJITRef
)Ctx
;
651 LLVMOrcSymbolStringPoolEntryRef OtherSymbol
=
652 LLVMOrcLLJITMangleAndIntern(J
, "other");
653 LLVMOrcSymbolStringPoolEntryRef DependencySymbol
=
654 LLVMOrcLLJITMangleAndIntern(J
, "dependency");
656 LLVMOrcRetainSymbolStringPoolEntry(OtherSymbol
);
657 LLVMOrcRetainSymbolStringPoolEntry(DependencySymbol
);
658 LLVMOrcCSymbolFlagsMapPair NewSymbols
[] = {
659 {OtherSymbol
, Flags
},
660 {DependencySymbol
, Flags
},
662 LLVMOrcMaterializationResponsibilityDefineMaterializing(MR
, NewSymbols
, 2);
664 LLVMOrcRetainSymbolStringPoolEntry(OtherSymbol
);
665 LLVMOrcMaterializationResponsibilityRef OtherMR
= NULL
;
667 LLVMErrorRef Err
= LLVMOrcMaterializationResponsibilityDelegate(
668 MR
, &OtherSymbol
, 1, &OtherMR
);
670 char *ErrMsg
= LLVMGetErrorMessage(Err
);
671 fprintf(stderr
, "Error: %s\n", ErrMsg
);
672 LLVMDisposeErrorMessage(ErrMsg
);
673 LLVMOrcMaterializationResponsibilityFailMaterialization(MR
);
674 LLVMOrcDisposeMaterializationResponsibility(MR
);
680 LLVMOrcCSymbolMapPair OtherPair
= {OtherSymbol
, Sym
};
681 LLVMOrcMaterializationUnitRef OtherMU
= LLVMOrcAbsoluteSymbols(&OtherPair
, 1);
682 // OtherSymbol is no longer owned by us
685 LLVMOrcMaterializationResponsibilityReplace(OtherMR
, OtherMU
);
687 char *ErrMsg
= LLVMGetErrorMessage(Err
);
688 fprintf(stderr
, "Error: %s\n", ErrMsg
);
689 LLVMDisposeErrorMessage(ErrMsg
);
691 LLVMOrcMaterializationResponsibilityFailMaterialization(OtherMR
);
692 LLVMOrcMaterializationResponsibilityFailMaterialization(MR
);
694 LLVMOrcDisposeMaterializationResponsibility(OtherMR
);
695 LLVMOrcDisposeMaterializationResponsibility(MR
);
696 LLVMOrcDisposeMaterializationUnit(OtherMU
);
700 LLVMOrcDisposeMaterializationResponsibility(OtherMR
);
702 // FIXME: Implement async lookup
703 LLVMOrcRetainSymbolStringPoolEntry(DependencySymbol
);
704 LLVMOrcCSymbolMapPair Pair
= {DependencySymbol
, Sym
};
705 LLVMOrcMaterializationResponsibilityNotifyResolved(MR
, &Pair
, 1);
706 // DependencySymbol no longer owned by us
708 Pair
= {TargetSym
.Name
, Sym
};
709 LLVMOrcMaterializationResponsibilityNotifyResolved(MR
, &Pair
, 1);
711 LLVMOrcRetainSymbolStringPoolEntry(TargetSym
.Name
);
712 LLVMOrcCDependenceMapPair Dependency
= {JD
, {&DependencySymbol
, 1}};
713 LLVMOrcCSymbolDependenceGroup DependenceSet
= {
714 /*.Symbols = */ {/*.Symbols = */ &TargetSym
.Name
, /* .Length = */ 1},
715 /* .Dependencies = */ &Dependency
,
716 /* .NumDependencies = */ 1};
718 LLVMOrcMaterializationResponsibilityNotifyEmitted(MR
, &DependenceSet
, 1);
719 LLVMOrcDisposeMaterializationResponsibility(MR
);
722 TEST_F(OrcCAPITestBase
, MaterializationResponsibility
) {
723 LLVMJITSymbolFlags Flags
= {
724 LLVMJITSymbolGenericFlagsExported
| LLVMJITSymbolGenericFlagsCallable
, 0};
725 LLVMOrcCSymbolFlagsMapPair Sym
= {LLVMOrcLLJITMangleAndIntern(Jit
, "foo"),
728 LLVMOrcMaterializationUnitRef MU
= LLVMOrcCreateCustomMaterializationUnit(
729 "MU", (void *)Jit
, &Sym
, 1, NULL
, &Materialize
, NULL
, &Destroy
);
730 LLVMOrcJITDylibRef JD
= LLVMOrcLLJITGetMainJITDylib(Jit
);
731 LLVMOrcJITDylibDefine(JD
, MU
);
733 LLVMOrcJITTargetAddress Addr
;
734 if (LLVMErrorRef Err
= LLVMOrcLLJITLookup(Jit
, &Addr
, "foo")) {
735 FAIL() << "foo was not materialized " << toString(Err
);
738 ASSERT_EQ(Addr
, (LLVMOrcJITTargetAddress
)&TargetFn
);
740 if (LLVMErrorRef Err
= LLVMOrcLLJITLookup(Jit
, &Addr
, "other")) {
741 FAIL() << "other was not materialized " << toString(Err
);
744 ASSERT_EQ(Addr
, (LLVMOrcJITTargetAddress
)&TargetFn
);
746 if (LLVMErrorRef Err
= LLVMOrcLLJITLookup(Jit
, &Addr
, "dependency")) {
747 FAIL() << "dependency was not materialized " << toString(Err
);
750 ASSERT_EQ(Addr
, (LLVMOrcJITTargetAddress
)&TargetFn
);
753 struct SuspendedLookupContext
{
754 std::function
<void()> AsyncWork
;
755 LLVMOrcSymbolStringPoolEntryRef NameToGenerate
;
756 JITTargetAddress AddrToGenerate
;
758 bool Disposed
= false;
759 bool QueryCompleted
= true;
762 static LLVMErrorRef
TryToGenerateWithSuspendedLookup(
763 LLVMOrcDefinitionGeneratorRef GeneratorObj
, void *RawCtx
,
764 LLVMOrcLookupStateRef
*LookupState
, LLVMOrcLookupKind Kind
,
765 LLVMOrcJITDylibRef JD
, LLVMOrcJITDylibLookupFlags JDLookupFlags
,
766 LLVMOrcCLookupSet LookupSet
, size_t LookupSetSize
) {
768 auto *Ctx
= static_cast<SuspendedLookupContext
*>(RawCtx
);
770 assert(LookupSetSize
== 1);
771 assert(LookupSet
[0].Name
== Ctx
->NameToGenerate
);
773 LLVMJITEvaluatedSymbol Sym
= {0x1234, {LLVMJITSymbolGenericFlagsExported
, 0}};
774 LLVMOrcRetainSymbolStringPoolEntry(LookupSet
[0].Name
);
775 LLVMOrcCSymbolMapPair Pair
= {LookupSet
[0].Name
, Sym
};
776 LLVMOrcCSymbolMapPair Pairs
[] = {Pair
};
777 LLVMOrcMaterializationUnitRef MU
= LLVMOrcAbsoluteSymbols(Pairs
, 1);
779 // Capture and reset LookupState to suspend the lookup. We'll continue it in
780 // the SuspendedLookup testcase below.
781 Ctx
->AsyncWork
= [LS
= *LookupState
, JD
, MU
]() {
782 LLVMErrorRef Err
= LLVMOrcJITDylibDefine(JD
, MU
);
783 LLVMOrcLookupStateContinueLookup(LS
, Err
);
785 *LookupState
= nullptr;
786 return LLVMErrorSuccess
;
789 static void DisposeSuspendedLookupContext(void *Ctx
) {
790 static_cast<SuspendedLookupContext
*>(Ctx
)->Disposed
= true;
794 suspendLookupTestLookupHandlerCallback(LLVMErrorRef Err
,
795 LLVMOrcCSymbolMapPairs Result
,
796 size_t NumPairs
, void *RawCtx
) {
798 FAIL() << "Suspended DefinitionGenerator did not create symbol \"foo\": "
803 EXPECT_EQ(NumPairs
, 1U)
804 << "Unexpected number of result entries: expected 1, got " << NumPairs
;
806 auto *Ctx
= static_cast<SuspendedLookupContext
*>(RawCtx
);
807 EXPECT_EQ(Result
[0].Name
, Ctx
->NameToGenerate
);
808 EXPECT_EQ(Result
[0].Sym
.Address
, Ctx
->AddrToGenerate
);
810 Ctx
->QueryCompleted
= true;
813 TEST_F(OrcCAPITestBase
, SuspendedLookup
) {
814 // Test that we can suspend lookup in a custom generator.
815 SuspendedLookupContext Ctx
;
816 Ctx
.NameToGenerate
= LLVMOrcLLJITMangleAndIntern(Jit
, "foo");
817 Ctx
.AddrToGenerate
= 0x1234;
820 LLVMOrcJITDylibAddGenerator(MainDylib
,
821 LLVMOrcCreateCustomCAPIDefinitionGenerator(
822 &TryToGenerateWithSuspendedLookup
, &Ctx
,
823 DisposeSuspendedLookupContext
));
825 // Expect no work to do before the lookup.
826 EXPECT_FALSE(Ctx
.AsyncWork
) << "Unexpected generator work before lookup";
828 // Issue lookup. This should trigger the generator, but generation should
830 LLVMOrcCJITDylibSearchOrderElement SO
[] = {
831 {MainDylib
, LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly
}};
832 LLVMOrcRetainSymbolStringPoolEntry(Ctx
.NameToGenerate
);
833 LLVMOrcCLookupSetElement LS
[] = {
834 {Ctx
.NameToGenerate
, LLVMOrcSymbolLookupFlagsRequiredSymbol
}};
835 LLVMOrcExecutionSessionLookup(ExecutionSession
, LLVMOrcLookupKindStatic
, SO
,
837 suspendLookupTestLookupHandlerCallback
, &Ctx
);
839 // Expect that we now have generator work to do.
840 EXPECT_TRUE(Ctx
.AsyncWork
)
841 << "Failed to generator (or failed to suspend generator)";
843 // Do the work. This should allow the query to complete.
846 // Check that the query completed.
847 EXPECT_TRUE(Ctx
.QueryCompleted
);
849 // Release our local copy of the string.
850 LLVMOrcReleaseSymbolStringPoolEntry(Ctx
.NameToGenerate
);
852 // Explicitly tear down the JIT.
853 LLVMOrcDisposeLLJIT(Jit
);
856 // Check that the generator context was "destroyed".
857 EXPECT_TRUE(Ctx
.Disposed
);