[llvm] 803c770 - [C-API][ORC] Add LLVMOrcExecutionSessionLookup -- generic async symbol lookup.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 13 16:37:47 PDT 2022


Author: Lang Hames
Date: 2022-06-13T16:37:35-07:00
New Revision: 803c770ee0a2833beba2365a269d36fb08cb6f5d

URL: https://github.com/llvm/llvm-project/commit/803c770ee0a2833beba2365a269d36fb08cb6f5d
DIFF: https://github.com/llvm/llvm-project/commit/803c770ee0a2833beba2365a269d36fb08cb6f5d.diff

LOG: [C-API][ORC] Add LLVMOrcExecutionSessionLookup -- generic async symbol lookup.

An API to wrap ExecutionSession::lookup, this allows C API clients to use async
lookup.

The immediate motivation for adding this is to simplify upcoming
definition-generator unit tests.

As we're adding more tests that need to convert between C and C++ flag values
this commit adds helper functions to support this. This patch also updates the
CAPIDefinitionGenerator to use these new utilities.

Added: 
    

Modified: 
    llvm/include/llvm-c/Orc.h
    llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
    llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
    llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h
index 57478208a6d06..e843e76a6da0f 100644
--- a/llvm/include/llvm-c/Orc.h
+++ b/llvm/include/llvm-c/Orc.h
@@ -54,6 +54,7 @@ typedef uint64_t LLVMOrcExecutorAddress;
  * Represents generic linkage flags for a symbol definition.
  */
 typedef enum {
+  LLVMJITSymbolGenericFlagsNone = 0,
   LLVMJITSymbolGenericFlagsExported = 1U << 0,
   LLVMJITSymbolGenericFlagsWeak = 1U << 1,
   LLVMJITSymbolGenericFlagsCallable = 1U << 2,
@@ -202,6 +203,22 @@ typedef enum {
   LLVMOrcJITDylibLookupFlagsMatchAllSymbols
 } LLVMOrcJITDylibLookupFlags;
 
+/**
+ * An element type for a JITDylib search order.
+ */
+typedef struct {
+  LLVMOrcJITDylibRef JD;
+  LLVMOrcJITDylibLookupFlags JDLookupFlags;
+} LLVMOrcCJITDylibSearchOrderElement;
+
+/**
+ * A JITDylib search order.
+ *
+ * The list is terminated with an element containing a null pointer for the JD
+ * field.
+ */
+typedef LLVMOrcCJITDylibSearchOrderElement *LLVMOrcCJITDylibSearchOrder;
+
 /**
  * Symbol lookup flags for lookup sets. This should be kept in sync with
  * llvm::orc::SymbolLookupFlags.
@@ -494,6 +511,58 @@ void LLVMOrcSymbolStringPoolClearDeadEntries(LLVMOrcSymbolStringPoolRef SSP);
 LLVMOrcSymbolStringPoolEntryRef
 LLVMOrcExecutionSessionIntern(LLVMOrcExecutionSessionRef ES, const char *Name);
 
+/**
+ * Callback type for ExecutionSession lookups.
+ *
+ * If Err is LLVMErrorSuccess then Result will contain a pointer to a
+ * list of ( SymbolStringPtr, JITEvaluatedSymbol ) pairs of length NumPairs.
+ *
+ * If Err is a failure value then Result and Ctx are undefined and should
+ * not be accessed. The Callback is responsible for handling the error
+ * value (e.g. by calling LLVMGetErrorMessage + LLVMDisposeErrorMessage).
+ *
+ * The caller retains ownership of the Result array and will release all
+ * contained symbol names. Clients are responsible for retaining any symbol
+ * names that they wish to hold after the function returns.
+ */
+typedef void (*LLVMOrcExecutionSessionLookupHandleResultFunction)(
+    LLVMErrorRef Err, LLVMOrcCSymbolMapPairs Result, size_t NumPairs,
+    void *Ctx);
+
+/**
+ * Look up symbols in an execution session.
+ *
+ * This is a wrapper around the general ExecutionSession::lookup function.
+ *
+ * The SearchOrder argument contains a list of (JITDylibs, JITDylibSearchFlags)
+ * pairs that describe the search order. The JITDylibs will be searched in the
+ * given order to try to find the symbols in the Symbols argument.
+ *
+ * The Symbols argument should contain a null-terminated array of
+ * (SymbolStringPtr, SymbolLookupFlags) pairs describing the symbols to be
+ * searched for. This function takes ownership of the elements of the Symbols
+ * array. The Name fields of the Symbols elements are taken to have been
+ * retained by the client for this function. The client should *not* release the
+ * Name fields, but are still responsible for destroying the array itself.
+ *
+ * The HandleResult function will be called once all searched for symbols have
+ * been found, or an error occurs. The HandleResult function will be passed an
+ * LLVMErrorRef indicating success or failure, and (on success) a
+ * null-terminated LLVMOrcCSymbolMapPairs array containing the function result,
+ * and the Ctx value passed to the lookup function.
+ *
+ * The client is fully responsible for managing the lifetime of the Ctx object.
+ * A common idiom is to allocate the context prior to the lookup and deallocate
+ * it in the handler.
+ *
+ * THIS API IS EXPERIMENTAL AND LIKELY TO CHANGE IN THE NEAR FUTURE!
+ */
+void LLVMOrcExecutionSessionLookup(
+    LLVMOrcExecutionSessionRef ES, LLVMOrcLookupKind K,
+    LLVMOrcCJITDylibSearchOrder SearchOrder, size_t SearchOrderSize,
+    LLVMOrcCLookupSet Symbols, size_t SymbolsSize,
+    LLVMOrcExecutionSessionLookupHandleResultFunction HandleResult, void *Ctx);
+
 /**
  * Increments the ref-count for a SymbolStringPool entry.
  */
@@ -547,7 +616,7 @@ void LLVMOrcDisposeMaterializationUnit(LLVMOrcMaterializationUnitRef MU);
  * unit. This function takes ownership of the elements of the Syms array. The
  * Name fields of the array elements are taken to have been retained for this
  * function. The client should *not* release the elements of the array, but is
- * still responsible for destroyingthe array itself.
+ * still responsible for destroying the array itself.
  *
  * The InitSym argument indicates whether or not this MaterializationUnit
  * contains static initializers. If three are no static initializers (the common
@@ -701,7 +770,7 @@ LLVMOrcMaterializationResponsibilityGetRequestedSymbols(
  */
 void LLVMOrcDisposeSymbols(LLVMOrcSymbolStringPoolEntryRef *Symbols);
 
-/*
+/**
  * Notifies the target JITDylib that the given symbols have been resolved.
  * This will update the given symbols' addresses in the JITDylib, and notify
  * any pending queries on the given symbols of their resolution. The given

diff  --git a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
index 2f61b31ae3832..6dfd5548fcfdb 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
@@ -15,7 +15,6 @@
 #include "llvm/ExecutionEngine/JITLink/x86_64.h"
 
 #include "MachOLinkGraphBuilder.h"
-#include "PerGraphGOTAndPLTStubsBuilder.h"
 
 #define DEBUG_TYPE "jitlink"
 

diff  --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
index ca52d3ea3a5d0..0d1024ab14556 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
@@ -106,82 +106,6 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJITBuilder, LLVMOrcLLJITBuilderRef)
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJIT, LLVMOrcLLJITRef)
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
 
-namespace llvm {
-namespace orc {
-
-class CAPIDefinitionGenerator final : public DefinitionGenerator {
-public:
-  CAPIDefinitionGenerator(
-      void *Ctx,
-      LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction TryToGenerate)
-      : Ctx(Ctx), TryToGenerate(TryToGenerate) {}
-
-  Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
-                      JITDylibLookupFlags JDLookupFlags,
-                      const SymbolLookupSet &LookupSet) override {
-
-    // Take the lookup state.
-    LLVMOrcLookupStateRef LSR = ::wrap(OrcV2CAPIHelper::extractLookupState(LS));
-
-    // Translate the lookup kind.
-    LLVMOrcLookupKind CLookupKind;
-    switch (K) {
-    case LookupKind::Static:
-      CLookupKind = LLVMOrcLookupKindStatic;
-      break;
-    case LookupKind::DLSym:
-      CLookupKind = LLVMOrcLookupKindDLSym;
-      break;
-    }
-
-    // Translate the JITDylibSearchFlags.
-    LLVMOrcJITDylibLookupFlags CJDLookupFlags;
-    switch (JDLookupFlags) {
-    case JITDylibLookupFlags::MatchExportedSymbolsOnly:
-      CJDLookupFlags = LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly;
-      break;
-    case JITDylibLookupFlags::MatchAllSymbols:
-      CJDLookupFlags = LLVMOrcJITDylibLookupFlagsMatchAllSymbols;
-      break;
-    }
-
-    // Translate the lookup set.
-    std::vector<LLVMOrcCLookupSetElement> CLookupSet;
-    CLookupSet.reserve(LookupSet.size());
-    for (auto &KV : LookupSet) {
-      LLVMOrcSymbolLookupFlags SLF;
-      LLVMOrcSymbolStringPoolEntryRef Name =
-        ::wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(KV.first));
-      switch (KV.second) {
-      case SymbolLookupFlags::RequiredSymbol:
-        SLF = LLVMOrcSymbolLookupFlagsRequiredSymbol;
-        break;
-      case SymbolLookupFlags::WeaklyReferencedSymbol:
-        SLF = LLVMOrcSymbolLookupFlagsWeaklyReferencedSymbol;
-        break;
-      }
-      CLookupSet.push_back({Name, SLF});
-    }
-
-    // Run the C TryToGenerate function.
-    auto Err = unwrap(TryToGenerate(::wrap(this), Ctx, &LSR, CLookupKind,
-                                    ::wrap(&JD), CJDLookupFlags,
-                                    CLookupSet.data(), CLookupSet.size()));
-
-    // Restore the lookup state.
-    OrcV2CAPIHelper::resetLookupState(LS, ::unwrap(LSR));
-
-    return Err;
-  }
-
-private:
-  void *Ctx;
-  LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction TryToGenerate;
-};
-
-} // end namespace orc
-} // end namespace llvm
-
 namespace {
 
 class OrcCAPIMaterializationUnit : public llvm::orc::MaterializationUnit {
@@ -282,8 +206,128 @@ toSymbolDependenceMap(LLVMOrcCDependenceMapPairs Pairs, size_t NumPairs) {
   return SDM;
 }
 
+static LookupKind toLookupKind(LLVMOrcLookupKind K) {
+  switch (K) {
+  case LLVMOrcLookupKindStatic:
+    return LookupKind::Static;
+  case LLVMOrcLookupKindDLSym:
+    return LookupKind::DLSym;
+  }
+  llvm_unreachable("unrecognized LLVMOrcLookupKind value");
+}
+
+static LLVMOrcLookupKind fromLookupKind(LookupKind K) {
+  switch (K) {
+  case LookupKind::Static:
+    return LLVMOrcLookupKindStatic;
+  case LookupKind::DLSym:
+    return LLVMOrcLookupKindDLSym;
+  }
+  llvm_unreachable("unrecognized LookupKind value");
+}
+
+static JITDylibLookupFlags
+toJITDylibLookupFlags(LLVMOrcJITDylibLookupFlags LF) {
+  switch (LF) {
+  case LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly:
+    return JITDylibLookupFlags::MatchExportedSymbolsOnly;
+  case LLVMOrcJITDylibLookupFlagsMatchAllSymbols:
+    return JITDylibLookupFlags::MatchAllSymbols;
+  }
+  llvm_unreachable("unrecognized LLVMOrcJITDylibLookupFlags value");
+}
+
+static LLVMOrcJITDylibLookupFlags
+fromJITDylibLookupFlags(JITDylibLookupFlags LF) {
+  switch (LF) {
+  case JITDylibLookupFlags::MatchExportedSymbolsOnly:
+    return LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly;
+  case JITDylibLookupFlags::MatchAllSymbols:
+    return LLVMOrcJITDylibLookupFlagsMatchAllSymbols;
+  }
+  llvm_unreachable("unrecognized JITDylibLookupFlags value");
+}
+
+static SymbolLookupFlags toSymbolLookupFlags(LLVMOrcSymbolLookupFlags SLF) {
+  switch (SLF) {
+  case LLVMOrcSymbolLookupFlagsRequiredSymbol:
+    return SymbolLookupFlags::RequiredSymbol;
+  case LLVMOrcSymbolLookupFlagsWeaklyReferencedSymbol:
+    return SymbolLookupFlags::WeaklyReferencedSymbol;
+  }
+  llvm_unreachable("unrecognized LLVMOrcSymbolLookupFlags value");
+}
+
+static LLVMOrcSymbolLookupFlags fromSymbolLookupFlags(SymbolLookupFlags SLF) {
+  switch (SLF) {
+  case SymbolLookupFlags::RequiredSymbol:
+    return LLVMOrcSymbolLookupFlagsRequiredSymbol;
+  case SymbolLookupFlags::WeaklyReferencedSymbol:
+    return LLVMOrcSymbolLookupFlagsWeaklyReferencedSymbol;
+  }
+  llvm_unreachable("unrecognized SymbolLookupFlags value");
+}
+
+static LLVMJITEvaluatedSymbol
+fromJITEvaluatedSymbol(const JITEvaluatedSymbol &S) {
+  return {S.getAddress(), fromJITSymbolFlags(S.getFlags())};
+}
+
 } // end anonymous namespace
 
+namespace llvm {
+namespace orc {
+
+class CAPIDefinitionGenerator final : public DefinitionGenerator {
+public:
+  CAPIDefinitionGenerator(
+      void *Ctx,
+      LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction TryToGenerate)
+      : Ctx(Ctx), TryToGenerate(TryToGenerate) {}
+
+  Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
+                      JITDylibLookupFlags JDLookupFlags,
+                      const SymbolLookupSet &LookupSet) override {
+
+    // Take the lookup state.
+    LLVMOrcLookupStateRef LSR = ::wrap(OrcV2CAPIHelper::extractLookupState(LS));
+
+    // Translate the lookup kind.
+    LLVMOrcLookupKind CLookupKind = fromLookupKind(K);
+
+    // Translate the JITDylibLookupFlags.
+    LLVMOrcJITDylibLookupFlags CJDLookupFlags =
+        fromJITDylibLookupFlags(JDLookupFlags);
+
+    // Translate the lookup set.
+    std::vector<LLVMOrcCLookupSetElement> CLookupSet;
+    CLookupSet.reserve(LookupSet.size());
+    for (auto &KV : LookupSet) {
+      LLVMOrcSymbolStringPoolEntryRef Name =
+          ::wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(KV.first));
+      LLVMOrcSymbolLookupFlags SLF = fromSymbolLookupFlags(KV.second);
+      CLookupSet.push_back({Name, SLF});
+    }
+
+    // Run the C TryToGenerate function.
+    auto Err = unwrap(TryToGenerate(::wrap(this), Ctx, &LSR, CLookupKind,
+                                    ::wrap(&JD), CJDLookupFlags,
+                                    CLookupSet.data(), CLookupSet.size()));
+
+    // Restore the lookup state.
+    OrcV2CAPIHelper::resetLookupState(LS, ::unwrap(LSR));
+
+    return Err;
+  }
+
+private:
+  void *Ctx;
+  LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction TryToGenerate;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
 void LLVMOrcExecutionSessionSetErrorReporter(
     LLVMOrcExecutionSessionRef ES, LLVMOrcErrorReporterFunction ReportError,
     void *Ctx) {
@@ -307,6 +351,42 @@ LLVMOrcExecutionSessionIntern(LLVMOrcExecutionSessionRef ES, const char *Name) {
       OrcV2CAPIHelper::moveFromSymbolStringPtr(unwrap(ES)->intern(Name)));
 }
 
+void LLVMOrcExecutionSessionLookup(
+    LLVMOrcExecutionSessionRef ES, LLVMOrcLookupKind K,
+    LLVMOrcCJITDylibSearchOrder SearchOrder, size_t SearchOrderSize,
+    LLVMOrcCLookupSet Symbols, size_t SymbolsSize,
+    LLVMOrcExecutionSessionLookupHandleResultFunction HandleResult, void *Ctx) {
+  assert(ES && "ES cannot be null");
+  assert(SearchOrder && "SearchOrder cannot be null");
+  assert(Symbols && "Symbols cannot be null");
+  assert(HandleResult && "HandleResult cannot be null");
+
+  JITDylibSearchOrder SO;
+  for (size_t I = 0; I != SearchOrderSize; ++I)
+    SO.push_back({unwrap(SearchOrder[I].JD),
+                  toJITDylibLookupFlags(SearchOrder[I].JDLookupFlags)});
+
+  SymbolLookupSet SLS;
+  for (size_t I = 0; I != SymbolsSize; ++I)
+    SLS.add(OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Symbols[I].Name)),
+            toSymbolLookupFlags(Symbols[I].LookupFlags));
+
+  unwrap(ES)->lookup(
+      toLookupKind(K), SO, std::move(SLS), SymbolState::Ready,
+      [HandleResult, Ctx](Expected<SymbolMap> Result) {
+        if (Result) {
+          SmallVector<LLVMOrcCSymbolMapPair> CResult;
+          for (auto &KV : *Result)
+            CResult.push_back(LLVMOrcCSymbolMapPair{
+                wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(KV.first)),
+                fromJITEvaluatedSymbol(KV.second)});
+          HandleResult(LLVMErrorSuccess, CResult.data(), CResult.size(), Ctx);
+        } else
+          HandleResult(wrap(Result.takeError()), nullptr, 0, Ctx);
+      },
+      NoDependenciesToRegister);
+}
+
 void LLVMOrcRetainSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S) {
   OrcV2CAPIHelper::retainPoolEntry(unwrap(S));
 }

diff  --git a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
index 0a18fda0d4e03..2660c8bf72b2b 100644
--- a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
@@ -18,7 +18,9 @@
 #include "llvm/IR/Module.h"
 #include "llvm/IRReader/IRReader.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/SourceMgr.h"
+#include "llvm/Testing/Support/Error.h"
 #include <string>
 
 using namespace llvm;
@@ -265,6 +267,146 @@ TEST_F(OrcCAPITestBase, MaterializationUnitCreation) {
   ASSERT_EQ(Addr, OutAddr);
 }
 
+struct ExecutionSessionLookupHelper {
+  bool ExpectSuccess = true;
+  bool CallbackReceived = false;
+  size_t NumExpectedPairs;
+  LLVMOrcCSymbolMapPair *ExpectedMapping;
+};
+
+static void executionSessionLookupHandlerCallback(LLVMErrorRef Err,
+                                                  LLVMOrcCSymbolMapPairs Result,
+                                                  size_t NumPairs,
+                                                  void *RawCtx) {
+  auto *Ctx = static_cast<ExecutionSessionLookupHelper *>(RawCtx);
+  Ctx->CallbackReceived = true;
+  if (Ctx->ExpectSuccess) {
+    EXPECT_THAT_ERROR(unwrap(Err), Succeeded());
+    EXPECT_EQ(NumPairs, Ctx->NumExpectedPairs)
+        << "Expected " << Ctx->NumExpectedPairs << " entries in result, got "
+        << NumPairs;
+    auto ExpectedMappingEnd = Ctx->ExpectedMapping + Ctx->NumExpectedPairs;
+    for (unsigned I = 0; I != NumPairs; ++I) {
+      auto J =
+          std::find_if(Ctx->ExpectedMapping, ExpectedMappingEnd,
+                       [N = Result[I].Name](const LLVMOrcCSymbolMapPair &Val) {
+                         return Val.Name == N;
+                       });
+      EXPECT_NE(J, ExpectedMappingEnd)
+          << "Missing symbol \""
+          << LLVMOrcSymbolStringPoolEntryStr(Result[I].Name) << "\"";
+      if (J != ExpectedMappingEnd) {
+        EXPECT_EQ(Result[I].Sym.Address, J->Sym.Address)
+            << "Result map for \"" << Result[I].Name
+            << "\" 
diff ers from expected value: "
+            << formatv("{0:x} vs {1:x}", Result[I].Sym.Address, J->Sym.Address);
+      }
+    }
+  } else
+    EXPECT_THAT_ERROR(unwrap(Err), Failed());
+}
+
+TEST_F(OrcCAPITestBase, ExecutionSessionLookup_Success) {
+  // Test a successful generic lookup. We will look up three symbols over two
+  // JITDylibs: { "Foo" (Required), "Bar" (Weakly-ref), "Baz" (Required) } over
+  // { MainJITDylib (Exported-only), ExtraJD (All symbols) }.
+  //
+  // Foo will be defined as exported in MainJD.
+  // Bar will be defined as non-exported in MainJD.
+  // Baz will be defined as non-exported in ExtraJD.
+  //
+  // This will require (1) that we find the regular exported symbol Foo in
+  // MainJD, (2) that we *don't* find the non-exported symbol Bar in MainJD
+  // but also don't error (since it's weakly referenced), and (3) that we
+  // find the non-exported symbol Baz in ExtraJD (since we're searching all
+  // symbols in ExtraJD).
+
+  ExecutionSessionLookupHelper H;
+  LLVMOrcSymbolStringPoolEntryRef Foo = LLVMOrcLLJITMangleAndIntern(Jit, "Foo");
+  LLVMOrcSymbolStringPoolEntryRef Bar = LLVMOrcLLJITMangleAndIntern(Jit, "Bar");
+  LLVMOrcSymbolStringPoolEntryRef Baz = LLVMOrcLLJITMangleAndIntern(Jit, "Baz");
+
+  // Create ExtraJD.
+  LLVMOrcJITDylibRef ExtraJD = nullptr;
+  if (auto E = LLVMOrcExecutionSessionCreateJITDylib(ExecutionSession, &ExtraJD,
+                                                     "ExtraJD")) {
+    FAIL() << "Unexpected error while creating JITDylib \"ExtraJD\" (triple = "
+           << TargetTriple << "): " << toString(E);
+    return;
+  }
+
+  // Add exported symbols "Foo" and "Bar" to Main JITDylib.
+  LLVMOrcRetainSymbolStringPoolEntry(Foo);
+  LLVMOrcRetainSymbolStringPoolEntry(Bar);
+  LLVMOrcCSymbolMapPair MainJDPairs[] = {
+      {Foo, {0x1, {LLVMJITSymbolGenericFlagsExported, 0}}},
+      {Bar, {0x2, {LLVMJITSymbolGenericFlagsNone, 0}}}};
+  LLVMOrcMaterializationUnitRef MainJDMU =
+      LLVMOrcAbsoluteSymbols(MainJDPairs, 2);
+  if (LLVMErrorRef E = LLVMOrcJITDylibDefine(MainDylib, MainJDMU))
+    FAIL() << "Unexpected error while adding MainDylib symbols (triple = "
+           << TargetTriple << "): " << toString(E);
+
+  // Add non-exported symbol "Baz" to ExtraJD.
+  LLVMOrcRetainSymbolStringPoolEntry(Baz);
+  LLVMOrcCSymbolMapPair ExtraJDPairs[] = {
+      {Baz, {0x3, {LLVMJITSymbolGenericFlagsNone, 0}}}};
+  LLVMOrcMaterializationUnitRef ExtraJDMU =
+      LLVMOrcAbsoluteSymbols(ExtraJDPairs, 1);
+  if (LLVMErrorRef E = LLVMOrcJITDylibDefine(ExtraJD, ExtraJDMU))
+    FAIL() << "Unexpected error while adding ExtraJD symbols (triple = "
+           << TargetTriple << "): " << toString(E);
+
+  // Create expected mapping for result:
+  LLVMOrcCSymbolMapPair ExpectedMapping[] = {
+      {Foo, {0x1, {LLVMJITSymbolGenericFlagsExported, 0}}},
+      {Baz, {0x3, {LLVMJITSymbolGenericFlagsNone, 0}}}};
+  H.ExpectedMapping = ExpectedMapping;
+  H.NumExpectedPairs = 2;
+
+  // Issue the lookup. We're using the default same-thread dispatch, so the
+  // handler should have run by the time we return from this call.
+  LLVMOrcCJITDylibSearchOrderElement SO[] = {
+      {MainDylib, LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly},
+      {ExtraJD, LLVMOrcJITDylibLookupFlagsMatchAllSymbols}};
+
+  LLVMOrcRetainSymbolStringPoolEntry(Foo);
+  LLVMOrcRetainSymbolStringPoolEntry(Bar);
+  LLVMOrcRetainSymbolStringPoolEntry(Baz);
+  LLVMOrcCLookupSetElement LS[] = {
+      {Foo, LLVMOrcSymbolLookupFlagsRequiredSymbol},
+      {Bar, LLVMOrcSymbolLookupFlagsWeaklyReferencedSymbol},
+      {Baz, LLVMOrcSymbolLookupFlagsRequiredSymbol}};
+  LLVMOrcExecutionSessionLookup(ExecutionSession, LLVMOrcLookupKindStatic, SO,
+                                2, LS, 3, executionSessionLookupHandlerCallback,
+                                &H);
+
+  EXPECT_TRUE(H.CallbackReceived) << "Lookup callback never received";
+
+  // Release our local string ptrs.
+  LLVMOrcReleaseSymbolStringPoolEntry(Baz);
+  LLVMOrcReleaseSymbolStringPoolEntry(Bar);
+  LLVMOrcReleaseSymbolStringPoolEntry(Foo);
+}
+
+TEST_F(OrcCAPITestBase, ExecutionSessionLookup_Failure) {
+  // Test generic lookup failure case. We will look up a symbol in MainDylib
+  // without defining it. We expect this to result in a symbol-not-found error.
+
+  ExecutionSessionLookupHelper H;
+  H.ExpectSuccess = false;
+
+  LLVMOrcCJITDylibSearchOrderElement SO[] = {
+      {MainDylib, LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly}};
+  LLVMOrcCLookupSetElement LS[] = {{LLVMOrcLLJITMangleAndIntern(Jit, "Foo"),
+                                    LLVMOrcSymbolLookupFlagsRequiredSymbol}};
+  LLVMOrcExecutionSessionLookup(ExecutionSession, LLVMOrcLookupKindStatic, SO,
+                                1, LS, 1, executionSessionLookupHandlerCallback,
+                                &H);
+
+  EXPECT_TRUE(H.CallbackReceived) << "Lookup callback never received";
+}
+
 TEST_F(OrcCAPITestBase, DefinitionGenerators) {
   LLVMOrcDefinitionGeneratorRef Gen =
       LLVMOrcCreateCustomCAPIDefinitionGenerator(&definitionGeneratorFn,


        


More information about the llvm-commits mailing list