- Use MangleNumeringContext for the guard variable bit index.

Hi rjmccall,

http://llvm-reviews.chandlerc.com/D1416

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1416?vs=3516&id=3615#toc

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/Mangle.h
  include/clang/AST/MangleNumberingContext.h
  include/clang/Sema/Sema.h
  lib/AST/ASTContext.cpp
  lib/AST/CXXABI.h
  lib/AST/ItaniumCXXABI.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MangleNumberingContext.cpp
  lib/AST/MicrosoftCXXABI.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/CodeGen/CGCXXABI.cpp
  lib/CodeGen/CGCXXABI.h
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaLambda.cpp
  test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
  test/CodeGenCXX/microsoft-abi-static-initializers.cpp
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -19,7 +19,6 @@
 #include "clang/AST/CanonicalType.h"
 #include "clang/AST/CommentCommandTraits.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/MangleNumberingContext.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/RawCommentList.h"
@@ -59,6 +58,7 @@
   class SelectorTable;
   class TargetInfo;
   class CXXABI;
+  class MangleNumberingContext;
   // Decls
   class MangleContext;
   class ObjCIvarDecl;
@@ -353,7 +353,7 @@
   /// \brief Mapping from each declaration context to its corresponding
   /// mangling numbering context (used for constructs like lambdas which
   /// need to be consistently numbered for the mangler).
-  llvm::DenseMap<const DeclContext *, MangleNumberingContext>
+  llvm::DenseMap<const DeclContext *, MangleNumberingContext *>
       MangleNumberingContexts;
 
   /// \brief Side-table of mangling numbers for declarations which rarely
@@ -2118,6 +2118,8 @@
   /// DeclContext.
   MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
 
+  MangleNumberingContext *createMangleNumberingContext() const;
+
   /// \brief Used by ParmVarDecl to store on the side the
   /// index of the parameter when it exceeds the size of the normal bitfield.
   void setParameterIndex(const ParmVarDecl *D, unsigned index);
Index: include/clang/AST/Mangle.h
===================================================================
--- include/clang/AST/Mangle.h
+++ include/clang/AST/Mangle.h
@@ -139,11 +139,11 @@
   void mangleObjCMethodName(const ObjCMethodDecl *MD,
                             raw_ostream &);
 
