[clang] [X86_64] fix arg pass error in struct. (PR #85394)

Longsheng Mou via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 15 18:51:56 PDT 2024


https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/85394

>From b31780cba73ea39bf7f630a059a554914d804446 Mon Sep 17 00:00:00 2001
From: Longsheng Mou <moulongsheng at huawei.com>
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

typedef long long Alignll __attribute__((aligned (4)));
struct S {
  int a;
  Alignll b;
};

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.
---
 clang/lib/CodeGen/Targets/X86.cpp         |  6 ++++++
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..c3e32e5ed63a97 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1787,6 +1787,8 @@ 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 +1801,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..92b0192658a555 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__((aligned (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__((aligned (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:



More information about the cfe-commits mailing list