From 633ea07200ea055320dcd0ecad32639bd95aac59 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Sat, 14 Mar 2020 14:16:42 -0700 Subject: [PATCH] [Orc] Add basic OrcV2 C bindings and example. Renames the llvm/examples/LLJITExamples directory to llvm/examples/OrcV2Examples since it is becoming a home for all OrcV2 examples, not just LLJIT. See http://llvm.org/PR31103. --- llvm/examples/CMakeLists.txt | 2 +- .../BasicOrcV2CBindings/BasicOrcV2CBindings.c | 142 ++++++++++++++++++ .../BasicOrcV2CBindings/CMakeLists.txt | 15 ++ .../CMakeLists.txt | 1 + .../ExampleModules.h | 0 .../LLJITDumpObjects/CMakeLists.txt | 0 .../LLJITDumpObjects/LLJITDumpObjects.cpp | 0 .../CMakeLists.txt | 0 .../LLJITWithCustomObjectLinkingLayer.cpp | 0 .../LLJITWithLazyReexports/CMakeLists.txt | 0 .../LLJITWithLazyReexports.cpp | 0 .../LLJITWithObjectCache/CMakeLists.txt | 0 .../LLJITWithObjectCache.cpp | 0 .../CMakeLists.txt | 0 .../LLJITWithObjectLinkingLayerPlugin.cpp | 0 llvm/include/llvm-c/Orc.h | 95 ++++++++++++ llvm/lib/ExecutionEngine/Orc/CMakeLists.txt | 1 + .../ExecutionEngine/Orc/OrcV2CBindings.cpp | 80 ++++++++++ 18 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 llvm/examples/OrcV2Examples/BasicOrcV2CBindings/BasicOrcV2CBindings.c create mode 100644 llvm/examples/OrcV2Examples/BasicOrcV2CBindings/CMakeLists.txt rename llvm/examples/{LLJITExamples => OrcV2Examples}/CMakeLists.txt (85%) rename llvm/examples/{LLJITExamples => OrcV2Examples}/ExampleModules.h (100%) rename llvm/examples/{LLJITExamples => OrcV2Examples}/LLJITDumpObjects/CMakeLists.txt (100%) rename llvm/examples/{LLJITExamples => OrcV2Examples}/LLJITDumpObjects/LLJITDumpObjects.cpp (100%) rename llvm/examples/{LLJITExamples => OrcV2Examples}/LLJITWithCustomObjectLinkingLayer/CMakeLists.txt (100%) rename llvm/examples/{LLJITExamples => OrcV2Examples}/LLJITWithCustomObjectLinkingLayer/LLJITWithCustomObjectLinkingLayer.cpp (100%) rename llvm/examples/{LLJITExamples => OrcV2Examples}/LLJITWithLazyReexports/CMakeLists.txt (100%) rename llvm/examples/{LLJITExamples => OrcV2Examples}/LLJITWithLazyReexports/LLJITWithLazyReexports.cpp (100%) rename llvm/examples/{LLJITExamples => OrcV2Examples}/LLJITWithObjectCache/CMakeLists.txt (100%) rename llvm/examples/{LLJITExamples => OrcV2Examples}/LLJITWithObjectCache/LLJITWithObjectCache.cpp (100%) rename llvm/examples/{LLJITExamples => OrcV2Examples}/LLJITWithObjectLinkingLayerPlugin/CMakeLists.txt (100%) rename llvm/examples/{LLJITExamples => OrcV2Examples}/LLJITWithObjectLinkingLayerPlugin/LLJITWithObjectLinkingLayerPlugin.cpp (100%) create mode 100644 llvm/include/llvm-c/Orc.h create mode 100644 llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp diff --git a/llvm/examples/CMakeLists.txt b/llvm/examples/CMakeLists.txt index 49d5f52ee077..6d926d0bfba2 100644 --- a/llvm/examples/CMakeLists.txt +++ b/llvm/examples/CMakeLists.txt @@ -3,9 +3,9 @@ add_subdirectory(Fibonacci) add_subdirectory(HowToUseJIT) add_subdirectory(HowToUseLLJIT) add_subdirectory(IRTransforms) -add_subdirectory(LLJITExamples) add_subdirectory(Kaleidoscope) add_subdirectory(ModuleMaker) +add_subdirectory(OrcV2Examples) add_subdirectory(SpeculativeJIT) add_subdirectory(Bye) add_subdirectory(ThinLtoJIT) diff --git a/llvm/examples/OrcV2Examples/BasicOrcV2CBindings/BasicOrcV2CBindings.c b/llvm/examples/OrcV2Examples/BasicOrcV2CBindings/BasicOrcV2CBindings.c new file mode 100644 index 000000000000..11d4f36fd19c --- /dev/null +++ b/llvm/examples/OrcV2Examples/BasicOrcV2CBindings/BasicOrcV2CBindings.c @@ -0,0 +1,142 @@ +//===-------- 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 + +int handleError(LLVMErrorRef Err) { + char *ErrMsg = LLVMGetErrorMessage(Err); + fprintf(stderr, "Error: %s\n", ErrMsg); + LLVMDisposeErrorMessage(ErrMsg); + return 1; +} + +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 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); + + // 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 = LLVMOrcCreateDefaultLLJIT(&J))) { + MainResult = handleError(Err); + goto llvm_shutdown; + } + } + + // 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 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 0; +} diff --git a/llvm/examples/OrcV2Examples/BasicOrcV2CBindings/CMakeLists.txt b/llvm/examples/OrcV2Examples/BasicOrcV2CBindings/CMakeLists.txt new file mode 100644 index 000000000000..4d36d80922ff --- /dev/null +++ b/llvm/examples/OrcV2Examples/BasicOrcV2CBindings/CMakeLists.txt @@ -0,0 +1,15 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + IRReader + JITLink + MC + OrcJIT + Support + Target + nativecodegen + ) + +add_llvm_example(BasicOrcV2CBindings + BasicOrcV2CBindings.c + ) diff --git a/llvm/examples/LLJITExamples/CMakeLists.txt b/llvm/examples/OrcV2Examples/CMakeLists.txt similarity index 85% rename from llvm/examples/LLJITExamples/CMakeLists.txt rename to llvm/examples/OrcV2Examples/CMakeLists.txt index 8b9d599167c2..f1c51b79690a 100644 --- a/llvm/examples/LLJITExamples/CMakeLists.txt +++ b/llvm/examples/OrcV2Examples/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(BasicOrcV2CBindings) add_subdirectory(LLJITDumpObjects) add_subdirectory(LLJITWithObjectCache) add_subdirectory(LLJITWithCustomObjectLinkingLayer) diff --git a/llvm/examples/LLJITExamples/ExampleModules.h b/llvm/examples/OrcV2Examples/ExampleModules.h similarity index 100% rename from llvm/examples/LLJITExamples/ExampleModules.h rename to llvm/examples/OrcV2Examples/ExampleModules.h diff --git a/llvm/examples/LLJITExamples/LLJITDumpObjects/CMakeLists.txt b/llvm/examples/OrcV2Examples/LLJITDumpObjects/CMakeLists.txt similarity index 100% rename from llvm/examples/LLJITExamples/LLJITDumpObjects/CMakeLists.txt rename to llvm/examples/OrcV2Examples/LLJITDumpObjects/CMakeLists.txt diff --git a/llvm/examples/LLJITExamples/LLJITDumpObjects/LLJITDumpObjects.cpp b/llvm/examples/OrcV2Examples/LLJITDumpObjects/LLJITDumpObjects.cpp similarity index 100% rename from llvm/examples/LLJITExamples/LLJITDumpObjects/LLJITDumpObjects.cpp rename to llvm/examples/OrcV2Examples/LLJITDumpObjects/LLJITDumpObjects.cpp diff --git a/llvm/examples/LLJITExamples/LLJITWithCustomObjectLinkingLayer/CMakeLists.txt b/llvm/examples/OrcV2Examples/LLJITWithCustomObjectLinkingLayer/CMakeLists.txt similarity index 100% rename from llvm/examples/LLJITExamples/LLJITWithCustomObjectLinkingLayer/CMakeLists.txt rename to llvm/examples/OrcV2Examples/LLJITWithCustomObjectLinkingLayer/CMakeLists.txt diff --git a/llvm/examples/LLJITExamples/LLJITWithCustomObjectLinkingLayer/LLJITWithCustomObjectLinkingLayer.cpp b/llvm/examples/OrcV2Examples/LLJITWithCustomObjectLinkingLayer/LLJITWithCustomObjectLinkingLayer.cpp similarity index 100% rename from llvm/examples/LLJITExamples/LLJITWithCustomObjectLinkingLayer/LLJITWithCustomObjectLinkingLayer.cpp rename to llvm/examples/OrcV2Examples/LLJITWithCustomObjectLinkingLayer/LLJITWithCustomObjectLinkingLayer.cpp diff --git a/llvm/examples/LLJITExamples/LLJITWithLazyReexports/CMakeLists.txt b/llvm/examples/OrcV2Examples/LLJITWithLazyReexports/CMakeLists.txt similarity index 100% rename from llvm/examples/LLJITExamples/LLJITWithLazyReexports/CMakeLists.txt rename to llvm/examples/OrcV2Examples/LLJITWithLazyReexports/CMakeLists.txt diff --git a/llvm/examples/LLJITExamples/LLJITWithLazyReexports/LLJITWithLazyReexports.cpp b/llvm/examples/OrcV2Examples/LLJITWithLazyReexports/LLJITWithLazyReexports.cpp similarity index 100% rename from llvm/examples/LLJITExamples/LLJITWithLazyReexports/LLJITWithLazyReexports.cpp rename to llvm/examples/OrcV2Examples/LLJITWithLazyReexports/LLJITWithLazyReexports.cpp diff --git a/llvm/examples/LLJITExamples/LLJITWithObjectCache/CMakeLists.txt b/llvm/examples/OrcV2Examples/LLJITWithObjectCache/CMakeLists.txt similarity index 100% rename from llvm/examples/LLJITExamples/LLJITWithObjectCache/CMakeLists.txt rename to llvm/examples/OrcV2Examples/LLJITWithObjectCache/CMakeLists.txt diff --git a/llvm/examples/LLJITExamples/LLJITWithObjectCache/LLJITWithObjectCache.cpp b/llvm/examples/OrcV2Examples/LLJITWithObjectCache/LLJITWithObjectCache.cpp similarity index 100% rename from llvm/examples/LLJITExamples/LLJITWithObjectCache/LLJITWithObjectCache.cpp rename to llvm/examples/OrcV2Examples/LLJITWithObjectCache/LLJITWithObjectCache.cpp diff --git a/llvm/examples/LLJITExamples/LLJITWithObjectLinkingLayerPlugin/CMakeLists.txt b/llvm/examples/OrcV2Examples/LLJITWithObjectLinkingLayerPlugin/CMakeLists.txt similarity index 100% rename from llvm/examples/LLJITExamples/LLJITWithObjectLinkingLayerPlugin/CMakeLists.txt rename to llvm/examples/OrcV2Examples/LLJITWithObjectLinkingLayerPlugin/CMakeLists.txt diff --git a/llvm/examples/LLJITExamples/LLJITWithObjectLinkingLayerPlugin/LLJITWithObjectLinkingLayerPlugin.cpp b/llvm/examples/OrcV2Examples/LLJITWithObjectLinkingLayerPlugin/LLJITWithObjectLinkingLayerPlugin.cpp similarity index 100% rename from llvm/examples/LLJITExamples/LLJITWithObjectLinkingLayerPlugin/LLJITWithObjectLinkingLayerPlugin.cpp rename to llvm/examples/OrcV2Examples/LLJITWithObjectLinkingLayerPlugin/LLJITWithObjectLinkingLayerPlugin.cpp diff --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h new file mode 100644 index 000000000000..2a060a603774 --- /dev/null +++ b/llvm/include/llvm-c/Orc.h @@ -0,0 +1,95 @@ +/*===---------------- llvm-c/Orc.h - OrcV2 C bindings -----------*- C++ -*-===*\ +|* *| +|* 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 *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMOrcJIT.a, which implements *| +|* JIT compilation of LLVM IR. *| +|* *| +|* 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 *| +|* tools written in such languages. *| +|* *| +|* Note: This interface is experimental. It is *NOT* stable, and may be *| +|* changed without warning. Only C API usage documentation is *| +|* provided. See the C++ documentation for all higher level ORC API *| +|* details. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ORC_H +#define LLVM_C_ORC_H + +#include "llvm-c/Error.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +typedef struct LLVMOrcOpaqueThreadSafeContext *LLVMOrcThreadSafeContextRef; +typedef struct LLVMOrcOpaqueThreadSafeModule *LLVMOrcThreadSafeModuleRef; +typedef struct LLVMOrcOpaqueLLJIT *LLVMOrcLLJITRef; +typedef uint64_t LLVMOrcJITTargetAddress; + +/** + * Create a ThreadSafeContext containing a new LLVMContext. + */ +LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext(void); + +/** + * Get a reference to the wrapped LLVMContext. + */ +LLVMContextRef +LLVMOrcThreadSafeContextGetContext(LLVMOrcThreadSafeContextRef TSCtx); + +/** + * Dispose of a ThreadSafeContext. + */ +void LLVMOrcDisposeThreadSafeContext(LLVMOrcThreadSafeContextRef TSCtx); + +/** + * Create a ThreadSafeModule wrapper around the given LLVM module. This takes + * ownership of the M argument which should not be disposed of or referenced + * after this function returns. + */ +LLVMOrcThreadSafeModuleRef +LLVMOrcCreateNewThreadSafeModule(LLVMModuleRef M, + LLVMOrcThreadSafeContextRef TSCtx); + +/** + * Dispose of a ThreadSafeModule. + */ +void LLVMOrcDisposeThreadSafeModule(LLVMOrcThreadSafeModuleRef TSM); + +/** + * Create an LLJIT instance using all default values. + */ +LLVMErrorRef LLVMOrcCreateDefaultLLJIT(LLVMOrcLLJITRef *Result); + +/** + * Dispose of an LLJIT instance. + */ +LLVMErrorRef LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J); + +/** + * 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. + */ +LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J, + LLVMOrcThreadSafeModuleRef TSM); +/** + * Look up the given symbol in the main JITDylib of the given LLJIT instance. + * + * This operation does not take ownership of the Name argument. + */ +LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J, + LLVMOrcJITTargetAddress *Result, + const char *Name); + +LLVM_C_EXTERN_C_END + +#endif /* LLVM_C_ORC_H */ diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt index 7eb2742d7b53..473cf9299523 100644 --- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt @@ -19,6 +19,7 @@ add_llvm_component_library(LLVMOrcJIT ObjectTransformLayer.cpp OrcABISupport.cpp OrcCBindings.cpp + OrcV2CBindings.cpp OrcMCJITReplacement.cpp RTDyldObjectLinkingLayer.cpp ThreadSafeModule.cpp diff --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp new file mode 100644 index 000000000000..d623e17af264 --- /dev/null +++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp @@ -0,0 +1,80 @@ +//===--------------- OrcV2CBindings.cpp - C bindings OrcV2 APIs -----------===// +// +// 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/Orc.h" +#include "llvm-c/TargetMachine.h" + +#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" +#include "llvm/ExecutionEngine/Orc/LLJIT.h" + +using namespace llvm; +using namespace llvm::orc; + +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeContext, + LLVMOrcThreadSafeContextRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule, LLVMOrcThreadSafeModuleRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJIT, LLVMOrcLLJITRef) + +LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext() { + return wrap(new ThreadSafeContext(std::make_unique())); +} + +LLVMContextRef +LLVMOrcThreadSafeContextGetContext(LLVMOrcThreadSafeContextRef TSCtx) { + return wrap(unwrap(TSCtx)->getContext()); +} + +void LLVMOrcDisposeThreadSafeContext(LLVMOrcThreadSafeContextRef TSCtx) { + delete unwrap(TSCtx); +} + +LLVMOrcThreadSafeModuleRef +LLVMOrcCreateNewThreadSafeModule(LLVMModuleRef M, + LLVMOrcThreadSafeContextRef TSCtx) { + return wrap( + new ThreadSafeModule(std::unique_ptr(unwrap(M)), *unwrap(TSCtx))); +} + +void LLVMOrcDisposeThreadSafeModule(LLVMOrcThreadSafeModuleRef TSM) { + delete unwrap(TSM); +} + +LLVMErrorRef LLVMOrcCreateDefaultLLJIT(LLVMOrcLLJITRef *Result) { + auto J = LLJITBuilder().create(); + + if (!J) { + Result = 0; + return wrap(J.takeError()); + } + + *Result = wrap(J->release()); + return LLVMErrorSuccess; +} + +LLVMErrorRef LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J) { + delete unwrap(J); + return LLVMErrorSuccess; +} + +LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J, + LLVMOrcThreadSafeModuleRef TSM) { + return wrap(unwrap(J)->addIRModule(std::move(*unwrap(TSM)))); +} + +LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J, + LLVMOrcJITTargetAddress *Result, + const char *Name) { + auto Sym = unwrap(J)->lookup(Name); + if (!Sym) { + *Result = 0; + return wrap(Sym.takeError()); + } + + *Result = Sym->getAddress(); + return LLVMErrorSuccess; +}