Skip to content

Commit 0d5f15f

Browse files
committed
[ORC] Add C API support for adding object files to an LLJIT instance.
1 parent 1cd8493 commit 0d5f15f

File tree

5 files changed

+200
-2
lines changed

5 files changed

+200
-2
lines changed

llvm/examples/OrcV2Examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ add_subdirectory(LLJITWithGDBRegistrationListener)
44
add_subdirectory(LLJITWithLazyReexports)
55
add_subdirectory(LLJITWithObjectCache)
66
add_subdirectory(LLJITWithObjectLinkingLayerPlugin)
7+
add_subdirectory(OrcV2CBindingsAddObjectFile)
78
add_subdirectory(OrcV2CBindingsBasicUsage)
89
add_subdirectory(OrcV2CBindingsReflectProcessSymbols)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
set(LLVM_LINK_COMPONENTS
2+
Core
3+
ExecutionEngine
4+
IRReader
5+
JITLink
6+
MC
7+
OrcJIT
8+
Support
9+
Target
10+
nativecodegen
11+
)
12+
13+
add_llvm_example(OrcV2CBindingsAddObjectFile
14+
OrcV2CBindingsAddObjectFile.c
15+
)
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
//===-------- BasicOrcV2CBindings.c - Basic OrcV2 C Bindings Demo ---------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm-c/Core.h"
10+
#include "llvm-c/Error.h"
11+
#include "llvm-c/Initialization.h"
12+
#include "llvm-c/Orc.h"
13+
#include "llvm-c/Support.h"
14+
#include "llvm-c/Target.h"
15+
#include "llvm-c/TargetMachine.h"
16+
17+
#include <stdio.h>
18+
19+
int handleError(LLVMErrorRef Err) {
20+
char *ErrMsg = LLVMGetErrorMessage(Err);
21+
fprintf(stderr, "Error: %s\n", ErrMsg);
22+
LLVMDisposeErrorMessage(ErrMsg);
23+
return 1;
24+
}
25+
26+
LLVMModuleRef createDemoModule(LLVMContextRef Ctx) {
27+
// Create a new LLVM module.
28+
LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx);
29+
30+
// Add a "sum" function":
31+
// - Create the function type and function instance.
32+
LLVMTypeRef ParamTypes[] = {LLVMInt32Type(), LLVMInt32Type()};
33+
LLVMTypeRef SumFunctionType =
34+
LLVMFunctionType(LLVMInt32Type(), ParamTypes, 2, 0);
35+
LLVMValueRef SumFunction = LLVMAddFunction(M, "sum", SumFunctionType);
36+
37+
// - Add a basic block to the function.
38+
LLVMBasicBlockRef EntryBB = LLVMAppendBasicBlock(SumFunction, "entry");
39+
40+
// - Add an IR builder and point it at the end of the basic block.
41+
LLVMBuilderRef Builder = LLVMCreateBuilder();
42+
LLVMPositionBuilderAtEnd(Builder, EntryBB);
43+
44+
// - Get the two function arguments and use them co construct an "add"
45+
// instruction.
46+
LLVMValueRef SumArg0 = LLVMGetParam(SumFunction, 0);
47+
LLVMValueRef SumArg1 = LLVMGetParam(SumFunction, 1);
48+
LLVMValueRef Result = LLVMBuildAdd(Builder, SumArg0, SumArg1, "result");
49+
50+
// - Build the return instruction.
51+
LLVMBuildRet(Builder, Result);
52+
53+
return M;
54+
}
55+
56+
int main(int argc, char *argv[]) {
57+
58+
int MainResult = 0;
59+
60+
// Parse command line arguments and initialize LLVM Core.
61+
LLVMParseCommandLineOptions(argc, (const char **)argv, "");
62+
LLVMInitializeCore(LLVMGetGlobalPassRegistry());
63+
64+
// Initialize native target codegen and asm printer.
65+
LLVMInitializeNativeTarget();
66+
LLVMInitializeNativeAsmPrinter();
67+
68+
// Create the JIT instance.
69+
LLVMOrcLLJITRef J;
70+
{
71+
LLVMErrorRef Err;
72+
if ((Err = LLVMOrcCreateLLJIT(&J, 0))) {
73+
MainResult = handleError(Err);
74+
goto llvm_shutdown;
75+
}
76+
}
77+
78+
// Create our demo object file.
79+
LLVMMemoryBufferRef ObjectFileBuffer;
80+
{
81+
// Create a module.
82+
LLVMContextRef Ctx = LLVMContextCreate();
83+
LLVMModuleRef M = createDemoModule(Ctx);
84+
85+
// Get the Target.
86+
const char *Triple = LLVMOrcLLJITGetTripleString(J);
87+
LLVMTargetRef Target = 0;
88+
char *ErrorMsg = 0;
89+
if (LLVMGetTargetFromTriple(Triple, &Target, &ErrorMsg)) {
90+
fprintf(stderr, "Error getting target for %s: %s\n", Triple, ErrorMsg);
91+
LLVMDisposeModule(M);
92+
LLVMContextDispose(Ctx);
93+
goto jit_cleanup;
94+
}
95+
96+
// Construct a TargetMachine.
97+
LLVMTargetMachineRef TM =
98+
LLVMCreateTargetMachine(Target, Triple, "", "", LLVMCodeGenLevelNone,
99+
LLVMRelocDefault, LLVMCodeModelDefault);
100+
101+
// Run CodeGen to produce the buffer.
102+
if (LLVMTargetMachineEmitToMemoryBuffer(TM, M, LLVMObjectFile, &ErrorMsg,
103+
&ObjectFileBuffer)) {
104+
fprintf(stderr, "Error emitting object: %s\n", ErrorMsg);
105+
LLVMDisposeTargetMachine(TM);
106+
LLVMDisposeModule(M);
107+
LLVMContextDispose(Ctx);
108+
goto jit_cleanup;
109+
}
110+
}
111+
112+
// Add our object file buffer to the JIT.
113+
{
114+
LLVMErrorRef Err;
115+
if ((Err = LLVMOrcLLJITAddObjectFile(J, ObjectFileBuffer))) {
116+
MainResult = handleError(Err);
117+
goto jit_cleanup;
118+
}
119+
}
120+
121+
// Look up the address of our demo entry point.
122+
LLVMOrcJITTargetAddress SumAddr;
123+
{
124+
LLVMErrorRef Err;
125+
if ((Err = LLVMOrcLLJITLookup(J, &SumAddr, "sum"))) {
126+
MainResult = handleError(Err);
127+
goto jit_cleanup;
128+
}
129+
}
130+
131+
// If we made it here then everything succeeded. Execute our JIT'd code.
132+
int32_t (*Sum)(int32_t, int32_t) = (int32_t(*)(int32_t, int32_t))SumAddr;
133+
int32_t Result = Sum(1, 2);
134+
135+
// Print the result.
136+
printf("1 + 2 = %i\n", Result);
137+
138+
jit_cleanup:
139+
// Destroy our JIT instance. This will clean up any memory that the JIT has
140+
// taken ownership of. This operation is non-trivial (e.g. it may need to
141+
// JIT static destructors) and may also fail. In that case we want to render
142+
// the error to stderr, but not overwrite any existing return value.
143+
{
144+
LLVMErrorRef Err;
145+
if ((Err = LLVMOrcDisposeLLJIT(J))) {
146+
int NewFailureResult = handleError(Err);
147+
if (MainResult == 0)
148+
MainResult = NewFailureResult;
149+
}
150+
}
151+
152+
llvm_shutdown:
153+
// Shut down LLVM.
154+
LLVMShutdown();
155+
156+
return MainResult;
157+
}

