aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/ItaniumCXXABI.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-06-17 07:33:57 +0000
committerJohn McCall <rjmccall@apple.com>2011-06-17 07:33:57 +0000
commit0502a224984a26087ea4d64e8e5d2dd4dca432f6 (patch)
tree99b9f567851006efd02865f6ec262661b9a4fa67 /lib/CodeGen/ItaniumCXXABI.cpp
parent71c482c76c67ad4240757c4e319ffdb72272b8ee (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.cpp44
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);
}