Expose the RTDyldMemoryManager through the C API. This allows clients of
[oota-llvm.git] / lib / ExecutionEngine / ExecutionEngineBindings.cpp
index f9b08a01ea7d61b0ad942dc7c9dcf3d25f7a7ba7..88e73bf253e496d2d46d316b714237212751569a 100644 (file)
@@ -15,6 +15,7 @@
 #include "llvm-c/ExecutionEngine.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"
@@ -157,10 +158,8 @@ LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
 void LLVMInitializeMCJITCompilerOptions(LLVMMCJITCompilerOptions *PassedOptions,
                                         size_t SizeOfPassedOptions) {
   LLVMMCJITCompilerOptions options;
-  options.OptLevel = 0;
+  memset(&options, 0, sizeof(options)); // Most fields are zero by default.
   options.CodeModel = LLVMCodeModelJITDefault;
-  options.NoFramePointerElim = false;
-  options.EnableFastISel = false;
   
   memcpy(PassedOptions, &options,
          std::min(sizeof(options), SizeOfPassedOptions));
@@ -199,6 +198,8 @@ LLVMBool LLVMCreateMCJITCompilerForModule(
          .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;
@@ -332,3 +333,110 @@ void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) {
   
   return unwrap(EE)->getPointerToGlobal(unwrap<GlobalValue>(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);
+}
+