X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FExecutionEngine%2FExecutionEngineBindings.cpp;h=88e73bf253e496d2d46d316b714237212751569a;hb=f46e5eadc307beaef6e8dd0602bb4c63ca41fd50;hp=43389e0bbfe831d515169a86e90db545279d1d36;hpb=c25e7581b9b8088910da31702d4ca21c4734c6d7;p=oota-llvm.git diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp index 43389e0bbfe..88e73bf253e 100644 --- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -13,18 +13,41 @@ #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 using namespace llvm; +// Wrapping the C bindings types. +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(GenericValue, LLVMGenericValueRef) + +inline DataLayout *unwrap(LLVMTargetDataRef P) { + return reinterpret_cast(P); +} + +inline LLVMTargetDataRef wrap(const DataLayout *P) { + return reinterpret_cast(const_cast(P)); +} + +inline TargetLibraryInfo *unwrap(LLVMTargetLibraryInfoRef P) { + return reinterpret_cast(P); +} + +inline LLVMTargetLibraryInfoRef wrap(const TargetLibraryInfo *P) { + TargetLibraryInfo *X = const_cast(P); + return reinterpret_cast(X); +} + /*===-- Operations on generic values --------------------------------------===*/ LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, unsigned long long N, - int IsSigned) { + LLVMBool IsSigned) { GenericValue *GenVal = new GenericValue(); GenVal->IntVal = APInt(unwrap(Ty)->getBitWidth(), N, IsSigned); return wrap(GenVal); @@ -46,7 +69,7 @@ LLVMGenericValueRef LLVMCreateGenericValueOfFloat(LLVMTypeRef TyRef, double N) { GenVal->DoubleVal = N; break; default: - LLVM_UNREACHABLE("LLVMGenericValueToFloat supports only float and double."); + llvm_unreachable("LLVMGenericValueToFloat supports only float and double."); } return wrap(GenVal); } @@ -56,7 +79,7 @@ unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef) { } unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenValRef, - int IsSigned) { + LLVMBool IsSigned) { GenericValue *GenVal = unwrap(GenValRef); if (IsSigned) return GenVal->IntVal.getSExtValue(); @@ -75,10 +98,8 @@ double LLVMGenericValueToFloat(LLVMTypeRef TyRef, LLVMGenericValueRef GenVal) { case Type::DoubleTyID: return unwrap(GenVal)->DoubleVal; default: - LLVM_UNREACHABLE("LLVMGenericValueToFloat supports only float and double."); - break; + llvm_unreachable("LLVMGenericValueToFloat supports only float and double."); } - return 0; // Not reached } void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal) { @@ -87,11 +108,14 @@ void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal) { /*===-- Operations on execution engines -----------------------------------===*/ -int LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE, - LLVMModuleProviderRef MP, - char **OutError) { +LLVMBool LLVMCreateExecutionEngineForModule(LLVMExecutionEngineRef *OutEE, + LLVMModuleRef M, + char **OutError) { std::string Error; - if (ExecutionEngine *EE = ExecutionEngine::create(unwrap(MP), false, &Error)){ + EngineBuilder builder(unwrap(M)); + builder.setEngineKind(EngineKind::Either) + .setErrorStr(&Error); + if (ExecutionEngine *EE = builder.create()){ *OutEE = wrap(EE); return 0; } @@ -99,12 +123,14 @@ int LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE, return 1; } -int LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp, - LLVMModuleProviderRef MP, - char **OutError) { +LLVMBool LLVMCreateInterpreterForModule(LLVMExecutionEngineRef *OutInterp, + LLVMModuleRef M, + char **OutError) { std::string Error; - if (ExecutionEngine *Interp = - ExecutionEngine::create(unwrap(MP), true, &Error)) { + EngineBuilder builder(unwrap(M)); + builder.setEngineKind(EngineKind::Interpreter) + .setErrorStr(&Error); + if (ExecutionEngine *Interp = builder.create()) { *OutInterp = wrap(Interp); return 0; } @@ -112,14 +138,16 @@ int LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp, return 1; } -int LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT, - LLVMModuleProviderRef MP, - unsigned OptLevel, - char **OutError) { +LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, + LLVMModuleRef M, + unsigned OptLevel, + char **OutError) { std::string Error; - if (ExecutionEngine *JIT = - ExecutionEngine::create(unwrap(MP), false, &Error, - (CodeGenOpt::Level)OptLevel)) { + EngineBuilder builder(unwrap(M)); + builder.setEngineKind(EngineKind::JIT) + .setErrorStr(&Error) + .setOptLevel((CodeGenOpt::Level)OptLevel); + if (ExecutionEngine *JIT = builder.create()) { *OutJIT = wrap(JIT); return 0; } @@ -127,6 +155,88 @@ int LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT, 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.NoFramePointerElim = options.NoFramePointerElim; + targetOptions.EnableFastISel = options.EnableFastISel; + + std::string Error; + EngineBuilder builder(unwrap(M)); + builder.setEngineKind(EngineKind::JIT) + .setErrorStr(&Error) + .setUseMCJIT(true) + .setOptLevel((CodeGenOpt::Level)options.OptLevel) + .setCodeModel(unwrap(options.CodeModel)) + .setTargetOptions(targetOptions); + if (options.MCJMM) + builder.setMCJITMemoryManager(unwrap(options.MCJMM)); + if (ExecutionEngine *JIT = builder.create()) { + *OutJIT = wrap(JIT); + return 0; + } + *OutError = strdup(Error.c_str()); + 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); +} + +LLVMBool LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp, + LLVMModuleProviderRef MP, + char **OutError) { + /* The module provider is now actually a module. */ + return LLVMCreateInterpreterForModule(OutInterp, + reinterpret_cast(MP), + OutError); +} + +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); +} + + void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE) { delete unwrap(EE); } @@ -142,6 +252,8 @@ void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE) { int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F, unsigned ArgC, const char * const *ArgV, const char * const *EnvP) { + unwrap(EE)->finalizeObject(); + std::vector ArgVec; for (unsigned I = 0; I != ArgC; ++I) ArgVec.push_back(ArgV[I]); @@ -152,6 +264,8 @@ int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F, 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) @@ -166,25 +280,33 @@ 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){ - unwrap(EE)->addModuleProvider(unwrap(MP)); + /* The module provider is now actually a module. */ + LLVMAddModule(EE, reinterpret_cast(MP)); } -int LLVMRemoveModuleProvider(LLVMExecutionEngineRef EE, - LLVMModuleProviderRef MP, - LLVMModuleRef *OutMod, char **OutError) { - std::string Error; - if (Module *Gone = unwrap(EE)->removeModuleProvider(unwrap(MP), &Error)) { - *OutMod = wrap(Gone); - return 0; - } - if (OutError) - *OutError = strdup(Error.c_str()); - return 1; +LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M, + LLVMModuleRef *OutMod, char **OutError) { + Module *Mod = unwrap(M); + unwrap(EE)->removeModule(Mod); + *OutMod = wrap(Mod); + return 0; } -int LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, - LLVMValueRef *OutFn) { +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)) { *OutFn = wrap(F); return 0; @@ -192,8 +314,13 @@ int LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, return 1; } +void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, + LLVMValueRef Fn) { + return unwrap(EE)->recompileAndRelinkFunction(unwrap(Fn)); +} + LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) { - return wrap(unwrap(EE)->getTargetData()); + return wrap(unwrap(EE)->getDataLayout()); } void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, @@ -202,5 +329,114 @@ void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, } void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) { + unwrap(EE)->finalizeObject(); + return unwrap(EE)->getPointerToGlobal(unwrap(Global)); } + +/*===-- Operations on memory managers -------------------------------------===*/ + +namespace { + +struct SimpleBindingMMFunctions { + uint8_t *(*AllocateCodeSection)(void *Opaque, + uintptr_t Size, unsigned Alignment, + unsigned SectionID); + uint8_t *(*AllocateDataSection)(void *Opaque, + uintptr_t Size, unsigned Alignment, + unsigned SectionID, LLVMBool IsReadOnly); + LLVMBool (*FinalizeMemory)(void *Opaque, char **ErrMsg); + void (*Destroy)(void *Opaque); +}; + +class SimpleBindingMemoryManager : public RTDyldMemoryManager { +public: + SimpleBindingMemoryManager(const SimpleBindingMMFunctions& Functions, + void *Opaque); + virtual ~SimpleBindingMemoryManager(); + + virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); + + virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + bool isReadOnly); + + virtual bool finalizeMemory(std::string *ErrMsg); + +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) { + return Functions.AllocateCodeSection(Opaque, Size, Alignment, SectionID); +} + +uint8_t *SimpleBindingMemoryManager::allocateDataSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, bool isReadOnly) { + return Functions.AllocateDataSection(Opaque, Size, Alignment, SectionID, + isReadOnly); +} + +bool SimpleBindingMemoryManager::finalizeMemory(std::string *ErrMsg) { + char *errMsgCString = 0; + 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, + uint8_t *(*AllocateCodeSection)(void *Opaque, + uintptr_t Size, unsigned Alignment, + unsigned SectionID), + uint8_t *(*AllocateDataSection)(void *Opaque, + uintptr_t Size, unsigned Alignment, + unsigned SectionID, LLVMBool IsReadOnly), + LLVMBool (*FinalizeMemory)(void *Opaque, char **ErrMsg), + void (*Destroy)(void *Opaque)) { + + if (!AllocateCodeSection || !AllocateDataSection || !FinalizeMemory || + !Destroy) + return NULL; + + 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); +} +