[llvm] 45e8a0b - [Orc] At CBindings for LazyRexports

Valentin Churavy via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 1 12:52:16 PDT 2021


Author: Valentin Churavy
Date: 2021-07-01T21:52:05+02:00
New Revision: 45e8a0befbc8e174c3fa4ba4d21ef4445a16191b

URL: https://github.com/llvm/llvm-project/commit/45e8a0befbc8e174c3fa4ba4d21ef4445a16191b
DIFF: https://github.com/llvm/llvm-project/commit/45e8a0befbc8e174c3fa4ba4d21ef4445a16191b.diff

LOG: [Orc] At CBindings for LazyRexports

At C bindings and an example for LLJIT with lazy reexports

Differential Revision: https://reviews.llvm.org/D104672

Added: 
    llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/CMakeLists.txt
    llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/OrcV2CBindingsLazy.c
    llvm/test/Examples/OrcV2Examples/orcv2-cbindings-lazy.test

Modified: 
    llvm/examples/OrcV2Examples/CMakeLists.txt
    llvm/include/llvm-c/Orc.h
    llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
    llvm/test/CMakeLists.txt
    llvm/test/lit.cfg.py

Removed: 
    


################################################################################
diff  --git a/llvm/examples/OrcV2Examples/CMakeLists.txt b/llvm/examples/OrcV2Examples/CMakeLists.txt
index e46448bed06f..59311f8fbf1c 100644
--- a/llvm/examples/OrcV2Examples/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/CMakeLists.txt
@@ -14,6 +14,7 @@ add_subdirectory(OrcV2CBindingsDumpObjects)
 add_subdirectory(OrcV2CBindingsIRTransforms)
 add_subdirectory(OrcV2CBindingsReflectProcessSymbols)
 add_subdirectory(OrcV2CBindingsRemovableCode)
+add_subdirectory(OrcV2CBindingsLazy)
 
 if(CMAKE_HOST_UNIX)
   add_subdirectory(LLJITWithRemoteDebugging)

diff  --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/CMakeLists.txt b/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/CMakeLists.txt
new file mode 100644
index 000000000000..52eb2d496fc2
--- /dev/null
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS
+  Core
+  ExecutionEngine
+  IRReader
+  JITLink
+  MC
+  OrcJIT
+  Support
+  Target
+  nativecodegen
+  )
+
+add_llvm_example(OrcV2CBindingsLazy
+  OrcV2CBindingsLazy.c
+  )

