-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
[X86_64] fix arg pass error in struct. #85394
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write If you have received no comments on your PR for a week, you can request a review If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-clang Author: Longsheng Mou (CoTinker) Changestypedef long long Alignll attribute((align (4))); struct S { When classify: In this case, only one i64 register is used when the structure parameter is transferred, which is obviously incorrect.So we need to treat the split case specially. fix #85387. Full diff: https://github.com/llvm/llvm-project/pull/85394.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..1a02d94a8eb530 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1787,6 +1787,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo,
Lo = Hi = NoClass;
Class &Current = OffsetBase < 64 ? Lo : Hi;
+ bool IsSplit = OffsetBase < 64 && (OffsetBase + getContext().getTypeSize(Ty)) > 64;
Current = Memory;
if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) {
@@ -1799,9 +1800,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo,
Hi = Integer;
} else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
Current = Integer;
+ if (IsSplit)
+ Hi = Integer;
} else if (k == BuiltinType::Float || k == BuiltinType::Double ||
k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
Current = SSE;
+ if (IsSplit)
+ Hi = SSE;
} else if (k == BuiltinType::Float128) {
Lo = SSE;
Hi = SSEUp;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..c8a215989cf9fc 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), __aligned__(128)));
void f66(t66 a0) {
}
+typedef long long t67 __attribute__((align (4)));
+struct s67 {
+ int a;
+ t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(i64 %x.coerce0, i32 %x.coerce1)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((align (4)));
+struct s68 {
+ int a;
+ t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(i64 %x.coerce0, double %x.coerce1)
+void f68(struct s68 x) {
+}
+
/// The synthesized __va_list_tag does not have file/line fields.
// CHECK: = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__va_list_tag",
// CHECK-NOT: file:
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
57760b2
to
d344d20
Compare
I think the logic the code is using is that t67 is actually properly aligned: it's a type with size 8 and alignment 4, so everything is fine. If that's not right, we should tweak the relevant logic (around line 2104). Specifically checking whether a type crosses an 8-byte boundary seems wrong; the only relevant text I can find in the standard is just "if the size of an object is larger than eight eightbytes, or it contains unaligned fields, it has class MEMORY." |
Thanks, I'll modify it according to this. |
Which is more appropriate to pass this structure through, memory or register? |
gcc uses memory, and the ABI standard doesn't explicitly contradict it, so let's just go with that. |
57cdbca
to
07e8b31
Compare
In some struct like s67, only one i64 register is used when the structure parameter is transferred, which is obviously incorrect.So we need to treat the split case specially, using memory like gcc.
When classify:
a: Lo = Integer, Hi = NoClass
b: Lo = Integer, Hi = NoClass
struct S: Lo = Integer, Hi = NoClass
In this case, only one i64 register is used when the structure parameter is transferred, which is obviously incorrect.So we need to treat the split case specially. fix #85387.