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/Orc.h" 13 #include "gtest/gtest.h" 14 15 #include "llvm/ADT/Triple.h" 16 #include "llvm/ExecutionEngine/Orc/CompileUtils.h" 17 #include "llvm/IR/LLVMContext.h" 18 #include "llvm/IR/Module.h" 19 #include "llvm/IRReader/IRReader.h" 20 #include "llvm/Support/Error.h" 21 #include "llvm/Support/SourceMgr.h" 22 #include <string> 23 24 using namespace llvm; 25 using namespace llvm::orc; 26 27 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule, LLVMOrcThreadSafeModuleRef) 28 29 // OrcCAPITestBase contains several helper methods and pointers for unit tests 30 // written for the LLVM-C API. It provides the following helpers: 31 // 32 // 1. Jit: an LLVMOrcLLJIT instance which is freed upon test exit 33 // 2. ExecutionSession: the LLVMOrcExecutionSession for the JIT 34 // 3. MainDylib: the main JITDylib for the LLJIT instance 35 // 4. materializationUnitFn: function pointer to an empty function, used for 36 // materialization unit testing 37 // 5. definitionGeneratorFn: function pointer for a basic 38 // LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction 39 // 6. createTestModule: helper method for creating a basic thread-safe-module 40 class OrcCAPITestBase : public testing::Test { 41 protected: 42 LLVMOrcLLJITRef Jit = nullptr; 43 LLVMOrcExecutionSessionRef ExecutionSession = nullptr; 44 LLVMOrcJITDylibRef MainDylib = nullptr; 45 46 public: 47 static void SetUpTestCase() { 48 LLVMInitializeNativeTarget(); 49 LLVMInitializeNativeAsmParser(); 50 LLVMInitializeNativeAsmPrinter(); 51 52 // Attempt to set up a JIT instance once to verify that we can. 53 LLVMOrcJITTargetMachineBuilderRef JTMB = nullptr; 54 if (LLVMErrorRef E = LLVMOrcJITTargetMachineBuilderDetectHost(&JTMB)) { 55 // If setup fails then disable these tests. 56 LLVMConsumeError(E); 57 TargetSupported = false; 58 return; 59 } 60 61 // Capture the target triple. We'll use it for both verification that 62 // this target is *supposed* to be supported, and error messages in 63 // the case that it fails anyway. 64 char *TT = LLVMOrcJITTargetMachineBuilderGetTargetTriple(JTMB); 65 TargetTriple = TT; 66 LLVMDisposeMessage(TT); 67 68 if (!isSupported(TargetTriple)) { 69 // If this triple isn't supported then bail out. 70 TargetSupported = false; 71 LLVMOrcDisposeJITTargetMachineBuilder(JTMB); 72 return; 73 } 74 75 LLVMOrcLLJITBuilderRef Builder = LLVMOrcCreateLLJITBuilder(); 76 LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(Builder, JTMB); 77 LLVMOrcLLJITRef J; 78 if (LLVMErrorRef E = LLVMOrcCreateLLJIT(&J, Builder)) { 79 // If setup fails then disable these tests. 80 TargetSupported = false; 81 LLVMConsumeError(E); 82 return; 83 } 84 85 LLVMOrcDisposeLLJIT(J); 86 TargetSupported = true; 87 } 88 89 void SetUp() override { 90 if (!TargetSupported) 91 GTEST_SKIP(); 92 93 LLVMOrcJITTargetMachineBuilderRef JTMB = nullptr; 94 LLVMErrorRef E1 = LLVMOrcJITTargetMachineBuilderDetectHost(&JTMB); 95 assert(E1 == LLVMErrorSuccess && "Expected call to detect host to succeed"); 96 (void)E1; 97 98 LLVMOrcLLJITBuilderRef Builder = LLVMOrcCreateLLJITBuilder(); 99 LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(Builder, JTMB); 100 LLVMErrorRef E2 = LLVMOrcCreateLLJIT(&Jit, Builder); 101 assert(E2 == LLVMErrorSuccess && 102 "Expected call to create LLJIT to succeed"); 103 (void)E2; 104 ExecutionSession = LLVMOrcLLJITGetExecutionSession(Jit); 105 MainDylib = LLVMOrcLLJITGetMainJITDylib(Jit); 106 } 107 void TearDown() override { 108 LLVMOrcDisposeLLJIT(Jit); 109 Jit = nullptr; 110 } 111 112 protected: 113 static bool isSupported(StringRef Triple) { 114 // TODO: Print error messages in failure logs, use them to audit this list. 115 // Some architectures may be unsupportable or missing key components, but 116 // some may just be failing due to bugs in this testcase. 117 if (Triple.startswith("armv7") || Triple.startswith("armv8l")) 118 return false; 119 llvm::Triple T(Triple); 120 if (T.isOSAIX() && T.isPPC64()) 121 return false; 122 return true; 123 } 124 125 static void materializationUnitFn() {} 126 127 // Stub definition generator, where all Names are materialized from the 128 // materializationUnitFn() test function and defined into the JIT Dylib 129 static LLVMErrorRef 130 definitionGeneratorFn(LLVMOrcDefinitionGeneratorRef G, void *Ctx, 131 LLVMOrcLookupStateRef *LS, LLVMOrcLookupKind K, 132 LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags F, 133 LLVMOrcCLookupSet Names, size_t NamesCount) { 134 for (size_t I = 0; I < NamesCount; I++) { 135 LLVMOrcCLookupSetElement Element = Names[I]; 136 LLVMOrcJITTargetAddress Addr = 137 (LLVMOrcJITTargetAddress)(&materializationUnitFn); 138 LLVMJITSymbolFlags Flags = {LLVMJITSymbolGenericFlagsWeak, 0}; 139 LLVMJITEvaluatedSymbol Sym = {Addr, Flags}; 140 LLVMOrcRetainSymbolStringPoolEntry(Element.Name); 141 LLVMJITCSymbolMapPair Pair = {Element.Name, Sym}; 142 LLVMJITCSymbolMapPair Pairs[] = {Pair}; 143 LLVMOrcMaterializationUnitRef MU = LLVMOrcAbsoluteSymbols(Pairs, 1); 144 LLVMErrorRef Err = LLVMOrcJITDylibDefine(JD, MU); 145 if (Err) 146 return Err; 147 } 148 return LLVMErrorSuccess; 149 } 150 151 static Error createSMDiagnosticError(llvm::SMDiagnostic &Diag) { 152 std::string Msg; 153 { 154 raw_string_ostream OS(Msg); 155 Diag.print("", OS); 156 } 157 return make_error<StringError>(std::move(Msg), inconvertibleErrorCode()); 158 } 159 160 // Create an LLVM IR module from the given StringRef. 161 static Expected<std::unique_ptr<Module>> 162 parseTestModule(LLVMContext &Ctx, StringRef Source, StringRef Name) { 163 assert(TargetSupported && 164 "Attempted to create module for unsupported target"); 165 SMDiagnostic Err; 166 if (auto M = parseIR(MemoryBufferRef(Source, Name), Err, Ctx)) 167 return std::move(M); 168 return createSMDiagnosticError(Err); 169 } 170 171 // returns the sum of its two parameters 172 static LLVMOrcThreadSafeModuleRef createTestModule(StringRef Source, 173 StringRef Name) { 174 auto Ctx = std::make_unique<LLVMContext>(); 175 auto M = cantFail(parseTestModule(*Ctx, Source, Name)); 176 return wrap(new ThreadSafeModule(std::move(M), std::move(Ctx))); 177 } 178 179 static LLVMMemoryBufferRef createTestObject(StringRef Source, 180 StringRef Name) { 181 auto Ctx = std::make_unique<LLVMContext>(); 182 auto M = cantFail(parseTestModule(*Ctx, Source, Name)); 183 184 auto JTMB = cantFail(JITTargetMachineBuilder::detectHost()); 185 M->setDataLayout(cantFail(JTMB.getDefaultDataLayoutForTarget())); 186 auto TM = cantFail(JTMB.createTargetMachine()); 187 188 SimpleCompiler SC(*TM); 189 auto ObjBuffer = cantFail(SC(*M)); 190 return wrap(ObjBuffer.release()); 191 } 192 193 static std::string TargetTriple; 194 static bool TargetSupported; 195 }; 196 197 std::string OrcCAPITestBase::TargetTriple; 198 bool OrcCAPITestBase::TargetSupported = false; 199 200 namespace { 201 202 constexpr StringRef SumExample = 203 R"( 204 define i32 @sum(i32 %x, i32 %y) { 205 entry: 206 %r = add nsw i32 %x, %y 207 ret i32 %r 208 } 209 )"; 210 211 } // end anonymous namespace. 212 213 // Consumes the given error ref and returns the string error message. 214 static std::string toString(LLVMErrorRef E) { 215 char *ErrMsg = LLVMGetErrorMessage(E); 216 std::string Result(ErrMsg); 217 LLVMDisposeErrorMessage(ErrMsg); 218 return Result; 219 } 220 221 TEST_F(OrcCAPITestBase, SymbolStringPoolUniquing) { 222 LLVMOrcSymbolStringPoolEntryRef E1 = 223 LLVMOrcExecutionSessionIntern(ExecutionSession, "aaa"); 224 LLVMOrcSymbolStringPoolEntryRef E2 = 225 LLVMOrcExecutionSessionIntern(ExecutionSession, "aaa"); 226 LLVMOrcSymbolStringPoolEntryRef E3 = 227 LLVMOrcExecutionSessionIntern(ExecutionSession, "bbb"); 228 const char *SymbolName = LLVMOrcSymbolStringPoolEntryStr(E1); 229 ASSERT_EQ(E1, E2) << "String pool entries are not unique"; 230 ASSERT_NE(E1, E3) << "Unique symbol pool entries are equal"; 231 ASSERT_STREQ("aaa", SymbolName) << "String value of symbol is not equal"; 232 LLVMOrcReleaseSymbolStringPoolEntry(E1); 233 LLVMOrcReleaseSymbolStringPoolEntry(E2); 234 LLVMOrcReleaseSymbolStringPoolEntry(E3); 235 } 236 237 TEST_F(OrcCAPITestBase, JITDylibLookup) { 238 LLVMOrcJITDylibRef DoesNotExist = 239 LLVMOrcExecutionSessionGetJITDylibByName(ExecutionSession, "test"); 240 ASSERT_FALSE(!!DoesNotExist); 241 LLVMOrcJITDylibRef L1 = 242 LLVMOrcExecutionSessionCreateBareJITDylib(ExecutionSession, "test"); 243 LLVMOrcJITDylibRef L2 = 244 LLVMOrcExecutionSessionGetJITDylibByName(ExecutionSession, "test"); 245 ASSERT_EQ(L1, L2) << "Located JIT Dylib is not equal to original"; 246 } 247 248 TEST_F(OrcCAPITestBase, MaterializationUnitCreation) { 249 LLVMOrcSymbolStringPoolEntryRef Name = 250 LLVMOrcLLJITMangleAndIntern(Jit, "test"); 251 LLVMJITSymbolFlags Flags = {LLVMJITSymbolGenericFlagsWeak, 0}; 252 LLVMOrcJITTargetAddress Addr = 253 (LLVMOrcJITTargetAddress)(&materializationUnitFn); 254 LLVMJITEvaluatedSymbol Sym = {Addr, Flags}; 255 LLVMJITCSymbolMapPair Pair = {Name, Sym}; 256 LLVMJITCSymbolMapPair Pairs[] = {Pair}; 257 LLVMOrcMaterializationUnitRef MU = LLVMOrcAbsoluteSymbols(Pairs, 1); 258 LLVMOrcJITDylibDefine(MainDylib, MU); 259 LLVMOrcJITTargetAddress OutAddr; 260 if (LLVMErrorRef E = LLVMOrcLLJITLookup(Jit, &OutAddr, "test")) 261 FAIL() << "Failed to look up \"test\" symbol (triple = " << TargetTriple 262 << "): " << toString(E); 263 ASSERT_EQ(Addr, OutAddr); 264 } 265 266 TEST_F(OrcCAPITestBase, DefinitionGenerators) { 267 LLVMOrcDefinitionGeneratorRef Gen = 268 LLVMOrcCreateCustomCAPIDefinitionGenerator(&definitionGeneratorFn, 269 nullptr); 270 LLVMOrcJITDylibAddGenerator(MainDylib, Gen); 271 LLVMOrcJITTargetAddress OutAddr; 272 if (LLVMErrorRef E = LLVMOrcLLJITLookup(Jit, &OutAddr, "test")) 273 FAIL() << "The DefinitionGenerator did not create symbol \"test\" " 274 << "(triple = " << TargetTriple << "): " << toString(E); 275 LLVMOrcJITTargetAddress ExpectedAddr = 276 (LLVMOrcJITTargetAddress)(&materializationUnitFn); 277 ASSERT_EQ(ExpectedAddr, OutAddr); 278 } 279 280 TEST_F(OrcCAPITestBase, ResourceTrackerDefinitionLifetime) { 281 // This test case ensures that all symbols loaded into a JITDylib with a 282 // ResourceTracker attached are cleared from the JITDylib once the RT is 283 // removed. 284 LLVMOrcResourceTrackerRef RT = 285 LLVMOrcJITDylibCreateResourceTracker(MainDylib); 286 LLVMOrcThreadSafeModuleRef TSM = createTestModule(SumExample, "sum.ll"); 287 if (LLVMErrorRef E = LLVMOrcLLJITAddLLVMIRModuleWithRT(Jit, RT, TSM)) 288 FAIL() << "Failed to add LLVM IR module to LLJIT (triple = " << TargetTriple 289 << "): " << toString(E); 290 LLVMOrcJITTargetAddress TestFnAddr; 291 if (LLVMErrorRef E = LLVMOrcLLJITLookup(Jit, &TestFnAddr, "sum")) 292 FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple 293 << "): " << toString(E); 294 ASSERT_TRUE(!!TestFnAddr); 295 LLVMOrcResourceTrackerRemove(RT); 296 LLVMOrcJITTargetAddress OutAddr; 297 LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &OutAddr, "sum"); 298 ASSERT_TRUE(Err); 299 LLVMConsumeError(Err); 300 301 ASSERT_FALSE(OutAddr); 302 LLVMOrcReleaseResourceTracker(RT); 303 } 304 305 TEST_F(OrcCAPITestBase, ResourceTrackerTransfer) { 306 LLVMOrcResourceTrackerRef DefaultRT = 307 LLVMOrcJITDylibGetDefaultResourceTracker(MainDylib); 308 LLVMOrcResourceTrackerRef RT2 = 309 LLVMOrcJITDylibCreateResourceTracker(MainDylib); 310 LLVMOrcThreadSafeModuleRef TSM = createTestModule(SumExample, "sum.ll"); 311 if (LLVMErrorRef E = LLVMOrcLLJITAddLLVMIRModuleWithRT(Jit, DefaultRT, TSM)) 312 FAIL() << "Failed to add LLVM IR module to LLJIT (triple = " << TargetTriple 313 << "): " << toString(E); 314 LLVMOrcJITTargetAddress Addr; 315 if (LLVMErrorRef E = LLVMOrcLLJITLookup(Jit, &Addr, "sum")) 316 FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple 317 << "): " << toString(E); 318 LLVMOrcResourceTrackerTransferTo(DefaultRT, RT2); 319 LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "sum"); 320 ASSERT_FALSE(Err); 321 LLVMOrcReleaseResourceTracker(RT2); 322 } 323 324 TEST_F(OrcCAPITestBase, AddObjectBuffer) { 325 LLVMOrcObjectLayerRef ObjLinkingLayer = LLVMOrcLLJITGetObjLinkingLayer(Jit); 326 LLVMMemoryBufferRef ObjBuffer = createTestObject(SumExample, "sum.ll"); 327 328 if (LLVMErrorRef E = LLVMOrcObjectLayerAddObjectFile(ObjLinkingLayer, 329 MainDylib, ObjBuffer)) 330 FAIL() << "Failed to add object file to ObjLinkingLayer (triple = " 331 << TargetTriple << "): " << toString(E); 332 333 LLVMOrcJITTargetAddress SumAddr; 334 if (LLVMErrorRef E = LLVMOrcLLJITLookup(Jit, &SumAddr, "sum")) 335 FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple 336 << "): " << toString(E); 337 ASSERT_TRUE(!!SumAddr); 338 } 339 340 TEST_F(OrcCAPITestBase, ExecutionTest) { 341 using SumFunctionType = int32_t (*)(int32_t, int32_t); 342 343 // This test performs OrcJIT compilation of a simple sum module 344 LLVMInitializeNativeAsmPrinter(); 345 LLVMOrcThreadSafeModuleRef TSM = createTestModule(SumExample, "sum.ll"); 346 if (LLVMErrorRef E = LLVMOrcLLJITAddLLVMIRModule(Jit, MainDylib, TSM)) 347 FAIL() << "Failed to add LLVM IR module to LLJIT (triple = " << TargetTriple 348 << ")" << toString(E); 349 LLVMOrcJITTargetAddress TestFnAddr; 350 if (LLVMErrorRef E = LLVMOrcLLJITLookup(Jit, &TestFnAddr, "sum")) 351 FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple 352 << "): " << toString(E); 353 auto *SumFn = (SumFunctionType)(TestFnAddr); 354 int32_t Result = SumFn(1, 1); 355 ASSERT_EQ(2, Result); 356 } 357 358 void Destroy(void *Ctx) {} 359 360 void TargetFn() {} 361 362 void Materialize(void *Ctx, LLVMOrcMaterializationResponsibilityRef MR) { 363 LLVMOrcJITDylibRef JD = 364 LLVMOrcMaterializationResponsibilityGetTargetDylib(MR); 365 ASSERT_TRUE(!!JD); 366 367 LLVMOrcExecutionSessionRef ES = 368 LLVMOrcMaterializationResponsibilityGetExecutionSession(MR); 369 ASSERT_TRUE(!!ES); 370 371 LLVMOrcSymbolStringPoolEntryRef InitSym = 372 LLVMOrcMaterializationResponsibilityGetInitializerSymbol(MR); 373 ASSERT_TRUE(!InitSym); 374 375 size_t NumSymbols; 376 LLVMOrcCSymbolFlagsMapPairs Symbols = 377 LLVMOrcMaterializationResponsibilityGetSymbols(MR, &NumSymbols); 378 379 ASSERT_TRUE(!!Symbols); 380 ASSERT_EQ(NumSymbols, (size_t)1); 381 382 LLVMOrcSymbolStringPoolEntryRef *RequestedSymbols = 383 LLVMOrcMaterializationResponsibilityGetRequestedSymbols(MR, &NumSymbols); 384 385 ASSERT_TRUE(!!RequestedSymbols); 386 ASSERT_EQ(NumSymbols, (size_t)1); 387 388 LLVMOrcCSymbolFlagsMapPair TargetSym = Symbols[0]; 389 390 ASSERT_EQ(RequestedSymbols[0], TargetSym.Name); 391 LLVMOrcRetainSymbolStringPoolEntry(TargetSym.Name); 392 393 LLVMOrcDisposeCSymbolFlagsMap(Symbols); 394 LLVMOrcDisposeSymbols(RequestedSymbols); 395 396 LLVMOrcJITTargetAddress Addr = (LLVMOrcJITTargetAddress)(&TargetFn); 397 398 LLVMJITSymbolFlags Flags = { 399 LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0}; 400 ASSERT_EQ(TargetSym.Flags.GenericFlags, Flags.GenericFlags); 401 ASSERT_EQ(TargetSym.Flags.TargetFlags, Flags.TargetFlags); 402 403 LLVMJITEvaluatedSymbol Sym = {Addr, Flags}; 404 405 LLVMOrcLLJITRef J = (LLVMOrcLLJITRef)Ctx; 406 407 LLVMOrcSymbolStringPoolEntryRef OtherSymbol = 408 LLVMOrcLLJITMangleAndIntern(J, "other"); 409 LLVMOrcSymbolStringPoolEntryRef DependencySymbol = 410 LLVMOrcLLJITMangleAndIntern(J, "dependency"); 411 412 LLVMOrcRetainSymbolStringPoolEntry(OtherSymbol); 413 LLVMOrcRetainSymbolStringPoolEntry(DependencySymbol); 414 LLVMOrcCSymbolFlagsMapPair NewSymbols[] = { 415 {OtherSymbol, Flags}, 416 {DependencySymbol, Flags}, 417 }; 418 LLVMOrcMaterializationResponsibilityDefineMaterializing(MR, NewSymbols, 2); 419 420 LLVMOrcRetainSymbolStringPoolEntry(OtherSymbol); 421 LLVMOrcMaterializationResponsibilityRef OtherMR = NULL; 422 { 423 LLVMErrorRef Err = LLVMOrcMaterializationResponsibilityDelegate( 424 MR, &OtherSymbol, 1, &OtherMR); 425 if (Err) { 426 char *ErrMsg = LLVMGetErrorMessage(Err); 427 fprintf(stderr, "Error: %s\n", ErrMsg); 428 LLVMDisposeErrorMessage(ErrMsg); 429 LLVMOrcMaterializationResponsibilityFailMaterialization(MR); 430 LLVMOrcDisposeMaterializationResponsibility(MR); 431 return; 432 } 433 } 434 assert(OtherMR); 435 436 LLVMJITCSymbolMapPair OtherPair = {OtherSymbol, Sym}; 437 LLVMOrcMaterializationUnitRef OtherMU = LLVMOrcAbsoluteSymbols(&OtherPair, 1); 438 // OtherSymbol is no longer owned by us 439 { 440 LLVMErrorRef Err = 441 LLVMOrcMaterializationResponsibilityReplace(OtherMR, OtherMU); 442 if (Err) { 443 char *ErrMsg = LLVMGetErrorMessage(Err); 444 fprintf(stderr, "Error: %s\n", ErrMsg); 445 LLVMDisposeErrorMessage(ErrMsg); 446 447 LLVMOrcMaterializationResponsibilityFailMaterialization(OtherMR); 448 LLVMOrcMaterializationResponsibilityFailMaterialization(MR); 449 450 LLVMOrcDisposeMaterializationResponsibility(OtherMR); 451 LLVMOrcDisposeMaterializationResponsibility(MR); 452 LLVMOrcDisposeMaterializationUnit(OtherMU); 453 return; 454 } 455 } 456 LLVMOrcDisposeMaterializationResponsibility(OtherMR); 457 458 // FIXME: Implement async lookup 459 // A real test of the dependence tracking in the success case would require 460 // async lookups. You could: 461 // 1. Materialize foo, making foo depend on other. 462 // 2. In the caller, verify that the lookup callback for foo has not run (due 463 // to the dependence) 464 // 3. Materialize other by looking it up. 465 // 4. In the caller, verify that the lookup callback for foo has now run. 466 467 LLVMOrcRetainSymbolStringPoolEntry(TargetSym.Name); 468 LLVMOrcRetainSymbolStringPoolEntry(DependencySymbol); 469 LLVMOrcCDependenceMapPair Dependency = {JD, {&DependencySymbol, 1}}; 470 LLVMOrcMaterializationResponsibilityAddDependencies(MR, TargetSym.Name, 471 &Dependency, 1); 472 473 LLVMOrcRetainSymbolStringPoolEntry(DependencySymbol); 474 LLVMOrcMaterializationResponsibilityAddDependenciesForAll(MR, &Dependency, 1); 475 476 // See FIXME above 477 LLVMJITCSymbolMapPair Pair = {DependencySymbol, Sym}; 478 LLVMOrcMaterializationResponsibilityNotifyResolved(MR, &Pair, 1); 479 // DependencySymbol no longer owned by us 480 481 Pair = {TargetSym.Name, Sym}; 482 LLVMOrcMaterializationResponsibilityNotifyResolved(MR, &Pair, 1); 483 484 LLVMOrcMaterializationResponsibilityNotifyEmitted(MR); 485 LLVMOrcDisposeMaterializationResponsibility(MR); 486 return; 487 } 488 489 TEST_F(OrcCAPITestBase, MaterializationResponsibility) { 490 LLVMJITSymbolFlags Flags = { 491 LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0}; 492 LLVMOrcCSymbolFlagsMapPair Sym = {LLVMOrcLLJITMangleAndIntern(Jit, "foo"), 493 Flags}; 494 495 LLVMOrcMaterializationUnitRef MU = LLVMOrcCreateCustomMaterializationUnit( 496 "MU", (void *)Jit, &Sym, 1, NULL, &Materialize, NULL, &Destroy); 497 LLVMOrcJITDylibRef JD = LLVMOrcLLJITGetMainJITDylib(Jit); 498 LLVMOrcJITDylibDefine(JD, MU); 499 500 LLVMOrcJITTargetAddress Addr; 501 if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "foo")) { 502 FAIL() << "foo was not materialized " << toString(Err); 503 } 504 ASSERT_TRUE(!!Addr); 505 ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn); 506 507 if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "other")) { 508 FAIL() << "other was not materialized " << toString(Err); 509 } 510 ASSERT_TRUE(!!Addr); 511 ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn); 512 513 if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "dependency")) { 514 FAIL() << "dependency was not materialized " << toString(Err); 515 } 516 ASSERT_TRUE(!!Addr); 517 ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn); 518 } 519