diff options
author | Anders Carlsson <andersca@mac.com> | 2010-02-06 23:23:06 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-02-06 23:23:06 +0000 |
commit | a508b7de6c5246ab04ed69d0ab4e9977ec1fb4d4 (patch) | |
tree | 9b5b83fb4a534e2d2decf51f1af85d1a68dae007 /lib | |
parent | 594d5e8bd9870080aad6a761538e272bc2dfcc13 (diff) |
Add support for threadsafe statics, and make them the default (matching gcc).
Daniel, I'd appreciate a review of the driver/cc1 parts.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95508 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/CGDeclCXX.cpp | 107 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 2 |
4 files changed, 96 insertions, 26 deletions
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 3d5a4e8051..0de3b0be4b 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -184,42 +184,100 @@ void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, FinishFunction(); } +static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) { + // int __cxa_guard_acquire(__int64_t *guard_object); + + const llvm::Type *Int64PtrTy = + llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); + + std::vector<const llvm::Type*> Args(1, Int64PtrTy); + + const llvm::FunctionType *FTy = + llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy), + Args, /*isVarArg=*/false); + + return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire"); +} + +static llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) { + // void __cxa_guard_release(__int64_t *guard_object); + + const llvm::Type *Int64PtrTy = + llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); + + std::vector<const llvm::Type*> Args(1, Int64PtrTy); + + const llvm::FunctionType *FTy = + llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), + Args, /*isVarArg=*/false); + + return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release"); +} + +static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) { + // void __cxa_guard_abort(__int64_t *guard_object); + + const llvm::Type *Int64PtrTy = + llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); + + std::vector<const llvm::Type*> Args(1, Int64PtrTy); + + const llvm::FunctionType *FTy = + llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), + Args, /*isVarArg=*/false); + + return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort"); +} + void CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV) { - // FIXME: This should use __cxa_guard_{acquire,release}? - - assert(!getContext().getLangOptions().ThreadsafeStatics && - "thread safe statics are currently not supported!"); - + bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics; + llvm::SmallString<256> GuardVName; CGM.getMangleContext().mangleGuardVariable(&D, GuardVName); // Create the guard variable. - llvm::GlobalValue *GuardV = - new llvm::GlobalVariable(CGM.getModule(), llvm::Type::getInt64Ty(VMContext), + const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(VMContext); + llvm::GlobalValue *GuardVariable = + new llvm::GlobalVariable(CGM.getModule(), Int64Ty, false, GV->getLinkage(), - llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)), + llvm::Constant::getNullValue(Int64Ty), GuardVName.str()); // Load the first byte of the guard variable. const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); - llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy), - "tmp"); + llvm::Value *V = + Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp"); - // Compare it against 0. - llvm::Value *nullValue - = llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext)); - llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool"); - - llvm::BasicBlock *InitBlock = createBasicBlock("init"); + llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check"); llvm::BasicBlock *EndBlock = createBasicBlock("init.end"); - // If the guard variable is 0, jump to the initializer code. - Builder.CreateCondBr(ICmp, InitBlock, EndBlock); + // Check if the first byte of the guard variable is zero. + Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"), + InitCheckBlock, EndBlock); - EmitBlock(InitBlock); + EmitBlock(InitCheckBlock); + + if (ThreadsafeStatics) { + // Call __cxa_guard_acquire. + V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable); + + llvm::BasicBlock *InitBlock = createBasicBlock("init"); + + Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), + InitBlock, EndBlock); + + EmitBlock(InitBlock); + + if (Exceptions) { + EHCleanupBlock Cleanup(*this); + + // Call __cxa_guard_abort. + Builder.CreateCall(getGuardAbortFn(*this), GuardVariable); + } + } if (D.getType()->isReferenceType()) { QualType T = D.getType(); @@ -232,9 +290,14 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, } else EmitDeclInit(*this, D, GV); - Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), - 1), - Builder.CreateBitCast(GuardV, PtrTy)); + if (ThreadsafeStatics) { + // Call __cxa_guard_release. + Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable); + } else { + llvm::Value *One = + llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1); + Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy)); + } EmitBlock(EndBlock); } diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 6c0616d370..2aa71163be 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1013,6 +1013,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, isSignedCharDefault(getToolChain().getTriple()))) CmdArgs.push_back("-fno-signed-char"); + // -fthreadsafe-static is default. + if (!Args.hasFlag(options::OPT_fthreadsafe_statics, + options::OPT_fno_threadsafe_statics)) + CmdArgs.push_back("-fno-threadsafe-statics"); + // -fms-extensions=0 is default. if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, getToolChain().getTriple().getOS() == llvm::Triple::Win32)) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 464c9938c8..5b64c7e639 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -480,8 +480,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fno-builtin"); if (!Opts.AssumeSaneOperatorNew) Res.push_back("-fno-assume-sane-operator-new"); - if (Opts.ThreadsafeStatics) - llvm::llvm_report_error("FIXME: Not yet implemented!"); + if (!Opts.ThreadsafeStatics) + Res.push_back("-fno-threadsafe-statics"); if (Opts.POSIXThreads) Res.push_back("-pthread"); if (Opts.Blocks) @@ -1155,7 +1155,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.Microsoft = Args.hasArg(OPT_fms_extensions); Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); if (Args.hasArg(OPT_fno_lax_vector_conversions)) - Opts.LaxVectorConversions = 0; + Opts.LaxVectorConversions = 0; + if (Args.hasArg(OPT_fno_threadsafe_statics)) + Opts.ThreadsafeStatics = 0; Opts.Exceptions = Args.hasArg(OPT_fexceptions); Opts.RTTI = !Args.hasArg(OPT_fno_rtti); Opts.Blocks = Args.hasArg(OPT_fblocks); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 45cd930ba0..1cdfde3488 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3005,7 +3005,6 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity, bool IsCopy) { switch (Entity.getKind()) { case InitializedEntity::EK_Result: - case InitializedEntity::EK_Exception: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Member: return !IsCopy; @@ -3014,6 +3013,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity, case InitializedEntity::EK_Variable: case InitializedEntity::EK_Base: case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_Exception: return false; case InitializedEntity::EK_Parameter: |