[llvm] 1cd8493 - [ORC] Expand the OrcV2 C API bindings.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 9 16:36:18 PDT 2020


Author: Lang Hames
Date: 2020-04-09T16:18:46-07:00
New Revision: 1cd8493e69ba37f68e6e9a03b8c6b24cb5f15fa4

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

LOG: [ORC] Expand the OrcV2 C API bindings.

Adds basic support for LLJITBuilder and DynamicLibrarySearchGenerator. This
allows C API clients to configure LLJIT to expose process symbols to JIT'd
code. An example of this is added in
llvm/examples/OrcV2CBindingsReflectProcessSymbols.

Added: 
    llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/CMakeLists.txt
    llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c
    llvm/examples/OrcV2Examples/OrcV2CBindingsReflectProcessSymbols/CMakeLists.txt
    llvm/examples/OrcV2Examples/OrcV2CBindingsReflectProcessSymbols/OrcV2CBindingsReflectProcessSymbols.c

Modified: 
    llvm/examples/OrcV2Examples/CMakeLists.txt
    llvm/include/llvm-c/Orc.h
    llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
    llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp

Removed: 
    llvm/examples/OrcV2Examples/BasicOrcV2CBindings/BasicOrcV2CBindings.c
    llvm/examples/OrcV2Examples/BasicOrcV2CBindings/CMakeLists.txt


################################################################################
diff  --git a/llvm/examples/OrcV2Examples/CMakeLists.txt b/llvm/examples/OrcV2Examples/CMakeLists.txt
index b6d8d705f216..6bcef262ff80 100644
--- a/llvm/examples/OrcV2Examples/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/CMakeLists.txt
@@ -1,7 +1,8 @@
-add_subdirectory(BasicOrcV2CBindings)
 add_subdirectory(LLJITDumpObjects)
 add_subdirectory(LLJITWithCustomObjectLinkingLayer)
 add_subdirectory(LLJITWithGDBRegistrationListener)
 add_subdirectory(LLJITWithLazyReexports)
 add_subdirectory(LLJITWithObjectCache)
 add_subdirectory(LLJITWithObjectLinkingLayerPlugin)
+add_subdirectory(OrcV2CBindingsBasicUsage)
+add_subdirectory(OrcV2CBindingsReflectProcessSymbols)

diff  --git a/llvm/examples/OrcV2Examples/BasicOrcV2CBindings/CMakeLists.txt b/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/CMakeLists.txt
similarity index 64%
rename from llvm/examples/OrcV2Examples/BasicOrcV2CBindings/CMakeLists.txt
rename to llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/CMakeLists.txt
index 4d36d80922ff..0f18d6c24912 100644
--- a/llvm/examples/OrcV2Examples/BasicOrcV2CBindings/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/CMakeLists.txt
@@ -10,6 +10,6 @@ set(LLVM_LINK_COMPONENTS
   nativecodegen
   )
 