-  // This is pretty lame.
-  virtual void mangleItaniumGuardVariable(const VarDecl *D,
-                                          raw_ostream &) {
-    llvm_unreachable("Target does not support mangling guard variables");
-  }
+  virtual void mangleStaticGuardVariable(const VarDecl *D,
+                                         raw_ostream &Out) = 0;
+  virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
+                                             raw_ostream &Out) = 0;
+
   // FIXME: Revisit this once we know what we need to do for MSVC compatibility.
   virtual void mangleItaniumThreadLocalInit(const VarDecl *D,
                                             raw_ostream &) {
Index: include/clang/AST/MangleNumberingContext.h
===================================================================
--- include/clang/AST/MangleNumberingContext.h
+++ include/clang/AST/MangleNumberingContext.h
@@ -33,10 +33,11 @@
 class MangleNumberingContext 
     : public RefCountedBase<MangleNumberingContext> {
   llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
-  llvm::DenseMap<IdentifierInfo*, unsigned> VarManglingNumbers;
   llvm::DenseMap<IdentifierInfo*, unsigned> TagManglingNumbers;
 
 public:
+  virtual ~MangleNumberingContext();
+
   /// \brief Retrieve the mangling number of a new lambda expression with the
   /// given call operator within this context.
   unsigned getManglingNumber(const CXXMethodDecl *CallOperator);
@@ -47,7 +48,7 @@
 
   /// \brief Retrieve the mangling number of a static local variable within
   /// this context.
-  unsigned getManglingNumber(const VarDecl *VD);
+  virtual unsigned getManglingNumber(const VarDecl *VD) = 0;
 
   /// \brief Retrieve the mangling number of a static local variable within
   /// this context.
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -703,12 +703,7 @@
 
     /// \brief Retrieve the mangling numbering context, used to consistently
     /// number constructs like lambdas for mangling.
-    MangleNumberingContext &getMangleNumberingContext() {
-      assert(ManglingContextDecl && "Need to have a context declaration");
-      if (!MangleNumbering)
-        MangleNumbering = new MangleNumberingContext;
-      return *MangleNumbering;
-    }
+    MangleNumberingContext &getMangleNumberingContext(ASTContext &Ctx);
 
     bool isUnevaluated() const {
       return Context == Unevaluated || Context == UnevaluatedAbstract;
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExternalASTSource.h"
 #include "clang/AST/Mangle.h"
+#include "clang/AST/MangleNumberingContext.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeLoc.h"
@@ -766,6 +767,12 @@
                                                     AEnd = DeclAttrs.end();
        A != AEnd; ++A)
     A->second->~AttrVec();
+
+  for (llvm::DenseMap<const DeclContext *, MangleNumberingContext *>::iterator
+           I = MangleNumberingContexts.begin(),
+           E = MangleNumberingContexts.end();
+       I != E; ++I)
+    delete I->second;
 }
 
 void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
@@ -8017,7 +8024,15 @@
 
 MangleNumberingContext &
 ASTContext::getManglingNumberContext(const DeclContext *DC) {
-  return MangleNumberingContexts[DC];
+  assert(LangOpts.CPlusPlus);  // We don't need mangling numbers for plain C.
+  MangleNumberingContext *&MCtx = MangleNumberingContexts[DC];
+  if (!MCtx)
+    MCtx = createMangleNumberingContext();
+  return *MCtx;
+}
+
+MangleNumberingContext *ASTContext::createMangleNumberingContext() const {
+  return ABI->createMangleNumberingContext();
 }
 
 void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
Index: lib/AST/CXXABI.h
===================================================================
--- lib/AST/CXXABI.h
+++ lib/AST/CXXABI.h
@@ -21,6 +21,7 @@
 
 class ASTContext;
 class MemberPointerType;
+class MangleNumberingContext;
 
 /// Implements C++ ABI-specific semantic analysis functions.
 class CXXABI {
@@ -34,9 +35,12 @@
   /// Returns the default calling convention for C++ methods.
   virtual CallingConv getDefaultMethodCallConv(bool isVariadic) const = 0;
 
-  // Returns whether the given class is nearly empty, with just virtual pointers
-  // and no data except possibly virtual bases.
+  /// Returns whether the given class is nearly empty, with just virtual
+  /// pointers and no data except possibly virtual bases.
   virtual bool isNearlyEmpty(const CXXRecordDecl *RD) const = 0;
+
+  /// Returns a new mangling number context for this C++ ABI.
+  virtual MangleNumberingContext *createMangleNumberingContext() const = 0;
 };
 
 /// Creates an instance of a C++ ABI class.
Index: lib/AST/ItaniumCXXABI.cpp
===================================================================
--- lib/AST/ItaniumCXXABI.cpp
+++ lib/AST/ItaniumCXXABI.cpp
@@ -20,13 +20,27 @@
 #include "CXXABI.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/MangleNumberingContext.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/TargetInfo.h"
 
 using namespace clang;
 
 namespace {
+
+/// \brief Keeps track of the mangled names of lambda expressions and block
+/// literals within a particular context.
+class ItaniumNumberingContext : public MangleNumberingContext {
+  llvm::DenseMap<IdentifierInfo*, unsigned> VarManglingNumbers;
+
+public:
+  /// Variable decls are numbered by identifier.
+  virtual unsigned getManglingNumber(const VarDecl *VD) {
+    return ++VarManglingNumbers[VD->getIdentifier()];
+  }
+};
+
 class ItaniumCXXABI : public CXXABI {
 protected:
   ASTContext &Context;
@@ -61,6 +75,10 @@
       Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
     return Layout.getNonVirtualSize() == PointerSize;
   }
+
+  virtual MangleNumberingContext *createMangleNumberingContext() const {
+    return new ItaniumNumberingContext();
+  }
 };
 
 class ARMCXXABI : public ItaniumCXXABI {
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -152,7 +152,8 @@
   void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
                      raw_ostream &);
 
-  void mangleItaniumGuardVariable(const VarDecl *D, raw_ostream &);
+  void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &);
+  void mangleDynamicAtExitDestructor(const VarDecl *D, raw_ostream &Out);
   void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &);
   void mangleItaniumThreadLocalWrapper(const VarDecl *D, raw_ostream &);
 
