]> granicus.if.org Git - clang/commitdiff
Implement target-specific __attribute__((aligned)) value
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Tue, 21 Apr 2015 17:29:35 +0000 (17:29 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Tue, 21 Apr 2015 17:29:35 +0000 (17:29 +0000)
The GCC construct __attribute__((aligned)) is defined to set alignment
to "the default alignment for the target architecture" according to
the GCC documentation:

  The default alignment is sufficient for all scalar types, but may not be
  enough for all vector types on a target that supports vector operations.
  The default alignment is fixed for a particular target ABI.

clang currently hard-coded an alignment of 16 bytes for that construct,
which is correct on some platforms (including X86), but wrong on others
(including SystemZ).  Since this value is ABI-relevant, it is important
to get correct for compatibility purposes.

This patch adds a new TargetInfo member "DefaultAlignForAttributeAligned"
that targets can set to the appropriate default __attribute__((aligned))
value.

Note that I'm deliberately *not* using the existing "SuitableAlign"
value, which is used to set the pre-defined macro __BIGGEST_ALIGNMENT__,
since those two values may not be the same on all platforms.  In fact,
on X86, __attribute__((aligned)) always uses 16-byte alignment, while
__BIGGEST_ALIGNMENT__ may be larger if AVX-2 or AVX-512 are supported.
(This is actually not yet correctly implemented in clang either.)

The patch provides a value for DefaultAlignForAttributeAligned only for
SystemZ, and leaves the default for all other targets at 16, which means
no visible change in behavior on all other targets.  (The value is still
wrong for some other targets, but I'd prefer to leave it to the target
maintainers for those platforms to fix.)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@235397 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
include/clang/Basic/TargetInfo.h
lib/AST/ASTContext.cpp
lib/Basic/TargetInfo.cpp
lib/Basic/Targets.cpp
test/Sema/struct-packed-align.c
utils/TableGen/ClangAttrEmitter.cpp

index 48e3451f25770b041226c6f2dfc34e1fe75cded2..b6f8c735cc83429384fb102a1c619a4524dc7732 100644 (file)
@@ -1691,6 +1691,10 @@ public:
   /// beneficial for performance to overalign a data type.
   unsigned getPreferredTypeAlign(const Type *T) const;
 
+  /// \brief Return the default alignment for __attribute__((aligned)) on
+  /// this target, to be used if no alignment value is specified.
+  unsigned getTargetDefaultAlignForAttributeAligned(void) const;
+
   /// \brief Return the alignment in bits that should be given to a
   /// global variable with type \p T.
   unsigned getAlignOfGlobalVar(QualType T) const;
index 1d6485a56e9340f2e4382ce6a50132963792ff1b..8406205c7fd9ddc4422c3aee0b8c0f35476414ee 100644 (file)
@@ -66,6 +66,7 @@ protected:
   unsigned char LongWidth, LongAlign;
   unsigned char LongLongWidth, LongLongAlign;
   unsigned char SuitableAlign;
+  unsigned char DefaultAlignForAttributeAligned;
   unsigned char MinGlobalAlign;
   unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
   unsigned short MaxVectorAlign;
@@ -314,6 +315,12 @@ public:
   /// object with a fundamental alignment requirement.
   unsigned getSuitableAlign() const { return SuitableAlign; }
 
+  /// \brief Return the default alignment for __attribute__((aligned)) on
+  /// this target, to be used if no alignment value is specified.
+  unsigned getDefaultAlignForAttributeAligned() const {
+    return DefaultAlignForAttributeAligned;
+  }
+
   /// getMinGlobalAlign - Return the minimum alignment of a global variable,
   /// unless its alignment is explicitly reduced via attributes.
   unsigned getMinGlobalAlign() const { return MinGlobalAlign; }
index c54a006d26a765bd30ccdffc47a811361c4d47b0..4d6a51bf1924196a7d189aaf6ff137c66bd8ee87 100644 (file)
@@ -1817,6 +1817,13 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
   return ABIAlign;
 }
 
+/// getTargetDefaultAlignForAttributeAligned - Return the default alignment
+/// for __attribute__((aligned)) on this target, to be used if no alignment
+/// value is specified.
+unsigned ASTContext::getTargetDefaultAlignForAttributeAligned(void) const {
+  return getTargetInfo().getDefaultAlignForAttributeAligned();
+}
+
 /// getAlignOfGlobalVar - Return the alignment in bits that should be given
 /// to a global variable of the specified type.
 unsigned ASTContext::getAlignOfGlobalVar(QualType T) const {
index 871bbd5ef43f9e13bda6af5b93037bfe5b8ffc8a..330258b025b5f5c9d11cda6ad45c523378dc4f79 100644 (file)
@@ -36,6 +36,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
   LongWidth = LongAlign = 32;
   LongLongWidth = LongLongAlign = 64;
   SuitableAlign = 64;
+  DefaultAlignForAttributeAligned = 128;
   MinGlobalAlign = 0;
   HalfWidth = 16;
   HalfAlign = 16;
index 1f81bcd46d4fd0a9c16c8bde06a111becfe2fbaa..047cf0d5b5c04686940bfd8c4bb53a2ebb01d200 100644 (file)
@@ -5521,6 +5521,7 @@ public:
     LongDoubleWidth = 128;
     LongDoubleAlign = 64;
     LongDoubleFormat = &llvm::APFloat::IEEEquad;
+    DefaultAlignForAttributeAligned = 64;
     MinGlobalAlign = 16;
     DescriptionString = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64";
     MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
index 291de6762cd18354152c518b5b8d25de2afba121..417c30308ca3b0d6f268518d4c9f5a5d079c2458 100644 (file)
@@ -55,13 +55,16 @@ struct __attribute__((aligned(8))) as1 {
 extern int e1[sizeof(struct as1) == 8 ? 1 : -1];
 extern int e2[__alignof(struct as1) == 8 ? 1 : -1];
 
-// FIXME: Will need to force arch once max usable alignment isn't hard
-// coded.
 struct __attribute__((aligned)) as1_2 {
     char c;
 };
+#ifdef __s390x__
+extern int e1_2[sizeof(struct as1_2) == 8 ? 1 : -1];
+extern int e2_2[__alignof(struct as1_2) == 8 ? 1 : -1];
+#else
 extern int e1_2[sizeof(struct as1_2) == 16 ? 1 : -1];
 extern int e2_2[__alignof(struct as1_2) == 16 ? 1 : -1];
+#endif
 
 struct as2 {
     char c;
index c1d1a1dbe6d40ba328fd092c46ddf5b760634305..58857b91a9aa7de71a9bec8b65e0e274654cd1cc 100644 (file)
@@ -413,15 +413,14 @@ namespace {
       // FIXME: Do not do the calculation here
       // FIXME: Handle types correctly
       // A null pointer means maximum alignment
-      // FIXME: Load the platform-specific maximum alignment, rather than
-      //        16, the x86 max.
       OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
          << "(ASTContext &Ctx) const {\n";
       OS << "  assert(!is" << getUpperName() << "Dependent());\n";
       OS << "  if (is" << getLowerName() << "Expr)\n";
-      OS << "    return (" << getLowerName() << "Expr ? " << getLowerName()
-         << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
-         << "* Ctx.getCharWidth();\n";
+      OS << "    return " << getLowerName() << "Expr ? " << getLowerName()
+         << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue()"
+         << " * Ctx.getCharWidth() : "
+         << "Ctx.getTargetDefaultAlignForAttributeAligned();\n";
       OS << "  else\n";
       OS << "    return 0; // FIXME\n";
       OS << "}\n";