brintos

brintos / llvm-project-archived public Read only

0
0
Text · 32.7 KiB · 0ddbb33 Raw
858 lines · cpp
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-exception6//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 30using namespace llvm;31using namespace llvm::orc;32 33DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ObjectLayer, LLVMOrcObjectLayerRef)34DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule, LLVMOrcThreadSafeModuleRef)35 36// A class that sets strings for extension attributes by querying37// TargetLibraryInfo.38struct 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 tests51// written for the LLVM-C API. It provides the following helpers:52//53// 1. Jit: an LLVMOrcLLJIT instance which is freed upon test exit54// 2. ExecutionSession: the LLVMOrcExecutionSession for the JIT55// 3. MainDylib: the main JITDylib for the LLJIT instance56// 4. materializationUnitFn: function pointer to an empty function, used for57//                           materialization unit testing58// 5. definitionGeneratorFn: function pointer for a basic59//                           LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction60// 6. createTestModule: helper method for creating a basic thread-safe-module61class OrcCAPITestBase : public testing::Test {62protected:63  LLVMOrcLLJITRef Jit = nullptr;64  LLVMOrcExecutionSessionRef ExecutionSession = nullptr;65  LLVMOrcJITDylibRef MainDylib = nullptr;66 67public: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 that83    // this target is *supposed* to be supported, and error messages in84    // 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 extension110    // 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, %y119          ret i32 %r120          }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 do155    // this manually to check teardown behavior.156    if (Jit) {157      LLVMOrcDisposeLLJIT(Jit);158      Jit = nullptr;159    }160  }161 162protected: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, but166    // 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 the175  // materializationUnitFn() test function and defined into the JIT Dylib176  static LLVMErrorRef177  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 parameters219  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 247std::string OrcCAPITestBase::TargetTriple;248bool OrcCAPITestBase::TargetSupported = false;249 250std::string OrcCAPITestBase::SumExample;251std::string OrcCAPITestBase::SumDebugExample;252 253// Consumes the given error ref and returns the string error message.254static std::string toString(LLVMErrorRef E) {255  char *ErrMsg = LLVMGetErrorMessage(E);256  std::string Result(ErrMsg);257  LLVMDisposeErrorMessage(ErrMsg);258  return Result;259}260 261TEST_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 277TEST_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 288TEST_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 = " << TargetTriple304           << "): " << toString(E);305  ASSERT_EQ(Addr, OutAddr);306}307 308struct ExecutionSessionLookupHelper {309  bool ExpectSuccess = true;310  bool CallbackReceived = false;311  size_t NumExpectedPairs;312  LLVMOrcCSymbolMapPair *ExpectedMapping;313};314 315static 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].Name339            << "\" differs from expected value: "340            << formatv("{0:x} vs {1:x}", Result[I].Sym.Address, J->Sym.Address);341      }342    }343  } else344    EXPECT_THAT_ERROR(unwrap(Err), Failed());345}346 347TEST_F(OrcCAPITestBase, ExecutionSessionLookup_Success) {348  // Test a successful generic lookup. We will look up three symbols over two349  // JITDylibs: { "Foo" (Required), "Bar" (Weakly-ref), "Baz" (Required) } over350  // { 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 in357  // MainJD, (2) that we *don't* find the non-exported symbol Bar in MainJD358  // but also don't error (since it's weakly referenced), and (3) that we359  // find the non-exported symbol Baz in ExtraJD (since we're searching all360  // 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 the406  // 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 430TEST_F(OrcCAPITestBase, ExecutionSessionLookup_Failure) {431  // Test generic lookup failure case. We will look up a symbol in MainDylib432  // 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 448TEST_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)463TEST_F(OrcCAPITestBase, DISABLED_ResourceTrackerDefinitionLifetime) {464#else465TEST_F(OrcCAPITestBase, ResourceTrackerDefinitionLifetime) {466#endif467  // This test case ensures that all symbols loaded into a JITDylib with a468  // ResourceTracker attached are cleared from the JITDylib once the RT is469  // 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 = " << TargetTriple475           << "): " << toString(E);476  LLVMOrcJITTargetAddress TestFnAddr;477  if (LLVMErrorRef E = LLVMOrcLLJITLookup(Jit, &TestFnAddr, "sum"))478    FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple479           << "): " << 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)492TEST_F(OrcCAPITestBase, DISABLED_ResourceTrackerTransfer) {493#else494TEST_F(OrcCAPITestBase, ResourceTrackerTransfer) {495#endif496  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 = " << TargetTriple503           << "): " << toString(E);504  LLVMOrcJITTargetAddress Addr;505  if (LLVMErrorRef E = LLVMOrcLLJITLookup(Jit, &Addr, "sum"))506    FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple507           << "): " << 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)515TEST_F(OrcCAPITestBase, DISABLED_AddObjectBuffer) {516#else517TEST_F(OrcCAPITestBase, AddObjectBuffer) {518#endif519  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 = " << TargetTriple530           << "): " << toString(E);531  ASSERT_TRUE(!!SumAddr);532}533 534// JITLink debug support plugins put information about JITed code in this GDB535// JIT Interface global from OrcTargetProcess.536extern "C" LLVM_ABI struct jit_descriptor __jit_debug_descriptor;537 538static 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__))546TEST_F(OrcCAPITestBase, DISABLED_EnableDebugSupport) {547#else548static LLVM_ATTRIBUTE_USED void linkComponents() {549  errs() << "Linking in runtime functions\n"550         << (void *)&llvm_orc_registerJITLoaderGDBAllocAction << '\n';551}552TEST_F(OrcCAPITestBase, EnableDebugSupport) {553#endif554  void *Before = findLastDebugDescriptorEntryPtr();555  LLVMMemoryBufferRef ObjBuffer = createTestObject(SumDebugExample, "sum.ll");556  LLVMOrcObjectLayerRef ObjLayer = LLVMOrcLLJITGetObjLinkingLayer(Jit);557 558  if (LLVMErrorRef E = LLVMOrcLLJITEnableDebugSupport(Jit)) {559    EXPECT_FALSE(isa<ObjectLinkingLayer>(unwrap(ObjLayer)))560        << "Error testing LLJIT debug support "561        << "(triple = " << TargetTriple << "): " << toString(E);562    GTEST_SKIP() << "LLJIT C bindings provide debug support only for JITLink";563  }564 565  if (LLVMErrorRef E =566          LLVMOrcObjectLayerAddObjectFile(ObjLayer, MainDylib, ObjBuffer))567    FAIL() << "Failed to add object file to ObjLinkingLayer (triple = "568           << TargetTriple << "): " << toString(E);569 570  LLVMOrcJITTargetAddress SumAddr;571  if (LLVMErrorRef E = LLVMOrcLLJITLookup(Jit, &SumAddr, "sum"))572    FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple573           << "): " << toString(E);574 575  void *After = findLastDebugDescriptorEntryPtr();576  ASSERT_NE(Before, After);577}578 579#if defined(_AIX)580TEST_F(OrcCAPITestBase, DISABLED_ExecutionTest) {581#else582TEST_F(OrcCAPITestBase, ExecutionTest) {583#endif584  using SumFunctionType = int32_t (*)(int32_t, int32_t);585 586  // This test performs OrcJIT compilation of a simple sum module587  LLVMInitializeNativeAsmPrinter();588  LLVMOrcThreadSafeModuleRef TSM = createTestModule(SumExample, "sum.ll");589  if (LLVMErrorRef E = LLVMOrcLLJITAddLLVMIRModule(Jit, MainDylib, TSM))590    FAIL() << "Failed to add LLVM IR module to LLJIT (triple = " << TargetTriple591           << ")" << toString(E);592  LLVMOrcJITTargetAddress TestFnAddr;593  if (LLVMErrorRef E = LLVMOrcLLJITLookup(Jit, &TestFnAddr, "sum"))594    FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple595           << "): " << toString(E);596  auto *SumFn = (SumFunctionType)(TestFnAddr);597  int32_t Result = SumFn(1, 1);598  ASSERT_EQ(2, Result);599}600 601void Destroy(void *Ctx) {}602 603void TargetFn() {}604 605void Materialize(void *Ctx, LLVMOrcMaterializationResponsibilityRef MR) {606  LLVMOrcJITDylibRef JD =607      LLVMOrcMaterializationResponsibilityGetTargetDylib(MR);608  ASSERT_TRUE(!!JD);609 610  LLVMOrcExecutionSessionRef ES =611      LLVMOrcMaterializationResponsibilityGetExecutionSession(MR);612  ASSERT_TRUE(!!ES);613 614  LLVMOrcSymbolStringPoolEntryRef InitSym =615      LLVMOrcMaterializationResponsibilityGetInitializerSymbol(MR);616  ASSERT_TRUE(!InitSym);617 618  size_t NumSymbols;619  LLVMOrcCSymbolFlagsMapPairs Symbols =620      LLVMOrcMaterializationResponsibilityGetSymbols(MR, &NumSymbols);621 622  ASSERT_TRUE(!!Symbols);623  ASSERT_EQ(NumSymbols, (size_t)1);624 625  LLVMOrcSymbolStringPoolEntryRef *RequestedSymbols =626      LLVMOrcMaterializationResponsibilityGetRequestedSymbols(MR, &NumSymbols);627 628  ASSERT_TRUE(!!RequestedSymbols);629  ASSERT_EQ(NumSymbols, (size_t)1);630 631  LLVMOrcCSymbolFlagsMapPair TargetSym = Symbols[0];632 633  ASSERT_EQ(RequestedSymbols[0], TargetSym.Name);634  LLVMOrcRetainSymbolStringPoolEntry(TargetSym.Name);635 636  LLVMOrcDisposeCSymbolFlagsMap(Symbols);637  LLVMOrcDisposeSymbols(RequestedSymbols);638 639  LLVMOrcJITTargetAddress Addr = (LLVMOrcJITTargetAddress)(&TargetFn);640 641  LLVMJITSymbolFlags Flags = {642      LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0};643  ASSERT_EQ(TargetSym.Flags.GenericFlags, Flags.GenericFlags);644  ASSERT_EQ(TargetSym.Flags.TargetFlags, Flags.TargetFlags);645 646  LLVMJITEvaluatedSymbol Sym = {Addr, Flags};647 648  LLVMOrcLLJITRef J = (LLVMOrcLLJITRef)Ctx;649 650  LLVMOrcSymbolStringPoolEntryRef OtherSymbol =651      LLVMOrcLLJITMangleAndIntern(J, "other");652  LLVMOrcSymbolStringPoolEntryRef DependencySymbol =653      LLVMOrcLLJITMangleAndIntern(J, "dependency");654 655  LLVMOrcRetainSymbolStringPoolEntry(OtherSymbol);656  LLVMOrcRetainSymbolStringPoolEntry(DependencySymbol);657  LLVMOrcCSymbolFlagsMapPair NewSymbols[] = {658      {OtherSymbol, Flags},659      {DependencySymbol, Flags},660  };661  LLVMOrcMaterializationResponsibilityDefineMaterializing(MR, NewSymbols, 2);662 663  LLVMOrcRetainSymbolStringPoolEntry(OtherSymbol);664  LLVMOrcMaterializationResponsibilityRef OtherMR = NULL;665  {666    LLVMErrorRef Err = LLVMOrcMaterializationResponsibilityDelegate(667        MR, &OtherSymbol, 1, &OtherMR);668    if (Err) {669      char *ErrMsg = LLVMGetErrorMessage(Err);670      fprintf(stderr, "Error: %s\n", ErrMsg);671      LLVMDisposeErrorMessage(ErrMsg);672      LLVMOrcMaterializationResponsibilityFailMaterialization(MR);673      LLVMOrcDisposeMaterializationResponsibility(MR);674      return;675    }676  }677  assert(OtherMR);678 679  LLVMOrcCSymbolMapPair OtherPair = {OtherSymbol, Sym};680  LLVMOrcMaterializationUnitRef OtherMU = LLVMOrcAbsoluteSymbols(&OtherPair, 1);681  // OtherSymbol is no longer owned by us682  {683    LLVMErrorRef Err =684        LLVMOrcMaterializationResponsibilityReplace(OtherMR, OtherMU);685    if (Err) {686      char *ErrMsg = LLVMGetErrorMessage(Err);687      fprintf(stderr, "Error: %s\n", ErrMsg);688      LLVMDisposeErrorMessage(ErrMsg);689 690      LLVMOrcMaterializationResponsibilityFailMaterialization(OtherMR);691      LLVMOrcMaterializationResponsibilityFailMaterialization(MR);692 693      LLVMOrcDisposeMaterializationResponsibility(OtherMR);694      LLVMOrcDisposeMaterializationResponsibility(MR);695      LLVMOrcDisposeMaterializationUnit(OtherMU);696      return;697    }698  }699  LLVMOrcDisposeMaterializationResponsibility(OtherMR);700 701  // FIXME: Implement async lookup702  LLVMOrcRetainSymbolStringPoolEntry(DependencySymbol);703  LLVMOrcCSymbolMapPair Pair = {DependencySymbol, Sym};704  LLVMOrcMaterializationResponsibilityNotifyResolved(MR, &Pair, 1);705  // DependencySymbol no longer owned by us706 707  Pair = {TargetSym.Name, Sym};708  LLVMOrcMaterializationResponsibilityNotifyResolved(MR, &Pair, 1);709 710  LLVMOrcRetainSymbolStringPoolEntry(TargetSym.Name);711  LLVMOrcCDependenceMapPair Dependency = {JD, {&DependencySymbol, 1}};712  LLVMOrcCSymbolDependenceGroup DependenceSet = {713      /*.Symbols = */ {/*.Symbols = */ &TargetSym.Name, /* .Length = */ 1},714      /* .Dependencies = */ &Dependency,715      /* .NumDependencies = */ 1};716 717  LLVMOrcMaterializationResponsibilityNotifyEmitted(MR, &DependenceSet, 1);718  LLVMOrcDisposeMaterializationResponsibility(MR);719}720 721TEST_F(OrcCAPITestBase, MaterializationResponsibility) {722  LLVMJITSymbolFlags Flags = {723      LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0};724  LLVMOrcCSymbolFlagsMapPair Sym = {LLVMOrcLLJITMangleAndIntern(Jit, "foo"),725                                    Flags};726 727  LLVMOrcMaterializationUnitRef MU = LLVMOrcCreateCustomMaterializationUnit(728      "MU", (void *)Jit, &Sym, 1, NULL, &Materialize, NULL, &Destroy);729  LLVMOrcJITDylibRef JD = LLVMOrcLLJITGetMainJITDylib(Jit);730  LLVMOrcJITDylibDefine(JD, MU);731 732  LLVMOrcJITTargetAddress Addr;733  if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "foo")) {734    FAIL() << "foo was not materialized " << toString(Err);735  }736  ASSERT_TRUE(!!Addr);737  ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn);738 739  if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "other")) {740    FAIL() << "other was not materialized " << toString(Err);741  }742  ASSERT_TRUE(!!Addr);743  ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn);744 745  if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "dependency")) {746    FAIL() << "dependency was not materialized " << toString(Err);747  }748  ASSERT_TRUE(!!Addr);749  ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn);750}751 752struct SuspendedLookupContext {753  std::function<void()> AsyncWork;754  LLVMOrcSymbolStringPoolEntryRef NameToGenerate;755  JITTargetAddress AddrToGenerate;756 757  bool Disposed = false;758  bool QueryCompleted = true;759};760 761static LLVMErrorRef TryToGenerateWithSuspendedLookup(762    LLVMOrcDefinitionGeneratorRef GeneratorObj, void *RawCtx,763    LLVMOrcLookupStateRef *LookupState, LLVMOrcLookupKind Kind,764    LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags JDLookupFlags,765    LLVMOrcCLookupSet LookupSet, size_t LookupSetSize) {766 767  auto *Ctx = static_cast<SuspendedLookupContext *>(RawCtx);768 769  assert(LookupSetSize == 1);770  assert(LookupSet[0].Name == Ctx->NameToGenerate);771 772  LLVMJITEvaluatedSymbol Sym = {0x1234, {LLVMJITSymbolGenericFlagsExported, 0}};773  LLVMOrcRetainSymbolStringPoolEntry(LookupSet[0].Name);774  LLVMOrcCSymbolMapPair Pair = {LookupSet[0].Name, Sym};775  LLVMOrcCSymbolMapPair Pairs[] = {Pair};776  LLVMOrcMaterializationUnitRef MU = LLVMOrcAbsoluteSymbols(Pairs, 1);777 778  // Capture and reset LookupState to suspend the lookup. We'll continue it in779  // the SuspendedLookup testcase below.780  Ctx->AsyncWork = [LS = *LookupState, JD, MU]() {781    LLVMErrorRef Err = LLVMOrcJITDylibDefine(JD, MU);782    LLVMOrcLookupStateContinueLookup(LS, Err);783  };784  *LookupState = nullptr;785  return LLVMErrorSuccess;786}787 788static void DisposeSuspendedLookupContext(void *Ctx) {789  static_cast<SuspendedLookupContext *>(Ctx)->Disposed = true;790}791 792static void793suspendLookupTestLookupHandlerCallback(LLVMErrorRef Err,794                                       LLVMOrcCSymbolMapPairs Result,795                                       size_t NumPairs, void *RawCtx) {796  if (Err) {797    FAIL() << "Suspended DefinitionGenerator did not create symbol \"foo\": "798           << toString(Err);799    return;800  }801 802  EXPECT_EQ(NumPairs, 1U)803      << "Unexpected number of result entries: expected 1, got " << NumPairs;804 805  auto *Ctx = static_cast<SuspendedLookupContext *>(RawCtx);806  EXPECT_EQ(Result[0].Name, Ctx->NameToGenerate);807  EXPECT_EQ(Result[0].Sym.Address, Ctx->AddrToGenerate);808 809  Ctx->QueryCompleted = true;810}811 812TEST_F(OrcCAPITestBase, SuspendedLookup) {813  // Test that we can suspend lookup in a custom generator.814  SuspendedLookupContext Ctx;815  Ctx.NameToGenerate = LLVMOrcLLJITMangleAndIntern(Jit, "foo");816  Ctx.AddrToGenerate = 0x1234;817 818  // Add generator.819  LLVMOrcJITDylibAddGenerator(MainDylib,820                              LLVMOrcCreateCustomCAPIDefinitionGenerator(821                                  &TryToGenerateWithSuspendedLookup, &Ctx,822                                  DisposeSuspendedLookupContext));823 824  // Expect no work to do before the lookup.825  EXPECT_FALSE(Ctx.AsyncWork) << "Unexpected generator work before lookup";826 827  // Issue lookup. This should trigger the generator, but generation should828  // be suspended.829  LLVMOrcCJITDylibSearchOrderElement SO[] = {830      {MainDylib, LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly}};831  LLVMOrcRetainSymbolStringPoolEntry(Ctx.NameToGenerate);832  LLVMOrcCLookupSetElement LS[] = {833      {Ctx.NameToGenerate, LLVMOrcSymbolLookupFlagsRequiredSymbol}};834  LLVMOrcExecutionSessionLookup(ExecutionSession, LLVMOrcLookupKindStatic, SO,835                                1, LS, 1,836                                suspendLookupTestLookupHandlerCallback, &Ctx);837 838  // Expect that we now have generator work to do.839  EXPECT_TRUE(Ctx.AsyncWork)840      << "Failed to generator (or failed to suspend generator)";841 842  // Do the work. This should allow the query to complete.843  Ctx.AsyncWork();844 845  // Check that the query completed.846  EXPECT_TRUE(Ctx.QueryCompleted);847 848  // Release our local copy of the string.849  LLVMOrcReleaseSymbolStringPoolEntry(Ctx.NameToGenerate);850 851  // Explicitly tear down the JIT.852  LLVMOrcDisposeLLJIT(Jit);853  Jit = nullptr;854 855  // Check that the generator context was "destroyed".856  EXPECT_TRUE(Ctx.Disposed);857}858