-add_llvm_example(BasicOrcV2CBindings
-  BasicOrcV2CBindings.c
+add_llvm_example(OrcV2CBindingsBasicUsage
+  OrcV2CBindingsBasicUsage.c
   )

diff  --git a/llvm/examples/OrcV2Examples/BasicOrcV2CBindings/BasicOrcV2CBindings.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c
similarity index 98%
rename from llvm/examples/OrcV2Examples/BasicOrcV2CBindings/BasicOrcV2CBindings.c
rename to llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c
index 0fcf453db5f8..373ff58c4d8e 100644
--- a/llvm/examples/OrcV2Examples/BasicOrcV2CBindings/BasicOrcV2CBindings.c
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/OrcV2CBindingsBasicUsage.c
@@ -83,7 +83,7 @@ int main(int argc, char *argv[]) {
   LLVMOrcLLJITRef J;
   {
     LLVMErrorRef Err;
-    if ((Err = LLVMOrcCreateDefaultLLJIT(&J))) {
+    if ((Err = LLVMOrcCreateLLJIT(&J, 0))) {
       MainResult = handleError(Err);
       goto llvm_shutdown;
     }

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

diff  --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsReflectProcessSymbols/OrcV2CBindingsReflectProcessSymbols.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsReflectProcessSymbols/OrcV2CBindingsReflectProcessSymbols.c
new file mode 100644
index 000000000000..7d70e13da4b4
--- /dev/null
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsReflectProcessSymbols/OrcV2CBindingsReflectProcessSymbols.c
@@ -0,0 +1,219 @@
+//===-------- 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/Initialization.h"
+#include "llvm-c/Orc.h"
+#include "llvm-c/Support.h"
+#include "llvm-c/Target.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+int handleError(LLVMErrorRef Err) {
+  char *ErrMsg = LLVMGetErrorMessage(Err);
+  fprintf(stderr, "Error: %s\n", ErrMsg);
+  LLVMDisposeErrorMessage(ErrMsg);
+  return 1;
+}
+
+int32_t add(int32_t X, int32_t Y) { return X + Y; }
+
+int32_t mul(int32_t X, int32_t Y) { return X * Y; }
+
+int whitelistedSymbols(LLVMOrcSymbolStringPoolEntryRef Sym, void *Ctx) {
+  assert(Ctx && "Cannot call whitelistedSymbols with a null context");
+
+  LLVMOrcSymbolStringPoolEntryRef *Whitelist =
+      (LLVMOrcSymbolStringPoolEntryRef *)Ctx;
+
+  // If Sym appears in the whitelist then return true.
+  LLVMOrcSymbolStringPoolEntryRef *P = Whitelist;
+  while (*P) {
+    if (Sym == *P)
+      return 1;
+    ++P;
+  }
+
+  // otherwise return false.
+  return 0;
+}
+
+LLVMOrcThreadSafeModuleRef createDemoModule() {
+  // Create a new ThreadSafeContext and underlying LLVMContext.
+  LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();
+
+  // Get a reference to the underlying LLVMContext.
+  LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx);
+
+  // Create a new LLVM module.
+  LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx);
+
+  // Add a "sum" function":
+  //  - Create the function type and function instance.
+  LLVMTypeRef I32BinOpParamTypes[] = {LLVMInt32Type(), LLVMInt32Type()};
+  LLVMTypeRef I32BinOpFunctionType =
+      LLVMFunctionType(LLVMInt32Type(), I32BinOpParamTypes, 2, 0);
+  LLVMValueRef AddI32Function = LLVMAddFunction(M, "add", I32BinOpFunctionType);
+  LLVMValueRef MulI32Function = LLVMAddFunction(M, "mul", I32BinOpFunctionType);
+
+  LLVMTypeRef MulAddParamTypes[] = {LLVMInt32Type(), LLVMInt32Type(),
+                                    LLVMInt32Type()};
+  LLVMTypeRef MulAddFunctionType =
+      LLVMFunctionType(LLVMInt32Type(), MulAddParamTypes, 3, 0);
+  LLVMValueRef MulAddFunction =
+      LLVMAddFunction(M, "mul_add", MulAddFunctionType);
+
+  //  - Add a basic block to the function.
+  LLVMBasicBlockRef EntryBB = LLVMAppendBasicBlock(MulAddFunction, "entry");
+
+  //  - Add an IR builder and point it at the end of the basic block.
+  LLVMBuilderRef Builder = LLVMCreateBuilder();
+  LLVMPositionBuilderAtEnd(Builder, EntryBB);
+
+  //  - Get the three function arguments and use them co construct calls to
+  //    'mul' and 'add':
+  //
+  //    i32 mul_add(i32 %0, i32 %1, i32 %2) {
+  //      %t = call i32 @mul(i32 %0, i32 %1)
+  //      %r = call i32 @add(i32 %t, i32 %2)
+  //      ret i32 %r
+  //    }
+  LLVMValueRef SumArg0 = LLVMGetParam(MulAddFunction, 0);
+  LLVMValueRef SumArg1 = LLVMGetParam(MulAddFunction, 1);
+  LLVMValueRef SumArg2 = LLVMGetParam(MulAddFunction, 2);
+
+  LLVMValueRef MulArgs[] = {SumArg0, SumArg1};
+  LLVMValueRef MulResult = LLVMBuildCall2(Builder, I32BinOpFunctionType,
+                                          MulI32Function, MulArgs, 2, "t");
+
+  LLVMValueRef AddArgs[] = {MulResult, SumArg2};
+  LLVMValueRef AddResult = LLVMBuildCall2(Builder, I32BinOpFunctionType,
+                                          AddI32Function, AddArgs, 2, "r");
+
+  //  - Build the return instruction.
+  LLVMBuildRet(Builder, AddResult);
+
+  // Our demo module is now complete. Wrap it and our ThreadSafeContext in a
+  // ThreadSafeModule.
+  LLVMOrcThreadSafeModuleRef TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);
+
+  // Dispose of our local ThreadSafeContext value. The underlying LLVMContext
+  // will be kept alive by our ThreadSafeModule, TSM.
+  LLVMOrcDisposeThreadSafeContext(TSCtx);
+
+  // Return the result.
+  return TSM;
+}
+
+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();
+
+  // Create the JIT instance.
+  LLVMOrcLLJITRef J;
+  {
+    LLVMErrorRef Err;
+    if ((Err = LLVMOrcCreateLLJIT(&J, 0))) {
+      MainResult = handleError(Err);
+      goto llvm_shutdown;
+    }
+  }
+
+  // Build a filter to allow JIT'd code to only access whitelisted symbols.
+  // This filter is optional: If a null value is suppled for the Filter
+  // argument to LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess then
+  // all process symbols will be reflected.
+  LLVMOrcSymbolStringPoolEntryRef Whitelist[] = {
+      LLVMOrcLLJITMangleAndIntern(J, "mul"),
+      LLVMOrcLLJITMangleAndIntern(J, "add"), 0};
+
+  {
+    LLVMOrcJITDylibDefinitionGeneratorRef ProcessSymbolsGenerator = 0;
+    LLVMErrorRef Err;
+    if ((Err = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(
+             &ProcessSymbolsGenerator, LLVMOrcLLJITGetGlobalPrefix(J),
+             whitelistedSymbols, Whitelist))) {
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+
+    LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(J),
+                                ProcessSymbolsGenerator);
+  }
+
+  // Create our demo module.
+  LLVMOrcThreadSafeModuleRef TSM = createDemoModule();
+
+  // Add our demo module to the JIT.
+  {
+    LLVMErrorRef Err;
+    if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, TSM))) {
+      // If adding the ThreadSafeModule fails then we need to clean it up
+      // ourselves. If adding it succeeds the JIT will manage the memory.
+      LLVMOrcDisposeThreadSafeModule(TSM);
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+  }
+
+  // Look up the address of our demo entry point.
+  LLVMOrcJITTargetAddress MulAddAddr;
+  {
+    LLVMErrorRef Err;
+    if ((Err = LLVMOrcLLJITLookup(J, &MulAddAddr, "mul_add"))) {
+      MainResult = handleError(Err);
+      goto jit_cleanup;
+    }
+  }
+
+  // If we made it here then everything succeeded. Execute our JIT'd code.
+  int32_t (*MulAdd)(int32_t, int32_t, int32_t) =
+      (int32_t(*)(int32_t, int32_t, int32_t))MulAddAddr;
+  int32_t Result = MulAdd(3, 4, 5);
+
+  // Print the result.
+  printf("3 * 4 + 5 = %i\n", Result);
+
+jit_cleanup:
+  // Release all symbol string pool entries that we have allocated. In this
+  // example that's just our whitelist entries.
+  {
+    LLVMOrcSymbolStringPoolEntryRef *P = Whitelist;
+    while (*P)
+      LLVMOrcReleaseSymbolStringPoolEntry(*P++);
+  }
+
+  // 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 935e5d123f68..35586a795ac8 100644
--- a/llvm/include/llvm-c/Orc.h
+++ b/llvm/include/llvm-c/Orc.h
@@ -8,7 +8,10 @@
 |*===----------------------------------------------------------------------===*|
 |*                                                                            *|
 |* This header declares the C interface to libLLVMOrcJIT.a, which implements  *|
