[Clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (#113830)
This adds an option to control whether guards for on-demand TLS initialization in combination with Microsoft's CXX ABI are emitted or not. The behaviour should match with Microsoft: https://learn.microsoft.com/en-us/cpp/build/reference/zc-tlsguards?view=msvc-170 This fixes #103484
This commit is contained in:
parent
b88e938b1f
commit
71b3b32c6e
@ -155,6 +155,7 @@ VALUE_CODEGENOPT(PatchableFunctionEntryOffset , 32, 0)
|
||||
CODEGENOPT(HotPatch, 1, 0) ///< Supports the Microsoft /HOTPATCH flag and
|
||||
///< generates a 'patchable-function' attribute.
|
||||
|
||||
CODEGENOPT(TlsGuards , 1, 1) ///< Controls emission of tls guards via -fms-tls-guards
|
||||
CODEGENOPT(JMCInstrument, 1, 0) ///< Set when -fjmc is enabled.
|
||||
CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
|
||||
CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled.
|
||||
|
@ -4072,6 +4072,11 @@ defm threadsafe_statics : BoolFOption<"threadsafe-statics",
|
||||
NegFlag<SetFalse, [], [ClangOption, CC1Option],
|
||||
"Do not emit code to make initialization of local statics thread safe">,
|
||||
PosFlag<SetTrue>>;
|
||||
defm ms_tls_guards : BoolFOption<"ms-tls-guards",
|
||||
CodeGenOpts<"TlsGuards">, DefaultTrue,
|
||||
NegFlag<SetFalse, [], [CC1Option],
|
||||
"Do not emit code to perform on-demand initialization of thread-local variables">,
|
||||
PosFlag<SetTrue>>;
|
||||
def ftime_report : Flag<["-"], "ftime-report">, Group<f_Group>,
|
||||
Visibility<[ClangOption, CC1Option]>,
|
||||
MarshallingInfoFlag<CodeGenOpts<"TimePasses">>;
|
||||
@ -8635,6 +8640,12 @@ def _SLASH_Zc_threadSafeInit : CLFlag<"Zc:threadSafeInit">,
|
||||
def _SLASH_Zc_threadSafeInit_ : CLFlag<"Zc:threadSafeInit-">,
|
||||
HelpText<"Disable thread-safe initialization of static variables">,
|
||||
Alias<fno_threadsafe_statics>;
|
||||
def _SLASH_Zc_tlsGuards : CLFlag<"Zc:tlsGuards">,
|
||||
HelpText<"Enable on-demand initialization of thread-local variables">,
|
||||
Alias<fms_tls_guards>;
|
||||
def _SLASH_Zc_tlsGuards_ : CLFlag<"Zc:tlsGuards-">,
|
||||
HelpText<"Disable on-demand initialization of thread-local variables">,
|
||||
Alias<fno_ms_tls_guards>;
|
||||
def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">,
|
||||
HelpText<"Enable trigraphs">, Alias<ftrigraphs>;
|
||||
def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">,
|
||||
|
@ -431,6 +431,7 @@ public:
|
||||
bool usesThreadWrapperFunction(const VarDecl *VD) const override {
|
||||
return getContext().getLangOpts().isCompatibleWithMSVC(
|
||||
LangOptions::MSVC2019_5) &&
|
||||
CGM.getCodeGenOpts().TlsGuards &&
|
||||
(!isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD));
|
||||
}
|
||||
LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
|
||||
|
@ -7317,6 +7317,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
(!IsWindowsMSVC || IsMSVC2015Compatible)))
|
||||
CmdArgs.push_back("-fno-threadsafe-statics");
|
||||
|
||||
if (!Args.hasFlag(options::OPT_fms_tls_guards, options::OPT_fno_ms_tls_guards,
|
||||
true))
|
||||
CmdArgs.push_back("-fno-ms-tls-guards");
|
||||
|
||||
// Add -fno-assumptions, if it was specified.
|
||||
if (!Args.hasFlag(options::OPT_fassumptions, options::OPT_fno_assumptions,
|
||||
true))
|
||||
|
@ -1,5 +1,6 @@
|
||||
// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 -fms-compatibility-version=19.25 -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 -fms-compatibility-version=19.20 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LEGACY
|
||||
// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 -fms-compatibility-version=19.25 -fno-ms-tls-guards -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-NO-GUARDS
|
||||
// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 -fms-compatibility-version=19.25 -ftls-model=local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LD
|
||||
|
||||
struct A {
|
||||
@ -23,17 +24,20 @@ thread_local A a = A();
|
||||
// CHECK-LD-DAG: @"__tls_init$initializer$" = internal constant ptr @__tls_init, section ".CRT$XDU"
|
||||
// CHECK-LD-DAG: @__tls_guard = external dso_local thread_local global i8
|
||||
// CHECK-LEGACY-NOT: @__tls_guard = external dso_local thread_local global i8
|
||||
// CHECK-NO-GUARDS-NOT: @__tls_guard = external dso_local thread_local global i8
|
||||
thread_local A b;
|
||||
|
||||
// CHECK-LABEL: declare dso_local void @__dyn_tls_on_demand_init()
|
||||
// CHECK-LD-LABEL: declare dso_local void @__dyn_tls_on_demand_init()
|
||||
// CHECK-LEGACY-NOT: declare dso_local void @__dyn_tls_on_demand_init()
|
||||
// CHECK-NO-GUARDS-NOT: declare dso_local void @__dyn_tls_on_demand_init()
|
||||
|
||||
// CHECK-LABEL: define dso_local void @"?f@@YA?AUA@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.A) align 1 %agg.result)
|
||||
// CHECK: call void @__dyn_tls_on_demand_init()
|
||||
// CHECK-LD-LABEL: define dso_local void @"?f@@YA?AUA@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.A) align 1 %agg.result)
|
||||
// CHECK-LD: call void @__dyn_tls_on_demand_init()
|
||||
// CHECK-LEGACY-NOT: call void @__dyn_tls_on_demand_init()
|
||||
// CHECK-NO-GUARDS-NOT: call void @__dyn_tls_on_demand_init()
|
||||
|
||||
thread_local A &c = b;
|
||||
thread_local A &d = c;
|
||||
|
@ -99,6 +99,9 @@
|
||||
// RUN: %clang_cl /Zc:threadSafeInit /c -### -- %s 2>&1 | FileCheck -check-prefix=ThreadSafeStatics %s
|
||||
// ThreadSafeStatics-NOT: "-fno-threadsafe-statics"
|
||||
|
||||
// RUN: %clang_cl /Zc:tlsGuards- /c -### -- %s 2>&1 | FileCheck -check-prefix=NoTlsGuards %s
|
||||
// NoTlsGuards: "-fno-ms-tls-guards"
|
||||
|
||||
// RUN: %clang_cl /Zc:dllexportInlines- /c -### -- %s 2>&1 | FileCheck -check-prefix=NoDllExportInlines %s
|
||||
// NoDllExportInlines: "-fno-dllexport-inlines"
|
||||
// RUN: %clang_cl /Zc:dllexportInlines /c -### -- %s 2>&1 | FileCheck -check-prefix=DllExportInlines %s
|
||||
|
Loading…
x
Reference in New Issue
Block a user