diff --git a/deps/Makefile b/deps/Makefile index 74e05914cd0bf..d5c71f9dccacc 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -182,7 +182,6 @@ LLVM_TAR=llvm-$(LLVM_VER).tar.gz else LLVM_TAR=llvm-$(LLVM_VER).src.tar.gz endif -endif ifeq ($(BUILD_LLVM_CLANG),1) ifeq ($(LLVM_VER), 3.0) @@ -202,6 +201,7 @@ LLVM_CLANG_TAR= LLVM_COMPILER_RT_TAR= LLVM_LIBCXX_TAR= endif +endif LLVM_TARGET_FLAGS= --enable-targets=host LLVM_FLAGS = --disable-profiling --enable-shared --enable-static $(LLVM_TARGET_FLAGS) --disable-bindings --disable-docs diff --git a/src/Makefile b/src/Makefile index 98258723ae9bc..48c7e7a12679f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,7 +16,7 @@ FLAGS = \ -I$(call exec,$(LLVM_CONFIG) --includedir) \ -I$(LIBUV_INC) -I$(JULIAHOME)/usr/include -DLIBRARY_EXPORTS -LLVMLINK = $(call exec,$(LLVM_CONFIG) --libs) +LLVMLINK = $(call exec,$(LLVM_CONFIG) --libs) $(call exec,$(LLVM_CONFIG) --system-libs 2> /dev/null) ifeq ($(USE_LLVM_SHLIB),1) LLVMLINK = -lLLVM-$(LLVM_VER) endif diff --git a/src/ccall.cpp b/src/ccall.cpp index 57aa65a664ae2..9d1ed1401dac1 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -124,14 +124,19 @@ static Value *runtime_sym_lookup(PointerType *funcptype, char *f_lib, char *f_na bool runtime_lib = false; GlobalVariable *libptrgv; #ifdef _OS_WINDOWS_ - if ((intptr_t)f_lib == 1) - libptrgv = jlexe_var; - else if ((intptr_t)f_lib == 2) - libptrgv = jldll_var; + if ((intptr_t)f_lib == 1) { + libptrgv = prepare_global(jlexe_var); + libsym = jl_exe_handle; + } + else if ((intptr_t)f_lib == 2) { + libptrgv = prepare_global(jldll_var); + libsym = jl_dll_handle; + } else #endif if (f_lib == NULL) { - libptrgv = jlRTLD_DEFAULT_var; + libptrgv = prepare_global(jlRTLD_DEFAULT_var); + libsym = jl_RTLD_DEFAULT_handle; } else { runtime_lib = true; @@ -142,20 +147,39 @@ static Value *runtime_sym_lookup(PointerType *funcptype, char *f_lib, char *f_na initnul, f_lib); libMapGV[f_lib] = libptrgv; libsym = get_library(f_lib); + assert(libsym != NULL); +#ifdef USE_MCJIT + llvm_to_jl_value[libptrgv] = libsym; +#else *((uv_lib_t**)jl_ExecutionEngine->getPointerToGlobal(libptrgv)) = libsym; +#endif } } if (libsym == NULL) { +#ifdef USE_MCJIT + libsym = (uv_lib_t*)llvm_to_jl_value[libptrgv]; +#else libsym = *((uv_lib_t**)jl_ExecutionEngine->getPointerToGlobal(libptrgv)); +#endif } + assert(libsym != NULL); + GlobalVariable *llvmgv = symMapGV[f_name]; if (llvmgv == NULL) { + // MCJIT forces this to have external linkage eventually, so we would clobber + // the symbol of the actual function. + std::string name = f_name; + name = "ccall_" + name; llvmgv = new GlobalVariable(*jl_Module, T_pint8, false, GlobalVariable::PrivateLinkage, - initnul, f_name); + initnul, name); symMapGV[f_name] = llvmgv; +#ifdef USE_MCJIT + llvm_to_jl_value[llvmgv] = jl_dlsym_e(libsym, f_name); +#else *((void**)jl_ExecutionEngine->getPointerToGlobal(llvmgv)) = jl_dlsym_e(libsym, f_name); +#endif } BasicBlock *dlsym_lookup = BasicBlock::Create(getGlobalContext(), "dlsym"), @@ -171,7 +195,7 @@ static Value *runtime_sym_lookup(PointerType *funcptype, char *f_lib, char *f_na else { libname = literal_static_pointer_val(f_lib, T_pint8); } - Value *llvmf = builder.CreateCall3(jldlsym_func, libname, builder.CreateGlobalStringPtr(f_name), libptrgv); + Value *llvmf = builder.CreateCall3(prepare_call(jldlsym_func), libname, builder.CreateGlobalStringPtr(f_name), libptrgv); builder.CreateStore(llvmf, llvmgv); builder.CreateBr(ccall_bb); @@ -354,7 +378,7 @@ static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv, return builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), ty); // skip type tag field } *mightNeedTempSpace = true; - Value *p = builder.CreateCall4(value_to_pointer_func, + Value *p = builder.CreateCall4(prepare_call(value_to_pointer_func), literal_pointer_val(jl_tparam0(jt)), jv, ConstantInt::get(T_int32, argn), ConstantInt::get(T_int32, (int)addressOf)); @@ -758,10 +782,10 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) msg << f_lib; } msg << "\n"; - builder.CreateCall2(jlputs_func, + builder.CreateCall2(prepare_call(jlputs_func), builder.CreateGEP(stringConst(msg.str()), ArrayRef(zeros)), - jlstderr_var); + prepare_global(jlstderr_var)); } // emit arguments @@ -770,7 +794,7 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) if (sret) { assert(jl_is_structtype(rt)); result = builder.CreateCall( - jlallocobj_func, + prepare_call(jlallocobj_func), ConstantInt::get(T_size, sizeof(void*)+((jl_datatype_t*)rt)->size)); //TODO: Fill type pointer fields with C_NULL's @@ -894,7 +918,7 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) if (needTempSpace) { // save temp argument area stack pointer // TODO: inline this - saveloc = CallInst::Create(save_arg_area_loc_func); + saveloc = CallInst::Create(prepare_call(save_arg_area_loc_func)); if (savespot) instList.insertAfter(savespot, (Instruction*)saveloc); else @@ -912,7 +936,7 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) // the actual call Value *ret = builder.CreateCall( - llvmf, + prepare_call(llvmf), ArrayRef(&argvals[0],(nargs-3)/2+sret)); attr_type attributes; @@ -944,7 +968,7 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) if (needTempSpace) { // restore temp argument area stack pointer assert(saveloc != NULL); - builder.CreateCall(restore_arg_area_loc_func, saveloc); + builder.CreateCall(prepare_call(restore_arg_area_loc_func), saveloc); } ctx->argDepth = last_depth; if (0) { // Enable this to turn on SSPREQ (-fstack-protector) on the function containing this ccall @@ -962,7 +986,7 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) //fprintf(stderr, "ccall rt: %s -> %s\n", f_name, ((jl_tag_type_t*)rt)->name->name->name); assert(jl_is_structtype(rt)); Value *strct = - builder.CreateCall(jlallocobj_func, + builder.CreateCall(prepare_call(jlallocobj_func), ConstantInt::get(T_size, sizeof(void*)+((jl_datatype_t*)rt)->size)); builder.CreateStore(literal_pointer_val((jl_value_t*)rt), diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 8fd27e5048445..f6780b9967937 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1,5 +1,54 @@ // utility procedures used in code generation +// Fixing up references to other modules for MCJIT +static GlobalVariable *prepare_global(GlobalVariable *G) +{ +#ifdef USE_MCJIT + if(G->getParent() != jl_Module) { + GlobalVariable *gv = jl_Module->getGlobalVariable(G->getName()); + if(!gv) { + gv = + new GlobalVariable(*jl_Module, G->getType()->getElementType(), + true, GlobalVariable::ExternalLinkage, + NULL, G->getName()); + } + return gv; + } +#endif + return G; +} + +static llvm::Value *prepare_call(llvm::Value* Callee) +{ +#ifdef USE_MCJIT + llvm::Function *F = dyn_cast(Callee); + if (!F) + return Callee; + if (F->getParent() != jl_Module) { + Function *ModuleF = jl_Module->getFunction(F->getName()); + if(ModuleF) { + return ModuleF; + } + else { + return Function::Create(F->getFunctionType(), + Function::ExternalLinkage, + F->getName(), + jl_Module); + } + } +#endif + return Callee; +} + +static inline void add_named_global(GlobalValue *gv, void *addr) +{ +#ifdef USE_MCJIT + sys::DynamicLibrary::AddSymbol(gv->getName(),addr); +#else + jl_ExecutionEngine->addGlobalMapping(gv,addr); +#endif +} + // --- string constants --- static std::map stringConstants; @@ -16,7 +65,7 @@ static GlobalVariable *stringConst(const std::string &txt) gv = new GlobalVariable(*jl_Module, ArrayType::get(T_int8, txt.length()+1), true, - GlobalVariable::PrivateLinkage, + imaging_mode ? GlobalVariable::PrivateLinkage : GlobalVariable::ExternalLinkage, #ifndef LLVM_VERSION_MAJOR ConstantArray::get(getGlobalContext(), txt.c_str()), @@ -34,6 +83,114 @@ static GlobalVariable *stringConst(const std::string &txt) } +// --- Shadow module handling --- + +typedef struct {Value* gv; int32_t index;} jl_value_llvm; // uses 1-based indexing +static std::map jl_value_to_llvm; +static std::map llvm_to_jl_value; + +#ifdef USE_MCJIT +class FunctionMover; + +static Function *clone_llvm_function(llvm::Function *toClone,FunctionMover *mover); + +class FunctionMover : public ValueMaterializer +{ +public: + FunctionMover(llvm::Module *dest,llvm::Module *src) : + ValueMaterializer(), VMap(), destModule(dest), srcModule(src) + { + + } + ValueToValueMapTy VMap; + llvm::Module *destModule; + llvm::Module *srcModule; + virtual Value *materializeValueFor (Value *V) + { + Function *F = dyn_cast(V); + if(F) { + if(F->isIntrinsic()) { + return destModule->getOrInsertFunction(F->getName(),F->getFunctionType()); + } + if(F->isDeclaration() || F->getParent() != destModule) { + Function *shadow = srcModule->getFunction(F->getName()); + if (shadow != NULL && !shadow->isDeclaration()) { + // Not truly external + // Check whether we already emitted it once + uint64_t addr = jl_mcjmm->getSymbolAddress(F->getName()); + if (addr == 0) { + return clone_llvm_function(shadow,this); + } + else { + return destModule->getOrInsertFunction(F->getName(),F->getFunctionType()); + } + } + else if (!F->isDeclaration()) { + return clone_llvm_function(F,this); + } + } + // Still a declaration and still in a different module + if(F->isDeclaration() && F->getParent() != destModule) { + // Create forward declaration in current module + return destModule->getOrInsertFunction(F->getName(),F->getFunctionType()); + } + } + else if (isa(V)) { + GlobalVariable *GV = cast(V); + assert(GV != NULL); + GlobalVariable *newGV = new GlobalVariable(*destModule, + GV->getType()->getElementType(), + GV->isConstant(), + GlobalVariable::ExternalLinkage, + NULL, + GV->getName()); + newGV->copyAttributesFrom(GV); + if (GV->isDeclaration()) + return newGV; + uint64_t addr = jl_mcjmm->getSymbolAddress(GV->getName()); + if(addr != 0) { + newGV->setExternallyInitialized(true); + return newGV; + } + std::map::iterator it; + it = llvm_to_jl_value.find(GV); + if (it != llvm_to_jl_value.end()) { + newGV->setInitializer(Constant::getIntegerValue(GV->getType()->getElementType(),APInt(sizeof(void*)*8,(ptrint_t)it->second))); + newGV->setConstant(true); + } + else if (GV->hasInitializer()) { + Value *C = MapValue(GV->getInitializer(),VMap,RF_None,NULL,this); + newGV->setInitializer(cast(C)); + } + return newGV; + } + return NULL; + }; +}; + +static Function *clone_llvm_function(llvm::Function *toClone,FunctionMover *mover) +{ + Function *NewF = Function::Create(toClone->getFunctionType(), + Function::ExternalLinkage, + toClone->getName(), + mover->destModule); + ClonedCodeInfo info; + Function::arg_iterator DestI = NewF->arg_begin(); + for (Function::const_arg_iterator I = toClone->arg_begin(), E = toClone->arg_end(); I != E; ++I) { + DestI->setName(I->getName()); // Copy the name over... + mover->VMap[I] = DestI++; // Add mapping to VMap + } + + // Necessary in case the function is self referential + mover->VMap[toClone] = NewF; + + SmallVector Returns; + llvm::CloneFunctionInto(NewF,toClone,mover->VMap,true,Returns,"",NULL,NULL,mover); + + return NewF; +} +#endif + // --- emitting pointers directly into code --- static Value *literal_static_pointer_val(void *p, Type *t) @@ -48,8 +205,6 @@ static Value *literal_static_pointer_val(void *p, Type *t) #endif } -typedef struct {Value* gv; int32_t index;} jl_value_llvm; // uses 1-based indexing -static std::map jl_value_to_llvm; static std::vector jl_sysimg_gvars; extern "C" int32_t jl_get_llvm_gv(jl_value_t *p) @@ -94,11 +249,16 @@ static Value *julia_gv(const char *cname, void *addr) return builder.CreateLoad(it->second.gv); // no existing GlobalVariable, create one and store it GlobalValue *gv = new GlobalVariable(*jl_Module, jl_pvalue_llvmt, - false, GlobalVariable::InternalLinkage, + false, imaging_mode ? GlobalVariable::InternalLinkage : GlobalVariable::ExternalLinkage, ConstantPointerNull::get((PointerType*)jl_pvalue_llvmt), cname); + // make the pointer valid for this session +#ifdef USE_MCJIT + llvm_to_jl_value[gv] = addr; +#else void **p = (void**)jl_ExecutionEngine->getPointerToGlobal(gv); *p = addr; +#endif // make the pointer valid for future sessions jl_sysimg_gvars.push_back(ConstantExpr::getBitCast(gv, T_psize)); jl_value_llvm gv_struct; @@ -494,7 +654,7 @@ static void just_emit_error(const std::string &txt, jl_codectx_t *ctx) { Value *zeros[2] = { ConstantInt::get(T_int32, 0), ConstantInt::get(T_int32, 0) }; - builder.CreateCall(jlerror_func, + builder.CreateCall(prepare_call(jlerror_func), builder.CreateGEP(stringConst(txt), ArrayRef(zeros))); } @@ -525,7 +685,7 @@ static void raise_exception_unless(Value *cond, Value *exc, jl_codectx_t *ctx) BasicBlock *passBB = BasicBlock::Create(getGlobalContext(),"pass"); builder.CreateCondBr(cond, passBB, failBB); builder.SetInsertPoint(failBB); - builder.CreateCall2(jlthrow_line_func, exc, + builder.CreateCall2(prepare_call(jlthrow_line_func), exc, ConstantInt::get(T_int32, ctx->lineno)); builder.CreateUnreachable(); ctx->f->getBasicBlockList().push_back(passBB); @@ -553,7 +713,7 @@ static void raise_exception_if(Value *cond, GlobalVariable *exc, static void null_pointer_check(Value *v, jl_codectx_t *ctx) { raise_exception_unless(builder.CreateICmpNE(v,Constant::getNullValue(v->getType())), - jlundeferr_var, ctx); + prepare_global(jlundeferr_var), ctx); } static Value *boxed(Value *v, jl_codectx_t *ctx, jl_value_t *jt=NULL); @@ -567,7 +727,7 @@ static void emit_type_error(Value *x, jl_value_t *type, const std::string &msg, ArrayRef(zeros)); Value *msg_val = builder.CreateGEP(stringConst(msg), ArrayRef(zeros)); - builder.CreateCall4(jltypeerror_func, + builder.CreateCall4(prepare_call(jltypeerror_func), fname_val, msg_val, literal_pointer_val(type), boxed(x,ctx)); } @@ -597,7 +757,7 @@ static Value *emit_bounds_check(Value *i, Value *len, jl_codectx_t *ctx) #if CHECK_BOUNDS==1 if (ctx->boundsCheck.empty() || ctx->boundsCheck.back()==true) { Value *ok = builder.CreateICmpULT(im1, len); - raise_exception_unless(ok, jlboundserr_var, ctx); + raise_exception_unless(ok, prepare_global(jlboundserr_var), ctx); } #endif return im1; @@ -928,7 +1088,7 @@ static Value *emit_tupleref(Value *tuple, Value *ival, jl_value_t *jt, jl_codect else { for (i = 0; i < l; i++) { if (!jl_isbits(jl_tupleref(jt,i))) { - v = builder.CreateCall2(jlnewbits_func, lty, + v = builder.CreateCall2(prepare_call(jlnewbits_func), lty, builder.CreatePointerCast(v,T_pint8)); break; } @@ -955,7 +1115,7 @@ static Value *emit_tupleref(Value *tuple, Value *ival, jl_value_t *jt, jl_codect SwitchInst *sw = builder.CreateSwitch(ival,deflt,n); // Anything else is a bounds error builder.SetInsertPoint(deflt); - builder.CreateCall2(jlthrow_line_func, builder.CreateLoad(jlboundserr_var), + builder.CreateCall2(prepare_call(jlthrow_line_func), builder.CreateLoad(prepare_global(jlboundserr_var)), ConstantInt::get(T_int32, ctx->lineno)); builder.CreateUnreachable(); size_t ntuple = jl_tuple_len(jt); @@ -1061,7 +1221,7 @@ static Value *emit_arraylen_prim(Value *t, jl_value_t *ty) fargt.push_back(jl_pvalue_llvmt); FunctionType *ft = FunctionType::get(T_size, fargt, false); Value *alen = jl_Module->getOrInsertFunction("jl_array_len_", ft); - return builder.CreateCall(alen, t); + return builder.CreateCall(prepare_call(alen), t); } #endif } @@ -1150,7 +1310,7 @@ static Value *emit_array_nd_index(Value *a, jl_value_t *ex, size_t nd, jl_value_ ctx->f->getBasicBlockList().push_back(failBB); builder.SetInsertPoint(failBB); - builder.CreateCall2(jlthrow_line_func, builder.CreateLoad(jlboundserr_var), + builder.CreateCall2(prepare_call(jlthrow_line_func), builder.CreateLoad(prepare_global(jlboundserr_var)), ConstantInt::get(T_int32, ctx->lineno)); builder.CreateUnreachable(); @@ -1187,7 +1347,7 @@ static Value *allocate_box_dynamic(Value *jlty, Value *nb, Value *v) if (v->getType()->isPointerTy()) { v = builder.CreatePtrToInt(v, T_size); } - Value *newv = builder.CreateCall(jlallocobj_func, + Value *newv = builder.CreateCall(prepare_call(jlallocobj_func), builder.CreateAdd(nb, ConstantInt::get(T_size, sizeof(void*)))); // TODO: make sure this is rooted. I think it is. @@ -1303,7 +1463,7 @@ static Value *boxed(Value *v, jl_codectx_t *ctx, jl_value_t *jt) } if (jl_is_tuple(jt)) { size_t n = jl_tuple_len(jt); - Value *tpl = builder.CreateCall(jl_alloc_tuple_func,ConstantInt::get(T_size,n)); + Value *tpl = builder.CreateCall(prepare_call(jl_alloc_tuple_func),ConstantInt::get(T_size,n)); int last_depth = ctx->argDepth; make_gcroot(tpl,ctx); for (size_t i = 0; i < n; ++i) { @@ -1317,29 +1477,29 @@ static Value *boxed(Value *v, jl_codectx_t *ctx, jl_value_t *jt) jl_datatype_t *jb = (jl_datatype_t*)jt; assert(jl_is_datatype(jb)); if (jb == jl_int8_type) - return builder.CreateCall(box_int8_func, + return builder.CreateCall(prepare_call(box_int8_func), builder.CreateSExt(v, T_int32)); - if (jb == jl_int16_type) return builder.CreateCall(box_int16_func, v); - if (jb == jl_int32_type) return builder.CreateCall(box_int32_func, v); - if (jb == jl_int64_type) return builder.CreateCall(box_int64_func, v); - if (jb == jl_float32_type) return builder.CreateCall(box_float32_func, v); + if (jb == jl_int16_type) return builder.CreateCall(prepare_call(box_int16_func), v); + if (jb == jl_int32_type) return builder.CreateCall(prepare_call(box_int32_func), v); + if (jb == jl_int64_type) return builder.CreateCall(prepare_call(box_int64_func), v); + if (jb == jl_float32_type) return builder.CreateCall(prepare_call(box_float32_func), v); //if (jb == jl_float64_type) return builder.CreateCall(box_float64_func, v); if (jb == jl_float64_type) { // manually inline alloc & init of Float64 box. cheap, I know. #ifdef _P64 - Value *newv = builder.CreateCall(jlalloc2w_func); + Value *newv = builder.CreateCall(prepare_call(jlalloc2w_func)); #else - Value *newv = builder.CreateCall(jlalloc3w_func); + Value *newv = builder.CreateCall(prepare_call(jlalloc3w_func)); #endif return init_bits_value(newv, literal_pointer_val(jt), t, v); } if (jb == jl_uint8_type) - return builder.CreateCall(box_uint8_func, + return builder.CreateCall(prepare_call(box_uint8_func), builder.CreateZExt(v, T_int32)); - if (jb == jl_uint16_type) return builder.CreateCall(box_uint16_func, v); - if (jb == jl_uint32_type) return builder.CreateCall(box_uint32_func, v); - if (jb == jl_uint64_type) return builder.CreateCall(box_uint64_func, v); - if (jb == jl_char_type) return builder.CreateCall(box_char_func, v); + if (jb == jl_uint16_type) return builder.CreateCall(prepare_call(box_uint16_func), v); + if (jb == jl_uint32_type) return builder.CreateCall(prepare_call(box_uint32_func), v); + if (jb == jl_uint64_type) return builder.CreateCall(prepare_call(box_uint64_func), v); + if (jb == jl_char_type) return builder.CreateCall(prepare_call(box_char_func), v); if (!jl_isbits(jt)) { assert("Don't know how to box this type" && false); return NULL; diff --git a/src/codegen.cpp b/src/codegen.cpp index 144dc5a55b855..3492503ca3df8 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -34,6 +34,10 @@ #include "llvm/Bitcode/ReaderWriter.h" #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 4 #define LLVM34 1 +#define USE_MCJIT 1 +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/ADT/DenseMapInfo.h" #endif #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 3 #include "llvm/IR/DerivedTypes.h" @@ -115,8 +119,14 @@ void __attribute__(()) __stack_chk_fail() static LLVMContext &jl_LLVMContext = getGlobalContext(); static IRBuilder<> builder(getGlobalContext()); static bool nested_compile=false; -static Module *jl_Module; static ExecutionEngine *jl_ExecutionEngine; +#ifdef USE_MCJIT +static Module *shadow_module; +static RTDyldMemoryManager *jl_mcjmm; +#define jl_Module (builder.GetInsertBlock()->getParent()->getParent()) +#else +static Module *jl_Module; +#endif static std::map argNumberStrings; static FunctionPassManager *FPM; @@ -232,9 +242,125 @@ static Function *jlgetnthfieldchecked_func; static Function *resetstkoflw_func; #endif +// --- code generation --- + +// per-local-variable information +struct jl_varinfo_t { + Value *memvalue; // an address, if the var is alloca'd + Value *SAvalue; // register, if the var is SSA + Value *passedAs; // if an argument, the original passed value + int closureidx; // index in closure env, or -1 + bool isAssigned; + bool isCaptured; + bool isSA; + bool isVolatile; + bool isArgument; + bool isGhost; // Has size 0 and is thus never actually allocated + bool hasGCRoot; + bool escapes; + bool usedUndef; + bool used; + jl_value_t *declType; + jl_value_t *initExpr; // initializing expression for SSA variables + + jl_varinfo_t() : memvalue(NULL), SAvalue(NULL), passedAs(NULL), closureidx(-1), + isAssigned(true), isCaptured(false), isSA(false), isVolatile(false), + isArgument(false), isGhost(false), hasGCRoot(false), escapes(true), + usedUndef(false), used(false), + declType((jl_value_t*)jl_any_type), initExpr(NULL) + { + } +}; + +// --- helpers for reloading IR image +extern "C" +void jl_set_imaging_mode(int stat) +{ + imaging_mode = !!stat; +} + +static void jl_gen_llvm_gv_array(); + +extern "C" +void jl_dump_bitcode(char* fname) +{ + std::string err; + raw_fd_ostream OS(fname, err); + jl_gen_llvm_gv_array(); +#ifdef USE_MCJIT + WriteBitcodeToFile(shadow_module, OS); +#else + WriteBitcodeToFile(jl_Module, OS); +#endif +} + +// aggregate of array metadata +typedef struct { + Value *dataptr; + Value *len; + std::vector sizes; + jl_value_t *ty; +} jl_arrayvar_t; + +// information about the context of a piece of code: its enclosing +// function and module, and visible local variables and labels. +typedef struct { + Function *f; + // local var info. globals are not in here. + // NOTE: you must be careful not to access vars[s] before you are sure "s" is + // a local, since otherwise this will add it to the map. + std::map vars; + std::map *arrayvars; + std::map *labels; + std::map *handlers; + jl_module_t *module; + jl_expr_t *ast; + jl_tuple_t *sp; + jl_lambda_info_t *linfo; + Value *envArg; + Value *argArray; + Value *argCount; + Instruction *argTemp; + int argDepth; + int maxDepth; + int argSpaceOffs; + std::string funcName; + jl_sym_t *vaName; // name of vararg argument + bool vaStack; // varargs stack-allocated + int nReqArgs; + int lineno; + std::vector boundsCheck; +#ifdef JL_GC_MARKSWEEP + Instruction *gcframe ; + Instruction *argSpaceInits; + StoreInst *storeFrameSize; +#endif + BasicBlock::iterator first_gcframe_inst; + BasicBlock::iterator last_gcframe_inst; + llvm::DIBuilder *dbuilder; + std::vector gc_frame_pops; + std::vector to_inline; +} jl_codectx_t; + +static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool boxed=true, + bool valuepos=true); +static Value *emit_unboxed(jl_value_t *e, jl_codectx_t *ctx); +static int is_global(jl_sym_t *s, jl_codectx_t *ctx); +static Value *make_gcroot(Value *v, jl_codectx_t *ctx); +static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s, + jl_binding_t **pbnd, bool assign); +static Value *emit_checked_var(Value *bp, jl_sym_t *name, jl_codectx_t *ctx); +static bool might_need_root(jl_value_t *ex); +static Value *emit_condition(jl_value_t *cond, const std::string &msg, jl_codectx_t *ctx); + // NoopType static Type *NoopType; +// --- utilities --- + +#include "cgutils.cpp" + + static void jl_rethrow_with_add(const char *fmt, ...) { if (jl_typeis(jl_exception_in_transit, jl_errorexception_type)) { @@ -283,17 +409,21 @@ static Function *to_function(jl_lambda_info_t *li, bool cstyle) } assert(f != NULL); nested_compile = last_n_c; - //f->dump(); -#ifdef DEBUG - verifyFunction(*f); -#endif + #ifdef DEBUG + if (verifyFunction(*f,PrintMessageAction)) { + f->dump(); + abort(); + } + #endif FPM->run(*f); //n_compile++; // print out the function's LLVM code //ios_printf(ios_stderr, "%s:%d\n", // ((jl_sym_t*)li->file)->name, li->line); - //f->dump(); - //verifyFunction(*f); + //if (verifyFunction(*f,PrintMessageAction)) { + // f->dump(); + // abort(); + //} if (old != NULL) { builder.SetInsertPoint(old); builder.SetCurrentDebugLocation(olddl); @@ -304,17 +434,51 @@ static Function *to_function(jl_lambda_info_t *li, bool cstyle) extern "C" jl_function_t *jl_get_specialization(jl_function_t *f, jl_tuple_t *types); +static void jl_setup_module(Module *m, bool add) +{ + m->addModuleFlag(llvm::Module::Warning, "Dwarf Version",4); +#ifdef LLVM34 + m->addModuleFlag(llvm::Module::Error, "Debug Info Version", + llvm::DEBUG_METADATA_VERSION); +#endif + if (add) + jl_ExecutionEngine->addModule(m); +} + extern "C" void jl_generate_fptr(jl_function_t *f) { // objective: assign li->fptr jl_lambda_info_t *li = f->linfo; assert(li->functionObject); - Function *llvmf = (Function*)li->functionObject; if (li->fptr == &jl_trampoline) { JL_SIGATOMIC_BEGIN(); + #ifdef USE_MCJIT + if (imaging_mode) { + // Copy the function out of the shadow module + Module *m = new Module("julia", jl_LLVMContext); + jl_setup_module(m,true); + FunctionMover mover(m,shadow_module); + li->functionObject = MapValue((Function*)li->functionObject,mover.VMap,RF_None,NULL,&mover); + if (li->cFunctionObject != NULL) + li->cFunctionObject = MapValue((Function*)li->cFunctionObject,mover.VMap,RF_None,NULL,&mover); + } + #endif + + Function *llvmf = (Function*)li->functionObject; + +#ifdef USE_MCJIT + li->fptr = (jl_fptr_t)jl_ExecutionEngine->getFunctionAddress(llvmf->getName()); +#else li->fptr = (jl_fptr_t)jl_ExecutionEngine->getPointerToFunction(llvmf); - if (li->cFunctionObject != NULL) +#endif + assert(li->fptr != NULL); + if (li->cFunctionObject != NULL) { +#ifdef USE_MCJIT + (void)jl_ExecutionEngine->getFunctionAddress(((Function*)li->cFunctionObject)->getName()); +#else (void)jl_ExecutionEngine->getPointerToFunction((Function*)li->cFunctionObject); +#endif + } JL_SIGATOMIC_END(); if (!imaging_mode) { llvmf->deleteBody(); @@ -400,6 +564,7 @@ const jl_value_t *jl_dump_llvmf(void *f, bool dumpasm) } else { size_t fptr = (size_t)jl_ExecutionEngine->getPointerToFunction(llvmf); + assert(fptr != 0); std::map &fmap = jl_jit_events->getMap(); std::map::iterator fit = fmap.find(fptr); @@ -445,118 +610,6 @@ const jl_value_t *jl_dump_function(jl_function_t *f, jl_tuple_t *types, bool dum return jl_dump_llvmf(llvmf,dumpasm); } - -// --- code generation --- - -// per-local-variable information -struct jl_varinfo_t { - Value *memvalue; // an address, if the var is alloca'd - Value *SAvalue; // register, if the var is SSA - Value *passedAs; // if an argument, the original passed value - int closureidx; // index in closure env, or -1 - bool isAssigned; - bool isCaptured; - bool isSA; - bool isVolatile; - bool isArgument; - bool isGhost; // Has size 0 and is thus never actually allocated - bool hasGCRoot; - bool escapes; - bool usedUndef; - bool used; - jl_value_t *declType; - jl_value_t *initExpr; // initializing expression for SSA variables - - jl_varinfo_t() : memvalue(NULL), SAvalue(NULL), passedAs(NULL), closureidx(-1), - isAssigned(true), isCaptured(false), isSA(false), isVolatile(false), - isArgument(false), isGhost(false), hasGCRoot(false), escapes(true), - usedUndef(false), used(false), - declType((jl_value_t*)jl_any_type), initExpr(NULL) - { - } -}; - -// --- helpers for reloading IR image -extern "C" -void jl_set_imaging_mode(int stat) -{ - imaging_mode = !!stat; -} - -static void jl_gen_llvm_gv_array(); - -extern "C" -void jl_dump_bitcode(char* fname) -{ - std::string err; - raw_fd_ostream OS(fname, err); - jl_gen_llvm_gv_array(); - WriteBitcodeToFile(jl_Module, OS); -} - -// aggregate of array metadata -typedef struct { - Value *dataptr; - Value *len; - std::vector sizes; - jl_value_t *ty; -} jl_arrayvar_t; - -// information about the context of a piece of code: its enclosing -// function and module, and visible local variables and labels. -typedef struct { - Function *f; - // local var info. globals are not in here. - // NOTE: you must be careful not to access vars[s] before you are sure "s" is - // a local, since otherwise this will add it to the map. - std::map vars; - std::map *arrayvars; - std::map *labels; - std::map *handlers; - jl_module_t *module; - jl_expr_t *ast; - jl_tuple_t *sp; - jl_lambda_info_t *linfo; - Value *envArg; - Value *argArray; - Value *argCount; - Instruction *argTemp; - int argDepth; - int maxDepth; - int argSpaceOffs; - std::string funcName; - jl_sym_t *vaName; // name of vararg argument - bool vaStack; // varargs stack-allocated - int nReqArgs; - int lineno; - std::vector boundsCheck; -#ifdef JL_GC_MARKSWEEP - Instruction *gcframe ; - Instruction *argSpaceInits; - StoreInst *storeFrameSize; -#endif - BasicBlock::iterator first_gcframe_inst; - BasicBlock::iterator last_gcframe_inst; - llvm::DIBuilder *dbuilder; - std::vector gc_frame_pops; - std::vector to_inline; -} jl_codectx_t; - -static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool boxed=true, - bool valuepos=true); -static Value *emit_unboxed(jl_value_t *e, jl_codectx_t *ctx); -static int is_global(jl_sym_t *s, jl_codectx_t *ctx); -static Value *make_gcroot(Value *v, jl_codectx_t *ctx); -static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s, - jl_binding_t **pbnd, bool assign); -static Value *emit_checked_var(Value *bp, jl_sym_t *name, jl_codectx_t *ctx); -static bool might_need_root(jl_value_t *ex); -static Value *emit_condition(jl_value_t *cond, const std::string &msg, jl_codectx_t *ctx); - -// --- utilities --- - -#include "cgutils.cpp" - // --- code gen for intrinsic functions --- #include "intrinsics.cpp" @@ -1035,12 +1088,12 @@ static Value *emit_lambda_closure(jl_value_t *expr, jl_codectx_t *ctx) captured[i+1] = val; } Value *env_tuple; - env_tuple = builder.CreateCall(jlntuple_func, + env_tuple = builder.CreateCall(prepare_call(jlntuple_func), ArrayRef(&captured[0], 1+clen)); ctx->argDepth = argStart; make_gcroot(env_tuple, ctx); - Value *result = builder.CreateCall3(jlclosure_func, + Value *result = builder.CreateCall3(prepare_call(jlclosure_func), Constant::getNullValue(T_pint8), env_tuple, literal_pointer_val(expr)); ctx->argDepth--; @@ -1128,7 +1181,7 @@ static Value *emit_getfield(jl_value_t *expr, jl_sym_t *name, jl_codectx_t *ctx) make_gcroot(arg2, ctx); Value *myargs = builder.CreateGEP(ctx->argTemp, ConstantInt::get(T_size, argStart+ctx->argSpaceOffs)); - Value *result = builder.CreateCall3(jlgetfield_func, V_null, myargs, + Value *result = builder.CreateCall3(prepare_call(jlgetfield_func), V_null, myargs, ConstantInt::get(T_int32,2)); ctx->argDepth = argStart; return result; @@ -1224,7 +1277,7 @@ static Value *emit_f_is(jl_value_t *rt1, jl_value_t *rt2, if (ptr_comparable) answer = builder.CreateICmpEQ(varg1, varg2); else - answer = builder.CreateTrunc(builder.CreateCall2(jlegal_func, varg1, varg2), T_int1); + answer = builder.CreateTrunc(builder.CreateCall2(prepare_call(jlegal_func), varg1, varg2), T_int1); done: ctx->argDepth = last_depth; return answer; @@ -1335,7 +1388,7 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, else if (might_need_root(args[1])) { make_gcroot(arg1, ctx); } - builder.CreateCall2(typeassert, arg1, boxed(emit_expr(args[2], ctx),ctx)); + builder.CreateCall2(prepare_call(typeassert), arg1, boxed(emit_expr(args[2], ctx),ctx)); ctx->argDepth = ldepth; JL_GC_POP(); return arg1; @@ -1387,7 +1440,7 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, nva = builder.CreateTrunc(nva, T_int32); #endif Value *r = - builder.CreateCall3(theFptr, theF, + builder.CreateCall3(prepare_call(theFptr), theF, builder.CreateGEP(ctx->argArray, ConstantInt::get(T_size, ctx->nReqArgs)), nva); @@ -1420,8 +1473,8 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, return emit_tupleref(arg1,ConstantInt::get(T_size,idx),tty,ctx); } if (idx==0 || (!isseqt && idx > tlen)) { - builder.CreateCall2(jlthrow_line_func, - builder.CreateLoad(jlboundserr_var), + builder.CreateCall2(prepare_call(jlthrow_line_func), + builder.CreateLoad(prepare_global(jlboundserr_var)), ConstantInt::get(T_int32, ctx->lineno)); JL_GC_POP(); return V_null; @@ -1493,7 +1546,7 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, size_t nwords = nargs+2; #endif Value *tup = - builder.CreateCall(jlallocobj_func, + builder.CreateCall(prepare_call(jlallocobj_func), ConstantInt::get(T_size, sizeof(void*)*nwords)); #ifdef OVERLAP_TUPLE_LEN builder.CreateStore(arg1, emit_nthptr_addr(tup, 1)); @@ -1543,7 +1596,7 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, else if (f->fptr == &jl_f_throw && nargs==1) { Value *arg1 = boxed(emit_expr(args[1], ctx), ctx); JL_GC_POP(); - builder.CreateCall2(jlthrow_line_func, arg1, + builder.CreateCall2(prepare_call(jlthrow_line_func), arg1, ConstantInt::get(T_int32, ctx->lineno)); return V_null; } @@ -1819,7 +1872,7 @@ static Value *emit_jlcall(Value *theFptr, Value *theF, jl_value_t **args, else { myargs = Constant::getNullValue(jl_ppvalue_llvmt); } - Value *result = builder.CreateCall3(theFptr, theF, myargs, + Value *result = builder.CreateCall3(prepare_call(theFptr), theF, myargs, ConstantInt::get(T_int32,nargs)); ctx->argDepth = argStart; return result; @@ -1905,7 +1958,7 @@ static Value *emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx, idx++; } assert(idx == nfargs); - result = builder.CreateCall(cf, ArrayRef(&argvals[0],nfargs)); + result = builder.CreateCall(prepare_call(cf), ArrayRef(&argvals[0],nfargs)); if (result->getType() == T_void) { result = literal_pointer_val((jl_value_t*)jl_nothing); } @@ -2096,7 +2149,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) Value *rval; if (bnd) { rval = boxed(emit_expr(r, ctx, true),ctx); - builder.CreateCall2(jlcheckassign_func, + builder.CreateCall2(prepare_call(jlcheckassign_func), literal_pointer_val(bnd), rval); } @@ -2247,7 +2300,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, if (lv != NULL) { // create a new uninitialized variable if (isBoxed(var, ctx)) { - builder.CreateStore(builder.CreateCall(jlbox_func, V_null), lv); + builder.CreateStore(builder.CreateCall(prepare_call(jlbox_func), V_null), lv); } else if (lv->getType() == jl_ppvalue_llvmt && vi.usedUndef) { builder.CreateStore(V_null, lv); @@ -2348,7 +2401,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, make_gcroot(a2, ctx); Value *mdargs[5] = { name, bp, literal_pointer_val(bnd), a1, a2 }; ctx->argDepth = last_depth; - return builder.CreateCall(jlmethod_func, ArrayRef(&mdargs[0], 5)); + return builder.CreateCall(prepare_call(jlmethod_func), ArrayRef(&mdargs[0], 5)); } else if (head == const_sym) { jl_sym_t *sym = (jl_sym_t*)args[0]; @@ -2356,7 +2409,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, jl_binding_t *bnd = NULL; (void)var_binding_pointer(sym, &bnd, true, ctx); if (bnd) { - builder.CreateCall(jldeclareconst_func, + builder.CreateCall(prepare_call(jldeclareconst_func), literal_pointer_val(bnd)); } } @@ -2427,7 +2480,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, make_gcroot(f1, ctx); } Value *strct = - builder.CreateCall(jlallocobj_func, + builder.CreateCall(prepare_call(jlallocobj_func), ConstantInt::get(T_size, sizeof(void*)+sty->size)); builder.CreateStore(literal_pointer_val((jl_value_t*)ty), @@ -2469,11 +2522,11 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, return emit_jlcall(jlnew_func, typ, &args[1], nargs-1, ctx); } else if (head == exc_sym) { - return builder.CreateLoad(jlexc_var, true); + return builder.CreateLoad(prepare_global(jlexc_var), true); } else if (head == leave_sym) { assert(jl_is_long(args[0])); - builder.CreateCall(jlleave_func, + builder.CreateCall(prepare_call(jlleave_func), ConstantInt::get(T_int32, jl_unbox_long(args[0]))); } else if (head == enter_sym) { @@ -2481,11 +2534,11 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, int labl = jl_unbox_long(args[0]); Value *jbuf = builder.CreateGEP((*ctx->handlers)[labl], ConstantInt::get(T_size,0)); - builder.CreateCall(jlenter_func, jbuf); + builder.CreateCall(prepare_call(jlenter_func), jbuf); #ifndef _OS_WINDOWS_ - Value *sj = builder.CreateCall2(setjmp_func, jbuf, ConstantInt::get(T_int32,0)); + Value *sj = builder.CreateCall2(prepare_call(setjmp_func), jbuf, ConstantInt::get(T_int32,0)); #else - Value *sj = builder.CreateCall(setjmp_func, jbuf); + Value *sj = builder.CreateCall(prepare_call(setjmp_func), jbuf); #endif Value *isz = builder.CreateICmpEQ(sj, ConstantInt::get(T_int32,0)); BasicBlock *tryblk = BasicBlock::Create(getGlobalContext(), "try", @@ -2499,10 +2552,10 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, builder.SetInsertPoint(cond_resetstkoflw_blk); builder.CreateCondBr(builder.CreateICmpEQ( literal_pointer_val(jl_stackovf_exception), - builder.CreateLoad(jlexc_var, true)), + builder.CreateLoad(prepare_glboal(jlexc_var), true)), resetstkoflw_blk, handlr); builder.SetInsertPoint(resetstkoflw_blk); - builder.CreateCall(resetstkoflw_func); + builder.CreateCall(prepare_call(resetstkoflw_func)); builder.CreateBr(handlr); #else builder.CreateCondBr(isz, tryblk, handlr); @@ -2536,7 +2589,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, return emit_expr(arg, ctx); } } - return builder.CreateCall(jlcopyast_func, emit_expr(arg, ctx)); + return builder.CreateCall(prepare_call(jlcopyast_func), emit_expr(arg, ctx)); } else { if (!strcmp(head->name, "$")) @@ -2546,7 +2599,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, ctx->linfo->module == jl_current_module) { // call interpreter to run a toplevel expr from inside a // compiled toplevel thunk. - builder.CreateCall(jltopeval_func, literal_pointer_val(expr)); + builder.CreateCall(prepare_call(jltopeval_func), literal_pointer_val(expr)); jl_add_linfo_root(ctx->linfo, expr); return valuepos ? literal_pointer_val(jl_nothing) : NULL; } @@ -2649,9 +2702,9 @@ static void allocate_gc_frame(size_t n_roots, jl_codectx_t *ctx) ctx->storeFrameSize = builder.CreateStore(ConstantInt::get(T_size, n_roots<<1), builder.CreateBitCast(builder.CreateConstGEP1_32(ctx->gcframe, 0), T_psize)); - builder.CreateStore(builder.CreateLoad(jlpgcstack_var, false), + builder.CreateStore(builder.CreateLoad(prepare_global(jlpgcstack_var), false), builder.CreateBitCast(builder.CreateConstGEP1_32(ctx->gcframe, 1), PointerType::get(jl_ppvalue_llvmt,0))); - Instruction *linst = builder.CreateStore(ctx->gcframe, jlpgcstack_var, false); + Instruction *linst = builder.CreateStore(ctx->gcframe, prepare_global(jlpgcstack_var), false); ctx->last_gcframe_inst = BasicBlock::iterator(linst); // initialize local variable stack roots to null for(size_t i=0; i < (size_t)ctx->argSpaceOffs; i++) { @@ -2739,8 +2792,8 @@ static void finalize_gc_frame(jl_codectx_t *ctx) // generate a julia-callable function that calls f (AKA lam) static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast, Function *f) { - Function *w = Function::Create(jl_func_sig, Function::InternalLinkage, - f->getName(), jl_Module); + Function *w = Function::Create(jl_func_sig, Function::ExternalLinkage, + f->getName(), f->getParent()); Function::arg_iterator AI = w->arg_begin(); AI++; //const Argument &fArg = *AI++; Value *argArray = AI++; @@ -2790,7 +2843,7 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast, Funct } // TODO: consider pulling the function pointer out of fArg so these // wrappers can be reused for different functions of the same type. - Value *r = builder.CreateCall(f, ArrayRef(&args[0], nfargs)); + Value *r = builder.CreateCall(prepare_call(f), ArrayRef(&args[0], nfargs)); if (r->getType() != jl_pvalue_llvmt) { r = boxed(r, &ctx, jl_ast_rettype(lam, (jl_value_t*)ast)); } @@ -2800,7 +2853,7 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast, Funct Instruction *gcpop = (Instruction*)builder.CreateConstGEP1_32(ctx.gcframe, 1); ctx.gc_frame_pops.push_back(gcpop); builder.CreateStore(builder.CreateBitCast(builder.CreateLoad(gcpop, false), jl_ppvalue_llvmt), - jlpgcstack_var); + prepare_global(jlpgcstack_var)); finalize_gc_frame(&ctx); builder.CreateRet(r); @@ -2808,6 +2861,8 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast, Funct return w; } +static int globalUnique = 0; + // cstyle = compile with c-callable signature, not jlcall static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) { @@ -2946,9 +3001,24 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) } } - std::string funcName = lam->name->name; + std::stringstream funcName; // try to avoid conflicts in the global symbol table - funcName = "julia_" + funcName; + funcName << "julia_" << lam->name->name; + + Module *m; + #ifdef USE_MCJIT + if(!imaging_mode) { + m = new Module(funcName.str(), jl_LLVMContext); + jl_setup_module(m,true); + } + else { + m = shadow_module; + } + #else + m = jl_Module; + #endif + + funcName << globalUnique++; if (specsig) { std::vector fsig(0); @@ -2963,7 +3033,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) } Type *rt = (jlrettype == (jl_value_t*)jl_nothing->type ? T_void : julia_type_to_llvm(jlrettype)); f = Function::Create(FunctionType::get(rt, fsig, false), - Function::InternalLinkage, funcName, jl_Module); + Function::ExternalLinkage, funcName.str(), m); if (lam->cFunctionObject == NULL) { lam->cFunctionObject = (void*)f; lam->cFunctionID = jl_assign_functionID(f); @@ -2975,8 +3045,8 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) } } else { - f = Function::Create(jl_func_sig, Function::InternalLinkage, - funcName, jl_Module); + f = Function::Create(jl_func_sig, Function::ExternalLinkage, + funcName.str(), m); if (lam->functionObject == NULL) { lam->functionObject = (void*)f; lam->functionID = jl_assign_functionID(f); @@ -3036,14 +3106,15 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) } ctx.lineno = lno; + DIBuilder dbuilder(*m); + ctx.dbuilder = &dbuilder; + DIFile fil; + DISubprogram SP; + BasicBlock *b0 = BasicBlock::Create(jl_LLVMContext, "top", f); builder.SetInsertPoint(b0); - DIBuilder dbuilder(*jl_Module); - ctx.dbuilder = &dbuilder; llvm::DIArray EltTypeArray = dbuilder.getOrCreateArray(ArrayRef()); - DIFile fil; - DISubprogram SP; //ios_printf(ios_stderr, "\n*** compiling %s at %s:%d\n\n", // lam->name->name, filename.c_str(), lno); @@ -3179,7 +3250,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) jl_sym_t *s = ((jl_sym_t*)jl_cellref(lvars,i)); if (isBoxed(s, &ctx)) { Value *lv = ctx.vars[s].memvalue; - builder.CreateStore(builder.CreateCall(jlbox_func, V_null), lv); + builder.CreateStore(builder.CreateCall(prepare_call(jlbox_func), V_null), lv); } } */ @@ -3278,7 +3349,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) theArg = boxed(theArg,&ctx); builder.CreateStore(theArg, lv); // temporarily root } - builder.CreateStore(builder.CreateCall(jlbox_func, theArg), lv); + builder.CreateStore(builder.CreateCall(prepare_call(jlbox_func), theArg), lv); } else if (dyn_cast(lv) != NULL) { builder.CreateStore(boxed(theArg,&ctx), lv); @@ -3313,13 +3384,13 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) Value *lv = vi.memvalue; if (dyn_cast(lv) != NULL || dyn_cast(lv)->getAllocatedType() == jl_pvalue_llvmt) { Value *restTuple = - builder.CreateCall3(jltuple_func, V_null, + builder.CreateCall3(prepare_call(jltuple_func), V_null, builder.CreateGEP(argArray, ConstantInt::get(T_size,nreq)), builder.CreateSub(argCount, ConstantInt::get(T_int32,nreq))); if (isBoxed(argname, &ctx)) - builder.CreateStore(builder.CreateCall(jlbox_func, restTuple), lv); + builder.CreateStore(builder.CreateCall(prepare_call(jlbox_func), restTuple), lv); else builder.CreateStore(restTuple, lv); } @@ -3392,7 +3463,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) Instruction *gcpop = (Instruction*)builder.CreateConstGEP1_32(ctx.gcframe, 1); ctx.gc_frame_pops.push_back(gcpop); builder.CreateStore(builder.CreateBitCast(builder.CreateLoad(gcpop, false), jl_ppvalue_llvmt), - jlpgcstack_var); + prepare_global(jlpgcstack_var)); #endif if (builder.GetInsertBlock()->getTerminator() == NULL) { if (retty == T_void) @@ -3436,20 +3507,20 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) // --- initialization --- -static GlobalVariable *global_to_llvm(const std::string &cname, void *addr) +static GlobalVariable *global_to_llvm(const std::string &cname, void *addr, Module *m) { GlobalVariable *gv = - new GlobalVariable(*jl_Module, jl_pvalue_llvmt, true, + new GlobalVariable(*m, jl_pvalue_llvmt, true, GlobalVariable::ExternalLinkage, NULL, cname); - jl_ExecutionEngine->addGlobalMapping(gv, addr); + add_named_global(gv, addr); return gv; } -static Function *jlcall_func_to_llvm(const std::string &cname, void *addr) +static Function *jlcall_func_to_llvm(const std::string &cname, void *addr, Module *m) { Function *f = Function::Create(jl_func_sig, Function::ExternalLinkage, - cname, jl_Module); - jl_ExecutionEngine->addGlobalMapping(f, addr); + cname, m); + add_named_global(f, addr); return f; } @@ -3468,15 +3539,24 @@ extern "C" void jl_fptr_to_llvm(void *fptr, jl_lambda_info_t *lam, int specsig) } Type *rt = (jlrettype == (jl_value_t*)jl_nothing->type ? T_void : julia_type_to_llvm(jlrettype)); Function *f = Function::Create(FunctionType::get(rt, fsig, false), +#ifdef USE_MCJIT + Function::ExternalLinkage, funcName, shadow_module); +#else Function::ExternalLinkage, funcName, jl_Module); +#endif + if (lam->cFunctionObject == NULL) { lam->cFunctionObject = (void*)f; lam->cFunctionID = jl_assign_functionID(f); } - jl_ExecutionEngine->addGlobalMapping(f, (void*)fptr); + add_named_global(f, (void*)fptr); } else { - Function *f = jlcall_func_to_llvm(funcName, fptr); +#ifdef USE_MCJIT + Function *f = jlcall_func_to_llvm(funcName, fptr, shadow_module); +#else + Function *f = jlcall_func_to_llvm(funcName, fptr, jl_Module); +#endif if (lam->functionObject == NULL) { lam->functionObject = (void*)f; lam->functionID = jl_assign_functionID(f); @@ -3549,99 +3629,100 @@ static void init_julia_llvm_env(Module *m) #ifdef JL_GC_MARKSWEEP jlpgcstack_var = - new GlobalVariable(*jl_Module, jl_ppvalue_llvmt, + new GlobalVariable(*m, jl_ppvalue_llvmt, true, GlobalVariable::ExternalLinkage, NULL, "jl_pgcstack"); - jl_ExecutionEngine->addGlobalMapping(jlpgcstack_var, (void*)&jl_pgcstack); + add_named_global(jlpgcstack_var, (void*)&jl_pgcstack); #endif - global_to_llvm("__stack_chk_guard", (void*)&__stack_chk_guard); + global_to_llvm("__stack_chk_guard", (void*)&__stack_chk_guard, m); Function *jl__stack_chk_fail = Function::Create(FunctionType::get(T_void, false), Function::ExternalLinkage, - "__stack_chk_fail", jl_Module); + "__stack_chk_fail", m); //jl__stack_chk_fail->setDoesNotReturn(); - jl_ExecutionEngine->addGlobalMapping(jl__stack_chk_fail, (void*)&__stack_chk_fail); + add_named_global(jl__stack_chk_fail, (void*)&__stack_chk_fail); - jltrue_var = global_to_llvm("jl_true", (void*)&jl_true); - jlfalse_var = global_to_llvm("jl_false", (void*)&jl_false); - jlnull_var = global_to_llvm("jl_null", (void*)&jl_null); + jltrue_var = global_to_llvm("jl_true", (void*)&jl_true, m); + jlfalse_var = global_to_llvm("jl_false", (void*)&jl_false, m); + jlnull_var = global_to_llvm("jl_null", (void*)&jl_null, m); jlexc_var = global_to_llvm("jl_exception_in_transit", - (void*)&jl_exception_in_transit); + (void*)&jl_exception_in_transit, m); jldiverr_var = global_to_llvm("jl_diverror_exception", - (void*)&jl_diverror_exception); + (void*)&jl_diverror_exception, m); jlundeferr_var = global_to_llvm("jl_undefref_exception", - (void*)&jl_undefref_exception); + (void*)&jl_undefref_exception, m); jldomerr_var = global_to_llvm("jl_domain_exception", - (void*)&jl_domain_exception); + (void*)&jl_domain_exception, m); jlovferr_var = global_to_llvm("jl_overflow_exception", - (void*)&jl_overflow_exception); + (void*)&jl_overflow_exception, m); jlinexacterr_var = global_to_llvm("jl_inexact_exception", - (void*)&jl_inexact_exception); + (void*)&jl_inexact_exception, m); jlboundserr_var = global_to_llvm("jl_bounds_exception", - (void*)&jl_bounds_exception); + (void*)&jl_bounds_exception, m); jlstderr_var = - new GlobalVariable(*jl_Module, T_int8, + new GlobalVariable(*m, T_int8, true, GlobalVariable::ExternalLinkage, NULL, "jl_uv_stderr"); - jl_ExecutionEngine->addGlobalMapping(jlstderr_var, (void*)&jl_uv_stderr); + add_named_global(jlstderr_var, (void*)&jl_uv_stderr); jlRTLD_DEFAULT_var = - new GlobalVariable(*jl_Module, T_pint8, + new GlobalVariable(*m, T_pint8, true, GlobalVariable::ExternalLinkage, NULL, "jl_RTLD_DEFAULT_handle"); - jl_ExecutionEngine->addGlobalMapping(jlRTLD_DEFAULT_var, (void*)&jl_RTLD_DEFAULT_handle); + add_named_global(jlRTLD_DEFAULT_var, (void*)&jl_RTLD_DEFAULT_handle); #ifdef _OS_WINDOWS_ jlexe_var = - new GlobalVariable(*jl_Module, T_pint8, + new GlobalVariable(*m, T_pint8, true, GlobalVariable::ExternalLinkage, NULL, "jl_exe_handle"); - jl_ExecutionEngine->addGlobalMapping(jlexe_var, (void*)&jl_exe_handle); + add_named_global(jlexe_var, (void*)&jl_exe_handle); jldll_var = - new GlobalVariable(*jl_Module, T_pint8, + new GlobalVariable(*m, T_pint8, true, GlobalVariable::ExternalLinkage, NULL, "jl_dl_handle"); - jl_ExecutionEngine->addGlobalMapping(jldll_var, (void*)&jl_dl_handle); + add_named_global(jldll_var, (void*)&jl_dl_handle); #endif // Has to be big enough for the biggest LLVM-supported float type jlfloattemp_var = - new GlobalVariable(*jl_Module, IntegerType::get(jl_LLVMContext,128), - false, GlobalVariable::PrivateLinkage, + new GlobalVariable(*m, IntegerType::get(jl_LLVMContext,128), + false, GlobalVariable::ExternalLinkage, ConstantInt::get(IntegerType::get(jl_LLVMContext,128),0), "jl_float_temp"); + std::vector args1(0); args1.push_back(T_pint8); jlerror_func = Function::Create(FunctionType::get(T_void, args1, false), Function::ExternalLinkage, - "jl_error", jl_Module); + "jl_error", m); jlerror_func->setDoesNotReturn(); - jl_ExecutionEngine->addGlobalMapping(jlerror_func, (void*)&jl_error); + add_named_global(jlerror_func, (void*)&jl_error); std::vector args1_(0); args1_.push_back(jl_pvalue_llvmt); jlthrow_func = Function::Create(FunctionType::get(T_void, args1_, false), Function::ExternalLinkage, - "jl_throw", jl_Module); + "jl_throw", m); jlthrow_func->setDoesNotReturn(); - jl_ExecutionEngine->addGlobalMapping(jlthrow_func, (void*)&jl_throw); + add_named_global(jlthrow_func, (void*)&jl_throw); std::vector args2_throw(0); args2_throw.push_back(jl_pvalue_llvmt); args2_throw.push_back(T_int32); jlthrow_line_func = - (Function*)jl_Module->getOrInsertFunction("jl_throw_with_superfluous_argument", + (Function*)m->getOrInsertFunction("jl_throw_with_superfluous_argument", FunctionType::get(T_void, args2_throw, false)); jlthrow_line_func->setDoesNotReturn(); - jl_ExecutionEngine->addGlobalMapping(jlthrow_line_func, (void*)&jl_throw_with_superfluous_argument); + add_named_global(jlthrow_line_func, (void*)&jl_throw_with_superfluous_argument); jlnew_func = Function::Create(jl_func_sig, Function::ExternalLinkage, - "jl_new_structv", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlnew_func, (void*)&jl_new_structv); + "jl_new_structv", m); + add_named_global(jlnew_func, (void*)&jl_new_structv); std::vector args2(0); args2.push_back(T_pint8); @@ -3650,13 +3731,13 @@ static void init_julia_llvm_env(Module *m) #endif setjmp_func = Function::Create(FunctionType::get(T_int32, args2, false), - Function::ExternalLinkage, jl_setjmp_name, jl_Module); + Function::ExternalLinkage, jl_setjmp_name, m); #if LLVM32 && !LLVM33 setjmp_func->addFnAttr(Attributes::ReturnsTwice); #else setjmp_func->addFnAttr(Attribute::ReturnsTwice); #endif - jl_ExecutionEngine->addGlobalMapping(setjmp_func, (void*)&jl_setjmp_f); + add_named_global(setjmp_func, (void*)&jl_setjmp_f); std::vector te_args(0); te_args.push_back(T_pint8); @@ -3666,9 +3747,9 @@ static void init_julia_llvm_env(Module *m) jltypeerror_func = Function::Create(FunctionType::get(T_void, te_args, false), Function::ExternalLinkage, - "jl_type_error_rt", jl_Module); + "jl_type_error_rt", m); jltypeerror_func->setDoesNotReturn(); - jl_ExecutionEngine->addGlobalMapping(jltypeerror_func, + add_named_global(jltypeerror_func, (void*)&jl_type_error_rt); std::vector args_2ptrs(0); @@ -3677,8 +3758,8 @@ static void init_julia_llvm_env(Module *m) jlcheckassign_func = Function::Create(FunctionType::get(T_void, args_2ptrs, false), Function::ExternalLinkage, - "jl_checked_assignment", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlcheckassign_func, + "jl_checked_assignment", m); + add_named_global(jlcheckassign_func, (void*)&jl_checked_assignment); std::vector args_1ptr(0); @@ -3686,34 +3767,34 @@ static void init_julia_llvm_env(Module *m) jldeclareconst_func = Function::Create(FunctionType::get(T_void, args_1ptr, false), Function::ExternalLinkage, - "jl_declare_constant", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jldeclareconst_func, + "jl_declare_constant", m); + add_named_global(jldeclareconst_func, (void*)&jl_declare_constant); - jltuple_func = jlcall_func_to_llvm("jl_f_tuple", (void*)&jl_f_tuple); + jltuple_func = jlcall_func_to_llvm("jl_f_tuple", (void*)&jl_f_tuple, m); jlapplygeneric_func = - jlcall_func_to_llvm("jl_apply_generic", (void*)&jl_apply_generic); - jlgetfield_func = jlcall_func_to_llvm("jl_f_get_field", (void*)&jl_f_get_field); + jlcall_func_to_llvm("jl_apply_generic", (void*)&jl_apply_generic, m); + jlgetfield_func = jlcall_func_to_llvm("jl_f_get_field", (void*)&jl_f_get_field, m); std::vector args3(0); args3.push_back(jl_pvalue_llvmt); jlbox_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, args3, false), Function::ExternalLinkage, - "jl_new_box", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlbox_func, (void*)&jl_new_box); + "jl_new_box", m); + add_named_global(jlbox_func, (void*)&jl_new_box); jltopeval_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, args3, false), Function::ExternalLinkage, - "jl_toplevel_eval", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jltopeval_func, (void*)&jl_toplevel_eval); + "jl_toplevel_eval", m); + add_named_global(jltopeval_func, (void*)&jl_toplevel_eval); jlcopyast_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, args3, false), Function::ExternalLinkage, - "jl_copy_ast", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlcopyast_func, (void*)&jl_copy_ast); + "jl_copy_ast", m); + add_named_global(jlcopyast_func, (void*)&jl_copy_ast); std::vector args4(0); args4.push_back(T_pint8); @@ -3722,8 +3803,8 @@ static void init_julia_llvm_env(Module *m) jlclosure_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, args4, false), Function::ExternalLinkage, - "jl_new_closure", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlclosure_func, + "jl_new_closure", m); + add_named_global(jlclosure_func, (void*)&jl_new_closure); std::vector args5(0); @@ -3731,8 +3812,8 @@ static void init_julia_llvm_env(Module *m) jlntuple_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, args5, true), Function::ExternalLinkage, - "jl_tuple", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlntuple_func, (void*)&jl_tuple); + "jl_tuple", m); + add_named_global(jlntuple_func, (void*)&jl_tuple); std::vector mdargs(0); mdargs.push_back(jl_pvalue_llvmt); @@ -3743,21 +3824,21 @@ static void init_julia_llvm_env(Module *m) jlmethod_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, mdargs, false), Function::ExternalLinkage, - "jl_method_def", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlmethod_func, (void*)&jl_method_def); + "jl_method_def", m); + add_named_global(jlmethod_func, (void*)&jl_method_def); std::vector ehargs(0); ehargs.push_back(T_pint8); jlenter_func = Function::Create(FunctionType::get(T_void, ehargs, false), Function::ExternalLinkage, - "jl_enter_handler", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlenter_func, (void*)&jl_enter_handler); + "jl_enter_handler", m); + add_named_global(jlenter_func, (void*)&jl_enter_handler); #ifdef _OS_WINDOWS_ resetstkoflw_func = Function::Create(FunctionType::get(T_void, false), - Function::ExternalLinkage, "_resetstkoflw", jl_Module); - jl_ExecutionEngine->addGlobalMapping(resetstkoflw_func, (void*)&_resetstkoflw); + Function::ExternalLinkage, "_resetstkoflw", m); + add_named_global(resetstkoflw_func, (void*)&_resetstkoflw); #endif std::vector lhargs(0); @@ -3765,8 +3846,8 @@ static void init_julia_llvm_env(Module *m) jlleave_func = Function::Create(FunctionType::get(T_void, lhargs, false), Function::ExternalLinkage, - "jl_pop_handler", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlleave_func, (void*)&jl_pop_handler); + "jl_pop_handler", m); + add_named_global(jlleave_func, (void*)&jl_pop_handler); std::vector args_2vals(0); args_2vals.push_back(jl_pvalue_llvmt); @@ -3774,37 +3855,37 @@ static void init_julia_llvm_env(Module *m) jlegal_func = Function::Create(FunctionType::get(T_int32, args_2vals, false), Function::ExternalLinkage, - "jl_egal", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlegal_func, (void*)&jl_egal); + "jl_egal", m); + add_named_global(jlegal_func, (void*)&jl_egal); std::vector aoargs(0); aoargs.push_back(T_size); jlallocobj_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, aoargs, false), Function::ExternalLinkage, - "allocobj", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlallocobj_func, (void*)&allocobj); + "allocobj", m); + add_named_global(jlallocobj_func, (void*)&allocobj); std::vector empty_args(0); jlalloc2w_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, empty_args, false), Function::ExternalLinkage, - "alloc_2w", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlalloc2w_func, (void*)&alloc_2w); + "alloc_2w", m); + add_named_global(jlalloc2w_func, (void*)&alloc_2w); jlalloc3w_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, empty_args, false), Function::ExternalLinkage, - "alloc_3w", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlalloc3w_func, (void*)&alloc_3w); + "alloc_3w", m); + add_named_global(jlalloc3w_func, (void*)&alloc_3w); std::vector atargs(0); atargs.push_back(T_size); jl_alloc_tuple_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, atargs, false), Function::ExternalLinkage, - "jl_alloc_tuple", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jl_alloc_tuple_func, (void*)&jl_alloc_tuple); + "jl_alloc_tuple", m); + add_named_global(jl_alloc_tuple_func, (void*)&jl_alloc_tuple); std::vector puts_args(0); puts_args.push_back(T_pint8); @@ -3812,8 +3893,8 @@ static void init_julia_llvm_env(Module *m) jlputs_func = Function::Create(FunctionType::get(T_void, puts_args, false), Function::ExternalLinkage, - "jl_puts", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlputs_func, (void*)&jl_puts); + "jl_puts", m); + add_named_global(jlputs_func, (void*)&jl_puts); std::vector dlsym_args(0); dlsym_args.push_back(T_pint8); @@ -3822,8 +3903,8 @@ static void init_julia_llvm_env(Module *m) jldlsym_func = Function::Create(FunctionType::get(T_pint8, dlsym_args, false), Function::ExternalLinkage, - "jl_load_and_lookup", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jldlsym_func, (void*)&jl_load_and_lookup); + "jl_load_and_lookup", m); + add_named_global(jldlsym_func, (void*)&jl_load_and_lookup); std::vector newbits_args(0); newbits_args.push_back(jl_pvalue_llvmt); @@ -3831,7 +3912,7 @@ static void init_julia_llvm_env(Module *m) jlnewbits_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, newbits_args, false), Function::ExternalLinkage, - "jl_new_bits", jl_Module); + "jl_new_bits", m); jl_ExecutionEngine->addGlobalMapping(jlnewbits_func, (void*)&jl_new_bits); std::vector getnthfld_args(0); @@ -3840,11 +3921,11 @@ static void init_julia_llvm_env(Module *m) jlgetnthfieldchecked_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, getnthfld_args, false), Function::ExternalLinkage, - "jl_get_nth_field_checked", jl_Module); + "jl_get_nth_field_checked", m); jl_ExecutionEngine->addGlobalMapping(jlgetnthfieldchecked_func, (void*)*jl_get_nth_field_checked); // set up optimization passes - FPM = new FunctionPassManager(jl_Module); + FPM = new FunctionPassManager(m); #ifdef LLVM32 jl_data_layout = new DataLayout(*jl_ExecutionEngine->getDataLayout()); @@ -3905,10 +3986,29 @@ static void init_julia_llvm_env(Module *m) extern "C" void jl_init_codegen(void) { InitializeNativeTarget(); - jl_Module = new Module("julia", jl_LLVMContext); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + + Module *m, *engine_module; + +#ifdef USE_MCJIT + m = shadow_module = new Module("shadow", jl_LLVMContext); + jl_setup_module(shadow_module,false); + if (imaging_mode) { + engine_module = new Module("engine_module", jl_LLVMContext); + jl_setup_module(engine_module,false); + } + else { + engine_module = m; + } +#else + engine_module = m = jl_Module = new Module("julia", jl_LLVMContext); + jl_setup_module(engine_module,false); +#endif + #if !defined(LLVM_VERSION_MAJOR) || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 0) - jl_ExecutionEngine = EngineBuilder(jl_Module).setEngineKind(EngineKind::JIT).create(); + jl_ExecutionEngine = EngineBuilder(m).setEngineKind(EngineKind::JIT).create(); #ifdef DEBUG llvm::JITEmitDebugInfo = true; #endif @@ -3934,25 +4034,33 @@ extern "C" void jl_init_codegen(void) // to ensure compatibility with GCC codes options.StackAlignmentOverride = 8; #endif -#ifdef __APPLE__ +#if defined(__APPLE__) && !defined(LLVM34) // turn on JIT support for libunwind to walk the stack options.JITExceptionHandling = 1; #endif +#ifdef USE_MCJIT + jl_mcjmm = new SectionMemoryManager(); +#else // Temporarily disable Haswell BMI2 features due to LLVM bug. const char *mattr[] = {"-bmi2", "-avx2"}; std::vector attrvec (mattr, mattr+2); - jl_ExecutionEngine = EngineBuilder(jl_Module) +#endif + jl_ExecutionEngine = EngineBuilder(engine_module) .setEngineKind(EngineKind::JIT) #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_) .setJITMemoryManager(new JITMemoryManagerWin()) #endif .setTargetOptions(options) +#ifdef USE_MCJIT + .setUseMCJIT(true) +#else .setMAttrs(attrvec) +#endif .create(); #endif // LLVM VERSION jl_ExecutionEngine->DisableLazyCompilation(); - init_julia_llvm_env(jl_Module); + init_julia_llvm_env(m); jl_jit_events = new JuliaJITEventListener(); jl_ExecutionEngine->RegisterJITEventListener(jl_jit_events); @@ -3971,13 +4079,13 @@ extern "C" void jl_init_codegen(void) BOX_F(char,char); box8_func = boxfunc_llvm(ft2arg(jl_pvalue_llvmt, jl_pvalue_llvmt, T_int8), - "jl_box8", (void*)&jl_box8); + "jl_box8", (void*)&jl_box8, m); box16_func = boxfunc_llvm(ft2arg(jl_pvalue_llvmt, jl_pvalue_llvmt, T_int16), - "jl_box16", (void*)&jl_box16); + "jl_box16", (void*)&jl_box16, m); box32_func = boxfunc_llvm(ft2arg(jl_pvalue_llvmt, jl_pvalue_llvmt, T_int32), - "jl_box32", (void*)&jl_box32); + "jl_box32", (void*)&jl_box32, m); box64_func = boxfunc_llvm(ft2arg(jl_pvalue_llvmt, jl_pvalue_llvmt, T_int64), - "jl_box64", (void*)&jl_box64); + "jl_box64", (void*)&jl_box64, m); std::vector toptrargs(0); toptrargs.push_back(jl_pvalue_llvmt); @@ -3987,8 +4095,8 @@ extern "C" void jl_init_codegen(void) value_to_pointer_func = Function::Create(FunctionType::get(T_pint8, toptrargs, false), Function::ExternalLinkage, "jl_value_to_pointer", - jl_Module); - jl_ExecutionEngine->addGlobalMapping(value_to_pointer_func, + m); + add_named_global(value_to_pointer_func, (void*)&jl_value_to_pointer); temp_arg_area = (char*)malloc(arg_area_sz); @@ -3998,15 +4106,15 @@ extern "C" void jl_init_codegen(void) save_arg_area_loc_func = Function::Create(FunctionType::get(T_uint64, noargs, false), Function::ExternalLinkage, "save_arg_area_loc", - jl_Module); - jl_ExecutionEngine->addGlobalMapping(save_arg_area_loc_func, + m); + add_named_global(save_arg_area_loc_func, (void*)&save_arg_area_loc); restore_arg_area_loc_func = Function::Create(ft1arg(T_void, T_uint64), Function::ExternalLinkage, "restore_arg_area_loc", - jl_Module); - jl_ExecutionEngine->addGlobalMapping(restore_arg_area_loc_func, + m); + add_named_global(restore_arg_area_loc_func, (void*)&restore_arg_area_loc); typeToTypeId = jl_alloc_cell_1d(16); diff --git a/src/disasm.cpp b/src/disasm.cpp index 2af539f4adc6e..a206790480c61 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -132,7 +132,11 @@ void jl_dump_function_asm(void* Fptr, size_t Fsize, MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); +#ifdef LLVM34 + MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); +#else MAB = TheTarget->createMCAsmBackend(TripleName, MCPU); +#endif } Streamer.reset(TheTarget->createAsmStreamer(Ctx, stream, /*asmverbose*/true, diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index ecd5014151fc3..23b028cb1e45c 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -464,7 +464,7 @@ static Value *emit_checked_fptosi(Type *to, Value *x, jl_codectx_t *ctx) raise_exception_unless (builder.CreateFCmpOEQ(builder.CreateFPExt(x, T_float64), builder.CreateSIToFP(v, T_float64)), - jlinexacterr_var, ctx); + prepare_global(jlinexacterr_var), ctx); } else { Value *xx = x, *vv = v; @@ -472,7 +472,7 @@ static Value *emit_checked_fptosi(Type *to, Value *x, jl_codectx_t *ctx) xx = builder.CreateFPExt(x, T_float64); if (to->getPrimitiveSizeInBits() < 64) vv = builder.CreateSExt(v, T_int64); - raise_exception_unless(emit_eqfsi64(xx, vv), jlinexacterr_var, ctx); + raise_exception_unless(emit_eqfsi64(xx, vv), prepare_global(jlinexacterr_var), ctx); } return v; } @@ -490,7 +490,7 @@ static Value *emit_checked_fptoui(Type *to, Value *x, jl_codectx_t *ctx) raise_exception_unless (builder.CreateFCmpOEQ(builder.CreateFPExt(x, T_float64), builder.CreateUIToFP(v, T_float64)), - jlinexacterr_var, ctx); + prepare_global(jlinexacterr_var), ctx); } else { Value *xx = x, *vv = v; @@ -498,7 +498,7 @@ static Value *emit_checked_fptoui(Type *to, Value *x, jl_codectx_t *ctx) xx = builder.CreateFPExt(x, T_float64); if (to->getPrimitiveSizeInBits() < 64) vv = builder.CreateZExt(v, T_int64); - raise_exception_unless(emit_eqfui64(xx, vv), jlinexacterr_var, ctx); + raise_exception_unless(emit_eqfui64(xx, vv), prepare_global(jlinexacterr_var), ctx); } return v; } @@ -575,7 +575,7 @@ static Value *emit_iround(Value *x, bool issigned, jl_codectx_t *ctx) raise_exception_unless(builder.CreateAnd(builder.CreateFCmpOLE(src, max), builder.CreateFCmpOGE(src, min)), - jlinexacterr_var, ctx); + prepare_global(jlinexacterr_var), ctx); if (issigned) return builder.CreateFPToSI(src, intt); else @@ -608,7 +608,7 @@ static Value *emit_pointerref(jl_value_t *e, jl_value_t *i, jl_codectx_t *ctx) assert(jl_is_datatype(ety)); uint64_t size = ((jl_datatype_t*)ety)->size; Value *strct = - builder.CreateCall(jlallocobj_func, + builder.CreateCall(prepare_call(jlallocobj_func), ConstantInt::get(T_size, sizeof(void*)+size)); builder.CreateStore(literal_pointer_val((jl_value_t*)ety), @@ -760,8 +760,8 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, // but if we start looking at more bits we need to actually do the // rounding first instead of carrying around incorrect low bits. Value *x = auto_unbox(args[2],ctx); - builder.CreateStore(FP(x), builder.CreateBitCast(jlfloattemp_var,FT(x->getType())->getPointerTo()), true); - return builder.CreateFPExt(builder.CreateLoad(builder.CreateBitCast(jlfloattemp_var,FT(x->getType())->getPointerTo()), true), + builder.CreateStore(FP(x), builder.CreateBitCast(prepare_global(jlfloattemp_var),FT(x->getType())->getPointerTo()), true); + return builder.CreateFPExt(builder.CreateLoad(builder.CreateBitCast(prepare_global(jlfloattemp_var),FT(x->getType())->getPointerTo()), true), FTnbits(try_to_determine_bitstype_nbits(args[1],ctx))); } HANDLE(select_value,3) { @@ -822,7 +822,7 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, CreateICmpNE(den, ConstantInt::get(t,-1,true)), builder.CreateICmpNE(x, typemin))), - jldiverr_var, ctx); + prepare_global(jldiverr_var), ctx); return builder.CreateSDiv(x, den); HANDLE(udiv_int,2) @@ -876,7 +876,7 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, ArrayRef(ix->getType())), ix, iy); Value *obit = builder.CreateExtractValue(res, ArrayRef(1)); - raise_exception_if(obit, jlovferr_var, ctx); + raise_exception_if(obit, prepare_global(jlovferr_var), ctx); return builder.CreateExtractValue(res, ArrayRef(0)); } @@ -1133,7 +1133,7 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, Value *f = FP(x); x = FP(y); raise_exception_unless(builder.CreateOr(builder.CreateFCmpORD(f,f), builder.CreateFCmpUNO(x,x)), - jldomerr_var, ctx); + prepare_global(jldomerr_var), ctx); return f; } @@ -1198,11 +1198,11 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, #undef HANDLE static Function *boxfunc_llvm(FunctionType *ft, const std::string &cname, - void *addr) + void *addr, Module *m) { Function *f = - Function::Create(ft, Function::ExternalLinkage, cname, jl_Module); - jl_ExecutionEngine->addGlobalMapping(f, addr); + Function::Create(ft, Function::ExternalLinkage, cname, m); + add_named_global(f, addr); return f; } @@ -1223,7 +1223,7 @@ static FunctionType *ft2arg(Type *ret, Type *arg1, Type *arg2) #define BOX_F(ct,jl_ct) \ box_##ct##_func = boxfunc_llvm(ft1arg(jl_pvalue_llvmt, T_##jl_ct), \ - "jl_box_"#ct, (void*)&jl_box_##ct); + "jl_box_"#ct, (void*)&jl_box_##ct, m); static void add_intrinsic(jl_module_t *m, const std::string &name, intrinsic f) {