LLVM 20.0.0git
ExecutionEngineBindings.cpp
Go to the documentation of this file.
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
19#include "llvm/IR/Module.h"
23#include <cstring>
24#include <optional>
25
26using namespace llvm;
27
28#define DEBUG_TYPE "jit"
29
30// Wrapping the C bindings types.
32
33
35 return
36 reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P));
37}
38
39/*===-- Operations on generic values --------------------------------------===*/
40
42 unsigned long long N,
43 LLVMBool IsSigned) {
44 GenericValue *GenVal = new GenericValue();
45 GenVal->IntVal = APInt(unwrap<IntegerType>(Ty)->getBitWidth(), N, IsSigned);
46 return wrap(GenVal);
47}
48
50 GenericValue *GenVal = new GenericValue();
51 GenVal->PointerVal = P;
52 return wrap(GenVal);
53}
54
56 GenericValue *GenVal = new GenericValue();
57 switch (unwrap(TyRef)->getTypeID()) {
58 case Type::FloatTyID:
59 GenVal->FloatVal = N;
60 break;
62 GenVal->DoubleVal = N;
63 break;
64 default:
65 llvm_unreachable("LLVMGenericValueToFloat supports only float and double.");
66 }
67 return wrap(GenVal);
68}
69
71 return unwrap(GenValRef)->IntVal.getBitWidth();
72}
73
74unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenValRef,
75 LLVMBool IsSigned) {
76 GenericValue *GenVal = unwrap(GenValRef);
77 if (IsSigned)
78 return GenVal->IntVal.getSExtValue();
79 else
80 return GenVal->IntVal.getZExtValue();
81}
82
84 return unwrap(GenVal)->PointerVal;
85}
86
88 switch (unwrap(TyRef)->getTypeID()) {
89 case Type::FloatTyID:
90 return unwrap(GenVal)->FloatVal;
92 return unwrap(GenVal)->DoubleVal;
93 default:
94 llvm_unreachable("LLVMGenericValueToFloat supports only float and double.");
95 }
96}
97
99 delete unwrap(GenVal);
100}
101
102/*===-- Operations on execution engines -----------------------------------===*/
103
106 char **OutError) {
107 std::string Error;
108 EngineBuilder builder(std::unique_ptr<Module>(unwrap(M)));
111 if (ExecutionEngine *EE = builder.create()){
112 *OutEE = wrap(EE);
113 return 0;
114 }
115 *OutError = strdup(Error.c_str());
116 return 1;
117}
118
121 char **OutError) {
122 std::string Error;
123 EngineBuilder builder(std::unique_ptr<Module>(unwrap(M)));
126 if (ExecutionEngine *Interp = builder.create()) {
127 *OutInterp = wrap(Interp);
128 return 0;
129 }
130 *OutError = strdup(Error.c_str());
131 return 1;
132}
133
136 unsigned OptLevel,
137 char **OutError) {
138 std::string Error;
139 EngineBuilder builder(std::unique_ptr<Module>(unwrap(M)));
142 .setOptLevel((CodeGenOptLevel)OptLevel);
143 if (ExecutionEngine *JIT = builder.create()) {
144 *OutJIT = wrap(JIT);
145 return 0;
146 }
147 *OutError = strdup(Error.c_str());
148 return 1;
149}
150
152 size_t SizeOfPassedOptions) {
154 memset(&options, 0, sizeof(options)); // Most fields are zero by default.
155 options.CodeModel = LLVMCodeModelJITDefault;
156
157 memcpy(PassedOptions, &options,
158 std::min(sizeof(options), SizeOfPassedOptions));
159}
160
163 LLVMMCJITCompilerOptions *PassedOptions, size_t SizeOfPassedOptions,
164 char **OutError) {
166 // If the user passed a larger sized options struct, then they were compiled
167 // against a newer LLVM. Tell them that something is wrong.
168 if (SizeOfPassedOptions > sizeof(options)) {
169 *OutError = strdup(
170 "Refusing to use options struct that is larger than my own; assuming "
171 "LLVM library mismatch.");
172 return 1;
173 }
174
175 // Defend against the user having an old version of the API by ensuring that
176 // any fields they didn't see are cleared. We must defend against fields being
177 // set to the bitwise equivalent of zero, and assume that this means "do the
178 // default" as if that option hadn't been available.
179 LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
180 memcpy(&options, PassedOptions, SizeOfPassedOptions);
181
182 TargetOptions targetOptions;
183 targetOptions.EnableFastISel = options.EnableFastISel;
184 std::unique_ptr<Module> Mod(unwrap(M));
185
186 if (Mod)
187 // Set function attribute "frame-pointer" based on
188 // NoFramePointerElim.
189 for (auto &F : *Mod) {
190 auto Attrs = F.getAttributes();
191 StringRef Value = options.NoFramePointerElim ? "all" : "none";
192 Attrs = Attrs.addFnAttribute(F.getContext(), "frame-pointer", Value);
193 F.setAttributes(Attrs);
194 }
195
196 std::string Error;
197 EngineBuilder builder(std::move(Mod));
200 .setOptLevel((CodeGenOptLevel)options.OptLevel)
201 .setTargetOptions(targetOptions);
202 bool JIT;
203 if (std::optional<CodeModel::Model> CM = unwrap(options.CodeModel, JIT))
204 builder.setCodeModel(*CM);
205 if (options.MCJMM)
206 builder.setMCJITMemoryManager(
207 std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM)));
208 if (ExecutionEngine *JIT = builder.create()) {
209 *OutJIT = wrap(JIT);
210 return 0;
211 }
212 *OutError = strdup(Error.c_str());
213 return 1;
214}
215
217 delete unwrap(EE);
218}
219
221 unwrap(EE)->finalizeObject();
222 unwrap(EE)->runStaticConstructorsDestructors(false);
223}
224
226 unwrap(EE)->finalizeObject();
227 unwrap(EE)->runStaticConstructorsDestructors(true);
228}
229
231 unsigned ArgC, const char * const *ArgV,
232 const char * const *EnvP) {
233 unwrap(EE)->finalizeObject();
234
235 std::vector<std::string> ArgVec(ArgV, ArgV + ArgC);
236 return unwrap(EE)->runFunctionAsMain(unwrap<Function>(F), ArgVec, EnvP);
237}
238
240 unsigned NumArgs,
241 LLVMGenericValueRef *Args) {
242 unwrap(EE)->finalizeObject();
243
244 std::vector<GenericValue> ArgVec;
245 ArgVec.reserve(NumArgs);
246 for (unsigned I = 0; I != NumArgs; ++I)
247 ArgVec.push_back(*unwrap(Args[I]));
248
249 GenericValue *Result = new GenericValue();
250 *Result = unwrap(EE)->runFunction(unwrap<Function>(F), ArgVec);
251 return wrap(Result);
252}
253
255}
256
258 unwrap(EE)->addModule(std::unique_ptr<Module>(unwrap(M)));
259}
260
262 LLVMModuleRef *OutMod, char **OutError) {
263 Module *Mod = unwrap(M);
264 unwrap(EE)->removeModule(Mod);
265 *OutMod = wrap(Mod);
266 return 0;
267}
268
270 LLVMValueRef *OutFn) {
271 if (Function *F = unwrap(EE)->FindFunctionNamed(Name)) {
272 *OutFn = wrap(F);
273 return 0;
274 }
275 return 1;
276}
277
279 LLVMValueRef Fn) {
280 return nullptr;
281}
282
284 return wrap(&unwrap(EE)->getDataLayout());
285}
286
289 return wrap(unwrap(EE)->getTargetMachine());
290}
291
293 void* Addr) {
294 unwrap(EE)->addGlobalMapping(unwrap<GlobalValue>(Global), Addr);
295}
296
298 unwrap(EE)->finalizeObject();
299
300 return unwrap(EE)->getPointerToGlobal(unwrap<GlobalValue>(Global));
301}
302
304 return unwrap(EE)->getGlobalValueAddress(Name);
305}
306
308 return unwrap(EE)->getFunctionAddress(Name);
309}
310
312 char **OutError) {
313 assert(OutError && "OutError must be non-null");
314 auto *ExecEngine = unwrap(EE);
315 if (ExecEngine->hasError()) {
316 *OutError = strdup(ExecEngine->getErrorMessage().c_str());
317 ExecEngine->clearErrorMessage();
318 return true;
319 }
320 return false;
321}
322
323/*===-- Operations on memory managers -------------------------------------===*/
324
325namespace {
326
327struct SimpleBindingMMFunctions {
332};
333
334class SimpleBindingMemoryManager : public RTDyldMemoryManager {
335public:
336 SimpleBindingMemoryManager(const SimpleBindingMMFunctions& Functions,
337 void *Opaque);
338 ~SimpleBindingMemoryManager() override;
339
340 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
341 unsigned SectionID,
342 StringRef SectionName) override;
343
344 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
345 unsigned SectionID, StringRef SectionName,
346 bool isReadOnly) override;
347
348 bool finalizeMemory(std::string *ErrMsg) override;
349
350private:
351 SimpleBindingMMFunctions Functions;
352 void *Opaque;
353};
354
355SimpleBindingMemoryManager::SimpleBindingMemoryManager(
356 const SimpleBindingMMFunctions& Functions,
357 void *Opaque)
358 : Functions(Functions), Opaque(Opaque) {
359 assert(Functions.AllocateCodeSection &&
360 "No AllocateCodeSection function provided!");
361 assert(Functions.AllocateDataSection &&
362 "No AllocateDataSection function provided!");
363 assert(Functions.FinalizeMemory &&
364 "No FinalizeMemory function provided!");
365 assert(Functions.Destroy &&
366 "No Destroy function provided!");
367}
368
369SimpleBindingMemoryManager::~SimpleBindingMemoryManager() {
370 Functions.Destroy(Opaque);
371}
372
373uint8_t *SimpleBindingMemoryManager::allocateCodeSection(
374 uintptr_t Size, unsigned Alignment, unsigned SectionID,
376 return Functions.AllocateCodeSection(Opaque, Size, Alignment, SectionID,
377 SectionName.str().c_str());
378}
379
380uint8_t *SimpleBindingMemoryManager::allocateDataSection(
381 uintptr_t Size, unsigned Alignment, unsigned SectionID,
382 StringRef SectionName, bool isReadOnly) {
383 return Functions.AllocateDataSection(Opaque, Size, Alignment, SectionID,
384 SectionName.str().c_str(),
385 isReadOnly);
386}
387
388bool SimpleBindingMemoryManager::finalizeMemory(std::string *ErrMsg) {
389 char *errMsgCString = nullptr;
390 bool result = Functions.FinalizeMemory(Opaque, &errMsgCString);
391 assert((result || !errMsgCString) &&
392 "Did not expect an error message if FinalizeMemory succeeded");
393 if (errMsgCString) {
394 if (ErrMsg)
395 *ErrMsg = errMsgCString;
396 free(errMsgCString);
397 }
398 return result;
399}
400
401} // anonymous namespace
402
404 void *Opaque,
409
410 if (!AllocateCodeSection || !AllocateDataSection || !FinalizeMemory ||
411 !Destroy)
412 return nullptr;
413
414 SimpleBindingMMFunctions functions;
415 functions.AllocateCodeSection = AllocateCodeSection;
416 functions.AllocateDataSection = AllocateDataSection;
417 functions.FinalizeMemory = FinalizeMemory;
418 functions.Destroy = Destroy;
419 return wrap(new SimpleBindingMemoryManager(functions, Opaque));
420}
421
423 delete unwrap(MM);
424}
425
426/*===-- JIT Event Listener functions -------------------------------------===*/
427
428
429#if !LLVM_USE_INTEL_JITEVENTS
431{
432 return nullptr;
433}
434#endif
435
436#if !LLVM_USE_OPROFILE
438{
439 return nullptr;
440}
441#endif
442
443#if !LLVM_USE_PERF
445{
446 return nullptr;
447}
448#endif
aarch64 promote const
Lower uses of LDS variables from non kernel functions
#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref)
uint64_t Addr
std::string Name
uint64_t Size
static LLVMTargetMachineRef wrap(const TargetMachine *P)
static char getTypeID(Type *Ty)
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
Module.h This file contains the declarations for the Module class.
#define P(N)
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
Class for arbitrary precision integers.
Definition: APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1498
int64_t getSExtValue() const
Get sign extended value.
Definition: APInt.h:1520
Builder class for ExecutionEngines.
EngineBuilder & setTargetOptions(const TargetOptions &Opts)
setTargetOptions - Set the target options that the ExecutionEngine target is using.
EngineBuilder & setMCJITMemoryManager(std::unique_ptr< RTDyldMemoryManager > mcjmm)
setMCJITMemoryManager - Sets the MCJIT memory manager to use.
EngineBuilder & setCodeModel(CodeModel::Model M)
setCodeModel - Set the CodeModel that the ExecutionEngine target data is using.
EngineBuilder & setOptLevel(CodeGenOptLevel l)
setOptLevel - Set the optimization level for the JIT.
EngineBuilder & setErrorStr(std::string *e)
setErrorStr - Set the error string to write to on error.
EngineBuilder & setEngineKind(EngineKind::Kind w)
setEngineKind - Controls whether the user wants the interpreter, the JIT, or whichever engine works.
ExecutionEngine * create()
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
Abstract interface for implementation execution of LLVM modules, designed to support both interpreter...
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
virtual uint8_t * allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, bool IsReadOnly)=0
Allocate a memory block of (at least) the given size suitable for data.
virtual uint8_t * allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName)=0
Allocate a memory block of (at least) the given size suitable for executable code.
virtual bool finalizeMemory(std::string *ErrMsg=nullptr)=0
This method is called when object loading is complete and section page permissions can be applied.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:77
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
@ FloatTyID
32-bit floating point type
Definition: Type.h:58
@ DoubleTyID
64-bit floating point type
Definition: Type.h:59
LLVM Value Representation.
Definition: Value.h:74
LLVMGenericValueRef LLVMCreateGenericValueOfPointer(void *P)
double LLVMGenericValueToFloat(LLVMTypeRef TyRef, LLVMGenericValueRef GenVal)
LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void)
LLVMBool LLVMExecutionEngineGetErrMsg(LLVMExecutionEngineRef EE, char **OutError)
Returns true on error, false on success.
LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager(void *Opaque, LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection, LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection, LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory, LLVMMemoryManagerDestroyCallback Destroy)
Create a simple custom MCJIT memory manager.
void LLVMInitializeMCJITCompilerOptions(LLVMMCJITCompilerOptions *PassedOptions, size_t SizeOfPassedOptions)
void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE)
LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M, unsigned OptLevel, char **OutError)
LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, LLVMValueRef *OutFn)
struct LLVMOpaqueMCJITMemoryManager * LLVMMCJITMemoryManagerRef
LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, unsigned long long N, LLVMBool IsSigned)
void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM)
void(* LLVMMemoryManagerDestroyCallback)(void *Opaque)
LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F, unsigned NumArgs, LLVMGenericValueRef *Args)
LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE)
void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE)
LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void)
void * LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, LLVMValueRef Fn)
struct LLVMOpaqueExecutionEngine * LLVMExecutionEngineRef
uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name)
LLVMBool LLVMCreateExecutionEngineForModule(LLVMExecutionEngineRef *OutEE, LLVMModuleRef M, char **OutError)
uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name)
void LLVMAddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M)
LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M, LLVMModuleRef *OutMod, char **OutError)
LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void)
struct LLVMOpaqueGenericValue * LLVMGenericValueRef
void * LLVMGenericValueToPointer(LLVMGenericValueRef GenVal)
LLVMBool(* LLVMMemoryManagerFinalizeMemoryCallback)(void *Opaque, char **ErrMsg)
unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef)
void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE)
LLVMBool LLVMCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M, LLVMMCJITCompilerOptions *PassedOptions, size_t SizeOfPassedOptions, char **OutError)
Create an MCJIT execution engine for a module, with the given options.
LLVMGenericValueRef LLVMCreateGenericValueOfFloat(LLVMTypeRef TyRef, double N)
uint8_t *(* LLVMMemoryManagerAllocateDataSectionCallback)(void *Opaque, uintptr_t Size, unsigned Alignment, unsigned SectionID, const char *SectionName, LLVMBool IsReadOnly)
unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenValRef, LLVMBool IsSigned)
int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F, unsigned ArgC, const char *const *ArgV, const char *const *EnvP)
void * LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global)
uint8_t *(* LLVMMemoryManagerAllocateCodeSectionCallback)(void *Opaque, uintptr_t Size, unsigned Alignment, unsigned SectionID, const char *SectionName)
void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void *Addr)
LLVMBool LLVMCreateInterpreterForModule(LLVMExecutionEngineRef *OutInterp, LLVMModuleRef M, char **OutError)
void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F)
void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal)
LLVMTargetMachineRef LLVMGetExecutionEngineTargetMachine(LLVMExecutionEngineRef EE)
struct LLVMOpaqueValue * LLVMValueRef
Represents an individual value in LLVM IR.
Definition: Types.h:75
int LLVMBool
Definition: Types.h:28
struct LLVMOpaqueType * LLVMTypeRef
Each value in the LLVM IR has a type, an LLVMTypeRef.
Definition: Types.h:68
struct LLVMOpaqueModule * LLVMModuleRef
The top-level container for all other LLVM Intermediate Representation (IR) objects.
Definition: Types.h:61
struct LLVMOpaqueJITEventListener * LLVMJITEventListenerRef
Definition: Types.h:165
struct LLVMOpaqueTargetMachine * LLVMTargetMachineRef
Definition: TargetMachine.h:35
struct LLVMOpaqueTargetData * LLVMTargetDataRef
Definition: Target.h:37
@ LLVMCodeModelJITDefault
Definition: TargetMachine.h:57
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static const Kind Either
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:54
@ Global
Append to llvm.global_dtors.
Attribute unwrap(LLVMAttributeRef Attr)
Definition: Attributes.h:320
#define N
PointerTy PointerVal
Definition: GenericValue.h:31