@@ -4014,8 +4014,8 @@ static void emit_cfunc_invalidate(
40144014
40154015static Function* gen_cfun_wrapper (
40164016 Module *into, jl_codegen_params_t ¶ms,
4017- const function_sig_t &sig, jl_value_t *ff,
4018- jl_typemap_entry_t *sf, jl_value_t *declrt, jl_method_instance_t *lam,
4017+ const function_sig_t &sig, jl_value_t *ff, const char *aliasname,
4018+ jl_value_t *declrt, jl_method_instance_t *lam,
40194019 jl_unionall_t *unionall_env, jl_svec_t *sparam_vals, jl_array_t **closure_types)
40204020{
40214021 // Generate a c-callable wrapper
@@ -4027,12 +4027,11 @@ static Function* gen_cfun_wrapper(
40274027 jl_value_t *astrt = (jl_value_t *)jl_any_type;
40284028 void *callptr = NULL ;
40294029 int calltype = 0 ;
4030- // infer it first, if necessary
4031- // FIXME! pretend this is OK
4032- if (lam)
4030+ if (aliasname)
4031+ name = aliasname;
4032+ else if (lam)
40334033 name = jl_symbol_name (lam->def .method ->name );
40344034 if (lam && params.cache ) {
4035- // if (!into)
40364035 // TODO: this isn't ideal to be unconditionally calling type inference (and compile) from here
40374036 codeinst = jl_compile_method_internal (lam, world);
40384037 assert (codeinst->invoke );
@@ -4086,20 +4085,6 @@ static Function* gen_cfun_wrapper(
40864085 cw->setAttributes (attributes);
40874086 jl_init_function (cw);
40884087 Function *cw_proto = into ? cw : function_proto (cw);
4089- // Save the Function object reference
4090- if (sf) {
4091- jl_value_t *oldsf = sf->func .value ;
4092- size_t i, oldlen = jl_svec_len (oldsf);
4093- jl_value_t *newsf = (jl_value_t *)jl_alloc_svec (oldlen + 2 );
4094- JL_GC_PUSH1 (&newsf);
4095- jl_svecset (newsf, 0 , sig.rt );
4096- jl_svecset (newsf, 1 , jl_box_voidpointer ((void *)cw_proto));
4097- for (i = 0 ; i < oldlen; i++)
4098- jl_svecset (newsf, i + 2 , jl_svecref (oldsf, i));
4099- sf->func .value = newsf;
4100- jl_gc_wb (sf, sf->func .value );
4101- JL_GC_POP ();
4102- }
41034088
41044089 jl_codectx_t ctx (jl_LLVMContext, params);
41054090 ctx.f = cw;
@@ -4515,6 +4500,10 @@ static Function* gen_cfun_wrapper(
45154500 cw_proto = into ? cw_make : function_proto (cw_make);
45164501 }
45174502
4503+ if (aliasname) {
4504+ GlobalAlias::create (cw->getType ()->getElementType (), cw->getType ()->getAddressSpace (),
4505+ GlobalValue::ExternalLinkage, aliasname, cw, M);
4506+ }
45184507 if (!into)
45194508 jl_finalize_module (std::unique_ptr<Module>(M));
45204509
@@ -4628,8 +4617,8 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con
46284617 jl_method_instance_t *lam = sigt ? jl_get_specialization1 ((jl_tupletype_t *)sigt, world, &min_valid, &max_valid, 0 ) : NULL ;
46294618 Value *F = gen_cfun_wrapper (
46304619 jl_Module, ctx.emission_context ,
4631- sig, fexpr_rt.constant ,
4632- NULL , declrt, lam,
4620+ sig, fexpr_rt.constant , NULL ,
4621+ declrt, lam,
46334622 unionall_env, sparam_vals, &closure_types);
46344623 bool outboxed;
46354624 if (nest) {
@@ -4689,116 +4678,54 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con
46894678 return mark_julia_type (ctx, F, outboxed, output_type);
46904679}
46914680
4692- const struct jl_typemap_info cfunction_cache = {
4693- 1 , (jl_datatype_t **)&jl_array_any_type
4694- };
4695-
4696- jl_array_t *jl_cfunction_list;
4697-
4698- Function *jl_cfunction_object (jl_function_t *ff, jl_value_t *declrt, jl_tupletype_t *argt,
4699- jl_codegen_params_t ¶ms)
4681+ // do codegen to create a C-callable alias/wrapper, or if sysimg_handle is set,
4682+ // restore one from a loaded system image.
4683+ Function *jl_generate_ccallable (void *llvmmod, void *sysimg_handle, jl_value_t *declrt, jl_value_t *sigt, jl_codegen_params_t ¶ms)
47004684{
4701- // Assumes the codegen lock is acquired. The caller is responsible for that.
4702- jl_ptls_t ptls = jl_get_ptls_states ();
4703- if (ptls->in_pure_callback )
4704- jl_error (" cfunction cannot be used in a generated function" );
4705-
4706- // validate and unpack the arguments
4707- JL_TYPECHK (cfunction, type, declrt);
4708- if (!jl_is_tuple_type (argt)) // the C API requires that argt Tuple type actually be an svec
4709- jl_type_error (" cfunction" , (jl_value_t *)jl_anytuple_type_type, (jl_value_t *)argt);
4710- // trampolines are not supported here:
4711- // check that f is a guaranteed singleton type
4712- jl_value_t *ft = jl_typeof (ff);
4713- if (((jl_datatype_t *)ft)->instance != ff)
4714- jl_error (" cfunction: use `@cfunction` to make closures" );
4715-
4716- // check the cache structure
4717- // this has three levels (for the 3 parameters above)
4718- // first split on `ft` using a simple eqtable
4719- // then use the typemap to split on argt
4720- // and finally, pick declrt from the pair-list
4721- jl_typemap_t *cache_l2 = NULL ;
4722- jl_typemap_entry_t *cache_l3 = NULL ;
4723- if (!jl_cfunction_list) {
4724- jl_cfunction_list = jl_alloc_vec_any (16 );
4725- }
4726- else {
4727- cache_l2 = jl_eqtable_get (jl_cfunction_list, ft, NULL );
4728- if (cache_l2) {
4729- struct jl_typemap_assoc search = {(jl_value_t *)argt, 1 , NULL , 0 , ~(size_t )0 };
4730- cache_l3 = jl_typemap_assoc_by_type (cache_l2, &search, /* offs*/ 0 , /* subtype*/ 0 );
4731- if (cache_l3) {
4732- jl_svec_t *sf = (jl_svec_t *)cache_l3->func .value ;
4733- size_t i, l = jl_svec_len (sf);
4734- for (i = 0 ; i < l; i += 2 ) {
4735- jl_value_t *ti = jl_svecref (sf, i);
4736- if (jl_egal (ti, declrt)) {
4737- return (Function*)jl_unbox_voidpointer (jl_svecref (sf, i + 1 ));
4738- }
4739- }
4740- }
4741- }
4742- }
4743-
4744- if (cache_l3 == NULL ) {
4745- jl_typemap_t *insert = cache_l2;
4746- if (!insert)
4747- insert = jl_nothing;
4748- cache_l3 = jl_typemap_insert (&insert, (jl_value_t *)insert, (jl_tupletype_t *)argt,
4749- NULL , jl_emptysvec, (jl_value_t *)jl_emptysvec, /* offs*/ 0 , &cfunction_cache, 1 , ~(size_t )0 );
4750- if (insert != cache_l2)
4751- jl_cfunction_list = jl_eqtable_put (jl_cfunction_list, ft, insert, NULL );
4752- }
4753-
4754- // compute / validate return type
4685+ jl_datatype_t *ft = (jl_datatype_t *)jl_tparam0 (sigt);
4686+ jl_value_t *ff = ft->instance ;
4687+ assert (ff);
4688+ const char *name = jl_symbol_name (ft->name ->mt ->name );
47554689 jl_value_t *crt = declrt;
47564690 if (jl_is_abstract_ref_type (declrt)) {
47574691 declrt = jl_tparam0 (declrt);
4758- if (jl_is_typevar (declrt))
4759- jl_error (" cfunction: return type Ref should have an element type, not Ref{<:T}" );
4760- if (declrt == (jl_value_t *)jl_any_type)
4761- jl_error (" cfunction: return type Ref{Any} is invalid. Use Any or Ptr{Any} instead." );
47624692 crt = (jl_value_t *)jl_any_type;
47634693 }
47644694 bool toboxed;
47654695 Type *lcrt = _julia_struct_to_llvm (¶ms, crt, NULL , &toboxed);
4766- if (lcrt == NULL )
4767- jl_error (" cfunction: return type doesn't correspond to a C type" );
4768- else if (toboxed)
4696+ if (toboxed)
47694697 lcrt = T_prjlvalue;
4770-
4771- // compute / validate method signature
4772- jl_value_t *sigt = NULL ; // dispatch sig: type signature (argt) with Ref{} annotations removed and ft added
4773- JL_GC_PUSH1 (&sigt);
4774- size_t i, nargs = jl_nparams (argt);
4775- sigt = (jl_value_t *)jl_alloc_svec (nargs + 1 );
4776- jl_svecset (sigt, 0 , ft);
4777- for (i = 0 ; i < nargs; i++) {
4778- jl_value_t *ati = jl_tparam (argt, i);
4779- if (jl_is_abstract_ref_type (ati)) {
4780- ati = jl_tparam0 (ati);
4781- if (jl_is_typevar (ati))
4782- jl_error (" cfunction: argument type Ref should have an element type, not Ref{<:T}" );
4783- }
4784- if (jl_is_pointer (ati) && jl_is_typevar (jl_tparam0 (ati)))
4785- jl_error (" cfunction: argument type Ptr should have an element type, Ptr{<:T}" );
4786- jl_svecset (sigt, i + 1 , ati);
4787- }
4788- sigt = (jl_value_t *)jl_apply_tuple_type ((jl_svec_t *)sigt);
4789-
4790- // emit cfunction (trampoline)
4698+ size_t nargs = jl_nparams (sigt)-1 ;
4699+ jl_svec_t *argtypes = NULL ;
4700+ JL_GC_PUSH1 (&argtypes);
4701+ argtypes = jl_alloc_svec (nargs);
4702+ for (size_t i = 0 ; i < nargs; i++) {
4703+ jl_svecset (argtypes, i, jl_tparam (sigt, i+1 ));
4704+ }
47914705 jl_value_t *err;
47924706 { // scope block for sig
47934707 function_sig_t sig (" cfunction" , lcrt, crt, toboxed,
4794- argt-> parameters , NULL , false , CallingConv::C, false , ¶ms);
4708+ argtypes , NULL , false , CallingConv::C, false , ¶ms);
47954709 if (sig.err_msg .empty ()) {
47964710 size_t world = jl_world_counter;
47974711 size_t min_valid = 0 ;
47984712 size_t max_valid = ~(size_t )0 ;
4799- // try to look up this function for direct invoking
4800- jl_method_instance_t *lam = jl_get_specialization1 ((jl_tupletype_t *)sigt, world, &min_valid, &max_valid, 0 );
4801- Function *F = gen_cfun_wrapper (NULL , params, sig, ff, cache_l3, declrt, lam, NULL , NULL , NULL );
4713+ Function *F = NULL ;
4714+ if (sysimg_handle) {
4715+ // restore a ccallable from the system image
4716+ void *addr;
4717+ int found = jl_dlsym (sysimg_handle, name, &addr, 0 );
4718+ if (found) {
4719+ FunctionType *ftype = sig.functype ();
4720+ F = Function::Create (ftype, GlobalVariable::ExternalLinkage,
4721+ name, shadow_output);
4722+ add_named_global (F, addr);
4723+ }
4724+ }
4725+ else {
4726+ jl_method_instance_t *lam = jl_get_specialization1 ((jl_tupletype_t *)sigt, world, &min_valid, &max_valid, 0 );
4727+ F = gen_cfun_wrapper ((Module*)llvmmod, params, sig, ff, name, declrt, lam, NULL , NULL , NULL );
4728+ }
48024729 JL_GC_POP ();
48034730 return F;
48044731 }
0 commit comments