Skip to content

Commit

Permalink
lookup all ccall/cglobal values at runtime (very inefficiently)
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash committed Nov 29, 2013
1 parent dfbf414 commit 67a11cb
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 66 deletions.
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys%o: $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys%bc

$(BUILD)/$(JL_PRIVATE_LIBDIR)/sys%$(SHLIB_EXT): $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys%o
$(CXX) -g -shared -fPIC -L$(BUILD)/$(JL_PRIVATE_LIBDIR) -L$(BUILD)/$(JL_LIBDIR) -o $@ $< \
-Wl,-undefined,dynamic_lookup -Wl,--unresolved-symbols,ignore-all \
-lgrisu -lrandom -lgmp -lpcre -lmpfr $(LIBBLAS) $(LIBLAPACK) $(LIBM) $(LIBUNWIND) \
$$([ $(OS) = Darwin ] && echo -Wl,-undefined,dynamic_lookup || echo -Wl,--unresolved-symbols,ignore-all ]) \
$$([ $(OS) = WINNT ] && echo -ljulia -lssp)

$(BUILD)/$(JL_PRIVATE_LIBDIR)/sys0.bc:
Expand Down
136 changes: 75 additions & 61 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,7 @@ extern "C" const char *jl_lookup_soname(char *pfx, size_t n)
// map from user-specified lib names to handles
static std::map<std::string, void*> libMap;

extern "C" int add_library_mapping(char *lib, void *hnd)
{
JL_PUTS(const_cast<char*>("WARNING: add_library_mapping is deprecated, use push!(DL_LOAD_PATH,\"/path/to/search\") instead.\n"), JL_STDERR);
if (libMap[lib] == NULL && hnd != NULL) {
libMap[lib] = hnd;
return 0;
}
else {
return -1;
}
}

static void *add_library_sym(char *name, char *lib)
static void *get_library_sym(char *name, char *lib)
{
void *hnd;
if (lib == NULL) {
Expand All @@ -100,20 +88,7 @@ static void *add_library_sym(char *name, char *lib)
return NULL;
}
}
// add a symbol->address mapping for the JIT
void *sval = jl_dlsym_e((uv_lib_t*)hnd, name);
if (lib != NULL && hnd != jl_dl_handle) {
void *exist = sys::DynamicLibrary::SearchForAddressOfSymbol(name);
if (exist != NULL && exist != sval &&
// openlibm conflicts with libm, and lots of our libraries
// (including LLVM) link to libm. fortunately AddSymbol() is
// able to resolve these in favor of openlibm, but this could
// be an issue in the future (TODO).
strcmp(lib,"libopenlibm")) {
ios_printf(ios_stderr, "Warning: Possible conflict in library symbol %s\n", name);
}
sys::DynamicLibrary::AddSymbol(name, sval);
}
return sval;
}

