| From 0e4cf807aeaf54a10e02176498a7df13ac722b37 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin@martin.st> |
| Date: Sun, 23 May 2021 01:47:04 +0300 |
| Subject: [PATCH] [clang] [MinGW] Don't mark emutls variables as DSO local |
| |
| These actually can be automatically imported from another DLL. (This |
| works properly as long as the actual implementation of emutls is |
| linked dynamically from e.g. libgcc; if the implementation comes from |
| compiler-rt or a statically linked libgcc, it doesn't work as intended.) |
| |
| This fixes PR50146 and https://github.com/msys2/MINGW-packages/issues/8706 |
| (fixing calling std::call_once in a dynamically linked libstdc++); |
| since f73183958482602c4588b0f4a1c3a096e7542947 the dso_local attribute |
| on the TLS variable affected the actual generated code for accessing |
| the emutls variable. |
| |
| The dso_local attribute on the emutls variable made those accesses to |
| use 32 bit relative addressing in code, which requires runtime pseudo |
| relocations in the text section, and breaks entirely if the actual |
| other variable ends up loaded too far away in the virtual address |
| space. |
| |
| Differential Revision: https://reviews.llvm.org/D102970 |
| --- |
| lib/CodeGen/CodeGenModule.cpp | 7 ++++++- |
| test/CodeGen/dso-local-executable.c | 6 ++++-- |
| 2 files changed, 10 insertions(+), 3 deletions(-) |
| |
| diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp |
| index 744ccf0fe59f1..9b31ecdbd81a9 100644 |
| --- a/lib/CodeGen/CodeGenModule.cpp |
| +++ b/lib/CodeGen/CodeGenModule.cpp |
| @@ -986,8 +986,13 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM, |
| // In MinGW, variables without DLLImport can still be automatically |
| // imported from a DLL by the linker; don't mark variables that |
| // potentially could come from another DLL as DSO local. |
| + |
| + // With EmulatedTLS, TLS variables can be autoimported from other DLLs |
| + // (and this actually happens in the public interface of libstdc++), so |
| + // such variables can't be marked as DSO local. (Native TLS variables |
| + // can't be dllimported at all, though.) |
| if (GV->isDeclarationForLinker() && isa<llvm::GlobalVariable>(GV) && |
| - !GV->isThreadLocal()) |
| + (!GV->isThreadLocal() || CGM.getCodeGenOpts().EmulatedTLS)) |
| return false; |
| } |
| |
| diff --git a/test/CodeGen/dso-local-executable.c b/test/CodeGen/dso-local-executable.c |
| index 4c282a334b114..e16b8db9d4ede 100644 |
| --- a/test/CodeGen/dso-local-executable.c |
| +++ b/test/CodeGen/dso-local-executable.c |
| @@ -9,13 +9,15 @@ |
| // COFF-DAG: define dso_local i32* @zed() |
| // COFF-DAG: declare dllimport void @import_func() |
| |
| -// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - | FileCheck --check-prefix=MINGW %s |
| +// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - | FileCheck --check-prefixes=MINGW,MINGW-NATIVE_TLS %s |
| +// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - -femulated-tls | FileCheck --check-prefixes=MINGW,MINGW-EMUTLS %s |
| // MINGW: @baz = dso_local global i32 42 |
| // MINGW-NEXT: @import_var = external dllimport global i32 |
| // MINGW-NEXT: @weak_bar = extern_weak global i32 |
| // MINGW-NEXT: @bar = external global i32 |
| // MINGW-NEXT: @local_thread_var = dso_local thread_local global i32 42 |
| -// MINGW-NEXT: @thread_var = external dso_local thread_local global i32 |
| +// MINGW-NATIVE_TLS-NEXT: @thread_var = external dso_local thread_local global i32 |
| +// MINGW-EMUTLS-NEXT: @thread_var = external thread_local global i32 |
| // MINGW-DAG: declare dso_local void @foo() |
| // MINGW-DAG: define dso_local i32* @zed() |
| // MINGW-DAG: declare dllimport void @import_func() |