diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -545,6 +545,8 @@ def err_aix_default_altivec_abi : Error< "The default Altivec ABI on AIX is not yet supported, use '-mabi=vec-extabi' for the extended Altivec ABI">; +def err_aix_unsupported_tls_model : Error<"TLS model '%0' is not yet supported on AIX">; + def err_invalid_cxx_abi : Error<"Invalid C++ ABI name '%0'">; def err_unsupported_cxx_abi : Error<"C++ ABI '%0' is not supported on target triple '%1'">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3151,6 +3151,8 @@ def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", " "\"local-dynamic\", \"initial-exec\" or \"local-exec\"">; +def err_aix_attr_unsupported_tls_model : Error<"TLS model '%0' is not yet supported on AIX">; + def err_tls_var_aligned_over_maximum : Error< "alignment (%0) of thread-local variable %1 is greater than the maximum supported " "alignment (%2) for a thread-local variable on this target">; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1808,6 +1808,14 @@ Opts.ExplicitEmulatedTLS = true; } + if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) { + if (T.isOSAIX()) { + StringRef Name = A->getValue(); + if (Name != "global-dynamic") + Diags.Report(diag::err_aix_unsupported_tls_model) << Name; + } + } + if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) { StringRef Val = A->getValue(); Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1935,6 +1935,12 @@ return; } + if (S.Context.getTargetInfo().getTriple().isOSAIX() && + Model != "global-dynamic") { + S.Diag(LiteralLoc, diag::err_aix_attr_unsupported_tls_model) << Model; + return; + } + D->addAttr(::new (S.Context) TLSModelAttr(S.Context, AL, Model)); } diff --git a/clang/test/CodeGen/aix-tls-model.cpp b/clang/test/CodeGen/aix-tls-model.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/aix-tls-model.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD +// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=global-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD +// RUN: not %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-LD-ERROR +// RUN: not %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=initial-exec -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-IE-ERROR +// RUN: not %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=local-exec -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-LE-ERROR +// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD +// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=global-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD +// RUN: not %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-LD-ERROR +// RUN: not %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=initial-exec -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-IE-ERROR +// RUN: not %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=local-exec -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-LE-ERROR + +int z1 = 0; +int z2; +int __thread x; +int f() { + static int __thread y; + return y++; +} + +// CHECK-GD: @z1 ={{.*}} global i32 0 +// CHECK-GD: @z2 ={{.*}} global i32 0 +// CHECK-GD: @x ={{.*}} thread_local global i32 0 +// CHECK-GD: @_ZZ1fvE1y = internal thread_local global i32 0 +// CHECK-LD-ERROR: error: TLS model 'local-dynamic' is not yet supported on AIX +// CHECK-IE-ERROR: error: TLS model 'initial-exec' is not yet supported on AIX +// CHECK-LE-ERROR: error: TLS model 'local-exec' is not yet supported on AIX diff --git a/clang/test/Sema/aix-attr-tls_model.c b/clang/test/Sema/aix-attr-tls_model.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/aix-attr-tls_model.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple powerpc64-unknown-aix -target-cpu pwr8 -verify -fsyntax-only %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix -target-cpu pwr8 -verify -fsyntax-only %s + +#if !__has_attribute(tls_model) +#error "Should support tls_model attribute" +#endif + +static __thread int y __attribute((tls_model("global-dynamic"))); // no-warning +static __thread int y __attribute((tls_model("local-dynamic"))); // expected-error {{TLS model 'local-dynamic' is not yet supported on AIX}} +static __thread int y __attribute((tls_model("initial-exec"))); // expected-error {{TLS model 'initial-exec' is not yet supported on AIX}} +static __thread int y __attribute((tls_model("local-exec"))); // expected-error {{TLS model 'local-exec' is not yet supported on AIX}}