-|* JIT compilation of LLVM IR.                                                *|
+|* JIT compilation of LLVM IR. Minimal documentation of C API specific issues *|
+|* (especially memory ownership rules) is provided. Core Orc concepts are     *|
+|* documented in llvm/docs/ORCv2.rst and APIs are documented in the C++       *|
+|* headers                                                                    *|
 |*                                                                            *|
 |* Many exotic languages can interoperate with C code but have a harder time  *|
 |* with C++ due to name mangling. So in addition to C, this interface enables *|
@@ -29,10 +32,123 @@
 
 LLVM_C_EXTERN_C_BEGIN
 
+/**
+ * Represents an address in the target process.
+ */
+typedef uint64_t LLVMOrcJITTargetAddress;
+
+/**
+ * A reference to an orc::ExecutionSession instance.
+ */
+typedef struct LLVMOrcOpaqueExecutionSession *LLVMOrcExecutionSessionRef;
+
+/**
+ * A reference to an orc::SymbolStringPool table entry.
+ */
+typedef struct LLVMOrcQuaqueSymbolStringPoolEntryPtr
+    *LLVMOrcSymbolStringPoolEntryRef;
+
+/**
+ * A reference to an orc::JITDylib instance.
+ */
+typedef struct LLVMOrcOpaqueJITDylib *LLVMOrcJITDylibRef;
+
+/**
+ * A reference to an orc::JITDylib::DefinitionGenerator.
+ */
+typedef struct LLVMOrcOpaqueJITDylibDefinitionGenerator
+    *LLVMOrcJITDylibDefinitionGeneratorRef;
+
+/**
+ * Predicate function for SymbolStringPoolEntries.
+ */
+typedef int (*LLVMOrcSymbolPredicate)(LLVMOrcSymbolStringPoolEntryRef Sym,
+                                      void *Ctx);
+
+/**
+ * A reference to an orc::ThreadSafeContext instance.
+ */
 typedef struct LLVMOrcOpaqueThreadSafeContext *LLVMOrcThreadSafeContextRef;
