@@ -4014,8 +4014,8 @@ static void emit_cfunc_invalidate(
4014
4014
4015
4015
static Function* gen_cfun_wrapper (
4016
4016
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,
4019
4019
jl_unionall_t *unionall_env, jl_svec_t *sparam_vals, jl_array_t **closure_types)
4020
4020
{
4021
4021
// Generate a c-callable wrapper
@@ -4027,12 +4027,11 @@ static Function* gen_cfun_wrapper(
4027
4027
jl_value_t *astrt = (jl_value_t *)jl_any_type;
4028
4028
void *callptr = NULL ;
4029
4029
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)
4033
4033
name = jl_symbol_name (lam->def .method ->name );
4034
4034
if (lam && params.cache ) {
4035
- // if (!into)
4036
4035
// TODO: this isn't ideal to be unconditionally calling type inference (and compile) from here
4037
4036
codeinst = jl_compile_method_internal (lam, world);
4038
4037
assert (codeinst->invoke );
@@ -4086,20 +4085,6 @@ static Function* gen_cfun_wrapper(
4086
4085
cw->setAttributes (attributes);
4087
4086
jl_init_function (cw);
4088
4087
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
- }
4103
4088
4104
4089
jl_codectx_t ctx (jl_LLVMContext, params);
4105
4090
ctx.f = cw;
@@ -4515,6 +4500,10 @@ static Function* gen_cfun_wrapper(
4515
4500
cw_proto = into ? cw_make : function_proto (cw_make);
4516
4501
}
4517
4502
4503
+ if (aliasname) {
4504
+ GlobalAlias::create (cw->getType ()->getElementType (), cw->getType ()->getAddressSpace (),
4505
+ GlobalValue::ExternalLinkage, aliasname, cw, M);
4506
+ }
4518
4507
if (!into)
4519
4508
jl_finalize_module (std::unique_ptr<Module>(M));
4520
4509
@@ -4628,8 +4617,8 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con
4628
4617
jl_method_instance_t *lam = sigt ? jl_get_specialization1 ((jl_tupletype_t *)sigt, world, &min_valid, &max_valid, 0 ) : NULL ;
4629
4618
Value *F = gen_cfun_wrapper (
4630
4619
jl_Module, ctx.emission_context ,
4631
- sig, fexpr_rt.constant ,
4632
- NULL , declrt, lam,
4620
+ sig, fexpr_rt.constant , NULL ,
4621
+ declrt, lam,
4633
4622
unionall_env, sparam_vals, &closure_types);
4634
4623
bool outboxed;
4635
4624
if (nest) {
@@ -4689,116 +4678,54 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con
4689
4678
return mark_julia_type (ctx, F, outboxed, output_type);
4690
4679
}
4691
4680
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)
4700
4684
{
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 );
4755
4689
jl_value_t *crt = declrt;
4756
4690
if (jl_is_abstract_ref_type (declrt)) {
4757
4691
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." );
4762
4692
crt = (jl_value_t *)jl_any_type;
4763
4693
}
4764
4694
bool toboxed;
4765
4695
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)
4769
4697
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
+ }
4791
4705
jl_value_t *err;
4792
4706
{ // scope block for sig
4793
4707
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);
4795
4709
if (sig.err_msg .empty ()) {
4796
4710
size_t world = jl_world_counter;
4797
4711
size_t min_valid = 0 ;
4798
4712
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
+ }
4802
4729
JL_GC_POP ();
4803
4730
return F;
4804
4731
}
0 commit comments