static Value *runtime_sym_lookup(PointerType *funcptype, char *f_lib, char *f_name, jl_codectx_t *ctx) { // in pseudo-code, this function emits the following: // global uv_lib_t **libptrgv // global void **llvmgv // if (*llvmgv == NULL) { // *llvmgv = jl_load_and_lookup(f_lib, f_name, libptrgv); // } // return (*llvmgv) Constant *initnul = ConstantPointerNull::get((PointerType*)T_pint8); uv_lib_t *libsym = NULL; bool runtime_lib = false; GlobalVariable *libptrgv; #ifdef _OS_WINDOWS_ 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_dl_handle; } else #endif if (f_lib == NULL) { libptrgv = prepare_global(jlRTLD_DEFAULT_var); libsym = jl_RTLD_DEFAULT_handle; } else { runtime_lib = true; libptrgv = libMapGV[f_lib]; if (libptrgv == NULL) { libptrgv = new GlobalVariable(*jl_Module, T_pint8, false, GlobalVariable::PrivateLinkage, 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, 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"), *ccall_bb = BasicBlock::Create(getGlobalContext(), "ccall"); builder.CreateCondBr(builder.CreateICmpNE(builder.CreateLoad(llvmgv), initnul), ccall_bb, dlsym_lookup); ctx->f->getBasicBlockList().push_back(dlsym_lookup); builder.SetInsertPoint(dlsym_lookup); Value *libname; if (runtime_lib) { libname = builder.CreateGlobalStringPtr(f_lib); } else { libname = literal_static_pointer_val(f_lib, T_pint8); } Value *llvmf = builder.CreateCall3(prepare_call(jldlsym_func), libname, builder.CreateGlobalStringPtr(f_name), libptrgv); builder.CreateStore(llvmf, llvmgv); builder.CreateBr(ccall_bb); ctx->f->getBasicBlockList().push_back(ccall_bb); builder.SetInsertPoint(ccall_bb); llvmf = builder.CreateLoad(llvmgv); return builder.CreatePointerCast(llvmf,funcptype); }
static Value *runtime_sym_lookup(PointerType *funcptype, char *f_lib, char *f_name, jl_codectx_t *ctx) { // in pseudo-code, this function emits the following: // global uv_lib_t **libptrgv // global void **llvmgv // if (*llvmgv == NULL) { // *llvmgv = jl_load_and_lookup(f_lib, f_name, libptrgv); // } // return (*llvmgv) Constant *initnul = ConstantPointerNull::get((PointerType*)T_pint8); uv_lib_t *libsym = NULL; 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; else #endif if (f_lib == NULL) { libptrgv = jlRTLD_DEFAULT_var; } else { runtime_lib = true; libptrgv = libMapGV[f_lib]; if (libptrgv == NULL) { libptrgv = new GlobalVariable(*jl_Module, T_pint8, false, GlobalVariable::PrivateLinkage, initnul, f_lib); libMapGV[f_lib] = libptrgv; libsym = get_library(f_lib); *((uv_lib_t**)jl_ExecutionEngine->getPointerToGlobal(libptrgv)) = libsym; } } if (libsym == NULL) { libsym = *((uv_lib_t**)jl_ExecutionEngine->getPointerToGlobal(libptrgv)); } GlobalVariable *llvmgv = symMapGV[f_name]; if (llvmgv == NULL) { llvmgv = new GlobalVariable(*jl_Module, T_pint8, false, GlobalVariable::PrivateLinkage, initnul, f_name); symMapGV[f_name] = llvmgv; *((void**)jl_ExecutionEngine->getPointerToGlobal(llvmgv)) = jl_dlsym_e(libsym, f_name); } BasicBlock *dlsym_lookup = BasicBlock::Create(getGlobalContext(), "dlsym"), *ccall_bb = BasicBlock::Create(getGlobalContext(), "ccall"); builder.CreateCondBr(builder.CreateICmpNE(builder.CreateLoad(llvmgv), initnul), ccall_bb, dlsym_lookup); ctx->f->getBasicBlockList().push_back(dlsym_lookup); builder.SetInsertPoint(dlsym_lookup); Value *libname; if (runtime_lib) { libname = builder.CreateGlobalStringPtr(f_lib); } else { libname = literal_static_pointer_val(f_lib, T_pint8); } Value *llvmf = builder.CreateCall3(jldlsym_func, libname, builder.CreateGlobalStringPtr(f_name), libptrgv); builder.CreateStore(llvmf, llvmgv); builder.CreateBr(ccall_bb); ctx->f->getBasicBlockList().push_back(ccall_bb); builder.SetInsertPoint(ccall_bb); llvmf = builder.CreateLoad(llvmgv); return builder.CreatePointerCast(llvmf,funcptype); }