1 | //===-- ExecutionEngineBindings.cpp - C bindings for EEs ------------------===// |
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 | // This file defines the C bindings for the ExecutionEngine library. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm-c/ExecutionEngine.h" |
14 | #include "llvm/ExecutionEngine/ExecutionEngine.h" |
15 | #include "llvm/ExecutionEngine/GenericValue.h" |
16 | #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" |
17 | #include "llvm/IR/DerivedTypes.h" |
18 | #include "llvm/IR/Module.h" |
19 | #include "llvm/Support/ErrorHandling.h" |
20 | #include "llvm/Target/CodeGenCWrappers.h" |
21 | #include "llvm/Target/TargetOptions.h" |
22 | #include <cstring> |
23 | #include <optional> |
24 | |
25 | using namespace llvm; |
26 | |
27 | #define DEBUG_TYPE "jit" |
28 | |
29 | // Wrapping the C bindings types. |
30 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(GenericValue, LLVMGenericValueRef) |
31 | |
32 | |
33 | static LLVMTargetMachineRef wrap(const TargetMachine *P) { |
34 | return |
35 | reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P)); |
36 | } |
37 | |
38 | /*===-- Operations on generic values --------------------------------------===*/ |
39 | |
40 | LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, |
41 | unsigned long long N, |
42 | LLVMBool IsSigned) { |
43 | GenericValue *GenVal = new GenericValue(); |
44 | GenVal->IntVal = APInt(unwrap<IntegerType>(P: Ty)->getBitWidth(), N, IsSigned); |
45 | return wrap(P: GenVal); |
46 | } |
47 | |
48 | LLVMGenericValueRef LLVMCreateGenericValueOfPointer(void *P) { |
49 | GenericValue *GenVal = new GenericValue(); |
50 | GenVal->PointerVal = P; |
51 | return wrap(P: GenVal); |
52 | } |
53 | |
54 | LLVMGenericValueRef LLVMCreateGenericValueOfFloat(LLVMTypeRef TyRef, double N) { |
55 | GenericValue *GenVal = new GenericValue(); |
56 | switch (unwrap(P: TyRef)->getTypeID()) { |
57 | case Type::FloatTyID: |
58 | GenVal->FloatVal = N; |
59 | break; |
60 | case Type::DoubleTyID: |
61 | GenVal->DoubleVal = N; |
62 | break; |
63 | default: |
64 | llvm_unreachable("LLVMGenericValueToFloat supports only float and double." ); |
65 | } |
66 | return wrap(P: GenVal); |
67 | } |
68 | |
69 | unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef) { |
70 | return unwrap(P: GenValRef)->IntVal.getBitWidth(); |
71 | } |
72 | |
73 | unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenValRef, |
74 | LLVMBool IsSigned) { |
75 | GenericValue *GenVal = unwrap(P: GenValRef); |
76 | if (IsSigned) |
77 | return GenVal->IntVal.getSExtValue(); |
78 | else |
79 | return GenVal->IntVal.getZExtValue(); |
80 | } |
81 | |
82 | void *LLVMGenericValueToPointer(LLVMGenericValueRef GenVal) { |
83 | return unwrap(P: GenVal)->PointerVal; |
84 | } |
85 | |
86 | double LLVMGenericValueToFloat(LLVMTypeRef TyRef, LLVMGenericValueRef GenVal) { |
87 | switch (unwrap(P: TyRef)->getTypeID()) { |
88 | case Type::FloatTyID: |
89 | return unwrap(P: GenVal)->FloatVal; |
90 | case Type::DoubleTyID: |
91 | return unwrap(P: GenVal)->DoubleVal; |
92 | default: |
93 | llvm_unreachable("LLVMGenericValueToFloat supports only float and double." ); |
94 | } |
95 | } |
96 | |
97 | void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal) { |
98 | delete unwrap(P: GenVal); |
99 | } |
100 | |
101 | /*===-- Operations on execution engines -----------------------------------===*/ |
102 | |
103 | LLVMBool LLVMCreateExecutionEngineForModule(LLVMExecutionEngineRef *OutEE, |
104 | LLVMModuleRef M, |
105 | char **OutError) { |
106 | std::string Error; |
107 | EngineBuilder builder(std::unique_ptr<Module>(unwrap(P: M))); |
108 | builder.setEngineKind(EngineKind::Either) |
109 | .setErrorStr(&Error); |
110 | if (ExecutionEngine *EE = builder.create()){ |
111 | *OutEE = wrap(P: EE); |
112 | return 0; |
113 | } |
114 | *OutError = strdup(s: Error.c_str()); |
115 | return 1; |
116 | } |
117 | |
118 | LLVMBool LLVMCreateInterpreterForModule(LLVMExecutionEngineRef *OutInterp, |
119 | LLVMModuleRef M, |
120 | char **OutError) { |
121 | std::string Error; |
122 | EngineBuilder builder(std::unique_ptr<Module>(unwrap(P: M))); |
123 | builder.setEngineKind(EngineKind::Interpreter) |
124 | .setErrorStr(&Error); |
125 | if (ExecutionEngine *Interp = builder.create()) { |
126 | *OutInterp = wrap(P: Interp); |
127 | return 0; |
128 | } |
129 | *OutError = strdup(s: Error.c_str()); |
130 | return 1; |
131 | } |
132 | |
133 | LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, |
134 | LLVMModuleRef M, |
135 | unsigned OptLevel, |
136 | char **OutError) { |
137 | std::string Error; |
138 | EngineBuilder builder(std::unique_ptr<Module>(unwrap(P: M))); |
139 | builder.setEngineKind(EngineKind::JIT) |
140 | .setErrorStr(&Error) |
141 | .setOptLevel((CodeGenOptLevel)OptLevel); |
142 | if (ExecutionEngine *JIT = builder.create()) { |
143 | *OutJIT = wrap(P: JIT); |
144 | return 0; |
145 | } |
146 | *OutError = strdup(s: Error.c_str()); |
147 | return 1; |
148 | } |
149 | |
150 | void LLVMInitializeMCJITCompilerOptions(LLVMMCJITCompilerOptions *PassedOptions, |
151 | size_t SizeOfPassedOptions) { |
152 | LLVMMCJITCompilerOptions options; |
153 | memset(s: &options, c: 0, n: sizeof(options)); // Most fields are zero by default. |
154 | options.CodeModel = LLVMCodeModelJITDefault; |
155 | |
156 | memcpy(dest: PassedOptions, src: &options, |
157 | n: std::min(a: sizeof(options), b: SizeOfPassedOptions)); |
158 | } |
159 | |
160 | LLVMBool LLVMCreateMCJITCompilerForModule( |
161 | LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M, |
162 | LLVMMCJITCompilerOptions *PassedOptions, size_t SizeOfPassedOptions, |
163 | char **OutError) { |
164 | LLVMMCJITCompilerOptions options; |
165 | // If the user passed a larger sized options struct, then they were compiled |
166 | // against a newer LLVM. Tell them that something is wrong. |
167 | if (SizeOfPassedOptions > sizeof(options)) { |
168 | *OutError = strdup( |
169 | s: "Refusing to use options struct that is larger than my own; assuming " |
170 | "LLVM library mismatch." ); |
171 | return 1; |
172 | } |
173 | |
174 | // Defend against the user having an old version of the API by ensuring that |
175 | // any fields they didn't see are cleared. We must defend against fields being |
176 | // set to the bitwise equivalent of zero, and assume that this means "do the |
177 | // default" as if that option hadn't been available. |
178 | LLVMInitializeMCJITCompilerOptions(PassedOptions: &options, SizeOfPassedOptions: sizeof(options)); |
179 | memcpy(dest: &options, src: PassedOptions, n: SizeOfPassedOptions); |
180 | |
181 | TargetOptions targetOptions; |
182 | targetOptions.EnableFastISel = options.EnableFastISel; |
183 | std::unique_ptr<Module> Mod(unwrap(P: M)); |
184 | |
185 | if (Mod) |
186 | // Set function attribute "frame-pointer" based on |
187 | // NoFramePointerElim. |
188 | for (auto &F : *Mod) { |
189 | auto Attrs = F.getAttributes(); |
190 | StringRef Value = options.NoFramePointerElim ? "all" : "none" ; |
191 | Attrs = Attrs.addFnAttribute(C&: F.getContext(), Kind: "frame-pointer" , Value); |
192 | F.setAttributes(Attrs); |
193 | } |
194 | |
195 | std::string Error; |
196 | EngineBuilder builder(std::move(Mod)); |
197 | builder.setEngineKind(EngineKind::JIT) |
198 | .setErrorStr(&Error) |
199 | .setOptLevel((CodeGenOptLevel)options.OptLevel) |
200 | .setTargetOptions(targetOptions); |
201 | bool JIT; |
202 | if (std::optional<CodeModel::Model> CM = unwrap(Model: options.CodeModel, JIT)) |
203 | builder.setCodeModel(*CM); |
204 | if (options.MCJMM) |
205 | builder.setMCJITMemoryManager( |
206 | std::unique_ptr<RTDyldMemoryManager>(unwrap(P: options.MCJMM))); |
207 | if (ExecutionEngine *JIT = builder.create()) { |
208 | *OutJIT = wrap(P: JIT); |
209 | return 0; |
210 | } |
211 | *OutError = strdup(s: Error.c_str()); |
212 | return 1; |
213 | } |
214 | |
215 | void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE) { |
216 | delete unwrap(P: EE); |
217 | } |
218 | |
219 | void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE) { |
220 | unwrap(P: EE)->finalizeObject(); |
221 | unwrap(P: EE)->runStaticConstructorsDestructors(isDtors: false); |
222 | } |
223 | |
224 | void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE) { |
225 | unwrap(P: EE)->finalizeObject(); |
226 | unwrap(P: EE)->runStaticConstructorsDestructors(isDtors: true); |
227 | } |
228 | |
229 | int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F, |
230 | unsigned ArgC, const char * const *ArgV, |
231 | const char * const *EnvP) { |
232 | unwrap(P: EE)->finalizeObject(); |
233 | |
234 | std::vector<std::string> ArgVec(ArgV, ArgV + ArgC); |
235 | return unwrap(P: EE)->runFunctionAsMain(Fn: unwrap<Function>(P: F), argv: ArgVec, envp: EnvP); |
236 | } |
237 | |
238 | LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F, |
239 | unsigned NumArgs, |
240 | LLVMGenericValueRef *Args) { |
241 | unwrap(P: EE)->finalizeObject(); |
242 | |
243 | std::vector<GenericValue> ArgVec; |
244 | ArgVec.reserve(n: NumArgs); |
245 | for (unsigned I = 0; I != NumArgs; ++I) |
246 | ArgVec.push_back(x: *unwrap(P: Args[I])); |
247 | |
248 | GenericValue *Result = new GenericValue(); |
249 | *Result = unwrap(P: EE)->runFunction(F: unwrap<Function>(P: F), ArgValues: ArgVec); |
250 | return wrap(P: Result); |
251 | } |
252 | |
253 | void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F) { |
254 | } |
255 | |
256 | void LLVMAddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M){ |
257 | unwrap(P: EE)->addModule(M: std::unique_ptr<Module>(unwrap(P: M))); |
258 | } |
259 | |
260 | LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M, |
261 | LLVMModuleRef *OutMod, char **OutError) { |
262 | Module *Mod = unwrap(P: M); |
263 | unwrap(P: EE)->removeModule(M: Mod); |
264 | *OutMod = wrap(P: Mod); |
265 | return 0; |
266 | } |
267 | |
268 | LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, |
269 | LLVMValueRef *OutFn) { |
270 | if (Function *F = unwrap(P: EE)->FindFunctionNamed(FnName: Name)) { |
271 | *OutFn = wrap(P: F); |
272 | return 0; |
273 | } |
274 | return 1; |
275 | } |
276 | |
277 | void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, |
278 | LLVMValueRef Fn) { |
279 | return nullptr; |
280 | } |
281 | |
282 | LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) { |
283 | return wrap(P: &unwrap(P: EE)->getDataLayout()); |
284 | } |
285 | |
286 | LLVMTargetMachineRef |
287 | LLVMGetExecutionEngineTargetMachine(LLVMExecutionEngineRef EE) { |
288 | return wrap(P: unwrap(P: EE)->getTargetMachine()); |
289 | } |
290 | |
291 | void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, |
292 | void* Addr) { |
293 | unwrap(P: EE)->addGlobalMapping(GV: unwrap<GlobalValue>(P: Global), Addr); |
294 | } |
295 | |
296 | void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) { |
297 | unwrap(P: EE)->finalizeObject(); |
298 | |
299 | return unwrap(P: EE)->getPointerToGlobal(GV: unwrap<GlobalValue>(P: Global)); |
300 | } |
301 | |
302 | uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name) { |
303 | return unwrap(P: EE)->getGlobalValueAddress(Name); |
304 | } |
305 | |
306 | uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name) { |
307 | return unwrap(P: EE)->getFunctionAddress(Name); |
308 | } |
309 | |
310 | LLVMBool LLVMExecutionEngineGetErrMsg(LLVMExecutionEngineRef EE, |
311 | char **OutError) { |
312 | assert(OutError && "OutError must be non-null" ); |
313 | auto *ExecEngine = unwrap(P: EE); |
314 | if (ExecEngine->hasError()) { |
315 | *OutError = strdup(s: ExecEngine->getErrorMessage().c_str()); |
316 | ExecEngine->clearErrorMessage(); |
317 | return true; |
318 | } |
319 | return false; |
320 | } |
321 | |
322 | /*===-- Operations on memory managers -------------------------------------===*/ |
323 | |
324 | namespace { |
325 | |
326 | struct SimpleBindingMMFunctions { |
327 | LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection; |
328 | LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection; |
329 | LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory; |
330 | LLVMMemoryManagerDestroyCallback Destroy; |
331 | }; |
332 | |
333 | class SimpleBindingMemoryManager : public RTDyldMemoryManager { |
334 | public: |
335 | SimpleBindingMemoryManager(const SimpleBindingMMFunctions& Functions, |
336 | void *Opaque); |
337 | ~SimpleBindingMemoryManager() override; |
338 | |
339 | uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, |
340 | unsigned SectionID, |
341 | StringRef SectionName) override; |
342 | |
343 | uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, |
344 | unsigned SectionID, StringRef SectionName, |
345 | bool isReadOnly) override; |
346 | |
347 | bool finalizeMemory(std::string *ErrMsg) override; |
348 | |
349 | private: |
350 | SimpleBindingMMFunctions Functions; |
351 | void *Opaque; |
352 | }; |
353 | |
354 | SimpleBindingMemoryManager::SimpleBindingMemoryManager( |
355 | const SimpleBindingMMFunctions& Functions, |
356 | void *Opaque) |
357 | : Functions(Functions), Opaque(Opaque) { |
358 | assert(Functions.AllocateCodeSection && |
359 | "No AllocateCodeSection function provided!" ); |
360 | assert(Functions.AllocateDataSection && |
361 | "No AllocateDataSection function provided!" ); |
362 | assert(Functions.FinalizeMemory && |
363 | "No FinalizeMemory function provided!" ); |
364 | assert(Functions.Destroy && |
365 | "No Destroy function provided!" ); |
366 | } |
367 | |
368 | SimpleBindingMemoryManager::~SimpleBindingMemoryManager() { |
369 | Functions.Destroy(Opaque); |
370 | } |
371 | |
372 | uint8_t *SimpleBindingMemoryManager::allocateCodeSection( |
373 | uintptr_t Size, unsigned Alignment, unsigned SectionID, |
374 | StringRef SectionName) { |
375 | return Functions.AllocateCodeSection(Opaque, Size, Alignment, SectionID, |
376 | SectionName.str().c_str()); |
377 | } |
378 | |
379 | uint8_t *SimpleBindingMemoryManager::allocateDataSection( |
380 | uintptr_t Size, unsigned Alignment, unsigned SectionID, |
381 | StringRef SectionName, bool isReadOnly) { |
382 | return Functions.AllocateDataSection(Opaque, Size, Alignment, SectionID, |
383 | SectionName.str().c_str(), |
384 | isReadOnly); |
385 | } |
386 | |
387 | bool SimpleBindingMemoryManager::finalizeMemory(std::string *ErrMsg) { |
388 | char *errMsgCString = nullptr; |
389 | bool result = Functions.FinalizeMemory(Opaque, &errMsgCString); |
390 | assert((result || !errMsgCString) && |
391 | "Did not expect an error message if FinalizeMemory succeeded" ); |
392 | if (errMsgCString) { |
393 | if (ErrMsg) |
394 | *ErrMsg = errMsgCString; |
395 | free(ptr: errMsgCString); |
396 | } |
397 | return result; |
398 | } |
399 | |
400 | } // anonymous namespace |
401 | |
402 | LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager( |
403 | void *Opaque, |
404 | LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection, |
405 | LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection, |
406 | LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory, |
407 | LLVMMemoryManagerDestroyCallback Destroy) { |
408 | |
409 | if (!AllocateCodeSection || !AllocateDataSection || !FinalizeMemory || |
410 | !Destroy) |
411 | return nullptr; |
412 | |
413 | SimpleBindingMMFunctions functions; |
414 | functions.AllocateCodeSection = AllocateCodeSection; |
415 | functions.AllocateDataSection = AllocateDataSection; |
416 | functions.FinalizeMemory = FinalizeMemory; |
417 | functions.Destroy = Destroy; |
418 | return wrap(P: new SimpleBindingMemoryManager(functions, Opaque)); |
419 | } |
420 | |
421 | void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM) { |
422 | delete unwrap(P: MM); |
423 | } |
424 | |
425 | /*===-- JIT Event Listener functions -------------------------------------===*/ |
426 | |
427 | |
428 | #if !LLVM_USE_INTEL_JITEVENTS |
429 | LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void) |
430 | { |
431 | return nullptr; |
432 | } |
433 | #endif |
434 | |
435 | #if !LLVM_USE_OPROFILE |
436 | LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void) |
437 | { |
438 | return nullptr; |
439 | } |
440 | #endif |
441 | |
442 | #if !LLVM_USE_PERF |
443 | LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void) |
444 | { |
445 | return nullptr; |
446 | } |
447 | #endif |
448 | |