-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[clang] Ensure minimal alignment of global vars of incomplete type. #72886
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
@llvm/pr-subscribers-clang-driver @llvm/pr-subscribers-clang Author: Jonas Paulsson (JonPsson1) ChangesThe 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. Full diff: https://github.com/llvm/llvm-project/pull/72886.diff 2 Files Affected:
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;
+}
|
@efriedma-quic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
The questions that I came up with while reviewing:
- Does this affect other targets?
It looks like it affects Lanai, but that difference seems fine. It looks like it doesn't affect anything else in-tree; in particular, the overrides just return the default for size=0. Maybe out-of-tree, but we can't really do much about that (unless we want to add a separate target hook, but that seems like overkill).
- Are there any possible side-effects?
Given the actual usage, this seems safe enough. I'm a little concerned about people doing weird stuff with extern globals and linker scripts, but it looks like none of the targets where that would matter are actually impacted by this.
@@ -0,0 +1,32 @@ | |||
// RUN: %clang --target=s390x-linux -S -emit-llvm -o - %s | FileCheck %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this a Driver test rather than a CodeGen test using clang_cc1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found some other align tests there, like arm-alignment.c, so I thought this should work..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I missed this when reviewing.
We generally only use Driver tests when we're trying to test some aspect of the driver. For arm-alignment.c, it isn't really trying to test the code generation itself; it's trying to test the effect of alignment-related flags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, my bad. There is a SystemZ test for this already, so I moved these tests into it instead. I created a new PR: #73230.
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.