Skip to content

Commit

Permalink
[windows-itanium] Propagate DLL storage class to Initialisation Guard…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
bd1976bris committed Nov 24, 2022
1 parent 3027582 commit 437ccf5
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
4 changes: 3 additions & 1 deletion clang/lib/CodeGen/ItaniumCXXABI.cpp
Expand Up @@ -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());
Expand Down
32 changes: 32 additions & 0 deletions 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(); }

0 comments on commit 437ccf5

Please sign in to comment.