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
25using namespace llvm;
26
27#define DEBUG_TYPE "jit"
28
29// Wrapping the C bindings types.
30DEFINE_SIMPLE_CONVERSION_FUNCTIONS(GenericValue, LLVMGenericValueRef)
31
32
33static LLVMTargetMachineRef wrap(const TargetMachine *P) {
34 return
35 reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P));
36}
37
38/*===-- Operations on generic values --------------------------------------===*/
39
40LLVMGenericValueRef 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
48LLVMGenericValueRef LLVMCreateGenericValueOfPointer(void *P) {
49 GenericValue *GenVal = new GenericValue();
50 GenVal->PointerVal = P;
51 return wrap(P: GenVal);
52}
53
54LLVMGenericValueRef 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
69unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef) {
70 return unwrap(P: GenValRef)->IntVal.getBitWidth();
71}
72
73unsigned 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
82void *LLVMGenericValueToPointer(LLVMGenericValueRef GenVal) {
83 return unwrap(P: GenVal)->PointerVal;
84}
85
86double 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
97void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal) {
98 delete unwrap(P: GenVal);
99}
100
101/*===-- Operations on execution engines -----------------------------------===*/
102
103LLVMBool 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
118LLVMBool 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
133LLVMBool 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
150void 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
160LLVMBool 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
215void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE) {
216 delete unwrap(P: EE);
217}
218
219void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE) {
220 unwrap(P: EE)->finalizeObject();
221 unwrap(P: EE)->runStaticConstructorsDestructors(isDtors: false);
222}
223
224void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE) {
225 unwrap(P: EE)->finalizeObject();
226 unwrap(P: EE)->runStaticConstructorsDestructors(isDtors: true);
227}
228
229int 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
238LLVMGenericValueRef 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
253void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F) {
254}
255
256void LLVMAddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M){
257 unwrap(P: EE)->addModule(M: std::unique_ptr<Module>(unwrap(P: M)));
258}
259
260LLVMBool 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
268LLVMBool 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
277void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE,
278 LLVMValueRef Fn) {
279 return nullptr;
280}
281
282LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) {
283 return wrap(P: &unwrap(P: EE)->getDataLayout());
284}
285
286LLVMTargetMachineRef
287LLVMGetExecutionEngineTargetMachine(LLVMExecutionEngineRef EE) {
288 return wrap(P: unwrap(P: EE)->getTargetMachine());
289}
290
291void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
292 void* Addr) {
293 unwrap(P: EE)->addGlobalMapping(GV: unwrap<GlobalValue>(P: Global), Addr);
294}
295
296void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) {
297 unwrap(P: EE)->finalizeObject();
298
299 return unwrap(P: EE)->getPointerToGlobal(GV: unwrap<GlobalValue>(P: Global));
300}
301
302uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name) {
303 return unwrap(P: EE)->getGlobalValueAddress(Name);
304}
305
306uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name) {
307 return unwrap(P: EE)->getFunctionAddress(Name);
308}
309
310LLVMBool 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
324namespace {
325
326struct SimpleBindingMMFunctions {
327 LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection;
328 LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection;
329 LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory;
330 LLVMMemoryManagerDestroyCallback Destroy;
331};
332
333class SimpleBindingMemoryManager : public RTDyldMemoryManager {
334public:
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
349private:
350 SimpleBindingMMFunctions Functions;
351 void *Opaque;
352};
353
354SimpleBindingMemoryManager::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
368SimpleBindingMemoryManager::~SimpleBindingMemoryManager() {
369 Functions.Destroy(Opaque);
370}
371
372uint8_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
379uint8_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
387bool 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
402LLVMMCJITMemoryManagerRef 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
421void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM) {
422 delete unwrap(P: MM);
423}
424
425/*===-- JIT Event Listener functions -------------------------------------===*/
426
427
428#if !LLVM_USE_INTEL_JITEVENTS
429LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void)
430{
431 return nullptr;
432}
433#endif
434
435#if !LLVM_USE_OPROFILE
436LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void)
437{
438 return nullptr;
439}
440#endif
441
442#if !LLVM_USE_PERF
443LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void)
444{
445 return nullptr;
446}
447#endif
448