| //===-- ExecutionEngineBindings.cpp - C bindings for EEs ------------------===// | 
 | // | 
 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
 | // See https://llvm.org/LICENSE.txt for license information. | 
 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // This file defines the C bindings for the ExecutionEngine library. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "llvm-c/ExecutionEngine.h" | 
 | #include "llvm/ExecutionEngine/ExecutionEngine.h" | 
 | #include "llvm/ExecutionEngine/GenericValue.h" | 
 | #include "llvm/ExecutionEngine/JITEventListener.h" | 
 | #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" | 
 | #include "llvm/IR/DerivedTypes.h" | 
 | #include "llvm/IR/Module.h" | 
 | #include "llvm/Support/ErrorHandling.h" | 
 | #include "llvm/Target/CodeGenCWrappers.h" | 
 | #include "llvm/Target/TargetOptions.h" | 
 | #include <cstring> | 
 |  | 
 | using namespace llvm; | 
 |  | 
 | #define DEBUG_TYPE "jit" | 
 |  | 
 | // Wrapping the C bindings types. | 
 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(GenericValue, LLVMGenericValueRef) | 
 |  | 
 |  | 
 | static LLVMTargetMachineRef wrap(const TargetMachine *P) { | 
 |   return | 
 |   reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P)); | 
 | } | 
 |  | 
 | /*===-- Operations on generic values --------------------------------------===*/ | 
 |  | 
 | LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, | 
 |                                                 unsigned long long N, | 
 |                                                 LLVMBool IsSigned) { | 
 |   GenericValue *GenVal = new GenericValue(); | 
 |   GenVal->IntVal = APInt(unwrap<IntegerType>(Ty)->getBitWidth(), N, IsSigned); | 
 |   return wrap(GenVal); | 
 | } | 
 |  | 
 | LLVMGenericValueRef LLVMCreateGenericValueOfPointer(void *P) { | 
 |   GenericValue *GenVal = new GenericValue(); | 
 |   GenVal->PointerVal = P; | 
 |   return wrap(GenVal); | 
 | } | 
 |  | 
 | LLVMGenericValueRef LLVMCreateGenericValueOfFloat(LLVMTypeRef TyRef, double N) { | 
 |   GenericValue *GenVal = new GenericValue(); | 
 |   switch (unwrap(TyRef)->getTypeID()) { | 
 |   case Type::FloatTyID: | 
 |     GenVal->FloatVal = N; | 
 |     break; | 
 |   case Type::DoubleTyID: | 
 |     GenVal->DoubleVal = N; | 
 |     break; | 
 |   default: | 
 |     llvm_unreachable("LLVMGenericValueToFloat supports only float and double."); | 
 |   } | 
 |   return wrap(GenVal); | 
 | } | 
 |  | 
 | unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef) { | 
 |   return unwrap(GenValRef)->IntVal.getBitWidth(); | 
 | } | 
 |  | 
 | unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenValRef, | 
 |                                          LLVMBool IsSigned) { | 
 |   GenericValue *GenVal = unwrap(GenValRef); | 
 |   if (IsSigned) | 
 |     return GenVal->IntVal.getSExtValue(); | 
 |   else | 
 |     return GenVal->IntVal.getZExtValue(); | 
 | } | 
 |  | 
 | void *LLVMGenericValueToPointer(LLVMGenericValueRef GenVal) { | 
 |   return unwrap(GenVal)->PointerVal; | 
 | } | 
 |  | 
 | double LLVMGenericValueToFloat(LLVMTypeRef TyRef, LLVMGenericValueRef GenVal) { | 
 |   switch (unwrap(TyRef)->getTypeID()) { | 
 |   case Type::FloatTyID: | 
 |     return unwrap(GenVal)->FloatVal; | 
 |   case Type::DoubleTyID: | 
 |     return unwrap(GenVal)->DoubleVal; | 
 |   default: | 
 |     llvm_unreachable("LLVMGenericValueToFloat supports only float and double."); | 
 |   } | 
 | } | 
 |  | 
 | void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal) { | 
 |   delete unwrap(GenVal); | 
 | } | 
 |  | 
 | /*===-- Operations on execution engines -----------------------------------===*/ | 
 |  | 
 | LLVMBool LLVMCreateExecutionEngineForModule(LLVMExecutionEngineRef *OutEE, | 
 |                                             LLVMModuleRef M, | 
 |                                             char **OutError) { | 
 |   std::string Error; | 
 |   EngineBuilder builder(std::unique_ptr<Module>(unwrap(M))); | 
 |   builder.setEngineKind(EngineKind::Either) | 
 |          .setErrorStr(&Error); | 
 |   if (ExecutionEngine *EE = builder.create()){ | 
 |     *OutEE = wrap(EE); | 
 |     return 0; | 
 |   } | 
 |   *OutError = strdup(Error.c_str()); | 
 |   return 1; | 
 | } | 
 |  | 
 | LLVMBool LLVMCreateInterpreterForModule(LLVMExecutionEngineRef *OutInterp, | 
 |                                         LLVMModuleRef M, | 
 |                                         char **OutError) { | 
 |   std::string Error; | 
 |   EngineBuilder builder(std::unique_ptr<Module>(unwrap(M))); | 
 |   builder.setEngineKind(EngineKind::Interpreter) | 
 |          .setErrorStr(&Error); | 
 |   if (ExecutionEngine *Interp = builder.create()) { | 
 |     *OutInterp = wrap(Interp); | 
 |     return 0; | 
 |   } | 
 |   *OutError = strdup(Error.c_str()); | 
 |   return 1; | 
 | } | 
 |  | 
 | LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, | 
 |                                         LLVMModuleRef M, | 
 |                                         unsigned OptLevel, | 
 |                                         char **OutError) { | 
 |   std::string Error; | 
 |   EngineBuilder builder(std::unique_ptr<Module>(unwrap(M))); | 
 |   builder.setEngineKind(EngineKind::JIT) | 
 |          .setErrorStr(&Error) | 
 |          .setOptLevel((CodeGenOpt::Level)OptLevel); | 
 |   if (ExecutionEngine *JIT = builder.create()) { | 
 |     *OutJIT = wrap(JIT); | 
 |     return 0; | 
 |   } | 
 |   *OutError = strdup(Error.c_str()); | 
 |   return 1; | 
 | } | 
 |  | 
 | void LLVMInitializeMCJITCompilerOptions(LLVMMCJITCompilerOptions *PassedOptions, | 
 |                                         size_t SizeOfPassedOptions) { | 
 |   LLVMMCJITCompilerOptions options; | 
 |   memset(&options, 0, sizeof(options)); // Most fields are zero by default. | 
 |   options.CodeModel = LLVMCodeModelJITDefault; | 
 |  | 
 |   memcpy(PassedOptions, &options, | 
 |          std::min(sizeof(options), SizeOfPassedOptions)); | 
 | } | 
 |  | 
 | LLVMBool LLVMCreateMCJITCompilerForModule( | 
 |     LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M, | 
 |     LLVMMCJITCompilerOptions *PassedOptions, size_t SizeOfPassedOptions, | 
 |     char **OutError) { | 
 |   LLVMMCJITCompilerOptions options; | 
 |   // If the user passed a larger sized options struct, then they were compiled | 
 |   // against a newer LLVM. Tell them that something is wrong. | 
 |   if (SizeOfPassedOptions > sizeof(options)) { | 
 |     *OutError = strdup( | 
 |       "Refusing to use options struct that is larger than my own; assuming " | 
 |       "LLVM library mismatch."); | 
 |     return 1; | 
 |   } | 
 |  | 
 |   // Defend against the user having an old version of the API by ensuring that | 
 |   // any fields they didn't see are cleared. We must defend against fields being | 
 |   // set to the bitwise equivalent of zero, and assume that this means "do the | 
 |   // default" as if that option hadn't been available. | 
 |   LLVMInitializeMCJITCompilerOptions(&options, sizeof(options)); | 
 |   memcpy(&options, PassedOptions, SizeOfPassedOptions); | 
 |  | 
 |   TargetOptions targetOptions; | 
 |   targetOptions.EnableFastISel = options.EnableFastISel; | 
 |   std::unique_ptr<Module> Mod(unwrap(M)); | 
 |  | 
 |   if (Mod) | 
 |     // Set function attribute "frame-pointer" based on | 
 |     // NoFramePointerElim. | 
 |     for (auto &F : *Mod) { | 
 |       auto Attrs = F.getAttributes(); | 
 |       StringRef Value = options.NoFramePointerElim ? "all" : "none"; | 
 |       Attrs = Attrs.addFnAttribute(F.getContext(), "frame-pointer", Value); | 
 |       F.setAttributes(Attrs); | 
 |     } | 
 |  | 
 |   std::string Error; | 
 |   EngineBuilder builder(std::move(Mod)); | 
 |   builder.setEngineKind(EngineKind::JIT) | 
 |          .setErrorStr(&Error) | 
 |          .setOptLevel((CodeGenOpt::Level)options.OptLevel) | 
 |          .setTargetOptions(targetOptions); | 
 |   bool JIT; | 
 |   if (Optional<CodeModel::Model> CM = unwrap(options.CodeModel, JIT)) | 
 |     builder.setCodeModel(*CM); | 
 |   if (options.MCJMM) | 
 |     builder.setMCJITMemoryManager( | 
 |       std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM))); | 
 |   if (ExecutionEngine *JIT = builder.create()) { | 
 |     *OutJIT = wrap(JIT); | 
 |     return 0; | 
 |   } | 
 |   *OutError = strdup(Error.c_str()); | 
 |   return 1; | 
 | } | 
 |  | 
 | void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE) { | 
 |   delete unwrap(EE); | 
 | } | 
 |  | 
 | void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE) { | 
 |   unwrap(EE)->finalizeObject(); | 
 |   unwrap(EE)->runStaticConstructorsDestructors(false); | 
 | } | 
 |  | 
 | void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE) { | 
 |   unwrap(EE)->finalizeObject(); | 
 |   unwrap(EE)->runStaticConstructorsDestructors(true); | 
 | } | 
 |  | 
 | int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F, | 
 |                           unsigned ArgC, const char * const *ArgV, | 
 |                           const char * const *EnvP) { | 
 |   unwrap(EE)->finalizeObject(); | 
 |  | 
 |   std::vector<std::string> ArgVec(ArgV, ArgV + ArgC); | 
 |   return unwrap(EE)->runFunctionAsMain(unwrap<Function>(F), ArgVec, EnvP); | 
 | } | 
 |  | 
 | LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F, | 
 |                                     unsigned NumArgs, | 
 |                                     LLVMGenericValueRef *Args) { | 
 |   unwrap(EE)->finalizeObject(); | 
 |  | 
 |   std::vector<GenericValue> ArgVec; | 
 |   ArgVec.reserve(NumArgs); | 
 |   for (unsigned I = 0; I != NumArgs; ++I) | 
 |     ArgVec.push_back(*unwrap(Args[I])); | 
 |  | 
 |   GenericValue *Result = new GenericValue(); | 
 |   *Result = unwrap(EE)->runFunction(unwrap<Function>(F), ArgVec); | 
 |   return wrap(Result); | 
 | } | 
 |  | 
 | void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F) { | 
 | } | 
 |  | 
 | void LLVMAddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M){ | 
 |   unwrap(EE)->addModule(std::unique_ptr<Module>(unwrap(M))); | 
 | } | 
 |  | 
 | LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M, | 
 |                           LLVMModuleRef *OutMod, char **OutError) { | 
 |   Module *Mod = unwrap(M); | 
 |   unwrap(EE)->removeModule(Mod); | 
 |   *OutMod = wrap(Mod); | 
 |   return 0; | 
 | } | 
 |  | 
 | LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, | 
 |                           LLVMValueRef *OutFn) { | 
 |   if (Function *F = unwrap(EE)->FindFunctionNamed(Name)) { | 
 |     *OutFn = wrap(F); | 
 |     return 0; | 
 |   } | 
 |   return 1; | 
 | } | 
 |  | 
 | void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, | 
 |                                      LLVMValueRef Fn) { | 
 |   return nullptr; | 
 | } | 
 |  | 
 | LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) { | 
 |   return wrap(&unwrap(EE)->getDataLayout()); | 
 | } | 
 |  | 
 | LLVMTargetMachineRef | 
 | LLVMGetExecutionEngineTargetMachine(LLVMExecutionEngineRef EE) { | 
 |   return wrap(unwrap(EE)->getTargetMachine()); | 
 | } | 
 |  | 
 | void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, | 
 |                           void* Addr) { | 
 |   unwrap(EE)->addGlobalMapping(unwrap<GlobalValue>(Global), Addr); | 
 | } | 
 |  | 
 | void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) { | 
 |   unwrap(EE)->finalizeObject(); | 
 |  | 
 |   return unwrap(EE)->getPointerToGlobal(unwrap<GlobalValue>(Global)); | 
 | } | 
 |  | 
 | uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name) { | 
 |   return unwrap(EE)->getGlobalValueAddress(Name); | 
 | } | 
 |  | 
 | uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name) { | 
 |   return unwrap(EE)->getFunctionAddress(Name); | 
 | } | 
 |  | 
 | LLVMBool LLVMExecutionEngineGetErrMsg(LLVMExecutionEngineRef EE, | 
 |                                       char **OutError) { | 
 |   assert(OutError && "OutError must be non-null"); | 
 |   auto *ExecEngine = unwrap(EE); | 
 |   if (ExecEngine->hasError()) { | 
 |     *OutError = strdup(ExecEngine->getErrorMessage().c_str()); | 
 |     ExecEngine->clearErrorMessage(); | 
 |     return true; | 
 |   } | 
 |   return false; | 
 | } | 
 |  | 
 | /*===-- Operations on memory managers -------------------------------------===*/ | 
 |  | 
 | namespace { | 
 |  | 
 | struct SimpleBindingMMFunctions { | 
 |   LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection; | 
 |   LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection; | 
 |   LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory; | 
 |   LLVMMemoryManagerDestroyCallback Destroy; | 
 | }; | 
 |  | 
 | class SimpleBindingMemoryManager : public RTDyldMemoryManager { | 
 | public: | 
 |   SimpleBindingMemoryManager(const SimpleBindingMMFunctions& Functions, | 
 |                              void *Opaque); | 
 |   ~SimpleBindingMemoryManager() override; | 
 |  | 
 |   uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, | 
 |                                unsigned SectionID, | 
 |                                StringRef SectionName) override; | 
 |  | 
 |   uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, | 
 |                                unsigned SectionID, StringRef SectionName, | 
 |                                bool isReadOnly) override; | 
 |  | 
 |   bool finalizeMemory(std::string *ErrMsg) override; | 
 |  | 
 | private: | 
 |   SimpleBindingMMFunctions Functions; | 
 |   void *Opaque; | 
 | }; | 
 |  | 
 | SimpleBindingMemoryManager::SimpleBindingMemoryManager( | 
 |   const SimpleBindingMMFunctions& Functions, | 
 |   void *Opaque) | 
 |   : Functions(Functions), Opaque(Opaque) { | 
 |   assert(Functions.AllocateCodeSection && | 
 |          "No AllocateCodeSection function provided!"); | 
 |   assert(Functions.AllocateDataSection && | 
 |          "No AllocateDataSection function provided!"); | 
 |   assert(Functions.FinalizeMemory && | 
 |          "No FinalizeMemory function provided!"); | 
 |   assert(Functions.Destroy && | 
 |          "No Destroy function provided!"); | 
 | } | 
 |  | 
 | SimpleBindingMemoryManager::~SimpleBindingMemoryManager() { | 
 |   Functions.Destroy(Opaque); | 
 | } | 
 |  | 
 | uint8_t *SimpleBindingMemoryManager::allocateCodeSection( | 
 |   uintptr_t Size, unsigned Alignment, unsigned SectionID, | 
 |   StringRef SectionName) { | 
 |   return Functions.AllocateCodeSection(Opaque, Size, Alignment, SectionID, | 
 |                                        SectionName.str().c_str()); | 
 | } | 
 |  | 
 | uint8_t *SimpleBindingMemoryManager::allocateDataSection( | 
 |   uintptr_t Size, unsigned Alignment, unsigned SectionID, | 
 |   StringRef SectionName, bool isReadOnly) { | 
 |   return Functions.AllocateDataSection(Opaque, Size, Alignment, SectionID, | 
 |                                        SectionName.str().c_str(), | 
 |                                        isReadOnly); | 
 | } | 
 |  | 
 | bool SimpleBindingMemoryManager::finalizeMemory(std::string *ErrMsg) { | 
 |   char *errMsgCString = nullptr; | 
 |   bool result = Functions.FinalizeMemory(Opaque, &errMsgCString); | 
 |   assert((result || !errMsgCString) && | 
 |          "Did not expect an error message if FinalizeMemory succeeded"); | 
 |   if (errMsgCString) { | 
 |     if (ErrMsg) | 
 |       *ErrMsg = errMsgCString; | 
 |     free(errMsgCString); | 
 |   } | 
 |   return result; | 
 | } | 
 |  | 
 | } // anonymous namespace | 
 |  | 
 | LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager( | 
 |   void *Opaque, | 
 |   LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection, | 
 |   LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection, | 
 |   LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory, | 
 |   LLVMMemoryManagerDestroyCallback Destroy) { | 
 |  | 
 |   if (!AllocateCodeSection || !AllocateDataSection || !FinalizeMemory || | 
 |       !Destroy) | 
 |     return nullptr; | 
 |  | 
 |   SimpleBindingMMFunctions functions; | 
 |   functions.AllocateCodeSection = AllocateCodeSection; | 
 |   functions.AllocateDataSection = AllocateDataSection; | 
 |   functions.FinalizeMemory = FinalizeMemory; | 
 |   functions.Destroy = Destroy; | 
 |   return wrap(new SimpleBindingMemoryManager(functions, Opaque)); | 
 | } | 
 |  | 
 | void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM) { | 
 |   delete unwrap(MM); | 
 | } | 
 |  | 
 | /*===-- JIT Event Listener functions -------------------------------------===*/ | 
 |  | 
 |  | 
 | #if !LLVM_USE_INTEL_JITEVENTS | 
 | LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void) | 
 | { | 
 |   return nullptr; | 
 | } | 
 | #endif | 
 |  | 
 | #if !LLVM_USE_OPROFILE | 
 | LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void) | 
 | { | 
 |   return nullptr; | 
 | } | 
 | #endif | 
 |  | 
 | #if !LLVM_USE_PERF | 
 | LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void) | 
 | { | 
 |   return nullptr; | 
 | } | 
 | #endif |