diff  --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/OrcV2CBindingsLazy.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/OrcV2CBindingsLazy.c
new file mode 100644
index 000000000000..0f4f979127e8
--- /dev/null
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/OrcV2CBindingsLazy.c
@@ -0,0 +1,244 @@
+//===-------- BasicOrcV2CBindings.c - Basic OrcV2 C Bindings Demo ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/Core.h"
+#include "llvm-c/Error.h"
+#include "llvm-c/IRReader.h"
+#include "llvm-c/Initialization.h"
+#include "llvm-c/LLJIT.h"
+#include "llvm-c/Support.h"
+#include "llvm-c/Target.h"
+
+#include <stdio.h>
+
+int handleError(LLVMErrorRef Err) {
+  char *ErrMsg = LLVMGetErrorMessage(Err);
+  fprintf(stderr, "Error: %s\n", ErrMsg);
+  LLVMDisposeErrorMessage(ErrMsg);
+  return 1;
+}
+
+// Example IR modules.
+//
+// Note that in the conditionally compiled modules, FooMod and BarMod, functions
+// have been given an _body suffix. This is to ensure that their names do not
+// clash with their lazy-reexports.
+// For clients who do not wish to rename function bodies (e.g. because they want
+// to re-use cached objects between static and JIT compiles) techniques exist to
+// avoid renaming. See the lazy-reexports section of the ORCv2 design doc.
+
+const char FooMod[] = "  define i32 @foo_body() { \n"
+                      "  entry:                   \n"
+                      "    ret i32 1              \n"
+                      "  }                        \n";
+
+const char BarMod[] = "  define i32 @bar_body() { \n"
+                      "  entry:                   \n"
+                      "    ret i32 2              \n"
+                      "  }                        \n";
+
+const char MainMod[] =
+    "  define i32 @entry(i32 %argc) {                                 \n"
+    "  entry:                                                         \n"
+    "    %and = and i32 %argc, 1                                      \n"
+    "    %tobool = icmp eq i32 %and, 0                                \n"
+    "    br i1 %tobool, label %if.end, label %if.then                 \n"
+    "                                                                 \n"
+    "  if.then:                                                       \n"
+    "    %call = tail call i32 @foo()                                 \n"
+    "    br label %return                                             \n"
+    "                                                                 \n"
+    "  if.end:                                                        \n"
+    "    %call1 = tail call i32 @bar()                                \n"
+    "    br label %return                                             \n"
+    "                                                                 \n"
+    "  return:                                                        \n"
+    "    %retval.0 = phi i32 [ %call, %if.then ], [ %call1, %if.end ] \n"
+    "    ret i32 %retval.0                                            \n"
+    "  }                                                              \n"
+    "                                                                 \n"
+    "  declare i32 @foo()                                             \n"
+    "  declare i32 @bar()                                             \n";
+
+LLVMErrorRef parseExampleModule(const char *Source, size_t Len,
+                                const char *Name,
+                                LLVMOrcThreadSafeModuleRef *TSM) {
+  // Create a new ThreadSafeContext and underlying LLVMContext.
+  LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
+
+  // Get a reference to the underlying LLVMContext.
+  LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx);
+
+  // Wrap Source in a MemoryBuffer
+  LLVMMemoryBufferRef MB =
+      LLVMCreateMemoryBufferWithMemoryRange(Source, Len, Name, 0);
+
+  // Parse the LLVM module.
+  LLVMModuleRef M;
+  char *ErrMsg;
+  if (LLVMParseIRInContext(Ctx, MB, &M, &ErrMsg)) {
+    return LLVMCreateStringError(ErrMsg);
+    // TODO: LLVMDisposeMessage(ErrMsg);
+  }
+
+  // Our module is now complete. Wrap it and our ThreadSafeContext in a
+  // ThreadSafeModule.
+  *TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);
+
+  // Dispose of our local ThreadSafeContext value. The underlying LLVMContext
+  // will be kept alive by our ThreadSafeModule, TSM.
+  LLVMOrcDisposeThreadSafeContext(TSCtx);
+
+  return LLVMErrorSuccess;
+}
+
+int main(int argc, char *argv[]) {
+
+  int MainResult = 0;
+
+  // Parse command line arguments and initialize LLVM Core.
+  LLVMParseCommandLineOptions(argc, (const char **)argv, "");
+  LLVMInitializeCore(LLVMGetGlobalPassRegistry());
+
+  // Initialize native target codegen and asm printer.
+  LLVMInitializeNativeTarget();
+  LLVMInitializeNativeAsmPrinter();
+
+  // Set up a JIT instance.
+  LLVMOrcLLJITRef J;
+  const char *TargetTriple;
+  {
+    LLVMErrorRef Err;
+    if ((Err = LLVMOrcCreateLLJIT(&J, 0))) {
+      MainResult = handleError(Err);
+      goto llvm_shutdown;
+    }
+    TargetTriple = LLVMOrcLLJITGetTripleString(J);
+  }
+
+  // Add our demo modules to the JIT.
+  {
+    LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J);
+    LLVMErrorRef Err;
+
+    LLVMOrcThreadSafeModuleRef FooTSM;
+    if ((Err =
+             parseExampleModule(FooMod, sizeof(FooMod), "foo-mod", &FooTSM))) {
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+
+    if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, FooTSM))) {
+      // If adding the ThreadSafeModule fails then we need to clean it up
+      // ourselves. If adding it succeeds the JIT will manage the memory.
+      LLVMOrcDisposeThreadSafeModule(FooTSM);
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+
+    LLVMOrcThreadSafeModuleRef BarTSM;
+    if ((Err =
+             parseExampleModule(BarMod, sizeof(BarMod), "bar-mod", &BarTSM))) {
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+
+    if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, BarTSM))) {
+      LLVMOrcDisposeThreadSafeModule(BarTSM);
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+
+    LLVMOrcThreadSafeModuleRef MainTSM;
+    if ((Err = parseExampleModule(MainMod, sizeof(MainMod), "main-mod",
+                                  &MainTSM))) {
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+
+    if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, MainTSM))) {
+      LLVMOrcDisposeThreadSafeModule(MainTSM);
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+  }
+
+  // add lazy reexports
+  LLVMOrcIndirectStubsManagerRef ISM =
+      LLVMOrcCreateLocalIndirectStubsManager(TargetTriple);
+
+  LLVMOrcLazyCallThroughManagerRef LCTM;
+  {
+    LLVMErrorRef Err;
+    LLVMOrcExecutionSessionRef ES = LLVMOrcLLJITGetExecutionSession(J);
+    if ((Err = LLVMOrcCreateLocalLazyCallThroughManager(TargetTriple, ES, 0,
+                                                        &LCTM))) {
+      LLVMOrcDisposeIndirectStubsManager(ISM);
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+  }
+
+  LLVMJITSymbolFlags flag = {
+      LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0};
+  LLVMOrcCSymbolAliasMapPair ReExports[2] = {
+      {LLVMOrcLLJITMangleAndIntern(J, "foo"),
+       {LLVMOrcLLJITMangleAndIntern(J, "foo_body"), flag}},
+      {LLVMOrcLLJITMangleAndIntern(J, "bar"),
+       {LLVMOrcLLJITMangleAndIntern(J, "bar_body"), flag}},
+  };
+
+  {
+    LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J);
+    LLVMOrcMaterializationUnitRef MU =
+        LLVMOrcLazyReexports(LCTM, ISM, MainJD, ReExports, 2);
+    LLVMOrcJITDylibDefine(MainJD, MU);
+  }
+
+  // Look up the address of our demo entry point.
+  LLVMOrcJITTargetAddress EntryAddr;
+  {
+    LLVMErrorRef Err;
+    if ((Err = LLVMOrcLLJITLookup(J, &EntryAddr, "entry"))) {
+      MainResult = handleError(Err);
+      goto cleanup;
+    }
+  }
+
+  // If we made it here then everything succeeded. Execute our JIT'd code.
+  int32_t (*Entry)(int32_t) = (int32_t(*)(int32_t))EntryAddr;
+  int32_t Result = Entry(argc);
+
+  printf("--- Result ---\n");
+  printf("entry(%i) = %i\n", argc, Result);
+
+cleanup : {
+  LLVMOrcDisposeIndirectStubsManager(ISM);
+  LLVMOrcDisposeLazyCallThroughManager(LCTM);
+}
+
+jit_cleanup:
+  // Destroy our JIT instance. This will clean up any memory that the JIT has
+  // taken ownership of. This operation is non-trivial (e.g. it may need to
+  // JIT static destructors) and may also fail. In that case we want to render
+  // the error to stderr, but not overwrite any existing return value.
+  {
+    LLVMErrorRef Err;
+    if ((Err = LLVMOrcDisposeLLJIT(J))) {
+      int NewFailureResult = handleError(Err);
+      if (MainResult == 0)
+        MainResult = NewFailureResult;
+    }
+  }
+
+llvm_shutdown:
+  // Shut down LLVM.
+  LLVMShutdown();
+
+  return MainResult;
+}