@@ -3696,15 +3697,26 @@
 
 /// mangleGuardVariable - Returns the mangled name for a guard variable
 /// for the passed in VarDecl.
-void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D,
-                                                      raw_ostream &Out) {
+void ItaniumMangleContext::mangleStaticGuardVariable(const VarDecl *D,
+                                                     raw_ostream &Out) {
   //  <special-name> ::= GV <object name>       # Guard variable for one-time
   //                                            # initialization
   CXXNameMangler Mangler(*this, Out);
   Mangler.getStream() << "_ZGV";
   Mangler.mangleName(D);
 }
 
+void ItaniumMangleContext::mangleDynamicAtExitDestructor(const VarDecl *D,
+                                                         raw_ostream &Out) {
+  // Prefix the mangling of D with __dtor_.
+  CXXNameMangler Mangler(*this, Out);
+  Mangler.getStream() << "__dtor_";
+  if (shouldMangleDeclName(D))
+    Mangler.mangle(D);
+  else
+    Mangler.getStream() << D->getName();
+}
+
 void ItaniumMangleContext::mangleItaniumThreadLocalInit(const VarDecl *D,
                                                         raw_ostream &Out) {
   //  <special-name> ::= TH <object name>
Index: lib/AST/MangleNumberingContext.cpp
===================================================================
--- lib/AST/MangleNumberingContext.cpp
+++ lib/AST/MangleNumberingContext.cpp
@@ -18,6 +18,8 @@
 
 using namespace clang;
 
+MangleNumberingContext::~MangleNumberingContext() {}
+
 unsigned
 MangleNumberingContext::getManglingNumber(const CXXMethodDecl *CallOperator) {
   const FunctionProtoType *Proto
@@ -38,11 +40,6 @@
 }
 
 unsigned
-MangleNumberingContext::getManglingNumber(const VarDecl *VD) {
-  return ++VarManglingNumbers[VD->getIdentifier()];
-}
-
-unsigned
 MangleNumberingContext::getManglingNumber(const TagDecl *TD) {
   return ++TagManglingNumbers[TD->getIdentifier()];
 }
Index: lib/AST/MicrosoftCXXABI.cpp
===================================================================
--- lib/AST/MicrosoftCXXABI.cpp
+++ lib/AST/MicrosoftCXXABI.cpp
@@ -16,13 +16,30 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/MangleNumberingContext.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/TargetInfo.h"
 
 using namespace clang;
 
 namespace {
+
+/// \brief Numbers things which need to correspond across multiple TUs.
+/// Typically these are things like static locals, lambdas, or blocks.
+class MicrosoftNumberingContext : public MangleNumberingContext {
+  unsigned NumStaticLocals;
+
+public:
+  MicrosoftNumberingContext() : NumStaticLocals(0) { }
+
+  /// Static locals are numbered by source order.
+  virtual unsigned getManglingNumber(const VarDecl *VD) {
+    assert(VD->isStaticLocal());
+    return ++NumStaticLocals;
+  }
+};
+
 class MicrosoftCXXABI : public CXXABI {
   ASTContext &Context;
 public:
@@ -51,6 +68,10 @@
     return Layout.getNonVirtualSize() == PointerSize ||
       Layout.getNonVirtualSize() == PointerSize * 2;
   }    
+
+  MangleNumberingContext *createMangleNumberingContext() const {
+    return new MicrosoftNumberingContext();
+  }
 };
 }
 
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -92,15 +92,15 @@
                   QualifierMangleMode QMM = QMM_Mangle);
   void mangleFunctionType(const FunctionType *T, const FunctionDecl *D,
                           bool IsStructor, bool IsInstMethod);
