[llvm] b5a6ad8 - [Orc] Add verylazy example for C-bindings

Valentin Churavy via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 18 03:07:41 PDT 2021


Author: Valentin Churavy
Date: 2021-07-18T12:07:16+02:00
New Revision: b5a6ad8c893a642bcb08ab81b251952c545405d9

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

LOG: [Orc] Add verylazy example for C-bindings

Still WIP, based on the Kaleidoscope/BuildingAJIT/Chapter4.

Reviewed By: lhames

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

Added: 
    llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/CMakeLists.txt
    llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/OrcV2CBindingsVeryLazy.c

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

Removed: 
    


################################################################################
diff  --git a/llvm/examples/OrcV2Examples/CMakeLists.txt b/llvm/examples/OrcV2Examples/CMakeLists.txt
index 59311f8fbf1c0..d6fa7423df19a 100644
--- a/llvm/examples/OrcV2Examples/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/CMakeLists.txt
@@ -15,6 +15,7 @@ add_subdirectory(OrcV2CBindingsIRTransforms)
 add_subdirectory(OrcV2CBindingsReflectProcessSymbols)
 add_subdirectory(OrcV2CBindingsRemovableCode)
 add_subdirectory(OrcV2CBindingsLazy)
+add_subdirectory(OrcV2CBindingsVeryLazy)
 
 if(CMAKE_HOST_UNIX)
   add_subdirectory(LLJITWithRemoteDebugging)

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

diff  --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/OrcV2CBindingsVeryLazy.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/OrcV2CBindingsVeryLazy.c
new file mode 100644
index 0000000000000..93d36a40b12f3
--- /dev/null
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/OrcV2CBindingsVeryLazy.c
@@ -0,0 +1,301 @@
+//===-------- 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 <assert.h>
+#include <stdio.h>
+#include <string.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 applyDataLayout(void *Ctx, LLVMModuleRef M) {
+  LLVMSetDataLayout(M, LLVMOrcLLJITGetDataLayoutStr((LLVMOrcLLJITRef)Ctx));
+  return LLVMErrorSuccess;
+}
+
+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, 1);
+
+  // Parse the LLVM module.
+  LLVMModuleRef M;
+  char *ErrMsg;
+  if (LLVMParseIRInContext(Ctx, MB, &M, &ErrMsg)) {
+    LLVMErrorRef Err = LLVMCreateStringError(ErrMsg);
+    LLVMDisposeMessage(ErrMsg);
+    return Err;
+  }
+
+  // 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;
+}
+
+void Destroy(void *Ctx) {}
+
+void Materialize(void *Ctx, LLVMOrcMaterializationResponsibilityRef MR) {
+  int MainResult = 0;
+
+  size_t NumSymbols;
+  LLVMOrcSymbolStringPoolEntryRef *Symbols =
+      LLVMOrcMaterializationResponsibilityGetRequestedSymbols(MR, &NumSymbols);
+
+  assert(NumSymbols == 1);
+
+  LLVMOrcLLJITRef J = (LLVMOrcLLJITRef)Ctx;
+  LLVMOrcSymbolStringPoolEntryRef Sym = Symbols[0];
+
+  LLVMOrcThreadSafeModuleRef TSM = 0;
+  LLVMErrorRef Err;
+
+  LLVMOrcSymbolStringPoolEntryRef FooBody =
+      LLVMOrcLLJITMangleAndIntern(J, "foo_body");
+  LLVMOrcSymbolStringPoolEntryRef BarBody =
+      LLVMOrcLLJITMangleAndIntern(J, "bar_body");
+
+  if (Sym == FooBody) {
+    if ((Err = parseExampleModule(FooMod, strlen(FooMod), "foo-mod", &TSM))) {
+      MainResult = handleError(Err);
+      goto cleanup;
+    }
+  } else if (Sym == BarBody) {
+    if ((Err = parseExampleModule(BarMod, strlen(BarMod), "bar-mod", &TSM))) {
+      MainResult = handleError(Err);
+      goto cleanup;
+    }
+  } else {
+    MainResult = 1;
+    goto cleanup;
+  }
+  assert(TSM);
+
+  if ((Err = LLVMOrcThreadSafeModuleWithModuleDo(TSM, &applyDataLayout, Ctx))) {
+    MainResult = handleError(Err);
+    goto cleanup;
+  }
+
+cleanup:
+  LLVMOrcReleaseSymbolStringPoolEntry(BarBody);
+  LLVMOrcReleaseSymbolStringPoolEntry(FooBody);
+  LLVMOrcDisposeSymbols(Symbols);
+  if (MainResult == 1) {
+    LLVMOrcMaterializationResponsibilityFailMaterialization(MR);
+    LLVMOrcDisposeMaterializationResponsibility(MR);
+  } else {
+    LLVMOrcIRTransformLayerRef IRLayer = LLVMOrcLLJITGetIRTransformLayer(J);
+    LLVMOrcIRTransformLayerEmit(IRLayer, MR, TSM);
+  }
+  return;
+}
+
+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 main module to the JIT.
+  {
+    LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J);
+    LLVMErrorRef Err;
+
+    LLVMOrcThreadSafeModuleRef MainTSM;
+    if ((Err = parseExampleModule(MainMod, strlen(MainMod), "main-mod",
+                                  &MainTSM))) {
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+
+    if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, MainTSM))) {
+      LLVMOrcDisposeThreadSafeModule(MainTSM);
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+  }
+
+  LLVMJITSymbolFlags Flags = {
+      LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0};
+  LLVMOrcCSymbolFlagsMapPair FooSym = {
+      LLVMOrcLLJITMangleAndIntern(J, "foo_body"), Flags};
+  LLVMOrcCSymbolFlagsMapPair BarSym = {
+      LLVMOrcLLJITMangleAndIntern(J, "bar_body"), Flags};
+
+  // add custom MaterializationUnit
+  {
+    LLVMOrcMaterializationUnitRef FooMU =
+        LLVMOrcCreateCustomMaterializationUnit("FooMU", J, &FooSym, 1, NULL,
+                                               &Materialize, NULL, &Destroy);
+
+    LLVMOrcMaterializationUnitRef BarMU =
+        LLVMOrcCreateCustomMaterializationUnit("BarMU", J, &BarSym, 1, NULL,
+                                               &Materialize, NULL, &Destroy);
+
+    LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J);
+    LLVMOrcJITDylibDefine(MainJD, FooMU);
+    LLVMOrcJITDylibDefine(MainJD, BarMU);
+  }
+
+  // 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;
+    }
+  }
+
+  LLVMOrcCSymbolAliasMapPair ReExports[2] = {
+      {LLVMOrcLLJITMangleAndIntern(J, "foo"),
+       {LLVMOrcLLJITMangleAndIntern(J, "foo_body"), Flags}},
+      {LLVMOrcLLJITMangleAndIntern(J, "bar"),
+       {LLVMOrcLLJITMangleAndIntern(J, "bar_body"), Flags}},
+  };
+
+  {
+    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/LLJIT.h b/llvm/include/llvm-c/LLJIT.h
index bd98cfbab839c..f689ca0f1cf0b 100644
--- a/llvm/include/llvm-c/LLJIT.h
+++ b/llvm/include/llvm-c/LLJIT.h
@@ -227,6 +227,14 @@ LLVMOrcLLJITGetObjTransformLayer(LLVMOrcLLJITRef J);
  */
 LLVMOrcIRTransformLayerRef LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J);
 
