33#include < utility>
44#include < llvm/ADT/ArrayRef.h>
55#include < llvm/Support/Debug.h>
6+ #include < llvm/IR/Attributes.h>
67#include < llvm/IR/DebugLoc.h>
78#include < llvm/IR/IRBuilder.h>
89#include < llvm/IR/MDBuilder.h>
@@ -233,20 +234,39 @@ static inline void emit_signal_fence(llvm::IRBuilder<> &builder)
233234 builder.CreateFence (AtomicOrdering::SequentiallyConsistent, SyncScope::SingleThread);
234235}
235236
236- static inline void emit_gc_safepoint (llvm::IRBuilder<> &builder, llvm::Value *ptls, llvm::MDNode *tbaa)
237+ static inline void emit_gc_safepoint (llvm::IRBuilder<> &builder, llvm::Value *ptls, llvm::MDNode *tbaa, bool final = false )
237238{
239+ using namespace llvm ;
240+ llvm::Value *signal_page = get_current_signal_page_from_ptls (builder, ptls, tbaa);
238241 emit_signal_fence (builder);
239- builder.CreateLoad (getSizeTy (builder.getContext ()), get_current_signal_page_from_ptls (builder, ptls, tbaa), true );
242+ Module *M = builder.GetInsertBlock ()->getModule ();
243+ LLVMContext &C = builder.getContext ();
244+ // inline jlsafepoint_func->realize(M)
245+ if (final ) {
246+ auto T_size = getSizeTy (builder.getContext ());
247+ builder.CreateLoad (T_size, signal_page, true );
248+ }
249+ else {
250+ Function *F = M->getFunction (" julia.safepoint" );
251+ if (!F) {
252+ auto T_size = getSizeTy (builder.getContext ());
253+ auto T_psize = T_size->getPointerTo ();
254+ FunctionType *FT = FunctionType::get (Type::getVoidTy (C), {T_psize}, false );
255+ F = Function::Create (FT, Function::ExternalLinkage, " julia.safepoint" , M);
256+ F->addFnAttr (Attribute::InaccessibleMemOrArgMemOnly);
257+ }
258+ builder.CreateCall (F, {signal_page});
259+ }
240260 emit_signal_fence (builder);
241261}
242262
243- static inline llvm::Value *emit_gc_state_set (llvm::IRBuilder<> &builder, llvm::Value *ptls, llvm::Value *state, llvm::Value *old_state)
263+ static inline llvm::Value *emit_gc_state_set (llvm::IRBuilder<> &builder, llvm::Value *ptls, llvm::Value *state, llvm::Value *old_state, bool final )
244264{
245265 using namespace llvm ;
246266 Type *T_int8 = state->getType ();
247- ptls = emit_bitcast_with_builder (builder, ptls, builder.getInt8PtrTy ());
267+ llvm::Value *ptls_i8 = emit_bitcast_with_builder (builder, ptls, builder.getInt8PtrTy ());
248268 Constant *offset = ConstantInt::getSigned (builder.getInt32Ty (), offsetof (jl_tls_states_t , gc_state));
249- Value *gc_state = builder.CreateInBoundsGEP (T_int8, ptls , ArrayRef<Value*>(offset), " gc_state" );
269+ Value *gc_state = builder.CreateInBoundsGEP (T_int8, ptls_i8 , ArrayRef<Value*>(offset), " gc_state" );
250270 if (old_state == nullptr ) {
251271 old_state = builder.CreateLoad (T_int8, gc_state);
252272 cast<LoadInst>(old_state)->setOrdering (AtomicOrdering::Monotonic);
@@ -266,38 +286,38 @@ static inline llvm::Value *emit_gc_state_set(llvm::IRBuilder<> &builder, llvm::V
266286 passBB, exitBB);
267287 builder.SetInsertPoint (passBB);
268288 MDNode *tbaa = get_tbaa_const (builder.getContext ());
269- emit_gc_safepoint (builder, ptls, tbaa);
289+ emit_gc_safepoint (builder, ptls, tbaa, final );
270290 builder.CreateBr (exitBB);
271291 builder.SetInsertPoint (exitBB);
272292 return old_state;
273293}
274294
275- static inline llvm::Value *emit_gc_unsafe_enter (llvm::IRBuilder<> &builder, llvm::Value *ptls)
295+ static inline llvm::Value *emit_gc_unsafe_enter (llvm::IRBuilder<> &builder, llvm::Value *ptls, bool final )
276296{
277297 using namespace llvm ;
278298 Value *state = builder.getInt8 (0 );
279- return emit_gc_state_set (builder, ptls, state, nullptr );
299+ return emit_gc_state_set (builder, ptls, state, nullptr , final );
280300}
281301
282- static inline llvm::Value *emit_gc_unsafe_leave (llvm::IRBuilder<> &builder, llvm::Value *ptls, llvm::Value *state)
302+ static inline llvm::Value *emit_gc_unsafe_leave (llvm::IRBuilder<> &builder, llvm::Value *ptls, llvm::Value *state, bool final )
283303{
284304 using namespace llvm ;
285305 Value *old_state = builder.getInt8 (0 );
286- return emit_gc_state_set (builder, ptls, state, old_state);
306+ return emit_gc_state_set (builder, ptls, state, old_state, final );
287307}
288308
289- static inline llvm::Value *emit_gc_safe_enter (llvm::IRBuilder<> &builder, llvm::Value *ptls)
309+ static inline llvm::Value *emit_gc_safe_enter (llvm::IRBuilder<> &builder, llvm::Value *ptls, bool final )
290310{
291311 using namespace llvm ;
292312 Value *state = builder.getInt8 (JL_GC_STATE_SAFE);
293- return emit_gc_state_set (builder, ptls, state, nullptr );
313+ return emit_gc_state_set (builder, ptls, state, nullptr , final );
294314}
295315
296- static inline llvm::Value *emit_gc_safe_leave (llvm::IRBuilder<> &builder, llvm::Value *ptls, llvm::Value *state)
316+ static inline llvm::Value *emit_gc_safe_leave (llvm::IRBuilder<> &builder, llvm::Value *ptls, llvm::Value *state, bool final )
297317{
298318 using namespace llvm ;
299319 Value *old_state = builder.getInt8 (JL_GC_STATE_SAFE);
300- return emit_gc_state_set (builder, ptls, state, old_state);
320+ return emit_gc_state_set (builder, ptls, state, old_state, final );
301321}
302322
303323// Compatibility shims for LLVM attribute APIs that were renamed in LLVM 14.
0 commit comments