diff options
| -rw-r--r-- | clang/include/clang/AST/ASTContext.h | 6 | ||||
| -rw-r--r-- | clang/include/clang/AST/Mangle.h | 10 | ||||
| -rw-r--r-- | clang/include/clang/AST/MangleNumberingContext.h | 5 | ||||
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 7 | ||||
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 17 | ||||
| -rw-r--r-- | clang/lib/AST/CXXABI.h | 8 | ||||
| -rw-r--r-- | clang/lib/AST/ItaniumCXXABI.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/AST/MangleNumberingContext.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/AST/MicrosoftCXXABI.cpp | 21 | ||||
| -rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 41 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGCXXABI.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGCXXABI.h | 3 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGDeclCXX.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 93 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 12 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-static-initializers.cpp | 111 |
20 files changed, 342 insertions, 57 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 377282ff657..107b5f1fc08 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/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 @@ namespace clang { class SelectorTable; class TargetInfo; class CXXABI; + class MangleNumberingContext; // Decls class MangleContext; class ObjCIvarDecl; @@ -353,7 +353,7 @@ private: /// \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 @@ -2119,6 +2119,8 @@ public: /// 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); diff --git a/clang/include/clang/AST/Mangle.h b/clang/include/clang/AST/Mangle.h index c13cd257d9b..f6aa2fc9766 100644 --- a/clang/include/clang/AST/Mangle.h +++ b/clang/include/clang/AST/Mangle.h @@ -139,11 +139,11 @@ public: 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 &) { diff --git a/clang/include/clang/AST/MangleNumberingContext.h b/clang/include/clang/AST/MangleNumberingContext.h index 4f81e0c5548..5a227f201fb 100644 --- a/clang/include/clang/AST/MangleNumberingContext.h +++ b/clang/include/clang/AST/MangleNumberingContext.h @@ -33,10 +33,11 @@ class VarDecl; 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 @@ public: /// \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. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 885e7325ca5..bcae1037ad6 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -703,12 +703,7 @@ public: /// \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; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 85ac734a45c..4ab987d844f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/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 @@ ASTContext::~ASTContext() { 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) { @@ -8037,7 +8044,15 @@ unsigned ASTContext::getManglingNumber(const NamedDecl *ND) const { 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) { diff --git a/clang/lib/AST/CXXABI.h b/clang/lib/AST/CXXABI.h index 6d67d9a12b5..89203f18ca7 100644 --- a/clang/lib/AST/CXXABI.h +++ b/clang/lib/AST/CXXABI.h @@ -21,6 +21,7 @@ namespace clang { class ASTContext; class MemberPointerType; +class MangleNumberingContext; /// Implements C++ ABI-specific semantic analysis functions. class CXXABI { @@ -34,9 +35,12 @@ public: /// 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. diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp index 894eb3bff5f..578466028ce 100644 --- a/clang/lib/AST/ItaniumCXXABI.cpp +++ b/clang/lib/AST/ItaniumCXXABI.cpp @@ -20,6 +20,7 @@ #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" @@ -27,6 +28,19 @@ 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 @@ public: Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); return Layout.getNonVirtualSize() == PointerSize; } + + virtual MangleNumberingContext *createMangleNumberingContext() const { + return new ItaniumNumberingContext(); + } }; class ARMCXXABI : public ItaniumCXXABI { diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index c3121c0b53c..1d8a311c614 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -152,7 +152,8 @@ public: 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 &); @@ -3691,8 +3692,8 @@ ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD, /// 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); @@ -3700,6 +3701,17 @@ void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D, 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> diff --git a/clang/lib/AST/MangleNumberingContext.cpp b/clang/lib/AST/MangleNumberingContext.cpp index 4e9006ec24a..91ef0e2240d 100644 --- a/clang/lib/AST/MangleNumberingContext.cpp +++ b/clang/lib/AST/MangleNumberingContext.cpp @@ -38,11 +38,6 @@ MangleNumberingContext::getManglingNumber(const BlockDecl *BD) { } unsigned -MangleNumberingContext::getManglingNumber(const VarDecl *VD) { - return ++VarManglingNumbers[VD->getIdentifier()]; -} - -unsigned MangleNumberingContext::getManglingNumber(const TagDecl *TD) { return ++TagManglingNumbers[TD->getIdentifier()]; } diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp index fd932f7330a..4a93ea1f417 100644 --- a/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/clang/lib/AST/MicrosoftCXXABI.cpp @@ -16,6 +16,7 @@ #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" @@ -23,6 +24,22 @@ 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 @@ public: return Layout.getNonVirtualSize() == PointerSize || Layout.getNonVirtualSize() == PointerSize * 2; } + + MangleNumberingContext *createMangleNumberingContext() const { + return new MicrosoftNumberingContext(); + } }; } diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 78fa543979b..7e3d6c21395 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -92,6 +92,7 @@ public: 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; } @@ -100,7 +101,6 @@ private: } 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); @@ -168,8 +168,10 @@ public: 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); }; } @@ -1912,13 +1914,44 @@ void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D, 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); diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index fe779800ac6..53e7e636ab4 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -212,13 +212,6 @@ llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, 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, diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index 5baedfba1a0..37f678f4b55 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -413,7 +413,8 @@ public: /// - 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. diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 868820a0813..2417873858b 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -166,9 +166,13 @@ static llvm::Constant *createAtExitStub(CodeGenModule &CGM, const VarDecl &VD, 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(&VD, Out); + } llvm::Function *fn = - CreateGlobalInitOrDestructFunction(CGM, ty, - Twine("__dtor_", addr->getName())); + CreateGlobalInitOrDestructFunction(CGM, ty, FnName.str()); CodeGenFunction CGF(CGM); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 980face2176..b08e9b7462c 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1142,7 +1142,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, SmallString<256> guardName; { llvm::raw_svector_ostream out(guardName); - getMangleContext().mangleItaniumGuardVariable(&D, out); + getMangleContext().mangleStaticGuardVariable(&D, out); out.flush(); } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 837a5366313..e5d7c49a642 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -305,6 +305,18 @@ public: private: /// VBTables - All the vbtables which have been referenced. llvm::DenseMap<const CXXRecordDecl *, VBTableVector> VBTablesMap; + + /// Info on the global variable used to guard initialization of static locals. + /// The BitIndex field is only used for externally invisible declarations. + struct GuardInfo { + GuardInfo() : Guard(0), BitIndex(0) {} + llvm::GlobalVariable *Guard; + unsigned BitIndex; + }; + + /// Map from DeclContext to the current guard variable. We assume that the + /// AST is visited in source code order. + llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap; }; } @@ -727,17 +739,86 @@ llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, } 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. + GuardInfo &GI = GuardVariableMap[D.getDeclContext()]; + + unsigned BitIndex; + if (D.isExternallyVisible()) { + // Externally visible variables have to be numbered in Sema to properly + // handle unreachable VarDecls. + BitIndex = getContext().getManglingNumber(&D); + assert(BitIndex > 0); + BitIndex--; + } else { + // Non-externally visible variables are numbered here in CodeGen. + BitIndex = GI.BitIndex++; + } + + if (BitIndex >= 32) { + if (D.isExternallyVisible()) + ErrorUnsupportedABI(CGF, "more than 32 guarded initializations"); + BitIndex %= 32; + GI.Guard = 0; + } + + // Lazily create the i32 bitfield for this function. + if (!GI.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. + GI.Guard = new llvm::GlobalVariable(CGM.getModule(), GuardTy, false, + GV->getLinkage(), Zero, GuardName.str()); + GI.Guard->setVisibility(GV->getVisibility()); + } else { + assert(GI.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 << BitIndex); + llvm::LoadInst *LI = Builder.CreateLoad(GI.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), GI.Guard); + CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit); + Builder.CreateBr(EndBlock); + + // Continue. + CGF.EmitBlock(EndBlock); } // Member pointer helpers. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 36105e7117c..5dbfa105e13 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3083,6 +3083,9 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } 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. @@ -5356,7 +5359,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, isIncompleteDeclExternC(*this, NewVD)) RegisterLocallyScopedExternCDecl(NewVD, S); - if (NewVD->isStaticLocal()) { + if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) { Decl *ManglingContextDecl; if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext(NewVD->getDeclContext(), diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 3a796ad9025..761feffc265 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/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" @@ -114,12 +115,21 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC, // -- 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, diff --git a/clang/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp b/clang/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp index 56644761600..afa77077a25 100644 --- a/clang/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp +++ b/clang/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp @@ -20,7 +20,7 @@ void foo() { // 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]{{$}} diff --git a/clang/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/clang/test/CodeGenCXX/microsoft-abi-static-initializers.cpp index 56536b1a570..6c4e9e72f4a 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-static-initializers.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-static-initializers.cpp @@ -5,19 +5,81 @@ // CHECK: { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] 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: @@ -33,20 +95,55 @@ class B { 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]]() [[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 |