llvm/include/llvm-c/Orc.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,12 @@ LLVMOrcExecutionSessionRef LLVMOrcLLJITGetExecutionSession(LLVMOrcLLJITRef J);
270270
*/
271271
LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J);
272272

273+
/**
274+
* Return the target triple for this LLJIT instance. This string is owned by
275+
* the LLJIT instance and should not be freed by the client.
276+
*/
277+
const char *LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J);
278+
273279
/**
274280
* Returns the global prefix character according to the LLJIT's DataLayout.
275281
*/
@@ -285,10 +291,19 @@ char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J);
285291
LLVMOrcSymbolStringPoolEntryRef
286292
LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName);
287293

294+
/**
295+
* Add a buffer representing an object file to the given LLJIT instance. This
296+
* operation transfers ownership of the buffer to the LLJIT instance. The
297+
* buffer should not be disposed of or referenced once this function returns.
298+
*/
299+
LLVMErrorRef LLVMOrcLLJITAddObjectFile(LLVMOrcLLJITRef J,
300+
LLVMMemoryBufferRef ObjBuffer);
301+
288302
/**
289303
* Add an IR module to the main JITDylib of the given LLJIT instance. This
290-
* operation takes ownership of the TSM argument which should not be disposed
291-
* of or referenced once this function returns.
304+
* operation transfers ownership of the TSM argument to the LLJIT instance.
305+
* The TSM argument should not be 3disposed of or referenced once this
306+
* function returns.
292307
*/
293308
LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J,
294309
LLVMOrcThreadSafeModuleRef TSM);

llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J) {
190190
return wrap(&unwrap(J)->getMainJITDylib());
191191
}
192192

193+
const char *LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J) {
194+
return unwrap(J)->getTargetTriple().str().c_str();
195+
}
196+
193197
char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J) {
194198
return unwrap(J)->getDataLayout().getGlobalPrefix();
195199
}
@@ -200,6 +204,12 @@ LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName) {
200204
unwrap(J)->mangleAndIntern(UnmangledName)));
201205
}
202206

207+
LLVMErrorRef LLVMOrcLLJITAddObjectFile(LLVMOrcLLJITRef J,
208+
LLVMMemoryBufferRef ObjBuffer) {
209+
return wrap(unwrap(J)->addObjectFile(
210+
std::unique_ptr<MemoryBuffer>(unwrap(ObjBuffer))));
211+
}
212+
203213
LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J,
204214
LLVMOrcThreadSafeModuleRef TSM) {
205215
return wrap(unwrap(J)->addIRModule(std::move(*unwrap(TSM))));

0 commit comments

Comments
 (0)