diff options
author | John McCall <rjmccall@apple.com> | 2011-06-17 07:33:57 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-06-17 07:33:57 +0000 |
commit | 0502a224984a26087ea4d64e8e5d2dd4dca432f6 (patch) | |
tree | 99b9f567851006efd02865f6ec262661b9a4fa67 /lib/CodeGen/ItaniumCXXABI.cpp | |
parent | 71c482c76c67ad4240757c4e319ffdb72272b8ee (diff) |
Perform an acquire memory barrier on the fast path of a thread-safe
static initializer check, as required by the Itanium ABI.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133250 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/ItaniumCXXABI.cpp')
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 7e71df1268..34dafef545 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -24,6 +24,7 @@ #include "CodeGenModule.h" #include <clang/AST/Mangle.h> #include <clang/AST/Type.h> +#include <llvm/Intrinsics.h> #include <llvm/Target/TargetData.h> #include <llvm/Value.h> @@ -1088,19 +1089,19 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // We only need to use thread-safe statics for local variables; // global initialization is always single-threaded. - bool ThreadsafeStatics = (getContext().getLangOptions().ThreadsafeStatics && - D.isLocalVarDecl()); + bool threadsafe = + (getContext().getLangOptions().ThreadsafeStatics && D.isLocalVarDecl()); const llvm::IntegerType *GuardTy; // If we have a global variable with internal linkage and thread-safe statics // are disabled, we can just let the guard variable be of type i8. - bool UseInt8GuardVariable = !ThreadsafeStatics && GV->hasInternalLinkage(); - if (UseInt8GuardVariable) - GuardTy = Builder.getInt8Ty(); - else { + bool useInt8GuardVariable = !threadsafe && GV->hasInternalLinkage(); + if (useInt8GuardVariable) { + GuardTy = CGF.Int8Ty; + } else { // Guard variables are 64 bits in the generic ABI and 32 bits on ARM. - GuardTy = (IsARM ? Builder.getInt32Ty() : Builder.getInt64Ty()); + GuardTy = (IsARM ? CGF.Int32Ty : CGF.Int64Ty); } const llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo(); @@ -1132,7 +1133,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // if (__cxa_guard_acquire(&obj_guard)) // ... // } - if (IsARM && !UseInt8GuardVariable) { + if (IsARM && !useInt8GuardVariable) { llvm::Value *V = Builder.CreateLoad(GuardVariable); V = Builder.CreateAnd(V, Builder.getInt32(1)); IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized"); @@ -1163,13 +1164,16 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check"); llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); + llvm::BasicBlock *NoCheckBlock = EndBlock; + if (threadsafe) NoCheckBlock = CGF.createBasicBlock("init.barrier"); + // Check if the first byte of the guard variable is zero. - Builder.CreateCondBr(IsInitialized, InitCheckBlock, EndBlock); + Builder.CreateCondBr(IsInitialized, InitCheckBlock, NoCheckBlock); CGF.EmitBlock(InitCheckBlock); // Variables used when coping with thread-safe statics and exceptions. - if (ThreadsafeStatics) { + if (threadsafe) { // Call __cxa_guard_acquire. llvm::Value *V = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable); @@ -1188,7 +1192,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // Emit the initializer and add a global destructor if appropriate. CGF.EmitCXXGlobalVarDeclInit(D, GV); - if (ThreadsafeStatics) { + if (threadsafe) { // Pop the guard-abort cleanup if we pushed one. CGF.PopCleanupBlock(); @@ -1198,5 +1202,23 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable); } + // Emit an acquire memory barrier if using thread-safe statics: + // Itanium ABI: + // An implementation supporting thread-safety on multiprocessor + // systems must also guarantee that references to the initialized + // object do not occur before the load of the initialization flag. + if (threadsafe) { + Builder.CreateBr(EndBlock); + CGF.EmitBlock(NoCheckBlock); + + llvm::Value *_false = Builder.getFalse(); + llvm::Value *_true = Builder.getTrue(); + + Builder.CreateCall5(CGM.getIntrinsic(llvm::Intrinsic::memory_barrier), + /* load-load, load-store */ _true, _true, + /* store-load, store-store */ _false, _false, + /* device or I/O */ _false); + } + CGF.EmitBlock(EndBlock); } |