X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FExecutionEngine%2FExecutionEngineBindings.cpp;h=ff7c4dce0d5da7c3019abe276f9fe092d2095cef;hp=75e680ab36129d9765c1f08ee3cc6914f42a0de5;hb=9c2c05d70e84a8de4f2756c11b6d19d5c67ab527;hpb=4d6ccb5f68cd7c6418a209f1fa4dbade569e4493 diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp index 75e680ab361..ff7c4dce0d5 100644 --- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -11,15 +11,29 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "jit" #include "llvm-c/ExecutionEngine.h" -#include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Module.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetOptions.h" #include 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(const_cast(P)); +} + /*===-- Operations on generic values --------------------------------------===*/ LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, @@ -89,7 +103,7 @@ LLVMBool LLVMCreateExecutionEngineForModule(LLVMExecutionEngineRef *OutEE, LLVMModuleRef M, char **OutError) { std::string Error; - EngineBuilder builder(unwrap(M)); + EngineBuilder builder(std::unique_ptr(unwrap(M))); builder.setEngineKind(EngineKind::Either) .setErrorStr(&Error); if (ExecutionEngine *EE = builder.create()){ @@ -104,7 +118,7 @@ LLVMBool LLVMCreateInterpreterForModule(LLVMExecutionEngineRef *OutInterp, LLVMModuleRef M, char **OutError) { std::string Error; - EngineBuilder builder(unwrap(M)); + EngineBuilder builder(std::unique_ptr(unwrap(M))); builder.setEngineKind(EngineKind::Interpreter) .setErrorStr(&Error); if (ExecutionEngine *Interp = builder.create()) { @@ -120,7 +134,7 @@ LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, unsigned OptLevel, char **OutError) { std::string Error; - EngineBuilder builder(unwrap(M)); + EngineBuilder builder(std::unique_ptr(unwrap(M))); builder.setEngineKind(EngineKind::JIT) .setErrorStr(&Error) .setOptLevel((CodeGenOpt::Level)OptLevel); @@ -132,35 +146,70 @@ LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, return 1; } -LLVMBool LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE, - LLVMModuleProviderRef MP, - char **OutError) { - /* The module provider is now actually a module. */ - return LLVMCreateExecutionEngineForModule(OutEE, - reinterpret_cast(MP), - OutError); +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 LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp, - LLVMModuleProviderRef MP, - char **OutError) { - /* The module provider is now actually a module. */ - return LLVMCreateInterpreterForModule(OutInterp, - reinterpret_cast(MP), - OutError); -} +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 Mod(unwrap(M)); + + if (Mod) + // Set function attribute "no-frame-pointer-elim" based on + // NoFramePointerElim. + for (auto &F : *Mod) { + auto Attrs = F.getAttributes(); + auto Value = options.NoFramePointerElim ? "true" : "false"; + Attrs = Attrs.addAttribute(F.getContext(), AttributeSet::FunctionIndex, + "no-frame-pointer-elim", Value); + F.setAttributes(Attrs); + } -LLVMBool LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT, - LLVMModuleProviderRef MP, - unsigned OptLevel, - char **OutError) { - /* The module provider is now actually a module. */ - return LLVMCreateJITCompilerForModule(OutJIT, - reinterpret_cast(MP), - OptLevel, OutError); + std::string Error; + EngineBuilder builder(std::move(Mod)); + builder.setEngineKind(EngineKind::JIT) + .setErrorStr(&Error) + .setOptLevel((CodeGenOpt::Level)options.OptLevel) + .setCodeModel(unwrap(options.CodeModel)) + .setTargetOptions(targetOptions); + if (options.MCJMM) + builder.setMCJITMemoryManager( + std::unique_ptr(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); } @@ -176,16 +225,17 @@ void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE) { int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F, unsigned ArgC, const char * const *ArgV, const char * const *EnvP) { - std::vector ArgVec; - for (unsigned I = 0; I != ArgC; ++I) - ArgVec.push_back(ArgV[I]); - + unwrap(EE)->finalizeObject(); + + std::vector ArgVec(ArgV, ArgV + ArgC); return unwrap(EE)->runFunctionAsMain(unwrap(F), ArgVec, EnvP); } LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F, unsigned NumArgs, LLVMGenericValueRef *Args) { + unwrap(EE)->finalizeObject(); + std::vector ArgVec; ArgVec.reserve(NumArgs); for (unsigned I = 0; I != NumArgs; ++I) @@ -197,16 +247,10 @@ LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F, } void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F) { - unwrap(EE)->freeMachineCodeForFunction(unwrap(F)); } void LLVMAddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M){ - unwrap(EE)->addModule(unwrap(M)); -} - -void LLVMAddModuleProvider(LLVMExecutionEngineRef EE, LLVMModuleProviderRef MP){ - /* The module provider is now actually a module. */ - LLVMAddModule(EE, reinterpret_cast(MP)); + unwrap(EE)->addModule(std::unique_ptr(unwrap(M))); } LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M, @@ -217,14 +261,6 @@ LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M, return 0; } -LLVMBool LLVMRemoveModuleProvider(LLVMExecutionEngineRef EE, - LLVMModuleProviderRef MP, - LLVMModuleRef *OutMod, char **OutError) { - /* The module provider is now actually a module. */ - return LLVMRemoveModule(EE, reinterpret_cast(MP), OutMod, - OutError); -} - LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, LLVMValueRef *OutFn) { if (Function *F = unwrap(EE)->FindFunctionNamed(Name)) { @@ -234,12 +270,18 @@ LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, return 1; } -void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, LLVMValueRef Fn) { - return unwrap(EE)->recompileAndRelinkFunction(unwrap(Fn)); +void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, + LLVMValueRef Fn) { + return nullptr; } LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) { - return wrap(unwrap(EE)->getTargetData()); + return wrap(&unwrap(EE)->getDataLayout()); +} + +LLVMTargetMachineRef +LLVMGetExecutionEngineTargetMachine(LLVMExecutionEngineRef EE) { + return wrap(unwrap(EE)->getTargetMachine()); } void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, @@ -248,5 +290,119 @@ void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, } void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) { + unwrap(EE)->finalizeObject(); + return unwrap(EE)->getPointerToGlobal(unwrap(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); +} + +/*===-- 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); +} +