]> granicus.if.org Git - clang/commitdiff
MS ABI: Use a different guard variable for each weak global
authorReid Kleckner <reid@kleckner.net>
Wed, 23 Apr 2014 18:22:11 +0000 (18:22 +0000)
committerReid Kleckner <reid@kleckner.net>
Wed, 23 Apr 2014 18:22:11 +0000 (18:22 +0000)
We were using the same guard variable and failing to initialize the
second global.

Clang is still not MS ABI compatible in this area.  Fixing that is
PR16959, which will require LLVM changes to @llvm.global_ctors.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@207008 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/MicrosoftCXXABI.cpp
test/CodeGenCXX/microsoft-abi-static-initializers.cpp

index 9832969b57ee8093edd0c1c3780b699aae07cd40..528cdf6238ea2a33b89aa0c23baba223cff9dd6b 100644 (file)
@@ -1273,10 +1273,14 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
   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()];
+  GuardInfo EmptyGuardInfo;
+  GuardInfo *GI = &EmptyGuardInfo;
+  if (isa<FunctionDecl>(D.getDeclContext())) {
+    GI = &GuardVariableMap[D.getDeclContext()];
+  }
 
   unsigned BitIndex;
-  if (D.isExternallyVisible()) {
+  if (D.isStaticLocal() && D.isExternallyVisible()) {
     // Externally visible variables have to be numbered in Sema to properly
     // handle unreachable VarDecls.
     BitIndex = getContext().getStaticLocalNumber(&D);
@@ -1284,18 +1288,18 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
     BitIndex--;
   } else {
     // Non-externally visible variables are numbered here in CodeGen.
-    BitIndex = GI.BitIndex++;
+    BitIndex = GI->BitIndex++;
   }
 
   if (BitIndex >= 32) {
     if (D.isExternallyVisible())
       ErrorUnsupportedABI(CGF, "more than 32 guarded initializations");
     BitIndex %= 32;
-    GI.Guard = 0;
+    GI->Guard = 0;
   }
 
   // Lazily create the i32 bitfield for this function.
-  if (!GI.Guard) {
+  if (!GI->Guard) {
     // Mangle the name for the guard.
     SmallString<256> GuardName;
     {
@@ -1306,11 +1310,12 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
 
     // 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());
+    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() &&
+    assert(GI->Guard->getLinkage() == GV->getLinkage() &&
            "static local from the same function had different linkage");
   }
 
@@ -1322,7 +1327,7 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
 
   // Test our bit from the guard variable.
   llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1U << BitIndex);
-  llvm::LoadInst *LI = Builder.CreateLoad(GI.Guard);
+  llvm::LoadInst *LI = Builder.CreateLoad(GI->Guard);
   llvm::Value *IsInitialized =
       Builder.CreateICmpNE(Builder.CreateAnd(LI, Bit), Zero);
   llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
@@ -1332,7 +1337,7 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
   // 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);
+  Builder.CreateStore(Builder.CreateOr(LI, Bit), GI->Guard);
   CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
   Builder.CreateBr(EndBlock);
 
index 021356e8fa22ae87fd8f65bb01ae6caa3d5c2e48..0d336cf42ce92688e3d664c91e330260326b1882 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
 
 // CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()* }]
 // CHECK: [{ i32, void ()* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ"
@@ -20,6 +20,17 @@ S s;
 // CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ"
 // CHECK: ret void
 
+// These globals should use distinct guard variables, and not different bits of
+// the same global.
+__declspec(selectany) S selectany1;
+__declspec(selectany) S selectany2;
+// CHECK: define internal void @"\01??__Eselectany1@@YAXXZ"() [[NUW:#[0-9]+]]
+// CHECK: load i32* @"\01??_Bselectany1@@3US@@A@5"
+// CHECK: ret void
+// CHECK: define internal void @"\01??__Eselectany2@@YAXXZ"() [[NUW:#[0-9]+]]
+// CHECK: load i32* @"\01??_Bselectany2@@3US@@A@5"
+// CHECK: ret void
+
 void StaticLocal() {
   static S TheS;
 }