diff  --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h
index 1d26d7ca303c..62688d2675d5 100644
--- a/llvm/include/llvm-c/Orc.h
+++ b/llvm/include/llvm-c/Orc.h
@@ -123,6 +123,28 @@ typedef struct {
  */
 typedef LLVMJITCSymbolMapPair *LLVMOrcCSymbolMapPairs;
 
+/**
+ * Represents a SymbolAliasMapEntry
+ */
+typedef struct {
+  LLVMOrcSymbolStringPoolEntryRef Name;
+  LLVMJITSymbolFlags Flags;
+} LLVMOrcCSymbolAliasMapEntry;
+
+/**
+ * Represents a pair of a symbol name and SymbolAliasMapEntry.
+ */
+typedef struct {
+  LLVMOrcSymbolStringPoolEntryRef Name;
+  LLVMOrcCSymbolAliasMapEntry Entry;
+} LLVMOrcCSymbolAliasMapPair;
+
+/**
+ * Represents a list of (SymbolStringPtr, (SymbolStringPtr, JITSymbolFlags))
+ * pairs that can be used to construct a SymbolFlagsMap.
+ */
+typedef LLVMOrcCSymbolAliasMapPair *LLVMOrcCSymbolAliasMapPairs;
+
 /**
  * Lookup kind. This can be used by definition generators when deciding whether
  * to produce a definition for a requested symbol.
@@ -373,6 +395,18 @@ typedef struct LLVMOrcOpaqueObjectTransformLayer
 typedef LLVMErrorRef (*LLVMOrcObjectTransformLayerTransformFunction)(
     void *Ctx, LLVMMemoryBufferRef *ObjInOut);
 
+/**
+ * A reference to an orc::IndirectStubsManager instance.
+ */
+typedef struct LLVMOrcOpaqueIndirectStubsManager
+    *LLVMOrcIndirectStubsManagerRef;
+
+/**
+ * A reference to an orc::LazyCallThroughManager instance.
+ */
+typedef struct LLVMOrcOpaqueLazyCallThroughManager
+    *LLVMOrcLazyCallThroughManagerRef;
+
 /**
  * A reference to an orc::DumpObjects object.
  *
@@ -536,6 +570,33 @@ LLVMOrcMaterializationUnitRef LLVMOrcCreateCustomMaterializationUnit(
 LLVMOrcMaterializationUnitRef
 LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs);
 
+/**
+ * Create a MaterializationUnit to define lazy re-expots. These are callable
+ * entry points that call through to the given symbols.
+ *
+ * This function takes ownership of the CallableAliases array. The Name
+ * fields of the array elements are taken to have been retained for this
+ * function. This allows the following pattern...
+ *
+ *   size_t NumPairs;
+ *   LLVMOrcCSymbolAliasMapPairs CallableAliases;
+ *   -- Build CallableAliases array --
+ *   LLVMOrcMaterializationUnitRef MU =
+ *      LLVMOrcLazyReexports(LCTM, ISM, JD, CallableAliases, NumPairs);
+ *
+ * ... without requiring cleanup of the elements of the CallableAliases array afterwards.
+ *
+ * The client is still responsible for deleting the CallableAliases array itself.
+ *
+ * If a client wishes to reuse elements of the CallableAliases array after this call they
+ * must explicitly retain each of the elements for themselves.
+ */
+LLVMOrcMaterializationUnitRef LLVMOrcLazyReexports(
+    LLVMOrcLazyCallThroughManagerRef LCTM, LLVMOrcIndirectStubsManagerRef ISM,
+    LLVMOrcJITDylibRef SourceRef, LLVMOrcCSymbolAliasMapPairs CallableAliases,
+    size_t NumPairs);
+// TODO: ImplSymbolMad SrcJDLoc
+
 /**
  * Create a "bare" JITDylib.
  *
@@ -799,6 +860,31 @@ void LLVMOrcObjectTransformLayerSetTransform(
     LLVMOrcObjectTransformLayerRef ObjTransformLayer,
     LLVMOrcObjectTransformLayerTransformFunction TransformFunction, void *Ctx);
 
+/**
+ * Create a LocalIndirectStubsManager from the given target triple.
+ *
+ * The resulting IndirectStubsManager is owned by the client
+ * and must be disposed of by calling LLVMOrcDisposeDisposeIndirectStubsManager.
+ */
+LLVMOrcIndirectStubsManagerRef
+LLVMOrcCreateLocalIndirectStubsManager(const char *TargetTriple);
+
+/**
+ * Dispose of an IndirectStubsManager.
+ */
+void LLVMOrcDisposeIndirectStubsManager(LLVMOrcIndirectStubsManagerRef ISM);
+
+LLVMErrorRef LLVMOrcCreateLocalLazyCallThroughManager(
+    const char *TargetTriple, LLVMOrcExecutionSessionRef ES,
+    LLVMOrcJITTargetAddress ErrorHandlerAddr,
+    LLVMOrcLazyCallThroughManagerRef *LCTM);
+
+/**
+ * Dispose of an LazyCallThroughManager.
+ */
+void LLVMOrcDisposeLazyCallThroughManager(
+    LLVMOrcLazyCallThroughManagerRef LCTM);
+
 /**
  * Create a DumpObjects instance.
  *

diff  --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
index ed45ec6f836b..3068a41b932b 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
@@ -98,9 +98,12 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRTransformLayer, LLVMOrcIRTransformLayerRef)
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ObjectTransformLayer,
                                    LLVMOrcObjectTransformLayerRef)
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DumpObjects, LLVMOrcDumpObjectsRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IndirectStubsManager,
+                                   LLVMOrcIndirectStubsManagerRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LazyCallThroughManager,
+                                   LLVMOrcLazyCallThroughManagerRef)
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJITBuilder, LLVMOrcLLJITBuilderRef)
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJIT, LLVMOrcLLJITRef)
-
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
 
 namespace llvm {
@@ -341,6 +344,26 @@ LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs) {
   return wrap(absoluteSymbols(std::move(SM)).release());
 }
 
+LLVMOrcMaterializationUnitRef LLVMOrcLazyReexports(
+    LLVMOrcLazyCallThroughManagerRef LCTM, LLVMOrcIndirectStubsManagerRef ISM,
+    LLVMOrcJITDylibRef SourceJD, LLVMOrcCSymbolAliasMapPairs CallableAliases,
+    size_t NumPairs) {
+
+  SymbolAliasMap SAM;
+  for (size_t I = 0; I != NumPairs; ++I) {
+    auto pair = CallableAliases[I];
+    JITSymbolFlags Flags = toJITSymbolFlags(pair.Entry.Flags);
+    SymbolStringPtr Name =
+        OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(pair.Entry.Name));
+    SAM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(pair.Name))] =
+        SymbolAliasMapEntry(Name, Flags);
+  }
+
+  return wrap(lazyReexports(*unwrap(LCTM), *unwrap(ISM), *unwrap(SourceJD),
+                            std::move(SAM))
+                  .release());
+}
+
 LLVMOrcJITDylibRef
 LLVMOrcExecutionSessionCreateBareJITDylib(LLVMOrcExecutionSessionRef ES,
                                           const char *Name) {
@@ -725,3 +748,31 @@ void LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(
 LLVMOrcIRTransformLayerRef LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J) {
   return wrap(&unwrap(J)->getIRTransformLayer());
 }
+
+LLVMOrcIndirectStubsManagerRef
+LLVMOrcCreateLocalIndirectStubsManager(const char *TargetTriple) {
+  auto builder = createLocalIndirectStubsManagerBuilder(Triple(TargetTriple));
+  return wrap(builder().release());
+}
+
+void LLVMOrcDisposeIndirectStubsManager(LLVMOrcIndirectStubsManagerRef ISM) {
+  std::unique_ptr<IndirectStubsManager> TmpISM(unwrap(ISM));
+}
+
+LLVMErrorRef LLVMOrcCreateLocalLazyCallThroughManager(
+    const char *TargetTriple, LLVMOrcExecutionSessionRef ES,
+    LLVMOrcJITTargetAddress ErrorHandlerAddr,
+    LLVMOrcLazyCallThroughManagerRef *Result) {
+  auto LCTM = createLocalLazyCallThroughManager(Triple(TargetTriple),
+                                                *unwrap(ES), ErrorHandlerAddr);
+
+  if (!LCTM)
+    return wrap(LCTM.takeError());
+  *Result = wrap(LCTM->release());
+  return LLVMErrorSuccess;
+}
+
+void LLVMOrcDisposeLazyCallThroughManager(
+    LLVMOrcLazyCallThroughManagerRef LCM) {
+  std::unique_ptr<LazyCallThroughManager> TmpLCM(unwrap(LCM));
+}

diff  --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt
index 7fd52d207df4..89a2d8b9e113 100644
--- a/llvm/test/CMakeLists.txt
+++ b/llvm/test/CMakeLists.txt
@@ -166,6 +166,7 @@ if(LLVM_BUILD_EXAMPLES)
     OrcV2CBindingsAddObjectFile
     OrcV2CBindingsRemovableCode
     OrcV2CBindingsReflectProcessSymbols
+    OrcV2CBindingsLazy
     )
   if(CMAKE_HOST_UNIX)
     list(APPEND LLVM_TEST_DEPENDS

diff  --git a/llvm/test/Examples/OrcV2Examples/orcv2-cbindings-lazy.test b/llvm/test/Examples/OrcV2Examples/orcv2-cbindings-lazy.test
new file mode 100644
index 000000000000..b8e8f53361ea
--- /dev/null
+++ b/llvm/test/Examples/OrcV2Examples/orcv2-cbindings-lazy.test
@@ -0,0 +1,5 @@
+# RUN: OrcV2CBindingsLazy 2>&1 | FileCheck -check-prefix=THIS %s
+# RUN: OrcV2CBindingsLazy 0 2>&1 | FileCheck -check-prefix=OTHER %s
+
+# THIS: entry(1) = 1
+# OTHER: entry(2) = 2

diff  --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index e8de805eae71..887be9abaa12 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -186,7 +186,8 @@ def get_asan_rtlib():
     ToolSubst('OrcV2CBindingsBasicUsage', unresolved='ignore'),
     ToolSubst('OrcV2CBindingsAddObjectFile', unresolved='ignore'),
     ToolSubst('OrcV2CBindingsRemovableCode', unresolved='ignore'),
-    ToolSubst('OrcV2CBindingsReflectProcessSymbols', unresolved='ignore')])
+    ToolSubst('OrcV2CBindingsReflectProcessSymbols', unresolved='ignore'),
+    ToolSubst('OrcV2CBindingsLazy', unresolved='ignore')])
 
 llvm_config.add_tool_substitutions(tools, config.llvm_tools_dir)
 


        


More information about the llvm-commits mailing list