+
+/**
+ * A reference to an orc::ThreadSafeModule instance.
+ */
 typedef struct LLVMOrcOpaqueThreadSafeModule *LLVMOrcThreadSafeModuleRef;
+
+/**
+ * A reference to an orc::JITTargetMachineBuilder instance.
+ */
+typedef struct LLVMOrcOpaqueJITTargetMachineBuilder
+    *LLVMOrcJITTargetMachineBuilderRef;
+
+/**
+ * A reference to an orc::LLJITBuilder instance.
+ */
+typedef struct LLVMOrcOpaqueLLJITBuilder *LLVMOrcLLJITBuilderRef;
+
+/**
+ * A reference to an orc::LLJIT instance.
+ */
 typedef struct LLVMOrcOpaqueLLJIT *LLVMOrcLLJITRef;
-typedef uint64_t LLVMOrcJITTargetAddress;
+
+/**
+ * Intern a string in the ExecutionSession's SymbolStringPool and return a
+ * reference to it. This increments the ref-count of the pool entry, and the
+ * returned value should be released once the client is done with it by
+ * calling LLVMOrReleaseSymbolStringPoolEntry.
+ *
+ * Since strings are uniqued within the SymbolStringPool
+ * LLVMOrcSymbolStringPoolEntryRefs can be compared by value to test string
+ * equality.
+ *
+ * Note that this function does not perform linker-mangling on the string.
+ */
+LLVMOrcSymbolStringPoolEntryRef
+LLVMOrcExecutionSessionIntern(LLVMOrcExecutionSessionRef ES, const char *Name);
+
+/**
+ * Reduces the ref-count for of a SymbolStringPool entry.
+ */
+void LLVMOrcReleaseSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S);
+
+/**
+ * Dispose of a JITDylib::DefinitionGenerator. This should only be called if
+ * ownership has not been passed to a JITDylib (e.g. because some error
+ * prevented the client from calling LLVMOrcJITDylibAddGenerator).
+ */
+void LLVMOrcDisposeJITDylibDefinitionGenerator(
+    LLVMOrcJITDylibDefinitionGeneratorRef DG);
+
+/**
+ * Add a JITDylib::DefinitionGenerator to the given JITDylib.
+ *
+ * The JITDylib will take ownership of the given generator: The client is no
+ * longer responsible for managing its memory.
+ */
+void LLVMOrcJITDylibAddGenerator(LLVMOrcJITDylibRef JD,
+                                 LLVMOrcJITDylibDefinitionGeneratorRef DG);
+
+/**
+ * Get a DynamicLibrarySearchGenerator that will reflect process symbols into
+ * the JITDylib. On success the resulting generator is owned by the client.
+ * Ownership is typically transferred by adding the instance to a JITDylib
+ * using LLVMOrcJITDylibAddGenerator,
+ *
+ * The GlobalPrefix argument specifies the character that appears on the front
+ * of linker-mangled symbols for the target platform (e.g. '_' on MachO).
+ * If non-null, this character will be stripped from the start of all symbol
+ * strings before passing the remaining substring to dlsym.
+ *
+ * The optional Filter and Ctx arguments can be used to supply a symbol name
+ * filter: Only symbols for which the filter returns true will be visible to
+ * JIT'd code. If the Filter argument is null then all process symbols will
+ * be visible to JIT'd code. Note that the symbol name passed to the Filter
+ * function is the full mangled symbol: The client is responsible for stripping
+ * the global prefix if present.
+ */
+LLVMErrorRef LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(
+    LLVMOrcJITDylibDefinitionGeneratorRef *Result, char GlobalPrefx,
+    LLVMOrcSymbolPredicate Filter, void *FilterCtx);
 
 /**
  * Create a ThreadSafeContext containing a new LLVMContext.
@@ -70,26 +186,105 @@ LLVMOrcCreateNewThreadSafeModule(LLVMModuleRef M,
                                  LLVMOrcThreadSafeContextRef TSCtx);
 
 /**
- * Dispose of a ThreadSafeModule.
+ * Dispose of a ThreadSafeModule. This should only be called if ownership has
+ * not been passed to LLJIT (e.g. because some error prevented the client from
+ * adding this to the JIT).
  */
 void LLVMOrcDisposeThreadSafeModule(LLVMOrcThreadSafeModuleRef TSM);
 
 /**
- * Create an LLJIT instance using all default values.
+ * Create a JITTargetMachineBuilder by detecting the host.
  *
- * The LLJIT instance is uniquely owned by the client and automatically manages
- * the memory of all JIT'd code and all modules that are transferred to it
- * (e.g. via LLVMOrcLLJITAddLLVMIRModule). Disposing of the LLJIT instance will
- * free all memory managed by the JIT, including JIT'd code and not-yet
- * compiled modules.
+ * On success the client owns the resulting JITTargetMachineBuilder. It must be
+ * passed to a consuming operation (e.g. LLVMOrcCreateLLJITBuilder) or disposed
+ * of by calling LLVMOrcDisposeJITTargetMachineBuilder.
  */
