[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