https://github.com/JonPsson1 created https://github.com/llvm/llvm-project/pull/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. >From e9380e98527790aee19857b221b7b63d43a0ee87 Mon Sep 17 00:00:00 2001 From: Jonas Paulsson <pauls...@linux.ibm.com> Date: Mon, 20 Nov 2023 12:29:33 +0100 Subject: [PATCH] [clang] Ensure minimial alignment of global vars of incomplete type. 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. --- clang/lib/AST/ASTContext.cpp | 14 +++++++----- clang/test/Driver/systemz-alignment.c | 32 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 clang/test/Driver/systemz-alignment.c 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; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits