================ @@ -1070,13 +1084,20 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, // Mark as initialized before initializing anything else. If the // initializers use previously-initialized thread_local vars, that's // probably supposed to be OK, but the standard doesn't say. - Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard); - - // The guard variable can't ever change again. + // Get the thread-local address via intrinsic. + if (IsTLS) + GuardAddr = GuardAddr.withPointer( + Builder.CreateThreadLocalAddress(Guard.getPointer()), + NotKnownNonNull); + Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1), + GuardAddr); + + // Emit invariant start for TLS guard address. EmitInvariantStart( Guard.getPointer(), CharUnits::fromQuantity( - CGM.getDataLayout().getTypeAllocSize(GuardVal->getType()))); + CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())), + IsTLS); ---------------- rjmccall wrote:
I feel like we just need to file a DR with WG21 on this general question. The alternatives I can see: 1. Forbid TLVs in coroutines. Source-breaking. 2. Continue to eagerly initialize local TLVs in coroutines, but bind the name permanently to the TLV that was initialized. This means it is potentially a cross-thread reference after a suspension. It is the user's responsibility to make that not a problem. A semantics change for most (if not at all) existing compilers. 3. Like #2, but give references to the TLV undefined behavior if the thread has changed. The most compatible option, sadly. 4. Like #2, but make the program statically ill-formed if a suspension potentially intervenes between the initialization and a reference to the TLV. Source-breaking. Also a significant new implementation burden for compilers. 5. Switch local TLVs in coroutines to the same lazy-initialization model as global TLVs. Every reference to the variable dynamically resolves to the TLV for the current thread. Because of the model change, the variable is always initialized. A semantics change for most (if not all) existing compilers. 6. Like #5, but require the initializer to be a constant expression just to try to minimize the semantic impact. Note that a cross-thread reference can race not just with read/write or write/write conflicts between threads, but also with the destruction of the other thread. Because of the latter, it will be a potentially-dangling reference for most async-like use cases. https://github.com/llvm/llvm-project/pull/96633 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits