@@ -273,7 +273,7 @@ static int jl_analyze_workqueue(jl_code_instance_t *callee, jl_codegen_params_t
273273 std::swap (params.workqueue , edges);
274274 for (auto &it : edges) {
275275 jl_code_instance_t *codeinst = it.first ;
276- auto proto = it.second ;
276+ auto & proto = it.second ;
277277 // try to emit code for this item from the workqueue
278278 StringRef invokeName = " " ;
279279 StringRef preal_decl = " " ;
@@ -316,38 +316,38 @@ static int jl_analyze_workqueue(jl_code_instance_t *callee, jl_codegen_params_t
316316 // if we have a prototype emitted, compare it to what we emitted earlier
317317 Module *mod = proto.decl ->getParent ();
318318 assert (proto.decl ->isDeclaration ());
319- Function *preal = nullptr ;
320- if (proto.specsig != preal_specsig || preal_decl.empty ()) {
321- isedge = false ;
319+ Function *pinvoke = nullptr ;
320+ if (preal_decl.empty ()) {
322321 if (invoke != nullptr && invokeName.empty ()) {
323- if (invoke == jl_fptr_args_addr)
324- invokeName = " jl_fptr_args" ;
325- else if (invoke == jl_fptr_sparam_addr)
322+ assert (invoke != jl_fptr_args_addr);
323+ if (invoke == jl_fptr_sparam_addr)
326324 invokeName = " jl_fptr_sparam" ;
327325 else if (invoke == jl_f_opaque_closure_call_addr)
328326 invokeName = " jl_f_opaque_closure_call" ;
329327 else
330328 invokeName = jl_ExecutionEngine->getFunctionAtAddress ((uintptr_t )invoke, invoke, codeinst);
331329 }
332- preal = emit_tojlinvoke (codeinst, invokeName, mod, params);
333- if (proto.specsig ) {
334- // emit specsig-to-(jl)invoke conversion
335- proto.decl ->setLinkage (GlobalVariable::InternalLinkage);
336- // protodecl->setAlwaysInline();
337- jl_init_function (proto.decl , params.TargetTriple );
338- // TODO: maybe this can be cached in codeinst->specfptr?
339- int8_t gc_state = jl_gc_unsafe_enter (ct->ptls ); // codegen may contain safepoints (such as jl_subtype calls)
340- jl_method_instance_t *mi = codeinst->def ;
341- size_t nrealargs = jl_nparams (mi->specTypes ); // number of actual arguments being passed
342- bool is_opaque_closure = jl_is_method (mi->def .value ) && mi->def .method ->is_for_opaque_closure ;
343- emit_cfunc_invalidate (proto.decl , proto.cc , proto.return_roots , mi->specTypes , codeinst->rettype , is_opaque_closure, nrealargs, params, preal, 0 , 0 );
344- jl_gc_unsafe_leave (ct->ptls , gc_state);
345- preal_decl = " " ; // no need to fixup the name
346- }
347- else {
348- // emit jlcall1-to-(jl)invoke conversion
349- preal_decl = preal->getName ();
350- }
330+ pinvoke = emit_tojlinvoke (codeinst, invokeName, mod, params);
331+ if (!proto.specsig )
332+ proto.decl ->replaceAllUsesWith (pinvoke);
333+ isedge = false ;
334+ }
335+ if (proto.specsig && !preal_specsig) {
336+ // get or build an fptr1 that can invoke codeinst
337+ if (pinvoke == nullptr )
338+ pinvoke = get_or_emit_fptr1 (preal_decl, mod);
339+ // emit specsig-to-(jl)invoke conversion
340+ proto.decl ->setLinkage (GlobalVariable::InternalLinkage);
341+ // protodecl->setAlwaysInline();
342+ jl_init_function (proto.decl , params.TargetTriple );
343+ // TODO: maybe this can be cached in codeinst->specfptr?
344+ int8_t gc_state = jl_gc_unsafe_enter (ct->ptls ); // codegen may contain safepoints (such as jl_subtype calls)
345+ jl_method_instance_t *mi = codeinst->def ;
346+ size_t nrealargs = jl_nparams (mi->specTypes ); // number of actual arguments being passed
347+ bool is_opaque_closure = jl_is_method (mi->def .value ) && mi->def .method ->is_for_opaque_closure ;
348+ emit_specsig_to_fptr1 (proto.decl , proto.cc , proto.return_roots , mi->specTypes , codeinst->rettype , is_opaque_closure, nrealargs, params, pinvoke, 0 , 0 );
349+ jl_gc_unsafe_leave (ct->ptls , gc_state);
350+ preal_decl = " " ; // no need to fixup the name
351351 }
352352 if (!preal_decl.empty ()) {
353353 // merge and/or rename this prototype to the real function
@@ -359,26 +359,34 @@ static int jl_analyze_workqueue(jl_code_instance_t *callee, jl_codegen_params_t
359359 proto.decl ->setName (preal_decl);
360360 }
361361 }
362- if (proto.oc ) { // additionally, if we are dealing with an oc , then we might also need to fix up the fptr1 reference too
362+ if (proto.oc ) { // additionally, if we are dealing with an OC constructor , then we might also need to fix up the fptr1 reference too
363363 assert (proto.specsig );
364364 StringRef ocinvokeDecl = invokeName;
365365 if (invoke != nullptr && ocinvokeDecl.empty ()) {
366- if (invoke == jl_fptr_args_addr)
367- ocinvokeDecl = " jl_fptr_args" ;
368- else if (invoke == jl_fptr_sparam_addr)
369- ocinvokeDecl = " jl_fptr_sparam" ;
366+ // check for some special tokens used by opaque_closure.c and convert those to their real functions
367+ assert (invoke != jl_fptr_args_addr);
368+ assert (invoke != jl_fptr_sparam_addr);
369+ if (invoke == jl_fptr_interpret_call_addr)
370+ ocinvokeDecl = " jl_fptr_interpret_call" ;
371+ else if (invoke == jl_fptr_const_return_addr)
372+ ocinvokeDecl = " jl_fptr_const_return" ;
370373 else if (invoke == jl_f_opaque_closure_call_addr)
371374 ocinvokeDecl = " jl_f_opaque_closure_call" ;
375+ // else if (invoke == jl_interpret_opaque_closure_addr)
372376 else
373377 ocinvokeDecl = jl_ExecutionEngine->getFunctionAtAddress ((uintptr_t )invoke, invoke, codeinst);
374378 }
375379 // if OC expected a specialized specsig dispatch, but we don't have it, use the inner trampoline here too
376380 // XXX: this invoke translation logic is supposed to exactly match new_opaque_closure
377- if (ocinvokeDecl == " jl_fptr_args" )
378- ocinvokeDecl = preal->getName (); // TODO: use the original preal_decl it computed from specsig
379- else if (!preal_specsig || ocinvokeDecl == " jl_fptr_sparam" || ocinvokeDecl == " jl_f_opaque_closure_call" || ocinvokeDecl == " jl_fptr_interpret_call" || ocinvokeDecl == " jl_fptr_const_return" )
380- ocinvokeDecl = preal->getName ();
381+ if (!preal_specsig || ocinvokeDecl == " jl_f_opaque_closure_call" || ocinvokeDecl == " jl_fptr_interpret_call" || ocinvokeDecl == " jl_fptr_const_return" ) {
382+ if (pinvoke == nullptr )
383+ ocinvokeDecl = get_or_emit_fptr1 (preal_decl, mod)->getName ();
384+ else
385+ ocinvokeDecl = pinvoke->getName ();
386+ }
381387 assert (!ocinvokeDecl.empty ());
388+ assert (ocinvokeDecl != " jl_fptr_args" );
389+ assert (ocinvokeDecl != " jl_fptr_sparam" );
382390 // merge and/or rename this prototype to the real function
383391 if (Value *specfun = mod->getNamedValue (ocinvokeDecl)) {
384392 if (proto.oc != specfun)
0 commit comments