+  void manglePostfix(const DeclContext *DC, bool NoFunction = false);
 
 private:
   void disableBackReferences() { UseNameBackReferences = false; }
   void mangleUnqualifiedName(const NamedDecl *ND) {
     mangleUnqualifiedName(ND, ND->getDeclName());
   }
   void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name);
   void mangleSourceName(const IdentifierInfo *II);
-  void manglePostfix(const DeclContext *DC, bool NoFunction=false);
   void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
   void mangleCXXDtorType(CXXDtorType T);
   void mangleQualifiers(Qualifiers Quals, bool IsMember);
@@ -169,8 +169,10 @@
                              raw_ostream &);
   virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
                              raw_ostream &);
-  virtual void mangleReferenceTemporary(const clang::VarDecl *,
-                                        raw_ostream &);
+  virtual void mangleReferenceTemporary(const VarDecl *, raw_ostream &);
+  virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out);
+  virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
+                                             raw_ostream &Out);
 };
 
 }
@@ -1935,13 +1937,44 @@
   MicrosoftCXXNameMangler mangler(*this, Out, D, Type);
   mangler.mangle(D);
 }
-void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *VD,
+void MicrosoftMangleContext::mangleReferenceTemporary(const VarDecl *VD,
                                                       raw_ostream &) {
   unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
     "cannot mangle this reference temporary yet");
   getDiags().Report(VD->getLocation(), DiagID);
 }
 
+void MicrosoftMangleContext::mangleStaticGuardVariable(const VarDecl *VD,
+                                                       raw_ostream &Out) {
+  // <guard-name> ::= ?_B <postfix> @51
+  //              ::= ?$S <guard-num> @ <postfix> @4IA
+
+  // The first mangling is what MSVC uses to guard static locals in inline
+  // functions.  It uses a different mangling in external functions to support
+  // guarding more than 32 variables.  MSVC rejects inline functions with more
+  // than 32 static locals.  We don't fully implement the second mangling
+  // because those guards are not externally visible, and instead use LLVM's
+  // default renaming when creating a new guard variable.
+  MicrosoftCXXNameMangler Mangler(*this, Out);
+
+  bool Visible = VD->isExternallyVisible();
+  // <operator-name> ::= ?_B # local static guard
+  Mangler.getStream() << (Visible ? "\01??_B" : "\01?$S1@");
+  Mangler.manglePostfix(VD->getDeclContext());
+  Mangler.getStream() << (Visible ? "@51" : "@4IA");
+}
+
+void MicrosoftMangleContext::mangleDynamicAtExitDestructor(const VarDecl *D,
+                                                           raw_ostream &Out) {
+  // <destructor-name> ::= ?__F <postfix> YAXXZ
+  MicrosoftCXXNameMangler Mangler(*this, Out);
+  Mangler.getStream() << "\01??__F";
+  Mangler.mangleName(D);
+  // This is the mangling of the function type of the stub, which is a global,
+  // non-variadic, cdecl function that returns void and takes no args.
+  Mangler.getStream() << "YAXXZ";
+}
+
 MangleContext *clang::createMicrosoftMangleContext(ASTContext &Context,
                                                    DiagnosticsEngine &Diags) {
   return new MicrosoftMangleContext(Context, Diags);
Index: lib/CodeGen/CGCXXABI.cpp
===================================================================
--- lib/CodeGen/CGCXXABI.cpp
+++ lib/CodeGen/CGCXXABI.cpp
@@ -212,22 +212,15 @@
   return llvm::ConstantInt::get(CGF.SizeTy, 0);
 }
 
