@@ -4554,6 +4554,68 @@ static void emit_stmtpos(jl_codectx_t &ctx, jl_value_t *expr, int ssaval_result)
4554
4554
}
4555
4555
}
4556
4556
4557
+ static std::pair<Function*, Function*> get_oc_function (jl_codectx_t &ctx, jl_method_t *closure_method, jl_tupletype_t *env_t , jl_tupletype_t *argt_typ, jl_value_t *rettype, bool vaOverride)
4558
+ {
4559
+ jl_svec_t *sig_args = NULL ;
4560
+ jl_value_t *sigtype = NULL ;
4561
+ jl_code_info_t *ir = NULL ;
4562
+ JL_GC_PUSH3 (&sig_args, &sigtype, &ir);
4563
+
4564
+ size_t nsig = 1 + jl_svec_len (argt_typ->parameters );
4565
+ sig_args = jl_alloc_svec_uninit (nsig);
4566
+ jl_svecset (sig_args, 0 , env_t );
4567
+ for (size_t i = 0 ; i < jl_svec_len (argt_typ->parameters ); ++i) {
4568
+ jl_svecset (sig_args, 1 +i, jl_svecref (argt_typ->parameters , i));
4569
+ }
4570
+ sigtype = (jl_value_t *)jl_apply_tuple_type_v (jl_svec_data (sig_args), nsig);
4571
+
4572
+ jl_method_instance_t *mi = jl_specializations_get_linfo (closure_method, sigtype, jl_emptysvec);
4573
+ jl_code_instance_t *ci = (jl_code_instance_t *)jl_rettype_inferred (mi, ctx.world , ctx.world );
4574
+
4575
+ if (ci == NULL || (jl_value_t *)ci == jl_nothing || ci->inferred == NULL || ci->inferred == jl_nothing) {
4576
+ JL_GC_POP ();
4577
+ return std::make_pair ((Function*)NULL , (Function*)NULL );
4578
+ }
4579
+
4580
+ ir = jl_uncompress_ir (closure_method, ci, (jl_array_t *)ci->inferred );
4581
+
4582
+ // TODO: Emit this inline and outline it late using LLVM's coroutine support.
4583
+ std::unique_ptr<Module> closure_m;
4584
+ jl_llvm_functions_t closure_decls;
4585
+ std::tie (closure_m, closure_decls) = emit_function (mi, ir, rettype, ctx.emission_context ,
4586
+ ctx.builder .getContext (), vaOverride);
4587
+
4588
+ assert (closure_decls.functionObject != " jl_fptr_sparam" );
4589
+ bool isspecsig = closure_decls.functionObject != " jl_fptr_args" ;
4590
+
4591
+ Function *F = NULL ;
4592
+ std::string fname = isspecsig ?
4593
+ closure_decls.functionObject :
4594
+ closure_decls.specFunctionObject ;
4595
+ if (GlobalValue *V = jl_Module->getNamedValue (fname)) {
4596
+ F = cast<Function>(V);
4597
+ } else {
4598
+ F = Function::Create (get_func_sig (jl_LLVMContext),
4599
+ Function::ExternalLinkage,
4600
+ fname, jl_Module);
4601
+ F->setAttributes (get_func_attrs (jl_LLVMContext));
4602
+ }
4603
+ Function *specF = NULL ;
4604
+ if (!isspecsig) {
4605
+ specF = F;
4606
+ } else {
4607
+ specF = closure_m->getFunction (closure_decls.specFunctionObject );
4608
+ if (specF) {
4609
+ jl_returninfo_t returninfo = get_specsig_function (ctx, jl_Module,
4610
+ closure_decls.specFunctionObject , sigtype, rettype, true );
4611
+ specF = returninfo.decl ;
4612
+ }
4613
+ }
4614
+ ctx.oc_modules .push_back (std::move (closure_m));
4615
+ JL_GC_POP ();
4616
+ return std::make_pair (F, specF);
4617
+ }
4618
+
4557
4619
// `expr` is not clobbered in JL_TRY
4558
4620
JL_GCC_IGNORE_START (" -Wclobbered" )
4559
4621
static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval)
@@ -4832,112 +4894,54 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval)
4832
4894
}
4833
4895
4834
4896
if (can_optimize) {
4835
- // TODO: Emit this inline and outline it late using LLVM's coroutine
4836
- // support.
4837
- jl_method_t *closure_method = (jl_method_t *)source.constant ;
4838
- jl_code_info_t *closure_src = jl_uncompress_ir (closure_method, NULL ,
4839
- (jl_array_t *)closure_method->source );
4840
-
4841
- std::unique_ptr<Module> closure_m;
4842
- jl_llvm_functions_t closure_decls;
4843
-
4844
- jl_method_instance_t *li = NULL ;
4845
4897
jl_value_t *closure_t = NULL ;
4846
4898
jl_tupletype_t *env_t = NULL ;
4847
- jl_svec_t *sig_args = NULL ;
4848
- JL_GC_PUSH5 (&li, &closure_src, &closure_t , &env_t , &sig_args);
4849
-
4850
- li = jl_new_method_instance_uninit ();
4851
- li->def .method = closure_method;
4852
- jl_tupletype_t *argt_typ = (jl_tupletype_t *)argt.constant ;
4853
-
4854
- closure_t = jl_apply_type2 ((jl_value_t *)jl_opaque_closure_type, (jl_value_t *)argt_typ, ub.constant );
4855
-
4856
- size_t nsig = 1 + jl_svec_len (argt_typ->parameters );
4857
- sig_args = jl_alloc_svec_uninit (nsig);
4858
- jl_svecset (sig_args, 0 , closure_t );
4859
- for (size_t i = 0 ; i < jl_svec_len (argt_typ->parameters ); ++i) {
4860
- jl_svecset (sig_args, 1 +i, jl_svecref (argt_typ->parameters , i));
4861
- }
4862
- li->specTypes = (jl_value_t *)jl_apply_tuple_type_v (jl_svec_data (sig_args), nsig);
4863
- jl_gc_wb (li, li->specTypes );
4864
-
4865
- std::tie (closure_m, closure_decls) = emit_function (li, closure_src,
4866
- ub.constant , ctx.emission_context , ctx.builder .getContext (), jl_unbox_bool (isva.constant ));
4899
+ JL_GC_PUSH2 (&closure_t , &env_t );
4867
4900
4868
4901
jl_value_t **env_component_ts = (jl_value_t **)alloca (sizeof (jl_value_t *) * (nargs-5 ));
4869
4902
for (size_t i = 0 ; i < nargs - 5 ; ++i) {
4870
4903
env_component_ts[i] = argv[5 +i].typ ;
4871
4904
}
4872
4905
4873
4906
env_t = jl_apply_tuple_type_v (env_component_ts, nargs-5 );
4874
- jl_cgval_t env (ctx.builder .getContext ());
4875
- // TODO: Inline the env at the end of the opaque closure and generate a descriptor for GC
4907
+ // we need to know the full env type to look up the right specialization
4876
4908
if (jl_is_concrete_type ((jl_value_t *)env_t )) {
4877
- env = emit_new_struct (ctx, (jl_value_t *)env_t , nargs-5 , &argv.data ()[5 ]);
4878
- }
4879
- else {
4880
- Value *env_val = emit_jlcall (ctx, jltuple_func, Constant::getNullValue (ctx.types ().T_prjlvalue ),
4881
- &argv[5 ], nargs-5 , JLCALL_F_CC);
4882
- env = mark_julia_type (ctx, env_val, true , env_t );
4883
- }
4884
-
4885
- assert (closure_decls.functionObject != " jl_fptr_sparam" );
4886
- bool isspecsig = closure_decls.functionObject != " jl_fptr_args" ;
4887
-
4888
- Function *F = NULL ;
4889
- std::string fname = isspecsig ?
4890
- closure_decls.functionObject :
4891
- closure_decls.specFunctionObject ;
4892
- if (GlobalValue *V = jl_Module->getNamedValue (fname)) {
4893
- F = cast<Function>(V);
4894
- }
4895
- else {
4896
- F = Function::Create (get_func_sig (ctx.builder .getContext ()),
4897
- Function::ExternalLinkage,
4898
- fname, jl_Module);
4899
- F->setAttributes (get_func_attrs (ctx.builder .getContext ()));
4900
- }
4901
- jl_cgval_t jlcall_ptr = mark_julia_type (ctx,
4902
- F, false , jl_voidpointer_type);
4903
-
4904
- jl_cgval_t fptr (ctx.builder .getContext ());
4905
- if (!isspecsig) {
4906
- fptr = jlcall_ptr;
4907
- } else {
4908
- Function *specptr = closure_m->getFunction (closure_decls.specFunctionObject );
4909
- if (specptr) {
4910
- jl_returninfo_t returninfo = get_specsig_function (ctx, jl_Module,
4911
- closure_decls.specFunctionObject , li->specTypes , ub.constant , true );
4912
- fptr = mark_julia_type (ctx, returninfo.decl , false , jl_voidpointer_type);
4913
- } else {
4914
- fptr = mark_julia_type (ctx,
4915
- (llvm::Value*)Constant::getNullValue (getSizeTy (ctx.builder .getContext ())),
4916
- false , jl_voidpointer_type);
4917
- }
4918
- }
4909
+ jl_tupletype_t *argt_typ = (jl_tupletype_t *)argt.constant ;
4910
+ Function *F, *specF;
4911
+ std::tie (F, specF) = get_oc_function (ctx, (jl_method_t *)source.constant , env_t , argt_typ, ub.constant , jl_unbox_bool (isva.constant ));
4912
+ if (F) {
4913
+ jl_cgval_t jlcall_ptr = mark_julia_type (ctx, F, false , jl_voidpointer_type);
4914
+ jl_cgval_t world_age = mark_julia_type (ctx,
4915
+ tbaa_decorate (ctx.tbaa ().tbaa_gcframe ,
4916
+ ctx.builder .CreateAlignedLoad (ctx.world_age_field , Align (sizeof (size_t )))),
4917
+ false ,
4918
+ jl_long_type);
4919
+ jl_cgval_t fptr (ctx.builder .getContext ());
4920
+ if (specF)
4921
+ fptr = mark_julia_type (ctx, specF, false , jl_voidpointer_type);
4922
+ else
4923
+ fptr = mark_julia_type (ctx, (llvm::Value*)Constant::getNullValue (getSizeTy (ctx.builder .getContext ())), false , jl_voidpointer_type);
4919
4924
4920
- jl_cgval_t world_age = mark_julia_type (ctx,
4921
- tbaa_decorate (ctx.tbaa ().tbaa_gcframe ,
4922
- ctx.builder .CreateAlignedLoad (getSizeTy (ctx.builder .getContext ()), ctx.world_age_field , Align (sizeof (size_t )))),
4923
- false ,
4924
- jl_long_type);
4925
-
4926
- jl_cgval_t closure_fields[6 ] = {
4927
- env,
4928
- isva,
4929
- world_age,
4930
- source,
4931
- jlcall_ptr,
4932
- fptr
4933
- };
4925
+ // TODO: Inline the env at the end of the opaque closure and generate a descriptor for GC
4926
+ jl_cgval_t env = emit_new_struct (ctx, (jl_value_t *)env_t , nargs-5 , &argv.data ()[5 ]);
4934
4927
4935
- jl_cgval_t ret = emit_new_struct (ctx, closure_t , 6 , closure_fields);
4928
+ jl_cgval_t closure_fields[6 ] = {
4929
+ env,
4930
+ isva,
4931
+ world_age,
4932
+ source,
4933
+ jlcall_ptr,
4934
+ fptr
4935
+ };
4936
4936
4937
- ctx.oc_modules .push_back (std::move (closure_m));
4937
+ closure_t = jl_apply_type2 ((jl_value_t *)jl_opaque_closure_type, (jl_value_t *)argt_typ, ub.constant );
4938
+ jl_cgval_t ret = emit_new_struct (ctx, closure_t , 6 , closure_fields);
4938
4939
4940
+ JL_GC_POP ();
4941
+ return ret;
4942
+ }
4943
+ }
4939
4944
JL_GC_POP ();
4940
- return ret;
4941
4945
}
4942
4946
4943
4947
return mark_julia_type (ctx,
0 commit comments