Expand Down Expand Up @@ -451,38 +426,48 @@ static Value *emit_cglobal(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
else {
void *symaddr;
if (sym.f_lib != NULL)
symaddr = add_library_sym(sym.f_name, sym.f_lib);
symaddr = get_library_sym(sym.f_name, sym.f_lib);
else
symaddr = sys::DynamicLibrary::SearchForAddressOfSymbol(sym.f_name);
if (symaddr == NULL) {
std::stringstream msg;
msg << "cglobal: could not find symbol ";
msg << sym.f_name;
if (imaging_mode) {
PointerType *lrtp = PointerType::get(lrt,0);
Constant *nullval = ConstantPointerNull::get(lrtp);
GlobalValue *llvmgv = new GlobalVariable(*jl_Module, lrtp,
false, GlobalVariable::PrivateLinkage,
nullval, sym.f_name);
*((void**)jl_ExecutionEngine->getPointerToGlobal(llvmgv)) = symaddr;
BasicBlock *dlsym_lookup=BasicBlock::Create(getGlobalContext(), "dlsym-lookup"),
*cglobal_bb=BasicBlock::Create(getGlobalContext(), "cglobal");
builder.CreateCondBr(builder.CreateICmpNE(builder.CreateLoad(llvmgv), nullval), cglobal_bb, dlsym_lookup);
ctx->f->getBasicBlockList().push_back(dlsym_lookup);
builder.SetInsertPoint(dlsym_lookup);
Value *libptr;
if (sym.f_lib != NULL) {
msg << " in library ";
msg << sym.f_lib;
libptr = builder.CreateCall2(jldlopen_func, builder.CreateGlobalStringPtr(sym.f_lib), ConstantInt::get(T_int32,0));
} else {
libptr = builder.CreateCall2(jldlopen_func, ConstantPointerNull::get((PointerType*)T_pint8), ConstantInt::get(T_int32,0));
}
emit_error(msg.str(), ctx);
res = literal_static_pointer_val(NULL, lrt);
res = builder.CreateCall2(jldlsym_func, libptr, builder.CreateGlobalStringPtr(sym.f_name));
res = builder.CreatePointerCast(res, lrtp);
builder.CreateStore(res, llvmgv);
builder.CreateBr(cglobal_bb);
ctx->f->getBasicBlockList().push_back(cglobal_bb);
builder.SetInsertPoint(cglobal_bb);
res = builder.CreateLoad(llvmgv);
}
else {
Value *nv = jl_Module->getNamedValue(sym.f_name);
if (nv != NULL) {
// if the symbol already exists, it might be a function or
// something else other than a GlobalVariable, so return
// whatever it is.
res = nv;
if (res->getType() != lrt) {
// if you attempt to access a cglobal multiple times with
// different types, the type of the cached global might be
// wrong.
res = builder.CreateBitCast(res, lrt);
if (symaddr == NULL) {
std::stringstream msg;
msg << "cglobal: could not find symbol ";
msg << sym.f_name;
if (sym.f_lib != NULL) {
msg << " in library ";
msg << sym.f_lib;
}
emit_error(msg.str(), ctx);
res = literal_static_pointer_val(NULL, lrt);
}
else {
res = jl_Module->getOrInsertGlobal(sym.f_name,
lrt->getContainedType(0));
}
res = literal_static_pointer_val(symaddr, lrt);
}
}

Expand Down Expand Up @@ -691,24 +676,53 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
JL_PRINTF(JL_STDERR,"warning: literal address used in ccall for %s; code cannot be statically compiled\n", f_name);
}
else {
assert(f_name != NULL);
void *symaddr;
if (f_lib != NULL)
symaddr = add_library_sym(f_name, f_lib);
symaddr = get_library_sym(f_name, f_lib);
else
symaddr = sys::DynamicLibrary::SearchForAddressOfSymbol(f_name);
if (symaddr == NULL) {
JL_GC_POP();
std::stringstream msg;
msg << "ccall: could not find function ";
msg << f_name;
PointerType *funcptype = PointerType::get(functype,0);
if (imaging_mode) {
Constant *nullfunc = ConstantPointerNull::get(funcptype);
GlobalValue *llvmgv = new GlobalVariable(*jl_Module, funcptype,
false, GlobalVariable::PrivateLinkage,
nullfunc, f_name);
*((void**)jl_ExecutionEngine->getPointerToGlobal(llvmgv)) = symaddr;
BasicBlock *dlsym_lookup=BasicBlock::Create(getGlobalContext(), "dlsym-lookup"),
*ccall_bb=BasicBlock::Create(getGlobalContext(), "ccall");
builder.CreateCondBr(builder.CreateICmpNE(builder.CreateLoad(llvmgv), nullfunc), ccall_bb, dlsym_lookup);
ctx->f->getBasicBlockList().push_back(dlsym_lookup);
builder.SetInsertPoint(dlsym_lookup);
Value *libptr;
if (f_lib != NULL) {
msg << " in library ";
msg << f_lib;
libptr = builder.CreateCall2(jldlopen_func, builder.CreateGlobalStringPtr(f_lib), ConstantInt::get(T_int32,0));
} else {
libptr = builder.CreateCall2(jldlopen_func, ConstantPointerNull::get((PointerType*)T_pint8), ConstantInt::get(T_int32,0));
}
emit_error(msg.str(), ctx);
return literal_pointer_val(jl_nothing);
llvmf = builder.CreateCall2(jldlsym_func, libptr, builder.CreateGlobalStringPtr(f_name));
llvmf = builder.CreatePointerCast(llvmf,funcptype);
builder.CreateStore(llvmf, llvmgv);
builder.CreateBr(ccall_bb);
ctx->f->getBasicBlockList().push_back(ccall_bb);
builder.SetInsertPoint(ccall_bb);
llvmf = builder.CreateLoad(llvmgv);
}
else {
if (symaddr == NULL) {
JL_GC_POP();
std::stringstream msg;
msg << "ccall: could not find function ";
msg << f_name;
if (f_lib != NULL) {
msg << " in library ";
msg << f_lib;
}
emit_error(msg.str(), ctx);
return literal_pointer_val(jl_nothing);
}
llvmf = literal_static_pointer_val(symaddr, funcptype);
}
llvmf = jl_Module->getOrInsertFunction(f_name, functype);
}


Expand Down
2 changes: 1 addition & 1 deletion src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ static Value *julia_gv(const char *prefix, jl_sym_t *name, jl_module_t *mod, voi
static Value *literal_pointer_val(jl_value_t *p)
{
if (p == NULL)
return literal_static_pointer_val((void*)NULL, jl_pvalue_llvmt);
return ConstantPointerNull::get((PointerType*)jl_pvalue_llvmt);
if (jl_is_datatype(p)) {
jl_datatype_t* addr = (jl_datatype_t*)p;
return julia_gv("+", addr->name->name, addr->name->module, p);
Expand Down
20 changes: 20 additions & 0 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ static Function *box16_func;
static Function *box32_func;
static Function *box64_func;
static Function *jlputs_func;
static Function *jldlsym_func;
static Function *jldlopen_func;
#ifdef _OS_WINDOWS_
static Function *resetstkoflw_func;
#endif
Expand Down Expand Up @@ -3474,6 +3476,24 @@ static void init_julia_llvm_env(Module *m)
"jl_puts", jl_Module);
jl_ExecutionEngine->addGlobalMapping(jlputs_func, (void*)&jl_puts);

std::vector<Type *> dlopen_args(0);
dlopen_args.push_back(T_pint8);
dlopen_args.push_back(T_int32);
jldlopen_func =
Function::Create(FunctionType::get(T_pint8, dlopen_args, false),
Function::ExternalLinkage,
"jl_load_dynamic_library", jl_Module);
jl_ExecutionEngine->addGlobalMapping(jldlopen_func, (void*)&jl_load_dynamic_library);

std::vector<Type *> dlsym_args(0);
dlsym_args.push_back(T_pint8);
dlsym_args.push_back(T_pint8);
jldlsym_func =
Function::Create(FunctionType::get(T_pint8, dlsym_args, false),
Function::ExternalLinkage,
"jl_dlsym", jl_Module);
jl_ExecutionEngine->addGlobalMapping(jldlsym_func, (void*)&jl_dlsym);

// set up optimization passes
FPM = new FunctionPassManager(jl_Module);
#ifdef LLVM32
Expand Down
4 changes: 2 additions & 2 deletions src/dlload.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,15 @@ uv_lib_t *jl_load_dynamic_library(char *modname, unsigned flags)
return jl_load_dynamic_library_(modname, flags, 1);
}

DLLEXPORT void *jl_dlsym_e(uv_lib_t *handle, char *symbol)
void *jl_dlsym_e(uv_lib_t *handle, char *symbol)
{
void *ptr;
int error=uv_dlsym(handle, symbol, &ptr);
if (error) ptr=NULL;
return ptr;
}

DLLEXPORT void *jl_dlsym(uv_lib_t *handle, char *symbol)
void *jl_dlsym(uv_lib_t *handle, char *symbol)
{
void *ptr;
int error = uv_dlsym(handle, symbol, &ptr);
Expand Down

0 comments on commit 67a11cb

Please sign in to comment.