-void CGCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
-                               const VarDecl &D,
-                               llvm::GlobalVariable *GV,
-                               bool PerformInit) {
-  ErrorUnsupportedABI(CGF, "static local variable initialization");
-}
-
 void CGCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
                                   const VarDecl &D,
                                   llvm::Constant *dtor,
                                   llvm::Constant *addr) {
   if (D.getTLSKind())
     CGM.ErrorUnsupported(&D, "non-trivial TLS destruction");
 
   // The default behavior is to use atexit.
-  CGF.registerGlobalDtorWithAtExit(dtor, addr);
+  CGF.registerGlobalDtorWithAtExit(D, dtor, addr);
 }
 
 /// Returns the adjustment, in bytes, required for the given
Index: lib/CodeGen/CGCXXABI.h
===================================================================
--- lib/CodeGen/CGCXXABI.h
+++ lib/CodeGen/CGCXXABI.h
@@ -383,7 +383,8 @@
   ///   - a static local variable
   ///   - a static data member of a class template instantiation
   virtual void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
-                               llvm::GlobalVariable *DeclPtr, bool PerformInit);
+                               llvm::GlobalVariable *DeclPtr,
+                               bool PerformInit) = 0;
 
   /// Emit code to force the execution of a destructor during global
   /// teardown.  The default implementation of this uses atexit.
Index: lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- lib/CodeGen/CGDeclCXX.cpp
+++ lib/CodeGen/CGDeclCXX.cpp
@@ -162,13 +162,18 @@
 /// Create a stub function, suitable for being passed to atexit,
 /// which passes the given address to the given destructor function.
 static llvm::Constant *createAtExitStub(CodeGenModule &CGM,
+                                        const VarDecl &D,
                                         llvm::Constant *dtor,
                                         llvm::Constant *addr) {
   // Get the destructor function type, void(*)(void).
   llvm::FunctionType *ty = llvm::FunctionType::get(CGM.VoidTy, false);
+  SmallString<256> FnName;
+  {
+    llvm::raw_svector_ostream Out(FnName);
+    CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&D, Out);
+  }
   llvm::Function *fn =
-    CreateGlobalInitOrDestructFunction(CGM, ty,
-                                       Twine("__dtor_", addr->getName()));
+      CreateGlobalInitOrDestructFunction(CGM, ty, FnName.str());
 
   CodeGenFunction CGF(CGM);
 
@@ -192,10 +197,11 @@
 }
 
 /// Register a global destructor using the C atexit runtime function.
-void CodeGenFunction::registerGlobalDtorWithAtExit(llvm::Constant *dtor,
+void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &D,
+                                                   llvm::Constant *dtor,
                                                    llvm::Constant *addr) {
   // Create a function which calls the destructor.
-  llvm::Constant *dtorStub = createAtExitStub(CGM, dtor, addr);
+  llvm::Constant *dtorStub = createAtExitStub(CGM, D, dtor, addr);
 
   // extern "C" int atexit(void (*f)(void));
   llvm::FunctionType *atexitTy =
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -2311,7 +2311,8 @@
 
   /// Call atexit() with a function that passes the given argument to
   /// the given function.
-  void registerGlobalDtorWithAtExit(llvm::Constant *fn, llvm::Constant *addr);
+  void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::Constant *fn,
+                                    llvm::Constant *addr);
 
   /// Emit code in this function to perform a guarded variable
   /// initialization.  Guarded initializations are used when it's not
Index: lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -1125,7 +1125,7 @@
     SmallString<256> guardName;
     {
       llvm::raw_svector_ostream out(guardName);
-      getMangleContext().mangleItaniumGuardVariable(&D, out);
+      getMangleContext().mangleStaticGuardVariable(&D, out);
       out.flush();
     }
 
@@ -1293,7 +1293,7 @@
     return CGM.AddCXXDtorEntry(dtor, addr);
   }
 
