blob: 9dc0c6bce951f49eb4578ddef01b5cf95051b92a [file] [log] [blame]
//===---------------- 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();
}