55#include " support/dtypes.h"
66#include " passes.h"
77
8+ #include " llvm/IR/BasicBlock.h"
9+ #include " llvm/IR/Instruction.h"
10+ #include " llvm/Support/Debug.h"
811#include < llvm-c/Core.h>
912#include < llvm-c/Types.h>
1013
@@ -151,7 +154,17 @@ void LowerPTLS::fix_pgcstack_use(CallInst *pgcstack, Function *pgcstack_getter,
151154 return ;
152155 }
153156 if (or_new) {
154- // pgcstack();
157+ // pgcstack = pgstack_intrinsic()
158+
159+
160+ // if (offset != 0)
161+ // pgcstack = tp + offset; // fast
162+ // else
163+ // pgcstack_getter = load pgcstack_func_slot
164+ // if pgcstack_getter == nullptr // Runtime not initialized
165+ // pgcstack = nullptr
166+ // else
167+ // pgcstack = pgcstack_getter();
155168 // if (pgcstack != nullptr)
156169 // last_gc_state = emit_gc_unsafe_enter(ctx);
157170 // phi = pgcstack; // fast
@@ -177,17 +190,25 @@ void LowerPTLS::fix_pgcstack_use(CallInst *pgcstack, Function *pgcstack_getter,
177190 if (CFGModified)
178191 *CFGModified = true ;
179192 // emit slow branch code
180- CallInst *adopt = cast<CallInst>(pgcstack->clone ());
181193 Function *adoptFunc = M->getFunction (XSTR (jl_adopt_thread));
182194 if (adoptFunc == NULL ) {
183- adoptFunc = Function::Create (pgcstack_getter-> getFunctionType ( ),
195+ adoptFunc = Function::Create (FunctionType::get (builder. getPtrTy (), { builder. getPtrTy ()}, false ),
184196 pgcstack_getter->getLinkage (), pgcstack_getter->getAddressSpace (),
185197 XSTR (jl_adopt_thread), M);
186198 adoptFunc->copyAttributesFrom (pgcstack_getter);
187199 adoptFunc->copyMetadata (pgcstack_getter, 0 );
188200 }
189- adopt->setCalledFunction (adoptFunc);
190- adopt->insertBefore (slowTerm);
201+ // Adopt thread takes in a handle to the sysimage and this is the easiest way to get it.
202+ Function *dladdr = M->getFunction (XSTR (jl_find_dynamic_library_by_addr)); // gets handle to sysimage
203+ if (dladdr == NULL ) {
204+ dladdr = Function::Create (FunctionType::get (builder.getPtrTy (), { builder.getPtrTy ()}, false ),
205+ pgcstack_getter->getLinkage (), pgcstack_getter->getAddressSpace (),
206+ XSTR (jl_find_dynamic_library_by_addr), M);
207+ }
208+ builder.SetInsertPoint (slowTerm);
209+ auto this_func = builder.GetInsertBlock ()->getParent ();
210+ auto handle = builder.CreateCall (dladdr, {ConstantExpr::getBitCast (this_func, builder.getPtrTy ())});
211+ auto adopt = builder.CreateCall (adoptFunc, {handle});
191212 phi->addIncoming (adopt, slowTerm->getParent ());
192213 // emit fast branch code
193214 builder.SetInsertPoint (fastTerm->getParent ());
@@ -213,17 +234,20 @@ void LowerPTLS::fix_pgcstack_use(CallInst *pgcstack, Function *pgcstack_getter,
213234
214235 if (imaging_mode) {
215236 IRBuilder<> builder (pgcstack);
237+ SmallVector<uint32_t , 2 > Weights{9 , 1 };
238+ MDBuilder MDB (pgcstack->getContext ());
216239 if (jl_tls_elf_support) {
217240 // if (offset != 0)
218241 // pgcstack = tp + offset; // fast
219242 // else
220- // pgcstack = getter(); // slow
243+ // if pgcstack_getter == null
244+ // pgcstack = null; // slow
245+ // else
246+ // pgcstack = pgcstack_getter(); // slow
221247 auto offset = builder.CreateLoad (T_size, pgcstack_offset);
222248 offset->setMetadata (llvm::LLVMContext::MD_tbaa, tbaa_const);
223249 offset->setMetadata (llvm::LLVMContext::MD_invariant_load, MDNode::get (pgcstack->getContext (), None));
224250 auto cmp = builder.CreateICmpNE (offset, Constant::getNullValue (offset->getType ()));
225- MDBuilder MDB (pgcstack->getContext ());
226- SmallVector<uint32_t , 2 > Weights{9 , 1 };
227251 TerminatorInst *fastTerm;
228252 TerminatorInst *slowTerm;
229253 SplitBlockAndInsertIfThenElse (cmp, pgcstack, &fastTerm, &slowTerm,
@@ -240,21 +264,53 @@ void LowerPTLS::fix_pgcstack_use(CallInst *pgcstack, Function *pgcstack_getter,
240264 // refresh the basic block in the builder
241265 builder.SetInsertPoint (pgcstack);
242266 auto getter = builder.CreateLoad (T_pgcstack_getter, pgcstack_func_slot);
267+ auto phi_value = cast<Instruction>(pgcstack);
268+ if (or_new) {
269+ // if pgcstack_func_slot is not initialized we set pgcstack to null to trigger the slow path
270+ TerminatorInst *nonNullTerm;
271+ TerminatorInst *nullTerm;
272+ auto is_null = builder.CreateICmpEQ (getter, Constant::getNullValue (builder.getPtrTy ()));
273+ SplitBlockAndInsertIfThenElse (is_null, pgcstack, &nullTerm, &nonNullTerm,
274+ MDB.createBranchWeights (Weights));
275+ builder.SetInsertPoint (pgcstack);
276+ auto phi2 = builder.CreatePHI (T_pppjlvalue, 2 , " pgcstack" );
277+ pgcstack->moveBefore (nonNullTerm);
278+ phi2->addIncoming (pgcstack, nonNullTerm->getParent ());
279+ phi2->addIncoming (Constant::getNullValue (T_pppjlvalue), nullTerm->getParent ());
280+ phi_value = phi2;
281+ // Check if pgcstack_func_slot is initialized
282+ }
243283 getter->setMetadata (llvm::LLVMContext::MD_tbaa, tbaa_const);
244284 getter->setMetadata (llvm::LLVMContext::MD_invariant_load, MDNode::get (pgcstack->getContext (), None));
245285 pgcstack->setCalledFunction (pgcstack->getFunctionType (), getter);
246286 set_pgcstack_attrs (pgcstack);
247287
248288 phi->addIncoming (fastTLS, fastTLS->getParent ());
249- phi->addIncoming (pgcstack, pgcstack->getParent ());
250-
289+ phi->addIncoming (phi_value, phi_value->getParent ());
290+ if (or_new) {
291+ pgcstack->getParent ()->getParent ()->print (dbgs ());
292+ }
251293 return ;
252294 }
253295 // In imaging mode, we emit the function address as a load of a static
254296 // variable to be filled (in `staticdata.c`) at initialization time of the sysimg.
255297 // This way we can bypass the extra indirection in `jl_get_pgcstack`
256298 // since we may not know which getter function to use ahead of time.
257299 auto getter = builder.CreateLoad (T_pgcstack_getter, pgcstack_func_slot);
300+ if (or_new) {
301+ // if pgcstack_func_slot is not initialized we set pgcstack to null to trigger the slow path
302+ TerminatorInst *nonNullTerm;
303+ TerminatorInst *nullTerm;
304+ auto is_null = builder.CreateICmpEQ (getter, Constant::getNullValue (builder.getPtrTy ()));
305+ SplitBlockAndInsertIfThenElse (is_null, pgcstack, &nullTerm, &nonNullTerm,
306+ MDB.createBranchWeights (Weights));
307+ builder.SetInsertPoint (pgcstack);
308+ auto phi2 = builder.CreatePHI (T_pppjlvalue, 2 , " pgcstack" );
309+ pgcstack->moveBefore (nonNullTerm);
310+ phi2->addIncoming (pgcstack, nonNullTerm->getParent ());
311+ phi2->addIncoming (Constant::getNullValue (T_pppjlvalue), nullTerm->getParent ());
312+ pgcstack->replaceAllUsesWith (phi2);
313+ }
258314 getter->setMetadata (llvm::LLVMContext::MD_tbaa, tbaa_const);
259315 getter->setMetadata (llvm::LLVMContext::MD_invariant_load, MDNode::get (pgcstack->getContext (), None));
260316 if (TargetTriple.isOSDarwin ()) {
0 commit comments