| //===---------------- JIT.cc - Initialize the JIT -------------------------===// |
| // |
| // The Micro Virtual Machine |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/CallingConv.h" |
| #include <llvm/Constants.h> |
| #include <llvm/DerivedTypes.h> |
| #include <llvm/Instructions.h> |
| #include <llvm/Type.h> |
| #include "llvm/Support/MutexGuard.h" |
| #include "llvm/Target/TargetOptions.h" |
| |
| #include <stdio.h> |
| |
| #include "mvm/JIT.h" |
| #include "mvm/Method.h" |
| #include "mvm/MvmMemoryManager.h" |
| #include "mvm/Object.h" |
| #include "mvm/Threads/Thread.h" |
| |
| using namespace mvm; |
| using namespace mvm::jit; |
| using namespace llvm; |
| |
| |
| extern "C" void printFloat(float f) { |
| printf("%f\n", f); |
| } |
| |
| extern "C" void printDouble(double d) { |
| printf("%f\n", d); |
| } |
| |
| extern "C" void printLong(sint64 l) { |
| printf("%lld\n", l); |
| } |
| |
| extern "C" void printInt(sint32 i) { |
| printf("%d\n", i); |
| } |
| |
| extern "C" void printObject(mvm::Object* obj) { |
| printf("%s\n", obj->printString()); |
| } |
| |
| namespace mvm { |
| namespace llvm_runtime { |
| #include "LLVMRuntime.inc" |
| } |
| } |
| |
| void mvm::jit::initialise() { |
| llvm::NoFramePointerElim = true; |
| llvm::ExceptionHandling = true; |
| llvm::Module *module = globalModule = new Module("microvm"); |
| jit::globalModuleProvider = new ExistingModuleProvider (globalModule); |
| jit::memoryManager = new MvmMemoryManager(); |
| |
| executionEngine = ExecutionEngine::createJIT(globalModuleProvider, 0, |
| memoryManager); |
| std::string str = executionEngine->getTargetData()->getStringRepresentation(); |
| module->setDataLayout(str); |
| |
| mvm::llvm_runtime::makeLLVMModuleContents(module); |
| |
| printFloatLLVM = module->getFunction("printFloat"); |
| printDoubleLLVM = module->getFunction("printDouble"); |
| printLongLLVM = module->getFunction("printLong"); |
| printIntLLVM = module->getFunction("printInt"); |
| printObjectLLVM = module->getFunction("printObject"); |
| |
| unwindResume = module->getFunction("_Unwind_Resume_or_Rethrow"); |
| |
| llvmGetException = module->getFunction("llvm.eh.exception"); |
| exceptionSelector = sizeof(void*) == 4 ? |
| module->getFunction("llvm.eh.selector.i32") : |
| module->getFunction("llvm.eh.selector.i64"); |
| |
| personality = module->getFunction("__gxx_personality_v0"); |
| exceptionEndCatch = module->getFunction("__cxa_end_catch"); |
| exceptionBeginCatch = module->getFunction("__cxa_begin_catch"); |
| |
| func_llvm_sqrt_f64 = module->getFunction("llvm.sqrt.f64"); |
| func_llvm_sin_f64 = module->getFunction("llvm.sin.f64"); |
| func_llvm_cos_f64 = module->getFunction("llvm.cos.f64"); |
| |
| func_llvm_tan_f64 = module->getFunction("tan"); |
| func_llvm_asin_f64 = module->getFunction("asin"); |
| func_llvm_acos_f64 = module->getFunction("acos"); |
| func_llvm_atan_f64 = module->getFunction("atan"); |
| func_llvm_exp_f64 = module->getFunction("exp"); |
| func_llvm_log_f64 = module->getFunction("log"); |
| func_llvm_ceil_f64 = module->getFunction("ceil"); |
| func_llvm_floor_f64 = module->getFunction("floor"); |
| func_llvm_cbrt_f64 = module->getFunction("cbrt"); |
| func_llvm_cosh_f64 = module->getFunction("cosh"); |
| func_llvm_expm1_f64 = module->getFunction("expm1"); |
| func_llvm_log10_f64 = module->getFunction("log10"); |
| func_llvm_log1p_f64 = module->getFunction("log1p"); |
| func_llvm_sinh_f64 = module->getFunction("sinh"); |
| func_llvm_tanh_f64 = module->getFunction("tanh"); |
| func_llvm_fabs_f64 = module->getFunction("fabs"); |
| func_llvm_rint_f64 = module->getFunction("rint"); |
| |
| func_llvm_hypot_f64 = module->getFunction("hypot"); |
| func_llvm_pow_f64 = module->getFunction("pow"); |
| func_llvm_atan2_f64 = module->getFunction("atan2"); |
| |
| func_llvm_fabs_f32 = module->getFunction("fabsf"); |
| |
| setjmpLLVM = module->getFunction("setjmp"); |
| |
| llvm_memcpy_i32 = module->getFunction("llvm.memcpy.i32"); |
| llvm_memset_i32 = module->getFunction("llvm.memset.i32"); |
| |
| llvm_atomic_lcs_i8 = module->getFunction("llvm.atomic.cmp.swap.i8.p0i8"); |
| llvm_atomic_lcs_i16 = module->getFunction("llvm.atomic.cmp.swap.i16.p0i16"); |
| llvm_atomic_lcs_i32 = module->getFunction("llvm.atomic.cmp.swap.i32.p0i32"); |
| llvm_atomic_lcs_i64 = module->getFunction("llvm.atomic.cmp.swap.i64.p0i64"); |
| |
| llvm_atomic_cmp_swap_i8 = (uint8 (*)(uint8*, uint8, uint8)) |
| (uintptr_t)executionEngine->getPointerToFunction( |
| module->getFunction("runtime.llvm.atomic.cmp.swap.i8")); |
| llvm_atomic_cmp_swap_i16 = (uint16 (*)(uint16*, uint16, uint16)) |
| (uintptr_t)executionEngine->getPointerToFunction( |
| module->getFunction("runtime.llvm.atomic.cmp.swap.i16")); |
| llvm_atomic_cmp_swap_i32 = (uint32 (*)(uint32*, uint32, uint32)) |
| (uintptr_t)executionEngine->getPointerToFunction( |
| module->getFunction("runtime.llvm.atomic.cmp.swap.i32")); |
| llvm_atomic_cmp_swap_i64 = (uint64 (*)(uint64*, uint64, uint64)) |
| (uintptr_t)executionEngine->getPointerToFunction( |
| module->getFunction("runtime.llvm.atomic.cmp.swap.i64")); |
| |
| executionEnvironment = module->getGlobalVariable("executionEnvironment"); |
| getExecutionEnvironment = (mvm::Thread* (*)()) |
| (uintptr_t)executionEngine->getPointerToFunction( |
| module->getFunction("getExecutionEnvironment")); |
| setExecutionEnvironment = (void (*)(mvm::Thread*)) |
| (uintptr_t)executionEngine->getPointerToFunction( |
| module->getFunction("setExecutionEnvironment")); |
| |
| // Type declaration |
| ptrType = PointerType::getUnqual(Type::Int8Ty); |
| ptr32Type = PointerType::getUnqual(Type::Int32Ty); |
| ptrPtrType = PointerType::getUnqual(ptrType); |
| |
| // Constant declaration |
| constantLongMinusOne = ConstantInt::get(Type::Int64Ty, (uint64_t)-1); |
| constantLongZero = ConstantInt::get(Type::Int64Ty, 0); |
| constantLongOne = ConstantInt::get(Type::Int64Ty, 1); |
| constantZero = ConstantInt::get(Type::Int32Ty, 0); |
| constantInt8Zero = ConstantInt::get(Type::Int8Ty, 0); |
| constantOne = ConstantInt::get(Type::Int32Ty, 1); |
| constantTwo = ConstantInt::get(Type::Int32Ty, 2); |
| constantThree = ConstantInt::get(Type::Int32Ty, 3); |
| constantFour = ConstantInt::get(Type::Int32Ty, 4); |
| constantFive = ConstantInt::get(Type::Int32Ty, 5); |
| constantSix = ConstantInt::get(Type::Int32Ty, 6); |
| constantSeven = ConstantInt::get(Type::Int32Ty, 7); |
| constantEight = ConstantInt::get(Type::Int32Ty, 8); |
| constantMinusOne = ConstantInt::get(Type::Int32Ty, (uint64_t)-1); |
| constantMinInt = ConstantInt::get(Type::Int32Ty, MinInt); |
| constantMaxInt = ConstantInt::get(Type::Int32Ty, MaxInt); |
| constantMinLong = ConstantInt::get(Type::Int64Ty, MinLong); |
| constantMaxLong = ConstantInt::get(Type::Int64Ty, MaxLong); |
| constantFloatZero = ConstantFP::get(Type::FloatTy, 0.0f); |
| constantFloatOne = ConstantFP::get(Type::FloatTy, 1.0f); |
| constantFloatTwo = ConstantFP::get(Type::FloatTy, 2.0f); |
| constantDoubleZero = ConstantFP::get(Type::DoubleTy, 0.0); |
| constantDoubleOne = ConstantFP::get(Type::DoubleTy, 1.0); |
| constantMaxIntFloat = ConstantFP::get(Type::FloatTy, MaxIntFloat); |
| constantMinIntFloat = ConstantFP::get(Type::FloatTy, MinIntFloat); |
| constantMinLongFloat = ConstantFP::get(Type::FloatTy, MinLongFloat); |
| constantMinLongDouble = ConstantFP::get(Type::DoubleTy, MinLongDouble); |
| constantMaxLongFloat = ConstantFP::get(Type::FloatTy, MaxLongFloat); |
| constantMaxIntDouble = ConstantFP::get(Type::DoubleTy, MaxIntDouble); |
| constantMinIntDouble = ConstantFP::get(Type::DoubleTy, MinIntDouble); |
| constantMaxLongDouble = ConstantFP::get(Type::DoubleTy, MaxLongDouble); |
| constantMaxLongDouble = ConstantFP::get(Type::DoubleTy, MaxLongDouble); |
| constantFloatInfinity = ConstantFP::get(Type::FloatTy, MaxFloat); |
| constantFloatMinusInfinity = ConstantFP::get(Type::FloatTy, MinFloat); |
| constantDoubleInfinity = ConstantFP::get(Type::DoubleTy, MaxDouble); |
| constantDoubleMinusInfinity = ConstantFP::get(Type::DoubleTy, MinDouble); |
| constantDoubleMinusZero = ConstantFP::get(Type::DoubleTy, -0.0); |
| constantFloatMinusZero = ConstantFP::get(Type::FloatTy, -0.0f); |
| |
| constantPtrNull = Constant::getNullValue(ptrType); |
| constantPtrSize = ConstantInt::get(Type::Int32Ty, sizeof(void*)); |
| arrayPtrType = PointerType::getUnqual(ArrayType::get(Type::Int8Ty, 0)); |
| |
| mvm::jit::protectEngine = mvm::Lock::allocNormal(); |
| |
| } |
| |
| llvm::Function* mvm::jit::llvm_memcpy_i32; |
| llvm::Function* mvm::jit::llvm_memset_i32; |
| |
| llvm::Function* mvm::jit::llvm_atomic_lcs_i8; |
| llvm::Function* mvm::jit::llvm_atomic_lcs_i16; |
| llvm::Function* mvm::jit::llvm_atomic_lcs_i32; |
| llvm::Function* mvm::jit::llvm_atomic_lcs_i64; |
| |
| |
| llvm::Function* mvm::jit::exceptionEndCatch; |
| llvm::Function* mvm::jit::exceptionBeginCatch; |
| llvm::Function* mvm::jit::unwindResume; |
| llvm::Function* mvm::jit::exceptionSelector; |
| llvm::Function* mvm::jit::personality; |
| llvm::Function* mvm::jit::llvmGetException; |
| |
| llvm::Function* mvm::jit::printFloatLLVM; |
| llvm::Function* mvm::jit::printDoubleLLVM; |
| llvm::Function* mvm::jit::printLongLLVM; |
| llvm::Function* mvm::jit::printIntLLVM; |
| llvm::Function* mvm::jit::printObjectLLVM; |
| |
| llvm::Function* mvm::jit::setjmpLLVM; |
| |
| llvm::Function* mvm::jit::func_llvm_fabs_f32; |
| llvm::Function* mvm::jit::func_llvm_fabs_f64; |
| llvm::Function* mvm::jit::func_llvm_sqrt_f64; |
| llvm::Function* mvm::jit::func_llvm_sin_f64; |
| llvm::Function* mvm::jit::func_llvm_cos_f64; |
| llvm::Function* mvm::jit::func_llvm_tan_f64; |
| llvm::Function* mvm::jit::func_llvm_asin_f64; |
| llvm::Function* mvm::jit::func_llvm_acos_f64; |
| llvm::Function* mvm::jit::func_llvm_atan_f64; |
| llvm::Function* mvm::jit::func_llvm_atan2_f64; |
| llvm::Function* mvm::jit::func_llvm_exp_f64; |
| llvm::Function* mvm::jit::func_llvm_log_f64; |
| llvm::Function* mvm::jit::func_llvm_pow_f64; |
| llvm::Function* mvm::jit::func_llvm_ceil_f64; |
| llvm::Function* mvm::jit::func_llvm_floor_f64; |
| llvm::Function* mvm::jit::func_llvm_rint_f64; |
| llvm::Function* mvm::jit::func_llvm_cbrt_f64; |
| llvm::Function* mvm::jit::func_llvm_cosh_f64; |
| llvm::Function* mvm::jit::func_llvm_expm1_f64; |
| llvm::Function* mvm::jit::func_llvm_hypot_f64; |
| llvm::Function* mvm::jit::func_llvm_log10_f64; |
| llvm::Function* mvm::jit::func_llvm_log1p_f64; |
| llvm::Function* mvm::jit::func_llvm_sinh_f64; |
| llvm::Function* mvm::jit::func_llvm_tanh_f64; |
| |
| llvm::ExecutionEngine* mvm::jit::executionEngine; |
| |
| mvm::Lock* mvm::jit::protectEngine; |
| llvm::ConstantInt* mvm::jit::constantInt8Zero; |
| llvm::ConstantInt* mvm::jit::constantZero; |
| llvm::ConstantInt* mvm::jit::constantOne; |
| llvm::ConstantInt* mvm::jit::constantTwo; |
| llvm::ConstantInt* mvm::jit::constantThree; |
| llvm::ConstantInt* mvm::jit::constantFour; |
| llvm::ConstantInt* mvm::jit::constantFive; |
| llvm::ConstantInt* mvm::jit::constantSix; |
| llvm::ConstantInt* mvm::jit::constantSeven; |
| llvm::ConstantInt* mvm::jit::constantEight; |
| llvm::ConstantInt* mvm::jit::constantMinusOne; |
| llvm::ConstantInt* mvm::jit::constantLongMinusOne; |
| llvm::ConstantInt* mvm::jit::constantLongZero; |
| llvm::ConstantInt* mvm::jit::constantLongOne; |
| llvm::ConstantInt* mvm::jit::constantMinInt; |
| llvm::ConstantInt* mvm::jit::constantMaxInt; |
| llvm::ConstantInt* mvm::jit::constantMinLong; |
| llvm::ConstantInt* mvm::jit::constantMaxLong; |
| llvm::ConstantFP* mvm::jit::constantFloatZero; |
| llvm::ConstantFP* mvm::jit::constantFloatOne; |
| llvm::ConstantFP* mvm::jit::constantFloatTwo; |
| llvm::ConstantFP* mvm::jit::constantDoubleZero; |
| llvm::ConstantFP* mvm::jit::constantDoubleOne; |
| llvm::ConstantFP* mvm::jit::constantMaxIntFloat; |
| llvm::ConstantFP* mvm::jit::constantMinIntFloat; |
| llvm::ConstantFP* mvm::jit::constantMinLongFloat; |
| llvm::ConstantFP* mvm::jit::constantMinLongDouble; |
| llvm::ConstantFP* mvm::jit::constantMaxLongFloat; |
| llvm::ConstantFP* mvm::jit::constantMaxIntDouble; |
| llvm::ConstantFP* mvm::jit::constantMinIntDouble; |
| llvm::ConstantFP* mvm::jit::constantMaxLongDouble; |
| llvm::ConstantFP* mvm::jit::constantDoubleInfinity; |
| llvm::ConstantFP* mvm::jit::constantDoubleMinusInfinity; |
| llvm::ConstantFP* mvm::jit::constantFloatInfinity; |
| llvm::ConstantFP* mvm::jit::constantFloatMinusInfinity; |
| llvm::ConstantFP* mvm::jit::constantFloatMinusZero; |
| llvm::ConstantFP* mvm::jit::constantDoubleMinusZero; |
| llvm::Constant* mvm::jit::constantPtrNull; |
| llvm::ConstantInt* mvm::jit::constantPtrSize; |
| const llvm::PointerType* mvm::jit::ptrType; |
| const llvm::PointerType* mvm::jit::ptr32Type; |
| const llvm::PointerType* mvm::jit::ptrPtrType; |
| const llvm::Type* mvm::jit::arrayPtrType; |
| |
| llvm::Module *mvm::jit::globalModule; |
| llvm::ExistingModuleProvider *mvm::jit::globalModuleProvider; |
| mvm::MvmMemoryManager *mvm::jit::memoryManager; |
| |
| |
| uint8 (*mvm::jit::llvm_atomic_cmp_swap_i8) (uint8* ptr, uint8 cmp, |
| uint8 val); |
| uint16 (*mvm::jit::llvm_atomic_cmp_swap_i16) (uint16* ptr, uint16 cmp, |
| uint16 val); |
| uint32 (*mvm::jit::llvm_atomic_cmp_swap_i32) (uint32* ptr, uint32 cmp, |
| uint32 val); |
| uint64 (*mvm::jit::llvm_atomic_cmp_swap_i64) (uint64* ptr, uint64 cmp, |
| uint64 val); |
| |
| |
| llvm::GlobalVariable* mvm::jit::executionEnvironment; |
| mvm::Thread* (*mvm::jit::getExecutionEnvironment)(); |
| void (*mvm::jit::setExecutionEnvironment)(mvm::Thread*); |
| |
| uint64 mvm::jit::getTypeSize(const llvm::Type* type) { |
| return executionEngine->getTargetData()->getABITypeSize(type); |
| } |
| |
| void mvm::jit::runPasses(llvm::Function* func, llvm::FunctionPassManager* pm) { |
| pm->run(*func); |
| } |
| |
| #if defined(__MACH__) && !defined(__i386__) |
| #define FRAME_IP(fp) (fp[2]) |
| #else |
| #define FRAME_IP(fp) (fp[1]) |
| #endif |
| |
| int mvm::jit::getBacktrace(void** stack, int size) { |
| void** addr = (void**)__builtin_frame_address(0); |
| int cpt = 0; |
| void* baseSP = mvm::Thread::get()->baseSP; |
| while (addr && cpt < size && addr < baseSP && addr < addr[0]) { |
| addr = (void**)addr[0]; |
| stack[cpt++] = (void**)FRAME_IP(addr); |
| } |
| return cpt; |
| } |
| |
| LockNormal lock; |
| std::map<void*, Code*> pointerMap; |
| |
| Code* mvm::jit::getCodeFromPointer(void* Addr) { |
| lock.lock(); |
| std::map<void*, Code*>::iterator I = |
| pointerMap.lower_bound(Addr); |
| |
| lock.unlock(); |
| if (I != pointerMap.end()) { |
| Code* m = I->second; |
| if (Addr >= m->FunctionStart) return m; |
| } |
| |
| return 0; |
| } |
| |
| void mvm::jit::addMethodInfo(void* Addr, Code* C) { |
| lock.lock(); |
| pointerMap.insert(std::make_pair(Addr, C)); |
| lock.unlock(); |
| } |