-LLVMErrorRef LLVMOrcCreateDefaultLLJIT(LLVMOrcLLJITRef *Result);
+LLVMErrorRef LLVMOrcJITTargetMachineBuilderDetectHost(
+    LLVMOrcJITTargetMachineBuilderRef *Result);
+
+/**
+ * Dispose of a JITTargetMachineBuilder.
+ */
+void LLVMOrcDisposeJITTargetMachineBuilder(
+    LLVMOrcJITTargetMachineBuilderRef JTMB);
+
+/**
+ * Create an LLJITTargetMachineBuilder.
+ *
+ * The client owns the resulting LLJITBuilder and should dispose of it using
+ * LLVMOrcDisposeLLJITBuilder once they are done with it.
+ */
+LLVMOrcLLJITBuilderRef LLVMOrcCreateLLJITBuilder(void);
+
+/**
+ * Dispose of an LLVMOrcLLJITBuilderRef. This should only be called if ownership
+ * has not been passed to LLVMOrcCreateLLJIT (e.g. because some error prevented
+ * that function from being called).
+ */
+void LLVMOrcDisposeLLJITBuilder(LLVMOrcLLJITBuilderRef Builder);
+
+/**
+ * Set the JITTargetMachineBuilder to be used when constructing the LLJIT
+ * instance. Calling this function is optional: if it is not called then the
+ * LLJITBuilder will use JITTargeTMachineBuilder::detectHost to construct a
+ * JITTargetMachineBuilder.
+ */
+void LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(
+    LLVMOrcLLJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB);
+
+/**
+ * Create an LLJIT instance from an LLJITBuilder.
+ *
+ * This operation takes ownership of the Builder argument: clients should not
+ * dispose of the builder after calling this function (even if the function
+ * returns an error). If a null Builder argument is provided then a
+ * default-constructed LLJITBuilder will be used.
+ *
+ * On success the resulting LLJIT instance is uniquely owned by the client and
+ * automatically manages the memory of all JIT'd code and all modules that are
+ * transferred to it (e.g. via LLVMOrcLLJITAddLLVMIRModule). Disposing of the
+ * LLJIT instance will free all memory managed by the JIT, including JIT'd code
+ * and not-yet compiled modules.
+ */
+LLVMErrorRef LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result,
+                                LLVMOrcLLJITBuilderRef Builder);
 
 /**
  * Dispose of an LLJIT instance.
  */
 LLVMErrorRef LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J);
 
