[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