xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp (revision 9f73c69e5aa2d1112f72b2e18d4ae0462a6a2042)
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 "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"
15 
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"
28 #include <string>
29 
30 using namespace llvm;
31 using namespace llvm::orc;
32 
33 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ObjectLayer, LLVMOrcObjectLayerRef)
34 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule, LLVMOrcThreadSafeModuleRef)
35 
36 // A class that sets strings for extension attributes by querying
37 // TargetLibraryInfo.
38 struct TargetI32ArgExtensions {
39   std::string Ret;
40   std::string Arg;
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() + " ";
47   }
48 };
49 
50 // OrcCAPITestBase contains several helper methods and pointers for unit tests
51 // written for the LLVM-C API. It provides the following helpers:
52 //
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 {
62 protected:
63   LLVMOrcLLJITRef Jit = nullptr;
64   LLVMOrcExecutionSessionRef ExecutionSession = nullptr;
65   LLVMOrcJITDylibRef MainDylib = nullptr;
66 
67 public:
68   static void SetUpTestCase() {
69     LLVMInitializeNativeTarget();
70     LLVMInitializeNativeAsmParser();
71     LLVMInitializeNativeAsmPrinter();
72 
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.
77       LLVMConsumeError(E);
78       TargetSupported = false;
79       return;
80     }
81 
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);
86     TargetTriple = TT;
87     LLVMDisposeMessage(TT);
88 
89     if (!isSupported(TargetTriple)) {
90       // If this triple isn't supported then bail out.
91       TargetSupported = false;
92       LLVMOrcDisposeJITTargetMachineBuilder(JTMB);
93       return;
94     }
95 
96     LLVMOrcLLJITBuilderRef Builder = LLVMOrcCreateLLJITBuilder();
97     LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(Builder, JTMB);
98     LLVMOrcLLJITRef J;
99     if (LLVMErrorRef E = LLVMOrcCreateLLJIT(&J, Builder)) {
100       // If setup fails then disable these tests.
101       TargetSupported = false;
102       LLVMConsumeError(E);
103       return;
104     }
105 
106     LLVMOrcDisposeLLJIT(J);
107     TargetSupported = true;
108 
109     // Create test functions in text format, with the proper extension
110     // attributes.
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)"
116          << R"( {
117           entry:
118           %r = add nsw i32 %x, %y
119           ret i32 %r
120           }
121         )";
122       SumExample = OS.str();
123 
124       OS << R"(
125           !llvm.module.flags = !{!0}
126           !llvm.dbg.cu = !{!1}
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")
130         )";
131       SumDebugExample = OS.str();
132     }
133   }
134 
135   void SetUp() override {
136     if (!TargetSupported)
137       GTEST_SKIP();
138 
139     LLVMOrcJITTargetMachineBuilderRef JTMB = nullptr;
140     LLVMErrorRef E1 = LLVMOrcJITTargetMachineBuilderDetectHost(&JTMB);
141     assert(E1 == LLVMErrorSuccess && "Expected call to detect host to succeed");
142     (void)E1;
143 
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");
149     (void)E2;
150     ExecutionSession = LLVMOrcLLJITGetExecutionSession(Jit);
151     MainDylib = LLVMOrcLLJITGetMainJITDylib(Jit);
152   }
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.
156     if (Jit) {
157       LLVMOrcDisposeLLJIT(Jit);
158       Jit = nullptr;
159     }
160   }
161 
162 protected:
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"))
168       return false;
169     return true;
170   }
171 
172   static void materializationUnitFn() {}
173 
174   // Stub definition generator, where all Names are materialized from the
175   // materializationUnitFn() test function and defined into the JIT Dylib
176   static LLVMErrorRef
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);
192       if (Err)
193         return Err;
194     }
195     return LLVMErrorSuccess;
196   }
197 
198   static Error createSMDiagnosticError(llvm::SMDiagnostic &Diag) {
199     std::string Msg;
200     {
201       raw_string_ostream OS(Msg);
202       Diag.print("", OS);
203     }
204     return make_error<StringError>(std::move(Msg), inconvertibleErrorCode());
205   }
206 
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");
212     SMDiagnostic Err;
213     if (auto M = parseIR(MemoryBufferRef(Source, Name), Err, Ctx))
214       return std::move(M);
215     return createSMDiagnosticError(Err);
216   }
217 
218   // returns the sum of its two parameters
219   static LLVMOrcThreadSafeModuleRef createTestModule(StringRef Source,
220                                                      StringRef Name) {
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)));
224   }
225 
226   static LLVMMemoryBufferRef createTestObject(StringRef Source,
227                                               StringRef Name) {
228     auto Ctx = std::make_unique<LLVMContext>();
229     auto M = cantFail(parseTestModule(*Ctx, Source, Name));
230 
231     auto JTMB = cantFail(JITTargetMachineBuilder::detectHost());
232     M->setDataLayout(cantFail(JTMB.getDefaultDataLayoutForTarget()));
233     auto TM = cantFail(JTMB.createTargetMachine());
234 
235     SimpleCompiler SC(*TM);
236     auto ObjBuffer = cantFail(SC(*M));
237     return wrap(ObjBuffer.release());
238   }
239 
240   static std::string TargetTriple;
241   static bool TargetSupported;
242 
243   static std::string SumExample;
244   static std::string SumDebugExample;
245 };
246 
247 std::string OrcCAPITestBase::TargetTriple;
248 bool OrcCAPITestBase::TargetSupported = false;
249 
250 std::string OrcCAPITestBase::SumExample;
251 std::string OrcCAPITestBase::SumDebugExample;
252 
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);
258   return Result;
259 }
260 
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);
275 }
276 
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";
286 }
287 
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);
306 }
307 
308 struct ExecutionSessionLookupHelper {
309   bool ExpectSuccess = true;
310   bool CallbackReceived = false;
311   size_t NumExpectedPairs;
312   LLVMOrcCSymbolMapPair *ExpectedMapping;
313 };
314 
315 static void executionSessionLookupHandlerCallback(LLVMErrorRef Err,
316                                                   LLVMOrcCSymbolMapPairs Result,
317                                                   size_t NumPairs,
318                                                   void *RawCtx) {
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 "
325         << NumPairs;
326     auto ExpectedMappingEnd = Ctx->ExpectedMapping + Ctx->NumExpectedPairs;
327     for (unsigned I = 0; I != NumPairs; ++I) {
328       auto J =
329           std::find_if(Ctx->ExpectedMapping, ExpectedMappingEnd,
330                        [N = Result[I].Name](const LLVMOrcCSymbolMapPair &Val) {
331                          return Val.Name == N;
332                        });
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);
341       }
342     }
343   } else
344     EXPECT_THAT_ERROR(unwrap(Err), Failed());
345 }
346 
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) }.
351   //
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.
355   //
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).
361 
362   ExecutionSessionLookupHelper H;
363   LLVMOrcSymbolStringPoolEntryRef Foo = LLVMOrcLLJITMangleAndIntern(Jit, "Foo");
364   LLVMOrcSymbolStringPoolEntryRef Bar = LLVMOrcLLJITMangleAndIntern(Jit, "Bar");
365   LLVMOrcSymbolStringPoolEntryRef Baz = LLVMOrcLLJITMangleAndIntern(Jit, "Baz");
366 
367   // Create ExtraJD.
368   LLVMOrcJITDylibRef ExtraJD = nullptr;
369   if (auto E = LLVMOrcExecutionSessionCreateJITDylib(ExecutionSession, &ExtraJD,
370                                                      "ExtraJD")) {
371     FAIL() << "Unexpected error while creating JITDylib \"ExtraJD\" (triple = "
372            << TargetTriple << "): " << toString(E);
373     return;
374   }
375 
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);
387 
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);
397 
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;
404 
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}};
410 
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,
420                                 &H);
421 
422   EXPECT_TRUE(H.CallbackReceived) << "Lookup callback never received";
423 
424   // Release our local string ptrs.
425   LLVMOrcReleaseSymbolStringPoolEntry(Baz);
426   LLVMOrcReleaseSymbolStringPoolEntry(Bar);
427   LLVMOrcReleaseSymbolStringPoolEntry(Foo);
428 }
429 
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.
433 
434   ExecutionSessionLookupHelper H;
435   H.ExpectSuccess = false;
436 
437   LLVMOrcCJITDylibSearchOrderElement SO[] = {
438       {MainDylib, LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly}};
439   LLVMOrcCLookupSetElement LS[] = {{LLVMOrcLLJITMangleAndIntern(Jit, "Foo"),
440                                     LLVMOrcSymbolLookupFlagsRequiredSymbol}};
441   LLVMOrcExecutionSessionLookup(ExecutionSession, LLVMOrcLookupKindStatic, SO,
442                                 1, LS, 1, executionSessionLookupHandlerCallback,
443                                 &H);
444 
445   EXPECT_TRUE(H.CallbackReceived) << "Lookup callback never received";
446 }
447 
448 TEST_F(OrcCAPITestBase, DefinitionGenerators) {
449   LLVMOrcDefinitionGeneratorRef Gen =
450       LLVMOrcCreateCustomCAPIDefinitionGenerator(&definitionGeneratorFn,
451                                                  nullptr, nullptr);
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);
460 }
461 
462 #if defined(_AIX)
463 TEST_F(OrcCAPITestBase, DISABLED_ResourceTrackerDefinitionLifetime) {
464 #else
465 TEST_F(OrcCAPITestBase, ResourceTrackerDefinitionLifetime) {
466 #endif
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
469   // removed.
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");
484   ASSERT_TRUE(Err);
485   LLVMConsumeError(Err);
486 
487   ASSERT_FALSE(OutAddr);
488   LLVMOrcReleaseResourceTracker(RT);
489 }
490 
491 #if defined(_AIX)
492 TEST_F(OrcCAPITestBase, DISABLED_ResourceTrackerTransfer) {
493 #else
494 TEST_F(OrcCAPITestBase, ResourceTrackerTransfer) {
495 #endif
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");
510   ASSERT_FALSE(Err);
511   LLVMOrcReleaseResourceTracker(RT2);
512 }
513 
514 #if defined(_AIX)
515 TEST_F(OrcCAPITestBase, DISABLED_AddObjectBuffer) {
516 #else
517 TEST_F(OrcCAPITestBase, AddObjectBuffer) {
518 #endif
519   LLVMOrcObjectLayerRef ObjLinkingLayer = LLVMOrcLLJITGetObjLinkingLayer(Jit);
520   LLVMMemoryBufferRef ObjBuffer = createTestObject(SumExample, "sum.ll");
521 
522   if (LLVMErrorRef E = LLVMOrcObjectLayerAddObjectFile(ObjLinkingLayer,
523                                                        MainDylib, ObjBuffer))
524     FAIL() << "Failed to add object file to ObjLinkingLayer (triple = "
525            << TargetTriple << "): " << toString(E);
526 
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);
532 }
533 
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;
537 
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;
542   return Last;
543 }
544 
545 #if defined(_AIX) or not(defined(__ELF__) or defined(__MACH__))
546 TEST_F(OrcCAPITestBase, DISABLED_EnableDebugSupport) {
547 #else
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';
552 }
553 TEST_F(OrcCAPITestBase, EnableDebugSupport) {
554 #endif
555   void *Before = findLastDebugDescriptorEntryPtr();
556   LLVMMemoryBufferRef ObjBuffer = createTestObject(SumDebugExample, "sum.ll");
557   LLVMOrcObjectLayerRef ObjLayer = LLVMOrcLLJITGetObjLinkingLayer(Jit);
558 
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";
564   }
565 
566   if (LLVMErrorRef E =
567           LLVMOrcObjectLayerAddObjectFile(ObjLayer, MainDylib, ObjBuffer))
568     FAIL() << "Failed to add object file to ObjLinkingLayer (triple = "
569            << TargetTriple << "): " << toString(E);
570 
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);
575 
576   void *After = findLastDebugDescriptorEntryPtr();
577   ASSERT_NE(Before, After);
578 }
579 
580 #if defined(_AIX)
581 TEST_F(OrcCAPITestBase, DISABLED_ExecutionTest) {
582 #else
583 TEST_F(OrcCAPITestBase, ExecutionTest) {
584 #endif
585   using SumFunctionType = int32_t (*)(int32_t, int32_t);
586 
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);
600 }
601 
602 void Destroy(void *Ctx) {}
603 
604 void TargetFn() {}
605 
606 void Materialize(void *Ctx, LLVMOrcMaterializationResponsibilityRef MR) {
607   LLVMOrcJITDylibRef JD =
608       LLVMOrcMaterializationResponsibilityGetTargetDylib(MR);
609   ASSERT_TRUE(!!JD);
610 
611   LLVMOrcExecutionSessionRef ES =
612       LLVMOrcMaterializationResponsibilityGetExecutionSession(MR);
613   ASSERT_TRUE(!!ES);
614 
615   LLVMOrcSymbolStringPoolEntryRef InitSym =
616       LLVMOrcMaterializationResponsibilityGetInitializerSymbol(MR);
617   ASSERT_TRUE(!InitSym);
618 
619   size_t NumSymbols;
620   LLVMOrcCSymbolFlagsMapPairs Symbols =
621       LLVMOrcMaterializationResponsibilityGetSymbols(MR, &NumSymbols);
622 
623   ASSERT_TRUE(!!Symbols);
624   ASSERT_EQ(NumSymbols, (size_t)1);
625 
626   LLVMOrcSymbolStringPoolEntryRef *RequestedSymbols =
627       LLVMOrcMaterializationResponsibilityGetRequestedSymbols(MR, &NumSymbols);
628 
629   ASSERT_TRUE(!!RequestedSymbols);
630   ASSERT_EQ(NumSymbols, (size_t)1);
631 
632   LLVMOrcCSymbolFlagsMapPair TargetSym = Symbols[0];
633 
634   ASSERT_EQ(RequestedSymbols[0], TargetSym.Name);
635   LLVMOrcRetainSymbolStringPoolEntry(TargetSym.Name);
636 
637   LLVMOrcDisposeCSymbolFlagsMap(Symbols);
638   LLVMOrcDisposeSymbols(RequestedSymbols);
639 
640   LLVMOrcJITTargetAddress Addr = (LLVMOrcJITTargetAddress)(&TargetFn);
641 
642   LLVMJITSymbolFlags Flags = {
643       LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0};
644   ASSERT_EQ(TargetSym.Flags.GenericFlags, Flags.GenericFlags);
645   ASSERT_EQ(TargetSym.Flags.TargetFlags, Flags.TargetFlags);
646 
647   LLVMJITEvaluatedSymbol Sym = {Addr, Flags};
648 
649   LLVMOrcLLJITRef J = (LLVMOrcLLJITRef)Ctx;
650 
651   LLVMOrcSymbolStringPoolEntryRef OtherSymbol =
652       LLVMOrcLLJITMangleAndIntern(J, "other");
653   LLVMOrcSymbolStringPoolEntryRef DependencySymbol =
654       LLVMOrcLLJITMangleAndIntern(J, "dependency");
655 
656   LLVMOrcRetainSymbolStringPoolEntry(OtherSymbol);
657   LLVMOrcRetainSymbolStringPoolEntry(DependencySymbol);
658   LLVMOrcCSymbolFlagsMapPair NewSymbols[] = {
659       {OtherSymbol, Flags},
660       {DependencySymbol, Flags},
661   };
662   LLVMOrcMaterializationResponsibilityDefineMaterializing(MR, NewSymbols, 2);
663 
664   LLVMOrcRetainSymbolStringPoolEntry(OtherSymbol);
665   LLVMOrcMaterializationResponsibilityRef OtherMR = NULL;
666   {
667     LLVMErrorRef Err = LLVMOrcMaterializationResponsibilityDelegate(
668         MR, &OtherSymbol, 1, &OtherMR);
669     if (Err) {
670       char *ErrMsg = LLVMGetErrorMessage(Err);
671       fprintf(stderr, "Error: %s\n", ErrMsg);
672       LLVMDisposeErrorMessage(ErrMsg);
673       LLVMOrcMaterializationResponsibilityFailMaterialization(MR);
674       LLVMOrcDisposeMaterializationResponsibility(MR);
675       return;
676     }
677   }
678   assert(OtherMR);
679 
680   LLVMOrcCSymbolMapPair OtherPair = {OtherSymbol, Sym};
681   LLVMOrcMaterializationUnitRef OtherMU = LLVMOrcAbsoluteSymbols(&OtherPair, 1);
682   // OtherSymbol is no longer owned by us
683   {
684     LLVMErrorRef Err =
685         LLVMOrcMaterializationResponsibilityReplace(OtherMR, OtherMU);
686     if (Err) {
687       char *ErrMsg = LLVMGetErrorMessage(Err);
688       fprintf(stderr, "Error: %s\n", ErrMsg);
689       LLVMDisposeErrorMessage(ErrMsg);
690 
691       LLVMOrcMaterializationResponsibilityFailMaterialization(OtherMR);
692       LLVMOrcMaterializationResponsibilityFailMaterialization(MR);
693 
694       LLVMOrcDisposeMaterializationResponsibility(OtherMR);
695       LLVMOrcDisposeMaterializationResponsibility(MR);
696       LLVMOrcDisposeMaterializationUnit(OtherMU);
697       return;
698     }
699   }
700   LLVMOrcDisposeMaterializationResponsibility(OtherMR);
701 
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
707 
708   Pair = {TargetSym.Name, Sym};
709   LLVMOrcMaterializationResponsibilityNotifyResolved(MR, &Pair, 1);
710 
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};
717 
718   LLVMOrcMaterializationResponsibilityNotifyEmitted(MR, &DependenceSet, 1);
719   LLVMOrcDisposeMaterializationResponsibility(MR);
720 }
721 
722 TEST_F(OrcCAPITestBase, MaterializationResponsibility) {
723   LLVMJITSymbolFlags Flags = {
724       LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0};
725   LLVMOrcCSymbolFlagsMapPair Sym = {LLVMOrcLLJITMangleAndIntern(Jit, "foo"),
726                                     Flags};
727 
728   LLVMOrcMaterializationUnitRef MU = LLVMOrcCreateCustomMaterializationUnit(
729       "MU", (void *)Jit, &Sym, 1, NULL, &Materialize, NULL, &Destroy);
730   LLVMOrcJITDylibRef JD = LLVMOrcLLJITGetMainJITDylib(Jit);
731   LLVMOrcJITDylibDefine(JD, MU);
732 
733   LLVMOrcJITTargetAddress Addr;
734   if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "foo")) {
735     FAIL() << "foo was not materialized " << toString(Err);
736   }
737   ASSERT_TRUE(!!Addr);
738   ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn);
739 
740   if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "other")) {
741     FAIL() << "other was not materialized " << toString(Err);
742   }
743   ASSERT_TRUE(!!Addr);
744   ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn);
745 
746   if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "dependency")) {
747     FAIL() << "dependency was not materialized " << toString(Err);
748   }
749   ASSERT_TRUE(!!Addr);
750   ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn);
751 }
752 
753 struct SuspendedLookupContext {
754   std::function<void()> AsyncWork;
755   LLVMOrcSymbolStringPoolEntryRef NameToGenerate;
756   JITTargetAddress AddrToGenerate;
757 
758   bool Disposed = false;
759   bool QueryCompleted = true;
760 };
761 
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) {
767 
768   auto *Ctx = static_cast<SuspendedLookupContext *>(RawCtx);
769 
770   assert(LookupSetSize == 1);
771   assert(LookupSet[0].Name == Ctx->NameToGenerate);
772 
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);
778 
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);
784   };
785   *LookupState = nullptr;
786   return LLVMErrorSuccess;
787 }
788 
789 static void DisposeSuspendedLookupContext(void *Ctx) {
790   static_cast<SuspendedLookupContext *>(Ctx)->Disposed = true;
791 }
792 
793 static void
794 suspendLookupTestLookupHandlerCallback(LLVMErrorRef Err,
795                                        LLVMOrcCSymbolMapPairs Result,
796                                        size_t NumPairs, void *RawCtx) {
797   if (Err) {
798     FAIL() << "Suspended DefinitionGenerator did not create symbol \"foo\": "
799            << toString(Err);
800     return;
801   }
802 
803   EXPECT_EQ(NumPairs, 1U)
804       << "Unexpected number of result entries: expected 1, got " << NumPairs;
805 
806   auto *Ctx = static_cast<SuspendedLookupContext *>(RawCtx);
807   EXPECT_EQ(Result[0].Name, Ctx->NameToGenerate);
808   EXPECT_EQ(Result[0].Sym.Address, Ctx->AddrToGenerate);
809 
810   Ctx->QueryCompleted = true;
811 }
812 
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;
818 
819   // Add generator.
820   LLVMOrcJITDylibAddGenerator(MainDylib,
821                               LLVMOrcCreateCustomCAPIDefinitionGenerator(
822                                   &TryToGenerateWithSuspendedLookup, &Ctx,
823                                   DisposeSuspendedLookupContext));
824 
825   // Expect no work to do before the lookup.
826   EXPECT_FALSE(Ctx.AsyncWork) << "Unexpected generator work before lookup";
827 
828   // Issue lookup. This should trigger the generator, but generation should
829   // be suspended.
830   LLVMOrcCJITDylibSearchOrderElement SO[] = {
831       {MainDylib, LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly}};
832   LLVMOrcRetainSymbolStringPoolEntry(Ctx.NameToGenerate);
833   LLVMOrcCLookupSetElement LS[] = {
834       {Ctx.NameToGenerate, LLVMOrcSymbolLookupFlagsRequiredSymbol}};
835   LLVMOrcExecutionSessionLookup(ExecutionSession, LLVMOrcLookupKindStatic, SO,
836                                 1, LS, 1,
837                                 suspendLookupTestLookupHandlerCallback, &Ctx);
838 
839   // Expect that we now have generator work to do.
840   EXPECT_TRUE(Ctx.AsyncWork)
841       << "Failed to generator (or failed to suspend generator)";
842 
843   // Do the work. This should allow the query to complete.
844   Ctx.AsyncWork();
845 
846   // Check that the query completed.
847   EXPECT_TRUE(Ctx.QueryCompleted);
848 
849   // Release our local copy of the string.
850   LLVMOrcReleaseSymbolStringPoolEntry(Ctx.NameToGenerate);
851 
852   // Explicitly tear down the JIT.
853   LLVMOrcDisposeLLJIT(Jit);
854   Jit = nullptr;
855 
856   // Check that the generator context was "destroyed".
857   EXPECT_TRUE(Ctx.Disposed);
858 }
859