-  CGF.registerGlobalDtorWithAtExit(dtor, addr);
+  CGF.registerGlobalDtorWithAtExit(D, dtor, addr);
 }
 
 /// Get the appropriate linkage for the wrapper function. This is essentially
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -278,6 +278,10 @@
 private:
   /// VBTables - All the vbtables which have been referenced.
   llvm::DenseMap<const CXXRecordDecl *, VBTableVector> VBTablesMap;
+
+  /// Map from DeclContext to the current guard variable.  We assume that the
+  /// AST is visited in source code order.
+  llvm::DenseMap<const DeclContext *, llvm::GlobalVariable *> GuardVariableMap;
 };
 
 }
@@ -619,17 +623,80 @@
 }
 
 void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
-                                      llvm::GlobalVariable *DeclPtr,
+                                      llvm::GlobalVariable *GV,
                                       bool PerformInit) {
-  // FIXME: this code was only tested for global initialization.
-  // Not sure whether we want thread-safe static local variables as VS
-  // doesn't make them thread-safe.
+  // MSVC always uses an i32 bitfield to guard initialization, which is *not*
+  // threadsafe.  Since the user may be linking in inline functions compiled by
+  // cl.exe, there's no reason to provide a false sense of security by using
+  // critical sections here.
 
   if (D.getTLSKind())
     CGM.ErrorUnsupported(&D, "dynamic TLS initialization");
 
-  // Emit the initializer and add a global destructor if appropriate.
-  CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit);
+  CGBuilderTy &Builder = CGF.Builder;
+  llvm::IntegerType *GuardTy = CGF.Int32Ty;
+  llvm::ConstantInt *Zero = llvm::ConstantInt::get(GuardTy, 0);
+
+  // Get the guard variable for this function if we have one already.
+  llvm::GlobalVariable *&Guard = GuardVariableMap[D.getDeclContext()];
+
+  // Get the bit that we need to use for this static.  We have to track it
+  // through Sema because CodeGen might not see all statics depending on
+  // optimization levels.
+  unsigned BitIdx = getContext().getManglingNumber(&D);
+  assert(BitIdx > 0);
+  BitIdx--;
+  if (BitIdx >= 32) {
+    if (D.isExternallyVisible())
+      ErrorUnsupportedABI(CGF, "more than 32 guarded initializations");
+    BitIdx %= 32;
+    Guard = 0;
+  }
+
+  // Lazily create the i32 bitfield for this function.
+  if (!Guard) {
+    // Mangle the name for the guard.
+    SmallString<256> GuardName;
+    {
+      llvm::raw_svector_ostream Out(GuardName);
+      getMangleContext().mangleStaticGuardVariable(&D, Out);
+      Out.flush();
+    }
+
+    // Create the guard variable with a zero-initializer.  Just absorb linkage
+    // and visibility from the guarded variable.
+    Guard = new llvm::GlobalVariable(CGM.getModule(), GuardTy, false,
+                                     GV->getLinkage(), Zero, GuardName.str());
+    Guard->setVisibility(GV->getVisibility());
+  } else {
+    assert(Guard->getLinkage() == GV->getLinkage() &&
+           "static local from the same function had different linkage");
+  }
+
+  // Pseudo code for the test:
+  // if (!(GuardVar & MyGuardBit)) {
+  //   GuardVar |= MyGuardBit;
+  //   ... initialize the object ...;
+  // }
+
+  // Test our bit from the guard variable.
+  llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1U << BitIdx);
+  llvm::LoadInst *LI = Builder.CreateLoad(Guard);
+  llvm::Value *IsInitialized =
+      Builder.CreateICmpNE(Builder.CreateAnd(LI, Bit), Zero);
+  llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
+  llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
+  Builder.CreateCondBr(IsInitialized, EndBlock, InitBlock);
+
+  // Set our bit in the guard variable and emit the initializer and add a global
+  // destructor if appropriate.
+  CGF.EmitBlock(InitBlock);
+  Builder.CreateStore(Builder.CreateOr(LI, Bit), Guard);
+  CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
+  Builder.CreateBr(EndBlock);
+
+  // Continue.
+  CGF.EmitBlock(EndBlock);
 }
 
 // Member pointer helpers.
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -3049,6 +3049,9 @@
 }
 
 static void HandleTagNumbering(Sema &S, const TagDecl *Tag) {
+  if (!S.Context.getLangOpts().CPlusPlus)
+    return;
+
   if (isa<CXXRecordDecl>(Tag->getParent())) {
     // If this tag is the direct child of a class, number it if
     // it is anonymous.
@@ -5308,7 +5311,7 @@
       isIncompleteDeclExternC(*this, NewVD))
     RegisterLocallyScopedExternCDecl(NewVD, S);
 
-  if (NewVD->isStaticLocal()) {
+  if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) {
     Decl *ManglingContextDecl;
     if (MangleNumberingContext *MCtx =
             getCurrentMangleNumberContext(NewVD->getDeclContext(),
Index: lib/Sema/SemaLambda.cpp
===================================================================
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 #include "clang/Sema/DeclSpec.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
@@ -92,9 +93,12 @@
   case Normal:
     //  -- the bodies of non-exported nonspecialized template functions
     //  -- the bodies of inline functions
+    //  -- the bodies of regular functions in the Microsoft ABI
     if ((IsInNonspecializedTemplate &&
          !(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) ||
-        isInInlineFunction(CurContext)) {
+        isInInlineFunction(CurContext) ||
+        (isa<FunctionDecl>(CurContext) &&
+         Context.getTargetInfo().getCXXABI().isMicrosoft())) {
       ManglingContextDecl = 0;
       return &Context.getManglingNumberContext(DC);
     }
@@ -114,12 +118,21 @@
     //  -- the in-class initializers of class members
   case DefaultArgument:
     //  -- default arguments appearing in class definitions
-    return &ExprEvalContexts.back().getMangleNumberingContext();
+    return &ExprEvalContexts.back().getMangleNumberingContext(Context);
   }
 
   llvm_unreachable("unexpected context");
 }
 
+MangleNumberingContext &
+Sema::ExpressionEvaluationContextRecord::getMangleNumberingContext(
+    ASTContext &Ctx) {
+  assert(ManglingContextDecl && "Need to have a context declaration");
+  if (!MangleNumbering)
+    MangleNumbering = Ctx.createMangleNumberingContext();
+  return *MangleNumbering;
+}
+
 CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
                  SourceRange IntroducerRange,
                  TypeSourceInfo *MethodType,
Index: test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
===================================================================
--- test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
+++ test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
@@ -20,7 +20,7 @@
 // CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 12] [local] [def] [__dtor_glob]
 // CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 13] [local] [def] [__cxx_global_var_init1]
 // CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 13] [local] [def] [__cxx_global_array_dtor]
-// CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 13] [local] [def] [__dtor_]
+// CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 13] [local] [def] [__dtor_array]
 // CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 16] [local] [def] [__dtor__ZZ3foovE4stat]
 // CHECK-NOKEXT: [ DW_TAG_subprogram ] [line {{.*}}] [local] [def] [_GLOBAL__I_a]
 
Index: test/CodeGenCXX/microsoft-abi-static-initializers.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-static-initializers.cpp
+++ test/CodeGenCXX/microsoft-abi-static-initializers.cpp
@@ -1,19 +1,81 @@
 // RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
 
 struct S {
-  S() {}
-  ~S() {}
-} s;
+  S();
+  ~S();
+};
+
+S s;
 
 // CHECK: define internal void [[INIT_s:@.*global_var.*]] [[NUW:#[0-9]+]]
 // CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
-// CHECK: call i32 @atexit(void ()* @"__dtor_\01?s@@3US@@A")
+// CHECK: call i32 @atexit(void ()* @"\01??__Fs@@YAXXZ")
 // CHECK: ret void
 
-// CHECK: define internal void @"__dtor_\01?s@@3US@@A"() [[NUW]] {
+// CHECK: define internal void @"\01??__Fs@@YAXXZ"() [[NUW]] {
 // CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ"
 // CHECK: ret void
 
+void StaticLocal() {
+  static S TheS;
+}
+// CHECK-LABEL: define void @"\01?StaticLocal@@YAXXZ"()
+// CHECK: load i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
+// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
+// CHECK: ret
+
+void MultipleStatics() {
+  static S S1;
+  static S S2;
+  static S S3;
+  static S S4;
+  static S S5;
+  static S S6;
+  static S S7;
+  static S S8;
+  static S S9;
+  static S S10;
+  static S S11;
+  static S S12;
+  static S S13;
+  static S S14;
+  static S S15;
+  static S S16;
+  static S S17;
+  static S S18;
+  static S S19;
+  static S S20;
+  static S S21;
+  static S S22;
+  static S S23;
+  static S S24;
+  static S S25;
+  static S S26;
+  static S S27;
+  static S S28;
+  static S S29;
+  static S S30;
+  static S S31;
+  static S S32;
+  static S S33;
+  static S S34;
+  static S S35;
+}
+// CHECK-LABEL: define void @"\01?MultipleStatics@@YAXXZ"()
+// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA"
+// CHECK: and i32 {{.*}}, 1
+// CHECK: and i32 {{.*}}, 2
+// CHECK: and i32 {{.*}}, 4
+// CHECK: and i32 {{.*}}, 8
+// CHECK: and i32 {{.*}}, 16
+//   ...
+// CHECK: and i32 {{.*}}, -2147483648
+// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA1"
+// CHECK: and i32 {{.*}}, 1
+// CHECK: and i32 {{.*}}, 2
+// CHECK: and i32 {{.*}}, 4
+// CHECK: ret
+
 // Force WeakODRLinkage by using templates
 class A {
  public:
@@ -29,20 +91,55 @@
 
 template<typename T> A B<T>::foo;
 
+inline S &UnreachableStatic() {
+  if (0) {
+    static S s; // bit 1
+    return s;
+  }
+  static S s; // bit 2
+  return s;
+}
+
+// CHECK-LABEL: define linkonce_odr %struct.S* @"\01?UnreachableStatic@@YAAAUS@@XZ"()
+// CHECK: and i32 {{.*}}, 2
+// CHECK: or i32 {{.*}}, 2
+// CHECK: ret
+
+inline S &getS() {
+  static S TheS;
+  return TheS;
+}
+
+// CHECK-LABEL: define linkonce_odr %struct.S* @"\01?getS@@YAAAUS@@XZ"
+// CHECK: load i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51"
+// CHECK: and i32 {{.*}}, 1
+// CHECK: icmp ne i32 {{.*}}, 0
+// CHECK: br i1
+//   init:
+// CHECK: or i32 {{.*}}, 1
+// CHECK: store i32 {{.*}}, i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51"
+// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"(%struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A")
+// CHECK: call i32 @atexit(void ()* @"\01??__FTheS@?1??getS@@YAAAUS@@XZ@YAXXZ")
+// CHECK: br label
+//   init.end:
+// CHECK: ret %struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A"
+
 void force_usage() {
+  UnreachableStatic();
+  getS();
   (void)B<int>::foo;  // (void) - force usage
 }
 
 // CHECK: define internal void [[INIT_foo:@.*global_var.*]] [[NUW]]
 // CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"
-// CHECK: call i32 @atexit(void ()* [[FOO_DTOR:@"__dtor_.*foo@.*]])
+// CHECK: call i32 @atexit(void ()* @"\01??__Ffoo@?$B@H@@YAXXZ")
 // CHECK: ret void
 
 // CHECK: define linkonce_odr x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"
 
 // CHECK: define linkonce_odr x86_thiscallcc void @"\01??1A@@QAE@XZ"
 
-// CHECK: define internal void [[FOO_DTOR]]
+// CHECK: define internal void @"\01??__Ffoo@?$B@H@@YAXXZ"
 // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"{{.*}}foo
 // CHECK: ret void
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to