+/**
+ * Get a reference to the ExecutionSession for this LLJIT instance.
+ *
+ * The ExecutionSession is owned by the LLJIT instance. The client is not
+ * responsible for managing its memory.
+ */
+LLVMOrcExecutionSessionRef LLVMOrcLLJITGetExecutionSession(LLVMOrcLLJITRef J);
+
+/**
+ * Return a reference to the Main JITDylib.
+ *
+ * The JITDylib is owned by the LLJIT instance. The client is not responsible
+ * for managing its memory.
+ */
+LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J);
+
+/**
+ * Returns the global prefix character according to the LLJIT's DataLayout.
+ */
+char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J);
+
+/**
+ * Mangles the given string according to the LLJIT instance's DataLayout, then
+ * interns the result in the SymbolStringPool and returns a reference to the
+ * pool entry. Clients should call LLVMOrcReleaseSymbolStringPoolEntry to
+ * decrement the ref-count on the pool entry once they are finished with this
+ * value.
+ */
+LLVMOrcSymbolStringPoolEntryRef
+LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName);
+
 /**
  * Add an IR module to the main JITDylib of the given LLJIT instance. This
  * operation takes ownership of the TSM argument which should not be disposed

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h b/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
index a4207c2d2add..c9fadd727e88 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
@@ -48,6 +48,7 @@ class SymbolStringPool {
 
 /// Pointer to a pooled string representing a symbol name.
 class SymbolStringPtr {
+  friend class OrcV2CAPIHelper;
   friend class SymbolStringPool;
   friend struct DenseMapInfo<SymbolStringPtr>;
 
@@ -106,7 +107,8 @@ class SymbolStringPtr {
   }
 
 private:
-  using PoolEntryPtr = SymbolStringPool::PoolMapEntry *;
+  using PoolEntry = SymbolStringPool::PoolMapEntry;
+  using PoolEntryPtr = PoolEntry *;
 
   SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
       : S(S) {

diff  --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
index d623e17af264..62ae306236c5 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
@@ -15,12 +15,94 @@
 using namespace llvm;
 using namespace llvm::orc;
 
+namespace llvm {
+namespace orc {
+
+class OrcV2CAPIHelper {
+public:
+  using PoolEntry = SymbolStringPtr::PoolEntry;
+  using PoolEntryPtr = SymbolStringPtr::PoolEntryPtr;
+
+  static PoolEntryPtr releaseSymbolStringPtr(SymbolStringPtr S) {
+    PoolEntryPtr Result = nullptr;
+    std::swap(Result, S.S);
+    return Result;
+  }
+
+  static PoolEntryPtr getRawPoolEntryPtr(const SymbolStringPtr &S) {
+    return S.S;
+  }
+
+  static void releasePoolEntry(PoolEntryPtr P) {
+    SymbolStringPtr S;
+    S.S = P;
+  }
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionSession, LLVMOrcExecutionSessionRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcV2CAPIHelper::PoolEntry,
+                                   LLVMOrcSymbolStringPoolEntryRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITDylib, LLVMOrcJITDylibRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITDylib::DefinitionGenerator,
+                                   LLVMOrcJITDylibDefinitionGeneratorRef)
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeContext,
                                    LLVMOrcThreadSafeContextRef)
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule, LLVMOrcThreadSafeModuleRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITTargetMachineBuilder,
+                                   LLVMOrcJITTargetMachineBuilderRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJITBuilder, LLVMOrcLLJITBuilderRef)
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJIT, LLVMOrcLLJITRef)
 
-LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext() {
+LLVMOrcSymbolStringPoolEntryRef
+LLVMOrcExecutionSessionIntern(LLVMOrcExecutionSessionRef ES, const char *Name) {
+  return wrap(
+      OrcV2CAPIHelper::releaseSymbolStringPtr(unwrap(ES)->intern(Name)));
+}
+
+void LLVMOrcReleaseSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S) {
+  OrcV2CAPIHelper::releasePoolEntry(unwrap(S));
+}
+
+void LLVMOrcDisposeJITDylibDefinitionGenerator(
+    LLVMOrcJITDylibDefinitionGeneratorRef DG) {
+  delete unwrap(DG);
+}
+
+void LLVMOrcJITDylibAddGenerator(LLVMOrcJITDylibRef JD,
+                                 LLVMOrcJITDylibDefinitionGeneratorRef DG) {
+  unwrap(JD)->addGenerator(
+      std::unique_ptr<JITDylib::DefinitionGenerator>(unwrap(DG)));
+}
+
+LLVMErrorRef LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(
+    LLVMOrcJITDylibDefinitionGeneratorRef *Result, char GlobalPrefix,
+    LLVMOrcSymbolPredicate Filter, void *FilterCtx) {
+  assert(Result && "Result can not be null");
+  assert((Filter || !FilterCtx) &&
+         "if Filter is null then FilterCtx must also be null");
+
+  DynamicLibrarySearchGenerator::SymbolPredicate Pred;
+  if (Filter)
+    Pred = [=](const SymbolStringPtr &Name) -> bool {
+      return Filter(wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(Name)), FilterCtx);
+    };
+
+  auto ProcessSymsGenerator =
+      DynamicLibrarySearchGenerator::GetForCurrentProcess(GlobalPrefix, Pred);
+
+  if (!ProcessSymsGenerator) {
+    *Result = 0;
+    return wrap(ProcessSymsGenerator.takeError());
+  }
+
+  *Result = wrap(ProcessSymsGenerator->release());
+  return LLVMErrorSuccess;
+}
+
+LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext(void) {
   return wrap(new ThreadSafeContext(std::make_unique<LLVMContext>()));
 }
 
@@ -44,8 +126,47 @@ void LLVMOrcDisposeThreadSafeModule(LLVMOrcThreadSafeModuleRef TSM) {
   delete unwrap(TSM);
 }
 
-LLVMErrorRef LLVMOrcCreateDefaultLLJIT(LLVMOrcLLJITRef *Result) {
-  auto J = LLJITBuilder().create();
+LLVMErrorRef LLVMOrcJITTargetMachineBuilderDetectHost(
+    LLVMOrcJITTargetMachineBuilderRef *Result) {
+  assert(Result && "Result can not be null");
+
+  auto JTMB = JITTargetMachineBuilder::detectHost();
+  if (!JTMB) {
+    Result = 0;
+    return wrap(JTMB.takeError());
+  }
+
+  *Result = wrap(new JITTargetMachineBuilder(std::move(*JTMB)));
+  return LLVMErrorSuccess;
+}
+
+void LLVMOrcDisposeJITTargetMachineBuilder(
+    LLVMOrcJITTargetMachineBuilderRef JTMB) {
+  delete unwrap(JTMB);
+}
+
+LLVMOrcLLJITBuilderRef LLVMOrcCreateLLJITBuilder(void) {
+  return wrap(new LLJITBuilder());
+}
+
+void LLVMOrcDisposeLLJITBuilder(LLVMOrcLLJITBuilderRef Builder) {
+  delete unwrap(Builder);
+}
+
+void LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(
+    LLVMOrcLLJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB) {
+  unwrap(Builder)->setJITTargetMachineBuilder(*unwrap(JTMB));
+}
+
+LLVMErrorRef LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result,
+                                LLVMOrcLLJITBuilderRef Builder) {
+  assert(Result && "Result can not be null");
+
+  if (!Builder)
+    Builder = LLVMOrcCreateLLJITBuilder();
+
+  auto J = unwrap(Builder)->create();
+  LLVMOrcDisposeLLJITBuilder(Builder);
 
   if (!J) {
     Result = 0;
@@ -61,6 +182,24 @@ LLVMErrorRef LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J) {
   return LLVMErrorSuccess;
 }
 
+LLVMOrcExecutionSessionRef LLVMOrcLLJITGetExecutionSession(LLVMOrcLLJITRef J) {
+  return wrap(&unwrap(J)->getExecutionSession());
+}
+
+LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J) {
+  return wrap(&unwrap(J)->getMainJITDylib());
+}
+
+char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J) {
+  return unwrap(J)->getDataLayout().getGlobalPrefix();
+}
+
+LLVMOrcSymbolStringPoolEntryRef
+LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName) {
+  return wrap(OrcV2CAPIHelper::releaseSymbolStringPtr(
+      unwrap(J)->mangleAndIntern(UnmangledName)));
+}
+
 LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J,
                                          LLVMOrcThreadSafeModuleRef TSM) {
   return wrap(unwrap(J)->addIRModule(std::move(*unwrap(TSM))));
@@ -69,6 +208,8 @@ LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J,
 LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J,
                                 LLVMOrcJITTargetAddress *Result,
                                 const char *Name) {
+  assert(Result && "Result can not be null");
+
   auto Sym = unwrap(J)->lookup(Name);
   if (!Sym) {
     *Result = 0;


        


More information about the llvm-commits mailing list