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/LLJIT.h" |
12 | #include "llvm-c/Support.h" |
13 | #include "llvm-c/Target.h" |
14 | #include "llvm-c/TargetMachine.h" |
15 | |
16 | #include <stdio.h> |
17 | |
18 | int handleError(LLVMErrorRef Err) { |
19 | char *ErrMsg = LLVMGetErrorMessage(Err); |
20 | fprintf(stderr, format: "Error: %s\n" , ErrMsg); |
21 | LLVMDisposeErrorMessage(ErrMsg); |
22 | return 1; |
23 | } |
24 | |
25 | LLVMModuleRef createDemoModule(LLVMContextRef Ctx) { |
26 | // Create a new LLVM module. |
27 | LLVMModuleRef M = LLVMModuleCreateWithNameInContext(ModuleID: "demo" , C: Ctx); |
28 | |
29 | // Add a "sum" function": |
30 | // - Create the function type and function instance. |
31 | LLVMTypeRef ParamTypes[] = {LLVMInt32Type(), LLVMInt32Type()}; |
32 | LLVMTypeRef SumFunctionType = |
33 | LLVMFunctionType(ReturnType: LLVMInt32Type(), ParamTypes, ParamCount: 2, IsVarArg: 0); |
34 | LLVMValueRef SumFunction = LLVMAddFunction(M, Name: "sum" , FunctionTy: SumFunctionType); |
35 | |
36 | // - Add a basic block to the function. |
37 | LLVMBasicBlockRef EntryBB = LLVMAppendBasicBlock(Fn: SumFunction, Name: "entry" ); |
38 | |
39 | // - Add an IR builder and point it at the end of the basic block. |
40 | LLVMBuilderRef Builder = LLVMCreateBuilder(); |
41 | LLVMPositionBuilderAtEnd(Builder, Block: EntryBB); |
42 | |
43 | // - Get the two function arguments and use them co construct an "add" |
44 | // instruction. |
45 | LLVMValueRef SumArg0 = LLVMGetParam(Fn: SumFunction, Index: 0); |
46 | LLVMValueRef SumArg1 = LLVMGetParam(Fn: SumFunction, Index: 1); |
47 | LLVMValueRef Result = LLVMBuildAdd(Builder, LHS: SumArg0, RHS: SumArg1, Name: "result" ); |
48 | |
49 | // - Build the return instruction. |
50 | LLVMBuildRet(Builder, V: Result); |
51 | |
52 | // - Free the builder. |
53 | LLVMDisposeBuilder(Builder); |
54 | |
55 | return M; |
56 | } |
57 | |
58 | int main(int argc, const char *argv[]) { |
59 | |
60 | int MainResult = 0; |
61 | |
62 | // Parse command line arguments and initialize LLVM Core. |
63 | LLVMParseCommandLineOptions(argc, argv, Overview: "" ); |
64 | |
65 | // Initialize native target codegen and asm printer. |
66 | LLVMInitializeNativeTarget(); |
67 | LLVMInitializeNativeAsmPrinter(); |
68 | |
69 | // Create the JIT instance. |
70 | LLVMOrcLLJITRef J; |
71 | { |
72 | LLVMErrorRef Err; |
73 | if ((Err = LLVMOrcCreateLLJIT(Result: &J, Builder: 0))) { |
74 | MainResult = handleError(Err); |
75 | goto llvm_shutdown; |
76 | } |
77 | } |
78 | |
79 | // Create our demo object file. |
80 | LLVMMemoryBufferRef ObjectFileBuffer; |
81 | { |
82 | // Create a module. |
83 | LLVMContextRef Ctx = LLVMContextCreate(); |
84 | LLVMModuleRef M = createDemoModule(Ctx); |
85 | |
86 | // Get the Target. |
87 | const char *Triple = LLVMOrcLLJITGetTripleString(J); |
88 | LLVMTargetRef Target = 0; |
89 | char *ErrorMsg = 0; |
90 | if (LLVMGetTargetFromTriple(Triple, T: &Target, ErrorMessage: &ErrorMsg)) { |
91 | fprintf(stderr, format: "Error getting target for %s: %s\n" , Triple, ErrorMsg); |
92 | LLVMDisposeModule(M); |
93 | LLVMContextDispose(C: Ctx); |
94 | goto jit_cleanup; |
95 | } |
96 | |
97 | // Construct a TargetMachine. |
98 | LLVMTargetMachineRef TM = |
99 | LLVMCreateTargetMachine(T: Target, Triple, CPU: "" , Features: "" , Level: LLVMCodeGenLevelNone, |
100 | Reloc: LLVMRelocDefault, CodeModel: LLVMCodeModelDefault); |
101 | |
102 | // Run CodeGen to produce the buffer. |
103 | if (LLVMTargetMachineEmitToMemoryBuffer(T: TM, M, codegen: LLVMObjectFile, ErrorMessage: &ErrorMsg, |
104 | OutMemBuf: &ObjectFileBuffer)) { |
105 | fprintf(stderr, format: "Error emitting object: %s\n" , ErrorMsg); |
106 | LLVMDisposeTargetMachine(T: TM); |
107 | LLVMDisposeModule(M); |
108 | LLVMContextDispose(C: Ctx); |
109 | goto jit_cleanup; |
110 | } |
111 | |
112 | // CodeGen succeeded -- We have our module, so free the Module, LLVMContext, |
113 | // and TargetMachine. |
114 | LLVMDisposeModule(M); |
115 | LLVMContextDispose(C: Ctx); |
116 | LLVMDisposeTargetMachine(T: TM); |
117 | } |
118 | |
119 | // Add our object file buffer to the JIT. |
120 | { |
121 | LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J); |
122 | LLVMErrorRef Err; |
123 | if ((Err = LLVMOrcLLJITAddObjectFile(J, JD: MainJD, ObjBuffer: ObjectFileBuffer))) { |
124 | MainResult = handleError(Err); |
125 | goto jit_cleanup; |
126 | } |
127 | } |
128 | |
129 | // Look up the address of our demo entry point. |
130 | LLVMOrcJITTargetAddress SumAddr; |
131 | { |
132 | LLVMErrorRef Err; |
133 | if ((Err = LLVMOrcLLJITLookup(J, Result: &SumAddr, Name: "sum" ))) { |
134 | MainResult = handleError(Err); |
135 | goto jit_cleanup; |
136 | } |
137 | } |
138 | |
139 | // If we made it here then everything succeeded. Execute our JIT'd code. |
140 | int32_t (*Sum)(int32_t, int32_t) = (int32_t(*)(int32_t, int32_t))SumAddr; |
141 | int32_t Result = Sum(1, 2); |
142 | |
143 | // Print the result. |
144 | printf(format: "1 + 2 = %i\n" , Result); |
145 | |
146 | jit_cleanup: |
147 | // Destroy our JIT instance. This will clean up any memory that the JIT has |
148 | // taken ownership of. This operation is non-trivial (e.g. it may need to |
149 | // JIT static destructors) and may also fail. In that case we want to render |
150 | // the error to stderr, but not overwrite any existing return value. |
151 | { |
152 | LLVMErrorRef Err; |
153 | if ((Err = LLVMOrcDisposeLLJIT(J))) { |
154 | int NewFailureResult = handleError(Err); |
155 | if (MainResult == 0) |
156 | MainResult = NewFailureResult; |
157 | } |
158 | } |
159 | |
160 | llvm_shutdown: |
161 | // Shut down LLVM. |
162 | LLVMShutdown(); |
163 | |
164 | return MainResult; |
165 | } |
166 | |