3
3
#include < utility>
4
4
#include < llvm/ADT/ArrayRef.h>
5
5
#include < llvm/Support/Debug.h>
6
+ #include < llvm/IR/Attributes.h>
6
7
#include < llvm/IR/DebugLoc.h>
7
8
#include < llvm/IR/IRBuilder.h>
8
9
#include < llvm/IR/MDBuilder.h>
@@ -233,20 +234,39 @@ static inline void emit_signal_fence(llvm::IRBuilder<> &builder)
233
234
builder.CreateFence (AtomicOrdering::SequentiallyConsistent, SyncScope::SingleThread);
234
235
}
235
236
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 )
237
238
{
239
+ using namespace llvm ;
240
+ llvm::Value *signal_page = get_current_signal_page_from_ptls (builder, ptls, tbaa);
238
241
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
+ }
240
260
emit_signal_fence (builder);
241
261
}
242
262
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 )
244
264
{
245
265
using namespace llvm ;
246
266
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 ());
248
268
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" );
250
270
if (old_state == nullptr ) {
251
271
old_state = builder.CreateLoad (T_int8, gc_state);
252
272
cast<LoadInst>(old_state)->setOrdering (AtomicOrdering::Monotonic);
@@ -266,38 +286,38 @@ static inline llvm::Value *emit_gc_state_set(llvm::IRBuilder<> &builder, llvm::V
266
286
passBB, exitBB);
267
287
builder.SetInsertPoint (passBB);
268
288
MDNode *tbaa = get_tbaa_const (builder.getContext ());
269
- emit_gc_safepoint (builder, ptls, tbaa);
289
+ emit_gc_safepoint (builder, ptls, tbaa, final );
270
290
builder.CreateBr (exitBB);
271
291
builder.SetInsertPoint (exitBB);
272
292
return old_state;
273
293
}
274
294
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 )
276
296
{
277
297
using namespace llvm ;
278
298
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 );
280
300
}
281
301
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 )
283
303
{
284
304
using namespace llvm ;
285
305
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 );
287
307
}
288
308
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 )
290
310
{
291
311
using namespace llvm ;
292
312
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 );
294
314
}
295
315
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 )
297
317
{
298
318
using namespace llvm ;
299
319
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 );
301
321
}
302
322
303
323
// Compatibility shims for LLVM attribute APIs that were renamed in LLVM 14.
0 commit comments