+/**
+ * Get the LLJIT instance's default data layout string.
+ *
+ * This string is owned by the LLJIT instance and does not need to be freed
+ * by the caller.
+ */
+const char *LLVMOrcLLJITGetDataLayoutStr(LLVMOrcLLJITRef J);
+
 LLVM_C_EXTERN_C_END
 
 #endif /* LLVM_C_LLJIT_H */

diff  --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h
index 62688d2675d5a..1790afbcecc77 100644
--- a/llvm/include/llvm-c/Orc.h
+++ b/llvm/include/llvm-c/Orc.h
@@ -145,6 +145,34 @@ typedef struct {
  */
 typedef LLVMOrcCSymbolAliasMapPair *LLVMOrcCSymbolAliasMapPairs;
 
+/**
+ * A reference to an orc::JITDylib instance.
+ */
+typedef struct LLVMOrcOpaqueJITDylib *LLVMOrcJITDylibRef;
+
+/**
+ * Represents a list of LLVMOrcSymbolStringPoolEntryRef and the associated
+ * length.
+ */
+typedef struct {
+  LLVMOrcSymbolStringPoolEntryRef *Symbols;
+  size_t Length;
+} LLVMOrcCSymbolsList;
+
+/**
+ * Represents a pair of a JITDylib and LLVMOrcCSymbolsList.
+ */
+typedef struct {
+  LLVMOrcJITDylibRef JD;
+  LLVMOrcCSymbolsList Names;
+} LLVMOrcCDependenceMapPair;
+
+/**
+ * Represents a list of (JITDylibRef, (LLVMOrcSymbolStringPoolEntryRef*,
+ * size_t)) pairs that can be used to construct a SymbolDependenceMap.
+ */
+typedef LLVMOrcCDependenceMapPair *LLVMOrcCDependenceMapPairs;
+
 /**
  * Lookup kind. This can be used by definition generators when deciding whether
  * to produce a definition for a requested symbol.
@@ -210,11 +238,6 @@ typedef struct LLVMOrcOpaqueMaterializationUnit *LLVMOrcMaterializationUnitRef;
 typedef struct LLVMOrcOpaqueMaterializationResponsibility
     *LLVMOrcMaterializationResponsibilityRef;
 
-/**
- * A reference to an orc::JITDylib instance.
- */
-typedef struct LLVMOrcOpaqueJITDylib *LLVMOrcJITDylibRef;
-
 /**
  * A MaterializationUnit materialize callback.
  *
@@ -597,6 +620,199 @@ LLVMOrcMaterializationUnitRef LLVMOrcLazyReexports(
     size_t NumPairs);
 // TODO: ImplSymbolMad SrcJDLoc
 
+/**
+ * Disposes of the passed MaterializationResponsibility object.
+ *
+ * This should only be done after the symbols covered by the object have either
+ * been resolved and emitted (via
+ * LLVMOrcMaterializationResponsibilityNotifyResolved and
+ * LLVMOrcMaterializationResponsibilityNotifyEmitted) or failed (via
+ * LLVMOrcMaterializationResponsibilityFailMaterialization).
+ */
+void LLVMOrcDisposeMaterializationResponsibility(
+    LLVMOrcMaterializationResponsibilityRef MR);
+
+/**
+ * Returns the target JITDylib that these symbols are being materialized into.
+ */
+LLVMOrcJITDylibRef LLVMOrcMaterializationResponsibilityGetTargetDylib(
+    LLVMOrcMaterializationResponsibilityRef MR);
+
+/**
+ * Returns the ExecutionSession for this MaterializationResponsibility.
+ */
+LLVMOrcExecutionSessionRef
+LLVMOrcMaterializationResponsibilityGetExecutionSession(
+    LLVMOrcMaterializationResponsibilityRef MR);
+
+/**
+ * Returns the symbol flags map for this responsibility instance.
+ *
+ * The length of the array is returned in NumPairs and the caller is responsible
+ * for the returned memory and needs to call LLVMOrcDisposeCSymbolFlagsMap.
+ *
+ * To use the returned symbols beyond the livetime of the
+ * MaterializationResponsibility requires the caller to retain the symbols
+ * explicitly.
+ */
+LLVMOrcCSymbolFlagsMapPairs LLVMOrcMaterializationResponsibilityGetSymbols(
+    LLVMOrcMaterializationResponsibilityRef MR, size_t *NumPairs);
+
+/**
+ * Disposes of the passed LLVMOrcCSymbolFlagsMap.
+ *
+ * Does not release the entries themselves.
+ */
+void LLVMOrcDisposeCSymbolFlagsMap(LLVMOrcCSymbolFlagsMapPairs Pairs);
+
+/**
+ * Returns the initialization pseudo-symbol, if any. This symbol will also
+ * be present in the SymbolFlagsMap for this MaterializationResponsibility
+ * object.
+ *
+ * The returned symbol is not retained over any mutating operation of the
+ * MaterializationResponsbility or beyond the lifetime thereof.
+ */
+LLVMOrcSymbolStringPoolEntryRef
+LLVMOrcMaterializationResponsibilityGetInitializerSymbol(
+    LLVMOrcMaterializationResponsibilityRef MR);
+
+/**
+ * Returns the names of any symbols covered by this
+ * MaterializationResponsibility object that have queries pending. This
+ * information can be used to return responsibility for unrequested symbols
+ * back to the JITDylib via the delegate method.
+ */
+LLVMOrcSymbolStringPoolEntryRef *
+LLVMOrcMaterializationResponsibilityGetRequestedSymbols(
+    LLVMOrcMaterializationResponsibilityRef MR, size_t *NumSymbols);
+
+/**
+ * Disposes of the passed LLVMOrcSymbolStringPoolEntryRef* .
+ *
+ * Does not release the symbols themselves.
+ */
+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
+ * symbols must be ones covered by this MaterializationResponsibility
+ * instance. Individual calls to this method may resolve a subset of the
+ * symbols, but all symbols must have been resolved prior to calling emit.
+ *
+ * This method will return an error if any symbols being resolved have been
+ * moved to the error state due to the failure of a dependency. If this
+ * method returns an error then clients should log it and call
+ * LLVMOrcMaterializationResponsibilityFailMaterialization. If no dependencies
+ * have been registered for the symbols covered by this
+ * MaterializationResponsibiility then this method is guaranteed to return
+ * LLVMErrorSuccess.
+ */
+LLVMErrorRef LLVMOrcMaterializationResponsibilityNotifyResolved(
+    LLVMOrcMaterializationResponsibilityRef MR, LLVMOrcCSymbolMapPairs Symbols,
+    size_t NumPairs);
+
+/**
+ * Notifies the target JITDylib (and any pending queries on that JITDylib)
+ * that all symbols covered by this MaterializationResponsibility instance
+ * have been emitted.
+ *
+ * This method will return an error if any symbols being resolved have been
+ * moved to the error state due to the failure of a dependency. If this
+ * method returns an error then clients should log it and call
+ * LLVMOrcMaterializationResponsibilityFailMaterialization.
+ * If no dependencies have been registered for the symbols covered by this
+ * MaterializationResponsibiility then this method is guaranteed to return
+ * LLVMErrorSuccess.
+ */
+LLVMErrorRef LLVMOrcMaterializationResponsibilityNotifyEmitted(
+    LLVMOrcMaterializationResponsibilityRef MR);
+
+/**
+ * Attempt to claim responsibility for new definitions. This method can be
+ * used to claim responsibility for symbols that are added to a
+ * materialization unit during the compilation process (e.g. literal pool
+ * symbols). Symbol linkage rules are the same as for symbols that are
+ * defined up front: duplicate strong definitions will result in errors.
+ * Duplicate weak definitions will be discarded (in which case they will
+ * not be added to this responsibility instance).
+ *
+ * This method can be used by materialization units that want to add
+ * additional symbols at materialization time (e.g. stubs, compile
+ * callbacks, metadata)
+ */
+LLVMErrorRef LLVMOrcMaterializationResponsibilityDefineMaterializing(
+    LLVMOrcMaterializationResponsibilityRef MR,
+    LLVMOrcCSymbolFlagsMapPairs Pairs, size_t NumPairs);
+
+/**
+ * Notify all not-yet-emitted covered by this MaterializationResponsibility
+ * instance that an error has occurred.
+ * This will remove all symbols covered by this MaterializationResponsibilty
+ * from the target JITDylib, and send an error to any queries waiting on
+ * these symbols.
+ */
+void LLVMOrcMaterializationResponsibilityFailMaterialization(
+    LLVMOrcMaterializationResponsibilityRef MR);
+
+/**
+ * Transfers responsibility to the given MaterializationUnit for all
+ * symbols defined by that MaterializationUnit. This allows
+ * materializers to break up work based on run-time information (e.g.
+ * by introspecting which symbols have actually been looked up and
+ * materializing only those).
+ */
+LLVMErrorRef LLVMOrcMaterializationResponsibilityReplace(
+    LLVMOrcMaterializationResponsibilityRef MR,
+    LLVMOrcMaterializationUnitRef MU);
+
+/**
+ * Delegates responsibility for the given symbols to the returned
+ * materialization responsibility. Useful for breaking up work between
+ * threads, or 
diff erent kinds of materialization processes.
+ *
+ * The caller retains responsibility of the the passed
+ * MaterializationResponsibility.
+ */
+LLVMErrorRef LLVMOrcMaterializationResponsibilityDelegate(
+    LLVMOrcMaterializationResponsibilityRef MR,
+    LLVMOrcSymbolStringPoolEntryRef *Symbols, size_t NumSymbols,
+    LLVMOrcMaterializationResponsibilityRef *Result);
+
+/**
+ * Adds dependencies to a symbol that the MaterializationResponsibility is
+ * responsible for.
+ *
+ * This function takes ownership of Dependencies struct. The Names
+ * array have been retained for this function. This allows the following
+ * pattern...
+ *
+ *   LLVMOrcSymbolStringPoolEntryRef Names[] = {...};
+ *   LLVMOrcCDependenceMapPair Dependence = {JD, {Names, sizeof(Names)}}
+ *   LLVMOrcMaterializationResponsibilityAddDependencies(JD, Name, &Dependence,
+ * 1);
+ *
+ * ... without requiring cleanup of the elements of the Names array afterwards.
+ *
+ * The client is still responsible for deleting the Dependencies.Names array
+ * itself.
+ */
+void LLVMOrcMaterializationResponsibilityAddDependencies(
+    LLVMOrcMaterializationResponsibilityRef MR,
+    LLVMOrcSymbolStringPoolEntryRef Name,
+    LLVMOrcCDependenceMapPairs Dependencies, size_t NumPairs);
+
+/**
+ * Adds dependencies to all symbols that the MaterializationResponsibility is
+ * responsible for. See LLVMOrcMaterializationResponsibilityAddDependencies for
+ * notes about memory responsibility.
+ */
+void LLVMOrcMaterializationResponsibilityAddDependenciesForAll(
+    LLVMOrcMaterializationResponsibilityRef MR,
+    LLVMOrcCDependenceMapPairs Dependencies, size_t NumPairs);
+
 /**
  * Create a "bare" JITDylib.
  *
@@ -845,6 +1061,10 @@ void LLVMOrcObjectLayerEmit(LLVMOrcObjectLayerRef ObjLayer,
  */
 void LLVMOrcDisposeObjectLayer(LLVMOrcObjectLayerRef ObjLayer);
 
+void LLVMOrcIRTransformLayerEmit(LLVMOrcIRTransformLayerRef IRTransformLayer,
+                                 LLVMOrcMaterializationResponsibilityRef MR,
+                                 LLVMOrcThreadSafeModuleRef TSM);
+
 /**
  * Set the transform function of the provided transform layer, passing through a
  * pointer to user provided context.

diff  --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
index 3068a41b932ba..e6fdd065b9958 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
@@ -240,6 +240,48 @@ static JITSymbolFlags toJITSymbolFlags(LLVMJITSymbolFlags F) {
   return JSF;
 }
 
+static LLVMJITSymbolFlags fromJITSymbolFlags(JITSymbolFlags JSF) {
+  LLVMJITSymbolFlags F = {0, 0};
+  if (JSF & JITSymbolFlags::Exported)
+    F.GenericFlags |= LLVMJITSymbolGenericFlagsExported;
+  if (JSF & JITSymbolFlags::Weak)
+    F.GenericFlags |= LLVMJITSymbolGenericFlagsWeak;
+  if (JSF & JITSymbolFlags::Callable)
+    F.GenericFlags |= LLVMJITSymbolGenericFlagsCallable;
+  if (JSF & JITSymbolFlags::MaterializationSideEffectsOnly)
+    F.GenericFlags |= LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly;
+
+  F.TargetFlags = JSF.getTargetFlags();
+
+  return F;
+}
+
+static SymbolMap toSymbolMap(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs) {
+  SymbolMap SM;
+  for (size_t I = 0; I != NumPairs; ++I) {
+    JITSymbolFlags Flags = toJITSymbolFlags(Syms[I].Sym.Flags);
+    SM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] =
+        JITEvaluatedSymbol(Syms[I].Sym.Address, Flags);
+  }
+  return SM;
+}
+
+static SymbolDependenceMap
+toSymbolDependenceMap(LLVMOrcCDependenceMapPairs Pairs, size_t NumPairs) {
+  SymbolDependenceMap SDM;
+  for (size_t I = 0; I != NumPairs; ++I) {
+    JITDylib *JD = unwrap(Pairs[I].JD);
+    SymbolNameSet Names;
+
+    for (size_t J = 0; J != Pairs[I].Names.Length; ++J) {
+      auto Sym = Pairs[I].Names.Symbols[J];
+      Names.insert(OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Sym)));
+    }
+    SDM[JD] = Names;
+  }
+  return SDM;
+}
+
 } // end anonymous namespace
 
 void LLVMOrcExecutionSessionSetErrorReporter(
@@ -334,13 +376,7 @@ LLVMOrcMaterializationUnitRef LLVMOrcCreateCustomMaterializationUnit(
 
 LLVMOrcMaterializationUnitRef
 LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs) {
-  SymbolMap SM;
-  for (size_t I = 0; I != NumPairs; ++I) {
-    JITSymbolFlags Flags = toJITSymbolFlags(Syms[I].Sym.Flags);
-    SM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] =
-        JITEvaluatedSymbol(Syms[I].Sym.Address, Flags);
-  }
-
+  SymbolMap SM = toSymbolMap(Syms, NumPairs);
   return wrap(absoluteSymbols(std::move(SM)).release());
 }
 
@@ -364,6 +400,150 @@ LLVMOrcMaterializationUnitRef LLVMOrcLazyReexports(
                   .release());
 }
 
+void LLVMOrcDisposeMaterializationResponsibility(
+    LLVMOrcMaterializationResponsibilityRef MR) {
+  std::unique_ptr<MaterializationResponsibility> TmpMR(unwrap(MR));
+}
+
+LLVMOrcJITDylibRef LLVMOrcMaterializationResponsibilityGetTargetDylib(
+    LLVMOrcMaterializationResponsibilityRef MR) {
+  return wrap(&unwrap(MR)->getTargetJITDylib());
+}
+
+LLVMOrcExecutionSessionRef
+LLVMOrcMaterializationResponsibilityGetExecutionSession(
+    LLVMOrcMaterializationResponsibilityRef MR) {
+  return wrap(&unwrap(MR)->getExecutionSession());
+}
+
+LLVMOrcCSymbolFlagsMapPairs LLVMOrcMaterializationResponsibilityGetSymbols(
+    LLVMOrcMaterializationResponsibilityRef MR, size_t *NumPairs) {
+
+  auto Symbols = unwrap(MR)->getSymbols();
+  LLVMOrcCSymbolFlagsMapPairs Result = static_cast<LLVMOrcCSymbolFlagsMapPairs>(
+      safe_malloc(Symbols.size() * sizeof(LLVMOrcCSymbolFlagsMapPair)));
+  size_t I = 0;
+  for (auto const &pair : Symbols) {
+    auto Name = wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(pair.first));
+    auto Flags = pair.second;
+    Result[I] = {Name, fromJITSymbolFlags(Flags)};
+    I++;
+  }
+  *NumPairs = Symbols.size();
+  return Result;
+}
+
+void LLVMOrcDisposeCSymbolFlagsMap(LLVMOrcCSymbolFlagsMapPairs Pairs) {
+  free(Pairs);
+}
+
+LLVMOrcSymbolStringPoolEntryRef
+LLVMOrcMaterializationResponsibilityGetInitializerSymbol(
+    LLVMOrcMaterializationResponsibilityRef MR) {
+  auto Sym = unwrap(MR)->getInitializerSymbol();
+  return wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(Sym));
+}
+
+LLVMOrcSymbolStringPoolEntryRef *
+LLVMOrcMaterializationResponsibilityGetRequestedSymbols(
+    LLVMOrcMaterializationResponsibilityRef MR, size_t *NumSymbols) {
+
+  auto Symbols = unwrap(MR)->getRequestedSymbols();
+  LLVMOrcSymbolStringPoolEntryRef *Result =
+      static_cast<LLVMOrcSymbolStringPoolEntryRef *>(safe_malloc(
+          Symbols.size() * sizeof(LLVMOrcSymbolStringPoolEntryRef)));
+  size_t I = 0;
+  for (auto &Name : Symbols) {
+    Result[I] = wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(Name));
+    I++;
+  }
+  *NumSymbols = Symbols.size();
+  return Result;
+}
+
+void LLVMOrcDisposeSymbols(LLVMOrcSymbolStringPoolEntryRef *Symbols) {
+  free(Symbols);
+}
+
+LLVMErrorRef LLVMOrcMaterializationResponsibilityNotifyResolved(
+    LLVMOrcMaterializationResponsibilityRef MR, LLVMOrcCSymbolMapPairs Symbols,
+    size_t NumPairs) {
+  SymbolMap SM = toSymbolMap(Symbols, NumPairs);
+  return wrap(unwrap(MR)->notifyResolved(std::move(SM)));
+}
+
+LLVMErrorRef LLVMOrcMaterializationResponsibilityNotifyEmitted(
+    LLVMOrcMaterializationResponsibilityRef MR) {
+  return wrap(unwrap(MR)->notifyEmitted());
+}
+
+LLVMErrorRef LLVMOrcMaterializationResponsibilityDefineMaterializing(
+    LLVMOrcMaterializationResponsibilityRef MR,
+    LLVMOrcCSymbolFlagsMapPairs Syms, size_t NumSyms) {
+  SymbolFlagsMap SFM;
+  for (size_t I = 0; I != NumSyms; ++I)
+    SFM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] =
+        toJITSymbolFlags(Syms[I].Flags);
+
+  return wrap(unwrap(MR)->defineMaterializing(std::move(SFM)));
+}
+
+LLVMErrorRef LLVMOrcMaterializationResponsibilityReplace(
+    LLVMOrcMaterializationResponsibilityRef MR,
+    LLVMOrcMaterializationUnitRef MU) {
+  std::unique_ptr<MaterializationUnit> TmpMU(unwrap(MU));
+  return wrap(unwrap(MR)->replace(std::move(TmpMU)));
+}
+
+LLVMErrorRef LLVMOrcMaterializationResponsibilityDelegate(
+    LLVMOrcMaterializationResponsibilityRef MR,
+    LLVMOrcSymbolStringPoolEntryRef *Symbols, size_t NumSymbols,
+    LLVMOrcMaterializationResponsibilityRef *Result) {
+  SymbolNameSet Syms;
+  for (size_t I = 0; I != NumSymbols; I++) {
+    Syms.insert(OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Symbols[I])));
+  }
+  auto OtherMR = unwrap(MR)->delegate(Syms);
+
+  if (!OtherMR) {
+    return wrap(OtherMR.takeError());
+  }
+  *Result = wrap(OtherMR->release());
+  return LLVMErrorSuccess;
+}
+
+void LLVMOrcMaterializationResponsibilityAddDependencies(
+    LLVMOrcMaterializationResponsibilityRef MR,
+    LLVMOrcSymbolStringPoolEntryRef Name,
+    LLVMOrcCDependenceMapPairs Dependencies, size_t NumPairs) {
+
+  SymbolDependenceMap SDM = toSymbolDependenceMap(Dependencies, NumPairs);
+  auto Sym = OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Name));
+  unwrap(MR)->addDependencies(Sym, SDM);
+}
+
+void LLVMOrcMaterializationResponsibilityAddDependenciesForAll(
+    LLVMOrcMaterializationResponsibilityRef MR,
+    LLVMOrcCDependenceMapPairs Dependencies, size_t NumPairs) {
+
+  SymbolDependenceMap SDM = toSymbolDependenceMap(Dependencies, NumPairs);
+  unwrap(MR)->addDependenciesForAll(SDM);
+}
+
+void LLVMOrcMaterializationResponsibilityFailMaterialization(
+    LLVMOrcMaterializationResponsibilityRef MR) {
+  unwrap(MR)->failMaterialization();
+}
+
+void LLVMOrcIRTransformLayerEmit(LLVMOrcIRTransformLayerRef IRLayer,
+                                 LLVMOrcMaterializationResponsibilityRef MR,
+                                 LLVMOrcThreadSafeModuleRef TSM) {
+  std::unique_ptr<ThreadSafeModule> TmpTSM(unwrap(TSM));
+  unwrap(IRLayer)->emit(
+      std::unique_ptr<MaterializationResponsibility>(unwrap(MR)),
+      std::move(*TmpTSM));
+}
+
 LLVMOrcJITDylibRef
 LLVMOrcExecutionSessionCreateBareJITDylib(LLVMOrcExecutionSessionRef ES,
                                           const char *Name) {
@@ -749,6 +929,10 @@ LLVMOrcIRTransformLayerRef LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J) {
   return wrap(&unwrap(J)->getIRTransformLayer());
 }
 
+const char *LLVMOrcLLJITGetDataLayoutStr(LLVMOrcLLJITRef J) {
+  return unwrap(J)->getDataLayout().getStringRepresentation().c_str();
+}
+
 LLVMOrcIndirectStubsManagerRef
 LLVMOrcCreateLocalIndirectStubsManager(const char *TargetTriple) {
   auto builder = createLocalIndirectStubsManagerBuilder(Triple(TargetTriple));

diff  --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt
index 89a2d8b9e113d..fd60c5080099b 100644
--- a/llvm/test/CMakeLists.txt
+++ b/llvm/test/CMakeLists.txt
@@ -167,6 +167,7 @@ if(LLVM_BUILD_EXAMPLES)
     OrcV2CBindingsRemovableCode
     OrcV2CBindingsReflectProcessSymbols
     OrcV2CBindingsLazy
+    OrcV2CBindingsVeryLazy
     )
   if(CMAKE_HOST_UNIX)
     list(APPEND LLVM_TEST_DEPENDS

diff  --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index 07ec33abd4ce1..524832b1f8921 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -187,7 +187,8 @@ def get_asan_rtlib():
     ToolSubst('OrcV2CBindingsAddObjectFile', unresolved='ignore'),
     ToolSubst('OrcV2CBindingsRemovableCode', unresolved='ignore'),
     ToolSubst('OrcV2CBindingsReflectProcessSymbols', unresolved='ignore'),
-    ToolSubst('OrcV2CBindingsLazy', unresolved='ignore')])
+    ToolSubst('OrcV2CBindingsLazy', unresolved='ignore'),
+    ToolSubst('OrcV2CBindingsVeryLazy', unresolved='ignore')])
 
 llvm_config.add_tool_substitutions(tools, config.llvm_tools_dir)
 

diff  --git a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
index ceadebf811c7d..be566662a7992 100644
--- a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
@@ -354,3 +354,148 @@ TEST_F(OrcCAPITestBase, ExecutionTest) {
   int32_t Result = SumFn(1, 1);
   ASSERT_EQ(2, Result);
 }
+
+void Destroy(void *Ctx) {}
+
+void TargetFn() {}
+
+void Materialize(void *Ctx, LLVMOrcMaterializationResponsibilityRef MR) {
+  LLVMOrcJITDylibRef JD =
+      LLVMOrcMaterializationResponsibilityGetTargetDylib(MR);
+  ASSERT_TRUE(!!JD);
+
+  LLVMOrcExecutionSessionRef ES =
+      LLVMOrcMaterializationResponsibilityGetExecutionSession(MR);
+  ASSERT_TRUE(!!ES);
+
+  LLVMOrcSymbolStringPoolEntryRef InitSym =
+      LLVMOrcMaterializationResponsibilityGetInitializerSymbol(MR);
+  ASSERT_TRUE(!InitSym);
+
+  size_t NumSymbols;
+  LLVMOrcCSymbolFlagsMapPairs Symbols =
+      LLVMOrcMaterializationResponsibilityGetSymbols(MR, &NumSymbols);
+
+  ASSERT_TRUE(!!Symbols);
+  ASSERT_EQ(NumSymbols, (size_t)1);
+
+  LLVMOrcSymbolStringPoolEntryRef *RequestedSymbols =
+      LLVMOrcMaterializationResponsibilityGetRequestedSymbols(MR, &NumSymbols);
+
+  ASSERT_TRUE(!!RequestedSymbols);
+  ASSERT_EQ(NumSymbols, (size_t)1);
+
+  LLVMOrcCSymbolFlagsMapPair TargetSym = Symbols[0];
+
+  ASSERT_EQ(RequestedSymbols[0], TargetSym.Name);
+  LLVMOrcRetainSymbolStringPoolEntry(TargetSym.Name);
+
+  LLVMOrcDisposeCSymbolFlagsMap(Symbols);
+  LLVMOrcDisposeSymbols(RequestedSymbols);
+
+  LLVMOrcJITTargetAddress Addr = (LLVMOrcJITTargetAddress)(&TargetFn);
+
+  LLVMJITSymbolFlags Flags = {
+      LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0};
+  ASSERT_EQ(TargetSym.Flags.GenericFlags, Flags.GenericFlags);
+  ASSERT_EQ(TargetSym.Flags.TargetFlags, Flags.TargetFlags);
+
+  LLVMJITEvaluatedSymbol Sym = {Addr, Flags};
+
+  LLVMOrcLLJITRef J = (LLVMOrcLLJITRef)Ctx;
+
+  LLVMOrcSymbolStringPoolEntryRef OtherSymbol =
+      LLVMOrcLLJITMangleAndIntern(J, "other");
+  LLVMOrcSymbolStringPoolEntryRef DependencySymbol =
+      LLVMOrcLLJITMangleAndIntern(J, "dependency");
+
+  LLVMOrcRetainSymbolStringPoolEntry(OtherSymbol);
+  LLVMOrcRetainSymbolStringPoolEntry(DependencySymbol);
+  LLVMOrcCSymbolFlagsMapPair NewSymbols[] = {
+      {OtherSymbol, Flags},
+      {DependencySymbol, Flags},
+  };
+  LLVMOrcMaterializationResponsibilityDefineMaterializing(MR, NewSymbols, 2);
+
+  LLVMOrcRetainSymbolStringPoolEntry(OtherSymbol);
+  LLVMOrcMaterializationResponsibilityRef OtherMR = NULL;
+  {
+    LLVMErrorRef Err = LLVMOrcMaterializationResponsibilityDelegate(
+        MR, &OtherSymbol, 1, &OtherMR);
+    if (Err) {
+      char *ErrMsg = LLVMGetErrorMessage(Err);
+      fprintf(stderr, "Error: %s\n", ErrMsg);
+      LLVMDisposeErrorMessage(ErrMsg);
+      LLVMOrcMaterializationResponsibilityFailMaterialization(MR);
+      LLVMOrcDisposeMaterializationResponsibility(MR);
+      return;
+    }
+  }
+  assert(OtherMR);
+
+  LLVMJITCSymbolMapPair OtherPair = {OtherSymbol, Sym};
+  LLVMOrcMaterializationUnitRef OtherMU = LLVMOrcAbsoluteSymbols(&OtherPair, 1);
+  LLVMOrcMaterializationResponsibilityReplace(OtherMR, OtherMU);
+  // OtherSymbol is no longer owned by us
+
+  // FIXME: Implement async lookup
+  // A real test of the dependence tracking in the success case would require
+  // async lookups. You could:
+  // 1. Materialize foo, making foo depend on other.
+  // 2. In the caller, verify that the lookup callback for foo has not run (due
+  // to the dependence)
+  // 3. Materialize other by looking it up.
+  // 4. In the caller, verify that the lookup callback for foo has now run.
+
+  LLVMOrcRetainSymbolStringPoolEntry(TargetSym.Name);
+  LLVMOrcRetainSymbolStringPoolEntry(DependencySymbol);
+  LLVMOrcCDependenceMapPair Dependency = {JD, {&DependencySymbol, 1}};
+  LLVMOrcMaterializationResponsibilityAddDependencies(MR, TargetSym.Name,
+                                                      &Dependency, 1);
+
+  LLVMOrcRetainSymbolStringPoolEntry(DependencySymbol);
+  LLVMOrcMaterializationResponsibilityAddDependenciesForAll(MR, &Dependency, 1);
+
+  // See FIXME above
+  LLVMJITCSymbolMapPair Pair = {DependencySymbol, Sym};
+  LLVMOrcMaterializationResponsibilityNotifyResolved(MR, &Pair, 1);
+  // DependencySymbol no longer owned by us
+
+  Pair = {TargetSym.Name, Sym};
+  LLVMOrcMaterializationResponsibilityNotifyResolved(MR, &Pair, 1);
+
+  LLVMOrcMaterializationResponsibilityNotifyEmitted(MR);
+  LLVMOrcDisposeMaterializationResponsibility(MR);
+  return;
+}
+
+TEST_F(OrcCAPITestBase, MaterializationResponsibility) {
+  LLVMJITSymbolFlags Flags = {
+      LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0};
+  LLVMOrcCSymbolFlagsMapPair Sym = {LLVMOrcLLJITMangleAndIntern(Jit, "foo"),
+                                    Flags};
+
+  LLVMOrcMaterializationUnitRef MU = LLVMOrcCreateCustomMaterializationUnit(
+      "MU", (void *)Jit, &Sym, 1, NULL, &Materialize, NULL, &Destroy);
+  LLVMOrcJITDylibRef JD = LLVMOrcLLJITGetMainJITDylib(Jit);
+  LLVMOrcJITDylibDefine(JD, MU);
+
+  LLVMOrcJITTargetAddress Addr;
+  if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "foo")) {
+    FAIL() << "foo was not materialized " << toString(Err);
+  }
+  ASSERT_TRUE(!!Addr);
+  ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn);
+
+  if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "other")) {
+    FAIL() << "other was not materialized " << toString(Err);
+  }
+  ASSERT_TRUE(!!Addr);
+  ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn);
+
+  if (LLVMErrorRef Err = LLVMOrcLLJITLookup(Jit, &Addr, "dependency")) {
+    FAIL() << "dependency was not materialized " << toString(Err);
+  }
+  ASSERT_TRUE(!!Addr);
+  ASSERT_EQ(Addr, (LLVMOrcJITTargetAddress)&TargetFn);
+}


        


More information about the llvm-commits mailing list