[clang] 437ccf5 - [windows-itanium] Propagate DLL storage class to Initialisation Guard Variables

Ben Dunbobbin via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 23 16:24:32 PST 2022


Author: Ben Dunbobbin
Date: 2022-11-24T00:23:17Z
New Revision: 437ccf5af9c2aec915a68a164a95d506fbac2324

URL: https://github.com/llvm/llvm-project/commit/437ccf5af9c2aec915a68a164a95d506fbac2324
DIFF: https://github.com/llvm/llvm-project/commit/437ccf5af9c2aec915a68a164a95d506fbac2324.diff

LOG: [windows-itanium] Propagate DLL storage class to Initialisation Guard Variables

Initialisation Guard Variables should take their DLL storage class
from the guarded variable. Otherwise, there will be a link error if
the compiler inlines a reference to the guard variable into another
module but that guard variable is not exported from the defining
module.

This is required for platforms such as PlayStation and
windows-itanium, that are aiming for source compatibility with MSVC
w.r.t. dllimport/export annotations, given Clang's existing design
which allows for inlining of a dllimport function as long as all the
variables/functions referenced are also marked dllimport.

A similar change exists for the MSVC ABI:
https://reviews.llvm.org/D4136.

I have added a run test for windows-itanium for this issue to the
build recipe: https://reviews.llvm.org/D88124.

Differential Revision: https://reviews.llvm.org/D138463

Added: 
    clang/test/CodeGenCXX/windows-itanium-init-guard.cpp

Modified: 
    clang/lib/CodeGen/ItaniumCXXABI.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 20aa9698dc564..224a019d2fd3a 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2385,13 +2385,15 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
     }
 
     // Create the guard variable with a zero-initializer.
-    // Just absorb linkage and visibility from the guarded variable.
+    // Just absorb linkage, visibility and dll storage class  from the guarded
+    // variable.
     guard = new llvm::GlobalVariable(CGM.getModule(), guardTy,
                                      false, var->getLinkage(),
                                      llvm::ConstantInt::get(guardTy, 0),
                                      guardName.str());
     guard->setDSOLocal(var->isDSOLocal());
     guard->setVisibility(var->getVisibility());
+    guard->setDLLStorageClass(var->getDLLStorageClass());
     // If the variable is thread-local, so is its guard variable.
     guard->setThreadLocalMode(var->getThreadLocalMode());
     guard->setAlignment(guardAlignment.getAsAlign());

diff  --git a/clang/test/CodeGenCXX/windows-itanium-init-guard.cpp b/clang/test/CodeGenCXX/windows-itanium-init-guard.cpp
new file mode 100644
index 0000000000000..8bcfd272ae8f1
--- /dev/null
+++ b/clang/test/CodeGenCXX/windows-itanium-init-guard.cpp
@@ -0,0 +1,32 @@
+// Initialisation Guard Variables should take their DLL storage class from
+// the guarded variable. Otherwise, there will be a link error if the compiler
+// inlines a reference to the guard variable into another module but that
+// guard variable is not exported from the defining module.
+
+// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI= | FileCheck %s --check-prefixes=NONE
+// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllexport)" | FileCheck %s --check-prefixes=EXPORT
+// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllimport)" | FileCheck %s --check-prefixes=IMPORT
+
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps4 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI= | FileCheck %s --check-prefixes=NONE
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps4 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllexport)" | FileCheck %s --check-prefixes=EXPORT
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps4 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllimport)" | FileCheck %s --check-prefixes=IMPORT
+
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps5 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI= | FileCheck %s --check-prefixes=NONE
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps5 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllexport)" | FileCheck %s --check-prefixes=EXPORT
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps5 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllimport)" | FileCheck %s --check-prefixes=IMPORT
+
+//NONE: @_ZZN3foo3GetEvE9Singleton = linkonce_odr {{(dso_local )?}}global
+//NONE: @_ZGVZN3foo3GetEvE9Singleton = linkonce_odr {{(dso_local )?}}global
+
+//EXPORT: @_ZZN3foo3GetEvE9Singleton = weak_odr {{(dso_local )?}}dllexport global
+//EXPORT: @_ZGVZN3foo3GetEvE9Singleton = weak_odr {{(dso_local )?}}dllexport global
+
+//IMPORT: @_ZZN3foo3GetEvE9Singleton = available_externally dllimport global
+//IMPORT: @_ZGVZN3foo3GetEvE9Singleton = available_externally dllimport global
+
+struct API foo {
+  foo() {}
+  static void Get() { static foo Singleton; }
+};
+
+void f() { foo::Get(); }


        


More information about the cfe-commits mailing list