summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/TargetInfo.cpp1
-rw-r--r--clang/lib/Basic/Targets.cpp2
-rw-r--r--clang/lib/Sema/SemaDecl.cpp26
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp26
4 files changed, 50 insertions, 5 deletions
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 856ad50d378..dbd2f9ae995 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -50,6 +50,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
LargeArrayAlign = 0;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
MaxVectorAlign = 0;
+ MaxTLSAlign = 0;
SimdDefaultAlign = 0;
SizeType = UnsignedLong;
PtrDiffType = SignedLong;
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index c5bf90fa784..3cf74bc8492 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -580,6 +580,8 @@ public:
PS4OSTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {
this->WCharType = this->UnsignedShort;
+ // On PS4, TLS variable cannot be aligned to more than 32 bytes (256 bits).
+ this->MaxTLSAlign = 256;
this->UserLabelPrefix = "";
switch (Triple.getArch()) {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5646099015b..99d4a79c466 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9828,6 +9828,16 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
FinalizeVarWithDestructor(var, recordType);
}
+/// \brief Determines if a variable's alignment is dependent.
+static bool hasDependentAlignment(VarDecl *VD) {
+ if (VD->getType()->isDependentType())
+ return true;
+ for (auto *I : VD->specific_attrs<AlignedAttr>())
+ if (I->isAlignmentDependent())
+ return true;
+ return false;
+}
+
/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
/// any semantic actions necessary after any initializer has been attached.
void
@@ -9841,6 +9851,22 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
checkAttributesAfterMerging(*this, *VD);
+ // Perform TLS alignment check here after attributes attached to the variable
+ // which may affect the alignment have been processed. Only perform the check
+ // if the target has a maximum TLS alignment (zero means no constraints).
+ if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
+ // Protect the check so that it's not performed on dependent types and
+ // dependent alignments (we can't determine the alignment in that case).
+ if (VD->getTLSKind() && !hasDependentAlignment(VD)) {
+ CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
+ if (Context.getDeclAlign(VD) > MaxAlignChars) {
+ Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
+ << (unsigned)Context.getDeclAlign(VD).getQuantity() << VD
+ << (unsigned)MaxAlignChars.getQuantity();
+ }
+ }
+ }
+
// Static locals inherit dll attributes from their function.
if (VD->isStaticLocal()) {
if (FunctionDecl *FD =
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index b8d08306859..191dbd05c9b 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2985,11 +2985,27 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
// specifier shall have no effect
// C11 6.7.5p6:
// An alignment specification of zero has no effect.
- if (!(TmpAttr.isAlignas() && !Alignment) &&
- !llvm::isPowerOf2_64(Alignment.getZExtValue())) {
- Diag(AttrLoc, diag::err_alignment_not_power_of_two)
- << E->getSourceRange();
- return;
+ if (!(TmpAttr.isAlignas() && !Alignment)) {
+ if(!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
+ Diag(AttrLoc, diag::err_alignment_not_power_of_two)
+ << E->getSourceRange();
+ return;
+ }
+ if (Context.getTargetInfo().isTLSSupported()) {
+ if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->getTLSKind()) {
+ CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
+ if (Alignment.getSExtValue() > MaxAlignChars.getQuantity()) {
+ Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
+ << (unsigned)Alignment.getZExtValue() << VD
+ << (unsigned)MaxAlignChars.getQuantity();
+ return;
+ }
+ }
+ }
+ }
+ }
}
// Alignment calculations can wrap around if it's greater than 2**28.
OpenPOWER on IntegriCloud