Original file line number Diff line number Diff line change
@@ -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;
}
234 changes: 222 additions & 12 deletions llvm/include/llvm-c/Orc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *|
Expand All @@ -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.
Expand Down Expand Up @@ -70,30 +186,124 @@ 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.
*
* 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 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.
*
* 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 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 LLVMOrcCreateDefaultLLJIT(LLVMOrcLLJITRef *Result);
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);

/**
* 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.
*/
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 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);
Expand Down
4 changes: 3 additions & 1 deletion llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>;

Expand Down Expand Up @@ -106,7 +107,8 @@ class SymbolStringPtr {
}

private:
using PoolEntryPtr = SymbolStringPool::PoolMapEntry *;
using PoolEntry = SymbolStringPool::PoolMapEntry;
using PoolEntryPtr = PoolEntry *;

SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
: S(S) {
Expand Down
157 changes: 154 additions & 3 deletions llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>()));
}

Expand All @@ -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;
Expand All @@ -61,6 +182,34 @@ LLVMErrorRef LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J) {
return LLVMErrorSuccess;
}

LLVMOrcExecutionSessionRef LLVMOrcLLJITGetExecutionSession(LLVMOrcLLJITRef J) {
return wrap(&unwrap(J)->getExecutionSession());
}

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();
}

LLVMOrcSymbolStringPoolEntryRef
LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName) {
return wrap(OrcV2CAPIHelper::releaseSymbolStringPtr(
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))));
Expand All @@ -69,6 +218,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;
Expand Down