[clang] 2e09ea6 - [clang] Ensure minimal alignment of global vars of incomplete type. (#72886)

via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 22 02:24:50 PST 2023


Author: Jonas Paulsson
Date: 2023-11-22T11:24:45+01:00
New Revision: 2e09ea65c4f9e458ffb31fe63d84a4991704f9e6

URL: https://github.com/llvm/llvm-project/commit/2e09ea65c4f9e458ffb31fe63d84a4991704f9e6
DIFF: https://github.com/llvm/llvm-project/commit/2e09ea65c4f9e458ffb31fe63d84a4991704f9e6.diff

LOG: [clang] Ensure minimal alignment of global vars of incomplete type. (#72886)

The SystemZ ABI requires any global variable to be aligned to at least 2
bytes, and therefore an external global Value with an opaque type should
get this alignment as well.

Added: 
    clang/test/Driver/systemz-alignment.c

Modified: 
    clang/lib/AST/ASTContext.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 1c893d008cb49f3..a7cee3b7ba2b0db 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1680,14 +1680,16 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
       Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
       if (BaseT.getQualifiers().hasUnaligned())
         Align = Target->getCharWidth();
-      if (const auto *VD = dyn_cast<VarDecl>(D)) {
-        if (VD->hasGlobalStorage() && !ForAlignof) {
-          uint64_t TypeSize = getTypeSize(T.getTypePtr());
-          Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize));
-        }
-      }
     }
 
+    // Ensure miminum alignment for global variables.
+    if (const auto *VD = dyn_cast<VarDecl>(D))
+      if (VD->hasGlobalStorage() && !ForAlignof) {
+        uint64_t TypeSize =
+            !BaseT->isIncompleteType() ? getTypeSize(T.getTypePtr()) : 0;
+        Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize));
+      }
+
     // Fields can be subject to extra alignment constraints, like if
     // the field is packed, the struct is packed, or the struct has a
     // a max-field-alignment constraint (#pragma pack).  So calculate

diff  --git a/clang/test/Driver/systemz-alignment.c b/clang/test/Driver/systemz-alignment.c
new file mode 100644
index 000000000000000..6f3b2bc38be3688
--- /dev/null
+++ b/clang/test/Driver/systemz-alignment.c
@@ -0,0 +1,32 @@
+// RUN: %clang --target=s390x-linux -S -emit-llvm -o - %s | FileCheck %s
+//
+// Test that a global variable with an incomplete type gets the minimum
+// alignment of 2 per the ABI if no alignment was specified by user.
+//
+// CHECK:      @VarNoAl {{.*}} align 2
+// CHECK-NEXT: @VarExplAl1  {{.*}} align 1
+// CHECK-NEXT: @VarExplAl4  {{.*}} align 4
+
+// No alignemnt specified by user.
+struct incomplete_ty_noal;
+extern struct incomplete_ty_noal VarNoAl;
+struct incomplete_ty_noal *fun0 (void)
+{
+  return &VarNoAl;
+}
+
+// User-specified alignment of 1.
+struct incomplete_ty_al1;
+extern struct incomplete_ty_al1 __attribute__((aligned(1))) VarExplAl1;
+struct incomplete_ty_al1 *fun1 (void)
+{
+  return &VarExplAl1;
+}
+
+// User-specified alignment of 4.
+struct incomplete_ty_al4;
+extern struct incomplete_ty_al4 __attribute__((aligned(4))) VarExplAl4;
+struct incomplete_ty_al4 *fun2 (void)
+{
+  return &VarExplAl4;
+}


        


More information about the cfe-commits mailing list