[cfe-commits] r95508 - in /cfe/trunk: include/clang/Basic/LangOptions.h include/clang/Driver/CC1Options.td include/clang/Driver/Options.td lib/CodeGen/CGDeclCXX.cpp lib/Driver/Tools.cpp lib/Frontend/CompilerInvocation.cpp lib/Sema/SemaInit.cpp test/CodeGenCXX/threadsafe-statics.cpp

Anders Carlsson andersca at mac.com
Sat Feb 6 15:23:07 PST 2010


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.

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





More information about the cfe-commits mailing list