[llvm] 0d5f15f - [ORC] Add C API support for adding object files to an LLJIT instance.
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 9 16:36:20 PDT 2020
Author: Lang Hames
Date: 2020-04-09T16:18:46-07:00
New Revision: 0d5f15f7000928273aea305d6cff7ac7c1aa352f
URL: https://github.com/llvm/llvm-project/commit/0d5f15f7000928273aea305d6cff7ac7c1aa352f
DIFF: https://github.com/llvm/llvm-project/commit/0d5f15f7000928273aea305d6cff7ac7c1aa352f.diff
LOG: [ORC] Add C API support for adding object files to an LLJIT instance.
Added:
llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/CMakeLists.txt
llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/OrcV2CBindingsAddObjectFile.c
Modified:
llvm/examples/OrcV2Examples/CMakeLists.txt
llvm/include/llvm-c/Orc.h
llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
Removed:
################################################################################
diff --git a/llvm/examples/OrcV2Examples/CMakeLists.txt b/llvm/examples/OrcV2Examples/CMakeLists.txt
index 6bcef262ff80..761da008f5d6 100644
--- a/llvm/examples/OrcV2Examples/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/CMakeLists.txt
@@ -4,5 +4,6 @@ add_subdirectory(LLJITWithGDBRegistrationListener)
add_subdirectory(LLJITWithLazyReexports)
add_subdirectory(LLJITWithObjectCache)
add_subdirectory(LLJITWithObjectLinkingLayerPlugin)
+add_subdirectory(OrcV2CBindingsAddObjectFile)
add_subdirectory(OrcV2CBindingsBasicUsage)
add_subdirectory(OrcV2CBindingsReflectProcessSymbols)
diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/CMakeLists.txt b/llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/CMakeLists.txt
new file mode 100644
index 000000000000..cc50112f326e
--- /dev/null
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS
+ Core
+ ExecutionEngine
+ IRReader
+ JITLink
+ MC
+ OrcJIT
+ Support
+ Target
+ nativecodegen
+ )
+
+add_llvm_example(OrcV2CBindingsAddObjectFile
+ OrcV2CBindingsAddObjectFile.c
+ )
diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/OrcV2CBindingsAddObjectFile.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/OrcV2CBindingsAddObjectFile.c
new file mode 100644
index 000000000000..522eeb50f66c
--- /dev/null
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/OrcV2CBindingsAddObjectFile.c
@@ -0,0 +1,157 @@
+//===-------- 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 "llvm-c/TargetMachine.h"
+
+#include <stdio.h>
+
+int handleError(LLVMErrorRef Err) {
+ char *ErrMsg = LLVMGetErrorMessage(Err);
+ fprintf(stderr, "Error: %s\n", ErrMsg);
+ LLVMDisposeErrorMessage(ErrMsg);
+ return 1;
+}
+
+LLVMModuleRef createDemoModule(LLVMContextRef Ctx) {
+ // Create a new LLVM module.
+ LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx);
+
+ // Add a "sum" function":
+ // - Create the function type and function instance.
+ LLVMTypeRef ParamTypes[] = {LLVMInt32Type(), LLVMInt32Type()};
+ LLVMTypeRef SumFunctionType =
+ LLVMFunctionType(LLVMInt32Type(), ParamTypes, 2, 0);
+ LLVMValueRef SumFunction = LLVMAddFunction(M, "sum", SumFunctionType);
+
+ // - Add a basic block to the function.
+ LLVMBasicBlockRef EntryBB = LLVMAppendBasicBlock(SumFunction, "entry");
+
+ // - Add an IR builder and point it at the end of the basic block.
+ LLVMBuilderRef Builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(Builder, EntryBB);
+
+ // - Get the two function arguments and use them co construct an "add"
+ // instruction.
+ LLVMValueRef SumArg0 = LLVMGetParam(SumFunction, 0);
+ LLVMValueRef SumArg1 = LLVMGetParam(SumFunction, 1);
+ LLVMValueRef Result = LLVMBuildAdd(Builder, SumArg0, SumArg1, "result");
+
+ // - Build the return instruction.
+ LLVMBuildRet(Builder, Result);
+
+ return M;
+}
+
+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;
+ }
+ }
+
+ // Create our demo object file.
+ LLVMMemoryBufferRef ObjectFileBuffer;
+ {
+ // Create a module.
+ LLVMContextRef Ctx = LLVMContextCreate();
+ LLVMModuleRef M = createDemoModule(Ctx);
+
+ // Get the Target.
+ const char *Triple = LLVMOrcLLJITGetTripleString(J);
+ LLVMTargetRef Target = 0;
+ char *ErrorMsg = 0;
+ if (LLVMGetTargetFromTriple(Triple, &Target, &ErrorMsg)) {
+ fprintf(stderr, "Error getting target for %s: %s\n", Triple, ErrorMsg);
+ LLVMDisposeModule(M);
+ LLVMContextDispose(Ctx);
+ goto jit_cleanup;
+ }
+
+ // Construct a TargetMachine.
+ LLVMTargetMachineRef TM =
+ LLVMCreateTargetMachine(Target, Triple, "", "", LLVMCodeGenLevelNone,
+ LLVMRelocDefault, LLVMCodeModelDefault);
+
+ // Run CodeGen to produce the buffer.
+ if (LLVMTargetMachineEmitToMemoryBuffer(TM, M, LLVMObjectFile, &ErrorMsg,
+ &ObjectFileBuffer)) {
+ fprintf(stderr, "Error emitting object: %s\n", ErrorMsg);
+ LLVMDisposeTargetMachine(TM);
+ LLVMDisposeModule(M);
+ LLVMContextDispose(Ctx);
+ goto jit_cleanup;
+ }
+ }
+
+ // Add our object file buffer to the JIT.
+ {
+ LLVMErrorRef Err;
+ if ((Err = LLVMOrcLLJITAddObjectFile(J, ObjectFileBuffer))) {
+ MainResult = handleError(Err);
+ goto jit_cleanup;
+ }
+ }
+
+ // Look up the address of our demo entry point.
+ LLVMOrcJITTargetAddress SumAddr;
+ {
+ LLVMErrorRef Err;
+ if ((Err = LLVMOrcLLJITLookup(J, &SumAddr, "sum"))) {
+ MainResult = handleError(Err);
+ goto jit_cleanup;
+ }
+ }
+
+ // If we made it here then everything succeeded. Execute our JIT'd code.
+ int32_t (*Sum)(int32_t, int32_t) = (int32_t(*)(int32_t, int32_t))SumAddr;
+ int32_t Result = Sum(1, 2);
+
+ // Print the result.
+ printf("1 + 2 = %i\n", Result);
+
+jit_cleanup:
+ // Destroy our JIT instance. This will clean up any memory that the JIT has
+ // taken ownership of. This operation is non-trivial (e.g. it may need to
+ // JIT static destructors) and may also fail. In that case we want to render
+ // the error to stderr, but not overwrite any existing return value.
+ {
+ LLVMErrorRef Err;
+ if ((Err = LLVMOrcDisposeLLJIT(J))) {
+ int NewFailureResult = handleError(Err);
+ if (MainResult == 0)
+ MainResult = NewFailureResult;
+ }
+ }
+
+llvm_shutdown:
+ // Shut down LLVM.
+ LLVMShutdown();
+
+ return MainResult;
+}
diff --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h
index 35586a795ac8..60ff406150ba 100644
--- a/llvm/include/llvm-c/Orc.h
+++ b/llvm/include/llvm-c/Orc.h
@@ -270,6 +270,12 @@ LLVMOrcExecutionSessionRef LLVMOrcLLJITGetExecutionSession(LLVMOrcLLJITRef J);
*/
LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J);
+/**
+ * Return the target triple for this LLJIT instance. This string is owned by
+ * the LLJIT instance and should not be freed by the client.
+ */
+const char *LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J);
+
/**
* Returns the global prefix character according to the LLJIT's DataLayout.
*/
@@ -285,10 +291,19 @@ char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J);
LLVMOrcSymbolStringPoolEntryRef
LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName);
+/**
+ * Add a buffer representing an object file to the given LLJIT instance. This
+ * operation transfers ownership of the buffer to the LLJIT instance. The
+ * buffer should not be disposed of or referenced once this function returns.
+ */
+LLVMErrorRef LLVMOrcLLJITAddObjectFile(LLVMOrcLLJITRef J,
+ LLVMMemoryBufferRef ObjBuffer);
+
/**
* 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
- * of or referenced once this function returns.
+ * operation transfers ownership of the TSM argument to the LLJIT instance.
+ * The TSM argument should not be 3disposed of or referenced once this
+ * function returns.
*/
LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J,
LLVMOrcThreadSafeModuleRef TSM);
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
index 62ae306236c5..5e82a4a8613a 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
@@ -190,6 +190,10 @@ LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J) {
return wrap(&unwrap(J)->getMainJITDylib());
}
+const char *LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J) {
+ return unwrap(J)->getTargetTriple().str().c_str();
+}
+
char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J) {
return unwrap(J)->getDataLayout().getGlobalPrefix();
}
@@ -200,6 +204,12 @@ LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName) {
unwrap(J)->mangleAndIntern(UnmangledName)));
}
+LLVMErrorRef LLVMOrcLLJITAddObjectFile(LLVMOrcLLJITRef J,
+ LLVMMemoryBufferRef ObjBuffer) {
+ return wrap(unwrap(J)->addObjectFile(
+ std::unique_ptr<MemoryBuffer>(unwrap(ObjBuffer))));
+}
+
LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J,
LLVMOrcThreadSafeModuleRef TSM) {
return wrap(unwrap(J)->addIRModule(std::move(*unwrap(TSM))));
More information about the llvm-commits
mailing list