@@ -120,7 +120,7 @@ static Value *runtime_sym_lookup(
120120        IRBuilder<> &irbuilder,
121121        jl_codectx_t  *ctx,
122122        PointerType *funcptype, const  char  *f_lib, jl_value_t  *lib_expr,
123-         const  char  *f_name, Function *f,
123+         const  char  *f_name, const   char  *f_version,  Function *f,
124124        GlobalVariable *libptrgv,
125125        GlobalVariable *llvmgv, bool  runtime_lib)
126126{
@@ -158,8 +158,14 @@ static Value *runtime_sym_lookup(
158158    Value *nameval = stringConstPtr (emission_context, irbuilder, f_name);
159159    if  (lib_expr) {
160160        jl_cgval_t  libval = emit_expr (*ctx, lib_expr);
161-         llvmf = irbuilder.CreateCall (prepare_call_in (jl_builderModule (irbuilder), jllazydlsym_func),
162-                     { boxed (*ctx, libval), nameval });
161+         if  (f_version != NULL ) {
162+                 Value *versionval = stringConstPtr (emission_context, irbuilder, f_version);
163+                 llvmf = irbuilder.CreateCall (prepare_call_in (jl_builderModule (irbuilder), jllazydlvsym_func),
164+                             { boxed (*ctx, libval), nameval, versionval });
165+         } else  {
166+                 llvmf = irbuilder.CreateCall (prepare_call_in (jl_builderModule (irbuilder), jllazydlsym_func),
167+                             { boxed (*ctx, libval), nameval });
168+         }
163169    }
164170    else  {
165171        Value *libname;
@@ -170,8 +176,14 @@ static Value *runtime_sym_lookup(
170176            //  f_lib is actually one of the special sentinel values
171177            libname = ConstantExpr::getIntToPtr (ConstantInt::get (getSizeTy (irbuilder.getContext ()), (uintptr_t )f_lib), getInt8PtrTy (irbuilder.getContext ()));
172178        }
173-         llvmf = irbuilder.CreateCall (prepare_call_in (jl_builderModule (irbuilder), jldlsym_func),
174-                     { libname, nameval, libptrgv });
179+         if  (f_version != NULL ) {
180+                 Value *versionval = stringConstPtr (emission_context, irbuilder, f_version);
181+                 llvmf = irbuilder.CreateCall (prepare_call_in (jl_builderModule (irbuilder), jldlvsym_func),
182+                             { libname, nameval, versionval, libptrgv });
183+         } else  {
184+                 llvmf = irbuilder.CreateCall (prepare_call_in (jl_builderModule (irbuilder), jldlsym_func),
185+                             { libname, nameval, libptrgv });
186+         }
175187    }
176188    StoreInst *store = irbuilder.CreateAlignedStore (llvmf, llvmgv, Align (sizeof (void *)));
177189    store->setAtomic (AtomicOrdering::Release);
@@ -188,18 +200,18 @@ static Value *runtime_sym_lookup(
188200static  Value *runtime_sym_lookup (
189201        jl_codectx_t  &ctx,
190202        PointerType *funcptype, const  char  *f_lib, jl_value_t  *lib_expr,
191-         const  char  *f_name, Function *f,
203+         const  char  *f_name, const   char  *f_version,  Function *f,
192204        GlobalVariable *libptrgv,
193205        GlobalVariable *llvmgv, bool  runtime_lib)
194206{
195207    return  runtime_sym_lookup (ctx.emission_context , ctx.builder , &ctx, funcptype, f_lib, lib_expr,
196-                               f_name, f, libptrgv, llvmgv, runtime_lib);
208+                               f_name, f_version,  f, libptrgv, llvmgv, runtime_lib);
197209}
198210
199211static  Value *runtime_sym_lookup (
200212        jl_codectx_t  &ctx,
201213        PointerType *funcptype, const  char  *f_lib, jl_value_t  *lib_expr,
202-         const  char  *f_name, Function *f)
214+         const  char  *f_name, const   char  *f_version,  Function *f)
203215{
204216    auto  T_pvoidfunc = JuliaType::get_pvoidfunc_ty (ctx.builder .getContext ());
205217    GlobalVariable *libptrgv;
@@ -223,15 +235,16 @@ static Value *runtime_sym_lookup(
223235        libptrgv = prepare_global_in (jl_Module, libptrgv);
224236    }
225237    llvmgv = prepare_global_in (jl_Module, llvmgv);
226-     return  runtime_sym_lookup (ctx, funcptype, f_lib, lib_expr, f_name, f, libptrgv, llvmgv, runtime_lib);
238+     return  runtime_sym_lookup (ctx, funcptype, f_lib, lib_expr, f_name, f_version,  f, libptrgv, llvmgv, runtime_lib);
227239}
228240
229241//  Emit a "PLT" entry that will be lazily initialized
230242//  when being called the first time.
231243static  GlobalVariable *emit_plt_thunk (
232244        jl_codectx_t  &ctx,
233245        FunctionType *functype, const  AttributeList &attrs,
234-         CallingConv::ID cc, const  char  *f_lib, const  char  *f_name,
246+         CallingConv::ID cc,
247+         const  char  *f_lib, const  char  *f_name, const  char  *f_version,
235248        GlobalVariable *libptrgv, GlobalVariable *llvmgv,
236249        bool  runtime_lib)
237250{
@@ -256,8 +269,8 @@ static GlobalVariable *emit_plt_thunk(
256269                                             fname);
257270    BasicBlock *b0 = BasicBlock::Create (M->getContext (), " top" 
258271    IRBuilder<> irbuilder (b0);
259-     Value *ptr = runtime_sym_lookup (ctx.emission_context , irbuilder, NULL , funcptype, f_lib,  NULL , f_name, plt, libptrgv, 
260-                                     llvmgv, runtime_lib);
272+     Value *ptr = runtime_sym_lookup (ctx.emission_context , irbuilder, NULL , funcptype,
273+                                     f_lib,  NULL , f_name, f_version, plt, libptrgv,  llvmgv, runtime_lib);
261274    StoreInst *store = irbuilder.CreateAlignedStore (irbuilder.CreateBitCast (ptr, T_pvoidfunc), got, Align (sizeof (void *)));
262275    store->setAtomic (AtomicOrdering::Release);
263276    SmallVector<Value*, 16 > args;
@@ -303,7 +316,8 @@ static Value *emit_plt(
303316        jl_codectx_t  &ctx,
304317        FunctionType *functype,
305318        const  AttributeList &attrs,
306-         CallingConv::ID cc, const  char  *f_lib, const  char  *f_name)
319+         CallingConv::ID cc,
320+         const  char  *f_lib, const  char  *f_name, const  char  *f_version)
307321{
308322    ++PLT;
309323    assert (ctx.emission_context .imaging );
@@ -320,7 +334,7 @@ static Value *emit_plt(
320334    GlobalVariable *&sharedgot = pltMap[key];
321335    if  (!sharedgot) {
322336        sharedgot = emit_plt_thunk (ctx,
323-                 functype, attrs, cc, f_lib, f_name, libptrgv, llvmgv, runtime_lib);
337+                 functype, attrs, cc, f_lib, f_name, f_version,  libptrgv, llvmgv, runtime_lib);
324338    }
325339    GlobalVariable *got = prepare_global_in (jl_Module, sharedgot);
326340    LoadInst *got_val = ctx.builder .CreateAlignedLoad (got->getValueType (), got, Align (sizeof (void *)));
@@ -565,6 +579,7 @@ typedef struct {
565579    void  (*fptr)(void );     //  if the argument is a constant pointer
566580    const  char  *f_name;   //  if the symbol name is known
567581    const  char  *f_lib;    //  if a library name is specified
582+     const  char  *f_version;
568583    jl_value_t  *lib_expr; //  expression to compute library path lazily
569584    jl_value_t  *gcroot;
570585} native_sym_arg_t ;
@@ -576,6 +591,8 @@ static void interpret_symbol_arg(jl_codectx_t &ctx, native_sym_arg_t &out, jl_va
576591    void  (*&fptr)(void ) = out.fptr ;
577592    const  char  *&f_name = out.f_name ;
578593    const  char  *&f_lib = out.f_lib ;
594+     const  char  *&f_version = out.f_version ;
595+     f_version = NULL ;
579596
580597    jl_value_t  *ptr = static_eval (ctx, arg);
581598    if  (ptr == NULL ) {
@@ -709,20 +726,29 @@ static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t narg
709726    }
710727    else  {
711728        if  (sym.lib_expr ) {
712-             res = runtime_sym_lookup (ctx, cast<PointerType>(getInt8PtrTy (ctx.builder .getContext ())), NULL , sym.lib_expr , sym.f_name , ctx.f );
729+             res = runtime_sym_lookup (ctx, cast<PointerType>(getInt8PtrTy (ctx.builder .getContext ())), NULL ,
730+                                      sym.lib_expr , sym.f_name , sym.f_version , ctx.f );
713731        }
714732        else  if  (ctx.emission_context .imaging ) {
715-             res = runtime_sym_lookup (ctx, cast<PointerType>(getInt8PtrTy (ctx.builder .getContext ())), sym.f_lib , NULL , sym.f_name , ctx.f );
733+             res = runtime_sym_lookup (ctx, cast<PointerType>(getInt8PtrTy (ctx.builder .getContext ())),
734+                                      sym.f_lib , NULL , sym.f_name , sym.f_version , ctx.f );
716735            res = ctx.builder .CreatePtrToInt (res, lrt);
717736        }
718737        else  {
719738            void  *symaddr;
720739
721740            void * libsym = jl_get_library_ (sym.f_lib , 0 );
722-             if  (!libsym || !jl_dlsym (libsym, sym.f_name , &symaddr, 0 )) {
741+             int  symbol_found = 0 ;
742+             if  (sym.f_version  != NULL ) {
743+                 symbol_found = jl_dlvsym (libsym, sym.f_name , sym.f_version , &symaddr, 0 );
744+             } else  {
745+                 symbol_found = jl_dlsym (libsym, sym.f_name , &symaddr, 0 );
746+             }
747+             if  (!libsym || !symbol_found) {
723748                //  Error mode, either the library or the symbol couldn't be find during compiletime.
724749                //  Fallback to a runtime symbol lookup.
725-                 res = runtime_sym_lookup (ctx, cast<PointerType>(getInt8PtrTy (ctx.builder .getContext ())), sym.f_lib , NULL , sym.f_name , ctx.f );
750+                 res = runtime_sym_lookup (ctx, cast<PointerType>(getInt8PtrTy (ctx.builder .getContext ())),
751+                                          sym.f_lib , NULL , sym.f_name , sym.f_version , ctx.f );
726752                res = ctx.builder .CreatePtrToInt (res, lrt);
727753            } else  {
728754                //  since we aren't saving this code, there's no sense in
@@ -2043,25 +2069,31 @@ jl_cgval_t function_sig_t::emit_a_ccall(
20432069        PointerType *funcptype = PointerType::get (functype, 0 );
20442070        if  (symarg.lib_expr ) {
20452071            ++DeferredCCallLookups;
2046-             llvmf = runtime_sym_lookup (ctx, funcptype, NULL , symarg.lib_expr , symarg.f_name , ctx.f );
2072+             llvmf = runtime_sym_lookup (ctx, funcptype, NULL , symarg.lib_expr , symarg.f_name , symarg. f_version ,  ctx.f );
20472073        }
20482074        else  if  (ctx.emission_context .imaging ) {
20492075            ++DeferredCCallLookups;
20502076            //  vararg requires musttail,
20512077            //  but musttail is incompatible with noreturn.
20522078            if  (functype->isVarArg ())
2053-                 llvmf = runtime_sym_lookup (ctx, funcptype, symarg.f_lib , NULL , symarg.f_name , ctx.f );
2079+                 llvmf = runtime_sym_lookup (ctx, funcptype, symarg.f_lib , NULL , symarg.f_name , symarg. f_version ,  ctx.f );
20542080            else 
2055-                 llvmf = emit_plt (ctx, functype, attributes, cc, symarg.f_lib , symarg.f_name );
2081+                 llvmf = emit_plt (ctx, functype, attributes, cc, symarg.f_lib , symarg.f_name , symarg. f_version );
20562082        }
20572083        else  {
20582084            void  *symaddr;
20592085            void  *libsym = jl_get_library_ (symarg.f_lib , 0 );
2060-             if  (!libsym || !jl_dlsym (libsym, symarg.f_name , &symaddr, 0 )) {
2086+             int  symbol_found = 0 ;
2087+             if  (symarg.f_version  != NULL ) {
2088+                 symbol_found = jl_dlvsym (libsym, symarg.f_name , symarg.f_version , &symaddr, 0 );
2089+             } else  {
2090+                 symbol_found = jl_dlsym (libsym, symarg.f_name , &symaddr, 0 );
2091+             }
2092+             if  (!libsym || !symbol_found) {
20612093                ++DeferredCCallLookups;
20622094                //  either the library or the symbol could not be found, place a runtime
20632095                //  lookup here instead.
2064-                 llvmf = runtime_sym_lookup (ctx, funcptype, symarg.f_lib , NULL , symarg.f_name , ctx.f );
2096+                 llvmf = runtime_sym_lookup (ctx, funcptype, symarg.f_lib , NULL , symarg.f_name , symarg. f_version ,  ctx.f );
20652097            } else  {
20662098                ++LiteralCCalls;
20672099                //  since we aren't saving this code, there's no sense in
0 commit comments