Skip to content

Commit

Permalink
[clang] Ensure minimal alignment of global vars of incomplete type. (#…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
JonPsson1 committed Nov 22, 2023
1 parent 510fb87 commit 2e09ea6
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
14 changes: 8 additions & 6 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 32 additions & 0 deletions clang/test/Driver/systemz-alignment.c
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit 2e09ea6

Please sign in to comment.