// // mini-llvm-cpp.cpp: C++ support classes for the mono LLVM integration // // (C) 2009 Novell, Inc. // // // We need to override some stuff in LLVM, but this cannot be done using the C // interface, so we have to use some C++ code here. // The things which we override are: // - the default JIT code manager used by LLVM doesn't allocate memory using // MAP_32BIT, we require it. // - add some callbacks so we can obtain the size of methods and their exception // tables. // // // Mono's internal header files are not C++ clean, so avoid including them if // possible // #include #include #include #include #include #include #include #include #include "llvm-c/Core.h" #include "llvm-c/ExecutionEngine.h" #include "mini-llvm-cpp.h" using namespace llvm; class MonoJITMemoryManager : public JITMemoryManager { private: JITMemoryManager *mm; public: /* Callbacks installed by mono */ AllocCodeMemoryCb *alloc_cb; FunctionEmittedCb *emitted_cb; MonoJITMemoryManager (); ~MonoJITMemoryManager (); void setMemoryWritable (void); void setMemoryExecutable (void); void AllocateGOT(); unsigned char *getGOTBase() const { return mm->getGOTBase (); } void *getDlsymTable() const { return mm->getDlsymTable (); } void SetDlsymTable(void *ptr); unsigned char *startFunctionBody(const Function *F, uintptr_t &ActualSize); unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize, unsigned Alignment); void endFunctionBody(const Function *F, unsigned char *FunctionStart, unsigned char *FunctionEnd); unsigned char *allocateSpace(intptr_t Size, unsigned Alignment); void deallocateMemForFunction(const Function *F); unsigned char*startExceptionTable(const Function* F, uintptr_t &ActualSize); void endExceptionTable(const Function *F, unsigned char *TableStart, unsigned char *TableEnd, unsigned char* FrameRegister); }; MonoJITMemoryManager::MonoJITMemoryManager () { SizeRequired = true; mm = JITMemoryManager::CreateDefaultMemManager (); } MonoJITMemoryManager::~MonoJITMemoryManager () { } void MonoJITMemoryManager::setMemoryWritable (void) { } void MonoJITMemoryManager::setMemoryExecutable (void) { } void MonoJITMemoryManager::AllocateGOT() { mm->AllocateGOT (); } void MonoJITMemoryManager::SetDlsymTable(void *ptr) { mm->SetDlsymTable (ptr); } unsigned char * MonoJITMemoryManager::startFunctionBody(const Function *F, uintptr_t &ActualSize) { return alloc_cb (wrap (F), ActualSize); } unsigned char * MonoJITMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize, unsigned Alignment) { return alloc_cb (wrap (F), StubSize); } void MonoJITMemoryManager::endFunctionBody(const Function *F, unsigned char *FunctionStart, unsigned char *FunctionEnd) { emitted_cb (wrap (F), FunctionStart, FunctionEnd); } unsigned char * MonoJITMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) { return new unsigned char [Size]; } void MonoJITMemoryManager::deallocateMemForFunction(const Function *F) { } unsigned char* MonoJITMemoryManager::startExceptionTable(const Function* F, uintptr_t &ActualSize) { return alloc_cb (wrap (F), ActualSize); } void MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableStart, unsigned char *TableEnd, unsigned char* FrameRegister) { } static MonoJITMemoryManager *mono_mm; static FunctionPassManager *fpm; void mono_llvm_optimize_method (LLVMValueRef method) { verifyFunction (*(unwrap (method))); fpm->run (*unwrap (method)); } /* Missing overload for building an alloca with an alignment */ LLVMValueRef mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, LLVMValueRef ArraySize, int alignment, const char *Name) { return wrap (unwrap (builder)->Insert (new AllocaInst(unwrap (Ty), unwrap (ArraySize), alignment), Name)); } LLVMValueRef LLVMBuildArrayAlloca(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Val, const char *Name); LLVMExecutionEngineRef mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb) { std::string Error; mono_mm = new MonoJITMemoryManager (); mono_mm->alloc_cb = alloc_cb; mono_mm->emitted_cb = emitted_cb; ExceptionHandling = true; ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, false); EE->InstallExceptionTableRegister (exception_cb); fpm = new FunctionPassManager (unwrap (MP)); fpm->add(new TargetData(*EE->getTargetData())); /* Add a random set of passes */ /* Make this run-time configurable */ fpm->add(createInstructionCombiningPass()); fpm->add(createReassociatePass()); fpm->add(createGVNPass()); fpm->add(createCFGSimplificationPass()); return wrap(EE); }