From: David Majnemer Date: Thu, 7 May 2015 21:19:06 +0000 (+0000) Subject: [MS ABI] Make sure we number thread_local statics seperately X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d5295375fae7ab1c4ba1f18885efcc298e9a2431;p=clang [MS ABI] Make sure we number thread_local statics seperately The thread_local variables need their own numbers, they can't share with the other static local variables. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@236774 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp index 4eb960a60d..93ff77a2e9 100644 --- a/lib/AST/MicrosoftCXXABI.cpp +++ b/lib/AST/MicrosoftCXXABI.cpp @@ -31,11 +31,12 @@ class MicrosoftNumberingContext : public MangleNumberingContext { llvm::DenseMap ManglingNumbers; unsigned LambdaManglingNumber; unsigned StaticLocalNumber; + unsigned StaticThreadlocalNumber; public: MicrosoftNumberingContext() : MangleNumberingContext(), LambdaManglingNumber(0), - StaticLocalNumber(0) {} + StaticLocalNumber(0), StaticThreadlocalNumber(0) {} unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { return ++LambdaManglingNumber; @@ -47,6 +48,8 @@ public: } unsigned getStaticLocalNumber(const VarDecl *VD) override { + if (VD->getTLSKind()) + return ++StaticThreadlocalNumber; return ++StaticLocalNumber; } diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 0bac4159e5..bac3472e68 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -2534,6 +2534,7 @@ void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable( void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, raw_ostream &Out) { // ::= ?_B @5 + // ::= ?__J @5 // ::= ?$S @ @4IA // The first mangling is what MSVC uses to guard static locals in inline @@ -2546,10 +2547,7 @@ void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, bool Visible = VD->isExternallyVisible(); if (Visible) { - Mangler.getStream() << (getASTContext().getLangOpts().isCompatibleWithMSVC( - 19) - ? "\01??__J" - : "\01??_B"); + Mangler.getStream() << (VD->getTLSKind() ? "\01??__J" : "\01??_B"); } else { Mangler.getStream() << "\01?$S1@"; } diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 431633e808..35f5983372 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -687,6 +687,7 @@ private: /// Map from DeclContext to the current guard variable. We assume that the /// AST is visited in source code order. llvm::DenseMap GuardVariableMap; + llvm::DenseMap ThreadLocalGuardVariableMap; llvm::DenseMap ThreadSafeGuardNumMap; llvm::DenseMap TypeDescriptorTypeMap; @@ -2103,18 +2104,27 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, return; } - bool HasPerVariableGuard = - getContext().getLangOpts().ThreadsafeStatics && !D.getTLSKind(); + bool ThreadlocalStatic = D.getTLSKind(); + bool ThreadsafeStatic = getContext().getLangOpts().ThreadsafeStatics; + + // Thread-safe static variables which aren't thread-specific have a + // per-variable guard. + bool HasPerVariableGuard = ThreadsafeStatic && !ThreadlocalStatic; 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()]; - llvm::GlobalVariable *GuardVar = GI->Guard; + GuardInfo *GI = nullptr; + if (ThreadlocalStatic) + GI = &ThreadLocalGuardVariableMap[D.getDeclContext()]; + else if (!ThreadsafeStatic) + GI = &GuardVariableMap[D.getDeclContext()]; + + llvm::GlobalVariable *GuardVar = GI ? GI->Guard : nullptr; unsigned GuardNum; - if (D.isStaticLocal() && D.isExternallyVisible()) { + if (D.isExternallyVisible()) { // Externally visible variables have to be numbered in Sema to properly // handle unreachable VarDecls. GuardNum = getContext().getStaticLocalNumber(&D); @@ -2127,9 +2137,6 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, GuardNum = GI->BitIndex++; } - if (HasPerVariableGuard) - GuardVar = nullptr; - if (!HasPerVariableGuard && GuardNum >= 32) { if (D.isExternallyVisible()) ErrorUnsupportedABI(CGF, "more than 32 guarded initializations"); diff --git a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp index 76583d0c6f..5f6849dde0 100644 --- a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp +++ b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -fexceptions -fcxx-exceptions -fms-extensions -fms-compatibility -fms-compatibility-version=19 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s +// REQUIRES: asserts + struct S { S(); ~S(); @@ -9,6 +11,10 @@ struct S { // CHECK-DAG: @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr global %struct.S zeroinitializer // CHECK-DAG: @"\01?$TSS0@?1??g@@YAAAUS@@XZ" = linkonce_odr global i32 0 // CHECK-DAG: @_Init_thread_epoch = external thread_local global i32, align 4 +// CHECK-DAG: @"\01?j@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr thread_local global %struct.S zeroinitializer +// CHECK-DAG: @"\01??__J?1??h@@YAAAUS@@_N@Z@51" = linkonce_odr thread_local global i32 0 +// CHECK-DAG: @"\01?i@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr global %struct.S zeroinitializer +// CHECK-DAG: @"\01?$TSS0@?1??h@@YAAAUS@@_N@Z" = linkonce_odr global i32 0 // CHECK-LABEL: define {{.*}} @"\01?f@@YAAAUS@@XZ"() extern inline S &f() { @@ -80,4 +86,8 @@ extern inline S &g() { return s; } -// REQUIRES: asserts +extern inline S&h(bool b) { + static thread_local S j; + static S i; + return b ? j : i; +}