On Sat, Feb 6, 2010 at 3:23 PM, Anders Carlsson <[email protected]> wrote: > Author: andersca > Date: Sat Feb 6 17:23:06 2010 > New Revision: 95508 > > URL: http://llvm.org/viewvc/llvm-project?rev=95508&view=rev > Log: > Add support for threadsafe statics, and make them the default (matching gcc). > > Daniel, I'd appreciate a review of the driver/cc1 parts.
Looks good to me. - Daniel > Added: > cfe/trunk/test/CodeGenCXX/threadsafe-statics.cpp > Modified: > cfe/trunk/include/clang/Basic/LangOptions.h > cfe/trunk/include/clang/Driver/CC1Options.td > cfe/trunk/include/clang/Driver/Options.td > cfe/trunk/lib/CodeGen/CGDeclCXX.cpp > cfe/trunk/lib/Driver/Tools.cpp > cfe/trunk/lib/Frontend/CompilerInvocation.cpp > cfe/trunk/lib/Sema/SemaInit.cpp > > Modified: cfe/trunk/include/clang/Basic/LangOptions.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=95508&r1=95507&r2=95508&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Basic/LangOptions.h (original) > +++ cfe/trunk/include/clang/Basic/LangOptions.h Sat Feb 6 17:23:06 2010 > @@ -136,8 +136,7 @@ > > SymbolVisibility = (unsigned) Default; > > - // FIXME: The default should be 1. > - ThreadsafeStatics = 0; > + ThreadsafeStatics = 1; > POSIXThreads = 0; > Blocks = 0; > BlockIntrospection = 0; > > Modified: cfe/trunk/include/clang/Driver/CC1Options.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=95508&r1=95507&r2=95508&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Driver/CC1Options.td (original) > +++ cfe/trunk/include/clang/Driver/CC1Options.td Sat Feb 6 17:23:06 2010 > @@ -115,6 +115,8 @@ > HelpText<"Don't generate implicit floating point instructions (x86-only)">; > def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, > HelpText<"Disallow merging of constants.">; > +def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, > + HelpText<"Do not emit code to make initialization of local statics thread > safe">; > def masm_verbose : Flag<"-masm-verbose">, > HelpText<"Generate verbose assembly output">; > def mcode_model : Separate<"-mcode-model">, > > Modified: cfe/trunk/include/clang/Driver/Options.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=95508&r1=95507&r2=95508&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Driver/Options.td (original) > +++ cfe/trunk/include/clang/Driver/Options.td Sat Feb 6 17:23:06 2010 > @@ -311,6 +311,7 @@ > def fno_show_source_location : Flag<"-fno-show-source-location">, > Group<f_Group>; > def fno_stack_protector : Flag<"-fno-stack-protector">, Group<f_Group>; > def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, > Group<clang_ignored_f_Group>; > +def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>; > def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>; > def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>; > def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>; > @@ -351,6 +352,7 @@ > def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>; > def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>; > def fterminated_vtables : Flag<"-fterminated-vtables">, Group<f_Group>; > +def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>; > def ftime_report : Flag<"-ftime-report">, Group<f_Group>; > def ftrapv : Flag<"-ftrapv">, Group<f_Group>; > def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>; > > Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=95508&r1=95507&r2=95508&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Sat Feb 6 17:23:06 2010 > @@ -184,42 +184,100 @@ > 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); > - > - EmitBlock(InitBlock); > + // Check if the first byte of the guard variable is zero. > + Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"), > + InitCheckBlock, EndBlock); > + > + 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 @@ > } 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); > } > > Modified: cfe/trunk/lib/Driver/Tools.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=95508&r1=95507&r2=95508&view=diff > > ============================================================================== > --- cfe/trunk/lib/Driver/Tools.cpp (original) > +++ cfe/trunk/lib/Driver/Tools.cpp Sat Feb 6 17:23:06 2010 > @@ -1013,6 +1013,11 @@ > 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)) > > Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=95508&r1=95507&r2=95508&view=diff > > ============================================================================== > --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original) > +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Sat Feb 6 17:23:06 2010 > @@ -480,8 +480,8 @@ > 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 @@ > 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); > > Modified: cfe/trunk/lib/Sema/SemaInit.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=95508&r1=95507&r2=95508&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaInit.cpp (original) > +++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Feb 6 17:23:06 2010 > @@ -3005,7 +3005,6 @@ > 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 @@ > case InitializedEntity::EK_Variable: > case InitializedEntity::EK_Base: > case InitializedEntity::EK_VectorElement: > + case InitializedEntity::EK_Exception: > return false; > > case InitializedEntity::EK_Parameter: > > Added: cfe/trunk/test/CodeGenCXX/threadsafe-statics.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/threadsafe-statics.cpp?rev=95508&view=auto > > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/threadsafe-statics.cpp (added) > +++ cfe/trunk/test/CodeGenCXX/threadsafe-statics.cpp Sat Feb 6 17:23:06 2010 > @@ -0,0 +1,17 @@ > +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck -check-prefix=WITH-TSS %s > +// RUN: %clang_cc1 -emit-llvm -o - %s -fno-threadsafe-statics | FileCheck > -check-prefix=NO-TSS %s > + > +int f(); > + > +// WITH-TSS: define void @_Z1gv() nounwind > +// WITH-TSS: call i32 @__cxa_guard_acquire > +// WITH-TSS: call void @__cxa_guard_release > +// WITH-TSS: ret void > +void g() { > + static int a = f(); > +} > + > +// NO-TSS: define void @_Z1gv() nounwind > +// NO-TSS-NOT: call i32 @__cxa_guard_acquire > +// NO-TSS-NOT: call void @__cxa_guard_release > +// NO-TSS: ret void > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
